[Development] Qt5 API change coming up: QObject::connectNotify(const char *) --> connectNotify(QMetaMethod)
kent.hansen at nokia.com
Mon Apr 30 14:14:00 CEST 2012
Quick links: https://bugreports.qt-project.org/browse/QTBUG-25541 and
(TL;DR; skip down to "IMPACT ON EXISTING connectNotify() REIMPLEMENTATIONS")
Yes, it's late, but it's also one of the final nails in the const char
*-based Q(Meta)Object introspection API coffin.
We've had a nice template-based connect() in Qt for some time already.
But the old connectNotify() hook was biased towards the original
string-based connect(). To get connectNotify() to be called as expected
by client code, the template-based connect() had to reconstruct the
signal signature string (and prepend the darn QSIGNAL_CODE+'0'
character). In Qt5, this is an even costlier operation, since the method
signature is no longer stored verbatim in the QMetaObject data; it must
be dynamically constructed from the name and parameter type information.
Constructing a QMetaMethod, however, is very cheap; it's just a wrapper
around a QMetaObject* and an index (which the QObject implementation has
readily available when making/breaking connections). Once you have the
QMetaMethod, you can also query all aspects of the method (such as the
name, and parameter count), including its full signature
The other (public) shortcoming of the const char *-based connectNotify()
is that if you were comparing the signal string to something else, you
had to ensure that that "something else" was fully normalized. Otherwise
the string comparison would fail (due to an extra space character, for
example). In Qt5, there is an operator== for QMetaMethods, and there is
the new QMetaMethod::fromSignal() function to get a QMetaMethod that
corresponds to a C++ signal function. So you can easily compare methods
without resorting to fragile, raw string comparisons.
This is why we're migrating away from the const char *-based API (yes,
I'm also looking at you, QObject::receivers(const char *) ;-) ).
IMPACT ON EXISTING connectNotify() REIMPLEMENTATIONS
Existing reimplementations must be ported over to the new API in order
to build with Qt5. I'm preparing patches for the places in Qt that I'm
aware of. For a basic example, you can have a look at the QBuffer patch:
For modules like qtsystems, which has dozens of connectNotify()
reimplementations and performs signal proxying, it's more involved (WIP
qtsystems patch: https://codereview.qt-project.org/#change,24817).
However, we are keeping support for the old API for some time (obviously
it will have to be removed before Qt5.0 final), to allow places outside
of qtbase to be ported incrementally.
If there are places outside of the qt5 modules that need to be ported, I
can help you with that.
IN RELATED NEWS...
In addition to the API change itself: We now call (dis)connectNotify()
directly from the internal index-based
QMetaObjectPrivate::(dis)connect() function. The nice thing about this
is that connectNotify() reimplementations are called consistently "out
of the box" (e.g., when you call connectSlotsByName(), or when QML
connects to your signals -- and we could get rid of the hack that calls
it from qtscript: https://codereview.qt-project.org/#change,24558). So
the only remaining bug is that, as with the old API, disconnectNotify()
is not called when the receiver is destroyed. But I'll propose a patch
for fixing that (we will need to store the signal index in the internal
Connection object, for fast retrieval of the QMetaMethod).
More information about the Development