summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qobject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qobject.cpp')
-rw-r--r--src/corelib/kernel/qobject.cpp329
1 files changed, 226 insertions, 103 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index fb3e4e396b..49a9beb298 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -184,6 +184,7 @@ void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject
void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0;
void (*QAbstractDeclarativeData::objectNameChanged)(QAbstractDeclarativeData *, QObject *) = 0;
void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = 0;
+int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = 0;
QObjectData::~QObjectData() {}
@@ -568,9 +569,9 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
\l uic generates code that invokes this function to enable
auto-connection to be performed between widgets on forms created
- with \QD. More information about using auto-connection with \QD is
+ with \e{Qt Designer}. More information about using auto-connection with \e{Qt Designer} is
given in the \l{Using a Designer UI File in Your Application} section of
- the \QD manual.
+ the \e{Qt Designer} manual.
\section1 Dynamic Properties
@@ -606,7 +607,7 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
Returns 0 if there is no such child.
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 0
+ \snippet code/src_corelib_kernel_qobject.cpp 0
*/
void *qt_find_obj_child(QObject *parent, const char *type, const QString &name)
@@ -651,8 +652,8 @@ static bool check_parent_thread(QObject *parent,
Constructs an object with parent object \a parent.
The parent of an object may be viewed as the object's owner. For
- instance, a \l{QDialog}{dialog box} is the parent of the \gui OK
- and \gui Cancel buttons it contains.
+ instance, a \l{QDialog}{dialog box} is the parent of the \uicontrol{OK}
+ and \uicontrol{Cancel} buttons it contains.
The destructor of a parent object destroys all child objects.
@@ -881,7 +882,7 @@ QObjectPrivate::Connection::~Connection()
Example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 1
+ \snippet code/src_corelib_kernel_qobject.cpp 1
\sa staticMetaObject
*/
@@ -905,7 +906,7 @@ QObjectPrivate::Connection::~Connection()
Example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 2
+ \snippet code/src_corelib_kernel_qobject.cpp 2
\sa metaObject()
*/
@@ -924,7 +925,7 @@ QObjectPrivate::Connection::~Connection()
Example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 3
+ \snippet code/src_corelib_kernel_qobject.cpp 3
The qobject_cast() function behaves similarly to the standard C++
\c dynamic_cast(), with the advantages that it doesn't require
@@ -950,7 +951,7 @@ QObjectPrivate::Connection::~Connection()
Example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 4
+ \snippet code/src_corelib_kernel_qobject.cpp 4
If you need to determine whether an object is an instance of a particular
class for the purpose of casting it, consider using qobject_cast<Type *>(object)
@@ -967,7 +968,7 @@ QObjectPrivate::Connection::~Connection()
You can find an object by name (and type) using findChild().
You can find a set of objects with findChildren().
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 5
+ \snippet code/src_corelib_kernel_qobject.cpp 5
By default, this property contains an empty string.
@@ -988,7 +989,7 @@ void QObject::setObjectName(const QString &name)
Q_D(QObject);
if (d->objectName != name) {
d->objectName = name;
- if (d->declarativeData)
+ if (d->declarativeData && d->declarativeData->objectNameChanged)
d->declarativeData->objectNameChanged(d->declarativeData, this);
emit objectNameChanged(d->objectName);
}
@@ -1155,7 +1156,7 @@ void QObject::customEvent(QEvent * /* event */)
true; otherwise return false.
Example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 6
+ \snippet code/src_corelib_kernel_qobject.cpp 6
Notice in the example above that unhandled events are passed to
the base class's eventFilter() function, since the base class
@@ -1225,7 +1226,7 @@ QThread *QObject::thread() const
QApplication::thread() to retrieve the thread in which the
application lives. For example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 7
+ \snippet code/src_corelib_kernel_qobject.cpp 7
If \a targetThread is zero, all event processing for this object
and its children stops.
@@ -1390,7 +1391,7 @@ void QObjectPrivate::_q_reregisterTimers(void *pointer)
Example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 8
+ \snippet code/src_corelib_kernel_qobject.cpp 8
Note that QTimer's accuracy depends on the underlying operating system and
hardware. The \a timerType argument allows you to customize the accuracy of
@@ -1472,7 +1473,7 @@ void QObject::killTimer(int id)
The QObjectList class is defined in the \c{<QObject>} header
file as the following:
- \quotefromfile src/corelib/kernel/qobject.h
+ \quotefromfile kernel/qobject.h
\skipto /typedef .*QObjectList/
\printuntil QObjectList
@@ -1507,21 +1508,21 @@ void QObject::killTimer(int id)
named \c{"button1"}, even if the button isn't a direct child of
the parent:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 10
+ \snippet code/src_corelib_kernel_qobject.cpp 10
This example returns a \l{QListWidget} child of \c{parentWidget}:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 11
+ \snippet code/src_corelib_kernel_qobject.cpp 11
This example returns a child \l{QPushButton} of \c{parentWidget}
(its direct parent) named \c{"button1"}:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 41
+ \snippet code/src_corelib_kernel_qobject.cpp 41
This example returns a \l{QListWidget} child of \c{parentWidget},
its direct parent:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 42
+ \snippet code/src_corelib_kernel_qobject.cpp 42
\sa findChildren()
*/
@@ -1538,15 +1539,15 @@ void QObject::killTimer(int id)
The following example shows how to find a list of child \l{QWidget}s of
the specified \c{parentWidget} named \c{widgetname}:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 12
+ \snippet code/src_corelib_kernel_qobject.cpp 12
This example returns all \c{QPushButton}s that are children of \c{parentWidget}:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 13
+ \snippet code/src_corelib_kernel_qobject.cpp 13
This example returns all \c{QPushButton}s that are immediate children of \c{parentWidget}:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 43
+ \snippet code/src_corelib_kernel_qobject.cpp 43
\sa findChild()
*/
@@ -1653,10 +1654,11 @@ void qt_qFindChildren_helper(const QObject *parent, const QRegExp &re,
if (!parent || !list)
return;
const QObjectList &children = parent->children();
+ QRegExp reCopy = re;
QObject *obj;
for (int i = 0; i < children.size(); ++i) {
obj = children.at(i);
- if (mo.cast(obj) && re.indexIn(obj->objectName()) != -1)
+ if (mo.cast(obj) && reCopy.indexIn(obj->objectName()) != -1)
list->append(obj);
if (options & Qt::FindChildrenRecursively)
@@ -1791,7 +1793,7 @@ void QObjectPrivate::setParent_helper(QObject *o)
\fn void QObject::installEventFilter(QObject *filterObj)
Installs an event filter \a filterObj on this object. For example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 14
+ \snippet code/src_corelib_kernel_qobject.cpp 14
An event filter is an object that receives all events that are
sent to this object. The filter can either stop the event or
@@ -1806,11 +1808,11 @@ void QObjectPrivate::setParent_helper(QObject *o)
Here's a \c KeyPressEater class that eats the key presses of its
monitored objects:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 15
+ \snippet code/src_corelib_kernel_qobject.cpp 15
And here's how to install it on two widgets:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 16
+ \snippet code/src_corelib_kernel_qobject.cpp 16
The QShortcut class, for example, uses this technique to intercept
shortcut key presses.
@@ -1925,7 +1927,7 @@ void QObject::deleteLater()
Example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 17
+ \snippet code/src_corelib_kernel_qobject.cpp 17
\dots
See \l{Writing Source Code for Translation} for a detailed description of
@@ -1959,7 +1961,7 @@ void QObject::deleteLater()
escape sequences for specifying non-ASCII characters in string
literals to trUtf8(). For example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 20
+ \snippet code/src_corelib_kernel_qobject.cpp 20
\sa tr(), QApplication::translate(), {Internationalization with Qt}
*/
@@ -2153,15 +2155,14 @@ int QObject::senderSignalIndex() const
When calling this function, you can use the \c SIGNAL() macro to
pass a specific signal:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 21
-
- As the code snippet above illustrates, you can use this function
- to avoid emitting a signal that nobody listens to.
+ \snippet code/src_corelib_kernel_qobject.cpp 21
\warning This function violates the object-oriented principle of
modularity. However, it might be useful when you need to perform
expensive initialization only if something is connected to a
signal.
+
+ \sa isSignalConnected()
*/
int QObject::receivers(const char *signal) const
@@ -2181,10 +2182,17 @@ int QObject::receivers(const char *signal) const
#ifndef QT_NO_DEBUG
err_method_notfound(this, signal-1, "receivers");
#endif
- return false;
+ return 0;
}
- Q_D(const QObject);
+ if (d->declarativeData && QAbstractDeclarativeData::receivers) {
+ receivers += QAbstractDeclarativeData::receivers(d->declarativeData, this,
+ metaObject()->indexOfMethod(signal));
+ }
+
+ if (!d->isSignalConnected(signal_index))
+ return receivers;
+
QMutexLocker locker(signalSlotLock(this));
if (d->connectionLists) {
if (signal_index < d->connectionLists->count()) {
@@ -2201,6 +2209,60 @@ int QObject::receivers(const char *signal) const
}
/*!
+ \since 5.0
+ Returns true if the \a signal is connected to at least one receiver,
+ otherwise returns false.
+
+ \a signal must be a signal member of this object, otherwise the behaviour
+ is undefined.
+
+ \snippet code/src_corelib_kernel_qobject.cpp 21
+
+ As the code snippet above illustrates, you can use this function
+ to avoid emitting a signal that nobody listens to.
+
+ \warning This function violates the object-oriented principle of
+ modularity. However, it might be useful when you need to perform
+ expensive initialization only if something is connected to a
+ signal.
+*/
+bool QObject::isSignalConnected(const QMetaMethod &signal) const
+{
+ Q_D(const QObject);
+ if (!signal.mobj)
+ return false;
+
+ Q_ASSERT_X(signal.mobj->cast(this) && signal.methodType() == QMetaMethod::Signal,
+ "QObject::isSignalConnected" , "the parametter must be a signal member of the object");
+ uint signalIndex = (signal.handle - QMetaObjectPrivate::get(signal.mobj)->methodData)/5;
+
+ if (signal.mobj->d.data[signal.handle + 4] & MethodCloned)
+ signalIndex = QMetaObjectPrivate::originalClone(signal.mobj, signalIndex);
+
+ int signalOffset;
+ int methodOffset;
+ computeOffsets(signal.mobj, &signalOffset, &methodOffset);
+ signalIndex += signalOffset;
+
+ if (signalIndex < sizeof(d->connectedSignals) * 8)
+ return d->isSignalConnected(signalIndex);
+
+ QMutexLocker locker(signalSlotLock(this));
+ if (d->connectionLists) {
+ if (signalIndex < uint(d->connectionLists->count())) {
+ const QObjectPrivate::Connection *c =
+ d->connectionLists->at(signalIndex).first;
+ while (c) {
+ if (c->receiver)
+ return true;
+ c = c->nextConnectionList;
+ }
+ }
+ }
+ return false;
+}
+
+/*!
\internal
This helper function calculates signal and method index for the given
@@ -2278,18 +2340,18 @@ static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaM
You must use the \c SIGNAL() and \c SLOT() macros when specifying
the \a signal and the \a method, for example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 22
+ \snippet code/src_corelib_kernel_qobject.cpp 22
This example ensures that the label always displays the current
scroll bar value. Note that the signal and slots parameters must not
contain any variable names, only the type. E.g. the following would
not work and return false:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 23
+ \snippet code/src_corelib_kernel_qobject.cpp 23
A signal can also be connected to another signal:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 24
+ \snippet code/src_corelib_kernel_qobject.cpp 24
In this example, the \c MyWidget constructor relays a signal from
a private member variable, and makes it available under a name
@@ -2326,7 +2388,7 @@ static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaM
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
+ \snippet code/src_corelib_kernel_qobject.cpp 25
call qRegisterMetaType() to register the data type before you
establish the connection.
@@ -2376,7 +2438,6 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
int signalOffset, methodOffset;
computeOffsets(smeta, &signalOffset, &methodOffset);
- int signal_absolute_index = signal_index + methodOffset;
signal_index += signalOffset;
QByteArray tmp_method_name;
@@ -2445,12 +2506,12 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const char *sign
}
#ifndef QT_NO_DEBUG
- QMetaMethod smethod = smeta->method(signal_absolute_index);
+ QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
QMetaMethod rmethod = rmeta->method(method_index_relative + rmeta->methodOffset());
check_and_warn_compat(smeta, smethod, rmeta, rmethod);
#endif
QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
- sender, signal_index, receiver, method_index_relative, rmeta ,type, types));
+ sender, signal_index, smeta, receiver, method_index_relative, rmeta ,type, types));
if (handle)
const_cast<QObject*>(sender)->connectNotify(signal - 1);
return handle;
@@ -2538,7 +2599,7 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho
check_and_warn_compat(smeta, signal, rmeta, method);
#endif
QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
- sender, signal_index, receiver, method_index, 0, type, types));
+ sender, signal_index, signal.enclosingMetaObject(), receiver, method_index, 0, type, types));
if (handle)
const_cast<QObject*>(sender)->connectNotify(signalSignature.constData());
return handle;
@@ -2575,27 +2636,27 @@ QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMetho
\list 1
\li Disconnect everything connected to an object's signals:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 26
+ \snippet code/src_corelib_kernel_qobject.cpp 26
equivalent to the non-static overloaded function
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 27
+ \snippet code/src_corelib_kernel_qobject.cpp 27
\li Disconnect everything connected to a specific signal:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 28
+ \snippet code/src_corelib_kernel_qobject.cpp 28
equivalent to the non-static overloaded function
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 29
+ \snippet code/src_corelib_kernel_qobject.cpp 29
\li Disconnect a specific receiver:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 30
+ \snippet code/src_corelib_kernel_qobject.cpp 30
equivalent to the non-static overloaded function
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 31
+ \snippet code/src_corelib_kernel_qobject.cpp 31
\endlist
@@ -2697,7 +2758,7 @@ bool QObject::disconnect(const QObject *sender, const char *signal,
}
if (!method) {
- res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, -1, 0);
+ res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, -1, 0);
} else {
const QMetaObject *rmeta = receiver->metaObject();
do {
@@ -2708,7 +2769,7 @@ bool QObject::disconnect(const QObject *sender, const char *signal,
rmeta = rmeta->superClass();
if (method_index < 0)
break;
- res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index, 0);
+ res |= QMetaObjectPrivate::disconnect(sender, signal_index, smeta, receiver, method_index, 0);
method_found = true;
} while ((rmeta = rmeta->superClass()));
}
@@ -2721,8 +2782,11 @@ bool QObject::disconnect(const QObject *sender, const char *signal,
err_method_notfound(receiver, method_arg, "disconnect");
err_info_about_objects("disconnect", sender, receiver);
}
- if (res)
+ if (res) {
+ if (!signal)
+ const_cast<QObject*>(sender)->disconnectNotify(QMetaMethod());
const_cast<QObject*>(sender)->disconnectNotify(signal ? (signal - 1) : 0);
+ }
return res;
}
@@ -2807,9 +2871,16 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
return false;
}
- if (!QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index, 0))
+ if (!QMetaObjectPrivate::disconnect(sender, signal_index, signal.mobj, receiver, method_index, 0))
return false;
+ if (!signal.isValid()) {
+ // The signal is a wildcard, meaning all signals were disconnected.
+ // QMetaObjectPrivate::disconnect() doesn't call disconnectNotify()
+ // per connection in this case. Call it once now, with an invalid
+ // QMetaMethod as argument, as documented.
+ const_cast<QObject*>(sender)->disconnectNotify(signal);
+ }
const_cast<QObject*>(sender)->disconnectNotify(method.mobj ? signalSignature.constData() : 0);
return true;
}
@@ -2840,18 +2911,30 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
/*!
\fn void QObject::connectNotify(const char *signal)
+ \obsolete
+*/
+void QObject::connectNotify(const char *)
+{
+}
+
+/*!
+ \fn void QObject::disconnectNotify(const char *signal)
+ \obsolete
+*/
+void QObject::disconnectNotify(const char *)
+{
+}
+
+/*!
+ \since 5.0
This virtual function is called when something has been connected
to \a signal in this object.
- If you want to compare \a signal with a specific signal, use
- QLatin1String and the \c SIGNAL() macro as follows:
-
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 32
+ If you want to compare \a signal with a specific signal, you can
+ use QMetaMethod::fromSignal() as follows:
- If the signal contains multiple parameters or parameters that
- contain spaces, call QMetaObject::normalizedSignature() on
- the result of the \c SIGNAL() macro.
+ \snippet code/src_corelib_kernel_qobject.cpp 32
\warning This function violates the object-oriented principle of
modularity. However, it might be useful when you need to perform
@@ -2861,12 +2944,13 @@ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
\sa connect(), disconnectNotify()
*/
-void QObject::connectNotify(const char *)
+void QObject::connectNotify(const QMetaMethod &signal)
{
+ Q_UNUSED(signal);
}
/*!
- \fn void QObject::disconnectNotify(const char *signal)
+ \since 5.0
This virtual function is called when something has been
disconnected from \a signal in this object.
@@ -2874,6 +2958,11 @@ void QObject::connectNotify(const char *)
See connectNotify() for an example of how to compare
\a signal with a specific signal.
+ If all signals were disconnected from this object (e.g., the
+ signal argument to disconnect() was 0), disconnectNotify()
+ is only called once, and the \a signal will be an invalid
+ QMetaMethod (QMetaMethod::isValid() returns false).
+
\warning This function violates the object-oriented principle of
modularity. However, it might be useful for optimizing access to
expensive resources.
@@ -2881,17 +2970,19 @@ void QObject::connectNotify(const char *)
\sa disconnect(), connectNotify()
*/
-void QObject::disconnectNotify(const char *)
+void QObject::disconnectNotify(const QMetaMethod &signal)
{
+ Q_UNUSED(signal);
}
/* \internal
convert a signal index from the method range to the signal range
*/
-static int methodIndexToSignalIndex(const QMetaObject *metaObject, int signal_index)
+static int methodIndexToSignalIndex(const QMetaObject **base, int signal_index)
{
if (signal_index < 0)
return signal_index;
+ const QMetaObject *metaObject = *base;
while (metaObject && metaObject->methodOffset() > signal_index)
metaObject = metaObject->superClass();
@@ -2902,6 +2993,7 @@ static int methodIndexToSignalIndex(const QMetaObject *metaObject, int signal_in
signal_index = QMetaObjectPrivate::originalClone(metaObject, signal_index - methodOffset) + signalOffset;
else
signal_index = signal_index - methodOffset + signalOffset;
+ *base = metaObject;
}
return signal_index;
}
@@ -2916,8 +3008,9 @@ static int methodIndexToSignalIndex(const QMetaObject *metaObject, int signal_in
QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index, int type, int *types)
{
- signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
- return Connection(QMetaObjectPrivate::connect(sender, signal_index,
+ const QMetaObject *smeta = sender->metaObject();
+ signal_index = methodIndexToSignalIndex(&smeta, signal_index);
+ return Connection(QMetaObjectPrivate::connect(sender, signal_index, smeta,
receiver, method_index,
0, //FIXME, we could speed this connection up by computing the relative index
type, types));
@@ -2930,7 +3023,8 @@ QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_i
the QObjectPrivate::Connection* has a refcount of 2, so it must be passed to a QMetaObject::Connection
*/
-QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
+QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender,
+ int signal_index, const QMetaObject *smeta,
const QObject *receiver, int method_index,
const QMetaObject *rmeta, int type, int *types)
{
@@ -2940,8 +3034,7 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, i
int method_offset = rmeta ? rmeta->methodOffset() : 0;
Q_ASSERT(!rmeta || QMetaObjectPrivate::get(rmeta)->revision >= 6);
QObjectPrivate::StaticMetaCallFunction callFunction =
- (rmeta && rmeta->d.extradata)
- ? reinterpret_cast<const QMetaObjectExtraData *>(rmeta->d.extradata)->static_metacall : 0;
+ rmeta ? rmeta->d.static_metacall : 0;
QOrderedMutexLocker locker(signalSlotLock(sender),
signalSlotLock(receiver));
@@ -2975,6 +3068,12 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, i
c->callFunction = callFunction;
QObjectPrivate::get(s)->addConnection(signal_index, c.data());
+
+ locker.unlock();
+ QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
+ if (smethod.isValid())
+ s->connectNotify(smethod);
+
return c.take();
}
@@ -2983,8 +3082,9 @@ QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, i
bool QMetaObject::disconnect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index)
{
- signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
- return QMetaObjectPrivate::disconnect(sender, signal_index,
+ const QMetaObject *smeta = sender->metaObject();
+ signal_index = methodIndexToSignalIndex(&smeta, signal_index);
+ return QMetaObjectPrivate::disconnect(sender, signal_index, smeta,
receiver, method_index, 0);
}
@@ -2997,8 +3097,9 @@ one of these connections will be removed.
bool QMetaObject::disconnectOne(const QObject *sender, int signal_index,
const QObject *receiver, int method_index)
{
- signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
- return QMetaObjectPrivate::disconnect(sender, signal_index,
+ const QMetaObject *smeta = sender->metaObject();
+ signal_index = methodIndexToSignalIndex(&smeta, signal_index);
+ return QMetaObjectPrivate::disconnect(sender, signal_index, smeta,
receiver, method_index, 0,
QMetaObjectPrivate::DisconnectOne);
}
@@ -3047,7 +3148,8 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c,
/*! \internal
Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex
*/
-bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index,
+bool QMetaObjectPrivate::disconnect(const QObject *sender,
+ int signal_index, const QMetaObject *smeta,
const QObject *receiver, int method_index, void **slot,
DisconnectType disconnectType)
{
@@ -3070,9 +3172,9 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index,
bool success = false;
if (signal_index < 0) {
// remove from all connection lists
- for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) {
+ for (int sig_index = -1; sig_index < connectionLists->count(); ++sig_index) {
QObjectPrivate::Connection *c =
- (*connectionLists)[signal_index].first;
+ (*connectionLists)[sig_index].first;
if (disconnectHelper(c, receiver, method_index, slot, senderMutex, disconnectType)) {
success = true;
connectionLists->dirty = true;
@@ -3092,6 +3194,13 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index,
if (connectionLists->orphaned && !connectionLists->inUse)
delete connectionLists;
+ locker.unlock();
+ if (success) {
+ QMetaMethod smethod = QMetaObjectPrivate::signal(smeta, signal_index);
+ if (smethod.isValid())
+ s->disconnectNotify(smethod);
+ }
+
return success;
}
@@ -3101,13 +3210,13 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index,
Searches recursively for all child objects of the given \a object, and connects
matching signals from them to slots of \a object that follow the following form:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 33
+ \snippet code/src_corelib_kernel_qobject.cpp 33
Let's assume our object has a child object of type QPushButton with
the \l{QObject::objectName}{object name} \c{button1}. The slot to catch the
button's \c{clicked()} signal would be:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 34
+ \snippet code/src_corelib_kernel_qobject.cpp 34
\sa QObject::setObjectName()
*/
@@ -3131,7 +3240,8 @@ void QMetaObject::connectSlotsByName(QObject *o)
int len = objName.length();
if (!len || qstrncmp(slot + 3, objName.data(), len) || slot[len+3] != '_')
continue;
- int sigIndex = co->d_func()->signalIndex(slot + len + 4);
+ const QMetaObject *smeta;
+ int sigIndex = co->d_func()->signalIndex(slot + len + 4, &smeta);
if (sigIndex < 0) { // search for compatible signals
const QMetaObject *smo = co->metaObject();
int slotlen = qstrlen(slot + len + 4) - 1;
@@ -3141,8 +3251,9 @@ void QMetaObject::connectSlotsByName(QObject *o)
continue;
if (!qstrncmp(method.methodSignature().constData(), slot + len + 4, slotlen)) {
+ smeta = method.enclosingMetaObject();
int signalOffset, methodOffset;
- computeOffsets(method.enclosingMetaObject(), &signalOffset, &methodOffset);
+ computeOffsets(smeta, &signalOffset, &methodOffset);
sigIndex = k + - methodOffset + signalOffset;
break;
}
@@ -3150,7 +3261,8 @@ void QMetaObject::connectSlotsByName(QObject *o)
}
if (sigIndex < 0)
continue;
- if (Connection(QMetaObjectPrivate::connect(co, sigIndex, o, i))) {
+
+ if (Connection(QMetaObjectPrivate::connect(co, sigIndex, smeta, o, i))) {
foundIt = true;
break;
}
@@ -3381,8 +3493,11 @@ void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod
while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots.
+
+ If \a meta is not 0, it is set to the meta-object where the signal was found.
*/
-int QObjectPrivate::signalIndex(const char *signalName) const
+int QObjectPrivate::signalIndex(const char *signalName,
+ const QMetaObject **meta) const
{
Q_Q(const QObject);
const QMetaObject *base = q->metaObject();
@@ -3396,6 +3511,8 @@ int QObjectPrivate::signalIndex(const char *signalName) const
relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
int signalOffset, methodOffset;
computeOffsets(base, &signalOffset, &methodOffset);
+ if (meta)
+ *meta = base;
return relative_index + signalOffset;
}
@@ -3722,7 +3839,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) {
Example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 35
+ \snippet code/src_corelib_kernel_qobject.cpp 35
\sa QMetaObject::classInfo()
*/
@@ -3736,9 +3853,9 @@ QDebug operator<<(QDebug dbg, const QObject *o) {
Example:
- \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.h 1
+ \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.h 1
\dots
- \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.h 3
+ \snippet tools/plugandpaintplugins/basictools/basictoolsplugin.h 3
See the \l{tools/plugandpaintplugins/basictools}{Plug & Paint
Basic Tools} example for details.
@@ -3755,7 +3872,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) {
they have additional features accessible through the \l
{Meta-Object System}.
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 36
+ \snippet code/src_corelib_kernel_qobject.cpp 36
The property name and type and the \c READ function are required.
The type can be any type supported by QVariant, or it can be a
@@ -3765,7 +3882,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) {
For example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 37
+ \snippet code/src_corelib_kernel_qobject.cpp 37
For more details about how to use this macro, and a more detailed
example of its use, see the discussion on \l {Qt's Property System}.
@@ -3782,7 +3899,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) {
For example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 38
+ \snippet code/src_corelib_kernel_qobject.cpp 38
If you want to register an enum that is declared in another class,
the enum must be fully qualified with the name of the class
@@ -3804,12 +3921,12 @@ QDebug operator<<(QDebug dbg, const QObject *o) {
For example, in QLibrary, the \l{QLibrary::LoadHints}{LoadHints} flag is
declared in the following way:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 39a
+ \snippet code/src_corelib_kernel_qobject.cpp 39a
The declaration of the flags themselves is performed in the public section
of the QLibrary class itself, using the \l Q_DECLARE_FLAGS() macro:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 39b
+ \snippet code/src_corelib_kernel_qobject.cpp 39b
\note This macro takes care of registering individual flag values
with the meta-object system, so it is unnecessary to use Q_ENUMS()
@@ -3828,10 +3945,10 @@ QDebug operator<<(QDebug dbg, const QObject *o) {
For example:
- \snippet doc/src/snippets/signalsandslots/signalsandslots.h 1
+ \snippet signalsandslots/signalsandslots.h 1
\codeline
- \snippet doc/src/snippets/signalsandslots/signalsandslots.h 2
- \snippet doc/src/snippets/signalsandslots/signalsandslots.h 3
+ \snippet signalsandslots/signalsandslots.h 2
+ \snippet signalsandslots/signalsandslots.h 3
\note This macro requires the class to be a subclass of QObject. Use
Q_GADGET instead of Q_OBJECT to enable the meta object system's support
@@ -3927,7 +4044,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) {
be invoked via the meta-object system. The macro is written before
the return type, as shown in the following example:
- \snippet snippets/qmetaobject-invokable/window.h Window class with invokable method
+ \snippet qmetaobject-invokable/window.h Window class with invokable method
The \c invokableMethod() function is marked up using Q_INVOKABLE, causing
it to be registered with the meta-object system and enabling it to be
@@ -3968,7 +4085,7 @@ void qDeleteInEventHandler(QObject *o)
Example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 44
+ \snippet code/src_corelib_kernel_qobject.cpp 44
This example ensures that the label always displays the current
line edit text.
@@ -4003,7 +4120,7 @@ void qDeleteInEventHandler(QObject *o)
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
+ \snippet code/src_corelib_kernel_qobject.cpp 25
make sure to declare the argument type with Q_DECLARE_METATYPE
*/
@@ -4029,11 +4146,11 @@ void qDeleteInEventHandler(QObject *o)
Example:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 45
+ \snippet 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
+ \snippet code/src_corelib_kernel_qobject.cpp 46
The connection will automatically disconnect if the sender is destroyed.
*/
@@ -4120,9 +4237,13 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
QMetaObject::Connection ret(c.take());
locker.unlock();
+ QMetaMethod method = QMetaObjectPrivate::signal(senderMetaObject, signal_index);
+ Q_ASSERT(method.isValid());
+ s->connectNotify(method);
+
// reconstruct the signature to call connectNotify
const char *sig;
- QByteArray tmp_sig = senderMetaObject->method(signal_index - signalOffset + methodOffset).methodSignature();
+ QByteArray tmp_sig = method.methodSignature();
sig = tmp_sig.constData();
QVarLengthArray<char> signalSignature(qstrlen(sig) + 2);
signalSignature.data()[0] = char(QSIGNAL_CODE + '0');
@@ -4159,6 +4280,8 @@ bool QObject::disconnect(const QMetaObject::Connection &connection)
if (c->next)
c->next->prev = c->prev;
c->receiver = 0;
+ // disconnectNotify() not called (the signal index is unknown).
+
return true;
}
@@ -4178,19 +4301,19 @@ bool QObject::disconnect(const QMetaObject::Connection &connection)
\list 1
\li Disconnect everything connected to an object's signals:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 26
+ \snippet code/src_corelib_kernel_qobject.cpp 26
\li Disconnect everything connected to a specific signal:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 47
+ \snippet code/src_corelib_kernel_qobject.cpp 47
\li Disconnect a specific receiver:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 30
+ \snippet code/src_corelib_kernel_qobject.cpp 30
\li Disconnect a connection from one specific signal to a specific slot:
- \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 48
+ \snippet code/src_corelib_kernel_qobject.cpp 48
\endlist
@@ -4242,7 +4365,7 @@ bool QObject::disconnectImpl(const QObject *sender, void **signal, const QObject
signal_index += signalOffset;
}
- return QMetaObjectPrivate::disconnect(sender, signal_index, receiver, -1, slot);
+ return QMetaObjectPrivate::disconnect(sender, signal_index, senderMetaObject, receiver, -1, slot);
}
/*! \class QMetaObject::Connection