summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/kernel.pri4
-rw-r--r--src/corelib/kernel/qcfsocketnotifier.cpp6
-rw-r--r--src/corelib/kernel/qcore_mac.cpp1
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm34
-rw-r--r--src/corelib/kernel/qcore_mac_p.h177
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp83
-rw-r--r--src/corelib/kernel/qcoreapplication.h8
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp642
-rw-r--r--src/corelib/kernel/qcoreevent.cpp8
-rw-r--r--src/corelib/kernel/qcoreglobaldata.cpp5
-rw-r--r--src/corelib/kernel/qdeadlinetimer.cpp1
-rw-r--r--src/corelib/kernel/qdeadlinetimer.h5
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf.mm70
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf_p.h36
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp31
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp22
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt_p.h1
-rw-r--r--src/corelib/kernel/qeventloop.cpp6
-rw-r--r--src/corelib/kernel/qmetaobject.cpp104
-rw-r--r--src/corelib/kernel/qmetaobject.h1
-rw-r--r--src/corelib/kernel/qmetaobject_p.h3
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp49
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h3
-rw-r--r--src/corelib/kernel/qmetatype.cpp43
-rw-r--r--src/corelib/kernel/qmetatype.h17
-rw-r--r--src/corelib/kernel/qmetatype_p.h4
-rw-r--r--src/corelib/kernel/qobject.cpp27
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h32
-rw-r--r--src/corelib/kernel/qsystemerror.cpp4
-rw-r--r--src/corelib/kernel/qtcore_eval.cpp2
-rw-r--r--src/corelib/kernel/qtestsupport_core.cpp126
-rw-r--r--src/corelib/kernel/qtestsupport_core.h92
-rw-r--r--src/corelib/kernel/qtimer.cpp42
-rw-r--r--src/corelib/kernel/qtimer.h17
-rw-r--r--src/corelib/kernel/qtranslator.cpp15
-rw-r--r--src/corelib/kernel/qvariant.cpp364
-rw-r--r--src/corelib/kernel/qvariant.h2
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp7
-rw-r--r--src/corelib/kernel/qwineventnotifier.h2
39 files changed, 1503 insertions, 593 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index c528b16f9c..3f7bf3cd47 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -43,6 +43,7 @@ HEADERS += \
kernel/qsystemerror_p.h \
kernel/qmetatype_p.h \
kernel/qmetatypeswitcher_p.h \
+ kernel/qtestsupport_core.h
SOURCES += \
kernel/qabstracteventdispatcher.cpp \
@@ -69,7 +70,8 @@ SOURCES += \
kernel/qsystemsemaphore.cpp \
kernel/qpointer.cpp \
kernel/qmath.cpp \
- kernel/qsystemerror.cpp
+ kernel/qsystemerror.cpp \
+ kernel/qtestsupport_core.cpp
win32 {
SOURCES += \
diff --git a/src/corelib/kernel/qcfsocketnotifier.cpp b/src/corelib/kernel/qcfsocketnotifier.cpp
index 1fee2aa5fc..920ec9cd86 100644
--- a/src/corelib/kernel/qcfsocketnotifier.cpp
+++ b/src/corelib/kernel/qcfsocketnotifier.cpp
@@ -86,7 +86,7 @@ CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
if (!loopSource)
return 0;
- CFRunLoopAddSource(CFRunLoopGetMain(), loopSource, kCFRunLoopCommonModes);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), loopSource, kCFRunLoopCommonModes);
return loopSource;
}
@@ -96,7 +96,7 @@ CFRunLoopSourceRef qt_mac_add_socket_to_runloop(const CFSocketRef socket)
void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSourceRef runloop)
{
Q_ASSERT(runloop);
- CFRunLoopRemoveSource(CFRunLoopGetMain(), runloop, kCFRunLoopCommonModes);
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runloop, kCFRunLoopCommonModes);
CFSocketDisableCallBacks(socket, kCFSocketReadCallBack);
CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack);
}
@@ -188,7 +188,7 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier)
enableNotifiersObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeSources,
true, 0, enableSocketNotifiers, &context);
Q_ASSERT(enableNotifiersObserver);
- CFRunLoopAddObserver(CFRunLoopGetMain(), enableNotifiersObserver, kCFRunLoopCommonModes);
+ CFRunLoopAddObserver(CFRunLoopGetCurrent(), enableNotifiersObserver, kCFRunLoopCommonModes);
}
}
diff --git a/src/corelib/kernel/qcore_mac.cpp b/src/corelib/kernel/qcore_mac.cpp
index b5df0db232..58380001a4 100644
--- a/src/corelib/kernel/qcore_mac.cpp
+++ b/src/corelib/kernel/qcore_mac.cpp
@@ -42,6 +42,7 @@
#include "qhash.h"
#include "qpair.h"
+#include "qmutex.h"
#include "qvarlengtharray.h"
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index 6b11e90a4e..2e303607df 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -40,8 +40,13 @@
#include <private/qcore_mac_p.h>
-#ifdef Q_OS_OSX
-#include <AppKit/NSText.h>
+#ifdef Q_OS_MACOS
+# include <AppKit/AppKit.h>
+# if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
+@interface NSApplication (MojaveForwardDeclarations)
+@property (strong) NSAppearance *effectiveAppearance NS_AVAILABLE_MAC(10_14);
+@end
+# endif
#endif
#if defined(QT_PLATFORM_UIKIT)
@@ -91,19 +96,20 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TY
QT_END_NAMESPACE
QT_USE_NAMESPACE
@interface QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker) : NSObject
-{
+@end
+
+@implementation QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker) {
NSAutoreleasePool **m_pool;
}
--(id)initWithPool:(NSAutoreleasePool**)pool;
-@end
-@implementation QT_MANGLE_NAMESPACE(QMacAutoReleasePoolTracker)
--(id)initWithPool:(NSAutoreleasePool**)pool
+
+- (instancetype)initWithPool:(NSAutoreleasePool **)pool
{
- if (self = [super init])
+ if ((self = [self init]))
m_pool = pool;
return self;
}
--(void)dealloc
+
+- (void)dealloc
{
if (*m_pool) {
// The pool is still valid, which means we're not being drained from
@@ -165,6 +171,16 @@ QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool)
}
#endif // !QT_NO_DEBUG_STREAM
+#ifdef Q_OS_MACOS
+bool qt_mac_applicationIsInDarkMode()
+{
+ if (__builtin_available(macOS 10.14, *))
+ return [NSApp.effectiveAppearance.name hasSuffix:@"DarkAqua"];
+ else
+ return false;
+}
+#endif
+
bool qt_apple_isApplicationExtension()
{
static bool isExtension = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSExtension"];
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index af939abaac..bf540c2e35 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -51,18 +51,50 @@
// We mean it.
//
+#include "private/qglobal_p.h"
+
#ifndef __IMAGECAPTURE__
# define __IMAGECAPTURE__
#endif
+// --------------------------------------------------------------------------
+
+#if !defined(QT_BOOTSTRAPPED) && (QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) || !defined(Q_OS_MACOS))
+#define QT_USE_APPLE_ACTIVITIES
+
+#if defined(OS_ACTIVITY_OBJECT_API)
+#error The file <os/activity.h> has already been included
+#endif
+
+// We runtime-check all use of the activity APIs, so we can safely build
+// with them included, even if the deployment target is macOS 10.11
+#if QT_MACOS_DEPLOYMENT_TARGET_BELOW(__MAC_10_12)
+#undef __MAC_OS_X_VERSION_MIN_REQUIRED
+#define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_12
+#define DID_OVERRIDE_DEPLOYMENT_TARGET
+#endif
+
+#include <os/activity.h>
+#if !OS_ACTIVITY_OBJECT_API
+#error "Expected activity API to be available"
+#endif
+
+#if defined(DID_OVERRIDE_DEPLOYMENT_TARGET)
+#undef __MAC_OS_X_VERSION_MIN_REQUIRED
+#define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_11
+#undef DID_OVERRIDE_DEPLOYMENT_TARGET
+#endif
+
+#endif
+
+// --------------------------------------------------------------------------
+
#if defined(QT_BOOTSTRAPPED)
#include <ApplicationServices/ApplicationServices.h>
#else
#include <CoreFoundation/CoreFoundation.h>
#endif
-#include "private/qglobal_p.h"
-
#ifdef __OBJC__
#include <Foundation/Foundation.h>
#endif
@@ -148,9 +180,10 @@ private:
QString string;
};
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
+Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode();
#endif
#ifndef QT_NO_DEBUG_STREAM
@@ -215,6 +248,144 @@ private:
// --------------------------------------------------------------------------
+#if defined(QT_USE_APPLE_ACTIVITIES)
+
+QT_END_NAMESPACE
+#include <os/availability.h>
+#define OS_ACTIVITY_AVAILABILITY API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
+#define OS_ACTIVITY_AVAILABILITY_CHECK __builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)
+QT_BEGIN_NAMESPACE
+
+template <typename T> using QAppleOsType = QAppleRefCounted<T, void *, os_retain, os_release>;
+
+class Q_CORE_EXPORT QAppleLogActivity
+{
+public:
+ QAppleLogActivity() : activity(nullptr) {}
+ QAppleLogActivity(os_activity_t activity) OS_ACTIVITY_AVAILABILITY : activity(activity) {}
+ ~QAppleLogActivity() { if (activity) leave(); }
+
+ QAppleLogActivity(const QAppleLogActivity &) = delete;
+ QAppleLogActivity& operator=(const QAppleLogActivity &) = delete;
+
+ QAppleLogActivity(QAppleLogActivity&& other)
+ : activity(other.activity), state(other.state) { other.activity = nullptr; }
+
+ QAppleLogActivity& operator=(QAppleLogActivity &&other)
+ {
+ if (this != &other) {
+ activity = other.activity;
+ state = other.state;
+ other.activity = nullptr;
+ }
+ return *this;
+ }
+
+ QAppleLogActivity&& enter()
+ {
+ if (activity) {
+ if (OS_ACTIVITY_AVAILABILITY_CHECK)
+ os_activity_scope_enter(static_cast<os_activity_t>(*this), &state);
+ }
+ return std::move(*this);
+ }
+
+ void leave() {
+ if (activity) {
+ if (OS_ACTIVITY_AVAILABILITY_CHECK)
+ os_activity_scope_leave(&state);
+ }
+ }
+
+ operator os_activity_t() OS_ACTIVITY_AVAILABILITY
+ {
+ return reinterpret_cast<os_activity_t>(static_cast<void *>(activity));
+ }
+
+private:
+ // Work around API_AVAILABLE not working for templates by using void*
+ QAppleOsType<void *> activity;
+ os_activity_scope_state_s state;
+};
+
+#define QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) []() { \
+ if (!(condition)) \
+ return QAppleLogActivity(); \
+ if (OS_ACTIVITY_AVAILABILITY_CHECK) \
+ return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT)); \
+ return QAppleLogActivity(); \
+ }()
+
+#define QT_VA_ARGS_CHOOSE(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N
+#define QT_VA_ARGS_COUNT(...) QT_VA_ARGS_CHOOSE(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)
+
+#define QT_OVERLOADED_MACRO(MACRO, ...) _QT_OVERLOADED_MACRO(MACRO, QT_VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__)
+#define _QT_OVERLOADED_MACRO(MACRO, ARGC) _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC)
+#define _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) MACRO##ARGC
+
+#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(condition, description, parent) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent)
+#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(true, description, parent)
+#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY_WITH_PARENT, __VA_ARGS__)
+
+#define QT_APPLE_LOG_ACTIVITY2(condition, description) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, OS_ACTIVITY_CURRENT)
+#define QT_APPLE_LOG_ACTIVITY1(description) QT_APPLE_LOG_ACTIVITY2(true, description)
+#define QT_APPLE_LOG_ACTIVITY(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY, __VA_ARGS__)
+
+#define QT_APPLE_SCOPED_LOG_ACTIVITY(...) QAppleLogActivity scopedLogActivity = QT_APPLE_LOG_ACTIVITY(__VA_ARGS__).enter();
+
+#else
+// No-ops for macOS 10.11. We don't need to provide QT_APPLE_SCOPED_LOG_ACTIVITY,
+// as all the call sites for that are in code that's only built on 10.12 and above.
+#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...)
+#define QT_APPLE_LOG_ACTIVITY(...)
+#endif // QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE
+
+// -------------------------------------------------------------------------
+
+#if defined( __OBJC__)
+class QMacScopedObserver
+{
+public:
+ QMacScopedObserver() {}
+
+ template<typename Functor>
+ QMacScopedObserver(id object, NSNotificationName name, Functor callback) {
+ observer = [[NSNotificationCenter defaultCenter] addObserverForName:name
+ object:object queue:nil usingBlock:^(NSNotification *) {
+ callback();
+ }
+ ];
+ }
+
+ QMacScopedObserver(const QMacScopedObserver& other) = delete;
+ QMacScopedObserver(QMacScopedObserver&& other) : observer(other.observer) {
+ other.observer = nil;
+ }
+
+ QMacScopedObserver &operator=(const QMacScopedObserver& other) = delete;
+ QMacScopedObserver &operator=(QMacScopedObserver&& other) {
+ if (this != &other) {
+ remove();
+ observer = other.observer;
+ other.observer = nil;
+ }
+ return *this;
+ }
+
+ void remove() {
+ if (observer)
+ [[NSNotificationCenter defaultCenter] removeObserver:observer];
+ observer = nil;
+ }
+ ~QMacScopedObserver() { remove(); }
+
+private:
+ id observer = nil;
+};
+#endif
+
+// -------------------------------------------------------------------------
+
QT_END_NAMESPACE
#endif // QCORE_MAC_P_H
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 4e32f90964..04da52a960 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -58,9 +58,11 @@
#include <qtextcodec.h>
#ifndef QT_NO_QOBJECT
#include <qthread.h>
-#include <qthreadpool.h>
#include <qthreadstorage.h>
#include <private/qthread_p.h>
+#if QT_CONFIG(thread)
+#include <qthreadpool.h>
+#endif
#endif
#include <qelapsedtimer.h>
#include <qlibraryinfo.h>
@@ -268,9 +270,7 @@ typedef QList<QtStartUpFunction> QStartUpFuncList;
Q_GLOBAL_STATIC(QStartUpFuncList, preRList)
typedef QList<QtCleanUpFunction> QVFuncList;
Q_GLOBAL_STATIC(QVFuncList, postRList)
-#ifndef QT_NO_QOBJECT
static QBasicMutex globalRoutinesMutex;
-#endif
/*!
\internal
@@ -289,9 +289,7 @@ void qAddPreRoutine(QtStartUpFunction p)
// Due to C++11 parallel dynamic initialization, this can be called
// from multiple threads.
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines
}
@@ -300,9 +298,7 @@ void qAddPostRoutine(QtCleanUpFunction p)
QVFuncList *list = postRList();
if (!list)
return;
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
list->prepend(p);
}
@@ -311,9 +307,7 @@ void qRemovePostRoutine(QtCleanUpFunction p)
QVFuncList *list = postRList();
if (!list)
return;
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
list->removeAll(p);
}
@@ -324,9 +318,7 @@ static void qt_call_pre_routines()
QVFuncList list;
{
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
// Unlike qt_call_post_routines, we don't empty the list, because
// Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects
// the function to be executed every time QCoreApplication is created.
@@ -345,9 +337,7 @@ void Q_CORE_EXPORT qt_call_post_routines()
QVFuncList list;
{
// extract the current list and make the stored list empty
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
qSwap(*postRList, list);
}
@@ -513,7 +503,7 @@ QCoreApplicationPrivate::~QCoreApplicationPrivate()
void QCoreApplicationPrivate::cleanupThreadData()
{
if (threadData && !threadData_clean) {
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
void *data = &threadData->tls;
QThreadStorageData::finish((void **)data);
#endif
@@ -540,7 +530,7 @@ void QCoreApplicationPrivate::createEventDispatcher()
Q_Q(QCoreApplication);
QThreadData *data = QThreadData::current();
Q_ASSERT(!data->hasEventDispatcher());
- eventDispatcher = QThreadPrivate::createEventDispatcher(data);
+ eventDispatcher = data->createEventDispatcher();
eventDispatcher->setParent(q);
}
@@ -777,7 +767,7 @@ QCoreApplication::QCoreApplication(int &argc, char **argv
void QCoreApplicationPrivate::init()
{
- Q_TRACE(qcoreapplicationprivate_init_entry);
+ Q_TRACE(QCoreApplicationPrivate_init_entry);
#if defined(Q_OS_MACOS)
QMacAutoReleasePool pool;
@@ -872,7 +862,7 @@ void QCoreApplicationPrivate::init()
is_app_running = true; // No longer starting up.
#endif
- Q_TRACE(qcoreapplicationprivate_init_exit);
+ Q_TRACE(QCoreApplicationPrivate_init_exit);
}
/*!
@@ -888,7 +878,7 @@ QCoreApplication::~QCoreApplication()
QCoreApplicationPrivate::is_app_running = false;
#endif
-#if !defined(QT_NO_THREAD)
+#if QT_CONFIG(thread)
// Synchronize and stop the global thread pool threads.
QThreadPool *globalThreadPool = 0;
QT_TRY {
@@ -1185,16 +1175,31 @@ bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, Q
*/
bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
{
+ // Note: when adjusting the tracepoints in here
+ // consider adjusting QApplicationPrivate::notify_helper too.
+ Q_TRACE(QCoreApplication_notify_entry, receiver, event, event->type());
+
// send to all application event filters (only does anything in the main thread)
if (QCoreApplication::self
&& receiver->d_func()->threadData->thread == mainThread()
- && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event))
+ && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
+ Q_TRACE(QCoreApplication_notify_event_filtered, receiver, event, event->type());
return true;
+ }
// send to all receiver event filters
- if (sendThroughObjectEventFilters(receiver, event))
+ if (sendThroughObjectEventFilters(receiver, event)) {
+ Q_TRACE(QCoreApplication_notify_event_filtered, receiver, event, event->type());
return true;
+ }
+
+ Q_TRACE(QCoreApplication_notify_before_delivery, receiver, event, event->type());
+
// deliver the event
- return receiver->event(event);
+ const bool consumed = receiver->event(event);
+
+ Q_TRACE(QCoreApplication_notify_after_delivery, receiver, event, event->type(), consumed);
+
+ return consumed;
}
/*!
@@ -1399,6 +1404,7 @@ void QCoreApplication::exit(int returnCode)
QCoreApplication management of posted events
*****************************************************************************/
+#ifndef QT_NO_QOBJECT
/*!
\fn bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
@@ -1413,6 +1419,28 @@ void QCoreApplication::exit(int returnCode)
\sa postEvent(), notify()
*/
+bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
+{
+ Q_TRACE(QCoreApplication_sendEvent, receiver, event, event->type());
+
+ if (event)
+ event->spont = false;
+ return notifyInternal2(receiver, event);
+}
+
+/*!
+ \internal
+*/
+bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
+{
+ Q_TRACE(QCoreApplication_sendSpontaneousEvent, receiver, event, event->type());
+
+ if (event)
+ event->spont = true;
+ return notifyInternal2(receiver, event);
+}
+
+#endif // QT_NO_QOBJECT
/*!
\since 4.3
@@ -1441,6 +1469,8 @@ void QCoreApplication::exit(int returnCode)
*/
void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
{
+ Q_TRACE(QCoreApplication_postEvent_entry, receiver, event, event->type());
+
if (receiver == 0) {
qWarning("QCoreApplication::postEvent: Unexpected null receiver");
delete event;
@@ -1477,6 +1507,7 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
// if this is one of the compressible events, do compression
if (receiver->d_func()->postedEvents
&& self && self->compressEvent(event, receiver, &data->postEventList)) {
+ Q_TRACE(QCoreApplication_postEvent_event_compressed, receiver, event);
return;
}
@@ -1508,6 +1539,7 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
// delete the event on exceptions to protect against memory leaks till the event is
// properly owned in the postEventList
QScopedPointer<QEvent> eventDeleter(event);
+ Q_TRACE(QCoreApplication_postEvent_event_posted, receiver, event, event->type());
data->postEventList.addEvent(QPostEvent(receiver, event, priority));
eventDeleter.take();
event->posted = true;
@@ -1766,8 +1798,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
If \a receiver is null, the events of \a eventType are removed for
all objects. If \a eventType is 0, all the events are removed for
\a receiver. You should never call this function with \a eventType
- of 0. If you do call it in this way, be aware that killing events
- may cause \a receiver to break one or more invariants.
+ of 0.
\threadsafe
*/
@@ -1818,9 +1849,7 @@ void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
}
locker.unlock();
- for (int i = 0; i < events.count(); ++i) {
- delete events[i];
- }
+ qDeleteAll(events);
}
/*!
@@ -1889,7 +1918,7 @@ bool QCoreApplication::event(QEvent *e)
\value UnicodeUTF8 UTF-8.
\omitvalue Latin1
- \omitvalue DefaultCodec UTF-8.
+ \omitvalue DefaultCodec \omit UTF-8. \endomit
\omitvalue CodecForTr
\sa QObject::tr(), QString::fromUtf8()
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index a886c9d1d2..3581970765 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -229,14 +229,6 @@ private:
friend class QClassFactory;
};
-#ifndef QT_NO_QOBJECT
-inline bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
-{ if (event) event->spont = false; return notifyInternal2(receiver, event); }
-
-inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
-{ if (event) event->spont = true; return notifyInternal2(receiver, event); }
-#endif
-
#ifdef QT_NO_DEPRECATED
# define QT_DECLARE_DEPRECATED_TR_FUNCTIONS(context)
#else
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 00548365d2..0109e2c658 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -192,7 +192,7 @@ Q_CORE_EXPORT int qWinAppCmdShow() // get main window sho
#if defined(Q_OS_WIN) && !defined(QT_NO_DEBUG_STREAM)
/*****************************************************************************
Convenience functions for convert WM_* messages into human readable strings,
- including a nifty QDebug operator<< for simpel QDebug() << msg output.
+ including a nifty QDebug operator<< for simple QDebug() << msg output.
*****************************************************************************/
QT_BEGIN_INCLUDE_NAMESPACE
#include <windowsx.h>
@@ -207,10 +207,48 @@ QT_END_INCLUDE_NAMESPACE
// The values below should never change. Note that none of the usual
// WM_...FIRST & WM_...LAST values are in the list, as they normally have other
// WM_... representations
-struct KnownWM {
- uint WM;
- const char* str;
-} knownWM[] =
+
+template <class IntType>
+struct QWinMessageMapping {
+ IntType value;
+ const char *name;
+};
+
+#define FLAG_ENTRY(x) {x, #x} // for populating arrays
+
+// Looks up a value in a list of QWinMessageMapping
+template <class IntType>
+static const char *findWinMessageMapping(const QWinMessageMapping<IntType> *haystack,
+ size_t haystackSize,
+ IntType needle)
+{
+ for (auto p = haystack, end = haystack + haystackSize; p < end; ++p) {
+ if (p->value == needle)
+ return p->name;
+ }
+ return nullptr;
+}
+
+// Format flags using a mapping as "Flag1 | Flag2"...
+template <class IntType>
+static QString flagsValue(const QWinMessageMapping<IntType> *haystack,
+ size_t haystackSize, IntType value)
+{
+ QString result;
+ for (auto p = haystack, end = haystack + haystackSize; p < end; ++p) {
+ if ((p->value & value) == p->value) {
+ if (!result.isEmpty())
+ result += QLatin1String(" | ");
+ result += QLatin1String(p->name);
+ }
+ }
+ return result;
+}
+
+// Looks up the WM_ message in the table inside
+static const char *findWMstr(uint msg)
+{
+ static const QWinMessageMapping<uint> knownWM[] =
{{ 0x0000, "WM_NULL" },
{ 0x0001, "WM_CREATE" },
{ 0x0002, "WM_DESTROY" },
@@ -505,84 +543,146 @@ struct KnownWM {
{ 0x038E, "WM_PENWINFIRST + 14" },
{ 0x038F, "WM_PENWINLAST" },
{ 0x0400, "WM_USER" },
- { 0x8000, "WM_APP" },
- { 0,0 }}; // End of known messages
+ { 0x8000, "WM_APP" }
+ };
-// Looks up the WM_ message in the table above
-static const char* findWMstr(uint msg)
-{
- uint i = 0;
- const char* result = 0;
- // Known WM_'s
- while (knownWM[i].str && (knownWM[i].WM != msg))
- ++i;
- result = knownWM[i].str;
- return result;
-};
+ return findWinMessageMapping(knownWM, sizeof(knownWM) / sizeof(knownWM[0]), msg);
+}
-// Convenience function for converting flags and values into readable strings
-struct FLAG_STRING_STRUCT
+static const char *activateParameter(uint p)
{
- uint value;
- const char* str;
-};
+ static const QWinMessageMapping<uint> activeEnum[] = {
+ {WA_ACTIVE, "Activate"}, {WA_INACTIVE, "Deactivate"},
+ {WA_CLICKACTIVE, "Activate by mouseclick"}
+ };
-FLAG_STRING_STRUCT FLAG_STRING(uint value = 0, const char *c = 0)
+ return findWinMessageMapping(activeEnum, sizeof(activeEnum) / sizeof(activeEnum[0]), p);
+}
+
+static QString styleFlags(uint style)
{
- FLAG_STRING_STRUCT s = {value, c};
- return s;
+ static const QWinMessageMapping<uint> styleFlags[] = {
+ FLAG_ENTRY(WS_BORDER), FLAG_ENTRY(WS_CAPTION), FLAG_ENTRY(WS_CHILD),
+ FLAG_ENTRY(WS_CLIPCHILDREN), FLAG_ENTRY(WS_CLIPSIBLINGS),
+ FLAG_ENTRY(WS_DISABLED), FLAG_ENTRY(WS_DLGFRAME), FLAG_ENTRY(WS_GROUP),
+ FLAG_ENTRY(WS_HSCROLL), FLAG_ENTRY(WS_OVERLAPPED),
+ FLAG_ENTRY(WS_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_ICONIC),
+ FLAG_ENTRY(WS_MAXIMIZE), FLAG_ENTRY(WS_MAXIMIZEBOX),
+ FLAG_ENTRY(WS_MINIMIZE), FLAG_ENTRY(WS_MINIMIZEBOX),
+ FLAG_ENTRY(WS_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_POPUP),
+ FLAG_ENTRY(WS_POPUPWINDOW), FLAG_ENTRY(WS_SIZEBOX),
+ FLAG_ENTRY(WS_SYSMENU), FLAG_ENTRY(WS_TABSTOP), FLAG_ENTRY(WS_THICKFRAME),
+ FLAG_ENTRY(WS_TILED), FLAG_ENTRY(WS_TILEDWINDOW), FLAG_ENTRY(WS_VISIBLE),
+ FLAG_ENTRY(WS_VSCROLL)
+ };
+
+ return flagsValue(styleFlags, sizeof(styleFlags) / sizeof(styleFlags[0]), style);
}
-#define FLGSTR(x) FLAG_STRING(x, #x)
+static QString exStyleFlags(uint exStyle)
+{
+ static const QWinMessageMapping<uint> exStyleFlags[] = {
+ FLAG_ENTRY(WS_EX_ACCEPTFILES), FLAG_ENTRY(WS_EX_APPWINDOW),
+ FLAG_ENTRY(WS_EX_CLIENTEDGE), FLAG_ENTRY(WS_EX_DLGMODALFRAME),
+ FLAG_ENTRY(WS_EX_LEFT), FLAG_ENTRY(WS_EX_LEFTSCROLLBAR),
+ FLAG_ENTRY(WS_EX_LTRREADING), FLAG_ENTRY(WS_EX_MDICHILD),
+ FLAG_ENTRY(WS_EX_NOACTIVATE), FLAG_ENTRY(WS_EX_NOPARENTNOTIFY),
+ FLAG_ENTRY(WS_EX_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_EX_PALETTEWINDOW),
+ FLAG_ENTRY(WS_EX_RIGHT), FLAG_ENTRY(WS_EX_RIGHTSCROLLBAR),
+ FLAG_ENTRY(WS_EX_RTLREADING), FLAG_ENTRY(WS_EX_STATICEDGE),
+ FLAG_ENTRY(WS_EX_TOOLWINDOW), FLAG_ENTRY(WS_EX_TOPMOST),
+ FLAG_ENTRY(WS_EX_TRANSPARENT), FLAG_ENTRY(WS_EX_WINDOWEDGE)
+ };
+
+ return flagsValue(exStyleFlags, sizeof(exStyleFlags) / sizeof(exStyleFlags[0]), exStyle);
+}
-// Returns an ORed (" | ") together string for the flags active in the actual
-// value. (...) must consist of FLAG_STRING, with a FLAG_STRING() as the last
-// value in the list passed to the function
-QString flagCheck(uint actual, ...)
+static const char *imeCommand(uint cmd)
{
- va_list ap;
- va_start(ap, actual);
+ static const QWinMessageMapping<uint> commands[] = {
+ FLAG_ENTRY(IMN_CHANGECANDIDATE), FLAG_ENTRY(IMN_CLOSECANDIDATE),
+ FLAG_ENTRY(IMN_CLOSESTATUSWINDOW), FLAG_ENTRY(IMN_GUIDELINE),
+ FLAG_ENTRY(IMN_OPENCANDIDATE), FLAG_ENTRY(IMN_OPENSTATUSWINDOW),
+ FLAG_ENTRY(IMN_SETCANDIDATEPOS), FLAG_ENTRY(IMN_SETCOMPOSITIONFONT),
+ FLAG_ENTRY(IMN_SETCOMPOSITIONWINDOW), FLAG_ENTRY(IMN_SETCONVERSIONMODE),
+ FLAG_ENTRY(IMN_SETOPENSTATUS), FLAG_ENTRY(IMN_SETSENTENCEMODE),
+ FLAG_ENTRY(IMN_SETSTATUSWINDOWPOS)
+ };
+
+ return findWinMessageMapping(commands, sizeof(commands) / sizeof(commands[0]), cmd);
+}
- QString result;
- int count = 0;
- FLAG_STRING_STRUCT v;
- while((v=va_arg(ap,FLAG_STRING_STRUCT)).str) {
- if ((actual & v.value) == v.value) {
- if (count++)
- result += QLatin1String(" | ");
- result += QString::fromLatin1(v.str);
- }
- }
- va_end(ap);
- return result;
-};
+static QString imeShowFlags(uint flags)
+{
+ static const QWinMessageMapping<uint> showFlags[] = {
+ FLAG_ENTRY(ISC_SHOWUICOMPOSITIONWINDOW),
+ FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW),
+ FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 1),
+ FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 2),
+ FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 3)
+ };
+
+ return flagsValue(showFlags, sizeof(showFlags) / sizeof(showFlags[0]), flags);
+}
-// Returns the string representation of the value in 'actual'. (...) must
-// consist of FLAG_STRING, with a FLAG_STRING() as the last value in the list
-// passed to the function
-QString valueCheck(uint actual, ...)
+static const char *wmSizeParam(uint p)
{
- va_list ap;
- va_start(ap, actual);
+ static const QWinMessageMapping<uint> sizeParams[] = {
+ FLAG_ENTRY(SIZE_MAXHIDE), FLAG_ENTRY(SIZE_MAXIMIZED),
+ FLAG_ENTRY(SIZE_MAXSHOW), FLAG_ENTRY(SIZE_MINIMIZED),
+ FLAG_ENTRY(SIZE_RESTORED)
+ };
- QString result;
- FLAG_STRING_STRUCT v;
- while((v=va_arg(ap,FLAG_STRING_STRUCT)).str && (actual != v.value))
- ;
- result = QString::fromLatin1(v.str);
+ return findWinMessageMapping(sizeParams, sizeof(sizeParams) / sizeof(sizeParams[0]), p);
+}
- va_end(ap);
- return result;
-};
+static QString virtualKeys(uint vk)
+{
+ static const QWinMessageMapping<uint> keys[] = {
+ FLAG_ENTRY(MK_CONTROL), FLAG_ENTRY(MK_LBUTTON), FLAG_ENTRY(MK_MBUTTON),
+ FLAG_ENTRY(MK_RBUTTON), FLAG_ENTRY(MK_SHIFT), FLAG_ENTRY(MK_XBUTTON1),
+ FLAG_ENTRY(MK_XBUTTON2)
+ };
-#ifdef Q_CC_BOR
+ return flagsValue(keys, sizeof(keys) / sizeof(keys[0]), vk);
+}
-QString decodeMSG(const MSG& msg)
+static QString winPosFlags(uint f)
{
- return QString::fromLatin1("THis is not supported on Borland");
+ static const QWinMessageMapping<uint> winPosValues[] = {
+ FLAG_ENTRY(SWP_DRAWFRAME), FLAG_ENTRY(SWP_FRAMECHANGED),
+ FLAG_ENTRY(SWP_HIDEWINDOW), FLAG_ENTRY(SWP_NOACTIVATE),
+ FLAG_ENTRY(SWP_NOCOPYBITS), FLAG_ENTRY(SWP_NOMOVE),
+ FLAG_ENTRY(SWP_NOOWNERZORDER), FLAG_ENTRY(SWP_NOREDRAW),
+ FLAG_ENTRY(SWP_NOREPOSITION), FLAG_ENTRY(SWP_NOSENDCHANGING),
+ FLAG_ENTRY(SWP_NOSIZE), FLAG_ENTRY(SWP_NOZORDER),
+ FLAG_ENTRY(SWP_SHOWWINDOW)
+ };
+
+ return flagsValue(winPosValues, sizeof(winPosValues) / sizeof(winPosValues[0]), f);
}
-#else
+static const char *winPosInsertAfter(quintptr h)
+{
+ static const QWinMessageMapping<quintptr> insertAfterValues[] = {
+ {quintptr(HWND_BOTTOM), "HWND_BOTTOM"},
+ {quintptr(HWND_NOTOPMOST), "HWND_NOTOPMOST"},
+ {quintptr(HWND_TOP), "HWND_TOP"},
+ {quintptr(HWND_TOPMOST), "HWND_TOPMOST"}
+ };
+ return findWinMessageMapping(insertAfterValues, sizeof(insertAfterValues) / sizeof(insertAfterValues[0]), h);
+}
+
+static const char *sessionMgrLogOffOption(uint p)
+{
+ static const QWinMessageMapping<uint> values[] = {
+ {ENDSESSION_CLOSEAPP, "Close application"},
+ {ENDSESSION_CRITICAL, "Force application end"},
+ {ENDSESSION_LOGOFF, "User logoff"}
+ };
+
+ return findWinMessageMapping(values, sizeof(values) / sizeof(values[0]), p);
+}
// Returns a "human readable" string representation of the MSG and the
// information it points to
@@ -590,400 +690,177 @@ QString decodeMSG(const MSG& msg)
{
const WPARAM wParam = msg.wParam;
const LPARAM lParam = msg.lParam;
- QString wmmsg = QString::fromLatin1(findWMstr(msg.message));
- // Unknown WM_, so use number
- if (wmmsg.isEmpty())
- wmmsg = QString::fromLatin1("WM_(%1)").arg(msg.message);
-
- const QString rawParameters = QString::asprintf("hwnd(0x%p) ", (void *)msg.hwnd);
+ QString message;
// Custom WM_'s
if (msg.message > WM_APP)
- wmmsg = QString::fromLatin1("WM_APP + %1").arg(msg.message - WM_APP);
+ message= QString::fromLatin1("WM_APP + %1").arg(msg.message - WM_APP);
else if (msg.message > WM_USER)
- wmmsg = QString::fromLatin1("WM_USER + %1").arg(msg.message - WM_USER);
+ message = QString::fromLatin1("WM_USER + %1").arg(msg.message - WM_USER);
+ else if (const char *wmmsgC = findWMstr(msg.message))
+ message = QString::fromLatin1(wmmsgC);
+ else
+ message = QString::fromLatin1("WM_(%1)").arg(msg.message); // Unknown WM_, so use number
+
+ // Yes, we want to give the WM_ names 20 chars of space before showing the
+ // decoded message, since some of the common messages are quite long, and
+ // we don't want the decoded information to vary in output position
+ if (message.size() < 20)
+ message.prepend(QString(20 - message.size(), QLatin1Char(' ')));
+ message += QLatin1String(": ");
+
+ const QString hwndS = QString::asprintf("(%p)", reinterpret_cast<void *>(msg.hwnd));
+ const QString wParamS = QString::asprintf("(%p)", reinterpret_cast<void *>(wParam));
+ const QString lParamS = QString::asprintf("(%p)", reinterpret_cast<void *>(lParam));
QString parameters;
switch (msg.message) {
-#ifdef WM_ACTIVATE
case WM_ACTIVATE:
- {
- QString activation = valueCheck(wParam,
- FLAG_STRING(WA_ACTIVE, "Activate"),
- FLAG_STRING(WA_INACTIVE, "Deactivate"),
- FLAG_STRING(WA_CLICKACTIVE, "Activate by mouseclick"),
- FLAG_STRING());
- parameters = QString::asprintf("%s Hwnd (0x%p)", activation.toLatin1().data(), (void *)msg.hwnd);
- }
+ if (const char *a = activateParameter(uint(wParam)))
+ parameters += QLatin1String(a);
+ parameters += QLatin1String(" Hwnd ") + hwndS;
break;
-#endif
-#ifdef WM_CAPTURECHANGED
case WM_CAPTURECHANGED:
- parameters = QString::asprintf("Hwnd gaining capture (0x%p)", (void *)lParam);
+ parameters = QLatin1String("Hwnd gaining capture ") + hwndS;
break;
-#endif
-#ifdef WM_CREATE
case WM_CREATE:
{
- LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
- QString styles = flagCheck(lpcs->style,
- FLGSTR(WS_BORDER),
- FLGSTR(WS_CAPTION),
- FLGSTR(WS_CHILD),
- FLGSTR(WS_CLIPCHILDREN),
- FLGSTR(WS_CLIPSIBLINGS),
- FLGSTR(WS_DISABLED),
- FLGSTR(WS_DLGFRAME),
- FLGSTR(WS_GROUP),
- FLGSTR(WS_HSCROLL),
- FLGSTR(WS_OVERLAPPED),
-#if defined(WS_OVERLAPPEDWINDOW) && (WS_OVERLAPPEDWINDOW != 0)
- FLGSTR(WS_OVERLAPPEDWINDOW),
-#endif
-#ifdef WS_ICONIC
- FLGSTR(WS_ICONIC),
-#endif
- FLGSTR(WS_MAXIMIZE),
- FLGSTR(WS_MAXIMIZEBOX),
- FLGSTR(WS_MINIMIZE),
- FLGSTR(WS_MINIMIZEBOX),
- FLGSTR(WS_OVERLAPPEDWINDOW),
- FLGSTR(WS_POPUP),
-#ifdef WS_POPUPWINDOW
- FLGSTR(WS_POPUPWINDOW),
-#endif
- FLGSTR(WS_SIZEBOX),
- FLGSTR(WS_SYSMENU),
- FLGSTR(WS_TABSTOP),
- FLGSTR(WS_THICKFRAME),
-#ifdef WS_TILED
- FLGSTR(WS_TILED),
-#endif
-#ifdef WS_TILEDWINDOW
- FLGSTR(WS_TILEDWINDOW),
-#endif
- FLGSTR(WS_VISIBLE),
- FLGSTR(WS_VSCROLL),
- FLAG_STRING());
-
- QString exStyles = flagCheck(lpcs->dwExStyle,
-#ifdef WS_EX_ACCEPTFILES
- FLGSTR(WS_EX_ACCEPTFILES),
-#endif
-#ifdef WS_EX_APPWINDOW
- FLGSTR(WS_EX_APPWINDOW),
-#endif
- FLGSTR(WS_EX_CLIENTEDGE),
- FLGSTR(WS_EX_DLGMODALFRAME),
-#ifdef WS_EX_LEFT
- FLGSTR(WS_EX_LEFT),
-#endif
- FLGSTR(WS_EX_LEFTSCROLLBAR),
-#ifdef WS_EX_LTRREADING
- FLGSTR(WS_EX_LTRREADING),
-#endif
-#ifdef WS_EX_MDICHILD
- FLGSTR(WS_EX_MDICHILD),
-#endif
-#ifdef WS_EX_NOACTIVATE
- FLGSTR(WS_EX_NOACTIVATE),
-#endif
-#ifdef WS_EX_NOANIMATION
- FLGSTR(WS_EX_NOANIMATION),
-#endif
- FLGSTR(WS_EX_NOPARENTNOTIFY),
- FLGSTR(WS_EX_OVERLAPPEDWINDOW),
-#ifdef WS_EX_PALETTEWINDOW
- FLGSTR(WS_EX_PALETTEWINDOW),
-#endif
-#ifdef WS_EX_RIGHT
- FLGSTR(WS_EX_RIGHT),
-#endif
-#ifdef WS_EX_RIGHTSCROLLBAR
- FLGSTR(WS_EX_RIGHTSCROLLBAR),
-#endif
-#ifdef WS_EX_RTLREADING
- FLGSTR(WS_EX_RTLREADING),
-#endif
- FLGSTR(WS_EX_STATICEDGE),
- FLGSTR(WS_EX_TOOLWINDOW),
- FLGSTR(WS_EX_TOPMOST),
-#ifdef WS_EX_TRANSPARENT
- FLGSTR(WS_EX_TRANSPARENT),
-#endif
- FLGSTR(WS_EX_WINDOWEDGE),
-#ifdef WS_EX_CAPTIONOKBTN
- FLGSTR(WS_EX_CAPTIONOKBTN),
-#endif
- FLAG_STRING());
-
+ auto lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
QString className;
- if (lpcs->lpszClass != 0) {
- if (HIWORD(lpcs->lpszClass) == 0) // Atom
- className = QString::number(LOWORD(lpcs->lpszClass), 16);
- else // String
- className = QString((QChar*)lpcs->lpszClass,
- (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszClass)));
+ if (lpcs->lpszClass != nullptr) {
+ className = HIWORD(lpcs->lpszClass) == 0
+ ? QString::number(LOWORD(lpcs->lpszClass), 16) // Atom
+ : QString::fromWCharArray(lpcs->lpszClass);
}
- QString windowName;
- if (lpcs->lpszName != 0)
- windowName = QString((QChar*)lpcs->lpszName,
- (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszName)));
+ const QString windowName = lpcs->lpszName
+ ? QString::fromWCharArray(lpcs->lpszName) : QString();
parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) className(%s) windowName(%s) parent(0x%p) style(%s) exStyle(%s)",
- lpcs->x, lpcs->y, lpcs->cx, lpcs->cy, className.toLatin1().data(),
- windowName.toLatin1().data(), (void *)lpcs->hwndParent,
- styles.toLatin1().data(), exStyles.toLatin1().data());
+ lpcs->x, lpcs->y, lpcs->cx, lpcs->cy,
+ className.toLatin1().constData(),
+ windowName.toLatin1().constData(),
+ reinterpret_cast<void *>(lpcs->hwndParent),
+ styleFlags(uint(lpcs->style)).toLatin1().constData(),
+ exStyleFlags(lpcs->dwExStyle).toLatin1().constData());
}
break;
-#endif
-#ifdef WM_DESTROY
case WM_DESTROY:
- parameters = QString::asprintf("Destroy hwnd (0x%p)", (void *)msg.hwnd);
+ parameters = QLatin1String("Destroy hwnd ") + hwndS;
break;
-#endif
-#ifdef WM_IME_NOTIFY
case WM_IME_NOTIFY:
{
- QString imnCommand = valueCheck(wParam,
- FLGSTR(IMN_CHANGECANDIDATE),
- FLGSTR(IMN_CLOSECANDIDATE),
- FLGSTR(IMN_CLOSESTATUSWINDOW),
- FLGSTR(IMN_GUIDELINE),
- FLGSTR(IMN_OPENCANDIDATE),
- FLGSTR(IMN_OPENSTATUSWINDOW),
- FLGSTR(IMN_SETCANDIDATEPOS),
- FLGSTR(IMN_SETCOMPOSITIONFONT),
- FLGSTR(IMN_SETCOMPOSITIONWINDOW),
- FLGSTR(IMN_SETCONVERSIONMODE),
- FLGSTR(IMN_SETOPENSTATUS),
- FLGSTR(IMN_SETSENTENCEMODE),
- FLGSTR(IMN_SETSTATUSWINDOWPOS),
- FLAG_STRING());
- parameters = QString::asprintf("Command(%s : 0x%p)", imnCommand.toLatin1().data(), (void *)lParam);
+ parameters = QLatin1String("Command(");
+ if (const char *c = imeCommand(uint(wParam)))
+ parameters += QLatin1String(c);
+ parameters += QLatin1String(" : ") + lParamS;
}
break;
-#endif
-#ifdef WM_IME_SETCONTEXT
case WM_IME_SETCONTEXT:
- {
- bool fSet = (BOOL)wParam;
- DWORD fShow = (DWORD)lParam;
- QString showFlgs = flagCheck(fShow,
-#ifdef ISC_SHOWUICOMPOSITIONWINDOW
- FLGSTR(ISC_SHOWUICOMPOSITIONWINDOW),
-#endif
-#ifdef ISC_SHOWUIGUIDWINDOW
- FLGSTR(ISC_SHOWUIGUIDWINDOW),
-#endif
-#ifdef ISC_SHOWUISOFTKBD
- FLGSTR(ISC_SHOWUISOFTKBD),
-#endif
- FLGSTR(ISC_SHOWUICANDIDATEWINDOW),
- FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 1),
- FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 2),
- FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 3),
- FLAG_STRING());
- parameters = QString::asprintf("Input context(%s) Show flags(%s)", (fSet? "Active" : "Inactive"), showFlgs.toLatin1().data());
- }
+ parameters = QLatin1String("Input context(")
+ + QLatin1String(wParam == TRUE ? "Active" : "Inactive")
+ + QLatin1String(") Show flags(")
+ + imeShowFlags(DWORD(lParam)) + QLatin1Char(')');
break;
-#endif
-#ifdef WM_KILLFOCUS
case WM_KILLFOCUS:
- parameters = QString::asprintf("Hwnd gaining keyboard focus (0x%p)", (void *)wParam);
+ parameters = QLatin1String("Hwnd gaining keyboard focus ") + wParamS;
break;
-#endif
-#ifdef WM_CHAR
case WM_CHAR:
-#endif
-#ifdef WM_IME_CHAR
case WM_IME_CHAR:
-#endif
-#ifdef WM_KEYDOWN
case WM_KEYDOWN:
-#endif
-#ifdef WM_KEYUP
case WM_KEYUP:
{
- int nVirtKey = (int)wParam;
- long lKeyData = (long)lParam;
+ const int nVirtKey = int(wParam);
+ const long lKeyData = long(lParam);
int repCount = (lKeyData & 0xffff); // Bit 0-15
int scanCode = (lKeyData & 0xf0000) >> 16; // Bit 16-23
bool contextCode = !!(lKeyData & 0x20000000); // Bit 29
bool prevState = !!(lKeyData & 0x40000000); // Bit 30
bool transState = !!(lKeyData & 0x80000000); // Bit 31
- parameters = QString::asprintf("Virual-key(0x%x) Scancode(%d) Rep(%d) Contextcode(%d), Prev state(%d), Trans state(%d)",
- nVirtKey, scanCode, repCount, contextCode, prevState, transState);
+ parameters = QString::asprintf("Virtual-key(0x%x) Scancode(%d) Rep(%d) Contextcode(%d), Prev state(%d), Trans state(%d)",
+ nVirtKey, scanCode, repCount,
+ contextCode, prevState, transState);
}
break;
-#endif
-#ifdef WM_INPUTLANGCHANGE
case WM_INPUTLANGCHANGE:
parameters = QStringLiteral("Keyboard layout changed");
break;
-#endif // WM_INPUTLANGCHANGE
-#ifdef WM_NCACTIVATE
case WM_NCACTIVATE:
- {
parameters = (msg.wParam? QLatin1String("Active Titlebar") : QLatin1String("Inactive Titlebar"));
- }
break;
-#endif
-#ifdef WM_MOUSEACTIVATE
case WM_MOUSEACTIVATE:
{
- QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
- parameters = QString::asprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)", (void *)wParam, LOWORD(lParam), mouseMsg.toLatin1().data());
+ const char *mouseMsg = findWMstr(HIWORD(lParam));
+ parameters = QString::asprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)",
+ reinterpret_cast<void *>(wParam),
+ LOWORD(lParam), mouseMsg ? mouseMsg : "");
}
break;
-#endif
-#ifdef WM_MOUSELEAVE
case WM_MOUSELEAVE:
break; // wParam & lParam not used
-#endif
-#ifdef WM_MOUSEHOVER
case WM_MOUSEHOVER:
-#endif
-#ifdef WM_MOUSEWHEEL
case WM_MOUSEWHEEL:
-#endif
-#ifdef WM_MOUSEHWHEEL
case WM_MOUSEHWHEEL:
-#endif
-#ifdef WM_LBUTTONDBLCLK
case WM_LBUTTONDBLCLK:
-#endif
-#ifdef WM_LBUTTONDOWN
case WM_LBUTTONDOWN:
-#endif
-#ifdef WM_LBUTTONUP
case WM_LBUTTONUP:
-#endif
-#ifdef WM_MBUTTONDBLCLK
case WM_MBUTTONDBLCLK:
-#endif
-#ifdef WM_MBUTTONDOWN
case WM_MBUTTONDOWN:
-#endif
-#ifdef WM_MBUTTONUP
case WM_MBUTTONUP:
-#endif
-#ifdef WM_RBUTTONDBLCLK
case WM_RBUTTONDBLCLK:
-#endif
-#ifdef WM_RBUTTONDOWN
case WM_RBUTTONDOWN:
-#endif
-#ifdef WM_RBUTTONUP
case WM_RBUTTONUP:
-#endif
-#ifdef WM_MOUSEMOVE
case WM_MOUSEMOVE:
- {
- QString vrtKeys = flagCheck(wParam,
- FLGSTR(MK_CONTROL),
- FLGSTR(MK_LBUTTON),
- FLGSTR(MK_MBUTTON),
- FLGSTR(MK_RBUTTON),
- FLGSTR(MK_SHIFT),
-#ifdef MK_XBUTTON1
- FLGSTR(MK_XBUTTON1),
-#endif
-#ifdef MK_XBUTTON2
- FLGSTR(MK_XBUTTON2),
-#endif
- FLAG_STRING());
- parameters = QString::asprintf("x,y(%4d,%4d) Virtual Keys(%s)", GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), vrtKeys.toLatin1().data());
- }
+ parameters = QString::asprintf("x,y(%4d,%4d) Virtual Keys(",
+ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))
+ + virtualKeys(uint(wParam)) + QLatin1Char(')');
break;
-#endif
-#ifdef WM_MOVE
case WM_MOVE:
parameters = QString::asprintf("x,y(%4d,%4d)", LOWORD(lParam), HIWORD(lParam));
break;
-#endif
-#if defined(WM_PAINT) && defined(WM_ERASEBKGND)
case WM_ERASEBKGND:
case WM_PAINT:
- parameters = QString::asprintf("hdc(0x%p)", (void *)wParam);
+ parameters = QLatin1String("hdc") + wParamS;
break;
-#endif
-#ifdef WM_QUERYNEWPALETTE
case WM_QUERYNEWPALETTE:
break; // lParam & wParam are unused
-#endif
-#ifdef WM_SETCURSOR
case WM_SETCURSOR:
- {
- QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
- parameters = QString::asprintf("HitTestCode(0x%x) MouseMsg(%s)", LOWORD(lParam), mouseMsg.toLatin1().data());
- }
+ parameters = QString::asprintf("HitTestCode(0x%x) MouseMsg(", LOWORD(lParam));
+ if (const char *mouseMsg = findWMstr(HIWORD(lParam)))
+ parameters += QLatin1String(mouseMsg);
+ parameters += QLatin1Char(')');
break;
-#endif
-#ifdef WM_SETFOCUS
case WM_SETFOCUS:
- parameters = QString::asprintf("Lost Focus (0x%p)", (void *)wParam);
+ parameters = QLatin1String("Lost Focus ") + wParamS;
break;
-#endif
-#ifdef WM_SETTEXT
case WM_SETTEXT:
- parameters = QString::asprintf("Set Text (%s)", QString((QChar*)lParam, (int)wcslen(reinterpret_cast<const wchar_t *>(lParam))).toLatin1().data()); //Unicode string
+ parameters = QLatin1String("Set Text (")
+ + QString::fromWCharArray(reinterpret_cast<const wchar_t *>(lParam))
+ + QLatin1Char(')');
break;
-#endif
-#ifdef WM_SIZE
case WM_SIZE:
- {
- QString showMode = valueCheck(wParam,
- FLGSTR(SIZE_MAXHIDE),
- FLGSTR(SIZE_MAXIMIZED),
- FLGSTR(SIZE_MAXSHOW),
- FLGSTR(SIZE_MINIMIZED),
- FLGSTR(SIZE_RESTORED),
- FLAG_STRING());
-
- parameters = QString::asprintf("w,h(%4d,%4d) showmode(%s)", LOWORD(lParam), HIWORD(lParam), showMode.toLatin1().data());
- }
+ parameters = QString::asprintf("w,h(%4d,%4d) showmode(",
+ LOWORD(lParam), HIWORD(lParam));
+ if (const char *showMode = wmSizeParam(uint(wParam)))
+ parameters += QLatin1String(showMode);
+ parameters += QLatin1Char(')');
break;
-#endif
-#ifdef WM_WINDOWPOSCHANGED
case WM_WINDOWPOSCHANGED:
{
- LPWINDOWPOS winPos = (LPWINDOWPOS)lParam;
+ auto winPos = reinterpret_cast<LPWINDOWPOS>(lParam);
if (!winPos)
break;
- QString hwndAfter = valueCheck(quint64(winPos->hwndInsertAfter),
- FLAG_STRING((qptrdiff)HWND_BOTTOM, "HWND_BOTTOM"),
- FLAG_STRING((qptrdiff)HWND_NOTOPMOST, "HWND_NOTOPMOST"),
- FLAG_STRING((qptrdiff)HWND_TOP, "HWND_TOP"),
- FLAG_STRING((qptrdiff)HWND_TOPMOST, "HWND_TOPMOST"),
- FLAG_STRING());
- if (hwndAfter.isEmpty())
- hwndAfter = QString::number((quintptr)winPos->hwndInsertAfter, 16);
- QString flags = flagCheck(winPos->flags,
- FLGSTR(SWP_DRAWFRAME),
- FLGSTR(SWP_FRAMECHANGED),
- FLGSTR(SWP_HIDEWINDOW),
- FLGSTR(SWP_NOACTIVATE),
-#ifdef SWP_NOCOPYBITS
- FLGSTR(SWP_NOCOPYBITS),
-#endif
- FLGSTR(SWP_NOMOVE),
- FLGSTR(SWP_NOOWNERZORDER),
- FLGSTR(SWP_NOREDRAW),
- FLGSTR(SWP_NOREPOSITION),
-#ifdef SWP_NOSENDCHANGING
- FLGSTR(SWP_NOSENDCHANGING),
-#endif
- FLGSTR(SWP_NOSIZE),
- FLGSTR(SWP_NOZORDER),
- FLGSTR(SWP_SHOWWINDOW),
- FLAG_STRING());
- parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) flags(%s) hwndAfter(%s)", winPos->x, winPos->y, winPos->cx, winPos->cy, flags.toLatin1().data(), hwndAfter.toLatin1().data());
+ const auto insertAfter = quintptr(winPos->hwndInsertAfter);
+ parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) flags(%s) hwndAfter(",
+ winPos->x, winPos->y, winPos->cx, winPos->cy,
+ winPosFlags(winPos->flags).toLatin1().constData());
+ if (const char *h = winPosInsertAfter(insertAfter))
+ parameters += QLatin1String(h);
+ else
+ parameters += QString::number(insertAfter, 16);
+ parameters += QLatin1Char(')');
}
break;
-#endif
-#ifdef WM_QUERYENDSESSION
#ifndef ENDSESSION_CLOSEAPP
#define ENDSESSION_CLOSEAPP 0x00000001
#endif
@@ -991,34 +868,23 @@ QString decodeMSG(const MSG& msg)
#define ENDSESSION_CRITICAL 0x40000000
#endif
case WM_QUERYENDSESSION:
- {
- QString logoffOption = valueCheck(wParam,
- FLAG_STRING(ENDSESSION_CLOSEAPP, "Close application"),
- FLAG_STRING(ENDSESSION_CRITICAL, "Force application end"),
- FLAG_STRING(ENDSESSION_LOGOFF, "User logoff"),
- FLAG_STRING());
- parameters = QLatin1String("End session: ") + logoffOption;
- }
- break;
-#endif
+ parameters = QLatin1String("End session: ");
+ if (const char *logoffOption = sessionMgrLogOffOption(uint(wParam)))
+ parameters += QLatin1String(logoffOption);
+ break;
default:
- parameters = QString::asprintf("wParam(0x%p) lParam(0x%p)", (void *)wParam, (void *)lParam);
+ parameters = QLatin1String("wParam") + wParamS + QLatin1String(" lParam") + lParamS;
break;
}
- // Yes, we want to give the WM_ names 20 chars of space before showing the
- // decoded message, since some of the common messages are quite long, and
- // we don't want the decoded information to vary in output position
- QString message = QString::fromLatin1("%1: ").arg(wmmsg, 20);
- message += rawParameters;
- message += parameters;
- return message;
-}
-#endif
+ return message + QLatin1String("hwnd") + hwndS + QLatin1Char(' ') + parameters;
+}
QDebug operator<<(QDebug dbg, const MSG &msg)
{
QDebugStateSaver saver(dbg);
+ dbg.noquote();
+ dbg.nospace();
dbg << decodeMSG(msg);
return dbg;
}
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index 3d0a9dd05d..cacbb1e495 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -44,6 +44,8 @@
#include "qbasicatomic.h"
+#include <qtcore_tracepoints_p.h>
+
#include <limits>
QT_BEGIN_NAMESPACE
@@ -294,7 +296,9 @@ QT_BEGIN_NAMESPACE
*/
QEvent::QEvent(Type type)
: d(0), t(type), posted(false), spont(false), m_accept(true)
-{}
+{
+ Q_TRACE(QEvent_ctor, this, t);
+}
/*!
\internal
@@ -307,6 +311,7 @@ QEvent::QEvent(const QEvent &other)
: d(other.d), t(other.t), posted(other.posted), spont(other.spont),
m_accept(other.m_accept)
{
+ Q_TRACE(QEvent_ctor, this, t);
// if QEventPrivate becomes available, make sure to implement a
// virtual QEventPrivate *clone() const; function so we can copy here
Q_ASSERT_X(!d, "QEvent", "Impossible, this can't happen: QEventPrivate isn't defined anywhere");
@@ -339,6 +344,7 @@ QEvent &QEvent::operator=(const QEvent &other)
QEvent::~QEvent()
{
+ Q_TRACE(QEvent_dtor, this, t);
if (posted && QCoreApplication::instance())
QCoreApplicationPrivate::removePostedEvent(this);
Q_ASSERT_X(!d, "QEvent", "Impossible, this can't happen: QEventPrivate isn't defined anywhere");
diff --git a/src/corelib/kernel/qcoreglobaldata.cpp b/src/corelib/kernel/qcoreglobaldata.cpp
index e2087b9e64..88a45ef4ee 100644
--- a/src/corelib/kernel/qcoreglobaldata.cpp
+++ b/src/corelib/kernel/qcoreglobaldata.cpp
@@ -55,7 +55,10 @@ QCoreGlobalData::~QCoreGlobalData()
{
#if QT_CONFIG(textcodec)
codecForLocale = 0;
- for (QList<QTextCodec *>::const_iterator it = allCodecs.constBegin(); it != allCodecs.constEnd(); ++it)
+ QList<QTextCodec *> tmp = allCodecs;
+ allCodecs.clear();
+ codecCache.clear();
+ for (QList<QTextCodec *>::const_iterator it = tmp.constBegin(); it != tmp.constEnd(); ++it)
delete *it;
#endif
}
diff --git a/src/corelib/kernel/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp
index 8a5bd5d681..66d0dce7e8 100644
--- a/src/corelib/kernel/qdeadlinetimer.cpp
+++ b/src/corelib/kernel/qdeadlinetimer.cpp
@@ -39,7 +39,6 @@
#include "qdeadlinetimer.h"
#include "qdeadlinetimer_p.h"
-#include <qpair.h>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/kernel/qdeadlinetimer.h b/src/corelib/kernel/qdeadlinetimer.h
index 6c10e1025e..1a4ee04a96 100644
--- a/src/corelib/kernel/qdeadlinetimer.h
+++ b/src/corelib/kernel/qdeadlinetimer.h
@@ -43,6 +43,7 @@
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qpair.h>
#ifdef max
// un-pollute the namespace. We need std::numeric_limits::max() and std::chrono::duration::max()
@@ -186,6 +187,10 @@ private:
unsigned type;
qint64 rawRemainingTimeNSecs() const Q_DECL_NOTHROW;
+
+public:
+ // This is not a public function, it's here only for Qt's internal convenience...
+ QPair<qint64, unsigned> _q_data() const { return qMakePair(t1, t2); }
};
Q_DECLARE_SHARED(QDeadlineTimer)
diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm
index 503836d071..8881305b18 100644
--- a/src/corelib/kernel/qeventdispatcher_cf.mm
+++ b/src/corelib/kernel/qeventdispatcher_cf.mm
@@ -58,18 +58,36 @@
QT_USE_NAMESPACE
-@interface QT_MANGLE_NAMESPACE(RunLoopModeTracker) : NSObject {
- QStack<CFStringRef> m_runLoopModes;
-}
+/*!
+ During scroll view panning, and possibly other gestures, UIKit will
+ request a switch to UITrackingRunLoopMode via GSEventPushRunLoopMode,
+ which records the new runloop mode and stops the current runloop.
+
+ Unfortunately the runloop mode is just stored on an internal stack, used
+ when UIKit itself is running the runloop, and is not available through e.g.
+ CFRunLoopCopyCurrentMode, which only knows about the current running
+ runloop mode, not the requested future runloop mode.
+
+ To ensure that we pick up this new runloop mode and use it when calling
+ CFRunLoopRunInMode from processEvents, we listen for the notification
+ emitted by [UIApplication pushRunLoopMode:requester:].
+
+ Without this workaround we end up always running in the default runloop
+ mode, resulting in missing momentum-phases in UIScrollViews such as the
+ emoji keyboard.
+*/
+@interface QT_MANGLE_NAMESPACE(RunLoopModeTracker) : NSObject
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(RunLoopModeTracker);
-@implementation RunLoopModeTracker
+@implementation RunLoopModeTracker {
+ QStack<CFStringRef> m_runLoopModes;
+}
-- (id) init
+- (instancetype)init
{
- if (self = [super init]) {
+ if ((self = [super init])) {
m_runLoopModes.push(kCFRunLoopDefaultMode);
#if !defined(Q_OS_WATCHOS)
@@ -84,9 +102,9 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(RunLoopModeTracker);
return self;
}
-- (void) dealloc
+- (void)dealloc
{
- [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [NSNotificationCenter.defaultCenter removeObserver:self];
[super dealloc];
}
@@ -95,13 +113,13 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
{
for (NSString *key in dictionary) {
if (CFStringHasSuffix((CFStringRef)key, CFSTR("RunLoopMode")))
- return (CFStringRef)[dictionary objectForKey: key];
+ return (CFStringRef)dictionary[key];
}
return nil;
}
-- (void) receivedNotification:(NSNotification *) notification
+- (void)receivedNotification:(NSNotification *)notification
{
if (CFStringHasSuffix((CFStringRef)notification.name, CFSTR("RunLoopModePushNotification"))) {
if (CFStringRef mode = runLoopMode(notification.userInfo))
@@ -111,7 +129,7 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
} else if (CFStringHasSuffix((CFStringRef)notification.name, CFSTR("RunLoopModePopNotification"))) {
CFStringRef mode = runLoopMode(notification.userInfo);
- if (CFStringCompare(mode, [self currentMode], 0) == kCFCompareEqualTo)
+ if (CFStringCompare(mode, self.currentMode, 0) == kCFCompareEqualTo)
m_runLoopModes.pop();
else
qCWarning(lcEventDispatcher) << "Tried to pop run loop mode"
@@ -121,7 +139,7 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
}
}
-- (CFStringRef) currentMode
+- (CFStringRef)currentMode
{
return m_runLoopModes.top();
}
@@ -191,8 +209,16 @@ QEventDispatcherCoreFoundation::QEventDispatcherCoreFoundation(QObject *parent)
, m_blockedRunLoopTimer(0)
, m_overdueTimerScheduled(false)
{
- m_cfSocketNotifier.setHostEventDispatcher(this);
+}
+
+void QEventDispatcherCoreFoundation::startingUp()
+{
+ // The following code must run on the event dispatcher thread, so that
+ // CFRunLoopGetCurrent() returns the correct run loop.
+ Q_ASSERT(QThread::currentThread() == thread());
+ m_runLoop = QCFType<CFRunLoopRef>::constructFromGet(CFRunLoopGetCurrent());
+ m_cfSocketNotifier.setHostEventDispatcher(this);
m_postedEventsRunLoopSource.addToMode(kCFRunLoopCommonModes);
m_runLoopActivityObserver.addToMode(kCFRunLoopCommonModes);
}
@@ -233,6 +259,8 @@ QEventLoop *QEventDispatcherCoreFoundation::currentEventLoop() const
*/
bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlags flags)
{
+ QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "processEvents");
+
bool eventsProcessed = false;
if (flags & (QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers))
@@ -385,6 +413,8 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
bool QEventDispatcherCoreFoundation::processPostedEvents()
{
+ QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "processPostedEvents");
+
if (m_processEvents.processedPostedEvents && !(m_processEvents.flags & QEventLoop::EventLoopExec)) {
qCDebug(lcEventDispatcher) << "Already processed events this pass";
return false;
@@ -392,7 +422,8 @@ bool QEventDispatcherCoreFoundation::processPostedEvents()
m_processEvents.processedPostedEvents = true;
- qCDebug(lcEventDispatcher) << "Sending posted events for" << m_processEvents.flags;
+ qCDebug(lcEventDispatcher) << "Sending posted events for"
+ << QEventLoop::ProcessEventsFlags(m_processEvents.flags.load());
QCoreApplication::sendPostedEvents();
return true;
@@ -400,6 +431,8 @@ bool QEventDispatcherCoreFoundation::processPostedEvents()
void QEventDispatcherCoreFoundation::processTimers(CFRunLoopTimerRef timer)
{
+ QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "processTimers");
+
if (m_processEvents.processedTimers && !(m_processEvents.flags & QEventLoop::EventLoopExec)) {
qCDebug(lcEventDispatcher) << "Already processed timers this pass";
m_processEvents.deferredUpdateTimers = true;
@@ -473,7 +506,7 @@ bool QEventDispatcherCoreFoundation::hasPendingEvents()
// 'maybeHasPendingEvents' in our case.
extern uint qGlobalPostedEventsCount();
- return qGlobalPostedEventsCount() || !CFRunLoopIsWaiting(CFRunLoopGetMain());
+ return qGlobalPostedEventsCount() || !CFRunLoopIsWaiting(m_runLoop);
}
void QEventDispatcherCoreFoundation::wakeUp()
@@ -493,7 +526,8 @@ void QEventDispatcherCoreFoundation::wakeUp()
}
m_postedEventsRunLoopSource.signal();
- CFRunLoopWakeUp(CFRunLoopGetMain());
+ if (m_runLoop)
+ CFRunLoopWakeUp(m_runLoop);
qCDebug(lcEventDispatcher) << "Signaled posted event run-loop source";
}
@@ -502,7 +536,7 @@ void QEventDispatcherCoreFoundation::interrupt()
{
qCDebug(lcEventDispatcher) << "Marking current processEvent as interrupted";
m_processEvents.wasInterrupted = true;
- CFRunLoopStop(CFRunLoopGetMain());
+ CFRunLoopStop(m_runLoop);
}
void QEventDispatcherCoreFoundation::flush()
@@ -597,7 +631,7 @@ void QEventDispatcherCoreFoundation::updateTimers()
processTimers(timer);
});
- CFRunLoopAddTimer(CFRunLoopGetMain(), m_runLoopTimer, kCFRunLoopCommonModes);
+ CFRunLoopAddTimer(m_runLoop, m_runLoopTimer, kCFRunLoopCommonModes);
qCDebug(lcEventDispatcherTimers) << "Created new CFRunLoopTimer" << m_runLoopTimer;
} else {
diff --git a/src/corelib/kernel/qeventdispatcher_cf_p.h b/src/corelib/kernel/qeventdispatcher_cf_p.h
index a607ab7a15..26191d520c 100644
--- a/src/corelib/kernel/qeventdispatcher_cf_p.h
+++ b/src/corelib/kernel/qeventdispatcher_cf_p.h
@@ -208,24 +208,25 @@ class Q_CORE_EXPORT QEventDispatcherCoreFoundation : public QAbstractEventDispat
public:
explicit QEventDispatcherCoreFoundation(QObject *parent = 0);
+ void startingUp() override;
~QEventDispatcherCoreFoundation();
- bool processEvents(QEventLoop::ProcessEventsFlags flags);
- bool hasPendingEvents();
+ bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
+ bool hasPendingEvents() override;
- void registerSocketNotifier(QSocketNotifier *notifier);
- void unregisterSocketNotifier(QSocketNotifier *notifier);
+ void registerSocketNotifier(QSocketNotifier *notifier) override;
+ void unregisterSocketNotifier(QSocketNotifier *notifier) override;
- void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object);
- bool unregisterTimer(int timerId);
- bool unregisterTimers(QObject *object);
- QList<QAbstractEventDispatcher::TimerInfo> registeredTimers(QObject *object) const;
+ void registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) override;
+ bool unregisterTimer(int timerId) override;
+ bool unregisterTimers(QObject *object) override;
+ QList<QAbstractEventDispatcher::TimerInfo> registeredTimers(QObject *object) const override;
- int remainingTime(int timerId);
+ int remainingTime(int timerId) override;
- void wakeUp();
- void interrupt();
- void flush();
+ void wakeUp() override;
+ void interrupt() override;
+ void flush() override;
protected:
QEventLoop *currentEventLoop() const;
@@ -239,11 +240,11 @@ protected:
, processedPostedEvents(false), processedTimers(false)
, deferredWakeUp(false), deferredUpdateTimers(false) {}
- QEventLoop::ProcessEventsFlags flags;
- bool wasInterrupted;
- bool processedPostedEvents;
- bool processedTimers;
- bool deferredWakeUp;
+ QAtomicInt flags;
+ QAtomicInteger<char> wasInterrupted;
+ QAtomicInteger<char> processedPostedEvents;
+ QAtomicInteger<char> processedTimers;
+ QAtomicInteger<char> deferredWakeUp;
bool deferredUpdateTimers;
};
@@ -258,6 +259,7 @@ private:
QTimerInfoList m_timerInfoList;
CFRunLoopTimerRef m_runLoopTimer;
CFRunLoopTimerRef m_blockedRunLoopTimer;
+ QCFType<CFRunLoopRef> m_runLoop;
bool m_overdueTimerScheduled;
QCFSocketNotifier m_cfSocketNotifier;
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 330870f219..f1a4088d98 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -522,6 +522,22 @@ QEventDispatcherWin32::~QEventDispatcherWin32()
{
}
+static bool isUserInputMessage(UINT message)
+{
+ return (message >= WM_KEYFIRST && message <= WM_KEYLAST)
+ || (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST)
+ || message == WM_MOUSEWHEEL
+ || message == WM_MOUSEHWHEEL
+ || message == WM_TOUCH
+#ifndef QT_NO_GESTURES
+ || message == WM_GESTURE
+ || message == WM_GESTURENOTIFY
+#endif
+// Pointer input: Exclude WM_NCPOINTERUPDATE .. WM_POINTERROUTEDRELEASED
+ || (message >= 0x0241 && message <= 0x0253)
+ || message == WM_CLOSE;
+}
+
bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherWin32);
@@ -562,19 +578,8 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
} else {
haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
if (haveMessage) {
- if ((flags & QEventLoop::ExcludeUserInputEvents)
- && ((msg.message >= WM_KEYFIRST
- && msg.message <= WM_KEYLAST)
- || (msg.message >= WM_MOUSEFIRST
- && msg.message <= WM_MOUSELAST)
- || msg.message == WM_MOUSEWHEEL
- || msg.message == WM_MOUSEHWHEEL
- || msg.message == WM_TOUCH
-#ifndef QT_NO_GESTURES
- || msg.message == WM_GESTURE
- || msg.message == WM_GESTURENOTIFY
-#endif
- || msg.message == WM_CLOSE)) {
+ if (flags.testFlag(QEventLoop::ExcludeUserInputEvents)
+ && isUserInputMessage(msg.message)) {
// queue user input events for later processing
d->queuedUserInputEvents.append(msg);
continue;
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index 33753ed507..600c6c38fd 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -43,6 +43,8 @@
#include <QtCore/QThread>
#include <QtCore/QHash>
#include <QtCore/QMutex>
+#include <QtCore/QSemaphore>
+#include <QtCore/QSharedPointer>
#include <QtCore/qfunctions_winrt.h>
#include <private/qabstracteventdispatcher_p.h>
#include <private/qcoreapplication_p.h>
@@ -293,6 +295,26 @@ HRESULT QEventDispatcherWinRT::runOnXamlThread(const std::function<HRESULT ()> &
return QWinRTFunctions::await(op);
}
+HRESULT QEventDispatcherWinRT::runOnMainThread(const std::function<HRESULT()> &delegate, int timeout)
+{
+ if (QThread::currentThread() == QCoreApplication::instance()->thread())
+ return delegate();
+
+ auto semaphore = QSharedPointer<QSemaphore>(new QSemaphore);
+ auto ptrSemaphore = new QSharedPointer<QSemaphore>(semaphore);
+ auto result = QSharedPointer<HRESULT>(new HRESULT);
+ auto ptrResult = new QSharedPointer<HRESULT>(result);
+
+ QMetaObject::invokeMethod(QCoreApplication::instance(), [delegate, ptrSemaphore, ptrResult]() {
+ **ptrResult = delegate();
+ delete ptrResult;
+ (*ptrSemaphore)->release();
+ delete ptrSemaphore;
+ }, nullptr);
+
+ return semaphore->tryAcquire(1, timeout) ? *result : E_FAIL;
+}
+
bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherWinRT);
diff --git a/src/corelib/kernel/qeventdispatcher_winrt_p.h b/src/corelib/kernel/qeventdispatcher_winrt_p.h
index f69bb9cf3f..8b998a7958 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt_p.h
+++ b/src/corelib/kernel/qeventdispatcher_winrt_p.h
@@ -75,6 +75,7 @@ public:
~QEventDispatcherWinRT();
static HRESULT runOnXamlThread(const std::function<HRESULT()> &delegate, bool waitForRun = true);
+ static HRESULT runOnMainThread(const std::function<HRESULT()> &delegate, int timeout = 100);
bool processEvents(QEventLoop::ProcessEventsFlags flags);
bool hasPendingEvents();
diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp
index 6034698349..f1d32b15d1 100644
--- a/src/corelib/kernel/qeventloop.cpp
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -101,10 +101,8 @@ QEventLoop::QEventLoop(QObject *parent)
Q_D(QEventLoop);
if (!QCoreApplication::instance() && QCoreApplicationPrivate::threadRequiresCoreApplication()) {
qWarning("QEventLoop: Cannot be used without QApplication");
- } else if (!d->threadData->hasEventDispatcher()) {
- QAbstractEventDispatcher *eventDispatcher = QThreadPrivate::createEventDispatcher(d->threadData);
- d->threadData->eventDispatcher.storeRelease(eventDispatcher);
- eventDispatcher->startingUp();
+ } else {
+ d->threadData->ensureEventDispatcher();
}
}
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 27138dd075..6c17535f07 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -50,7 +50,9 @@
#include <qthread.h>
#include <qvariant.h>
#include <qdebug.h>
+#if QT_CONFIG(thread)
#include <qsemaphore.h>
+#endif
#include "private/qobject_p.h"
#include "private/qmetaobject_p.h"
@@ -968,10 +970,24 @@ static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, co
int QMetaObject::indexOfEnumerator(const char *name) const
{
const QMetaObject *m = this;
+ const int intsPerEnum = priv(m->d.data)->revision >= 8 ? 5 : 4;
+ while (m) {
+ const QMetaObjectPrivate *d = priv(m->d.data);
+ for (int i = d->enumeratorCount - 1; i >= 0; --i) {
+ const char *prop = rawStringData(m, m->d.data[d->enumeratorData + intsPerEnum * i]);
+ if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
+ i += m->enumeratorOffset();
+ return i;
+ }
+ }
+ m = m->d.superdata;
+ }
+ // Check alias names:
+ m = this;
while (m) {
const QMetaObjectPrivate *d = priv(m->d.data);
for (int i = d->enumeratorCount - 1; i >= 0; --i) {
- const char *prop = rawStringData(m, m->d.data[d->enumeratorData + 4*i]);
+ const char *prop = rawStringData(m, m->d.data[d->enumeratorData + intsPerEnum * i + 1]);
if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
i += m->enumeratorOffset();
return i;
@@ -1086,10 +1102,11 @@ QMetaEnum QMetaObject::enumerator(int index) const
if (i < 0 && d.superdata)
return d.superdata->enumerator(index);
+ const int intsPerEnum = priv(d.data)->revision >= 8 ? 5 : 4;
QMetaEnum result;
if (i >= 0 && i < priv(d.data)->enumeratorCount) {
result.mobj = this;
- result.handle = priv(d.data)->enumeratorData + 4*i;
+ result.handle = priv(d.data)->enumeratorData + intsPerEnum * i;
}
return result;
}
@@ -1525,14 +1542,14 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 1, types, args));
} else if (type == Qt::BlockingQueuedConnection) {
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
if (currentThread == objectThread)
qWarning("QMetaObject::invokeMethod: Dead lock detected");
QSemaphore semaphore;
QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 0, 0, argv, &semaphore));
semaphore.acquire();
-#endif // QT_NO_THREAD
+#endif // QT_CONFIG(thread)
} else {
qWarning("QMetaObject::invokeMethod: Unknown connection type");
return false;
@@ -2257,7 +2274,7 @@ bool QMetaMethod::invoke(QObject *object,
: Qt::QueuedConnection;
}
-#ifdef QT_NO_THREAD
+#if !QT_CONFIG(thread)
if (connectionType == Qt::BlockingQueuedConnection) {
connectionType = Qt::DirectConnection;
}
@@ -2333,7 +2350,7 @@ bool QMetaMethod::invoke(QObject *object,
QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
0, -1, nargs, types, args));
} else { // blocking queued connection
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
if (currentThread == objectThread) {
qWarning("QMetaMethod::invoke: Dead lock detected in "
"BlockingQueuedConnection: Receiver is %s(%p)",
@@ -2344,7 +2361,7 @@ bool QMetaMethod::invoke(QObject *object,
QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
0, -1, 0, 0, param, &semaphore));
semaphore.acquire();
-#endif // QT_NO_THREAD
+#endif // QT_CONFIG(thread)
}
return true;
}
@@ -2552,12 +2569,15 @@ bool QMetaMethod::invokeOnGadget(void* gadget, QGenericReturnArgument returnValu
*/
/*!
- Returns the name of the enumerator (without the scope).
+ Returns the name of the type (without the scope).
+
+ For example, the Qt::Key enumeration has \c
+ Key as the type name and \l Qt as the scope.
- For example, the Qt::AlignmentFlag enumeration has \c
- AlignmentFlag as the name and \l Qt as the scope.
+ For flags this returns the name of the flag type, not the
+ name of the enum type.
- \sa isValid(), scope()
+ \sa isValid(), scope(), enumName()
*/
const char *QMetaEnum::name() const
{
@@ -2567,6 +2587,28 @@ const char *QMetaEnum::name() const
}
/*!
+ Returns the enum name of the flag (without the scope).
+
+ For example, the Qt::AlignmentFlag flag has \c
+ AlignmentFlag as the enum name, but \c Alignment as as the type name.
+ Non flag enums has the same type and enum names.
+
+ Enum names have the same scope as the type name.
+
+ \since 5.12
+ \sa isValid(), name()
+*/
+const char *QMetaEnum::enumName() const
+{
+ if (!mobj)
+ return 0;
+ const bool rev8p = priv(mobj->d.data)->revision >= 8;
+ if (rev8p)
+ return rawStringData(mobj, mobj->d.data[handle + 1]);
+ return name();
+}
+
+/*!
Returns the number of keys.
\sa key()
@@ -2575,10 +2617,10 @@ int QMetaEnum::keyCount() const
{
if (!mobj)
return 0;
- return mobj->d.data[handle + 2];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ return mobj->d.data[handle + offset];
}
-
/*!
Returns the key with the given \a index, or 0 if no such key exists.
@@ -2588,8 +2630,9 @@ const char *QMetaEnum::key(int index) const
{
if (!mobj)
return 0;
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
if (index >= 0 && index < count)
return rawStringData(mobj, mobj->d.data[data + 2*index]);
return 0;
@@ -2605,8 +2648,9 @@ int QMetaEnum::value(int index) const
{
if (!mobj)
return 0;
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
if (index >= 0 && index < count)
return mobj->d.data[data + 2*index + 1];
return -1;
@@ -2624,7 +2668,8 @@ int QMetaEnum::value(int index) const
*/
bool QMetaEnum::isFlag() const
{
- return mobj && mobj->d.data[handle + 1] & EnumIsFlag;
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 2 : 1;
+ return mobj && mobj->d.data[handle + offset] & EnumIsFlag;
}
/*!
@@ -2635,7 +2680,8 @@ bool QMetaEnum::isFlag() const
*/
bool QMetaEnum::isScoped() const
{
- return mobj && mobj->d.data[handle + 1] & EnumIsScoped;
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 2 : 1;
+ return mobj && mobj->d.data[handle + offset] & EnumIsScoped;
}
/*!
@@ -2677,8 +2723,9 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
scope = s - key - 1;
key += scope + 2;
}
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
for (int i = 0; i < count; ++i) {
const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
if ((!scope || (className.size() == int(scope) && strncmp(qualified_key, className.constData(), scope) == 0))
@@ -2703,8 +2750,9 @@ const char* QMetaEnum::valueToKey(int value) const
{
if (!mobj)
return 0;
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
for (int i = 0; i < count; ++i)
if (value == (int)mobj->d.data[data + 2*i + 1])
return rawStringData(mobj, mobj->d.data[data + 2*i]);
@@ -2735,8 +2783,9 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const
return 0;
// ### TODO write proper code: do not allocate memory, so we can go nothrow
int value = 0;
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
for (const QStringRef &untrimmed : splitKeys) {
const QStringRef trimmed = untrimmed.trimmed();
QByteArray qualified_key = trimmed.toLatin1();
@@ -2778,8 +2827,9 @@ QByteArray QMetaEnum::valueToKeys(int value) const
QByteArray keys;
if (!mobj)
return keys;
- int count = mobj->d.data[handle + 2];
- int data = mobj->d.data[handle + 3];
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
+ int count = mobj->d.data[handle + offset];
+ int data = mobj->d.data[handle + offset + 1];
int v = value;
// reverse iterate to ensure values like Qt::Dialog=0x2|Qt::Window are processed first.
for (int i = count - 1; i >= 0; --i) {
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
index 51df8faad3..51ace3d5f7 100644
--- a/src/corelib/kernel/qmetaobject.h
+++ b/src/corelib/kernel/qmetaobject.h
@@ -209,6 +209,7 @@ public:
Q_DECL_CONSTEXPR inline QMetaEnum() : mobj(nullptr), handle(0) {}
const char *name() const;
+ const char *enumName() const;
bool isFlag() const;
bool isScoped() const;
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
index 434ef84808..4df9a8de77 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -171,7 +171,8 @@ class QMutex;
struct QMetaObjectPrivate
{
// revision 7 is Qt 5.0 everything lower is not supported
- enum { OutputRevision = 7 }; // Used by moc, qmetaobjectbuilder and qdbus
+ // revision 8 is Qt 5.12: It adds the enum name to QMetaEnum
+ enum { OutputRevision = 8 }; // Used by moc, qmetaobjectbuilder and qdbus
int revision;
int className;
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index e3b70638c6..d2030f0275 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -190,11 +190,12 @@ class QMetaEnumBuilderPrivate
{
public:
QMetaEnumBuilderPrivate(const QByteArray& _name)
- : name(_name), isFlag(false), isScoped(false)
+ : name(_name), enumName(_name), isFlag(false), isScoped(false)
{
}
QByteArray name;
+ QByteArray enumName;
bool isFlag;
bool isScoped;
QList<QByteArray> keys;
@@ -637,6 +638,7 @@ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
{
QMetaEnumBuilder en = addEnumerator(prototype.name());
+ en.setEnumName(prototype.enumName());
en.setIsFlag(prototype.isFlag());
en.setIsScoped(prototype.isScoped());
int count = prototype.keyCount();
@@ -1216,7 +1218,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
- int(d->methods.size()) // return "parameters" don't have names
- int(d->constructors.size()); // "this" parameters don't have names
if (buf) {
- Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QMetaObjectBuilder should generate the same version as moc");
+ Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 8, "QMetaObjectBuilder should generate the same version as moc");
pmeta->revision = QMetaObjectPrivate::OutputRevision;
pmeta->flags = d->flags;
pmeta->className = 0; // Class name is always the first string.
@@ -1244,7 +1246,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
pmeta->enumeratorCount = int(d->enumerators.size());
pmeta->enumeratorData = dataIndex;
- dataIndex += 4 * int(d->enumerators.size());
+ dataIndex += 5 * int(d->enumerators.size());
pmeta->constructorCount = int(d->constructors.size());
pmeta->constructorData = dataIndex;
@@ -1261,7 +1263,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
dataIndex += int(d->properties.size());
if (hasRevisionedProperties)
dataIndex += int(d->properties.size());
- dataIndex += 4 * int(d->enumerators.size());
+ dataIndex += 5 * int(d->enumerators.size());
dataIndex += 5 * int(d->constructors.size());
}
@@ -1410,15 +1412,17 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_ASSERT(!buf || dataIndex == pmeta->enumeratorData);
for (const auto &enumerator : d->enumerators) {
int name = strings.enter(enumerator.name);
+ int enumName = strings.enter(enumerator.enumName);
int isFlag = enumerator.isFlag ? EnumIsFlag : 0;
int isScoped = enumerator.isScoped ? EnumIsScoped : 0;
int count = enumerator.keys.size();
int enumOffset = enumIndex;
if (buf) {
data[dataIndex] = name;
- data[dataIndex + 1] = isFlag | isScoped;
- data[dataIndex + 2] = count;
- data[dataIndex + 3] = enumOffset;
+ data[dataIndex + 1] = enumName;
+ data[dataIndex + 2] = isFlag | isScoped;
+ data[dataIndex + 3] = count;
+ data[dataIndex + 4] = enumOffset;
}
for (int key = 0; key < count; ++key) {
int keyIndex = strings.enter(enumerator.keys[key]);
@@ -1427,7 +1431,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
data[enumOffset++] = enumerator.values[key];
}
}
- dataIndex += 4;
+ dataIndex += 5;
enumIndex += 2 * count;
}
@@ -2599,7 +2603,7 @@ QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const
*/
/*!
- Returns the name of the enumerator (without the scope).
+ Returns the type name of the enumerator (without the scope).
*/
QByteArray QMetaEnumBuilder::name() const
{
@@ -2611,6 +2615,33 @@ QByteArray QMetaEnumBuilder::name() const
}
/*!
+ Returns the enum name of the enumerator (without the scope).
+
+ \since 5.12
+*/
+QByteArray QMetaEnumBuilder::enumName() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->enumName;
+ else
+ return QByteArray();
+}
+
+/*!
+ Sets this enumerator to have the enum name \c alias.
+
+ \since 5.12
+ \sa isFlag(), enumName()
+*/
+void QMetaEnumBuilder::setEnumName(const QByteArray &alias)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ d->enumName = alias;
+}
+
+/*!
Returns \c true if this enumerator is used as a flag; otherwise returns
false.
diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h
index 03b2afaebc..781d206e0b 100644
--- a/src/corelib/kernel/qmetaobjectbuilder_p.h
+++ b/src/corelib/kernel/qmetaobjectbuilder_p.h
@@ -297,6 +297,9 @@ public:
QByteArray name() const;
+ QByteArray enumName() const;
+ void setEnumName(const QByteArray &alias);
+
bool isFlag() const;
void setIsFlag(bool value);
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index fc40668c9a..76e3d0d014 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -65,6 +65,9 @@
# include "qjsonobject.h"
# include "qjsonarray.h"
# include "qjsondocument.h"
+# include "qcborvalue.h"
+# include "qcborarray.h"
+# include "qcbormap.h"
# include "qbytearraylist.h"
#endif
@@ -316,7 +319,7 @@ struct DefinedTypesFilter {
\omitvalue WeakPointerToQObject
\omitvalue TrackingPointerToQObject
\omitvalue WasDeclaredAsMetaType
- \omitvalue IsGadget This type is a Q_GADGET and it's corresponding QMetaObject can be accessed with QMetaType::metaObject Since 5.5.
+ \omitvalue IsGadget \omit This type is a Q_GADGET and it's corresponding QMetaObject can be accessed with QMetaType::metaObject Since 5.5. \endomit
\omitvalue PointerToGadget
*/
@@ -835,15 +838,14 @@ void QMetaType::registerStreamOperators(int idx, SaveOperator saveOp,
}
#endif // QT_NO_DATASTREAM
-#if defined(Q_COMPILER_CONSTEXPR) || (defined(Q_CC_MSVC) && Q_CC_MSVC >= 1900)
// We don't officially support constexpr in MSVC 2015, but the limited support it
// has is enough for the code below.
-# define STRINGIFY_TYPE_NAME(MetaTypeName, TypeId, RealName) \
+#define STRINGIFY_TYPE_NAME(MetaTypeName, TypeId, RealName) \
#RealName "\0"
-# define CALCULATE_TYPE_LEN(MetaTypeName, TypeId, RealName) \
+#define CALCULATE_TYPE_LEN(MetaTypeName, TypeId, RealName) \
short(sizeof(#RealName)),
-# define MAP_TYPE_ID_TO_IDX(MetaTypeName, TypeId, RealName) \
+#define MAP_TYPE_ID_TO_IDX(MetaTypeName, TypeId, RealName) \
TypeId,
namespace {
@@ -911,10 +913,9 @@ template <int... TypeIds> struct MetaTypeOffsets<QtPrivate::IndexesList<TypeIds.
} // anonymous namespace
constexpr MetaTypeOffsets<QtPrivate::Indexes<QMetaType::HighestInternalId + 1>::Value> metaTypeNames {};
-# undef STRINGIFY_TYPE_NAME
-# undef CALCULATE_TYPE_LEN
-# undef MAP_TYPE_ID_TO_IDX
-#endif
+#undef STRINGIFY_TYPE_NAME
+#undef CALCULATE_TYPE_LEN
+#undef MAP_TYPE_ID_TO_IDX
/*!
Returns the type name associated with the given \a typeId, or a null
@@ -926,20 +927,8 @@ constexpr MetaTypeOffsets<QtPrivate::Indexes<QMetaType::HighestInternalId + 1>::
const char *QMetaType::typeName(int typeId)
{
const uint type = typeId;
-#define QT_METATYPE_TYPEID_TYPENAME_CONVERTER(MetaTypeName, TypeId, RealName) \
- case QMetaType::MetaTypeName: return #RealName; break;
-
if (Q_LIKELY(type <= QMetaType::HighestInternalId)) {
-#if defined(Q_COMPILER_CONSTEXPR) || (defined(Q_CC_MSVC) && Q_CC_MSVC >= 1900)
return metaTypeNames[typeId];
-#else
- switch (QMetaType::Type(type)) {
- QT_FOR_EACH_STATIC_TYPE(QT_METATYPE_TYPEID_TYPENAME_CONVERTER)
- case QMetaType::UnknownType:
- case QMetaType::User:
- break;
- }
-#endif
} else if (Q_UNLIKELY(type < QMetaType::User)) {
return nullptr; // It can happen when someone cast int to QVariant::Type, we should not crash...
}
@@ -1360,6 +1349,9 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
case QMetaType::QJsonObject:
case QMetaType::QJsonArray:
case QMetaType::QJsonDocument:
+ case QMetaType::QCborValue:
+ case QMetaType::QCborArray:
+ case QMetaType::QCborMap:
return false;
case QMetaType::Nullptr:
stream << *static_cast<const std::nullptr_t *>(data);
@@ -1498,6 +1490,9 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data)
case QMetaType::QEasingCurve:
stream << *static_cast<const NS(QEasingCurve)*>(data);
break;
+ case QMetaType::QCborSimpleType:
+ stream << *static_cast<const quint8 *>(data);
+ break;
#endif // QT_BOOTSTRAPPED
case QMetaType::QFont:
case QMetaType::QPixmap:
@@ -1586,6 +1581,9 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
case QMetaType::QJsonObject:
case QMetaType::QJsonArray:
case QMetaType::QJsonDocument:
+ case QMetaType::QCborValue:
+ case QMetaType::QCborArray:
+ case QMetaType::QCborMap:
return false;
case QMetaType::Nullptr:
stream >> *static_cast<std::nullptr_t *>(data);
@@ -1730,6 +1728,9 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
case QMetaType::QEasingCurve:
stream >> *static_cast< NS(QEasingCurve)*>(data);
break;
+ case QMetaType::QCborSimpleType:
+ stream >> *static_cast<quint8 *>(data);
+ break;
#endif // QT_BOOTSTRAPPED
case QMetaType::QFont:
case QMetaType::QPixmap:
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index cf68752f85..48cbe7f00b 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
** Contact: https://www.qt.io/licensing/
**
@@ -60,6 +61,9 @@
QT_BEGIN_NAMESPACE
+// from qcborcommon.h
+enum class QCborSimpleType : quint8;
+
template <typename T>
struct QMetaTypeId2;
@@ -85,6 +89,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(Float, 38, float) \
F(SChar, 40, signed char) \
F(Nullptr, 51, std::nullptr_t) \
+ F(QCborSimpleType, 52, QCborSimpleType) \
#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
F(VoidStar, 31, void*) \
@@ -125,6 +130,9 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId();
F(QJsonObject, 46, QJsonObject) \
F(QJsonArray, 47, QJsonArray) \
F(QJsonDocument, 48, QJsonDocument) \
+ F(QCborValue, 53, QCborValue) \
+ F(QCborArray, 54, QCborArray) \
+ F(QCborMap, 55, QCborMap) \
QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)
#define QT_FOR_EACH_STATIC_CORE_POINTER(F)\
@@ -420,7 +428,7 @@ public:
QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID)
FirstCoreType = Bool,
- LastCoreType = Nullptr,
+ LastCoreType = QCborMap,
FirstGuiType = QFont,
LastGuiType = QPolygonF,
FirstWidgetsType = QSizePolicy,
@@ -450,13 +458,18 @@ public:
Void = 43,
Nullptr = 51,
QVariantMap = 8, QVariantList = 9, QVariantHash = 28,
+ QCborSimpleType = 52, QCborValue = 53, QCborArray = 54, QCborMap = 55,
+
+ // Gui types
QFont = 64, QPixmap = 65, QBrush = 66, QColor = 67, QPalette = 68,
QIcon = 69, QImage = 70, QPolygon = 71, QRegion = 72, QBitmap = 73,
QCursor = 74, QKeySequence = 75, QPen = 76, QTextLength = 77, QTextFormat = 78,
QMatrix = 79, QTransform = 80, QMatrix4x4 = 81, QVector2D = 82,
QVector3D = 83, QVector4D = 84, QQuaternion = 85, QPolygonF = 86,
+
+ // Widget types
QSizePolicy = 121,
- LastCoreType = Nullptr,
+ LastCoreType = QCborMap,
LastGuiType = QPolygonF,
User = 1024
};
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index cef20a5d12..76f43db8d7 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -196,6 +196,10 @@ struct TypeDefinition {
// Ignore these types, as incomplete
#ifdef QT_BOOTSTRAPPED
template<> struct TypeDefinition<QBitArray> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QCborArray> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QCborMap> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QCborSimpleType> { static const bool IsAvailable = false; };
+template<> struct TypeDefinition<QCborValue> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QEasingCurve> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QJsonArray> { static const bool IsAvailable = false; };
template<> struct TypeDefinition<QJsonDocument> { static const bool IsAvailable = false; };
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index c6fe787e03..6254330d25 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -59,11 +59,14 @@
#include <qpair.h>
#include <qvarlengtharray.h>
#include <qset.h>
+#if QT_CONFIG(thread)
#include <qsemaphore.h>
+#endif
#include <qsharedpointer.h>
#include <private/qorderedmutexlocker_p.h>
#include <private/qhooks_p.h>
+#include <qtcore_tracepoints_p.h>
#include <new>
@@ -487,7 +490,7 @@ QMetaCallEvent::~QMetaCallEvent()
free(types_);
free(args_);
}
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
if (semaphore_)
semaphore_->release();
#endif
@@ -820,6 +823,7 @@ QObject::QObject(QObject *parent)
#endif
if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
+ Q_TRACE(QObject_ctor, this);
}
/*!
@@ -855,6 +859,7 @@ QObject::QObject(QObjectPrivate &dd, QObject *parent)
#endif
if (Q_UNLIKELY(qtHookData[QHooks::AddQObject]))
reinterpret_cast<QHooks::AddQObjectCallback>(qtHookData[QHooks::AddQObject])(this);
+ Q_TRACE(QObject_ctor, this);
}
/*!
@@ -1030,6 +1035,8 @@ QObject::~QObject()
if (Q_UNLIKELY(qtHookData[QHooks::RemoveQObject]))
reinterpret_cast<QHooks::RemoveQObjectCallback>(qtHookData[QHooks::RemoveQObject])(this);
+ Q_TRACE(QObject_dtor, this);
+
if (d->parent) // remove it from parent object
d->setParent_helper(0);
}
@@ -3722,7 +3729,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
|| (c->connectionType == Qt::QueuedConnection)) {
queued_activate(sender, signal_index, c, argv ? argv : empty_argv, locker);
continue;
-#ifndef QT_NO_THREAD
+#if QT_CONFIG(thread)
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
if (receiverInSameThread) {
qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
@@ -4534,6 +4541,11 @@ QDebug operator<<(QDebug dbg, const QObject *o)
invoked using QMetaObject::invokeMethod().
Since \c normalMethod() function is not registered in this way, it cannot
be invoked using QMetaObject::invokeMethod().
+
+ If an invokable member function returns a pointer to a QObject or a
+ subclass of QObject and it is invoked from QML, special ownership rules
+ apply. See \l{qtqml-cppintegration-data.html}{Data Type Conversion Between QML and C++}
+ for more information.
*/
/*!
@@ -4681,7 +4693,7 @@ void qDeleteInEventHandler(QObject *o)
The signal must be a function declared as a signal in the header.
The slot function can be any function or functor that can be connected
to the signal.
- A function can be connected to a given signal if the signal as at
+ A function can be connected to a given signal if the signal has at
least as many argument as the slot. A functor can be connected to a signal
if they have exactly the same number of arguments. There must exist implicit
conversion between the types of the corresponding arguments in the
@@ -4721,7 +4733,7 @@ void qDeleteInEventHandler(QObject *o)
The signal must be a function declared as a signal in the header.
The slot function can be any function or functor that can be connected
to the signal.
- A function can be connected to a given signal if the signal as at
+ A function can be connected to a given signal if the signal has at
least as many argument as the slot. A functor can be connected to a signal
if they have exactly the same number of arguments. There must exist implicit
conversion between the types of the corresponding arguments in the
@@ -4804,7 +4816,12 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s
const int *types, const QMetaObject *senderMetaObject)
{
if (!sender || !receiver || !slotObj || !senderMetaObject) {
- qWarning("QObject::connect: invalid null parameter");
+ const char *senderString = sender ? sender->metaObject()->className()
+ : senderMetaObject ? senderMetaObject->className()
+ : "Unknown";
+ const char *receiverString = receiver ? receiver->metaObject()->className()
+ : "Unknown";
+ qWarning("QObject::connect(%s, %s): invalid null parameter", senderString, receiverString);
if (slotObj)
slotObj->destroyIfLastRef();
return QMetaObject::Connection();
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h
index a6ad00ea22..8afff1fb98 100644
--- a/src/corelib/kernel/qobjectdefs_impl.h
+++ b/src/corelib/kernel/qobjectdefs_impl.h
@@ -112,13 +112,31 @@ namespace QtPrivate {
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.
*/
- 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<class T> using InvokeGenSeq = typename T::Type;
+
+ template<int...> struct IndexesList { using Type = IndexesList; };
+
+ template<int N, class S1, class S2> struct ConcatSeqImpl;
+
+ template<int N, int... I1, int... I2>
+ struct ConcatSeqImpl<N, IndexesList<I1...>, IndexesList<I2...>>
+ : IndexesList<I1..., (N + I2)...>{};
+
+ template<int N, class S1, class S2>
+ using ConcatSeq = InvokeGenSeq<ConcatSeqImpl<N, S1, S2>>;
+
+ template<int N> struct GenSeq;
+ template<int N> using makeIndexSequence = InvokeGenSeq<GenSeq<N>>;
+
+ template<int N>
+ struct GenSeq : ConcatSeq<N/2, makeIndexSequence<N/2>, makeIndexSequence<N - N/2>>{};
+
+ template<> struct GenSeq<0> : IndexesList<>{};
+ template<> struct GenSeq<1> : IndexesList<0>{};
+
+ template<int N>
+ struct Indexes { using Value = makeIndexSequence<N>; };
+
template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; };
template <typename, typename, typename, typename> struct FunctorCall;
diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp
index fc825257ec..53c3136857 100644
--- a/src/corelib/kernel/qsystemerror.cpp
+++ b/src/corelib/kernel/qsystemerror.cpp
@@ -49,7 +49,7 @@
QT_BEGIN_NAMESPACE
-#if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \
+#if !defined(Q_OS_WIN) && QT_CONFIG(thread) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \
defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L
namespace {
// There are two incompatible versions of strerror_r:
@@ -130,7 +130,7 @@ static QString standardLibraryErrorString(int errorCode)
s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device");
break;
default: {
- #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX)
+ #if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX)
QByteArray buf(1024, Qt::Uninitialized);
ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf);
#else
diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp
index 86992ce10b..5437210699 100644
--- a/src/corelib/kernel/qtcore_eval.cpp
+++ b/src/corelib/kernel/qtcore_eval.cpp
@@ -168,7 +168,7 @@ public:
}
}
- void timerEvent(QTimerEvent *e) {
+ void timerEvent(QTimerEvent *e) override {
if (e->timerId() == warn) {
killTimer(warn);
fprintf(stderr, "%s\n", will_shutdown_1min);
diff --git a/src/corelib/kernel/qtestsupport_core.cpp b/src/corelib/kernel/qtestsupport_core.cpp
new file mode 100644
index 0000000000..240e5795db
--- /dev/null
+++ b/src/corelib/kernel/qtestsupport_core.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtestsupport_core.h"
+
+#ifdef Q_OS_WIN
+#include <qt_windows.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT void QTestPrivate::qSleep(int ms)
+{
+ Q_ASSERT(ms > 0);
+
+#if defined(Q_OS_WINRT)
+ WaitForSingleObjectEx(GetCurrentThread(), ms, true);
+#elif defined(Q_OS_WIN)
+ Sleep(uint(ms));
+#else
+ struct timespec ts = { time_t(ms / 1000), (ms % 1000) * 1000 * 1000 };
+ nanosleep(&ts, NULL);
+#endif
+}
+
+/*! \fn template <typename Functor> bool qWaitFor(Functor predicate, int timeout)
+ \relates QTest
+
+ Waits for \a timeout milliseconds or until the \a predicate returns true.
+
+ Returns \c true if the \a predicate returned true at any point, otherwise returns \c false.
+
+ Example:
+
+ \code
+ MyObject obj;
+ obj.startup();
+ QTest::qWaitFor([&]() {
+ return obj.isReady();
+ }, 3000);
+ \endcode
+
+ The code above will wait for the object to become ready, for a
+ maximum of three seconds.
+
+ \since 5.10
+*/
+
+
+/*! \fn void qWait(int ms)
+ \relates QTest
+
+ Waits for \a ms milliseconds. While waiting, events will be processed and
+ your test will stay responsive to user interface events or network communication.
+
+ Example:
+
+ \code
+ int i = 0;
+ while (myNetworkServerNotResponding() && i++ < 50)
+ QTest::qWait(250);
+ \endcode
+
+ The code above will wait until the network server is responding for a
+ maximum of about 12.5 seconds.
+
+ \sa QTest::qSleep(), QSignalSpy::wait()
+*/
+Q_CORE_EXPORT void QTest::qWait(int ms)
+{
+ // Ideally this method would be implemented in terms of qWaitFor, with
+ // a predicate that always returns false, but due to a compiler bug in
+ // GCC 6 we can't do that.
+
+ Q_ASSERT(QCoreApplication::instance());
+
+ QDeadlineTimer timer(ms, Qt::PreciseTimer);
+ int remaining = ms;
+ do {
+ QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
+ QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete);
+ remaining = timer.remainingTime();
+ if (remaining <= 0)
+ break;
+ QTestPrivate::qSleep(qMin(10, remaining));
+ remaining = timer.remainingTime();
+ } while (remaining > 0);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtestsupport_core.h b/src/corelib/kernel/qtestsupport_core.h
new file mode 100644
index 0000000000..7fc0054580
--- /dev/null
+++ b/src/corelib/kernel/qtestsupport_core.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTESTSUPPORT_CORE_H
+#define QTESTSUPPORT_CORE_H
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdeadlinetimer.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QTestPrivate {
+Q_CORE_EXPORT void qSleep(int ms);
+}
+
+namespace QTest {
+
+template <typename Functor>
+Q_REQUIRED_RESULT static bool qWaitFor(Functor predicate, int timeout = 5000)
+{
+ // We should not spin the event loop in case the predicate is already true,
+ // otherwise we might send new events that invalidate the predicate.
+ if (predicate())
+ return true;
+
+ // qWait() is expected to spin the event loop, even when called with a small
+ // timeout like 1ms, so we we can't use a simple while-loop here based on
+ // the deadline timer not having timed out. Use do-while instead.
+
+ int remaining = timeout;
+ QDeadlineTimer deadline(remaining, Qt::PreciseTimer);
+
+ do {
+ QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+
+ remaining = deadline.remainingTime();
+ if (remaining > 0)
+ QTestPrivate::qSleep(qMin(10, remaining));
+
+ if (predicate())
+ return true;
+
+ remaining = deadline.remainingTime();
+ } while (remaining > 0);
+
+ return predicate(); // Last chance
+}
+
+Q_CORE_EXPORT void qWait(int ms);
+
+} // namespace QTest
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index 3edd1f056e..d8d520ff58 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -571,6 +571,48 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv
*/
/*!
+ \fn template<typename Functor> QMetaObject::Connection connectTo(Functor functor, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \since 5.12
+ \overload
+
+ Creates a connection from the timeout() signal to \a functor, and returns a
+ handle to the connection.
+
+ This method is provided for convenience.
+ It's equivalent to calling \c {QObject::connect(timer, &QTimer::timeout, timer, functor, connectionType)}.
+
+ \sa QObject::connect(), timeout()
+*/
+
+/*!
+ \fn template<typename Functor> QMetaObject::Connection connectTo(QObject *context, Functor functor, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \since 5.12
+ \overload connectTo()
+
+ Creates a connection from the timeout() signal to \a functor to be placed in a specific
+ event loop of \a context, and returns a handle to the connection.
+
+ This method is provided for convenience. It's equivalent to calling
+ \c {QObject::connect(timer, &QTimer::timeout, context, functor, connectionType)}.
+
+ \sa QObject::connect(), timeout()
+*/
+
+/*!
+ \fn template<typename PointerToMemberFunction> QMetaObject::Connection connectTo(QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \since 5.12
+ \overload connectTo()
+
+ Creates a connection from the timeout() signal to the \a method in the \a receiver object. Returns
+ a handle to the connection.
+
+ This method is provided for convenience. It's equivalent to calling
+ \c {QObject::connect(timer, &QTimer::timeout, receiver, method, connectionType)}.
+
+ \sa QObject::connect(), timeout()
+*/
+
+/*!
\fn void QTimer::start(std::chrono::milliseconds msec)
\since 5.8
\overload
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
index e6db586aa0..f5c04c7f70 100644
--- a/src/corelib/kernel/qtimer.h
+++ b/src/corelib/kernel/qtimer.h
@@ -96,6 +96,12 @@ public:
static void singleShot(int msec, const QObject *context, Functor functor);
template<typename Functor, int>
static void singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor);
+ template <typename Functor>
+ QMetaObject::Connection connectTo(Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
+ template <typename Functor>
+ QMetaObject::Connection connectTo(const QObject *context, Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
+ template <typename PointerToMemberFunction>
+ QMetaObject::Connection connectTo(const QObject *receiver, PointerToMemberFunction slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
#else
// singleShot to a QObject slot
template <typename Duration, typename Func1>
@@ -135,14 +141,14 @@ public:
template <typename Duration, typename Func1>
static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
!std::is_same<const char*, Func1>::value, void>::type
- singleShot(Duration interval, QObject *context, Func1 slot)
+ singleShot(Duration interval, const QObject *context, Func1 slot)
{
singleShot(interval, defaultTypeFor(interval), context, std::move(slot));
}
template <typename Duration, typename Func1>
static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
!std::is_same<const char*, Func1>::value, void>::type
- singleShot(Duration interval, Qt::TimerType timerType, QObject *context, Func1 slot)
+ singleShot(Duration interval, Qt::TimerType timerType, const QObject *context, Func1 slot)
{
//compilation error if the slot has arguments.
typedef QtPrivate::FunctionPointer<Func1> SlotType;
@@ -152,6 +158,13 @@ public:
new QtPrivate::QFunctorSlotObject<Func1, 0,
typename QtPrivate::List_Left<void, 0>::Value, void>(std::move(slot)));
}
+
+ template <typename ... Args>
+ QMetaObject::Connection connectTo(Args && ...args)
+ {
+ return QObject::connect(this, &QTimer::timeout, std::forward<Args>(args)... );
+ }
+
#endif
public Q_SLOTS:
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index c868f6d266..744bbfbff5 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -49,6 +49,7 @@
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
#include "qdatastream.h"
+#include "qendian.h"
#include "qfile.h"
#include "qmap.h"
#include "qalgorithms.h"
@@ -532,7 +533,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
// memory, so no need to use QFile to copy it again.
Q_ASSERT(!d->resource);
d->resource = new QResource(realname);
- if (resource->isValid() && !resource->isCompressed() && resource->size() > MagicLength
+ if (resource->isValid() && !resource->isCompressed() && resource->size() >= MagicLength
&& !memcmp(resource->data(), magic, MagicLength)) {
d->unmapLength = resource->size();
d->unmapPointer = reinterpret_cast<char *>(const_cast<uchar *>(resource->data()));
@@ -552,7 +553,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
return false;
qint64 fileSize = file.size();
- if (fileSize <= MagicLength || quint32(-1) <= fileSize)
+ if (fileSize < MagicLength || quint32(-1) <= fileSize)
return false;
{
@@ -857,8 +858,6 @@ bool QTranslatorPrivate::do_load(const uchar *data, int len, const QString &dire
data += blockLen;
}
- if (dependencies.isEmpty() && (!offsetArray || !messageArray))
- ok = false;
if (ok && !isValidNumerusRules(numerusRulesArray, numerusRulesLength))
ok = false;
if (ok) {
@@ -957,8 +956,8 @@ end:
return QString();
QString str = QString((const QChar *)tn, tn_length/2);
if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
- for (int i = 0; i < str.length(); ++i)
- str[i] = QChar((str.at(i).unicode() >> 8) + ((str.at(i).unicode() << 8) & 0xff00));
+ QChar *data = str.data();
+ qbswap<sizeof(QChar)>(data, str.length(), data);
}
return str;
}
@@ -1137,8 +1136,8 @@ QString QTranslator::translate(const char *context, const char *sourceText, cons
bool QTranslator::isEmpty() const
{
Q_D(const QTranslator);
- return !d->unmapPointer && !d->unmapLength && !d->messageArray &&
- !d->offsetArray && !d->contextArray && d->subTranslators.isEmpty();
+ return !d->messageArray && !d->offsetArray && !d->contextArray
+ && d->subTranslators.isEmpty();
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 6192b66487..4d1aa911f7 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
** Contact: https://www.qt.io/licensing/
**
@@ -60,6 +60,9 @@
#include "qabstractitemmodel.h"
#endif
#ifndef QT_BOOTSTRAPPED
+#include "qcborarray.h"
+#include "qcborcommon.h"
+#include "qcbormap.h"
#include "qjsonvalue.h"
#include "qjsonobject.h"
#include "qjsonarray.h"
@@ -167,6 +170,8 @@ static qlonglong qMetaTypeNumber(const QVariant::Private *d)
#ifndef QT_BOOTSTRAPPED
case QMetaType::QJsonValue:
return v_cast<QJsonValue>(d)->toDouble();
+ case QMetaType::QCborValue:
+ return v_cast<QCborValue>(d)->toInteger();
#endif
}
Q_ASSERT(false);
@@ -205,6 +210,10 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
case QVariant::Bool:
return qlonglong(d->data.b);
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isInteger() && !v_cast<QCborValue>(d)->isDouble())
+ break;
+ return qMetaTypeNumber(d);
case QMetaType::QJsonValue:
if (!v_cast<QJsonValue>(d)->isDouble())
break;
@@ -229,7 +238,7 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
}
QMetaType typeInfo(d->type);
- if (typeInfo.flags() & QMetaType::IsEnumeration) {
+ if (typeInfo.flags() & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) {
switch (typeInfo.sizeOf()) {
case 1:
return d->is_shared ? *reinterpret_cast<signed char *>(d->data.shared->ptr) : d->data.sc;
@@ -261,6 +270,8 @@ static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok)
case QMetaType::ULong:
return qreal(qMetaTypeUNumber(d));
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ return v_cast<QCborValue>(d)->toDouble();
case QMetaType::QJsonValue:
return v_cast<QJsonValue>(d)->toDouble();
#endif
@@ -284,6 +295,12 @@ static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok)
case QVariant::Bool:
return qulonglong(d->data.b);
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ if (v_cast<QCborValue>(d)->isDouble())
+ return qulonglong(qConvertToRealNumber(d, ok));
+ if (!v_cast<QCborValue>(d)->isInteger())
+ return false;
+ return qulonglong(qMetaTypeNumber(d));
case QMetaType::QJsonValue:
if (!v_cast<QJsonValue>(d)->isDouble())
break;
@@ -391,6 +408,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
case QVariant::String:
*static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d));
break;
+ case QMetaType::QCborValue:
+ if (v_cast<QCborValue>(d)->isUrl()) {
+ *static_cast<QUrl *>(result) = v_cast<QCborValue>(d)->toUrl();
+ break;
+ }
+ return false;
default:
return false;
}
@@ -476,6 +499,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
else if (!v_cast<QJsonValue>(d)->isNull())
return false;
break;
+ case QMetaType::QCborValue:
+ if (v_cast<QCborValue>(d)->isContainer() || v_cast<QCborValue>(d)->isTag())
+ return false;
+ *str = v_cast<QCborValue>(d)->toVariant().toString();
+ break;
#endif
case QVariant::Uuid:
*str = v_cast<QUuid>(d)->toString();
@@ -621,6 +649,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
case QVariant::String:
*dt = QDateTime::fromString(*v_cast<QString>(d), Qt::ISODate);
break;
+# ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ if (v_cast<QCborValue>(d)->isDateTime())
+ *dt = v_cast<QCborValue>(d)->toDateTime();
+ else
+ return false;
+ break;
+# endif
#endif
case QVariant::Date:
*dt = QDateTime(*v_cast<QDate>(d));
@@ -668,6 +704,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
case QMetaType::Nullptr:
*ba = QByteArray();
break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ if (v_cast<QCborValue>(d)->isByteArray())
+ *ba = v_cast<QCborValue>(d)->toByteArray();
+ else
+ return false;
+ break;
+#endif
default:
#ifndef QT_NO_QOBJECT
{
@@ -746,6 +790,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*b = qMetaTypeUNumber(d) != Q_UINT64_C(0);
break;
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ *b = v_cast<QCborValue>(d)->toBool();
+ if (!v_cast<QCborValue>(d)->isBool())
+ return false;
+ break;
case QMetaType::QJsonValue:
*b = v_cast<QJsonValue>(d)->toBool(false);
if (!v_cast<QJsonValue>(d)->isBool())
@@ -789,6 +838,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*f = double(qMetaTypeUNumber(d));
break;
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ *f = v_cast<QCborValue>(d)->toDouble();
+ if (!v_cast<QCborValue>(d)->isDouble())
+ return false;
+ break;
case QMetaType::QJsonValue:
*f = v_cast<QJsonValue>(d)->toDouble(0.0);
if (!v_cast<QJsonValue>(d)->isDouble())
@@ -832,6 +886,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*f = float(qMetaTypeUNumber(d));
break;
#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ *f = v_cast<QCborValue>(d)->toDouble();
+ if (!v_cast<QCborValue>(d)->isDouble())
+ return false;
+ break;
case QMetaType::QJsonValue:
*f = v_cast<QJsonValue>(d)->toDouble(0.0);
if (!v_cast<QJsonValue>(d)->isDouble())
@@ -856,6 +915,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*static_cast<QVariantList *>(result) =
*static_cast<QList<QVariant> *>(d->data.shared->ptr);
#ifndef QT_BOOTSTRAPPED
+ } else if (d->type == QMetaType::QCborValue) {
+ if (!v_cast<QCborValue>(d)->isArray())
+ return false;
+ *static_cast<QVariantList *>(result) = v_cast<QCborValue>(d)->toArray().toVariantList();
+ } else if (d->type == QMetaType::QCborArray) {
+ *static_cast<QVariantList *>(result) = v_cast<QCborArray>(d)->toVariantList();
} else if (d->type == QMetaType::QJsonValue) {
if (!v_cast<QJsonValue>(d)->isArray())
return false;
@@ -878,6 +943,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
for (auto it = hash->begin(); it != end; ++it)
map->insertMulti(it.key(), it.value());
#ifndef QT_BOOTSTRAPPED
+ } else if (d->type == QMetaType::QCborValue) {
+ if (!v_cast<QCborValue>(d)->isMap())
+ return false;
+ *static_cast<QVariantMap *>(result) = v_cast<QCborValue>(d)->toMap().toVariantMap();
+ } else if (d->type == QMetaType::QCborMap) {
+ *static_cast<QVariantMap *>(result) = v_cast<QCborMap>(d)->toVariantMap();
} else if (d->type == QMetaType::QJsonValue) {
if (!v_cast<QJsonValue>(d)->isObject())
return false;
@@ -900,6 +971,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
for (auto it = map->begin(); it != end; ++it)
hash->insertMulti(it.key(), it.value());
#ifndef QT_BOOTSTRAPPED
+ } else if (d->type == QMetaType::QCborValue) {
+ if (!v_cast<QCborValue>(d)->isMap())
+ return false;
+ *static_cast<QVariantHash *>(result) = v_cast<QCborValue>(d)->toMap().toVariantHash();
+ } else if (d->type == QMetaType::QCborMap) {
+ *static_cast<QVariantHash *>(result) = v_cast<QCborMap>(d)->toVariantHash();
} else if (d->type == QMetaType::QJsonValue) {
if (!v_cast<QJsonValue>(d)->isObject())
return false;
@@ -950,11 +1027,36 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
case QVariant::ByteArray:
*static_cast<QUuid *>(result) = QUuid(*v_cast<QByteArray>(d));
break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isUuid())
+ return false;
+ *static_cast<QUuid *>(result) = v_cast<QCborValue>(d)->toUuid();
+ break;
+#endif
default:
return false;
}
break;
+ case QMetaType::Nullptr:
+ *static_cast<std::nullptr_t *>(result) = nullptr;
+ if (QMetaType::typeFlags(t) & (QMetaType::PointerToGadget | QMetaType::PointerToQObject)
+ || d->type == QMetaType::VoidStar) {
+ if (v_cast<const void *>(d) == nullptr)
+ break;
+ }
#ifndef QT_BOOTSTRAPPED
+ if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isNull())
+ break;
+#endif
+ return false;
+
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QRegularExpression:
+ if (d->type != QMetaType::QCborValue || !v_cast<QCborValue>(d)->isRegularExpression())
+ return false;
+ *static_cast<QRegularExpression *>(result) = v_cast<QCborValue>(d)->toRegularExpression();
+ break;
case QMetaType::QJsonValue:
switch (d->type) {
case QMetaType::Nullptr:
@@ -1005,6 +1107,15 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*static_cast<QJsonValue *>(result) = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
break;
}
+ case QMetaType::QCborValue:
+ *static_cast<QJsonValue *>(result) = v_cast<QCborValue>(d)->toJsonValue();
+ break;
+ case QMetaType::QCborMap:
+ *static_cast<QJsonValue *>(result) = v_cast<QCborMap>(d)->toJsonObject();
+ break;
+ case QMetaType::QCborArray:
+ *static_cast<QJsonValue *>(result) = v_cast<QCborArray>(d)->toJsonArray();
+ break;
default:
*static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Undefined);
return false;
@@ -1028,6 +1139,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
return false;
*static_cast<QJsonArray *>(result) = v_cast<QJsonDocument>(d)->array();
break;
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isArray())
+ return false;
+ *static_cast<QJsonArray *>(result) = v_cast<QCborValue>(d)->toArray().toJsonArray();
+ break;
+ case QMetaType::QCborArray:
+ *static_cast<QJsonArray *>(result) = v_cast<QCborArray>(d)->toJsonArray();
+ break;
default:
return false;
}
@@ -1050,11 +1169,177 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
return false;
*static_cast<QJsonObject *>(result) = v_cast<QJsonDocument>(d)->object();
break;
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isMap())
+ return false;
+ *static_cast<QJsonObject *>(result) = v_cast<QCborValue>(d)->toMap().toJsonObject();
+ break;
+ case QMetaType::QCborMap:
+ *static_cast<QJsonObject *>(result) = v_cast<QCborMap>(d)->toJsonObject();
+ break;
+ default:
+ return false;
+ }
+ break;
+ case QMetaType::QCborSimpleType:
+ if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isSimpleType()) {
+ *static_cast<QCborSimpleType *>(result) = v_cast<QCborValue>(d)->toSimpleType();
+ break;
+ }
+ return false;
+ case QMetaType::QCborValue:
+ switch (d->type) {
+ case QMetaType::Nullptr:
+ *static_cast<QCborValue *>(result) = QCborValue(QCborValue::Null);
+ break;
+ case QVariant::Bool:
+ *static_cast<QCborValue *>(result) = QCborValue(d->data.b);
+ break;
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ case QMetaType::ULong:
+ case QMetaType::Long:
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ case QMetaType::UShort:
+ case QMetaType::UChar:
+ case QMetaType::Char:
+ case QMetaType::SChar:
+ case QMetaType::Short:
+ *static_cast<QCborValue *>(result) = QCborValue(qConvertToNumber(d, ok));
+ Q_ASSERT(ok);
+ break;
+ case QMetaType::Double:
+ case QMetaType::Float:
+ *static_cast<QCborValue *>(result) = QCborValue(qConvertToRealNumber(d, ok));
+ Q_ASSERT(ok);
+ break;
+ case QVariant::String:
+ *static_cast<QCborValue *>(result) = *v_cast<QString>(d);
+ break;
+ case QVariant::StringList:
+ *static_cast<QCborValue *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d));
+ break;
+ case QVariant::ByteArray:
+ *static_cast<QCborValue *>(result) = *v_cast<QByteArray>(d);
+ break;
+ case QVariant::Date:
+ *static_cast<QCborValue *>(result) = QCborValue(QDateTime(*v_cast<QDate>(d)));
+ break;
+ case QVariant::DateTime:
+ *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QDateTime>(d));
+ break;
+ case QVariant::Url:
+ *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUrl>(d));
+ break;
+ case QVariant::RegularExpression:
+ *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QRegularExpression>(d));
+ break;
+ case QVariant::Uuid:
+ *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUuid>(d));
+ break;
+ case QVariant::List:
+ *static_cast<QCborValue *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d));
+ break;
+ case QVariant::Map:
+ *static_cast<QCborValue *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d));
+ break;
+ case QVariant::Hash:
+ *static_cast<QCborValue *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d));
+ break;
+ case QMetaType::QJsonValue:
+ *static_cast<QCborValue *>(result) = QCborValue::fromJsonValue(*v_cast<QJsonValue>(d));
+ break;
+ case QMetaType::QJsonObject:
+ *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d));
+ break;
+ case QMetaType::QJsonArray:
+ *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d));
+ break;
+ case QMetaType::QJsonDocument: {
+ QJsonDocument doc = *v_cast<QJsonDocument>(d);
+ if (doc.isArray())
+ *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(doc.array());
+ else
+ *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(doc.object());
+ break;
+ }
+ case QMetaType::QCborSimpleType:
+ *static_cast<QCborValue *>(result) = *v_cast<QCborSimpleType>(d);
+ break;
+ case QMetaType::QCborMap:
+ *static_cast<QCborValue *>(result) = *v_cast<QCborMap>(d);
+ break;
+ case QMetaType::QCborArray:
+ *static_cast<QCborValue *>(result) = *v_cast<QCborArray>(d);
+ break;
+ default:
+ *static_cast<QCborValue *>(result) = {};
+ return false;
+ }
+ break;
+ case QMetaType::QCborArray:
+ switch (d->type) {
+ case QVariant::StringList:
+ *static_cast<QCborArray *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d));
+ break;
+ case QVariant::List:
+ *static_cast<QCborArray *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d));
+ break;
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isArray())
+ return false;
+ *static_cast<QCborArray *>(result) = v_cast<QCborValue>(d)->toArray();
+ break;
+ case QMetaType::QJsonDocument:
+ if (!v_cast<QJsonDocument>(d)->isArray())
+ return false;
+ *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonDocument>(d)->array());
+ break;
+ case QMetaType::QJsonValue:
+ if (!v_cast<QJsonValue>(d)->isArray())
+ return false;
+ *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonValue>(d)->toArray());
+ break;
+ case QMetaType::QJsonArray:
+ *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d));
+ break;
+ default:
+ return false;
+ }
+ break;
+ case QMetaType::QCborMap:
+ switch (d->type) {
+ case QVariant::Map:
+ *static_cast<QCborMap *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d));
+ break;
+ case QVariant::Hash:
+ *static_cast<QCborMap *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d));
+ break;
+ case QMetaType::QCborValue:
+ if (!v_cast<QCborValue>(d)->isMap())
+ return false;
+ *static_cast<QCborMap *>(result) = v_cast<QCborValue>(d)->toMap();
+ break;
+ case QMetaType::QJsonDocument:
+ if (v_cast<QJsonDocument>(d)->isArray())
+ return false;
+ *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonDocument>(d)->object());
+ break;
+ case QMetaType::QJsonValue:
+ if (!v_cast<QJsonValue>(d)->isObject())
+ return false;
+ *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonValue>(d)->toObject());
+ break;
+ case QMetaType::QJsonObject:
+ *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d));
+ break;
default:
return false;
}
break;
#endif
+
default:
#ifndef QT_NO_QOBJECT
if (d->type == QVariant::String || d->type == QVariant::ByteArray) {
@@ -1081,7 +1366,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
}
}
#endif
- if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration) {
+ if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) {
qlonglong value = qConvertToNumber(d, ok);
if (*ok) {
switch (QMetaType::sizeOf(t)) {
@@ -1175,9 +1460,16 @@ static void customConstruct(QVariant::Private *d, const void *copy)
type.construct(&d->data.ptr, copy);
d->is_shared = false;
} else {
- void *ptr = type.create(copy);
+ // Private::Data contains long long, and long double is the biggest standard type.
+ const size_t maxAlignment =
+ qMax(Q_ALIGNOF(QVariant::Private::Data), Q_ALIGNOF(long double));
+ const size_t s = sizeof(QVariant::PrivateShared);
+ const size_t offset = s + ((s * maxAlignment - s) % maxAlignment);
+ void *data = operator new(offset + size);
+ void *ptr = static_cast<char *>(data) + offset;
+ type.construct(ptr, copy);
d->is_shared = true;
- d->data.shared = new QVariant::PrivateShared(ptr);
+ d->data.shared = new (data) QVariant::PrivateShared(ptr);
}
}
@@ -1186,8 +1478,9 @@ static void customClear(QVariant::Private *d)
if (!d->is_shared) {
QMetaType::destruct(d->type, &d->data.ptr);
} else {
- QMetaType::destroy(d->type, d->data.shared->ptr);
- delete d->data.shared;
+ QMetaType::destruct(d->type, d->data.shared->ptr);
+ d->data.shared->~PrivateShared();
+ operator delete(d->data.shared);
}
}
@@ -3272,15 +3565,66 @@ bool QVariant::canConvert(int targetTypeId) const
case QMetaType::QVariantList:
case QMetaType::QVariantMap:
case QMetaType::QVariantHash:
+ case QMetaType::QCborValue:
+ case QMetaType::QCborArray:
+ case QMetaType::QCborMap:
return true;
default:
return false;
}
}
if (currentType == QMetaType::QJsonArray)
- return targetTypeId == QMetaType::QVariantList;
+ return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
+ || targetTypeId == QMetaType::QCborArray;
if (currentType == QMetaType::QJsonObject)
- return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash;
+ return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
+ || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QCborMap;
+
+ if (currentType == QMetaType::QCborValue || targetTypeId == QMetaType::QCborValue) {
+ switch (currentType == QMetaType::QCborValue ? targetTypeId : currentType) {
+ case QMetaType::UnknownType:
+ case QMetaType::Nullptr:
+ case QMetaType::Bool:
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ case QMetaType::Double:
+ case QMetaType::Float:
+ case QMetaType::ULong:
+ case QMetaType::Long:
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ case QMetaType::UShort:
+ case QMetaType::UChar:
+ case QMetaType::Char:
+ case QMetaType::SChar:
+ case QMetaType::Short:
+ case QMetaType::QString:
+ case QMetaType::QByteArray:
+ case QMetaType::QDateTime:
+ case QMetaType::QUrl:
+ case QMetaType::QRegularExpression:
+ case QMetaType::QUuid:
+ case QMetaType::QVariantList:
+ case QMetaType::QVariantMap:
+ case QMetaType::QVariantHash:
+ case QMetaType::QJsonValue:
+ case QMetaType::QJsonArray:
+ case QMetaType::QJsonObject:
+ case QMetaType::QJsonDocument:
+ case QMetaType::QCborArray:
+ case QMetaType::QCborMap:
+ case QMetaType::QCborSimpleType:
+ return true;
+ default:
+ return false;
+ }
+ }
+ if (currentType == QMetaType::QCborArray)
+ return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue
+ || targetTypeId == QMetaType::QJsonArray;
+ if (currentType == QMetaType::QCborMap)
+ return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash
+ || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QJsonObject;
// FIXME It should be LastCoreType intead of Uuid
if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) {
@@ -3380,7 +3724,7 @@ bool QVariant::convert(int targetTypeId)
create(targetTypeId, 0);
// Fail if the value is not initialized or was forced null by a previous failed convert.
- if (oldValue.d.is_null)
+ if (oldValue.d.is_null && oldValue.d.type != QMetaType::Nullptr)
return false;
if ((QMetaType::typeFlags(oldValue.userType()) & QMetaType::PointerToQObject) && (QMetaType::typeFlags(targetTypeId) & QMetaType::PointerToQObject)) {
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 9a5fc63d03..ff73c27b6e 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -633,6 +633,7 @@ public:
const_iterator &operator-=(int j);
const_iterator operator+(int j) const;
const_iterator operator-(int j) const;
+ friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
};
friend struct const_iterator;
@@ -690,6 +691,7 @@ public:
const_iterator &operator-=(int j);
const_iterator operator+(int j) const;
const_iterator operator-(int j) const;
+ friend inline const_iterator operator+(int j, const_iterator k) { return k + j; }
};
friend struct const_iterator;
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index 24de491326..85d4ad4fa9 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -157,7 +157,6 @@ void QWinEventNotifier::setHandle(HANDLE hEvent)
Q_D(QWinEventNotifier);
setEnabled(false);
d->handleToEvent = hEvent;
- d->signaledCount = 0;
}
/*!
@@ -209,10 +208,12 @@ void QWinEventNotifier::setEnabled(bool enable)
return;
}
- if (enable)
+ if (enable) {
+ d->signaledCount = 0;
eventDispatcher->registerEventNotifier(this);
- else
+ } else {
eventDispatcher->unregisterEventNotifier(this);
+ }
}
/*!
diff --git a/src/corelib/kernel/qwineventnotifier.h b/src/corelib/kernel/qwineventnotifier.h
index 624e77e638..71a1d29057 100644
--- a/src/corelib/kernel/qwineventnotifier.h
+++ b/src/corelib/kernel/qwineventnotifier.h
@@ -70,7 +70,7 @@ Q_SIGNALS:
void activated(HANDLE hEvent, QPrivateSignal);
protected:
- bool event(QEvent * e);
+ bool event(QEvent *e) override;
};
QT_END_NAMESPACE