diff options
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/kernel.pri | 3 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_mac_objc.mm | 30 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_mac_p.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 82 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication_p.h | 5 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication_win.cpp | 5 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_blackberry.cpp | 23 | ||||
-rw-r--r-- | src/corelib/kernel/qjni.cpp | 58 | ||||
-rw-r--r-- | src/corelib/kernel/qjni_p.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qjnihelpers.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qmath.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 55 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_impl.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 1 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 62 | ||||
-rw-r--r-- | src/corelib/kernel/qwineventnotifier.h | 2 |
16 files changed, 238 insertions, 102 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 998bf56874..4c43f292fb 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -110,6 +110,9 @@ mac:!nacl { kernel/qcore_mac.cpp OBJECTIVE_SOURCES += \ kernel/qcore_mac_objc.mm + + # We need UIKit for UIDevice + ios: LIBS_PRIVATE += -framework UIKit } nacl { diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 7b9eb67969..73f8296021 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -41,6 +41,10 @@ #include <private/qcore_mac_p.h> +#ifdef Q_OS_IOS +#import <UIKit/UIKit.h> +#endif + QT_BEGIN_NAMESPACE NSString *QCFString::toNSString(const QString &string) @@ -54,5 +58,31 @@ QString QCFString::toQString(const NSString *nsstr) return toQString(reinterpret_cast<CFStringRef>(nsstr)); } +#ifdef Q_OS_IOS +QSysInfo::MacVersion qt_ios_version() +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + int major = 0, minor = 0; + NSArray *components = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."]; + switch ([components count]) { + case 3: + // We don't care about the patch version + case 2: + minor = [[components objectAtIndex:1] intValue]; + // fall through + case 1: + major = [[components objectAtIndex:0] intValue]; + break; + default: + Q_UNREACHABLE(); + } + + [pool release]; + + return QSysInfo::MacVersion(Q_MV_IOS(major, minor)); +} +#endif + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index fa911fb967..f491be9768 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -143,6 +143,10 @@ private: QString string; }; +#ifdef Q_OS_IOS +QSysInfo::MacVersion qt_ios_version(); +#endif + QT_END_NAMESPACE #endif // QCORE_MAC_P_H diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 00e98a69bc..e83a6e2ac4 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -151,23 +151,21 @@ QString QCoreApplicationPrivate::macMenuBarName() #endif QString QCoreApplicationPrivate::appName() const { - static QBasicMutex applicationNameMutex; - QMutexLocker locker(&applicationNameMutex); - - if (applicationName.isNull()) { + QString applicationName; #ifdef Q_OS_MAC - applicationName = macMenuBarName(); + applicationName = macMenuBarName(); #endif - if (applicationName.isEmpty() && argv[0]) { - char *p = strrchr(argv[0], '/'); - applicationName = QString::fromLocal8Bit(p ? p + 1 : argv[0]); - } + if (applicationName.isEmpty() && argv[0]) { + char *p = strrchr(argv[0], '/'); + applicationName = QString::fromLocal8Bit(p ? p + 1 : argv[0]); } return applicationName; } #endif +QString *QCoreApplicationPrivate::cachedApplicationFilePath = 0; + bool QCoreApplicationPrivate::checkInstance(const char *function) { bool b = (QCoreApplication::self != 0); @@ -433,6 +431,7 @@ QCoreApplicationPrivate::~QCoreApplicationPrivate() #ifdef Q_OS_WIN delete [] origArgv; #endif + QCoreApplicationPrivate::clearApplicationFilePath(); } #ifndef QT_NO_QOBJECT @@ -1041,7 +1040,7 @@ bool QCoreApplication::closingDown() You can call this function occasionally when your program is busy performing a long operation (e.g. copying a file). - In event you are running a local loop which calls this function + In the event that you are running a local loop which calls this function continuously, without an event loop, the \l{QEvent::DeferredDelete}{DeferredDelete} events will not be processed. This can affect the behaviour of widgets, @@ -1898,6 +1897,20 @@ QString QCoreApplication::translate(const char *context, const char *sourceText, #endif //QT_NO_TRANSLATE +// Makes it possible to point QCoreApplication to a custom location to ensure +// the directory is added to the patch, and qt.conf and deployed plugins are +// found from there. This is for use cases in which QGuiApplication is +// instantiated by a library and not by an application executable, for example, +// Active X servers. + +void QCoreApplicationPrivate::setApplicationFilePath(const QString &path) +{ + if (QCoreApplicationPrivate::cachedApplicationFilePath) + *QCoreApplicationPrivate::cachedApplicationFilePath = path; + else + QCoreApplicationPrivate::cachedApplicationFilePath = new QString(path); +} + /*! Returns the directory that contains the application executable. @@ -1953,20 +1966,28 @@ QString QCoreApplication::applicationFilePath() } QCoreApplicationPrivate *d = self->d_func(); - if (!d->cachedApplicationFilePath.isNull()) - return d->cachedApplicationFilePath; + + static char *procName = d->argv[0]; + if (qstrcmp(procName, d->argv[0]) != 0) { + // clear the cache if the procname changes, so we reprocess it. + QCoreApplicationPrivate::clearApplicationFilePath(); + procName = d->argv[0]; + } + + if (QCoreApplicationPrivate::cachedApplicationFilePath) + return *QCoreApplicationPrivate::cachedApplicationFilePath; #if defined(Q_OS_WIN) - d->cachedApplicationFilePath = QFileInfo(qAppFileName()).filePath(); - return d->cachedApplicationFilePath; + QCoreApplicationPrivate::setApplicationFilePath(QFileInfo(qAppFileName()).filePath()); + return *QCoreApplicationPrivate::cachedApplicationFilePath; #elif defined(Q_OS_BLACKBERRY) if (!arguments().isEmpty()) { // args is never empty, but the navigator can change behaviour some day QFileInfo fileInfo(arguments().at(0)); const bool zygotized = fileInfo.exists(); if (zygotized) { // Handle the zygotized case: - d->cachedApplicationFilePath = QDir::cleanPath(fileInfo.absoluteFilePath()); - return d->cachedApplicationFilePath; + QCoreApplicationPrivate::setApplicationFilePath(QDir::cleanPath(fileInfo.absoluteFilePath())); + return *QCoreApplicationPrivate::cachedApplicationFilePath; } } @@ -1974,7 +1995,7 @@ QString QCoreApplication::applicationFilePath() const size_t maximum_path = static_cast<size_t>(pathconf("/",_PC_PATH_MAX)); char buff[maximum_path+1]; if (_cmdname(buff)) { - d->cachedApplicationFilePath = QDir::cleanPath(QString::fromLocal8Bit(buff)); + QCoreApplicationPrivate::setApplicationFilePath(QDir::cleanPath(QString::fromLocal8Bit(buff))); } else { qWarning("QCoreApplication::applicationFilePath: _cmdname() failed"); // _cmdname() won't fail, but just in case, fallback to the old method @@ -1982,18 +2003,19 @@ QString QCoreApplication::applicationFilePath() QStringList executables = dir.entryList(QDir::Executable | QDir::Files); if (!executables.empty()) { //We assume that there is only one executable in the folder - d->cachedApplicationFilePath = dir.absoluteFilePath(executables.first()); - } else { - d->cachedApplicationFilePath = QString(); + QCoreApplicationPrivate::setApplicationFilePath(dir.absoluteFilePath(executables.first())); } } - return d->cachedApplicationFilePath; + return *QCoreApplicationPrivate::cachedApplicationFilePath; #elif defined(Q_OS_MAC) QString qAppFileName_str = qAppFileName(); if(!qAppFileName_str.isEmpty()) { QFileInfo fi(qAppFileName_str); - d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString(); - return d->cachedApplicationFilePath; + if (fi.exists()) { + QCoreApplicationPrivate::setApplicationFilePath(fi.canonicalFilePath()); + return *QCoreApplicationPrivate::cachedApplicationFilePath; + } + return QString(); } #endif #if defined( Q_OS_UNIX ) @@ -2002,8 +2024,8 @@ QString QCoreApplication::applicationFilePath() // the absolute path of the executable QFileInfo pfi(QString::fromLatin1("/proc/%1/exe").arg(getpid())); if (pfi.exists() && pfi.isSymLink()) { - d->cachedApplicationFilePath = pfi.canonicalFilePath(); - return d->cachedApplicationFilePath; + QCoreApplicationPrivate::setApplicationFilePath(pfi.canonicalFilePath()); + return *QCoreApplicationPrivate::cachedApplicationFilePath; } # endif if (!arguments().isEmpty()) { @@ -2033,13 +2055,15 @@ QString QCoreApplication::applicationFilePath() absPath = QDir::cleanPath(absPath); QFileInfo fi(absPath); - d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString(); - } else { - d->cachedApplicationFilePath = QString(); + if (fi.exists()) { + QCoreApplicationPrivate::setApplicationFilePath(fi.canonicalFilePath()); + return *QCoreApplicationPrivate::cachedApplicationFilePath; + } } - return d->cachedApplicationFilePath; + return QString(); #endif + Q_UNREACHABLE(); } /*! diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index 4b57a7b67d..0c00f396b5 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -83,7 +83,6 @@ public: ~QCoreApplicationPrivate(); QString appName() const; - mutable QString applicationName; #ifdef Q_OS_MAC static QString macMenuBarName(); @@ -140,7 +139,9 @@ public: QCoreApplicationPrivate::Type application_type; QString cachedApplicationDirPath; - QString cachedApplicationFilePath; + static QString *cachedApplicationFilePath; + static void setApplicationFilePath(const QString &path); + static inline void clearApplicationFilePath() { delete cachedApplicationFilePath; cachedApplicationFilePath = 0; } #ifndef QT_NO_QOBJECT bool in_exec; diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 418074dc7a..65ca6b0dcb 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -831,6 +831,11 @@ QString decodeMSG(const MSG& msg) } break; #endif +#ifdef WM_INPUTLANGCHANGE + case WM_INPUTLANGCHANGE: + parameters = QStringLiteral("Keyboard layout changed"); + break; +#endif // WM_INPUTLANGCHANGE #ifdef WM_NCACTIVATE case WM_NCACTIVATE: { diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp index b9137ec139..a52cc60eaa 100644 --- a/src/corelib/kernel/qeventdispatcher_blackberry.cpp +++ b/src/corelib/kernel/qeventdispatcher_blackberry.cpp @@ -237,9 +237,6 @@ void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifie return; } - // Call the base Unix implementation. Needed to allow select() to be called correctly - QEventDispatcherUNIX::registerSocketNotifier(notifier); - // Register the fd with bps BpsChannelScopeSwitcher channelSwitcher(d->bps_channel); int io_events = ioEvents(sockfd); @@ -265,6 +262,9 @@ void QEventDispatcherBlackberry::registerSocketNotifier(QSocketNotifier *notifie const int result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data()); if (Q_UNLIKELY(result != BPS_SUCCESS)) qWarning() << "QEventDispatcherBlackberry: bps_add_fd failed"; + + // Call the base Unix implementation. Needed to allow select() to be called correctly + QEventDispatcherUNIX::registerSocketNotifier(notifier); } void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notifier) @@ -280,23 +280,22 @@ void QEventDispatcherBlackberry::unregisterSocketNotifier(QSocketNotifier *notif return; } - // Allow the base Unix implementation to unregister the fd too + // Allow the base Unix implementation to unregister the fd too (before call to ioEvents()!) QEventDispatcherUNIX::unregisterSocketNotifier(notifier); // Unregister the fd with bps BpsChannelScopeSwitcher channelSwitcher(d->bps_channel); - const int io_events = ioEvents(sockfd); int result = bps_remove_fd(sockfd); if (Q_UNLIKELY(result != BPS_SUCCESS)) qWarning() << "QEventDispatcherBlackberry: bps_remove_fd failed" << sockfd; - // if no other socket notifier is watching sockfd, our job ends here - if (!io_events) - return; - - result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data()); - if (Q_UNLIKELY(result != BPS_SUCCESS)) - qWarning("QEventDispatcherBlackberry: bps_add_fd error"); + const int io_events = ioEvents(sockfd); + // if other socket notifier is watching sockfd, readd it + if (io_events) { + result = bps_add_fd(sockfd, io_events, &bpsIOHandler, d->ioData.data()); + if (Q_UNLIKELY(result != BPS_SUCCESS)) + qWarning("QEventDispatcherBlackberry: bps_add_fd error"); + } } static inline int timespecToMillisecs(const timespec &tv) diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp index 54cd2b5a75..4e06d12aee 100644 --- a/src/corelib/kernel/qjni.cpp +++ b/src/corelib/kernel/qjni.cpp @@ -162,24 +162,31 @@ static jfieldID getCachedFieldID(JNIEnv *env, return id; } -Q_GLOBAL_STATIC(QThreadStorage<int>, refCount) +class QJNIEnvironmentPrivateTLS +{ +public: + inline ~QJNIEnvironmentPrivateTLS() + { + QtAndroidPrivate::javaVM()->DetachCurrentThread(); + } +}; + +Q_GLOBAL_STATIC(QThreadStorage<QJNIEnvironmentPrivateTLS *>, jniEnvTLS) QJNIEnvironmentPrivate::QJNIEnvironmentPrivate() : jniEnv(0) { JavaVM *vm = QtAndroidPrivate::javaVM(); if (vm->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) == JNI_EDETACHED) { - if (vm->AttachCurrentThread(&jniEnv, 0) < 0) + if (vm->AttachCurrentThread(&jniEnv, 0) != JNI_OK) return; } if (!jniEnv) return; - if (!refCount->hasLocalData()) - refCount->setLocalData(1); - else - refCount->setLocalData(refCount->localData() + 1); + if (!jniEnvTLS->hasLocalData()) + jniEnvTLS->setLocalData(new QJNIEnvironmentPrivateTLS); } JNIEnv *QJNIEnvironmentPrivate::operator->() @@ -194,16 +201,6 @@ QJNIEnvironmentPrivate::operator JNIEnv* () const QJNIEnvironmentPrivate::~QJNIEnvironmentPrivate() { - if (!jniEnv) - return; - - const int newRef = refCount->localData() - 1; - refCount->setLocalData(newRef); - - if (newRef == 0) - QtAndroidPrivate::javaVM()->DetachCurrentThread(); - - jniEnv = 0; } QJNIObjectData::QJNIObjectData() @@ -354,7 +351,9 @@ QJNIObjectPrivate::QJNIObjectPrivate(jobject obj) QJNIEnvironmentPrivate env; d->m_jobject = env->NewGlobalRef(obj); - d->m_jclass = static_cast<jclass>(env->NewGlobalRef(env->GetObjectClass(d->m_jobject))); + jclass objectClass = env->GetObjectClass(d->m_jobject); + d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass)); + env->DeleteLocalRef(objectClass); } template <> @@ -1265,7 +1264,10 @@ QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod(const char *methodName, if (id) { res = env->CallObjectMethodV(d->m_jobject, id, args); } - return res; + + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } QJNIObjectPrivate QJNIObjectPrivate::callObjectMethod(const char *methodName, @@ -1342,7 +1344,9 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(const char *classNam } } - return res; + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(const char *className, @@ -1369,7 +1373,9 @@ QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(jclass clazz, res = env->CallStaticObjectMethodV(clazz, id, args); } - return res; + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } QJNIObjectPrivate QJNIObjectPrivate::callStaticObjectMethod(jclass clazz, @@ -1681,7 +1687,9 @@ QJNIObjectPrivate QJNIObjectPrivate::getObjectField(const char *fieldName, if (id) res = env->GetObjectField(d->m_jobject, id); - return res; + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(const char *className, @@ -1707,7 +1715,9 @@ QJNIObjectPrivate QJNIObjectPrivate::getStaticObjectField(jclass clazz, if (id) res = env->GetStaticObjectField(clazz, id); - return res; + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } template <> @@ -2109,7 +2119,9 @@ QJNIObjectPrivate QJNIObjectPrivate::fromString(const QString &string) QJNIEnvironmentPrivate env; jstring res = env->NewString(reinterpret_cast<const jchar*>(string.constData()), string.length()); - return res; + QJNIObjectPrivate obj(res); + env->DeleteLocalRef(res); + return obj; } QString QJNIObjectPrivate::toString() const diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h index c5bbae26b9..ab98aec1bf 100644 --- a/src/corelib/kernel/qjni_p.h +++ b/src/corelib/kernel/qjni_p.h @@ -180,7 +180,9 @@ public: d = QSharedPointer<QJNIObjectData>(new QJNIObjectData()); QJNIEnvironmentPrivate env; d->m_jobject = env->NewGlobalRef(jobj); - d->m_jclass = static_cast<jclass>(env->NewGlobalRef(env->GetObjectClass(jobj))); + jclass objectClass = env->GetObjectClass(jobj); + d->m_jclass = static_cast<jclass>(env->NewGlobalRef(objectClass)); + env->DeleteLocalRef(objectClass); } return *this; diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index fbcd0606e6..9ec491f6a9 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -94,7 +94,9 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) return JNI_ERR; g_jClassLoader = env->NewGlobalRef(classLoader); + env->DeleteLocalRef(classLoader); g_jActivity = env->NewGlobalRef(activity); + env->DeleteLocalRef(activity); g_javaVM = vm; return JNI_OK; diff --git a/src/corelib/kernel/qmath.cpp b/src/corelib/kernel/qmath.cpp index 8f900e2101..b1860fa24a 100644 --- a/src/corelib/kernel/qmath.cpp +++ b/src/corelib/kernel/qmath.cpp @@ -310,8 +310,6 @@ const qreal qt_sine_table[QT_SINE_TABLE_SIZE] = { \brief The <QtMath> header file includes generic math declarations. - The global declarations include \l{functions}. - These functions are partly convenience definitions for basic operations, for instance not available in the Standard Template Library et al. diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 72ce941b6e..29c5a3dd24 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -177,6 +178,7 @@ private: void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; +void (*QAbstractDeclarativeData::destroyed_qml1)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; void (*QAbstractDeclarativeData::signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **) = 0; int (*QAbstractDeclarativeData::receivers)(QAbstractDeclarativeData *, const QObject *, int) = 0; @@ -639,7 +641,7 @@ void QMetaCallEvent::placeMetaCall(QObject *object) \li When a QObject is moved to another thread, all its children will be automatically moved too. \li moveToThread() will fail if the QObject has a parent. - \li If \l{QObject}s are created within QThread::run(), they cannot + \li If QObjects are created within QThread::run(), they cannot become children of the QThread object because the QThread does not live in the thread that calls QThread::run(). \endlist @@ -878,8 +880,12 @@ QObject::~QObject() } } - if (d->declarativeData) - QAbstractDeclarativeData::destroyed(d->declarativeData, this); + if (d->declarativeData) { + if (QAbstractDeclarativeData::destroyed) + QAbstractDeclarativeData::destroyed(d->declarativeData, this); + if (QAbstractDeclarativeData::destroyed_qml1) + QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this); + } // set ref to zero to indicate that this object has been deleted if (d->currentSender != 0) @@ -920,9 +926,9 @@ QObject::~QObject() // The destroy operation must happen outside the lock if (c->isSlotObject) { + c->isSlotObject = false; locker.unlock(); c->slotObj->destroyIfLastRef(); - c->isSlotObject = false; locker.relock(); } c->deref(); @@ -937,15 +943,29 @@ QObject::~QObject() d->connectionLists = 0; } - // disconnect all senders + /* Disconnect all senders: + * This loop basically just does + * for (node = d->senders; node; node = node->next) { ... } + * + * We need to temporarily unlock the receiver mutex to destroy the functors or to lock the + * sender's mutex. And when the mutex is released, node->next might be destroyed by another + * thread. That's why we set node->prev to &node, that way, if node is destroyed, node will + * be updated. + */ QObjectPrivate::Connection *node = d->senders; while (node) { QObject *sender = node->sender; + // Send disconnectNotify before removing the connection from sender's connection list. + // This ensures any eventual destructor of sender will block on getting receiver's lock + // and not finish until we release it. + sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), node->signal_index)); QMutex *m = signalSlotLock(sender); node->prev = &node; bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); //the node has maybe been removed while the mutex was unlocked in relock? if (!node || node->sender != sender) { + // We hold the wrong mutex + Q_ASSERT(needToUnlock); m->unlock(); continue; } @@ -954,8 +974,6 @@ QObject::~QObject() if (senderLists) senderLists->dirty = true; - int signal_index = node->signal_index; - QtPrivate::QSlotObjectBase *slotObj = Q_NULLPTR; if (node->isSlotObject) { slotObj = node->slotObj; @@ -967,12 +985,12 @@ QObject::~QObject() m->unlock(); if (slotObj) { + if (node) + node->prev = &node; locker.unlock(); slotObj->destroyIfLastRef(); locker.relock(); } - - sender->disconnectNotify(QMetaObjectPrivate::signal(sender->metaObject(), signal_index)); } } @@ -1557,12 +1575,12 @@ int QObject::startTimer(int interval, Qt::TimerType timerType) Q_D(QObject); if (interval < 0) { - qWarning("QObject::startTimer: QTimer cannot have a negative interval"); + qWarning("QObject::startTimer: Timers cannot have negative intervals"); return 0; } if (!d->threadData->eventDispatcher.load()) { - qWarning("QObject::startTimer: QTimer can only be used with threads started with QThread"); + qWarning("QObject::startTimer: Timers can only be used with threads started with QThread"); return 0; } int timerId = d->threadData->eventDispatcher.load()->registerTimer(interval, timerType, this); @@ -1931,7 +1949,7 @@ void QObjectPrivate::setParent_helper(QObject *o) } } } - if (!isDeletingChildren && declarativeData) + if (!isDeletingChildren && declarativeData && QAbstractDeclarativeData::parentChanged) QAbstractDeclarativeData::parentChanged(declarativeData, q, o); } @@ -3236,7 +3254,7 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, && (slot == 0 || (c->isSlotObject && c->slotObj->compare(slot)))))) { bool needToUnlock = false; QMutex *receiverMutex = 0; - if (!receiver) { + if (c->receiver) { receiverMutex = signalSlotLock(c->receiver); // need to relock this receiver and sender in the correct order needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex); @@ -3253,9 +3271,9 @@ bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c, c->receiver = 0; if (c->isSlotObject) { + c->isSlotObject = false; senderMutex->unlock(); c->slotObj->destroyIfLastRef(); - c->isSlotObject = false; senderMutex->lock(); } @@ -3284,8 +3302,7 @@ bool QMetaObjectPrivate::disconnect(const QObject *sender, QObject *s = const_cast<QObject *>(sender); QMutex *senderMutex = signalSlotLock(sender); - QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0; - QOrderedMutexLocker locker(senderMutex, receiverMutex); + QMutexLocker locker(senderMutex); QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists; if (!connectionLists) @@ -4213,7 +4230,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) { \macro Q_INVOKABLE \relates QObject - Apply this macro to definitions of member functions to allow them to + Apply this macro to declarations of member functions to allow them to be invoked via the meta-object system. The macro is written before the return type, as shown in the following example: @@ -4230,7 +4247,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) { \macro Q_REVISION \relates QObject - Apply this macro to definitions of member functions to tag them with a + Apply this macro to declarations of member functions to tag them with a revision number in the meta-object system. The macro is written before the return type, as shown in the following example: @@ -4695,7 +4712,7 @@ bool QObjectPrivate::disconnect(const QObject *sender, int signal_index, void ** It can be used to disconnect that connection, or check if the connection was successful - \sa QObject::disconnect + \sa QObject::disconnect() */ /*! diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h index 1bbd548be6..d2996e6e4d 100644 --- a/src/corelib/kernel/qobject_impl.h +++ b/src/corelib/kernel/qobject_impl.h @@ -99,6 +99,8 @@ namespace QtPrivate { template <typename ArgList, bool Declared = TypesAreDeclaredMetaType<ArgList>::Value > struct ConnectionTypes { static const int *types() { return 0; } }; + template <> struct ConnectionTypes<List<>, true> + { static const int *types() { return 0; } }; template <typename... Args> struct ConnectionTypes<List<Args...>, true> { static const int *types() { static const int t[sizeof...(Args) + 1] = { (QtPrivate::QMetaTypeIdHelper<Args>::qt_metatype_id())..., 0 }; return t; } }; #endif diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index f5745515c9..cd2d592cec 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -90,6 +90,7 @@ class Q_CORE_EXPORT QAbstractDeclarativeData { public: static void (*destroyed)(QAbstractDeclarativeData *, QObject *); + static void (*destroyed_qml1)(QAbstractDeclarativeData *, QObject *); static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *); static void (*signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **); static int (*receivers)(QAbstractDeclarativeData *, const QObject *, int); diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index db3b96d202..91ccf3996e 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -221,6 +222,19 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok) return qlonglong(qMetaTypeUNumber(d)); } + if (QMetaType::typeFlags(d->type) & QMetaType::IsEnumeration) { + switch (QMetaType::sizeOf(d->type)) { + case 1: + return d->is_shared ? *reinterpret_cast<signed char *>(d->data.shared->ptr) : d->data.sc; + case 2: + return d->is_shared ? *reinterpret_cast<qint16 *>(d->data.shared->ptr) : d->data.s; + case 4: + return d->is_shared ? *reinterpret_cast<qint32 *>(d->data.shared->ptr) : d->data.i; + case 8: + return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ll; + } + } + *ok = false; return Q_INT64_C(0); } @@ -256,6 +270,19 @@ static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok) return qMetaTypeUNumber(d); } + if (QMetaType::typeFlags(d->type) & QMetaType::IsEnumeration) { + switch (QMetaType::sizeOf(d->type)) { + case 1: + return d->is_shared ? *reinterpret_cast<uchar *>(d->data.shared->ptr) : d->data.uc; + case 2: + return d->is_shared ? *reinterpret_cast<quint16 *>(d->data.shared->ptr) : d->data.us; + case 4: + return d->is_shared ? *reinterpret_cast<quint32 *>(d->data.shared->ptr) : d->data.u; + case 8: + return d->is_shared ? *reinterpret_cast<qint64 *>(d->data.shared->ptr) : d->data.ull; + } + } + *ok = false; return Q_UINT64_C(0); } @@ -888,15 +915,13 @@ static bool customCompare(const QVariant::Private *a, const QVariant::Private *b static bool customConvert(const QVariant::Private *d, int t, void *result, bool *ok) { if (d->type >= QMetaType::User || t >= QMetaType::User) { - const bool isOk = QMetaType::convert(constData(*d), d->type, result, t); - if (ok) - *ok = isOk; - return isOk; + if (QMetaType::convert(constData(*d), d->type, result, t)) { + if (ok) + *ok = true; + return true; + } } - - if (ok) - *ok = false; - return false; + return convert(d, t, result, ok); } #if !defined(QT_NO_DEBUG_STREAM) @@ -2854,8 +2879,13 @@ bool QVariant::canConvert(int targetTypeId) const if (targetTypeId < 0) return false; - if (targetTypeId >= QMetaType::User) - return canConvertMetaObject(currentType, targetTypeId, d.data.o); + if (targetTypeId >= QMetaType::User) { + if (QMetaType::typeFlags(targetTypeId) & QMetaType::IsEnumeration) { + targetTypeId = QMetaType::Int; + } else { + return canConvertMetaObject(currentType, targetTypeId, d.data.o); + } + } if (currentType == QMetaType::QJsonValue) { switch (targetTypeId) { @@ -2888,13 +2918,16 @@ bool QVariant::canConvert(int targetTypeId) const return true; // fall through case QVariant::UInt: + case QVariant::LongLong: + case QVariant::ULongLong: return currentType == QMetaType::ULong || currentType == QMetaType::Long || currentType == QMetaType::UShort || currentType == QMetaType::UChar || currentType == QMetaType::Char || currentType == QMetaType::SChar - || currentType == QMetaType::Short; + || currentType == QMetaType::Short + || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration; case QVariant::Image: return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap; case QVariant::Pixmap: @@ -2923,7 +2956,9 @@ bool QVariant::canConvert(int targetTypeId) const case QMetaType::ULong: case QMetaType::Short: case QMetaType::UShort: - return qCanConvertMatrix[QVariant::Int] & (1 << currentType) || currentType == QVariant::Int; + return qCanConvertMatrix[QVariant::Int] & (1 << currentType) + || currentType == QVariant::Int + || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration; case QMetaType::QObjectStar: return canConvertMetaObject(currentType, targetTypeId, d.data.o); default: @@ -2974,7 +3009,8 @@ bool QVariant::convert(int targetTypeId) } bool isOk = true; - if (!handlerManager[d.type]->convert(&oldValue.d, targetTypeId, data(), &isOk)) + int converterType = std::max(oldValue.userType(), targetTypeId); + if (!handlerManager[converterType]->convert(&oldValue.d, targetTypeId, data(), &isOk)) isOk = false; d.is_null = !isOk; return isOk; diff --git a/src/corelib/kernel/qwineventnotifier.h b/src/corelib/kernel/qwineventnotifier.h index 56605d9aaa..cddb9d73be 100644 --- a/src/corelib/kernel/qwineventnotifier.h +++ b/src/corelib/kernel/qwineventnotifier.h @@ -45,7 +45,6 @@ #include "QtCore/qobject.h" #ifdef Q_OS_WIN -#include "QtCore/qt_windows.h" QT_BEGIN_NAMESPACE @@ -54,6 +53,7 @@ class Q_CORE_EXPORT QWinEventNotifier : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QWinEventNotifier) + typedef Qt::HANDLE HANDLE; public: explicit QWinEventNotifier(QObject *parent = 0); |