summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/qobject.cpp164
-rw-r--r--src/corelib/kernel/qobject.h101
-rw-r--r--src/corelib/kernel/qobject_impl.h354
-rw-r--r--src/corelib/kernel/qobject_p.h11
-rw-r--r--src/corelib/kernel/qobjectdefs.h4
5 files changed, 624 insertions, 10 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 59282d3464..e8735d0c09 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -923,9 +923,13 @@ QObject::~QObject()
QObjectPrivate::Connection::~Connection()
{
- int *v = argumentTypes.load();
- if (v != &DIRECT_CONNECTION_ONLY)
- delete [] v;
+ if (ownArgumentTypes) {
+ const int *v = argumentTypes.load();
+ if (v != &DIRECT_CONNECTION_ONLY)
+ delete [] v;
+ }
+ if (isSlotObject && !slotObj->ref.deref())
+ delete slotObj;
}
@@ -3022,6 +3026,7 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, i
c->method_relative = method_index;
c->method_offset = method_offset;
c->connectionType = type;
+ c->isSlotObject = false;
c->argumentTypes.store(types);
c->nextConnectionList = 0;
c->callFunction = callFunction;
@@ -3231,7 +3236,7 @@ void QMetaObject::connectSlotsByName(QObject *o)
static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
{
- int *argumentTypes = c->argumentTypes.load();
+ const int *argumentTypes = c->argumentTypes.load();
if (!argumentTypes && argumentTypes != &DIRECT_CONNECTION_ONLY) {
QMetaMethod m = sender->metaObject()->method(signal);
argumentTypes = queuedConnectionTypes(m.parameterTypes());
@@ -3392,7 +3397,12 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign
}
const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction;
const int method_relative = c->method_relative;
- if (callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
+ if (c->isSlotObject) {
+ QExplicitlySharedDataPointer<QObject::QSlotObjectBase> obj(c->slotObj);
+ locker.unlock();
+ obj->call(receiver, argv ? argv : empty_argv);
+ locker.relock();
+ } else if (callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
//we compare the vtable to make sure we are not in the destructor of the object.
locker.unlock();
if (qt_signal_spy_callback_set.slot_begin_callback != 0)
@@ -4043,6 +4053,146 @@ void qDeleteInEventHandler(QObject *o)
}
/*!
+ \fn QMetaObject::Connection QObject::connect(const QObject *sender, (T::*signal)(...), const QObject *receiver, (T::*method)(...), Qt::ConnectionType type)
+
+ \threadsafe
+
+ Creates a connection of the given \a type from the \a signal in
+ the \a sender object to the \a method in the \a receiver object.
+ Returns a handle to the connection that can be used to disconnect
+ it later.
+
+ The signal must be a function declared as a signal in the header.
+ The slot function can be any member function that can be connected
+ to the signal.
+ A slot can be connected to a given signal if the signal has at
+ least as many arguments as the slot, and there is an implicit
+ conversion between the types of the corresponding arguments in the
+ signal and the slot.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 44
+
+ This example ensures that the label always displays the current
+ line edit text.
+
+ A signal can be connected to many slots and signals. Many signals
+ can be connected to one slot.
+
+ If a signal is connected to several slots, the slots are activated
+ in the same order as the order the connection was made, when the
+ signal is emitted
+
+ The function returns an handle to a connection if it successfully
+ connects the signal to the slot. The Connection handle will be invalid
+ if it cannot create the connection, for example, if QObject is unable
+ to verify the existence of \a signal (if it was not declared as a signal)
+ You can check if the QMetaObject::Connection is valid by casting it to a bool.
+
+ The optional \a type parameter describes the type of connection
+ to establish. In particular, it determines whether a particular
+ signal is delivered to a slot immediately or queued for delivery
+ at a later time. If the signal is queued, the parameters must be
+ of types that are known to Qt's meta-object system, because Qt
+ needs to copy the arguments to store them in an event behind the
+ scenes. If you try to use a queued connection and get the error
+ message
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 25
+
+ make sure to declare the argument type with Q_DECLARE_METATYPE
+
+ A signal is emitted for every connection you make;
+ two signals are emitted for duplicate connections.
+ This overload does not support the type Qt::UniqueConnection
+ */
+
+
+/*!
+ \fn QMetaObject::Connection QObject::connect(const QObject *sender, (T::*signal)(...), Functor functor)
+
+ \threadsafe
+ \overload
+
+ Creates a connection of the given \a type from the \a signal in
+ the \a sender object to the \a functor and returns a handle to the connection
+
+ The signal must be a function declared as a signal in the header.
+ The slot function can be any function or functor that can be connected
+ to the signal.
+ A function can be connected to a given signal if the signal as at
+ least as many argument as the slot. A functor can be connected to a signal
+ if they have exactly the same number of arguments. There must exist implicit
+ conversion between the types of the corresponding arguments in the
+ signal and the slot.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 45
+
+ If your compiler support C++11 lambda expressions, you can use them:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 46
+
+ The connection will automatically disconnect if the sender is destroyed.
+ */
+QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signal, const QObject *receiver, QObject::QSlotObjectBase *slotObj,
+ Qt::ConnectionType type, const int* types, const QMetaObject* senderMetaObject)
+{
+ int signal_index = -1;
+ void *args[] = { &signal_index, signal };
+ senderMetaObject->static_metacall(QMetaObject::IndexOfMethod, 0, args);
+ if (signal_index < 0 || signal_index >= QMetaObjectPrivate::get(senderMetaObject)->signalCount) {
+ qWarning("QObject::connect: signal not found in %s", senderMetaObject->className());
+ return QMetaObject::Connection(0);
+ }
+ int signalOffset, methodOffset;
+ computeOffsets(senderMetaObject, &signalOffset, &methodOffset);
+ signal_index += signalOffset;
+
+ // duplicated from QMetaObjectPrivate::connect
+ QObject *s = const_cast<QObject *>(sender);
+ QObject *r = const_cast<QObject *>(receiver);
+
+ QOrderedMutexLocker locker(signalSlotLock(sender),
+ signalSlotLock(receiver));
+
+ if (type & Qt::UniqueConnection) {
+ qWarning() << "QObject::connect: Qt::UniqueConnection not supported when connecting function pointers";
+ type = static_cast<Qt::ConnectionType>(type & (Qt::UniqueConnection - 1));
+ }
+
+ QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection);
+ c->sender = s;
+ c->receiver = r;
+ c->slotObj = slotObj;
+ c->connectionType = type;
+ c->isSlotObject = true;
+ if (types) {
+ c->argumentTypes.store(types);
+ c->ownArgumentTypes = false;
+ }
+
+ QObjectPrivate::get(s)->addConnection(signal_index, c.data());
+
+ c->prev = &(QObjectPrivate::get(r)->senders);
+ c->next = *c->prev;
+ *c->prev = c.data();
+ if (c->next)
+ c->next->prev = &c->next;
+
+ QObjectPrivate *const sender_d = QObjectPrivate::get(s);
+ if (signal_index < 0) {
+ sender_d->connectedSignals[0] = sender_d->connectedSignals[1] = ~0;
+ } else if (signal_index < (int)sizeof(sender_d->connectedSignals) * 8) {
+ sender_d->connectedSignals[signal_index >> 5] |= (1 << (signal_index & 0x1f));
+ }
+
+ return QMetaObject::Connection(c.take());
+}
+
+/*!
Disconnect a connection.
If the \a connection is invalid or has already been disconnected, do nothing
@@ -4119,6 +4269,10 @@ QMetaObject::Connection::~Connection()
the signal or the slot, or if the arguments do not match.
*/
+QObject::QSlotObjectBase::~QSlotObjectBase()
+{
+}
+
QT_END_NAMESPACE
#include "moc_qobject.cpp"
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index 038b59042b..93448b5ad1 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -52,6 +52,9 @@
#include <QtCore/qcoreevent.h>
#endif
#include <QtCore/qscopedpointer.h>
+#include <QtCore/qmetatype.h>
+
+#include <QtCore/qobject_impl.h>
QT_BEGIN_HEADER
@@ -204,6 +207,58 @@ public:
inline QMetaObject::Connection connect(const QObject *sender, const char *signal,
const char *member, Qt::ConnectionType type = Qt::AutoConnection) const;
+ //Connect a signal to a pointer to qobject member function
+ template <typename Func1, typename Func2>
+ static inline QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal,
+ const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, Func2 slot,
+ Qt::ConnectionType type = Qt::AutoConnection)
+ {
+ typedef QtPrivate::FunctionPointer<Func1> SignalType;
+ typedef QtPrivate::FunctionPointer<Func2> SlotType;
+ reinterpret_cast<typename SignalType::Object *>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<typename SignalType::Object *>(0));
+
+ //compilation error if the arguments does not match.
+ typedef typename QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::IncompatibleSignalSlotArguments EnsureCompatibleArguments;
+
+ const int *types = 0;
+ return connectImpl(sender, reinterpret_cast<void **>(&signal),
+ receiver, new QSlotObject<Func2,
+ typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
+ typename SignalType::ReturnType>(slot),
+ type, types, &SignalType::Object::staticMetaObject);
+ }
+
+ //connect to a function pointer (not a member)
+ template <typename Func1, typename Func2>
+ static inline typename QtPrivate::QEnableIf<int(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0, QMetaObject::Connection>::Type
+ connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
+ {
+ typedef QtPrivate::FunctionPointer<Func1> SignalType;
+ typedef QtPrivate::FunctionPointer<Func2> SlotType;
+
+ //compilation error if the arguments does not match.
+ typedef typename QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::IncompatibleSignalSlotArguments EnsureCompatibleArguments;
+ typedef typename QtPrivate::QEnableIf<(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount))>::Type EnsureArgumentsCount;
+
+ return connectImpl(sender, reinterpret_cast<void **>(&signal), sender,
+ new QStaticSlotObject<Func2,
+ typename QtPrivate::List_Left<typename SignalType::Arguments, SlotType::ArgumentCount>::Value,
+ typename SignalType::ReturnType>(slot),
+ Qt::DirectConnection, 0, &SignalType::Object::staticMetaObject);
+ }
+
+ //connect to a functor
+ template <typename Func1, typename Func2>
+ static inline typename QtPrivate::QEnableIf<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::Type
+ connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
+ {
+ typedef QtPrivate::FunctionPointer<Func1> SignalType;
+
+ return connectImpl(sender, reinterpret_cast<void **>(&signal),
+ sender, new QFunctorSlotObject<Func2, SignalType::ArgumentCount, typename SignalType::Arguments, typename SignalType::ReturnType>(slot),
+ Qt::DirectConnection, 0, &SignalType::Object::staticMetaObject);
+ }
+
static bool disconnect(const QObject *sender, const char *signal,
const QObject *receiver, const char *member);
static bool disconnect(const QObject *sender, const QMetaMethod &signal,
@@ -273,6 +328,52 @@ protected:
private:
Q_DISABLE_COPY(QObject)
Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *))
+
+ private:
+ // internal base class (interface) containing functions required to call a slot managed by a pointer to function.
+ struct QSlotObjectBase {
+ QAtomicInt ref;
+ QSlotObjectBase() : ref(1) {}
+ virtual ~QSlotObjectBase();
+ virtual void call(QObject *receiver, void **a) = 0;
+ };
+ // implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject
+ // Args and R are the List of arguments and the returntype of the signal to which the slot is connected.
+ template<typename Func, typename Args, typename R> struct QSlotObject : QSlotObjectBase
+ {
+ typedef QtPrivate::FunctionPointer<Func> FuncType;
+ Func function;
+ QSlotObject(Func f) : function(f) {};
+ virtual void call(QObject *receiver, void **a) {
+ FuncType::template call<Args, R>(function, static_cast<typename FuncType::Object *>(receiver), a);
+ }
+ };
+ // implementation of QSlotObjectBase for which the slot is a static function
+ // Args and R are the List of arguments and the returntype of the signal to which the slot is connected.
+ template<typename Func, typename Args, typename R> struct QStaticSlotObject : QSlotObjectBase
+ {
+ typedef QtPrivate::FunctionPointer<Func> FuncType;
+ Func function;
+ QStaticSlotObject(Func f) : function(f) {}
+ virtual void call(QObject *receiver, void **a) {
+ FuncType::template call<Args, R>(function, receiver, a);
+ }
+ };
+ // implementation of QSlotObjectBase for which the slot is a functor (or lambda)
+ // N is the number of arguments
+ // Args and R are the List of arguments and the returntype of the signal to which the slot is connected.
+ template<typename Func, int N, typename Args, typename R> struct QFunctorSlotObject : QSlotObjectBase
+ {
+ typedef QtPrivate::Functor<Func, N> FuncType;
+ Func function;
+ QFunctorSlotObject(const Func &f) : function(f) {}
+ virtual void call(QObject *receiver, void **a) {
+ FuncType::template call<Args, R>(function, receiver, a);
+ }
+ };
+
+ static QMetaObject::Connection connectImpl(const QObject *sender, void **signal, const QObject *receiver, QSlotObjectBase *slot,
+ Qt::ConnectionType type, const int *types, const QMetaObject *senderMetaObject);
};
inline QMetaObject::Connection QObject::connect(const QObject *asender, const char *asignal,
diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h
new file mode 100644
index 0000000000..7d3dc1659b
--- /dev/null
+++ b/src/corelib/kernel/qobject_impl.h
@@ -0,0 +1,354 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef Q_QDOC
+
+#ifndef QOBJECT_H
+#error Do not include qobject_impl.h directly
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+namespace QtPrivate {
+ template <typename T> struct RemoveRef { typedef T Type; };
+ template <typename T> struct RemoveRef<const T&> { typedef T Type; };
+ template <typename T> struct RemoveRef<T&> { typedef T Type; };
+ template <typename T> struct RemoveConstRef { typedef T Type; };
+ template <typename T> struct RemoveConstRef<const T&> { typedef T Type; };
+
+ /*
+ The following List classes are used to help to handle the list of arguments.
+ It follow the same principles as the lisp lists.
+ List_Left<L,N> take a list and a number as a parametter and returns (via the Value typedef,
+ the list composed of the first N element of the list
+ */
+#ifndef Q_COMPILER_VARIADIC_TEMPLATES
+ template <typename Head, typename Tail> struct List { typedef Head Car; typedef Tail Cdr; };
+ template <typename L, int N> struct List_Left { typedef List<typename L::Car, typename List_Left<typename L::Cdr, N - 1>::Value > Value; };
+ template <typename L> struct List_Left<L,0> { typedef void Value; };
+#else
+ // With variadic template, lists are represented using a variadic template argument instead of the lisp way
+ template <typename...> struct List {};
+ template <typename Head, typename... Tail> struct List<Head, Tail...> { typedef Head Car; typedef List<Tail...> Cdr; };
+ template <typename, typename> struct List_Append;
+ template <typename... L1, typename...L2> struct List_Append<List<L1...>, List<L2...>> { typedef List<L1..., L2...> Value; };
+ template <typename L, int N> struct List_Left {
+ typedef typename List_Append<List<typename L::Car>,typename List_Left<typename L::Cdr, N - 1>::Value>::Value Value;
+ };
+ template <typename L> struct List_Left<L, 0> { typedef List<> Value; };
+#endif
+ // List_Select<L,N> returns (via typedef Value) the Nth element of the list L
+ template <typename L, int N> struct List_Select { typedef typename List_Select<typename L::Cdr, N - 1>::Value Value; };
+ template <typename L> struct List_Select<L,0> { typedef typename L::Car Value; };
+
+ /*
+ trick to set the return value of a slot that works even if the signal or the slot returns void
+ to be used like function(), ApplyReturnValue<ReturnType>(&return_value)
+ if function() returns a value, the operator,(T, ApplyReturnValue<ReturnType>) is called, but if it
+ returns void, the builtin one is used without an error.
+ */
+ template <typename T>
+ struct ApplyReturnValue {
+ void *data;
+ ApplyReturnValue(void *data) : data(data) {}
+ };
+ template<typename T, typename U>
+ void operator,(const T &value, const ApplyReturnValue<U> &container) {
+ *reinterpret_cast<U*>(container.data) = value;
+ }
+#ifdef Q_COMPILER_RVALUE_REFS
+ template<typename T, typename U>
+ void operator,(T &&value, const ApplyReturnValue<U> &container) {
+ *reinterpret_cast<U*>(container.data) = value;
+ }
+#endif
+ template<typename T>
+ void operator,(T, const ApplyReturnValue<void> &) {}
+
+
+ /*
+ The FunctionPointer<Func> struct is a type trait for function pointer.
+ - ArgumentCount is the number of argument, or -1 if it is unknown
+ - the Object typedef is the Object of a pointer to member function
+ - the Arguments typedef is the list of argument (in a QtPrivate::List)
+ - the Function typedef is an alias to the template parametter Func
+ - the call<Args, R>(f,o,args) method is used to call that slot
+ Args is the list of argument of the signal
+ R is the return type of the signal
+ f is the function pointer
+ o is the receiver object
+ and args is the array of pointer to arguments, as used in qt_metacall
+
+ The Functor<Func,N> struct is the helper to call a functor of N argument.
+ its call function is the same as the FunctionPointer::call function.
+ */
+#ifndef Q_COMPILER_VARIADIC_TEMPLATES
+ template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1}; };
+ template<class Obj, typename Ret> struct FunctionPointer<Ret (Obj::*) ()>
+ {
+ typedef Obj Object;
+ typedef void Arguments;
+ typedef Ret ReturnType;
+ typedef Ret (Obj::*Function) ();
+ enum {ArgumentCount = 0};
+ template <typename Args, typename R>
+ static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue<R>(arg[0]); }
+ };
+ template<class Obj, typename Ret, typename Arg1> struct FunctionPointer<Ret (Obj::*) (Arg1)>
+ {
+ typedef Obj Object;
+ typedef List<Arg1, void> Arguments;
+ typedef Ret ReturnType;
+ typedef Ret (Obj::*Function) (Arg1);
+ enum {ArgumentCount = 1};
+ template <typename Args, typename R>
+ static void call(Function f, Obj *o, void **arg) {
+ (o->*f)((*reinterpret_cast<typename RemoveRef<typename Args::Car>::Type *>(arg[1]))), ApplyReturnValue<R>(arg[0]);
+ }
+ };
+ template<class Obj, typename Ret, typename Arg1, typename Arg2> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2)>
+ {
+ typedef Obj Object;
+ typedef List<Arg1, List<Arg2, void> > Arguments;
+ typedef Ret ReturnType;
+ typedef Ret (Obj::*Function) (Arg1, Arg2);
+ enum {ArgumentCount = 2};
+ template <typename Args, typename R>
+ static void call(Function f, Obj *o, void **arg) {
+ (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
+ *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]);
+ }
+ };
+ template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3)>
+ {
+ typedef Obj Object;
+ typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments;
+ typedef Ret ReturnType;
+ typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3);
+ enum {ArgumentCount = 3};
+ template <typename Args, typename R>
+ static void call(Function f, Obj *o, void **arg) {
+ (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
+ *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
+ *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]);
+ }
+ };
+
+ template<typename Ret> struct FunctionPointer<Ret (*) ()>
+ {
+ typedef void Arguments;
+ typedef Ret (*Function) ();
+ typedef Ret ReturnType;
+ enum {ArgumentCount = 0};
+ template <typename Args, typename R>
+ static void call(Function f, void *, void **arg) { f(), ApplyReturnValue<R>(arg[0]); }
+ };
+ template<typename Ret, typename Arg1> struct FunctionPointer<Ret (*) (Arg1)>
+ {
+ typedef List<Arg1, void> Arguments;
+ typedef Ret ReturnType;
+ typedef Ret (*Function) (Arg1);
+ enum {ArgumentCount = 1};
+ template <typename Args, typename R>
+ static void call(Function f, void *, void **arg)
+ { f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1])), ApplyReturnValue<R>(arg[0]); }
+ };
+ template<typename Ret, typename Arg1, typename Arg2> struct FunctionPointer<Ret (*) (Arg1, Arg2)>
+ {
+ typedef List<Arg1, List<Arg2, void> > Arguments;
+ typedef Ret ReturnType;
+ typedef Ret (*Function) (Arg1, Arg2);
+ enum {ArgumentCount = 2};
+ template <typename Args, typename R>
+ static void call(Function f, void *, void **arg) {
+ f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
+ *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]); }
+ };
+ template<typename Ret, typename Arg1, typename Arg2, typename Arg3> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3)>
+ {
+ typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments;
+ typedef Ret ReturnType;
+ typedef Ret (*Function) (Arg1, Arg2, Arg3);
+ enum {ArgumentCount = 3};
+ template <typename Args, typename R>
+ static void call(Function f, void *, void **arg) {
+ f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
+ *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
+ *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]);
+ }
+ };
+
+ template<typename F, int N> struct Functor;
+ template<typename Function> struct Functor<Function, 0>
+ {
+ template <typename Args, typename R>
+ static void call(Function &f, void *, void **arg) { f(), ApplyReturnValue<R>(arg[0]); }
+ };
+ template<typename Function> struct Functor<Function, 1>
+ {
+ template <typename Args, typename R>
+ static void call(Function &f, void *, void **arg) {
+ f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1])), ApplyReturnValue<R>(arg[0]);
+ }
+ };
+ template<typename Function> struct Functor<Function, 2>
+ {
+ template <typename Args, typename R>
+ static void call(Function &f, void *, void **arg) {
+ f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
+ *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]);
+ }
+ };
+ template<typename Function> struct Functor<Function, 3>
+ {
+ template <typename Args, typename R>
+ static void call(Function &f, void *, void **arg) {
+ f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
+ *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
+ *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]);
+ }
+ };
+#else
+ template <int...> struct IndexesList {};
+ template <typename IndexList, int Right> struct IndexesAppend;
+ template <int... Left, int Right> struct IndexesAppend<IndexesList<Left...>, Right>
+ { typedef IndexesList<Left..., Right> Value; };
+ template <int N> struct Indexes
+ { typedef typename IndexesAppend<typename Indexes<N - 1>::Value, N - 1>::Value Value; };
+ template <> struct Indexes<0> { typedef IndexesList<> Value; };
+ template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1}; };
+
+ template <typename, typename, typename, typename> struct FunctorCall;
+ template <int... I, typename... SignalArgs, typename R, typename Function>
+ struct FunctorCall<IndexesList<I...>, List<SignalArgs...>, R, Function> {
+ static void call(Function f, void **arg) {
+ f((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[I+1]))...), ApplyReturnValue<R>(arg[0]);
+ }
+ };
+ template <int... I, typename... SignalArgs, typename R, typename... SlotArgs, typename SlotRet, class Obj>
+ struct FunctorCall<IndexesList<I...>, List<SignalArgs...>, R, SlotRet (Obj::*)(SlotArgs...)> {
+ static void call(SlotRet (Obj::*f)(SlotArgs...), Obj *o, void **arg) {
+ (o->*f)((*reinterpret_cast<typename RemoveRef<SignalArgs>::Type *>(arg[I+1]))...), ApplyReturnValue<R>(arg[0]);
+ }
+ };
+
+ template<class Obj, typename Ret, typename... Args> struct FunctionPointer<Ret (Obj::*) (Args...)>
+ {
+ typedef Obj Object;
+ typedef List<Args...> Arguments;
+ typedef Ret ReturnType;
+ typedef Ret (Obj::*Function) (Args...);
+ enum {ArgumentCount = sizeof...(Args)};
+ template <typename SignalArgs, typename R>
+ static void call(Function f, Obj *o, void **arg) {
+ FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, o, arg);
+ }
+ };
+
+ template<typename Ret, typename... Args> struct FunctionPointer<Ret (*) (Args...)>
+ {
+ typedef List<Args...> Arguments;
+ typedef Ret ReturnType;
+ typedef Ret (*Function) (Args...);
+ enum {ArgumentCount = sizeof...(Args)};
+ template <typename SignalArgs, typename R>
+ static void call(Function f, void *, void **arg) {
+ FunctorCall<typename Indexes<ArgumentCount>::Value, SignalArgs, R, Function>::call(f, arg);
+ }
+ };
+
+ template<typename Function, int N> struct Functor
+ {
+ template <typename SignalArgs, typename R>
+ static void call(Function &f, void *, void **arg) {
+ FunctorCall<typename Indexes<N>::Value, SignalArgs, R, Function>::call(f, arg);
+ }
+ };
+#endif
+
+ /*
+ Logic that check if the arguments of the slot matches the argument of the signal.
+ To be used like this:
+ CheckCompatibleArguments<FunctionPointer<Signal>::Arguments, FunctionPointer<Slot>::Arguments>::IncompatibleSignalSlotArguments
+ The IncompatibleSignalSlotArguments type do not exist if the argument are incompatible and can
+ then produce error message.
+ */
+ template<typename T, bool B> struct CheckCompatibleArgumentsHelper {};
+ template<typename T> struct CheckCompatibleArgumentsHelper<T, true> : T {};
+ template<typename A1, typename A2> struct AreArgumentsCompatible {
+ static int test(A2);
+ static char test(...);
+ static A2 dummy();
+ enum { value = sizeof(test(dummy())) == sizeof(int) };
+ };
+ template<typename A1, typename A2> struct AreArgumentsCompatible<A1, A2&> { enum { value = false }; };
+ template<typename A> struct AreArgumentsCompatible<A&, A&> { enum { value = true }; };
+
+#ifndef Q_COMPILER_VARIADIC_TEMPLATES
+ template <typename List1, typename List2> struct CheckCompatibleArguments{};
+ template <> struct CheckCompatibleArguments<void, void> { typedef bool IncompatibleSignalSlotArguments; };
+ template <typename List1> struct CheckCompatibleArguments<List1, void> { typedef bool IncompatibleSignalSlotArguments; };
+ template <typename Arg1, typename Arg2, typename Tail1, typename Tail2> struct CheckCompatibleArguments<List<Arg1, Tail1>, List<Arg2, Tail2> >
+ : CheckCompatibleArgumentsHelper<CheckCompatibleArguments<Tail1, Tail2>, AreArgumentsCompatible<
+ typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value > {};
+#else
+ template <typename List1, typename List2> struct CheckCompatibleArguments{};
+ template <> struct CheckCompatibleArguments<List<>, List<>> { typedef bool IncompatibleSignalSlotArguments; };
+ template <typename List1> struct CheckCompatibleArguments<List1, List<>> { typedef bool IncompatibleSignalSlotArguments; };
+ template <typename Arg1, typename Arg2, typename... Tail1, typename... Tail2>
+ struct CheckCompatibleArguments<List<Arg1, Tail1...>, List<Arg2, Tail2...>>
+ : CheckCompatibleArgumentsHelper<CheckCompatibleArguments<List<Tail1...>, List<Tail2...>>, AreArgumentsCompatible<
+ typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value > {};
+
+#endif
+
+}
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 2a9334ae8f..72cf5a8cca 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -114,18 +114,23 @@ public:
{
QObject *sender;
QObject *receiver;
- StaticMetaCallFunction callFunction;
+ union {
+ StaticMetaCallFunction callFunction;
+ QObject::QSlotObjectBase *slotObj;
+ };
// The next pointer for the singly-linked ConnectionList
Connection *nextConnectionList;
//senders linked list
Connection *next;
Connection **prev;
- QAtomicPointer<int> argumentTypes;
+ QAtomicPointer<const int> argumentTypes;
QAtomicInt ref_;
ushort method_offset;
ushort method_relative;
ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
- Connection() : nextConnectionList(0), ref_(2) {
+ ushort isSlotObject : 1;
+ ushort ownArgumentTypes : 1;
+ Connection() : nextConnectionList(0), ref_(2), ownArgumentTypes(true) {
//ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection
}
~Connection();
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 1ad24387e0..ce5a924e23 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -66,10 +66,10 @@ class QString;
# define QT_NO_EMIT
# else
# define slots
-# define signals protected
+# define signals public
# endif
# define Q_SLOTS
-# define Q_SIGNALS protected
+# define Q_SIGNALS public
# define Q_PRIVATE_SLOT(d, signature)
# define Q_EMIT
#ifndef QT_NO_EMIT