QskShortcutMap using QskMetaInvokable

This commit is contained in:
Uwe Rathmann 2018-03-12 09:27:54 +01:00
parent 42a09813ed
commit ee3ac13e36
5 changed files with 137 additions and 277 deletions

View File

@ -43,26 +43,26 @@ void Invoker::invoke( qreal realValue, int intValue,
{
void* args[4] = { nullptr };
const auto types = callback.invokable().parameterTypes();
void **a = args + 1;
const auto& invokable = callback.invokable();
int i = 1;
for ( auto type : types )
for ( int i = 0; i < invokable.parameterCount(); i++ )
{
switch ( type )
switch ( invokable.parameterType( i ) )
{
case QMetaType::Int:
{
args[i++] = reinterpret_cast< void* >( &intValue );
*a++ = reinterpret_cast< void* >( &intValue );
break;
}
case QMetaType::Double:
{
args[i++] = reinterpret_cast< void* >( &realValue );
*a++ = reinterpret_cast< void* >( &realValue );
break;
}
case QMetaType::QString:
{
args[i++] = reinterpret_cast< void* >( &s );
*a++ = reinterpret_cast< void* >( &s );
break;
}
default:

View File

@ -467,55 +467,55 @@ void QskMetaInvokable::reset()
m_type = Invalid;
}
QVector< int > QskMetaInvokable::parameterTypes() const
int QskMetaInvokable::parameterCount() const
{
QVector< int > paramTypes;
switch( m_type )
{
case MetaMethod:
{
// should be doable without QMetaMethod. TODO ...
const auto method = QskMetaInvokable::method();
const int paramCount = method.parameterCount();
if ( paramCount > 0 )
{
paramTypes.reserve( paramCount );
for ( int i = 0; i < paramCount; i++ )
paramTypes += method.parameterType( i );
}
break;
return method.parameterCount();
}
case MetaProperty:
{
// should be doable without QMetaProperty. TODO ...
const auto property = QskMetaInvokable::property();
if ( property.isWritable() )
{
paramTypes.reserve( 1 );
paramTypes += property.userType();
}
break;
return 1;
}
case MetaFunction:
{
auto types = function().parameterTypes();
if ( types )
{
while ( *types )
paramTypes += *types++;
}
break;
return function().parameterCount();
}
default:
break;
}
return paramTypes;
return 0;
}
int QskMetaInvokable::parameterType( int index ) const
{
switch( m_type )
{
case MetaMethod:
{
const auto method = QskMetaInvokable::method();
return method.parameterType( index );
}
case MetaProperty:
{
const auto property = QskMetaInvokable::property();
return property.userType();
}
case MetaFunction:
{
auto types = function().parameterTypes();
return types[index];
}
default:
{
return QMetaType::UnknownType;
}
}
}
int QskMetaInvokable::returnType() const
@ -531,6 +531,9 @@ int QskMetaInvokable::returnType() const
return function().returnType();
}
case MetaProperty:
{
return QMetaType::Void;
}
default:
{
return QMetaType::Void;
@ -560,7 +563,6 @@ QByteArray QskMetaInvokable::name() const
return QByteArray();
}
}
}
QMetaMethod QskMetaInvokable::method() const

View File

