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 }; void* args[4] = { nullptr };
const auto types = callback.invokable().parameterTypes(); void **a = args + 1;
const auto& invokable = callback.invokable();
int i = 1; for ( int i = 0; i < invokable.parameterCount(); i++ )
for ( auto type : types )
{ {
switch ( type ) switch ( invokable.parameterType( i ) )
{ {
case QMetaType::Int: case QMetaType::Int:
{ {
args[i++] = reinterpret_cast< void* >( &intValue ); *a++ = reinterpret_cast< void* >( &intValue );
break; break;
} }
case QMetaType::Double: case QMetaType::Double:
{ {
args[i++] = reinterpret_cast< void* >( &realValue ); *a++ = reinterpret_cast< void* >( &realValue );
break; break;
} }
case QMetaType::QString: case QMetaType::QString:
{ {
args[i++] = reinterpret_cast< void* >( &s ); *a++ = reinterpret_cast< void* >( &s );
break; break;
} }
default: default:

View File

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

View File

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

View File

@ -5,9 +5,9 @@
#include "QskShortcutMap.h" #include "QskShortcutMap.h"
#include "QskControl.h" #include "QskControl.h"
#include "QskMetaInvokable.h"
#include <QQuickWindow> #include <QQuickWindow>
#include <QMetaMethod>
#include <QKeySequence> #include <QKeySequence>
#include <QGlobalStatic> #include <QGlobalStatic>
#include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qguiapplication_p.h>
@ -24,11 +24,8 @@ class QskShortcutHandler final : public QObject
public: public:
QskShortcutHandler(); QskShortcutHandler();
int add( QQuickItem*, const QKeySequence&, int insert( QQuickItem*, const QKeySequence&, bool autoRepeat,
const QObject* receiver, const char* method ); const QObject*, const QskMetaInvokable& );
int add( QQuickItem*, const QKeySequence&,
const QObject* receiver, QtPrivate::QSlotObjectBase* );
void remove( int id ); void remove( int id );
@ -38,8 +35,6 @@ public:
virtual bool eventFilter( QObject*, QEvent* ) override final; virtual bool eventFilter( QObject*, QEvent* ) override final;
private: private:
int insert( QQuickItem*, const QKeySequence&,
const QObject* receiver, const QMetaMethod&, QtPrivate::QSlotObjectBase* );
void cleanUp( QObject* ); void cleanUp( QObject* );
@ -48,21 +43,13 @@ private:
public: public:
InvokeData(): InvokeData():
item( nullptr ), item( nullptr ),
receiver( nullptr ), receiver( nullptr )
slotObject( nullptr )
{ {
} }
~InvokeData()
{
if ( slotObject )
slotObject->destroyIfLastRef();
}
QQuickItem* item; QQuickItem* item;
const QObject* receiver; const QObject* receiver;
QMetaMethod method; QskMetaInvokable invokable;
QtPrivate::QSlotObjectBase* slotObject;
}; };
std::map< int, InvokeData > m_invokeDataMap; std::map< int, InvokeData > m_invokeDataMap;
@ -101,39 +88,25 @@ QskShortcutHandler::QskShortcutHandler()
installEventFilter( this ); installEventFilter( this );
} }
int QskShortcutHandler::add( QQuickItem* item, const QKeySequence& sequence,
const QObject* receiver, const char* method )
{
int id = 0;
if ( receiver )
{
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 );
}
}
return id;
}
int QskShortcutHandler::add( QQuickItem* item, const QKeySequence& sequence,
const QObject* receiver, QtPrivate::QSlotObjectBase* slotObj )
{
return insert( item, sequence, receiver, QMetaMethod(), slotObj );
}
int QskShortcutHandler::insert( int QskShortcutHandler::insert(
QQuickItem* item, const QKeySequence& sequence, QQuickItem* item, const QKeySequence& sequence, bool autoRepeat,
const QObject* receiver, const QMetaMethod& method, const QObject* receiver, const QskMetaInvokable& invokable )
QtPrivate::QSlotObjectBase* slotObject )
{ {
if ( sequence.isEmpty() )
{
qDebug() << "QskShortcutMap: invalid shortcut key sequence";
return 0;
}
#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
if ( receiver ) if ( receiver )
{ {
connect( receiver, &QObject::destroyed, connect( receiver, &QObject::destroyed,
@ -163,11 +136,10 @@ int QskShortcutHandler::insert(
data.item = item; data.item = item;
data.receiver = receiver; data.receiver = receiver;
data.invokable = invokable;
if ( slotObject ) if ( !autoRepeat )
data.slotObject = slotObject; setAutoRepeat( id, false );
else
data.method = method;
return id; return id;
} }
@ -266,30 +238,14 @@ bool QskShortcutHandler::eventFilter( QObject* object, QEvent* event )
const auto it = m_invokeDataMap.find( se->shortcutId() ); const auto it = m_invokeDataMap.find( se->shortcutId() );
if ( it != m_invokeDataMap.end() ) 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 ) data.invokable.invoke( receiver, args, Qt::AutoConnection );
{
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 );
}
return true; return true;
} }
@ -303,24 +259,26 @@ int QskShortcutMap::addMethod( QQuickItem* item, const QKeySequence& sequence,
{ {
if ( receiver == nullptr ) if ( receiver == nullptr )
{ {
qDebug() << "QskShortcutMap: bad receiver for shortcut:" << sequence;
return 0; return 0;
} }
int id = qskShortcutHandler->add( item, sequence, receiver, method ); return qskShortcutHandler->insert(
if ( id && !autoRepeat ) item, sequence, autoRepeat, receiver, qskMetaMethod( receiver, method ) );
qskShortcutHandler->setAutoRepeat( id, false );
return id;
} }
int QskShortcutMap::addSlotObject( QQuickItem* item, const QKeySequence& sequence, int QskShortcutMap::addFunction( QQuickItem* item, const QKeySequence& sequence,
bool autoRepeat, const QObject* receiver, QtPrivate::QSlotObjectBase* slotObject ) bool autoRepeat, const QObject* receiver, const QskMetaFunction& function )
{ {
int id = qskShortcutHandler->add( item, sequence, receiver, slotObject ); if ( ( receiver == nullptr )
if ( id && !autoRepeat ) && ( function.functionType() == QskMetaFunction::Member ) )
qskShortcutHandler->setAutoRepeat( id, false ); {
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 ) void QskShortcutMap::setAutoRepeat( int id, bool on )

View File

@ -7,6 +7,8 @@
#define QSK_SHORTCUT_MAP_H #define QSK_SHORTCUT_MAP_H
#include "QskGlobal.h" #include "QskGlobal.h"
#include "QskMetaFunction.h"
#include <QQuickWindow> #include <QQuickWindow>
class QQuickItem; class QQuickItem;
@ -20,51 +22,34 @@ public:
static void removeShortcut( int ); static void removeShortcut( int );
// -- traditional slots // string based slots
static int addShortcut( const QKeySequence&, bool autoRepeat, static int addShortcut( const QKeySequence&,
const QObject* receiver, const char* method ); bool autoRepeat, const QObject* receiver, const char* method );
static int addShortcut( QQuickWindow*, const QKeySequence&, bool autoRepeat, static int addShortcut( QQuickWindow*, const QKeySequence&,
const QObject* receiver, const char* method ); bool autoRepeat, const QObject* receiver, const char* method );
static int addShortcut( QQuickItem*, const QKeySequence&, bool autoRepeat, static int addShortcut( QQuickItem*, const QKeySequence&,
const QObject* receiver, const char* method ); bool autoRepeat, const QObject* receiver, const char* method );
// -- calling a QObject method // functor based slots
template< typename Func1 > static int addShortcut( const QKeySequence&,
static int addShortcut( const QKeySequence&, bool autoRepeat, bool autoRepeat, const QskMetaFunction& );
const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot );
template< typename Func1 > static int addShortcut( const QKeySequence&,
static int addShortcut( QQuickWindow*, const QKeySequence&, bool autoRepeat, bool autoRepeat, const QObject* context, const QskMetaFunction& );
const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot );
template< typename Func1 > static int addShortcut( QQuickItem*, const QKeySequence&,
static int addShortcut( QQuickItem*, const QKeySequence&, bool autoRepeat, bool autoRepeat, const QskMetaFunction& );
const typename QtPrivate::FunctionPointer< Func1 >::Object* receiver, Func1 slot );
// -- calling a functor or function pointer inside a thread context static int addShortcut( QQuickItem*, const QKeySequence&,
template< typename Func1 > bool autoRepeat, const QObject* context, const QskMetaFunction& );
static int addShortcut( const QKeySequence&, bool autoRepeat,
const QObject* context, Func1 slot );
template< typename Func1 > static int addShortcut( QQuickWindow*, const QKeySequence&,
static int addShortcut( QQuickWindow*, const QKeySequence&, bool autoRepeat, bool autoRepeat, const QskMetaFunction& );
const QObject* context, Func1 slot );
template< typename Func1 > static int addShortcut( QQuickWindow*, const QKeySequence&,
static int addShortcut( QQuickItem*, const QKeySequence&, bool autoRepeat, bool autoRepeat, const QObject* context, const QskMetaFunction& );
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 bool contextMatcher( const QQuickItem*, Qt::ShortcutContext ); static bool contextMatcher( const QQuickItem*, Qt::ShortcutContext );
@ -72,66 +57,15 @@ private:
QskShortcutMap() = delete; QskShortcutMap() = delete;
~QskShortcutMap() = delete; ~QskShortcutMap() = delete;
static int addMethod( QQuickItem*, const QKeySequence&, bool autoRepeat, static int addFunction(
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(
QQuickItem* item, const QKeySequence&, bool autoRepeat, 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( inline int QskShortcutMap::addShortcut(
const QKeySequence& sequence, bool autoRepeat, const QKeySequence& sequence, bool autoRepeat,
const QObject* receiver, const char* method ) const QObject* receiver, const char* method )
@ -140,89 +74,55 @@ inline int QskShortcutMap::addShortcut(
} }
inline int QskShortcutMap::addShortcut( inline int QskShortcutMap::addShortcut(
QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat, QQuickWindow* window, const QKeySequence& sequence,
const QObject* receiver, const char* method ) bool autoRepeat, const QObject* receiver, const char* method )
{ {
auto item = window ? window->contentItem() : nullptr; auto item = window ? window->contentItem() : nullptr;
return addMethod( item, sequence, autoRepeat, receiver, method ); 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( inline int QskShortcutMap::addShortcut(
const QKeySequence& sequence, bool autoRepeat, 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( inline int QskShortcutMap::addShortcut(
QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, 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( inline int QskShortcutMap::addShortcut(
QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat, QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat,
const QObject* context, Func1 slot ) const QskMetaFunction& function )
{ {
auto item = window ? window->contentItem() : nullptr; 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( inline int QskShortcutMap::addShortcut(
QQuickItem* item, const QKeySequence& sequence, bool autoRepeat, Func1 slot ) QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat,
{ const QObject* context, const QskMetaFunction& function )
return addFunctorSlot( item, sequence, autoRepeat, nullptr, slot );
}
template< typename Func1 >
inline int QskShortcutMap::addShortcut(
QQuickWindow* window, const QKeySequence& sequence, bool autoRepeat, Func1 slot )
{ {
auto item = window ? window->contentItem() : nullptr; auto item = window ? window->contentItem() : nullptr;
return addFunctorSlot( item, sequence, autoRepeat, nullptr, autoRepeat, slot ); return addFunction( item, sequence, autoRepeat, context, function );
}
template< typename Func1 >
int QskShortcutMap::addShortcut(
const QKeySequence& sequence, bool autoRepeat, Func1 slot )
{
return addFunctorSlot( nullptr, sequence, autoRepeat, nullptr, slot );
} }
#endif #endif