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;
@ -82,7 +69,7 @@ static bool qskContextMatcher( QObject* object, Qt::ShortcutContext context )
{
/*
Unfortunatley there is no way to have to know about
the contextItem without making it the receiver of
the contextItem without making it the receiver of
the following QShortcutEvent. So we have to install
an event handler to process and swallow it in QskShortcutHandler.
*/
@ -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