@ -11,8 +11,6 @@
#include <QMetaType>
#include <Qt>
template< typename T > class QVector;
class QskMetaFunction;
class QMetaObject;
class QMetaMethod;
@ -60,7 +58,9 @@ public:
Type type() const;
bool isNull() const;
QVector< int > parameterTypes() const;
int parameterCount() const;
int parameterType( int index ) const;
int returnType() const;
void invoke( QObject*, void* args[],

View File

@ -5,9 +5,9 @@
#include "QskShortcutMap.h"
#include "QskControl.h"
#include "QskMetaInvokable.h"
#include <QQuickWindow>
#include <QMetaMethod>
#include <QKeySequence>
#include <QGlobalStatic>
#include <QtGui/private/qguiapplication_p.h>
@ -24,11 +24,8 @@ class QskShortcutHandler final : public QObject
public:
QskShortcutHandler();
int add( QQuickItem*, const QKeySequence&,
const QObject* receiver, const char* method );
int add( QQuickItem*, const QKeySequence&,
const QObject* receiver, QtPrivate::QSlotObjectBase* );
int insert( QQuickItem*, const QKeySequence&, bool autoRepeat,
const QObject*, const QskMetaInvokable& );
void remove( int id );
@ -38,8 +35,6 @@ public:
virtual bool eventFilter( QObject*, QEvent* ) override final;
private:
int insert( QQuickItem*, const QKeySequence&,
const QObject* receiver, const QMetaMethod&, QtPrivate::QSlotObjectBase* );
void cleanUp( QObject* );
@ -48,21 +43,13 @@ private:
public:
InvokeData():
item( nullptr ),
receiver( nullptr ),
slotObject( nullptr )
receiver( nullptr )
{
}
~InvokeData()
{
if ( slotObject )
slotObject->destroyIfLastRef();
}
QQuickItem* item;
const QObject* receiver;
QMetaMethod method;
QtPrivate::QSlotObjectBase* slotObject;
QskMetaInvokable invokable;
};
std::map< int, InvokeData > m_invokeDataMap;
@ -101,39 +88,25 @@ QskShortcutHandler::QskShortcutHandler()
installEventFilter( this );
}
int QskShortcutHandler::add( QQuickItem* item, const QKeySequence& sequence,
const QObject* receiver, const char* method )
int QskShortcutHandler::insert(
QQuickItem* item, const QKeySequence& sequence, bool autoRepeat,
const QObject* receiver, const QskMetaInvokable& invokable )
{
int id = 0;
if ( receiver )
if ( sequence.isEmpty() )
{
const QMetaObject* metaObject = receiver->metaObject();
const int methodIndex = metaObject->indexOfMethod(
QMetaObject::normalizedSignature( method ).constData() + 1 );
if ( methodIndex >= 0 )
{
id = insert( item, sequence,
receiver, metaObject->method( methodIndex ), nullptr );
}
qDebug() << "QskShortcutMap: invalid shortcut key sequence";
return 0;
}
return id;
}
#if 1
// should be a compile time check for functor based slots
if ( invokable.parameterCount() > 0 )
{
qDebug() << "QskShortcutMap: invalid slot parameter count";
return 0;
}
#endif
int QskShortcutHandler::add( QQuickItem* item, const QKeySequence& sequence,
const QObject* receiver, QtPrivate::QSlotObjectBase* slotObj )
{
return insert( item, sequence, receiver, QMetaMethod(), slotObj );
}
int QskShortcutHandler::insert(
QQuickItem* item, const QKeySequence& sequence,
const QObject* receiver, const QMetaMethod& method,
QtPrivate::QSlotObjectBase* slotObject )
{
if ( receiver )
{
connect( receiver, &QObject::destroyed,
@ -163,11 +136,10 @@ int QskShortcutHandler::insert(
data.item = item;
data.receiver = receiver;
data.invokable = invokable;
if ( slotObject )
data.slotObject = slotObject;
else
data.method = method;
if ( !autoRepeat )
setAutoRepeat( id, false );
return id;
}
@ -266,30 +238,14 @@ bool QskShortcutHandler::eventFilter( QObject* object, QEvent* event )
const auto it = m_invokeDataMap.find( se->shortcutId() );
if ( it != m_invokeDataMap.end() )
{
const auto& invokeData = it->second;
auto& data = it->second;
Q_ASSERT( invokeData.item == nullptr || invokeData.item == object );
Q_ASSERT( data.item == nullptr || data.item == object );
auto receiver = const_cast< QObject* >( invokeData.receiver );
auto receiver = const_cast< QObject* > ( data.receiver );
void* args[] = { nullptr };
if ( invokeData.slotObject )
{
void* args[] = { 0 };
if ( receiver && receiver->thread() != thread() )
{
QCoreApplication::postEvent( receiver,
new QMetaCallEvent( invokeData.slotObject, nullptr, 0, 0, nullptr, args ) );
}
else
{
invokeData.slotObject->call( receiver, args );
}
}
else
{
invokeData.method.invoke( receiver, Qt::AutoConnection );
}
data.invokable.invoke( receiver, args, Qt::AutoConnection );
return true;
}
@ -303,24 +259,26 @@ int QskShortcutMap::addMethod( QQuickItem* item, const QKeySequence& sequence,
{
if ( receiver == nullptr )
{
qDebug() << "QskShortcutMap: bad receiver for shortcut:" << sequence;
return 0;
}
int id = qskShortcutHandler->add( item, sequence, receiver, method );
if ( id && !autoRepeat )
qskShortcutHandler->setAutoRepeat( id, false );
return id;
return qskShortcutHandler->insert(
item, sequence, autoRepeat, receiver, qskMetaMethod( receiver, method ) );
}
int QskShortcutMap::addSlotObject( QQuickItem* item, const QKeySequence& sequence,
bool autoRepeat, const QObject* receiver, QtPrivate::QSlotObjectBase* slotObject )
int QskShortcutMap::addFunction( QQuickItem* item, const QKeySequence& sequence,
bool autoRepeat, const QObject* receiver, const QskMetaFunction& function )
{
int id = qskShortcutHandler->add( item, sequence, receiver, slotObject );
if ( id && !autoRepeat )
qskShortcutHandler->setAutoRepeat( id, false );
if ( ( receiver == nullptr )
&& ( function.functionType() == QskMetaFunction::Member ) )
{
qDebug() << "QskShortcutMap: bad receiver for shortcut:" << sequence;
return 0;
}
return id;
return qskShortcutHandler->insert(
item, sequence, autoRepeat, receiver, function );
}
void QskShortcutMap::setAutoRepeat( int id, bool on )

View File

@ -7,6 +7,8 @@
#define QSK_SHORTCUT_MAP_H
#include "QskGlobal.h"
#include "QskMetaFunction.h"
#include <QQuickWindow>
class QQuickItem;
@ -20,51 +22,34 @@ public:
static void removeShortcut( int );
// -- traditional slots
static int addShortcut( const QKeySequence&, bool autoRepeat,
const QObject* receiver, const char* method );
// string based slots
static int addShortcut( const QKeySequence&,
bool autoRepeat, const QObject* receiver, const char* method );
static int addShortcut( QQuickWindow*, const QKeySequence&, bool autoRepeat,
const QObject* receiver, const char* method );
static int addShortcut( QQuickWindow*, const QKeySequence&,
bool autoRepeat, const QObject* receiver, const char* method );
static int addShortcut( QQuickItem*, const QKeySequence&, bool autoRepeat,
const QObject* receiver, const char* method );
static int addShortcut( QQuickItem*, const QKeySequence&,
bool autoRepeat, const QObject* receiver, const char* method );
// -- calling a QObject method
template< typename Func1 >
static int addShortcut( const QKeySequence&, bool autoRepeat,
const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot );
// functor based slots
static int addShortcut( const QKeySequence&,
bool autoRepeat, const QskMetaFunction& );
template< typename Func1 >
static int addShortcut( QQuickWindow*, const QKeySequence&, bool autoRepeat,
const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot );
static int addShortcut( const QKeySequence&,
bool autoRepeat, const QObject* context, const QskMetaFunction& );
template< typename Func1 >
static int addShortcut( QQuickItem*, const QKeySequence&, bool autoRepeat,
const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot );
static int addShortcut( QQuickItem*, const QKeySequence&,
bool autoRepeat, const QskMetaFunction& );
// -- calling a functor or function pointer inside a thread context
template< typename Func1 >
static int addShortcut( const QKeySequence&, bool autoRepeat,
const QObject* context, Func1 slot );
static int addShortcut( QQuickItem*, const QKeySequence&,
bool autoRepeat, const QObject* context, const QskMetaFunction& );
template< typename Func1 >
static int addShortcut( QQuickWindow*, const QKeySequence&, bool autoRepeat,
const QObject* context, Func1 slot );
static int addShortcut( QQuickWindow*, const QKeySequence&,
bool autoRepeat, const QskMetaFunction& );
template< typename Func1 >
static int addShortcut( QQuickItem*, const QKeySequence&, bool autoRepeat,
const QObject* context, Func1 slot );
// -- calling a functor or function pointer
template< typename Func1 >
static int addShortcut( const QKeySequence&, bool autoRepeat, Func1 slot );
template< typename Func1 >
static int addShortcut( QQuickWindow*, const QKeySequence&, bool autoRepeat, Func1 slot );
template< typename Func1 >
static int addShortcut( QQuickItem*, const QKeySequence&, bool autoRepeat, Func1 slot );
static int addShortcut( QQuickWindow*, const QKeySequence&,
bool autoRepeat, const QObject* context, const QskMetaFunction& );
static bool contextMatcher( const QQuickItem*, Qt::ShortcutContext );
@ -72,66 +57,15 @@ private:
QskShortcutMap() = delete;
~QskShortcutMap() = delete;
static int addMethod( QQuickItem*, const QKeySequence&, bool autoRepeat,
const QObject* receiver, const char* method );
template< typename Func1 >
static int addMemberSlot( QQuickItem*, const QKeySequence&, bool autoRepeat,
const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot );
template< typename Func1 >
static int addFunctorSlot( QQuickItem*, const QKeySequence&,
bool autoRepeat, const QObject* context, Func1 slot );
static int addSlotObject(
static int addFunction(
QQuickItem* item, const QKeySequence&, bool autoRepeat,
const QObject* receiver, QtPrivate::QSlotObjectBase* );
const QObject* receiver, const QskMetaFunction& );
static int addMethod(
QQuickItem* item, const QKeySequence&, bool autoRepeat,
const QObject* receiver, const char* );
};
template< typename Func1 >
inline int QskShortcutMap::addMemberSlot(
QQuickItem* item, const QKeySequence& sequence, bool autoRepeat,
const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot )
{
using namespace QtPrivate;
typedef FunctionPointer< Func1 > SlotType;
Q_STATIC_ASSERT_X( int( SlotType::ArgumentCount ) == 0,
"The slot must not have any arguments.");
return addSlotObject( item, sequence, autoRepeat, receiver,
new QSlotObject< Func1, typename SlotType::Arguments, void >( slot ) );
}
template< typename Func1 >
inline int QskShortcutMap::addFunctorSlot(
QQuickItem* item, const QKeySequence& sequence, bool autoRepeat,
const QObject* context, Func1 slot )
{
using namespace QtPrivate;
typedef FunctionPointer< Func1 > SlotType;
Q_STATIC_ASSERT_X( int( SlotType::ArgumentCount ) <= 0,
"The slot must not have any arguments.");
Q_STATIC_ASSERT_X( !SlotType::IsPointerToMemberFunction,
"The slot must be no member function." );
using Args = List_Left< void, 0 >::Value;
return addSlotObject( item, sequence, autoRepeat, context,
new QFunctorSlotObject< Func1, 0, Args, void >( slot ) );
}
// -- traditional slots
inline int QskShortcutMap::addShortcut(
QQuickItem* item, const QKeySequence& sequence, bool autoRepeat,
const QObject* receiver, const char* method )
{
return addMethod( item, sequence, autoRepeat, receiver, method );
}
inline int QskShortcutMap::addShortcut(
const QKeySequence& sequence, bool autoRepeat,
const QObject* receiver, const char* method )
@ -140,89 +74,55 @@ inline int QskShortcutMap::addShortcut(
}
inline int QskShortcutMap::addShortcut(
QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat,
const QObject* receiver, const char* method )
QQuickWindow* window, const QKeySequence& sequence,
bool autoRepeat, const QObject* receiver, const char* method )
{
auto item = window ? window->contentItem() : nullptr;
return addMethod( item, sequence, autoRepeat, receiver, method );
}
// -- calling a QObject method
template< typename Func1 >
inline int QskShortcutMap::addShortcut(
QQuickItem* item, const QKeySequence& sequence, bool autoRepeat,
const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot )
{
return addMemberSlot( item, sequence, autoRepeat, receiver, slot );
}
template< typename Func1 >
inline int QskShortcutMap::addShortcut(
QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat,
const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot )
{
auto item = window ? window->contentItem() : nullptr;
return addMemberSlot( item, sequence, autoRepeat, receiver, slot );
}
template< typename Func1 >
inline int QskShortcutMap::addShortcut(
const QKeySequence& sequence, bool autoRepeat,
const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot )
const QskMetaFunction& function )
{
return addMemberSlot( nullptr, sequence, autoRepeat, receiver, slot );
return addFunction( nullptr, sequence, autoRepeat, nullptr, function );
}
// -- calling a functor or function pointer with context
inline int QskShortcutMap::addShortcut(
const QKeySequence& sequence, bool autoRepeat,
const QObject* context, const QskMetaFunction& function )
{
return addFunction( nullptr, sequence, autoRepeat, context, function );
}
template< typename Func1 >
inline int QskShortcutMap::addShortcut(
QQuickItem* item, const QKeySequence& sequence, bool autoRepeat,
const QObject* context, Func1 slot )
const QskMetaFunction& function )
{
return addFunctorSlot( item, sequence, autoRepeat, context, slot );
return addFunction( item, sequence, autoRepeat, nullptr, function );
}
inline int QskShortcutMap::addShortcut(
QQuickItem* item, const QKeySequence& sequence, bool autoRepeat,
const QObject* context, const QskMetaFunction& function )
{
return addFunction( item, sequence, autoRepeat, context, function );
}
template< typename Func1 >
inline int QskShortcutMap::addShortcut(
QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat,
const QObject* context, Func1 slot )
const QskMetaFunction& function )
{
auto item = window ? window->contentItem() : nullptr;
return addFunctorSlot( item, sequence, autoRepeat, context, slot );
return addFunction( item, sequence, autoRepeat, nullptr, function );
}
template< typename Func1 >
inline int QskShortcutMap::addShortcut( const QKeySequence& sequence, bool autoRepeat,
const QObject* context, Func1 slot )
{
return addFunctorSlot( nullptr, sequence, autoRepeat, context, slot );
}
// -- calling a functor or function pointer
template< typename Func1 >
inline int QskShortcutMap::addShortcut(
QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, Func1 slot )
{
return addFunctorSlot( item, sequence, autoRepeat, nullptr, slot );
}
template< typename Func1 >
inline int QskShortcutMap::addShortcut(
QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat, Func1 slot )
QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat,
const QObject* context, const QskMetaFunction& function )
{
auto item = window ? window->contentItem() : nullptr;
return addFunctorSlot( item, sequence, autoRepeat, nullptr, autoRepeat, slot );
}
template< typename Func1 >
int QskShortcutMap::addShortcut(
const QKeySequence& sequence, bool autoRepeat, Func1 slot )
{
return addFunctorSlot( nullptr, sequence, autoRepeat, nullptr, slot );
return addFunction( item, sequence, autoRepeat, context, function );
}
#endif