QskMeta stuff seem to work now, but needs more testing
This commit is contained in:
parent
a9f5e0a528
commit
05e2b91c01
|
|
@ -17,12 +17,20 @@ void Invoker::addCallback( const QObject* object,
|
||||||
m_callbacks.append( QskMetaCallback( object, function ) );
|
m_callbacks.append( QskMetaCallback( object, function ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Invoker::addCallback( const QObject* object,
|
||||||
|
const char* methodName )
|
||||||
|
{
|
||||||
|
m_callbacks.append( QskMetaCallback( object, methodName ) );
|
||||||
|
}
|
||||||
|
|
||||||
void Invoker::invoke( qreal realValue, int intValue,
|
void Invoker::invoke( qreal realValue, int intValue,
|
||||||
Qt::ConnectionType connectionType )
|
Qt::ConnectionType connectionType )
|
||||||
{
|
{
|
||||||
|
QString s = QString( "S: %1 + %2" ).arg( realValue ).arg( intValue );
|
||||||
|
|
||||||
for ( auto& callback : m_callbacks )
|
for ( auto& callback : m_callbacks )
|
||||||
{
|
{
|
||||||
void* args[3] = { nullptr };
|
void* args[4] = { nullptr };
|
||||||
|
|
||||||
const auto types = callback.parameterTypes();
|
const auto types = callback.parameterTypes();
|
||||||
|
|
||||||
|
|
@ -41,6 +49,11 @@ void Invoker::invoke( qreal realValue, int intValue,
|
||||||
args[i++] = reinterpret_cast< void* >( &realValue );
|
args[i++] = reinterpret_cast< void* >( &realValue );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case QMetaType::QString:
|
||||||
|
{
|
||||||
|
args[i++] = reinterpret_cast< void* >( &s );
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ public:
|
||||||
|
|
||||||
void addCallback( const QskMetaFunction& );
|
void addCallback( const QskMetaFunction& );
|
||||||
void addCallback( const QObject*, const QskMetaFunction& );
|
void addCallback( const QObject*, const QskMetaFunction& );
|
||||||
|
void addCallback( const QObject*, const char* methodName );
|
||||||
|
|
||||||
void invoke( qreal d, int i, Qt::ConnectionType );
|
void invoke( qreal d, int i, Qt::ConnectionType );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,44 +9,52 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
static void debugNone1()
|
void debugNone1()
|
||||||
{
|
{
|
||||||
qDebug() << "None 1";
|
qDebug() << "None 1";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debugNone2()
|
void debugNone2()
|
||||||
{
|
{
|
||||||
qDebug() << "None 2";
|
qDebug() << "None 2";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debugValueI1( int i )
|
void debugValueI1( int i )
|
||||||
{
|
{
|
||||||
qDebug() << "I1" << i;
|
qDebug() << "I1" << i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debugValueI2( int i )
|
void debugValueI2( int i )
|
||||||
{
|
{
|
||||||
qDebug() << "I2" << i;
|
qDebug() << "I2" << i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debugValueD( qreal d )
|
void debugValueD( qreal d )
|
||||||
{
|
{
|
||||||
qDebug() << "D" << d;
|
qDebug() << "D" << d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void debugValue( qreal d, int i )
|
void debugValue( qreal d, int i )
|
||||||
{
|
{
|
||||||
qDebug() << d << i;
|
qDebug() << d << i;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyObject : public QObject
|
class MyObject : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MyObject( QObject* parent = nullptr ):
|
MyObject( QObject* parent = nullptr ):
|
||||||
QObject( parent )
|
QObject( parent )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_INVOKABLE void printInvokable( double d, int i ) const
|
||||||
|
{
|
||||||
|
qDebug() << "invokable" << d << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
void print0( double d, int i ) const
|
void print0( double d, int i ) const
|
||||||
{
|
{
|
||||||
qDebug() << "print0" << d << i;
|
qDebug() << "print0" << d << i;
|
||||||
|
|
@ -71,6 +79,11 @@ public:
|
||||||
{
|
{
|
||||||
qDebug() << i;
|
qDebug() << i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printS( const QString& s ) const
|
||||||
|
{
|
||||||
|
qDebug() << s;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static auto fs = []( int i, double d ) { qDebug() << i << d; };
|
static auto fs = []( int i, double d ) { qDebug() << i << d; };
|
||||||
|
|
@ -83,6 +96,18 @@ public:
|
||||||
m_object( new MyObject() ),
|
m_object( new MyObject() ),
|
||||||
m_thread( new QThread( this ) )
|
m_thread( new QThread( this ) )
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
|
m_invoker.addCallback( m_object, "print0(double,int)" );
|
||||||
|
m_invoker.addCallback( m_object, "print1(double,int)" );
|
||||||
|
m_invoker.addCallback( m_object, SLOT(print2(int,double)) );
|
||||||
|
m_invoker.addCallback( m_object, "print3(double)" );
|
||||||
|
m_invoker.addCallback( m_object, "print4(int)" );
|
||||||
|
m_invoker.addCallback( m_object, "print4(int)" );
|
||||||
|
m_invoker.addCallback( m_object, "printS(QString)" );
|
||||||
|
m_invoker.addCallback( m_object, "printInvokable(double,int)" );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
auto f = [this]( int i, double d ) { qDebug() << i << d << ( ++m_num ); };
|
auto f = [this]( int i, double d ) { qDebug() << i << d << ( ++m_num ); };
|
||||||
|
|
||||||
m_invoker.addCallback( m_object, &MyObject::print0 );
|
m_invoker.addCallback( m_object, &MyObject::print0 );
|
||||||
|
|
@ -99,6 +124,7 @@ public:
|
||||||
m_invoker.addCallback( m_object, &MyObject::print2 );
|
m_invoker.addCallback( m_object, &MyObject::print2 );
|
||||||
m_invoker.addCallback( m_object, &MyObject::print3 );
|
m_invoker.addCallback( m_object, &MyObject::print3 );
|
||||||
m_invoker.addCallback( m_object, &MyObject::print4 );
|
m_invoker.addCallback( m_object, &MyObject::print4 );
|
||||||
|
m_invoker.addCallback( m_object, &MyObject::printS );
|
||||||
m_invoker.addCallback( m_object, []( double d, int i ) { qDebug() << d << i; } );
|
m_invoker.addCallback( m_object, []( double d, int i ) { qDebug() << d << i; } );
|
||||||
|
|
||||||
m_invoker.addCallback( m_object, f );
|
m_invoker.addCallback( m_object, f );
|
||||||
|
|
@ -111,7 +137,7 @@ public:
|
||||||
m_invoker.addCallback( []( int i ) { qDebug() << "I2" << i; } );
|
m_invoker.addCallback( []( int i ) { qDebug() << "I2" << i; } );
|
||||||
m_invoker.addCallback( []( double d ) { qDebug() << "V" << d; } );
|
m_invoker.addCallback( []( double d ) { qDebug() << "V" << d; } );
|
||||||
m_invoker.addCallback( []( const double& d ) { qDebug() << "R" << d; } );
|
m_invoker.addCallback( []( const double& d ) { qDebug() << "R" << d; } );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Application()
|
virtual ~Application()
|
||||||
|
|
@ -164,3 +190,5 @@ int main( int argc, char* argv[] )
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "main.moc"
|
||||||
|
|
|
||||||
|
|
@ -5,31 +5,10 @@
|
||||||
|
|
||||||
#include "QskMetaCallback.h"
|
#include "QskMetaCallback.h"
|
||||||
#include "QskMetaFunction.h"
|
#include "QskMetaFunction.h"
|
||||||
|
#include "QskMetaMethod.h"
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QThread>
|
|
||||||
#include <QSemaphore>
|
|
||||||
#include <QMetaMethod>
|
#include <QMetaMethod>
|
||||||
|
|
||||||
QSK_QT_PRIVATE_BEGIN
|
|
||||||
#include <private/qobject_p.h>
|
|
||||||
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;
|
|
||||||
|
|
||||||
auto event = new QMetaCallEvent(
|
|
||||||
metaObject->methodOffset(), methodIndex, metaObject->d.static_metacall,
|
|
||||||
sender, signalId, nargs, types, args, semaphore );
|
|
||||||
|
|
||||||
QCoreApplication::postEvent( object, event );
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ) ),
|
||||||
|
|
@ -40,6 +19,12 @@ QskMetaCallback::QskMetaCallback( const QObject* object,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QskMetaCallback::QskMetaCallback( const QObject* object,
|
||||||
|
const char* methodName, Qt::ConnectionType connectionType ):
|
||||||
|
QskMetaCallback( object, QskMetaMethod::method( object, methodName ), connectionType )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
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 ) ),
|
||||||
|
|
@ -230,7 +215,7 @@ void QskMetaCallback::invoke( void* args[] )
|
||||||
{
|
{
|
||||||
case MetaMethod:
|
case MetaMethod:
|
||||||
{
|
{
|
||||||
qskInvokeMethod( object, m_methodData.metaObject,
|
QskMetaMethod::invoke( object, m_methodData.metaObject,
|
||||||
m_methodData.methodIndex, args, connectionType() );
|
m_methodData.methodIndex, args, connectionType() );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -247,111 +232,3 @@ void QskMetaCallback::invoke( void* args[] )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void qskInvokeMethod( 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();
|
|
||||||
qskInvokeMethod( object, metaObject, methodIndex, args, connectionType );
|
|
||||||
}
|
|
||||||
|
|
||||||
void qskInvokeMethod( QObject* object,
|
|
||||||
const QMetaObject* metaObject, int methodIndex, void* args[],
|
|
||||||
Qt::ConnectionType connectionType )
|
|
||||||
{
|
|
||||||
if ( ( metaObject == nullptr ) || ( methodIndex < 0 )
|
|
||||||
|| ( methodIndex > metaObject->methodCount() ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int invokeType = connectionType & 0x3;
|
|
||||||
|
|
||||||
if ( invokeType == Qt::AutoConnection )
|
|
||||||
{
|
|
||||||
invokeType = ( object && object->thread() != QThread::currentThread() )
|
|
||||||
? Qt::QueuedConnection : Qt::DirectConnection;
|
|
||||||
}
|
|
||||||
else if ( invokeType == Qt::BlockingQueuedConnection )
|
|
||||||
{
|
|
||||||
if ( ( object == nullptr ) || object->thread() == QThread::currentThread() )
|
|
||||||
{
|
|
||||||
// We would end up in a deadlock, better do nothing
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( invokeType == Qt::DirectConnection )
|
|
||||||
{
|
|
||||||
#if 1
|
|
||||||
if ( object == nullptr )
|
|
||||||
return; // do we really need an object here ???
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ( metaObject->d.static_metacall )
|
|
||||||
{
|
|
||||||
metaObject->d.static_metacall( object,
|
|
||||||
QMetaObject::InvokeMetaMethod, methodIndex, args );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QMetaObject::metacall( object,
|
|
||||||
QMetaObject::InvokeMetaMethod, methodIndex, args );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( object == nullptr )
|
|
||||||
return;
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
// should be doable without QMetaMethod. TODO ...
|
|
||||||
const auto method = metaObject->method( methodIndex );
|
|
||||||
#endif
|
|
||||||
const int paramCount = method.parameterCount();
|
|
||||||
|
|
||||||
auto types = static_cast< int* >( malloc( paramCount * sizeof( int ) ) );
|
|
||||||
auto arguments = static_cast< void** >( malloc( paramCount * sizeof( void* ) ) );
|
|
||||||
|
|
||||||
types[0] = QMetaType::UnknownType; // a return type is not possible
|
|
||||||
arguments[0] = nullptr;
|
|
||||||
|
|
||||||
for ( int i = 1; i < paramCount; i++ )
|
|
||||||
{
|
|
||||||
if ( arguments[i] == nullptr )
|
|
||||||
{
|
|
||||||
Q_ASSERT( arguments[i] != nullptr );
|
|
||||||
|
|
||||||
free( types );
|
|
||||||
free( arguments );
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
types[i] = method.parameterType( i );
|
|
||||||
arguments[i] = args[i - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_ASSERT( args[paramCount] == nullptr );
|
|
||||||
|
|
||||||
if ( connectionType == Qt::QueuedConnection )
|
|
||||||
{
|
|
||||||
qskInvokeMethodQueued( object,
|
|
||||||
metaObject, methodIndex, paramCount + 1, types, args );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QSemaphore semaphore;
|
|
||||||
|
|
||||||
qskInvokeMethodQueued( object,
|
|
||||||
metaObject, methodIndex, paramCount + 1, types, args, &semaphore );
|
|
||||||
|
|
||||||
semaphore.acquire();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,14 @@
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
class QskMetaInvokable;
|
class QskMetaInvokable;
|
||||||
class QskMetaFunction;
|
class QskMetaFunction;
|
||||||
|
class QMetaObject;
|
||||||
class QMetaMethod;
|
class QMetaMethod;
|
||||||
|
|
||||||
class QskMetaCallback
|
class QSK_EXPORT QskMetaCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type
|
enum Type
|
||||||
|
|
@ -37,6 +39,9 @@ public:
|
||||||
QskMetaCallback( const QObject*, const QMetaMethod&,
|
QskMetaCallback( const QObject*, const QMetaMethod&,
|
||||||
Qt::ConnectionType = Qt::AutoConnection );
|
Qt::ConnectionType = Qt::AutoConnection );
|
||||||
|
|
||||||
|
QskMetaCallback( const QObject*, const char* methodName,
|
||||||
|
Qt::ConnectionType = Qt::AutoConnection );
|
||||||
|
|
||||||
QskMetaCallback( const QskMetaCallback& );
|
QskMetaCallback( const QskMetaCallback& );
|
||||||
|
|
||||||
~QskMetaCallback();
|
~QskMetaCallback();
|
||||||
|
|
@ -99,14 +104,6 @@ inline Qt::ConnectionType QskMetaCallback::connectionType() const
|
||||||
return static_cast< Qt::ConnectionType >( m_connectionType );
|
return static_cast< Qt::ConnectionType >( m_connectionType );
|
||||||
}
|
}
|
||||||
|
|
||||||
QSK_EXPORT void qskInvokeMethod(
|
|
||||||
QObject* object, const QMetaMethod&, void* args[],
|
|
||||||
Qt::ConnectionType = Qt::AutoConnection );
|
|
||||||
|
|
||||||
QSK_EXPORT void qskInvokeMethod(
|
|
||||||
QObject* object, const QMetaObject*, int methodIndex, void* args[],
|
|
||||||
Qt::ConnectionType = Qt::AutoConnection );
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE( QskMetaCallback )
|
Q_DECLARE_METATYPE( QskMetaCallback )
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,8 @@ void QskMetaFunction::invoke(
|
||||||
// object might have died in the meantime
|
// object might have died in the meantime
|
||||||
free( types );
|
free( types );
|
||||||
free( arguments );
|
free( arguments );
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qskInvokeFunctionQueued( object, m_invokable, argc, types, arguments );
|
qskInvokeFunctionQueued( object, m_invokable, argc, types, arguments );
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,205 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* 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 <QObject>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QSemaphore>
|
||||||
|
#include <QMetaMethod>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
#include <private/qobject_p.h>
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* 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 <QObject>
|
||||||
|
#include <QMetaMethod>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
@ -43,6 +43,7 @@ HEADERS += \
|
||||||
common/QskMetaCallback.h \
|
common/QskMetaCallback.h \
|
||||||
common/QskMetaFunction.h \
|
common/QskMetaFunction.h \
|
||||||
common/QskMetaInvokable.cpp \
|
common/QskMetaInvokable.cpp \
|
||||||
|
common/QskMetaMethod.h \
|
||||||
common/QskModule.h \
|
common/QskModule.h \
|
||||||
common/QskNamespace.h \
|
common/QskNamespace.h \
|
||||||
common/QskObjectCounter.h \
|
common/QskObjectCounter.h \
|
||||||
|
|
@ -62,6 +63,7 @@ SOURCES += \
|
||||||
common/QskMetaCallback.cpp \
|
common/QskMetaCallback.cpp \
|
||||||
common/QskMetaFunction.cpp \
|
common/QskMetaFunction.cpp \
|
||||||
common/QskMetaInvokable.cpp \
|
common/QskMetaInvokable.cpp \
|
||||||
|
common/QskMetaMethod.cpp \
|
||||||
common/QskModule.cpp \
|
common/QskModule.cpp \
|
||||||
common/QskObjectCounter.cpp \
|
common/QskObjectCounter.cpp \
|
||||||
common/QskSizePolicy.cpp \
|
common/QskSizePolicy.cpp \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue