diff options
Diffstat (limited to 'src/corelib/kernel')
33 files changed, 1522 insertions, 758 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 4b81087e2f..b645d480d7 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -14,6 +14,7 @@ HEADERS += \ kernel/qobject.h \ kernel/qobject_impl.h \ kernel/qobjectdefs.h \ + kernel/qobjectdefs_impl.h \ kernel/qsignalmapper.h \ kernel/qsocketnotifier.h \ kernel/qtimer.h \ @@ -136,3 +137,10 @@ vxworks { kernel/qfunctions_vxworks.h } +blackberry { + SOURCES += \ + kernel/qeventdispatcher_blackberry.cpp + HEADERS += \ + kernel/qeventdispatcher_blackberry_p.h +} + diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index cf9b0cea4f..2ef98dba0f 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -374,7 +374,7 @@ void QAbstractEventDispatcher::closingDown() Typedef for a function with the signature - \snippet doc/src/snippets/code/src_corelib_kernel_qabstracteventdispatcher.cpp 0 + \snippet code/src_corelib_kernel_qabstracteventdispatcher.cpp 0 Note that the type of the \a message is platform dependent. The following table shows the \a {message}'s type on Windows, Mac, and @@ -460,7 +460,7 @@ bool QAbstractEventDispatcher::filterEvent(void *message) This signal is emitted after the event loop returns from a function that could block. - \sa wakeUp() aboutToBlock() + \sa wakeUp(), aboutToBlock() */ /*! \fn void QAbstractEventDispatcher::aboutToBlock() diff --git a/src/corelib/kernel/qbasictimer.cpp b/src/corelib/kernel/qbasictimer.cpp index 621223eb88..76db945c45 100644 --- a/src/corelib/kernel/qbasictimer.cpp +++ b/src/corelib/kernel/qbasictimer.cpp @@ -92,7 +92,7 @@ QT_BEGIN_NAMESPACE Returns true if the timer is running and has not been stopped; otherwise returns false. - \sa start() stop() + \sa start(), stop() */ /*! @@ -112,7 +112,7 @@ QT_BEGIN_NAMESPACE The given \a object will receive timer events. - \sa stop() isActive() QObject::timerEvent() Qt::CoarseTimer + \sa stop(), isActive(), QObject::timerEvent(), Qt::CoarseTimer */ void QBasicTimer::start(int msec, QObject *obj) { @@ -139,7 +139,7 @@ void QBasicTimer::start(int msec, QObject *obj) The given \a object will receive timer events. - \sa stop() isActive() QObject::timerEvent() Qt::TimerType + \sa stop(), isActive(), QObject::timerEvent(), Qt::TimerType */ void QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj) { @@ -160,7 +160,7 @@ void QBasicTimer::start(int msec, Qt::TimerType timerType, QObject *obj) /*! Stops the timer. - \sa start() isActive() + \sa start(), isActive() */ void QBasicTimer::stop() { diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 048d746183..3fc1b7f801 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -63,7 +63,7 @@ #include <CoreFoundation/CoreFoundation.h> #endif -#ifndef QT_NO_CORESERVICES +#ifndef Q_OS_IOS #include <CoreServices/CoreServices.h> #endif diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 56674bc08e..5d70c4c5d8 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -67,10 +67,14 @@ #include <private/qlocale_p.h> #if defined(Q_OS_UNIX) -# if !defined(QT_NO_GLIB) -# include "qeventdispatcher_glib_p.h" +# if defined(Q_OS_BLACKBERRY) +# include "qeventdispatcher_blackberry_p.h" +# else +# if !defined(QT_NO_GLIB) +# include "qeventdispatcher_glib_p.h" +# endif +# include "qeventdispatcher_unix_p.h" # endif -# include "qeventdispatcher_unix_p.h" #endif #ifdef Q_OS_WIN @@ -328,12 +332,16 @@ void QCoreApplicationPrivate::createEventDispatcher() { Q_Q(QCoreApplication); #if defined(Q_OS_UNIX) +# if defined(Q_OS_BLACKBERRY) + eventDispatcher = new QEventDispatcherBlackberry(q); +# else # if !defined(QT_NO_GLIB) if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported()) eventDispatcher = new QEventDispatcherGlib(q); else # endif eventDispatcher = new QEventDispatcherUNIX(q); +# endif #elif defined(Q_OS_WIN) eventDispatcher = new QEventDispatcherWin32(q); #else @@ -1000,7 +1008,7 @@ void QCoreApplication::exit(int returnCode) The event is \e not deleted when the event has been sent. The normal approach is to create the event on the stack, for example: - \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 0 + \snippet code/src_corelib_kernel_qcoreapplication.cpp 0 \sa postEvent(), notify() */ @@ -1473,7 +1481,7 @@ void QCoreApplicationPrivate::maybeQuit() Example: - \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 1 + \snippet code/src_corelib_kernel_qcoreapplication.cpp 1 \sa exit(), aboutToQuit(), QApplication::lastWindowClosed() */ @@ -1521,7 +1529,7 @@ void QCoreApplication::quit() The function returns true on success and false on failure. - \sa removeTranslator() translate() QTranslator::load() {Dynamic Translation} + \sa removeTranslator(), translate(), QTranslator::load(), {Dynamic Translation} */ bool QCoreApplication::installTranslator(QTranslator *translationFile) @@ -1634,7 +1642,7 @@ static void replacePercentN(QString *result, int n) so will most likely result in crashes or other undesirable behavior. - \sa QObject::tr() installTranslator() + \sa QObject::tr(), installTranslator() */ @@ -1910,7 +1918,7 @@ QStringList QCoreApplication::arguments() organizationName(). On all other platforms, QSettings uses organizationName() as the organization. - \sa organizationDomain applicationName + \sa organizationDomain, applicationName */ void QCoreApplication::setOrganizationName(const QString &orgName) @@ -1936,7 +1944,7 @@ QString QCoreApplication::organizationName() On all other platforms, QSettings uses organizationName() as the organization. - \sa organizationName applicationName applicationVersion + \sa organizationName, applicationName, applicationVersion */ void QCoreApplication::setOrganizationDomain(const QString &orgDomain) { @@ -1958,7 +1966,7 @@ QString QCoreApplication::organizationDomain() If not set, the application name defaults to the executable name (since 5.0). - \sa organizationName organizationDomain applicationVersion applicationFilePath + \sa organizationName, organizationDomain, applicationVersion, applicationFilePath */ void QCoreApplication::setApplicationName(const QString &application) { @@ -1984,7 +1992,7 @@ Q_CORE_EXPORT QString qt_applicationName_noFallback() \since 4.4 \brief the version of this application - \sa applicationName organizationName organizationDomain + \sa applicationName, organizationName, organizationDomain */ void QCoreApplication::setApplicationVersion(const QString &version) { @@ -2018,7 +2026,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutex, libraryPathMutex, (QMutex::Recursive)) If you want to iterate over the list, you can use the \l foreach pseudo-keyword: - \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 2 + \snippet code/src_corelib_kernel_qcoreapplication.cpp 2 \sa setLibraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary, {How to Create Qt Plugins} @@ -2140,7 +2148,7 @@ void QCoreApplication::removeLibraryPath(const QString &path) A function with the following signature that can be used as an event filter: - \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 3 + \snippet code/src_corelib_kernel_qcoreapplication.cpp 3 \sa setEventFilter() */ @@ -2275,7 +2283,7 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc The function specified by \a ptr should take no arguments and should return nothing. For example: - \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 4 + \snippet code/src_corelib_kernel_qcoreapplication.cpp 4 Note that for an application- or module-wide cleanup, qAddPostRoutine() is often not suitable. For example, if the @@ -2289,7 +2297,7 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc parent-child mechanism to call a cleanup function at the right time: - \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 5 + \snippet code/src_corelib_kernel_qcoreapplication.cpp 5 By selecting the right parent object, this can often be made to clean up the module's data at the right moment. @@ -2303,7 +2311,7 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc translation functions, \c tr() and \c trUtf8(), with these signatures: - \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 6 + \snippet code/src_corelib_kernel_qcoreapplication.cpp 6 This macro is useful if you want to use QObject::tr() or QObject::trUtf8() in classes that don't inherit from QObject. @@ -2312,7 +2320,7 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc class definition (before the first \c{public:} or \c{protected:}). For example: - \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 7 + \snippet code/src_corelib_kernel_qcoreapplication.cpp 7 The \a context parameter is normally the class name, but it can be any string. diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp new file mode 100644 index 0000000000..462e359bf3 --- /dev/null +++ b/src/corelib/kernel/qeventdispatcher_blackberry.cpp @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Research In Motion +** Contact: http://www.qt-project.org/ +** +** 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$ +** +****************************************************************************/ + +#include "qeventdispatcher_blackberry_p.h" +#include "qsocketnotifier.h" +#include "qdebug.h" + +#include <bps/bps.h> +#include <bps/event.h> + +struct bpsIOHandlerData { + bpsIOHandlerData() + : count(0), readfds(0), writefds(0), exceptfds(0) + { + } + + int count; + fd_set *readfds; + fd_set *writefds; + fd_set *exceptfds; +}; + +static int bpsIOReadyDomain = -1; + +static int bpsIOHandler(int fd, int io_events, void *data) +{ + // decode callback payload + bpsIOHandlerData *ioData = static_cast<bpsIOHandlerData*>(data); + + // check if first file is ready + bool firstReady = (ioData->count == 0); + + // update ready state of file + if (io_events & BPS_IO_INPUT) { + FD_SET(fd, ioData->readfds); + ioData->count++; + } + + if (io_events & BPS_IO_OUTPUT) { + FD_SET(fd, ioData->writefds); + ioData->count++; + } + + if (io_events & BPS_IO_EXCEPT) { + FD_SET(fd, ioData->exceptfds); + ioData->count++; + } + + // force bps_get_event() to return immediately by posting an event to ourselves; + // but this only needs to happen once if multiple files become ready at the same time + if (firstReady) { + // create IO ready event + bps_event_t *event; + int result = bps_event_create(&event, bpsIOReadyDomain, 0, NULL, NULL); + if (result != BPS_SUCCESS) { + qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_event_create() failed"); + return BPS_FAILURE; + } + + // post IO ready event to our thread + result = bps_push_event(event); + if (result != BPS_SUCCESS) { + qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_push_event() failed"); + bps_event_destroy(event); + return BPS_FAILURE; + } + } + + return BPS_SUCCESS; +} + +QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberryPrivate() + : ioData(new bpsIOHandlerData) +{ + // prepare to use BPS + int result = bps_initialize(); + if (result != BPS_SUCCESS) + qFatal("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_initialize() failed"); + + // get domain for IO ready events - ignoring race condition here for now + if (bpsIOReadyDomain == -1) { + bpsIOReadyDomain = bps_register_domain(); + if (bpsIOReadyDomain == -1) + qWarning("QEventDispatcherBlackberryPrivate::QEventDispatcherBlackberry: bps_register_domain() failed"); + } + + // \TODO Reinstate this when bps is fixed. See comment in select() below. + // Register thread_pipe[0] with bps + /* + int io_events = BPS_IO_INPUT; + result = bps_add_fd(thread_pipe[0], io_events, &bpsIOHandler, ioData.data()); + if (result != BPS_SUCCESS) + qWarning() << Q_FUNC_INFO << "bps_add_fd() failed"; + */ +} + +QEventDispatcherBlackberryPrivate::~QEventDispatcherBlackberryPrivate() +{ + // we're done using BPS + bps_shutdown(); +} + +///////////////////////////////////////////////////////////////////////////// + +QEventDispatcherBlackberry::QEventDispatcherBlackberry(QObject *parent) + : QEventDispatcherUNIX(*new QEventDispatcherBlackberryPrivate, parent) +{ +} + +QEventDispatcherBlackberry::QEventDispatcherBlackberry(QEventDispatcherBlackberryPrivate &dd, QObject *parent) + : QEventDispatcherUNIX(dd, parent) +{ +} + +QEventDispatcherBlackberry::~QEventDispatcherBlackberry() +{ +} + +void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifier) +{ + Q_ASSERT(notifier); + + // Call the base Unix implementation. Needed to allow select() to be called correctly + QEventDispatcherUNIX::registerSocketNotifier(notifier); + + // Register the fd with bps + int sockfd = notifier->socket(); + int type = notifier->type(); + + int io_events = 0; + switch (type) { + case QSocketNotifier::Read: + io_events |= BPS_IO_INPUT; + break; + case QSocketNotifier::Write: + io_events |= BPS_IO_OUTPUT; + break; + case QSocketNotifier::Exception: + default: + io_events |= BPS_IO_EXCEPT; + break; + } + + Q_D(QEventDispatcherBlackberry); + int result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data()); + if (result != BPS_SUCCESS) + qWarning() << Q_FUNC_INFO << "bps_add_fd() failed"; +} + +void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notifier) +{ + // Unregister the fd with bps + int sockfd = notifier->socket(); + int result = bps_remove_fd(sockfd); + if (result != BPS_SUCCESS) + qWarning() << Q_FUNC_INFO << "bps_remove_fd() failed"; + + // Allow the base Unix implementation to unregister the fd too + QEventDispatcherUNIX::unregisterSocketNotifier(notifier); +} + +int QEventDispatcherBlackberry::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + timeval *timeout) +{ + Q_UNUSED(nfds); + + // prepare file sets for bps callback + Q_D(QEventDispatcherBlackberry); + d->ioData->count = 0; + d->ioData->readfds = readfds; + d->ioData->writefds = writefds; + d->ioData->exceptfds = exceptfds; + + // \TODO Remove this when bps is fixed + // + // Work around a bug in BPS with which if we register the thread_pipe[0] fd with bps in the + // private class' ctor once only then we get spurious notifications that thread_pipe[0] is + // ready for reading. The first time the notification is correct and the pipe is emptied in + // the calling doSelect() function. The 2nd notification is an error and the resulting attempt + // to read and call to wakeUps.testAndSetRelease(1, 0) fails as there has been no intervening + // call to QEventDispatcherUNIX::wakeUp(). + // + // Registering thread_pipe[0] here and unregistering it at the end of this call works around + // this issue. + int io_events = BPS_IO_INPUT; + int result = bps_add_fd(d->thread_pipe[0], io_events, &bpsIOHandler, d->ioData.data()); + if (result != BPS_SUCCESS) + qWarning() << Q_FUNC_INFO << "bps_add_fd() failed"; + + // reset all file sets + if (readfds) + FD_ZERO(readfds); + + if (writefds) + FD_ZERO(writefds); + + if (exceptfds) + FD_ZERO(exceptfds); + + // convert timeout to milliseconds + int timeout_ms = -1; + if (timeout) + timeout_ms = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); + + // wait for event or file to be ready + bps_event_t *event = NULL; + result = bps_get_event(&event, timeout_ms); + if (result != BPS_SUCCESS) + qWarning("QEventDispatcherBlackberry::select: bps_get_event() failed"); + + // pass all received events through filter - except IO ready events + if (event && bps_event_get_domain(event) != bpsIOReadyDomain) + filterEvent((void*)event); + + // \TODO Remove this when bps is fixed (see comment above) + result = bps_remove_fd(d->thread_pipe[0]); + if (result != BPS_SUCCESS) + qWarning() << Q_FUNC_INFO << "bps_remove_fd() failed"; + + // the number of bits set in the file sets + return d->ioData->count; +} + +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qeventdispatcher_blackberry_p.h b/src/corelib/kernel/qeventdispatcher_blackberry_p.h new file mode 100644 index 0000000000..b996bc7ee7 --- /dev/null +++ b/src/corelib/kernel/qeventdispatcher_blackberry_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Research In Motion +** Contact: http://www.qt-project.org/ +** +** 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 QEVENTDISPATCHER_BLACKBERRY_P_H +#define QEVENTDISPATCHER_BLACKBERRY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qeventdispatcher_unix_p.h" + +QT_BEGIN_NAMESPACE + +class QEventDispatcherBlackberryPrivate; + +class Q_CORE_EXPORT QEventDispatcherBlackberry : public QEventDispatcherUNIX +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QEventDispatcherBlackberry) + +public: + explicit QEventDispatcherBlackberry(QObject *parent = 0); + ~QEventDispatcherBlackberry(); + + void registerSocketNotifier(QSocketNotifier *notifier); + void unregisterSocketNotifier(QSocketNotifier *notifier); + +protected: + QEventDispatcherBlackberry(QEventDispatcherBlackberryPrivate &dd, QObject *parent = 0); + + int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + timeval *timeout); +}; + +struct bpsIOHandlerData; + +class Q_CORE_EXPORT QEventDispatcherBlackberryPrivate : public QEventDispatcherUNIXPrivate +{ + Q_DECLARE_PUBLIC(QEventDispatcherBlackberry) + +public: + QEventDispatcherBlackberryPrivate(); + ~QEventDispatcherBlackberryPrivate(); + + QScopedPointer<bpsIOHandlerData> ioData; +}; + +QT_END_NAMESPACE + +#endif // QEVENTDISPATCHER_BLACKBERRY_P_H diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index d3a64aae04..deea463061 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -275,7 +275,7 @@ void QEventLoop::exit(int returnCode) false. The event loop is considered running from the time when exec() is called until exit() is called. - \sa exec() exit() + \sa exec(), exit() */ bool QEventLoop::isRunning() const { diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index e3b0b15e26..4e05b63c82 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -146,23 +146,17 @@ QT_BEGIN_NAMESPACE static inline const QMetaObjectPrivate *priv(const uint* data) { return reinterpret_cast<const QMetaObjectPrivate*>(data); } -static inline const QByteArrayData &stringData(const QMetaObject *mo, int index) +static inline const QByteArray stringData(const QMetaObject *mo, int index) { Q_ASSERT(priv(mo->d.data)->revision >= 7); - const QByteArrayData &data = mo->d.stringdata[index]; - Q_ASSERT(data.ref.isStatic()); - Q_ASSERT(data.alloc == 0); - Q_ASSERT(data.capacityReserved == 0); - Q_ASSERT(data.size >= 0); + const QByteArrayDataPtr data = { const_cast<QByteArrayData*>(&mo->d.stringdata[index]) }; + Q_ASSERT(data.ptr->ref.isStatic()); + Q_ASSERT(data.ptr->alloc == 0); + Q_ASSERT(data.ptr->capacityReserved == 0); + Q_ASSERT(data.ptr->size >= 0); return data; } -static inline QByteArray toByteArray(const QByteArrayData &d) -{ - QByteArrayDataPtr holder = { const_cast<QByteArrayData *>(&d) }; - return QByteArray(holder); -} - static inline const char *rawStringData(const QMetaObject *mo, int index) { return stringData(mo, index).data(); @@ -170,13 +164,13 @@ static inline const char *rawStringData(const QMetaObject *mo, int index) static inline int stringSize(const QMetaObject *mo, int index) { - return stringData(mo, index).size; + return stringData(mo, index).size(); } static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo) { if (typeInfo & IsUnresolvedType) { - return toByteArray(stringData(mo, typeInfo & TypeNameIndexMask)); + return stringData(mo, typeInfo & TypeNameIndexMask); } else { // ### Use the QMetaType::typeName() that returns QByteArray const char *t = QMetaType::typeName(typeInfo); @@ -193,7 +187,7 @@ static inline int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo) { if (!(typeInfo & IsUnresolvedType)) return typeInfo; - return QMetaType::type(toByteArray(stringData(mo, typeInfo & TypeNameIndexMask))); + return QMetaType::type(stringData(mo, typeInfo & TypeNameIndexMask)); } class QMetaMethodPrivate : public QMetaMethod @@ -294,11 +288,10 @@ QObject *QMetaObject::newInstance(QGenericArgument val0, */ int QMetaObject::static_metacall(Call cl, int idx, void **argv) const { - const QMetaObjectExtraData *extra = reinterpret_cast<const QMetaObjectExtraData *>(d.extradata); Q_ASSERT(priv(d.data)->revision >= 6); - if (!extra || !extra->static_metacall) + if (!d.static_metacall) return 0; - extra->static_metacall(0, cl, idx, argv); + d.static_metacall(0, cl, idx, argv); return -1; } @@ -492,7 +485,7 @@ int QMetaObject::constructorCount() const Use code like the following to obtain a QStringList containing the methods specific to a given class: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp methodCount + \snippet code/src_corelib_kernel_qmetaobject.cpp methodCount \sa method(), methodOffset(), indexOfMethod() */ @@ -530,7 +523,7 @@ int QMetaObject::enumeratorCount() const Use code like the following to obtain a QStringList containing the properties specific to a given class: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp propertyCount + \snippet code/src_corelib_kernel_qmetaobject.cpp propertyCount \sa property(), propertyOffset(), indexOfProperty() */ @@ -572,7 +565,7 @@ static bool methodMatch(const QMetaObject *m, int handle, if (int(m->d.data[handle + 1]) != argc) return false; - if (toByteArray(stringData(m, m->d.data[handle])) != name) + if (stringData(m, m->d.data[handle]) != name) return false; int paramsIndex = m->d.data[handle + 2] + 1; @@ -659,6 +652,7 @@ int QMetaObject::indexOfMethod(const char *method) const } // Parses a string of comma-separated types into QArgumentTypes. +// No normalization of the type names is performed. static void argumentTypesFromString(const char *str, const char *end, QArgumentTypeArray &types) { @@ -812,6 +806,35 @@ int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArra return -1; } +/*! \internal + Returns the signal for the given \a metaObject at \a signal_index. + + It it different from QMetaObject::method(); the index should not include + non-signal methods. + + The index must correspond to a signal defined in \ a metaObject itself; + it should not be an inherited signal. +*/ +QMetaMethod QMetaObjectPrivate::signal(const QMetaObject *metaObject, int signal_index) +{ + QMetaMethod result; + if (signal_index < 0) + return result; + Q_ASSERT(metaObject != 0); + + int signalOffset = 0; + for (const QMetaObject *m = metaObject->d.superdata; m; m = m->d.superdata) + signalOffset += priv(m->d.data)->signalCount; + + Q_ASSERT(signal_index >= signalOffset); + int signal_index_relative = signal_index - signalOffset; + if (signal_index_relative < priv(metaObject->d.data)->signalCount) { + result.mobj = metaObject; + result.handle = priv(metaObject->d.data)->methodData + 5*signal_index_relative; + } + return result; +} + /*! \internal @@ -869,11 +892,9 @@ static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, co while (self) { if (strcmp(rawStringData(self, 0), name) == 0) return self; - if (self->d.extradata) { - const QMetaObject **e; + if (self->d.relatedMetaObjects) { Q_ASSERT(priv(self->d.data)->revision >= 2); - const QMetaObjectExtraData *extra = (const QMetaObjectExtraData*)(self->d.extradata); - e = extra->objects; + const QMetaObject **e = self->d.relatedMetaObjects; if (e) { while (*e) { if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name)) @@ -1102,7 +1123,7 @@ QMetaProperty QMetaObject::userProperty() const Example: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 0 + \snippet code/src_corelib_kernel_qmetaobject.cpp 0 \sa classInfoCount(), classInfoOffset(), indexOfClassInfo() */ @@ -1207,7 +1228,7 @@ static char *qNormalizeType(char *d, int &templdepth, QByteArray &result) Example: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 1 + \snippet code/src_corelib_kernel_qmetaobject.cpp 1 \sa normalizedSignature() */ @@ -1312,7 +1333,7 @@ enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value the \l{QPushButton::animateClick()}{animateClick()} slot on a QPushButton, use the following code: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 2 + \snippet code/src_corelib_kernel_qmetaobject.cpp 2 With asynchronous method invocations, the parameters must be of types that are known to Qt's meta-object system, because Qt needs @@ -1320,7 +1341,7 @@ enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value scenes. If you try to use a queued connection and get the error message - \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 3 + \snippet code/src_corelib_kernel_qmetaobject.cpp 3 call qRegisterMetaType() to register the data type before you call invokeMethod(). @@ -1328,7 +1349,7 @@ enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value To synchronously invoke the \c compute(QString, int, double) slot on some arbitrary object \c obj retrieve its return value: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 4 + \snippet code/src_corelib_kernel_qmetaobject.cpp 4 If the "compute" slot does not take exactly one QString, one int and one double in the specified order, the call will fail. @@ -1483,6 +1504,24 @@ bool QMetaObject::invokeMethod(QObject *obj, invoked), otherwise returns false. */ +/*! \fn bool operator==(const QMetaMethod &m1, const QMetaMethod &m2) + \since 5.0 + \relates QMetaMethod + \overload + + Returns true if method \a m1 is equal to method \a m2, + otherwise returns false. +*/ + +/*! \fn bool operator!=(const QMetaMethod &m1, const QMetaMethod &m2) + \since 5.0 + \relates QMetaMethod + \overload + + Returns true if method \a m1 is not equal to method \a m2, + otherwise returns false. +*/ + /*! \fn const QMetaObject *QMetaMethod::enclosingMetaObject() const \internal @@ -1522,7 +1561,7 @@ QByteArray QMetaMethodPrivate::signature() const QByteArray QMetaMethodPrivate::name() const { Q_ASSERT(priv(mobj->d.data)->revision >= 7); - return toByteArray(stringData(mobj, mobj->d.data[handle])); + return stringData(mobj, mobj->d.data[handle]); } int QMetaMethodPrivate::typesDataIndex() const @@ -1599,14 +1638,14 @@ QList<QByteArray> QMetaMethodPrivate::parameterNames() const int argc = parameterCount(); int namesIndex = parametersDataIndex() + argc; for (int i = 0; i < argc; ++i) - list += toByteArray(stringData(mobj, mobj->d.data[namesIndex + i])); + list += stringData(mobj, mobj->d.data[namesIndex + i]); return list; } QByteArray QMetaMethodPrivate::tag() const { Q_ASSERT(priv(mobj->d.data)->revision >= 7); - return toByteArray(stringData(mobj, mobj->d.data[handle + 3])); + return stringData(mobj, mobj->d.data[handle + 3]); } /*! @@ -1848,6 +1887,41 @@ QMetaMethod::MethodType QMetaMethod::methodType() const } /*! + \fn QMetaMethod QMetaMethod::fromSignal(PointerToMemberFunction signal) + \since 5.0 + + Returns the meta-method that corresponds to the given \a signal, or an + invalid QMetaMethod if \a signal is not a signal of the class. + + Example: + + \snippet code/src_corelib_kernel_qmetaobject.cpp 9 +*/ + +/*! \internal + + Implementation of the fromSignal() function. + + \a metaObject is the class's meta-object + \a signal is a pointer to a pointer to a member signal of the class +*/ +QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **signal) +{ + int i = -1; + void *args[] = { &i, signal }; + QMetaMethod result; + for (const QMetaObject *m = metaObject; m; m = m->d.superdata) { + m->static_metacall(QMetaObject::IndexOfMethod, 0, args); + if (i >= 0) { + result.mobj = m; + result.handle = priv(m->d.data)->methodData + 5*i; + break; + } + } + return result; +} + +/*! Invokes this method on the object \a object. Returns true if the member could be invoked. Returns false if there is no such member or the parameters did not match. @@ -1883,7 +1957,7 @@ QMetaMethod::MethodType QMetaMethod::methodType() const \l{QPushButton::animateClick()}{animateClick()} slot on a QPushButton: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 6 + \snippet code/src_corelib_kernel_qmetaobject.cpp 6 With asynchronous method invocations, the parameters must be of types that are known to Qt's meta-object system, because Qt needs @@ -1891,7 +1965,7 @@ QMetaMethod::MethodType QMetaMethod::methodType() const scenes. If you try to use a queued connection and get the error message - \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 7 + \snippet code/src_corelib_kernel_qmetaobject.cpp 7 call qRegisterMetaType() to register the data type before you call QMetaMethod::invoke(). @@ -1899,7 +1973,7 @@ QMetaMethod::MethodType QMetaMethod::methodType() const To synchronously invoke the \c compute(QString, int, double) slot on some arbitrary object \c obj retrieve its return value: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 8 + \snippet code/src_corelib_kernel_qmetaobject.cpp 8 QMetaObject::normalizedSignature() is used here to ensure that the format of the signature is what invoke() expects. E.g. extra whitespace is @@ -2012,8 +2086,7 @@ bool QMetaMethod::invoke(QObject *object, int idx_relative = ((handle - priv(mobj->d.data)->methodData) / 5); int idx_offset = mobj->methodOffset(); Q_ASSERT(QMetaObjectPrivate::get(mobj)->revision >= 6); - QObjectPrivate::StaticMetaCallFunction callFunction = mobj->d.extradata - ? reinterpret_cast<const QMetaObjectExtraData *>(mobj->d.extradata)->static_metacall : 0; + QObjectPrivate::StaticMetaCallFunction callFunction = mobj->d.static_metacall; if (connectionType == Qt::DirectConnection) { if (callFunction) { @@ -2391,7 +2464,7 @@ QByteArray QMetaEnum::valueToKeys(int value) const v = v & ~k; if (!keys.isEmpty()) keys += '|'; - keys += toByteArray(stringData(mobj, mobj->d.data[data + 2*i])); + keys += stringData(mobj, mobj->d.data[data + 2*i]); } } return keys; @@ -3058,7 +3131,7 @@ bool QMetaProperty::isEditable(const QObject *object) const are specified using Q_CLASSINFO() in the source code. The information can be retrieved using name() and value(). For example: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 5 + \snippet code/src_corelib_kernel_qmetaobject.cpp 5 This mechanism is free for you to use in your Qt applications. Qt doesn't use it for any of its classes. diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 095b196dca..1c49506926 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -141,6 +141,20 @@ public: inline bool isValid() const { return mobj != 0; } +#ifdef Q_QDOC + static QMetaMethod fromSignal(PointerToMemberFunction signal); +#else + template <typename Func> + static inline QMetaMethod fromSignal(Func signal) + { + typedef QtPrivate::FunctionPointer<Func> SignalType; + reinterpret_cast<typename SignalType::Object *>(0)->qt_check_for_QOBJECT_macro( + *reinterpret_cast<typename SignalType::Object *>(0)); + return fromSignalImpl(&SignalType::Object::staticMetaObject, + reinterpret_cast<void **>(&signal)); + } +#endif + private: #if QT_DEPRECATED_SINCE(5,0) // signature() has been renamed to methodSignature() in Qt 5. @@ -148,6 +162,7 @@ private: // you convert to char*. char *signature(struct renamedInQt5_warning_checkTheLifeTime * = 0) Q_DECL_EQ_DELETE; #endif + static QMetaMethod fromSignalImpl(const QMetaObject *, void **); const QMetaObject *mobj; uint handle; @@ -155,9 +170,16 @@ private: friend struct QMetaObject; friend struct QMetaObjectPrivate; friend class QObject; + friend bool operator==(const QMetaMethod &m1, const QMetaMethod &m2); + friend bool operator!=(const QMetaMethod &m1, const QMetaMethod &m2); }; Q_DECLARE_TYPEINFO(QMetaMethod, Q_MOVABLE_TYPE); +inline bool operator==(const QMetaMethod &m1, const QMetaMethod &m2) +{ return m1.mobj == m2.mobj && m1.handle == m2.handle; } +inline bool operator!=(const QMetaMethod &m1, const QMetaMethod &m2) +{ return !(m1 == m2); } + class Q_CORE_EXPORT QMetaEnum { public: diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 3b732b4b93..5877ab18e4 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -110,6 +110,8 @@ enum MetaDataFlags { TypeNameIndexMask = 0x7FFFFFFF }; +extern int qMetaTypeTypeInternal(const char *); + class QArgumentType { public: @@ -117,7 +119,7 @@ public: : _type(type) {} QArgumentType(const QByteArray &name) - : _type(QMetaType::type(name.constData())), _name(name) + : _type(qMetaTypeTypeInternal(name.constData())), _name(name) {} QArgumentType() : _type(0) @@ -198,6 +200,7 @@ struct QMetaObjectPrivate int argc, const QArgumentType *types); static int indexOfConstructor(const QMetaObject *m, const QByteArray &name, int argc, const QArgumentType *types); + static QMetaMethod signal(const QMetaObject *m, int signal_index); static bool checkConnectArgs(int signalArgc, const QArgumentType *signalTypes, int methodArgc, const QArgumentType *methodTypes); static bool checkConnectArgs(const QMetaMethodPrivate *signal, @@ -211,10 +214,12 @@ struct QMetaObjectPrivate static void memberIndexes(const QObject *obj, const QMetaMethod &member, int *signalIndex, int *methodIndex); static QObjectPrivate::Connection *connect(const QObject *sender, int signal_index, + const QMetaObject *smeta, const QObject *receiver, int method_index_relative, const QMetaObject *rmeta = 0, int type = 0, int *types = 0); static bool disconnect(const QObject *sender, int signal_index, + const QMetaObject *smeta, const QObject *receiver, int method_index, void **slot, DisconnectType = DisconnectAll); static inline bool disconnectHelper(QObjectPrivate::Connection *c, diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp index d262d6a61b..16ff58e1ca 100644 --- a/src/corelib/kernel/qmetaobjectbuilder.cpp +++ b/src/corelib/kernel/qmetaobjectbuilder.cpp @@ -609,7 +609,7 @@ QMetaPropertyBuilder QMetaObjectBuilder::addProperty(const QMetaProperty& protot \a name. Returns an object that can be used to adjust the other attributes of the enumerator. - \sa enumerator(), enumeratorCount(), removeEnumerator(), + \sa enumerator(), enumeratorCount(), removeEnumerator() \sa indexOfEnumerator() */ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name) @@ -625,7 +625,7 @@ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name) QMetaObject. Returns an object that can be used to adjust the attributes of the enumerator. - \sa enumerator(), enumeratorCount(), removeEnumerator(), + \sa enumerator(), enumeratorCount(), removeEnumerator() \sa indexOfEnumerator() */ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype) @@ -737,13 +737,8 @@ void QMetaObjectBuilder::addMetaObject } if ((members & RelatedMetaObjects) != 0) { - const QMetaObject **objects; Q_ASSERT(priv(prototype->d.data)->revision >= 2); - const QMetaObjectExtraData *extra = (const QMetaObjectExtraData *)(prototype->d.extradata); - if (extra) - objects = extra->objects; - else - objects = 0; + const QMetaObject **objects = prototype->d.relatedMetaObjects; if (objects) { while (*objects != 0) { addRelatedMetaObject(*objects); @@ -754,10 +749,8 @@ void QMetaObjectBuilder::addMetaObject if ((members & StaticMetacall) != 0) { Q_ASSERT(priv(prototype->d.data)->revision >= 6); - const QMetaObjectExtraData *extra = - (const QMetaObjectExtraData *)(prototype->d.extradata); - if (extra && extra->static_metacall) - setStaticMetacallFunction(extra->static_metacall); + if (prototype->d.static_metacall) + setStaticMetacallFunction(prototype->d.static_metacall); } } @@ -1150,7 +1143,7 @@ static int aggregateParameterCount(const QList<QMetaMethodBuilderPrivate> &metho // Build a QMetaObject in "buf" based on the information in "d". // If "buf" is null, then return the number of bytes needed to // build the QMetaObject. Returns -1 if the metaobject if -// relocatable is set, but the metaobject contains extradata. +// relocatable is set, but the metaobject contains relatedMetaObjects. static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, int expectedSize, bool relocatable) { @@ -1174,7 +1167,9 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, ALIGN(size, int); if (buf) { if (!relocatable) meta->d.superdata = d->superClass; + meta->d.relatedMetaObjects = 0; meta->d.extradata = 0; + meta->d.static_metacall = d->staticMetacallFunction; } // Populate the QMetaObjectPrivate structure. @@ -1446,30 +1441,18 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf, if (buf) data[enumIndex] = 0; - // Create the extradata block if we need one. - if (d->relatedMetaObjects.size() > 0 || d->staticMetacallFunction) { - ALIGN(size, QMetaObject **); - ALIGN(size, QMetaObjectBuilder::StaticMetacallFunction); - QMetaObjectExtraData *extra = - reinterpret_cast<QMetaObjectExtraData *>(buf + size); - size += sizeof(QMetaObjectExtraData); + // Create the relatedMetaObjects block if we need one. + if (d->relatedMetaObjects.size() > 0) { ALIGN(size, QMetaObject *); const QMetaObject **objects = reinterpret_cast<const QMetaObject **>(buf + size); if (buf) { - if (d->relatedMetaObjects.size() > 0) { - extra->objects = objects; - for (index = 0; index < d->relatedMetaObjects.size(); ++index) - objects[index] = d->relatedMetaObjects[index]; - objects[index] = 0; - } else { - extra->objects = 0; - } - extra->static_metacall = d->staticMetacallFunction; - meta->d.extradata = reinterpret_cast<void *>(extra); + meta->d.relatedMetaObjects = objects; + for (index = 0; index < d->relatedMetaObjects.size(); ++index) + objects[index] = d->relatedMetaObjects[index]; + objects[index] = 0; } - if (d->relatedMetaObjects.size() > 0) - size += sizeof(QMetaObject *) * (d->relatedMetaObjects.size() + 1); + size += sizeof(QMetaObject *) * (d->relatedMetaObjects.size() + 1); } // Align the final size and return it. @@ -1552,6 +1535,8 @@ void QMetaObjectBuilder::fromRelocatableData(QMetaObject *output, output->d.stringdata = reinterpret_cast<const QByteArrayData *>(buf + stringdataOffset); output->d.data = reinterpret_cast<const uint *>(buf + dataOffset); output->d.extradata = 0; + output->d.relatedMetaObjects = 0; + output->d.static_metacall = 0; } /*! diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h index 4d766a9197..7c18298d35 100644 --- a/src/corelib/kernel/qmetaobjectbuilder_p.h +++ b/src/corelib/kernel/qmetaobjectbuilder_p.h @@ -165,7 +165,7 @@ public: int indexOfEnumerator(const QByteArray& name); int indexOfClassInfo(const QByteArray& name); - typedef QMetaObjectExtraData::StaticMetacallFunction StaticMetacallFunction; + typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); QMetaObjectBuilder::StaticMetacallFunction staticMetacallFunction() const; void setStaticMetacallFunction(QMetaObjectBuilder::StaticMetacallFunction value); diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 53b22958c3..2756dd5241 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -125,16 +125,16 @@ struct DefinedTypesFilter { This example shows a typical use case of Q_DECLARE_METATYPE(): - \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 0 + \snippet code/src_corelib_kernel_qmetatype.cpp 0 If \c MyStruct is in a namespace, the Q_DECLARE_METATYPE() macro has to be outside the namespace: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 1 + \snippet code/src_corelib_kernel_qmetatype.cpp 1 Since \c{MyStruct} is now known to QMetaType, it can be used in QVariant: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 2 + \snippet code/src_corelib_kernel_qmetatype.cpp 2 \sa qRegisterMetaType() */ @@ -220,21 +220,13 @@ struct DefinedTypesFilter { \value User Base value for user types \value UnknownType This is an invalid type id. It is returned from QMetaType for types that are not registered - \omitvalue FirstGuiType - \omitvalue FirstWidgetsType - \omitvalue LastCoreType - \omitvalue LastGuiType - \omitvalue LastWidgetsType - \omitvalue QReal - \omitvalue HighestInternalId - Additional types can be registered using Q_DECLARE_METATYPE(). \sa type(), typeName() */ /*! - \enum QMetaType::TypeFlags + \enum QMetaType::TypeFlag The enum describes attributes of a type supported by QMetaType. @@ -265,7 +257,7 @@ struct DefinedTypesFilter { The following code allocates and destructs an instance of \c{MyClass}: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 3 + \snippet code/src_corelib_kernel_qmetatype.cpp 3 If we want the stream operators \c operator<<() and \c operator>>() to work on QVariant objects that store custom types, @@ -449,16 +441,37 @@ int QMetaType::registerType(const char *typeName, Deleter deleter, int size, TypeFlags flags, const QMetaObject *metaObject) { Q_UNUSED(metaObject); - QVector<QCustomTypeInfo> *ct = customTypes(); - if (!ct || !typeName || !deleter || !creator || !destructor || !constructor) - return -1; - #ifdef QT_NO_QOBJECT NS(QByteArray) normalizedTypeName = typeName; #else NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName); #endif + return registerNormalizedType(normalizedTypeName, deleter, creator, destructor, constructor, size, flags, metaObject); +} + + +/*! \internal + \since 5.0 + + Registers a user type for marshalling, with \a normalizedTypeName, a \a + deleter, a \a creator, a \a destructor, a \a constructor, and + a \a size. Returns the type's handle, or -1 if the type could + not be registered. Note that normalizedTypeName is not checked for + conformance with Qt's normalized format, so it must already + conform. + */ +int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, Deleter deleter, + Creator creator, + Destructor destructor, + Constructor constructor, + int size, TypeFlags flags, const QMetaObject *metaObject) +{ + Q_UNUSED(metaObject); + QVector<QCustomTypeInfo> *ct = customTypes(); + if (!ct || normalizedTypeName.isEmpty() || !deleter || !creator || !destructor || !constructor) + return -1; + int idx = qMetaTypeStaticType(normalizedTypeName.constData(), normalizedTypeName.size()); @@ -521,16 +534,28 @@ int QMetaType::registerType(const char *typeName, Deleter deleter, */ int QMetaType::registerTypedef(const char* typeName, int aliasId) { - QVector<QCustomTypeInfo> *ct = customTypes(); - if (!ct || !typeName) - return -1; - #ifdef QT_NO_QOBJECT NS(QByteArray) normalizedTypeName = typeName; #else NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName); #endif + return registerNormalizedTypedef(normalizedTypeName, aliasId); +} + +/*! \internal + \since 5.0 + + Registers a user type for marshalling, as an alias of another type (typedef). + Note that normalizedTypeName is not checked for conformance with Qt's normalized format, + so it must already conform. +*/ +int QMetaType::registerNormalizedTypedef(const NS(QByteArray) &normalizedTypeName, int aliasId) +{ + QVector<QCustomTypeInfo> *ct = customTypes(); + if (!ct || normalizedTypeName.isEmpty()) + return -1; + int idx = qMetaTypeStaticType(normalizedTypeName.constData(), normalizedTypeName.size()); @@ -581,26 +606,26 @@ bool QMetaType::isRegistered(int type) } /*! - Returns a handle to the type called \a typeName, or QMetaType::UnknownType if there is - no such type. + \internal - \sa isRegistered(), typeName(), Type + Implementation of QMetaType::type(). */ -int QMetaType::type(const char *typeName) +template <int tryNormalizedType> +static inline int qMetaTypeTypeImpl(const char *typeName) { int length = qstrlen(typeName); if (!length) - return UnknownType; + return QMetaType::UnknownType; int type = qMetaTypeStaticType(typeName, length); - if (type == UnknownType) { + if (type == QMetaType::UnknownType) { QReadLocker locker(customTypesLock()); type = qMetaTypeCustomType_unlocked(typeName, length); #ifndef QT_NO_QOBJECT - if (type == UnknownType) { + if ((type == QMetaType::UnknownType) && tryNormalizedType) { const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName); type = qMetaTypeStaticType(normalizedTypeName.constData(), normalizedTypeName.size()); - if (type == UnknownType) { + if (type == QMetaType::UnknownType) { type = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(), normalizedTypeName.size()); } @@ -610,6 +635,29 @@ int QMetaType::type(const char *typeName) return type; } +/*! + Returns a handle to the type called \a typeName, or QMetaType::UnknownType if there is + no such type. + + \sa isRegistered(), typeName(), Type +*/ +int QMetaType::type(const char *typeName) +{ + return qMetaTypeTypeImpl</*tryNormalizedType=*/true>(typeName); +} + +/*! + \a internal + + Similar to QMetaType::type(); the only difference is that this function + doesn't attempt to normalize the type name (i.e., the lookup will fail + for type names in non-normalized form). +*/ +int qMetaTypeTypeInternal(const char *typeName) +{ + return qMetaTypeTypeImpl</*tryNormalizedType=*/false>(typeName); +} + #ifndef QT_NO_DATASTREAM /*! Writes the object pointed to by \a data with the ID \a type to @@ -1486,12 +1534,12 @@ QMetaType::TypeFlags QMetaType::typeFlags(int type) This example registers the class \c{MyClass}: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 4 + \snippet code/src_corelib_kernel_qmetatype.cpp 4 This function is useful to register typedefs so they can be used by QMetaProperty, or in QueuedConnections - \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 9 + \snippet code/src_corelib_kernel_qmetatype.cpp 9 \sa qRegisterMetaTypeStreamOperators(), QMetaType::isRegistered(), Q_DECLARE_METATYPE() @@ -1509,11 +1557,11 @@ QMetaType::TypeFlags QMetaType::typeFlags(int type) QMetaType::save(). These functions are used when streaming a QVariant. - \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 5 + \snippet code/src_corelib_kernel_qmetatype.cpp 5 The stream operators should have the following signatures: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 6 + \snippet code/src_corelib_kernel_qmetatype.cpp 6 \sa qRegisterMetaType(), QMetaType::isRegistered(), Q_DECLARE_METATYPE() */ @@ -1548,7 +1596,7 @@ QMetaType::TypeFlags QMetaType::typeFlags(int type) Example: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 7 + \snippet code/src_corelib_kernel_qmetatype.cpp 7 To use the type \c T in QVariant, using Q_DECLARE_METATYPE() is sufficient. To use the type \c T in queued signal and slot connections, @@ -1574,7 +1622,7 @@ QMetaType::TypeFlags QMetaType::typeFlags(int type) Typical usage: - \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 8 + \snippet code/src_corelib_kernel_qmetatype.cpp 8 QMetaType::type() returns the same ID as qMetaTypeId(), but does a lookup at runtime based on the name of the type. diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 21f4bc7afe..595da53562 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -45,8 +45,11 @@ #include <QtCore/qglobal.h> #include <QtCore/qatomic.h> #include <QtCore/qbytearray.h> +#include <QtCore/qvarlengtharray.h> #include <QtCore/qisenum.h> - +#ifndef QT_NO_QOBJECT +#include <QtCore/qobjectdefs.h> +#endif #include <new> #ifdef Bool @@ -195,6 +198,8 @@ class Q_CORE_EXPORT QMetaType { FlagsEx = 0x100 }; public: +#ifndef Q_QDOC + // The code that actually gets compiled. enum Type { // these are merged with QVariant QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID) @@ -212,6 +217,29 @@ public: UnknownType = 0, User = 1024 }; +#else + // If we are using QDoc it fakes the Type enum looks like this. + enum Type { + Void = 0, Bool = 1, Int = 2, UInt = 3, LongLong = 4, ULongLong = 5, + Double = 6, Long = 32, Short = 33, Char = 34, ULong = 35, UShort = 36, + UChar = 37, Float = 38, + VoidStar = 31, + QChar = 7, QString = 10, QStringList = 11, QByteArray = 12, + QBitArray = 13, QDate = 14, QTime = 15, QDateTime = 16, QUrl = 17, + QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22, + QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26, QRegExp = 27, + QEasingCurve = 29, QUuid = 30, QVariant = 41, QModelIndex = 42, + QObjectStar = 39, QWidgetStar = 40, + QVariantMap = 8, QVariantList = 9, QVariantHash = 28, + QFont = 64, QPixmap = 65, QBrush = 66, QColor = 67, QPalette = 68, + QImage = 69, QPolygon = 70, QRegion = 71, QBitmap = 72, QCursor = 73, + QKeySequence = 74, QPen = 75, QTextLength = 76, QTextFormat = 77, + QMatrix = 78, QTransform = 79, QMatrix4x4 = 80, QVector2D = 81, + QVector3D = 82, QVector4D = 83, QQuaternion = 84, QPolygonF = 85, + QIcon = 120, QSizePolicy = 121, + User = 256 + }; +#endif enum TypeFlag { NeedsConstruction = 0x1, @@ -245,7 +273,15 @@ public: int size, QMetaType::TypeFlags flags, const QMetaObject *metaObject); + static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Deleter deleter, + Creator creator, + Destructor destructor, + Constructor constructor, + int size, + QMetaType::TypeFlags flags, + const QMetaObject *metaObject); static int registerTypedef(const char *typeName, int aliasId); + static int registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, int aliasId); static int type(const char *typeName); static const char *typeName(int type); static int sizeOf(int type); @@ -480,7 +516,7 @@ namespace QtPrivate { } template <typename T> -int qRegisterMetaType(const char *typeName +int qRegisterNormalizedMetaType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName #ifndef qdoc , T * dummy = 0 #endif @@ -488,10 +524,10 @@ int qRegisterMetaType(const char *typeName { const int typedefOf = dummy ? -1 : QtPrivate::QMetaTypeIdHelper<T>::qt_metatype_id(); if (typedefOf != -1) - return QMetaType::registerTypedef(typeName, typedefOf); + return QMetaType::registerNormalizedTypedef(normalizedTypeName, typedefOf); QMetaType::TypeFlags flags(QtPrivate::QMetaTypeTypeFlags<T>::Flags); - return QMetaType::registerType(typeName, qMetaTypeDeleteHelper<T>, + return QMetaType::registerNormalizedType(normalizedTypeName, qMetaTypeDeleteHelper<T>, qMetaTypeCreateHelper<T>, qMetaTypeDestructHelper<T>, qMetaTypeConstructHelper<T>, @@ -500,6 +536,21 @@ int qRegisterMetaType(const char *typeName QtPrivate::MetaObjectForType<T>::value()); } +template <typename T> +int qRegisterMetaType(const char *typeName +#ifndef qdoc + , T * dummy = 0 +#endif +) +{ +#ifdef QT_NO_QOBJECT + QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = typeName; +#else + QT_PREPEND_NAMESPACE(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName); +#endif + return qRegisterNormalizedMetaType<T>(normalizedTypeName, dummy); +} + #ifndef QT_NO_DATASTREAM template <typename T> void qRegisterMetaTypeStreamOperators(const char *typeName @@ -548,9 +599,14 @@ struct QMetaTypeIdQObject<T*, /* isPointerToTypeDerivedFromQObject */ true> static int qt_metatype_id() { static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); - if (!metatype_id.load()) - metatype_id.storeRelease(qRegisterMetaType<T*>(QByteArray(T::staticMetaObject.className() + QByteArrayLiteral("*")).constData(), + if (!metatype_id.load()) { + const int len = int(strlen(T::staticMetaObject.className())); + QVarLengthArray<char, 16> classNameStar; + classNameStar.append(T::staticMetaObject.className(), len); + classNameStar.append("*\0", 2); + metatype_id.storeRelease(qRegisterMetaType<T*>(classNameStar.constData(), reinterpret_cast<T**>(quintptr(-1)))); + } return metatype_id.loadAcquire(); } }; @@ -687,6 +743,7 @@ inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeI , m_loadOp(loadOp) , m_constructor(constructor) , m_destructor(destructor) + , m_extension(0) , m_size(size) , m_typeFlags(theTypeFlags) , m_extensionFlags(extensionFlags) diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h index 74229d3f3c..b593489963 100644 --- a/src/corelib/kernel/qmetatype_p.h +++ b/src/corelib/kernel/qmetatype_p.h @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE namespace QModulesPrivate { enum Names { Core, Gui, Widgets, Unknown, ModulesCount /* ModulesCount has to be at the end */ }; -static inline int moduleForType(const int typeId) +static inline int moduleForType(const uint typeId) { if (typeId <= QMetaType::LastCoreType) return Core; diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp index 3a3464e43e..c18ce22247 100644 --- a/src/corelib/kernel/qmimedata.cpp +++ b/src/corelib/kernel/qmimedata.cpp @@ -257,7 +257,7 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty For example, if your write a widget that accepts URL drags, you would end up writing code like this: - \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 0 + \snippet code/src_corelib_kernel_qmimedata.cpp 0 There are three approaches for storing custom data in a QMimeData object: @@ -266,7 +266,7 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty \li Custom data can be stored directly in a QMimeData object as a QByteArray using setData(). For example: - \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 1 + \snippet code/src_corelib_kernel_qmimedata.cpp 1 \li We can subclass QMimeData and reimplement hasFormat(), formats(), and retrieveData(). @@ -276,7 +276,7 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty it, and use a qobject_cast() in the receiver's drop event handler. For example: - \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 2 + \snippet code/src_corelib_kernel_qmimedata.cpp 2 \endlist \section1 Platform-Specific MIME Types @@ -286,11 +286,11 @@ QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Ty indicate that they represent data in non-standard formats. The formats will take the following form: - \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 3 + \snippet code/src_corelib_kernel_qmimedata.cpp 3 The following are examples of custom MIME types: - \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 4 + \snippet code/src_corelib_kernel_qmimedata.cpp 4 The \c value declaration of each format describes the way in which the data is encoded. @@ -458,7 +458,7 @@ bool QMimeData::hasHtml() const library, whereas QImage belongs to \l QtGui. To convert the QVariant to a QImage, simply use qvariant_cast(). For example: - \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 5 + \snippet code/src_corelib_kernel_qmimedata.cpp 5 \sa hasImage() */ @@ -475,7 +475,7 @@ QVariant QMimeData::imageData() const library, whereas QImage belongs to \l QtGui. The conversion from QImage to QVariant is implicit. For example: - \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 6 + \snippet code/src_corelib_kernel_qmimedata.cpp 6 \sa hasImage(), setData() */ @@ -505,7 +505,7 @@ bool QMimeData::hasImage() const library, whereas QColor belongs to \l QtGui. To convert the QVariant to a QColor, simply use qvariant_cast(). For example: - \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 7 + \snippet code/src_corelib_kernel_qmimedata.cpp 7 \sa hasColor(), setColorData(), data() */ 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 diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 11b1a19e0b..5e969d67f6 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -365,11 +365,15 @@ protected: QObject *sender() const; int senderSignalIndex() const; int receivers(const char* signal) const; + bool isSignalConnected(const QMetaMethod &signal) const; virtual void timerEvent(QTimerEvent *); virtual void childEvent(QChildEvent *); virtual void customEvent(QEvent *); + virtual void connectNotify(const QMetaMethod &signal); + virtual void disconnectNotify(const QMetaMethod &signal); + // Deprecated; to be removed before Qt 5.0 virtual void connectNotify(const char *signal); virtual void disconnectNotify(const char *signal); @@ -382,6 +386,7 @@ protected: static const QMetaObject staticQtMetaObject; friend struct QMetaObject; + friend struct QMetaObjectPrivate; friend class QMetaCallEvent; friend class QApplication; friend class QApplicationPrivate; diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index 419fcc1dd4..e016002afa 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -51,431 +51,6 @@ QT_BEGIN_NAMESPACE namespace QtPrivate { - template <typename T> struct RemoveRef { 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) { - if (container.data) - *reinterpret_cast<U*>(container.data) = value; - } -#ifdef Q_COMPILER_RVALUE_REFS - template<typename T, typename U> - void operator,(T &&value, const ApplyReturnValue<U> &container) { - if (container.data) - *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<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4)> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4); - enum {ArgumentCount = 4}; - 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]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5)> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); - enum {ArgumentCount = 5}; - 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]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]); - } - }; - template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> - struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> - { - typedef Obj Object; - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); - enum {ArgumentCount = 6}; - 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]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), 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 Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4)> - { - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4); - enum {ArgumentCount = 4}; - 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]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4, Arg5)> - { - typedef List<Arg1, List<Arg2, List<Arg3, - List<Arg4, List<Arg5, void > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); - enum {ArgumentCount = 5}; - 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]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> - { - typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments; - typedef Ret ReturnType; - typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); - enum {ArgumentCount = 6}; - 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]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), 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]); - } - }; - template<typename Function> struct Functor<Function, 4> - { - 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]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Function> struct Functor<Function, 5> - { - 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]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]); - } - }; - template<typename Function> struct Functor<Function, 6> - { - 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]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]), - *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), 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: - Q_STATIC_ASSERT(CheckCompatibleArguments<FunctionPointer<Signal>::Arguments, FunctionPointer<Slot>::Arguments>::value) - */ - template<typename A1, typename A2> struct AreArgumentsCompatible { - static int test(A2); - static char test(...); - static A1 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 }; }; - // void as a return value - template<typename A> struct AreArgumentsCompatible<void, A> { enum { value = true }; }; - template<typename A> struct AreArgumentsCompatible<A, void> { enum { value = true }; }; - template<> struct AreArgumentsCompatible<void, void> { enum { value = true }; }; - -#ifndef Q_COMPILER_VARIADIC_TEMPLATES - template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; }; - template <> struct CheckCompatibleArguments<void, void> { enum { value = true }; }; - template <typename List1> struct CheckCompatibleArguments<List1, void> { enum { value = true }; }; - template <typename Arg1, typename Arg2, typename Tail1, typename Tail2> struct CheckCompatibleArguments<List<Arg1, Tail1>, List<Arg2, Tail2> > - { - enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value - && CheckCompatibleArguments<Tail1, Tail2>::value }; - }; -#else - template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; }; - template <> struct CheckCompatibleArguments<List<>, List<>> { enum { value = true }; }; - template <typename List1> struct CheckCompatibleArguments<List1, List<>> { enum { value = true }; }; - template <typename Arg1, typename Arg2, typename... Tail1, typename... Tail2> - struct CheckCompatibleArguments<List<Arg1, Tail1...>, List<Arg2, Tail2...>> - { - enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value - && CheckCompatibleArguments<List<Tail1...>, List<Tail2...>>::value }; - }; - -#endif - /* Logic to statically generate the array of qMetaTypeId ConnectionTypes<FunctionPointer<Signal>::Arguments>::types() returns an array diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index c8edadce9d..a31e091ae8 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -91,6 +91,7 @@ public: static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *); static void (*objectNameChanged)(QAbstractDeclarativeData *, QObject *); static void (*signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **); + static int (*receivers)(QAbstractDeclarativeData *, const QObject *, int); }; class Q_CORE_EXPORT QObjectPrivate : public QObjectData @@ -175,7 +176,7 @@ public: return o->d_func(); } - int signalIndex(const char *signalName) const; + int signalIndex(const char *signalName, const QMetaObject **meta = 0) const; inline bool isSignalConnected(uint signalIdx) const; public: diff --git a/src/corelib/kernel/qobjectcleanuphandler.cpp b/src/corelib/kernel/qobjectcleanuphandler.cpp index 166a90a74f..f165ec96ca 100644 --- a/src/corelib/kernel/qobjectcleanuphandler.cpp +++ b/src/corelib/kernel/qobjectcleanuphandler.cpp @@ -121,7 +121,7 @@ void QObjectCleanupHandler::remove(QObject *object) Returns true if this cleanup handler is empty or if all objects in this cleanup handler have been destroyed; otherwise return false. - \sa add() remove() clear() + \sa add(), remove(), clear() */ bool QObjectCleanupHandler::isEmpty() const { diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 9bcb8b9211..cc442457b0 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -44,6 +44,8 @@ #include <QtCore/qnamespace.h> +#include <QtCore/qobjectdefs_impl.h> + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -55,7 +57,7 @@ struct QByteArrayData; class QString; #ifndef Q_MOC_OUTPUT_REVISION -#define Q_MOC_OUTPUT_REVISION 65 +#define Q_MOC_OUTPUT_REVISION 66 #endif // The following macros are our "extensions" to C++ @@ -158,7 +160,6 @@ public: \ QT_TR_FUNCTIONS \ virtual int qt_metacall(QMetaObject::Call, int, void **); \ private: \ - Q_DECL_HIDDEN static const QMetaObjectExtraData staticMetaObjectExtraData; \ Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); /* tmake ignore Q_OBJECT */ @@ -451,7 +452,10 @@ struct Q_CORE_EXPORT QMetaObject const QMetaObject *superdata; const QByteArrayData *stringdata; const uint *data; - const void *extradata; + typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); + StaticMetacallFunction static_metacall; + const QMetaObject **relatedMetaObjects; + void *extradata; //reserved for future use } d; }; @@ -479,17 +483,6 @@ public: #endif }; -typedef const QMetaObject& (*QMetaObjectAccessor)(); - -struct QMetaObjectExtraData -{ - const QMetaObject **objects; - - typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); //from revision 6 - //typedef int (*StaticMetaCall)(QMetaObject::Call, int, void **); //used from revison 2 until revison 5 - StaticMetacallFunction static_metacall; -}; - inline const QMetaObject *QMetaObject::superClass() const { return d.superdata; } diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h new file mode 100644 index 0000000000..5efe08b3e5 --- /dev/null +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -0,0 +1,485 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** 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 QOBJECTDEFS_H +#error Do not include qobjectdefs_impl.h directly +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +namespace QtPrivate { + template <typename T> struct RemoveRef { 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) { + if (container.data) + *reinterpret_cast<U*>(container.data) = value; + } +#ifdef Q_COMPILER_RVALUE_REFS + template<typename T, typename U> + void operator,(T &&value, const ApplyReturnValue<U> &container) { + if (container.data) + *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<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4)> + { + typedef Obj Object; + typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments; + typedef Ret ReturnType; + typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4); + enum {ArgumentCount = 4}; + 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]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]); + } + }; + template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5)> + { + typedef Obj Object; + typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > > Arguments; + typedef Ret ReturnType; + typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); + enum {ArgumentCount = 5}; + 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]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]); + } + }; + template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> + struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> + { + typedef Obj Object; + typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments; + typedef Ret ReturnType; + typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); + enum {ArgumentCount = 6}; + 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]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), 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 Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4)> + { + typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments; + typedef Ret ReturnType; + typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4); + enum {ArgumentCount = 4}; + 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]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]); + } + }; + template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4, Arg5)> + { + typedef List<Arg1, List<Arg2, List<Arg3, + List<Arg4, List<Arg5, void > > > > > Arguments; + typedef Ret ReturnType; + typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5); + enum {ArgumentCount = 5}; + 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]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]); + } + }; + template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)> + { + typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments; + typedef Ret ReturnType; + typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); + enum {ArgumentCount = 6}; + 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]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), 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]); + } + }; + template<typename Function> struct Functor<Function, 4> + { + 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]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]); + } + }; + template<typename Function> struct Functor<Function, 5> + { + 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]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]); + } + }; + template<typename Function> struct Functor<Function, 6> + { + 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]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]), + *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), 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: + Q_STATIC_ASSERT(CheckCompatibleArguments<FunctionPointer<Signal>::Arguments, FunctionPointer<Slot>::Arguments>::value) + */ + template<typename A1, typename A2> struct AreArgumentsCompatible { + static int test(A2); + static char test(...); + static A1 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 }; }; + // void as a return value + template<typename A> struct AreArgumentsCompatible<void, A> { enum { value = true }; }; + template<typename A> struct AreArgumentsCompatible<A, void> { enum { value = true }; }; + template<> struct AreArgumentsCompatible<void, void> { enum { value = true }; }; + +#ifndef Q_COMPILER_VARIADIC_TEMPLATES + template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; }; + template <> struct CheckCompatibleArguments<void, void> { enum { value = true }; }; + template <typename List1> struct CheckCompatibleArguments<List1, void> { enum { value = true }; }; + template <typename Arg1, typename Arg2, typename Tail1, typename Tail2> struct CheckCompatibleArguments<List<Arg1, Tail1>, List<Arg2, Tail2> > + { + enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value + && CheckCompatibleArguments<Tail1, Tail2>::value }; + }; +#else + template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; }; + template <> struct CheckCompatibleArguments<List<>, List<>> { enum { value = true }; }; + template <typename List1> struct CheckCompatibleArguments<List1, List<>> { enum { value = true }; }; + template <typename Arg1, typename Arg2, typename... Tail1, typename... Tail2> + struct CheckCompatibleArguments<List<Arg1, Tail1...>, List<Arg2, Tail2...>> + { + enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value + && CheckCompatibleArguments<List<Tail1...>, List<Tail2...>>::value }; + }; + +#endif +} + + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/corelib/kernel/qpointer.cpp b/src/corelib/kernel/qpointer.cpp index e0e14e5b79..cd88baf9bf 100644 --- a/src/corelib/kernel/qpointer.cpp +++ b/src/corelib/kernel/qpointer.cpp @@ -74,10 +74,10 @@ Example: - \snippet doc/src/snippets/pointer/pointer.cpp 0 + \snippet pointer/pointer.cpp 0 \dots - \snippet doc/src/snippets/pointer/pointer.cpp 1 - \snippet doc/src/snippets/pointer/pointer.cpp 2 + \snippet pointer/pointer.cpp 1 + \snippet pointer/pointer.cpp 2 If the QLabel is deleted in the meantime, the \c label variable will hold 0 instead of an invalid address, and the last line will diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp index d8578a8059..50c24ba169 100644 --- a/src/corelib/kernel/qsharedmemory.cpp +++ b/src/corelib/kernel/qsharedmemory.cpp @@ -174,7 +174,7 @@ QSharedMemory::QSharedMemory(const QString &key, QObject *parent) the shared memory segment, the detach() operation destroys the shared memory segment. - \sa detach() isAttached() + \sa detach(), isAttached() */ QSharedMemory::~QSharedMemory() { @@ -193,7 +193,7 @@ QSharedMemory::~QSharedMemory() segment, it will \l {detach()} {detach} from it before setting the new key. This function does not do an attach(). - \sa key() nativeKey() isAttached() + \sa key(), nativeKey(), isAttached() */ void QSharedMemory::setKey(const QString &key) { @@ -225,7 +225,7 @@ void QSharedMemory::setKey(const QString &key) The application will not be portable if you set a native key. - \sa nativeKey() key() isAttached() + \sa nativeKey(), key(), isAttached() */ void QSharedMemory::setNativeKey(const QString &key) { @@ -288,7 +288,7 @@ bool QSharedMemoryPrivate::initKey() You can find the native, platform specific, key used by the operating system by calling nativeKey(). - \sa setKey() setNativeKey() + \sa setKey(), setNativeKey() */ QString QSharedMemory::key() const { @@ -306,7 +306,7 @@ QString QSharedMemory::key() const You can use the native key to access shared memory segments that have not been created by Qt, or to grant shared memory access to non-Qt applications. - \sa setKey() setNativeKey() + \sa setKey(), setNativeKey() */ QString QSharedMemory::nativeKey() const { @@ -363,7 +363,7 @@ bool QSharedMemory::create(int size, AccessMode mode) Returns the size of the attached shared memory segment. If no shared memory segment is attached, 0 is returned. - \sa create() attach() + \sa create(), attach() */ int QSharedMemory::size() const { @@ -472,7 +472,7 @@ void *QSharedMemory::data() the shared memory, and remember to release the lock with unlock() after you are done. - \sa attach() create() + \sa attach(), create() */ const void* QSharedMemory::constData() const { diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp index 27340020d8..c668047bd2 100644 --- a/src/corelib/kernel/qsignalmapper.cpp +++ b/src/corelib/kernel/qsignalmapper.cpp @@ -91,14 +91,14 @@ public: signal, \c clicked(), which is emitted with the text of the button that was clicked: - \snippet doc/src/snippets/qsignalmapper/buttonwidget.h 0 - \snippet doc/src/snippets/qsignalmapper/buttonwidget.h 1 + \snippet qsignalmapper/buttonwidget.h 0 + \snippet qsignalmapper/buttonwidget.h 1 The only function that we need to implement is the constructor: - \snippet doc/src/snippets/qsignalmapper/buttonwidget.cpp 0 - \snippet doc/src/snippets/qsignalmapper/buttonwidget.cpp 1 - \snippet doc/src/snippets/qsignalmapper/buttonwidget.cpp 2 + \snippet qsignalmapper/buttonwidget.cpp 0 + \snippet qsignalmapper/buttonwidget.cpp 1 + \snippet qsignalmapper/buttonwidget.cpp 2 A list of texts is passed to the constructor. A signal mapper is constructed and for each text in the list a QPushButton is diff --git a/src/corelib/kernel/qsystemsemaphore.cpp b/src/corelib/kernel/qsystemsemaphore.cpp index 0558f3cb59..70e75b54b9 100644 --- a/src/corelib/kernel/qsystemsemaphore.cpp +++ b/src/corelib/kernel/qsystemsemaphore.cpp @@ -79,7 +79,7 @@ QT_BEGIN_NAMESPACE can use to use the same semaphore. Example: Create a system semaphore - \snippet doc/src/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp 0 + \snippet code/src_corelib_kernel_qsystemsemaphore.cpp 0 A typical application of system semaphores is for controlling access to a circular buffer shared by a producer process and a consumer @@ -283,13 +283,13 @@ bool QSystemSemaphore::acquire() Example: Create a system semaphore having five resources; acquire them all and then release them all. - \snippet doc/src/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp 1 + \snippet code/src_corelib_kernel_qsystemsemaphore.cpp 1 This function can also "create" resources. For example, immediately following the sequence of statements above, suppose we add the statement: - \snippet doc/src/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp 2 + \snippet code/src_corelib_kernel_qsystemsemaphore.cpp 2 Ten new resources are now guarded by the semaphore, in addition to the five that already existed. You would not normally use this diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 2131188439..23e1826006 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -61,9 +61,9 @@ QT_BEGIN_NAMESPACE Example for a one second (1000 millisecond) timer (from the \l{widgets/analogclock}{Analog Clock} example): - \snippet examples/widgets/analogclock/analogclock.cpp 4 - \snippet examples/widgets/analogclock/analogclock.cpp 5 - \snippet examples/widgets/analogclock/analogclock.cpp 6 + \snippet widgets/analogclock/analogclock.cpp 4 + \snippet widgets/analogclock/analogclock.cpp 5 + \snippet widgets/analogclock/analogclock.cpp 6 From then on, the \c update() slot is called every second. @@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE QTimer::singleShot() function to call a slot after a specified interval: - \snippet doc/src/snippets/timers/timers.cpp 3 + \snippet timers/timers.cpp 3 In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI @@ -87,9 +87,9 @@ QT_BEGIN_NAMESPACE been processed. This can be used to do heavy work while providing a snappy user interface: - \snippet doc/src/snippets/timers/timers.cpp 4 - \snippet doc/src/snippets/timers/timers.cpp 5 - \snippet doc/src/snippets/timers/timers.cpp 6 + \snippet timers/timers.cpp 4 + \snippet timers/timers.cpp 5 + \snippet timers/timers.cpp 6 \c processOneThing() will from then on be called repeatedly. It should be written in such a way that it always returns quickly @@ -304,7 +304,7 @@ QT_END_INCLUDE_NAMESPACE create a local QTimer object. Example: - \snippet doc/src/snippets/code/src_corelib_kernel_qtimer.cpp 0 + \snippet code/src_corelib_kernel_qtimer.cpp 0 This sample program automatically terminates after 10 minutes (600,000 milliseconds). @@ -343,7 +343,7 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, QObject *receiver, co if (msec == 0) { // special code shortpath for 0-timers const char* bracketPosition = strchr(member, '('); - if (!bracketPosition || !(member[0] >= '0' && member[0] <= '3')) { + if (!bracketPosition || !(member[0] >= '0' && member[0] <= '2')) { qWarning("QTimer::singleShot: Invalid slot specification"); return; } diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 892883bacd..c34a3acb70 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -338,7 +338,7 @@ public: it via QObject::tr(). Here's the \c main() function from the \l{linguist/hellotr}{Hello tr()} example: - \snippet examples/linguist/hellotr/main.cpp 2 + \snippet linguist/hellotr/main.cpp 2 Note that the translator must be created \e before the application's widgets. diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 10b86bcb48..7ccc5e500e 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -87,7 +87,7 @@ class HandlersManager { static const QVariant::Handler *Handlers[QModulesPrivate::ModulesCount]; public: - const QVariant::Handler *operator[] (const int typeId) const + const QVariant::Handler *operator[] (const uint typeId) const { return Handlers[QModulesPrivate::moduleForType(typeId)]; } @@ -776,6 +776,7 @@ static void customConstruct(QVariant::Private *d, const void *copy) const QMetaType type(d->type); const uint size = type.sizeOf(); if (!size) { + qWarning("Trying to construct an instance of an invalid type, type id: %i", d->type); d->type = QVariant::Invalid; return; } @@ -839,6 +840,9 @@ static void customStreamDebug(QDebug dbg, const QVariant &variant) { QMetaType::TypeFlags flags = QMetaType::typeFlags(variant.userType()); if (flags & QMetaType::PointerToQObject) dbg.nospace() << variant.value<QObject*>(); +#else + Q_UNUSED(dbg); + Q_UNUSED(variant); #endif } #endif @@ -909,7 +913,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names Here is some example code to demonstrate the use of QVariant: - \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 0 + \snippet code/src_corelib_kernel_qvariant.cpp 0 You can even store QList<QVariant> and QMap<QString, QVariant> values in a variant, so you can easily construct arbitrarily @@ -921,7 +925,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names have a defined type with no value set. However, note that QVariant types can only be cast when they have had a value set. - \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 1 + \snippet code/src_corelib_kernel_qvariant.cpp 1 QVariant can be extended to support other types than those mentioned in the \l Type enum. See the \l QMetaType documentation @@ -935,13 +939,13 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names toColor() function. Instead, you can use the QVariant::value() or the qvariant_cast() template function. For example: - \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 2 + \snippet code/src_corelib_kernel_qvariant.cpp 2 The inverse conversion (e.g., from QColor to QVariant) is automatic for all data types supported by QVariant, including GUI-related types: - \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 3 + \snippet code/src_corelib_kernel_qvariant.cpp 3 \section1 Using canConvert() and convert() Consecutively @@ -1677,13 +1681,15 @@ void QVariant::load(QDataStream &s) return; } } - create(static_cast<int>(typeId), 0); + create(typeId, 0); d.is_null = is_null; if (!isValid()) { + if (s.version() < QDataStream::Qt_5_0) { // Since we wrote something, we should read something - QString x; - s >> x; + QString x; + s >> x; + } d.is_null = true; return; } @@ -1745,7 +1751,8 @@ void QVariant::save(QDataStream &s) const } if (!isValid()) { - s << QString(); + if (s.version() < QDataStream::Qt_5_0) + s << QString(); return; } @@ -2172,7 +2179,6 @@ inline T qNumVariantToHelper(const QVariant::Private &d, \b{Warning:} If the value is convertible to a \l LongLong but is too large to be represented in an int, the resulting arithmetic overflow will not be reflected in \a ok. A simple workaround is to use QString::toInt(). - Fixing this bug has been postponed to Qt 5 in order to avoid breaking existing code. \sa canConvert(), convert() */ @@ -2192,7 +2198,6 @@ int QVariant::toInt(bool *ok) const \b{Warning:} If the value is convertible to a \l ULongLong but is too large to be represented in an unsigned int, the resulting arithmetic overflow will not be reflected in \a ok. A simple workaround is to use QString::toUInt(). - Fixing this bug has been postponed to Qt 5 in order to avoid breaking existing code. \sa canConvert(), convert() */ @@ -2527,7 +2532,7 @@ bool QVariant::convert(int targetTypeId) } /*! - \fn convert(const int type, void *ptr) const + \fn bool QVariant::convert(const int type, void *ptr) const \internal Created for qvariant_cast() usage */ @@ -2671,7 +2676,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) Example: - \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 4 + \snippet code/src_corelib_kernel_qvariant.cpp 4 \sa value(), fromValue(), canConvert() */ @@ -2688,7 +2693,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) Example: - \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 5 + \snippet code/src_corelib_kernel_qvariant.cpp 5 \sa setValue(), fromValue(), canConvert() */ @@ -2700,7 +2705,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) Example: - \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 6 + \snippet code/src_corelib_kernel_qvariant.cpp 6 \sa convert() */ @@ -2712,7 +2717,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) Example: - \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 7 + \snippet code/src_corelib_kernel_qvariant.cpp 7 \note If you are working with custom types, you should use the Q_DECLARE_METATYPE() macro to register your custom type. @@ -2737,7 +2742,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) For example, a QObject pointer can be stored in a variant with the following code: - \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 8 + \snippet code/src_corelib_kernel_qvariant.cpp 8 \sa QVariant::fromValue() */ diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index 8af1ab2161..b48bd0c8cc 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -48,6 +48,19 @@ QT_BEGIN_NAMESPACE +class QWinEventNotifierPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QWinEventNotifier) +public: + QWinEventNotifierPrivate() + : handleToEvent(0), enabled(false) {} + QWinEventNotifierPrivate(HANDLE h, bool e) + : handleToEvent(h), enabled(e) {} + + HANDLE handleToEvent; + bool enabled; +}; + /*! \class QWinEventNotifier \since 5.0 @@ -103,7 +116,7 @@ QT_BEGIN_NAMESPACE */ QWinEventNotifier::QWinEventNotifier(QObject *parent) - : QObject(parent), handleToEvent(0), enabled(false) + : QObject(*new QWinEventNotifierPrivate, parent) {} /*! @@ -118,14 +131,14 @@ QWinEventNotifier::QWinEventNotifier(QObject *parent) */ QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent) - : QObject(parent), handleToEvent(hEvent), enabled(false) + : QObject(*new QWinEventNotifierPrivate(hEvent, false), parent) { - Q_D(QObject); + Q_D(QWinEventNotifier); QEventDispatcherWin32 *eventDispatcher = qobject_cast<QEventDispatcherWin32 *>(d->threadData->eventDispatcher); Q_ASSERT_X(eventDispatcher, "QWinEventNotifier::QWinEventNotifier()", "Cannot create a win event notifier without a QEventDispatcherWin32"); eventDispatcher->registerEventNotifier(this); - enabled = true; + d->enabled = true; } /*! @@ -149,8 +162,9 @@ QWinEventNotifier::~QWinEventNotifier() void QWinEventNotifier::setHandle(HANDLE hEvent) { + Q_D(QWinEventNotifier); setEnabled(false); - handleToEvent = hEvent; + d->handleToEvent = hEvent; } /*! @@ -161,7 +175,8 @@ void QWinEventNotifier::setHandle(HANDLE hEvent) HANDLE QWinEventNotifier::handle() const { - return handleToEvent; + Q_D(const QWinEventNotifier); + return d->handleToEvent; } /*! @@ -172,7 +187,8 @@ HANDLE QWinEventNotifier::handle() const bool QWinEventNotifier::isEnabled() const { - return enabled; + Q_D(const QWinEventNotifier); + return d->enabled; } /*! @@ -184,16 +200,16 @@ bool QWinEventNotifier::isEnabled() const void QWinEventNotifier::setEnabled(bool enable) { - if (enabled == enable) // no change + Q_D(QWinEventNotifier); + if (d->enabled == enable) // no change return; - enabled = enable; + d->enabled = enable; - Q_D(QObject); QEventDispatcherWin32 *eventDispatcher = qobject_cast<QEventDispatcherWin32 *>(d->threadData->eventDispatcher); if (!eventDispatcher) // perhaps application is shutting down return; - if (enabled) + if (enable) eventDispatcher->registerEventNotifier(this); else eventDispatcher->unregisterEventNotifier(this); @@ -205,16 +221,17 @@ void QWinEventNotifier::setEnabled(bool enable) bool QWinEventNotifier::event(QEvent * e) { + Q_D(QWinEventNotifier); if (e->type() == QEvent::ThreadChange) { - if (enabled) { + if (d->enabled) { QMetaObject::invokeMethod(this, "setEnabled", Qt::QueuedConnection, - Q_ARG(bool, enabled)); + Q_ARG(bool, true)); setEnabled(false); } } QObject::event(e); // will activate filters if (e->type() == QEvent::WinEventAct) { - emit activated(handleToEvent); + emit activated(d->handleToEvent); return true; } return false; diff --git a/src/corelib/kernel/qwineventnotifier.h b/src/corelib/kernel/qwineventnotifier.h index b364c68e05..36ec415124 100644 --- a/src/corelib/kernel/qwineventnotifier.h +++ b/src/corelib/kernel/qwineventnotifier.h @@ -54,11 +54,11 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE - +class QWinEventNotifierPrivate; class Q_CORE_EXPORT QWinEventNotifier : public QObject { Q_OBJECT - Q_DECLARE_PRIVATE(QObject) + Q_DECLARE_PRIVATE(QWinEventNotifier) public: explicit QWinEventNotifier(QObject *parent = 0); @@ -78,10 +78,6 @@ Q_SIGNALS: protected: bool event(QEvent * e); - -private: - HANDLE handleToEvent; - bool enabled; }; QT_END_NAMESPACE |