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/qabstracteventdispatcher.cpp18
-rw-r--r--src/corelib/kernel/qcfsocketnotifier.cpp6
-rw-r--r--src/corelib/kernel/qcore_mac.cpp2
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm57
-rw-r--r--src/corelib/kernel/qcore_mac_p.h154
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp112
-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.cpp86
-rw-r--r--src/corelib/kernel/qdeadlinetimer.h5
-rw-r--r--src/corelib/kernel/qelapsedtimer_win.cpp15
-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_glib.cpp4
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib_p.h1
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp2
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp112
-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.cpp30
-rw-r--r--src/corelib/kernel/qmetaobject.cpp132
-rw-r--r--src/corelib/kernel/qmetaobject.h1
-rw-r--r--src/corelib/kernel/qmetaobject_p.h7
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp49
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h10
-rw-r--r--src/corelib/kernel/qmetatype.cpp234
-rw-r--r--src/corelib/kernel/qmetatype.h50
-rw-r--r--src/corelib/kernel/qmetatype_p.h16
-rw-r--r--src/corelib/kernel/qobject.cpp56
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h32
-rw-r--r--src/corelib/kernel/qsharedmemory_win.cpp14
-rw-r--r--src/corelib/kernel/qsystemerror.cpp4
-rw-r--r--src/corelib/kernel/qsystemsemaphore_win.cpp7
-rw-r--r--src/corelib/kernel/qtcore_eval.cpp2
-rw-r--r--src/corelib/kernel/qtestsupport_core.cpp116
-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
46 files changed, 1816 insertions, 855 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/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
index 304a7bda08..8e1b560874 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.cpp
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -207,6 +207,15 @@ QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
\sa hasPendingEvents()
*/
+/*!
+ \internal
+
+ \note processEvents() only processes events queued before the function
+ is called. Events that are posted while the function runs will be queued
+ until a later round of event processing. This only applies to posted Qt
+ events. For timers and system level events, the situation is unknown.
+*/
+
/*! \fn bool QAbstractEventDispatcher::hasPendingEvents()
\deprecated
@@ -309,6 +318,15 @@ int QAbstractEventDispatcher::registerTimer(int interval, Qt::TimerType timerTyp
Wakes up the event loop.
+ \omit
+ ### FIXME - QTBUG-70229
+ On Unix and Glib event dispatchers, if the dispatcher is already awake when
+ this function is called, it is ensured that the current iteration won't block
+ waiting for more events, but will instead do another event loop iteration.
+
+ ### TODO - does other event dispatchers behave the same?
+ \endomit
+
\sa awake()
*/
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..e78b2d1171 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
@@ -64,6 +65,7 @@ QCFString::operator CFStringRef() const
#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
+QT_MAC_WEAK_IMPORT(_os_log_default);
bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogContext &context,
const QString &message, const QString &optionalSubsystem)
{
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index 6b11e90a4e..4ca9c2e996 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"];
@@ -432,16 +448,23 @@ void qt_apple_check_os_version()
version / 10000, version / 100 % 100, version % 100};
const NSOperatingSystemVersion current = NSProcessInfo.processInfo.operatingSystemVersion;
if (![NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:required]) {
- fprintf(stderr, "You can't use this version of %s with this version of %s. "
- "You have %s %ld.%ld.%ld. Qt requires %s %ld.%ld.%ld or later.\n",
- (reinterpret_cast<const NSString *>(
- NSBundle.mainBundle.infoDictionary[@"CFBundleName"]).UTF8String),
- os,
- os, long(current.majorVersion), long(current.minorVersion), long(current.patchVersion),
- os, long(required.majorVersion), long(required.minorVersion), long(required.patchVersion));
- abort();
+ NSDictionary *plist = NSBundle.mainBundle.infoDictionary;
+ NSString *applicationName = plist[@"CFBundleDisplayName"];
+ if (!applicationName)
+ applicationName = plist[@"CFBundleName"];
+ if (!applicationName)
+ applicationName = NSProcessInfo.processInfo.processName;
+
+ fprintf(stderr, "Sorry, \"%s\" can not be run on this version of %s. "
+ "Qt requires %s %ld.%ld.%ld or later, you have %s %ld.%ld.%ld.\n",
+ applicationName.UTF8String, os,
+ os, long(required.majorVersion), long(required.minorVersion), long(required.patchVersion),
+ os, long(current.majorVersion), long(current.minorVersion), long(current.patchVersion));
+
+ exit(1);
}
}
+Q_CONSTRUCTOR_FUNCTION(qt_apple_check_os_version);
// -------------------------------------------------------------------------
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index af939abaac..b14a494296 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -51,18 +51,20 @@
// We mean it.
//
+#include "private/qglobal_p.h"
+
#ifndef __IMAGECAPTURE__
# define __IMAGECAPTURE__
#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
@@ -76,6 +78,8 @@
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__)
#endif
+#define QT_MAC_WEAK_IMPORT(symbol) extern "C" decltype(symbol) symbol __attribute__((weak_import));
+
QT_BEGIN_NAMESPACE
template <typename T, typename U, U (*RetainFunction)(U), void (*ReleaseFunction)(U)>
class QAppleRefCounted
@@ -148,16 +152,16 @@ 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
QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
#endif
-Q_CORE_EXPORT void qt_apple_check_os_version();
Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED)
@@ -186,35 +190,153 @@ Q_CORE_EXPORT AppleApplication *qt_apple_sharedApplication();
// --------------------------------------------------------------------------
-#if !defined(QT_BOOTSTRAPPED) && (QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) || !defined(Q_OS_MACOS))
+#if !defined(QT_BOOTSTRAPPED)
#define QT_USE_APPLE_UNIFIED_LOGGING
QT_END_NAMESPACE
#include <os/log.h>
-
-// The compiler isn't smart enough to realize that we're calling these functions
-// guarded by __builtin_available, so we need to also tag each function with the
-// runtime requirements.
-#include <os/availability.h>
-#define OS_LOG_AVAILABILITY API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT AppleUnifiedLogger
{
public:
static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context, const QString &message,
- const QString &subsystem = QString()) OS_LOG_AVAILABILITY;
+ const QString &subsystem = QString());
private:
- static os_log_type_t logTypeForMessageType(QtMsgType msgType) OS_LOG_AVAILABILITY;
- static os_log_t cachedLog(const QString &subsystem, const QString &category) OS_LOG_AVAILABILITY;
+ static os_log_type_t logTypeForMessageType(QtMsgType msgType);
+ static os_log_t cachedLog(const QString &subsystem, const QString &category);
};
-#undef OS_LOG_AVAILABILITY
-
#endif
// --------------------------------------------------------------------------
+#if !defined(QT_BOOTSTRAPPED)
+
+QT_END_NAMESPACE
+#include <os/activity.h>
+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) : 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)
+ os_activity_scope_enter(static_cast<os_activity_t>(*this), &state);
+ return std::move(*this);
+ }
+
+ void leave() {
+ if (activity)
+ os_activity_scope_leave(&state);
+ }
+
+ operator os_activity_t()
+ {
+ 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(); \
+ return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT)); \
+ }()
+
+#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__)
+
+QT_MAC_WEAK_IMPORT(_os_activity_current);
+#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();
+
+#endif // !defined(QT_BOOTSTRAPPED)
+
+// -------------------------------------------------------------------------
+
+#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..463e30e1c3 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>
@@ -116,6 +118,10 @@
# include <taskLib.h>
#endif
+#ifdef Q_OS_WASM
+#include <emscripten.h>
+#endif
+
#ifdef QT_BOOTSTRAPPED
#include <private/qtrace_p.h>
#else
@@ -268,9 +274,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 +293,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 +302,7 @@ void qAddPostRoutine(QtCleanUpFunction p)
QVFuncList *list = postRList();
if (!list)
return;
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
list->prepend(p);
}
@@ -311,9 +311,7 @@ void qRemovePostRoutine(QtCleanUpFunction p)
QVFuncList *list = postRList();
if (!list)
return;
-#ifndef QT_NO_THREAD
QMutexLocker locker(&globalRoutinesMutex);
-#endif
list->removeAll(p);
}
@@ -324,9 +322,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 +341,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);
}
@@ -466,9 +460,6 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
, q_ptr(0)
#endif
{
-#if defined(Q_OS_DARWIN)
- qt_apple_check_os_version();
-#endif
app_compile_version = flags & 0xffffff;
static const char *const empty = "";
if (argc == 0 || argv == 0) {
@@ -491,6 +482,10 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
qFatal("FATAL: The application binary appears to be running setuid, this is a security hole.");
# endif // Q_OS_UNIX
+#ifdef Q_OS_WINRT
+ QThreadData::setMainThread();
+#endif
+
QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread!
if (cur != theMainThread)
qWarning("WARNING: QApplication was not created in the main() thread.");
@@ -499,6 +494,13 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
QCoreApplicationPrivate::~QCoreApplicationPrivate()
{
+#ifdef Q_OS_WASM
+ EM_ASM(
+ // unmount persistent directory as IDBFS
+ // see also QTBUG-70002
+ FS.unmount('/home/web_user');
+ );
+#endif
#ifndef QT_NO_QOBJECT
cleanupThreadData();
#endif
@@ -513,7 +515,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 +542,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 +779,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;
@@ -790,6 +792,17 @@ void QCoreApplicationPrivate::init()
Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object");
QCoreApplication::self = q;
+#ifdef Q_OS_WASM
+ EM_ASM(
+ // mount and sync persistent filesystem to sandbox
+ FS.mount(IDBFS, {}, '/home/web_user');
+ FS.syncfs(true, function(err) {
+ if (err)
+ Module.print(err);
+ });
+ );
+#endif
+
// Store app name/version (so they're still available after QCoreApplication is destroyed)
if (!coreappdata()->applicationNameSet)
coreappdata()->application = appName();
@@ -872,7 +885,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 +901,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 +1198,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 +1427,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 +1442,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 +1492,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 +1530,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 +1562,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 +1821,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 +1872,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 +1941,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..466056d513 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
@@ -76,17 +75,7 @@ Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64
QDeadlineTimer objects can be passed to functions being called to execute
this operation so they know how long to still operate.
- \code
- void executeOperation(int msecs)
- {
- QDeadlineTimer deadline(msecs);
- do {
- if (readFromDevice(deadline.remainingTime())
- break;
- waitForReadyRead(deadline);
- } while (!deadline.hasExpired());
- }
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 0
Many QDeadlineTimer functions deal with time out values, which all are
measured in milliseconds. There are two special values, the same as many
@@ -126,15 +115,7 @@ Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64
\c{std::chrono::time_point} objects. In addition, it is fully compatible
with the time literals from C++14, which allow one to write code as:
- \code
- using namespace std::chrono;
- using namespace std::chrono_literals;
-
- QDeadlineTimer deadline(30s);
- device->waitForReadyRead(deadline);
- if (deadline.remainingTime<nanoseconds>() > 300ms)
- cleanup();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 1
As can be seen in the example above, QDeadlineTimer offers a templated
version of remainingTime() and deadline() that can be used to return
@@ -146,13 +127,7 @@ Q_DECL_CONST_FUNCTION static inline QPair<qint64, qint64> toSecsAndNSecs(qint64
Also note that, due to this conversion, the deadlines will not be precise,
so the following code is not expected to compare equally:
- \code
- using namespace std::chrono;
- using namespace std::chrono_literals;
- auto now = steady_clock::now();
- QDeadlineTimer deadline(now + 1s);
- Q_ASSERT(deadline == now + 1s);
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 2
\sa QTime, QTimer, QDeadlineTimer, Qt::TimerType
*/
@@ -247,10 +222,7 @@ QDeadlineTimer::QDeadlineTimer(qint64 msecs, Qt::TimerType type) Q_DECL_NOTHROW
This constructor can be used with C++14's user-defined literals for time, such as in:
- \code
- using namespace std::chrono_literals;
- QDeadlineTimer deadline(250ms);
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 3
For optimization purposes, if \a remaining is zero or negative, this
function may skip obtaining the current time and may instead use a value
@@ -340,10 +312,7 @@ void QDeadlineTimer::setPreciseRemainingTime(qint64 secs, qint64 nsecs, Qt::Time
This function can be used with C++14's user-defined literals for time, such as in:
- \code
- using namespace std::chrono_literals;
- deadline.setRemainingTime(250ms);
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 4
\note Qt detects the necessary C++14 compiler support by way of the feature
test recommendations from
@@ -416,9 +385,7 @@ void QDeadlineTimer::setTimerType(Qt::TimerType timerType)
lock functions in \l QMutex, \l QWaitCondition, \l QSemaphore, or
\l QReadWriteLock. For example:
- \code
- mutex.tryLock(deadline.remainingTime());
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 5
\sa remainingTimeNSecs(), isForever(), hasExpired()
*/
@@ -470,16 +437,7 @@ qint64 QDeadlineTimer::rawRemainingTimeNSecs() const Q_DECL_NOTHROW
overdue, by subtracting QDeadlineTimer::current() or
QElapsedTimer::msecsSinceReference(), as in the following example:
- \code
- qint64 realTimeLeft = deadline.deadline();
- if (realTimeLeft != (std::numeric_limits<qint64>::max)()) {
- realTimeLeft -= QDeadlineTimer::current().deadline();
- // or:
- //QElapsedTimer timer;
- //timer.start();
- //realTimeLeft -= timer.msecsSinceReference();
- }
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 6
\note Timers that were created as expired have an indetermine time point in
the past as their deadline, so the above calculation may not work.
@@ -506,11 +464,7 @@ qint64 QDeadlineTimer::deadline() const Q_DECL_NOTHROW
overdue, by subtracting QDeadlineTimer::current(), as in the following
example:
- \code
- qint64 realTimeLeft = deadline.deadlineNSecs();
- if (realTimeLeft != std::numeric_limits<qint64>::max())
- realTimeLeft -= QDeadlineTimer::current().deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 7
\note Timers that were created as expired have an indetermine time point in
the past as their deadline, so the above calculation may not work.
@@ -615,9 +569,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
same, false otherwise. The timer type used to create the two deadlines is
ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() == d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 8
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
@@ -631,9 +583,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
diferent, false otherwise. The timer type used to create the two deadlines
is ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() != d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 9
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
@@ -647,9 +597,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
d2, false otherwise. The timer type used to create the two deadlines is
ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() < d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 10
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
@@ -663,9 +611,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
deadline in \a d2, false otherwise. The timer type used to create the two
deadlines is ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() <= d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 11
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
@@ -679,9 +625,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
d2, false otherwise. The timer type used to create the two deadlines is
ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() > d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 12
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
@@ -695,9 +639,7 @@ QDeadlineTimer QDeadlineTimer::addNSecs(QDeadlineTimer dt, qint64 nsecs) Q_DECL_
deadline in \a d2, false otherwise. The timer type used to create the two
deadlines is ignored. This function is equivalent to:
- \code
- return d1.deadlineNSecs() >= d2.deadlineNSecs();
- \endcode
+ \snippet code/src_corelib_kernel_qdeadlinetimer.cpp 13
\note comparing QDeadlineTimer objects with different timer types is
not supported and may result in unpredictable behavior.
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/qelapsedtimer_win.cpp b/src/corelib/kernel/qelapsedtimer_win.cpp
index 0c380b2f6a..a63290d2f8 100644
--- a/src/corelib/kernel/qelapsedtimer_win.cpp
+++ b/src/corelib/kernel/qelapsedtimer_win.cpp
@@ -72,10 +72,9 @@ static inline qint64 ticksToNanoseconds(qint64 ticks)
qint64 seconds = ticks / counterFrequency;
qint64 nanoSeconds = (ticks - seconds * counterFrequency) * 1000000000 / counterFrequency;
return seconds * 1000000000 + nanoSeconds;
- } else {
- // GetTickCount(64) return milliseconds
- return ticks * 1000000;
}
+ // GetTickCount(64) returns milliseconds
+ return ticks * 1000000;
}
static inline qint64 nanosecondsToTicks(qint64 nsec)
@@ -83,10 +82,9 @@ static inline qint64 nanosecondsToTicks(qint64 nsec)
if (counterFrequency > 0) {
// QueryPerformanceCounter uses an arbitrary frequency
return double(nsec) * counterFrequency / 1000000000.;
- } else {
- // GetTickCount(64) uses milliseconds
- return nsec / 1000000;
}
+ // GetTickCount(64) uses milliseconds
+ return nsec / 1000000;
}
static quint64 getTickCount()
@@ -116,10 +114,7 @@ QElapsedTimer::ClockType QElapsedTimer::clockType() Q_DECL_NOTHROW
{
resolveCounterFrequency();
- if (counterFrequency > 0)
- return PerformanceCounter;
- else
- return TickCounter;
+ return counterFrequency > 0 ? PerformanceCounter : TickCounter;
}
bool QElapsedTimer::isMonotonic() Q_DECL_NOTHROW
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_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp
index 4c780a9294..45c6e29e4b 100644
--- a/src/corelib/kernel/qeventdispatcher_glib.cpp
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -260,8 +260,8 @@ static gboolean postEventSourcePrepare(GSource *s, gint *timeout)
*timeout = canWait ? -1 : 0;
GPostEventSource *source = reinterpret_cast<GPostEventSource *>(s);
- return (!canWait
- || (source->serialNumber.load() != source->lastSerialNumber));
+ source->d->wakeUpCalled = source->serialNumber.load() != source->lastSerialNumber;
+ return !canWait || source->d->wakeUpCalled;
}
static gboolean postEventSourceCheck(GSource *source)
diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h
index 799f23b14a..88ff316ee5 100644
--- a/src/corelib/kernel/qeventdispatcher_glib_p.h
+++ b/src/corelib/kernel/qeventdispatcher_glib_p.h
@@ -108,6 +108,7 @@ public:
GSocketNotifierSource *socketNotifierSource;
GTimerSource *timerSource;
GIdleTimerSource *idleTimerSource;
+ bool wakeUpCalled = true;
void runTimersOnceWithNormalPriority();
};
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index a28f2e3f0a..535f86fefe 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -130,7 +130,7 @@ static void initThreadPipeFD(int fd)
bool QThreadPipe::init()
{
-#if defined(Q_OS_NACL)
+#if defined(Q_OS_NACL) || defined(Q_OS_WASM)
// do nothing.
#elif defined(Q_OS_VXWORKS)
qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf()));
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 330870f219..0bddf89b15 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -120,7 +120,7 @@ void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/,
{
if (!timerId) // sanity check
return;
- WinTimerInfo *t = (WinTimerInfo*)user;
+ auto t = reinterpret_cast<WinTimerInfo*>(user);
Q_ASSERT(t);
QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
}
@@ -141,20 +141,21 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
if (message == WM_TIMER)
KillTimer(hwnd, wp);
return 0;
- } else if (dispatcher->filterNativeEvent(QByteArrayLiteral("windows_dispatcher_MSG"), &msg, &result)) {
- return result;
}
+ if (dispatcher->filterNativeEvent(QByteArrayLiteral("windows_dispatcher_MSG"), &msg, &result))
+ return result;
#ifdef GWLP_USERDATA
- QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ auto q = reinterpret_cast<QEventDispatcherWin32 *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
#else
- QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA);
+ auto q = reinterpret_cast<QEventDispatcherWin32 *>(GetWindowLong(hwnd, GWL_USERDATA));
#endif
QEventDispatcherWin32Private *d = 0;
if (q != 0)
d = q->d_func();
- if (message == WM_QT_SOCKETNOTIFIER) {
+ switch (message) {
+ case WM_QT_SOCKETNOTIFIER: {
// socket notifier message
int type = -1;
switch (WSAGETSELECTEVENT(lp)) {
@@ -202,7 +203,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
}
}
return 0;
- } else if (message == WM_QT_ACTIVATENOTIFIERS) {
+ }
+ case WM_QT_ACTIVATENOTIFIERS: {
Q_ASSERT(d != 0);
// Postpone activation if we have unhandled socket notifier messages
@@ -226,22 +228,25 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
}
d->activateNotifiersPosted = false;
return 0;
- } else if (message == WM_QT_SENDPOSTEDEVENTS
- // we also use a Windows timer to send posted events when the message queue is full
- || (message == WM_TIMER
- && d->sendPostedEventsWindowsTimerId != 0
- && wp == (uint)d->sendPostedEventsWindowsTimerId)) {
+ }
+ case WM_TIMER:
+ if (d->sendPostedEventsWindowsTimerId == 0
+ || wp != uint(d->sendPostedEventsWindowsTimerId)) {
+ Q_ASSERT(d != 0);
+ d->sendTimerEvent(wp);
+ return 0;
+ }
+ // we also use a Windows timer to send posted events when the message queue is full
+ Q_FALLTHROUGH();
+ case WM_QT_SENDPOSTEDEVENTS: {
const int localSerialNumber = d->serialNumber.load();
if (localSerialNumber != d->lastSerialNumber) {
d->lastSerialNumber = localSerialNumber;
q->sendPostedEvents();
}
return 0;
- } else if (message == WM_TIMER) {
- Q_ASSERT(d != 0);
- d->sendTimerEvent(wp);
- return 0;
}
+ } // switch (message)
return DefWindowProc(hwnd, message, wp, lp);
}
@@ -369,9 +374,9 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch
}
#ifdef GWLP_USERDATA
- SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher);
+ SetWindowLongPtr(wnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(eventDispatcher));
#else
- SetWindowLong(wnd, GWL_USERDATA, (LONG)eventDispatcher);
+ SetWindowLong(wnd, GWL_USERDATA, reinterpret_cast<LONG>(eventDispatcher));
#endif
return wnd;
@@ -522,6 +527,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 +583,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;
@@ -598,7 +608,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
if (haveMessage) {
// WinCE doesn't support hooks at all, so we have to call this by hand :(
if (!d->getMessageHook)
- (void) qt_GetMessageHook(0, PM_REMOVE, (LPARAM) &msg);
+ (void) qt_GetMessageHook(0, PM_REMOVE, reinterpret_cast<LPARAM>(&msg));
if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
if (seenWM_QT_SENDPOSTEDEVENTS) {
@@ -678,7 +688,8 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
if (sockfd < 0) {
qWarning("QSocketNotifier: Internal error");
return;
- } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ }
+ if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
return;
}
@@ -738,7 +749,8 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
if (sockfd < 0) {
qWarning("QSocketNotifier: Internal error");
return;
- } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ }
+ if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
return;
}
@@ -784,7 +796,8 @@ void QEventDispatcherWin32::registerTimer(int timerId, int interval, Qt::TimerTy
if (timerId < 1 || interval < 0 || !object) {
qWarning("QEventDispatcherWin32::registerTimer: invalid arguments");
return;
- } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ }
+ if (object->thread() != thread() || thread() != QThread::currentThread()) {
qWarning("QEventDispatcherWin32::registerTimer: timers cannot be started from another thread");
return;
}
@@ -881,8 +894,7 @@ QEventDispatcherWin32::registeredTimers(QObject *object) const
Q_D(const QEventDispatcherWin32);
QList<TimerInfo> list;
- for (int i = 0; i < d->timerVec.size(); ++i) {
- const WinTimerInfo *t = d->timerVec.at(i);
+ for (const WinTimerInfo *t : qAsConst(d->timerVec)) {
if (t && t->obj == object)
list << TimerInfo(t->timerId, t->interval, t->timerType);
}
@@ -979,17 +991,9 @@ int QEventDispatcherWin32::remainingTime(int timerId)
quint64 currentTime = qt_msectime();
- WinTimerInfo *t;
- for (int i=0; i<d->timerVec.size(); i++) {
- t = d->timerVec.at(i);
- if (t && t->timerId == timerId) { // timer found
- if (currentTime < t->timeout) {
- // time to wait
- return t->timeout - currentTime;
- } else {
- return 0;
- }
- }
+ for (const WinTimerInfo *t : qAsConst(d->timerVec)) {
+ if (t && t->timerId == timerId) // timer found, return time to wait
+ return t->timeout > currentTime ? t->timeout - currentTime : 0;
}
#ifndef QT_NO_DEBUG
@@ -1049,7 +1053,8 @@ void QEventDispatcherWin32::closingDown()
bool QEventDispatcherWin32::event(QEvent *e)
{
Q_D(QEventDispatcherWin32);
- if (e->type() == QEvent::ZeroTimerEvent) {
+ switch (e->type()) {
+ case QEvent::ZeroTimerEvent: {
QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
WinTimerInfo *t = d->timerDict.value(zte->timerId());
if (t) {
@@ -1071,9 +1076,12 @@ bool QEventDispatcherWin32::event(QEvent *e)
}
}
return true;
- } else if (e->type() == QEvent::Timer) {
- QTimerEvent *te = static_cast<QTimerEvent*>(e);
- d->sendTimerEvent(te->timerId());
+ }
+ case QEvent::Timer:
+ d->sendTimerEvent(static_cast<const QTimerEvent*>(e)->timerId());
+ break;
+ default:
+ break;
}
return QAbstractEventDispatcher::event(e);
}
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..a6cc51621a 100644
--- a/src/corelib/kernel/qeventloop.cpp
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -48,6 +48,10 @@
#include "qeventloop_p.h"
#include <private/qthread_p.h>
+#ifdef Q_OS_WASM
+#include <emscripten.h>
+#endif
+
QT_BEGIN_NAMESPACE
/*!
@@ -101,10 +105,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();
}
}
@@ -210,6 +212,15 @@ int QEventLoop::exec(ProcessEventsFlags flags)
if (app && app->thread() == thread())
QCoreApplication::removePostedEvents(app, QEvent::Quit);
+#ifdef Q_OS_WASM
+ // Partial support for nested event loops: Make the runtime throw a JavaSrcript
+ // exception, which returns control to the browser while preserving the C++ stack.
+ // Event processing then continues as normal. The sleep call below never returns.
+ // QTBUG-70185
+ if (d->threadData->loopLevel > 1)
+ emscripten_sleep(1);
+#endif
+
while (!d->exit.loadAcquire())
processEvents(flags | WaitForMoreEvents | EventLoopExec);
@@ -271,6 +282,17 @@ void QEventLoop::exit(int returnCode)
d->returnCode.store(returnCode);
d->exit.storeRelease(true);
d->threadData->eventDispatcher.load()->interrupt();
+
+#ifdef Q_OS_WASM
+ // QEventLoop::exec() never returns in emscripten. We implement approximate behavior here.
+ // QTBUG-70185
+ if (d->threadData->loopLevel == 1) {
+ emscripten_force_exit(returnCode);
+ } else {
+ d->inExec = false;
+ --d->threadData->loopLevel;
+ }
+#endif
}
/*!
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 27138dd075..c642cd07f2 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"
@@ -970,8 +972,23 @@ int QMetaObject::indexOfEnumerator(const char *name) const
const QMetaObject *m = this;
while (m) {
const QMetaObjectPrivate *d = priv(m->d.data);
+ const int intsPerEnum = d->revision >= 8 ? 5 : 4;
+ 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);
+ const int intsPerEnum = d->revision >= 8 ? 5 : 4;
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 +1103,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 +1543,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;
@@ -1950,9 +1968,8 @@ QList<QByteArray> QMetaMethod::parameterTypes() const
*/
QList<QByteArray> QMetaMethod::parameterNames() const
{
- QList<QByteArray> list;
if (!mobj)
- return list;
+ return QList<QByteArray>();
return QMetaMethodPrivate::get(this)->parameterNames();
}
@@ -1978,27 +1995,11 @@ const char *QMetaMethod::typeName() const
Tag information can be added in the following
way in the function declaration:
- \code
- // In the class MainWindow declaration
- #ifndef Q_MOC_RUN
- // define the tag text as empty, so the compiler doesn't see it
- # define MY_CUSTOM_TAG
- #endif
- ...
- private slots:
- MY_CUSTOM_TAG void testFunc();
- \endcode
+ \snippet code/src_corelib_kernel_qmetaobject.cpp 10
and the information can be accessed by using:
- \code
- MainWindow win;
- win.show();
-
- int functionIndex = win.metaObject()->indexOfSlot("testFunc()");
- QMetaMethod mm = win.metaObject()->method(functionIndex);
- qDebug() << mm.tag(); // prints MY_CUSTOM_TAG
- \endcode
+ \snippet code/src_corelib_kernel_qmetaobject.cpp 11
For the moment, \c moc will extract and record all tags, but it will not
handle any of them specially. You can use the tags to annotate your methods
@@ -2257,7 +2258,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 +2334,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 +2345,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 +2553,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::AlignmentFlag enumeration has \c
- AlignmentFlag as the name and \l Qt as the scope.
+ For example, the Qt::Key enumeration has \c
+ Key as the type name and \l Qt as the scope.
- \sa isValid(), scope()
+ For flags this returns the name of the flag type, not the
+ name of the enum type.
+
+ \sa isValid(), scope(), enumName()
*/
const char *QMetaEnum::name() const
{
@@ -2567,6 +2571,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 +2601,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 +2614,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 +2632,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 +2652,10 @@ int QMetaEnum::value(int index) const
*/
bool QMetaEnum::isFlag() const
{
- return mobj && mobj->d.data[handle + 1] & EnumIsFlag;
+ if (!mobj)
+ return false;
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 2 : 1;
+ return mobj->d.data[handle + offset] & EnumIsFlag;
}
/*!
@@ -2635,7 +2666,10 @@ bool QMetaEnum::isFlag() const
*/
bool QMetaEnum::isScoped() const
{
- return mobj && mobj->d.data[handle + 1] & EnumIsScoped;
+ if (!mobj)
+ return false;
+ const int offset = priv(mobj->d.data)->revision >= 8 ? 2 : 1;
+ return mobj->d.data[handle + offset] & EnumIsScoped;
}
/*!
@@ -2677,8 +2711,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 +2738,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 +2771,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 +2815,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..522bd78e42 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -60,6 +60,8 @@
#include <QtCore/qvarlengtharray.h>
QT_BEGIN_NAMESPACE
+// ### TODO Qt6: add a proper namespace with Q_NAMESPACE and use scoped enums
+// A namespace and scoped are needed to avoid enum clashes
enum PropertyFlags {
Invalid = 0x00000000,
@@ -103,7 +105,7 @@ enum MethodFlags {
MethodRevisioned = 0x80
};
-enum MetaObjectFlags {
+enum MetaObjectFlags { // keep it in sync with QMetaObjectBuilder::MetaObjectFlag enum
DynamicMetaObject = 0x01,
RequiresVariantMetaObject = 0x02,
PropertyAccessInStaticMetaCall = 0x04 // since Qt 5.5, property code is in the static metacall
@@ -171,7 +173,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..115ec835aa 100644
--- a/src/corelib/kernel/qmetaobjectbuilder_p.h
+++ b/src/corelib/kernel/qmetaobjectbuilder_p.h
@@ -93,8 +93,11 @@ public:
};
Q_DECLARE_FLAGS(AddMembers, AddMember)
- enum MetaObjectFlag {
- DynamicMetaObject = 0x01
+ // ### TODO Qt6: remove me and use the MetaObjectFlags enum from qmetaobject_p.h
+ enum MetaObjectFlag { // keep it in sync with enum MetaObjectFlags from qmetaobject_p.h
+ DynamicMetaObject = 0x01,
+ RequiresVariantMetaObject = 0x02,
+ PropertyAccessInStaticMetaCall = 0x04 // since Qt 5.5, property code is in the static metacall
};
Q_DECLARE_FLAGS(MetaObjectFlags, MetaObjectFlag)
@@ -297,6 +300,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..eb67544f21 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...
}
@@ -1065,45 +1054,40 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
return registerNormalizedType(normalizedTypeName, deleter, creator, destructor, constructor, size, flags, metaObject);
}
-
/*!
- \internal
- \since 5.0
- \overload
- Don't use, kept for binary compatibility
+ \internal
+ \since 5.12
- ### TODO Qt6: remove me
-*/
-int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, Deleter deleter,
- Creator creator,
- Destructor destructor,
- Constructor constructor,
- int size, TypeFlags flags, const QMetaObject *metaObject)
+ Registers a user type for marshalling, with \a typeName, a
+ \a destructor, a \a constructor, and a \a size. Returns the
+ type's handle, or -1 if the type could not be registered.
+ */
+int QMetaType::registerType(const char *typeName,
+ TypedDestructor destructor,
+ TypedConstructor constructor,
+ int size,
+ TypeFlags flags,
+ const QMetaObject *metaObject)
{
- Q_UNUSED(deleter);
- Q_UNUSED(creator);
+#ifdef QT_NO_QOBJECT
+ NS(QByteArray) normalizedTypeName = typeName;
+#else
+ NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+#endif
+
return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject);
}
-/*!
- \internal
- \since 5.5
-
- Registers a user type for marshalling, with \a normalizedTypeName,
- a \a destructor, a \a constructor, and a \a size. Returns the type's
- handle, or -1 if the type could not be registered.
-
- \note normalizedTypeName is not checked for conformance with
- Qt's normalized format, so it must already conform.
- */
-int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
- Destructor destructor,
- Constructor constructor,
- int size, TypeFlags flags, const QMetaObject *metaObject)
+static int registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
+ QMetaType::Destructor destructor,
+ QMetaType::Constructor constructor,
+ QMetaType::TypedDestructor typedDestructor,
+ QMetaType::TypedConstructor typedConstructor,
+ int size, QMetaType::TypeFlags flags, const QMetaObject *metaObject)
{
QVector<QCustomTypeInfo> *ct = customTypes();
- if (!ct || normalizedTypeName.isEmpty() || !destructor || !constructor)
+ if (!ct || normalizedTypeName.isEmpty() || (!destructor && !typedDestructor) || (!constructor && !typedConstructor))
return -1;
int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
@@ -1111,13 +1095,13 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
int previousSize = 0;
QMetaType::TypeFlags::Int previousFlags = 0;
- if (idx == UnknownType) {
+ if (idx == QMetaType::UnknownType) {
QWriteLocker locker(customTypesLock());
int posInVector = -1;
idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
normalizedTypeName.size(),
&posInVector);
- if (idx == UnknownType) {
+ if (idx == QMetaType::UnknownType) {
QCustomTypeInfo inf;
inf.typeName = normalizedTypeName;
#ifndef QT_NO_DATASTREAM
@@ -1125,30 +1109,32 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
inf.saveOp = 0;
#endif
inf.alias = -1;
+ inf.typedConstructor = typedConstructor;
+ inf.typedDestructor = typedDestructor;
inf.constructor = constructor;
inf.destructor = destructor;
inf.size = size;
inf.flags = flags;
inf.metaObject = metaObject;
if (posInVector == -1) {
- idx = ct->size() + User;
+ idx = ct->size() + QMetaType::User;
ct->append(inf);
} else {
- idx = posInVector + User;
+ idx = posInVector + QMetaType::User;
ct->data()[posInVector] = inf;
}
return idx;
}
- if (idx >= User) {
- previousSize = ct->at(idx - User).size;
- previousFlags = ct->at(idx - User).flags;
+ if (idx >= QMetaType::User) {
+ previousSize = ct->at(idx - QMetaType::User).size;
+ previousFlags = ct->at(idx - QMetaType::User).flags;
// Set new/additional flags in case of old library/app.
// Ensures that older code works in conjunction with new Qt releases
// requiring the new flags.
if (flags != previousFlags) {
- QCustomTypeInfo &inf = ct->data()[idx - User];
+ QCustomTypeInfo &inf = ct->data()[idx - QMetaType::User];
inf.flags |= flags;
if (metaObject)
inf.metaObject = metaObject;
@@ -1156,7 +1142,7 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
}
}
- if (idx < User) {
+ if (idx < QMetaType::User) {
previousSize = QMetaType::sizeOf(idx);
previousFlags = QMetaType::typeFlags(idx);
}
@@ -1169,8 +1155,8 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
}
// these flags cannot change in a binary compatible way:
- const int binaryCompatibilityFlag = PointerToQObject | IsEnumeration | SharedPointerToQObject
- | WeakPointerToQObject | TrackingPointerToQObject;
+ const int binaryCompatibilityFlag = QMetaType::PointerToQObject | QMetaType::IsEnumeration | QMetaType::SharedPointerToQObject
+ | QMetaType::WeakPointerToQObject | QMetaType::TrackingPointerToQObject;
if (Q_UNLIKELY((previousFlags ^ flags) & binaryCompatibilityFlag)) {
const char *msg = "QMetaType::registerType: Binary compatibility break. "
@@ -1184,6 +1170,66 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
}
/*!
+ \internal
+ \since 5.0
+ \overload
+ Don't use, kept for binary compatibility
+
+ ### TODO Qt6: remove me
+*/
+int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, Deleter deleter,
+ Creator creator,
+ Destructor destructor,
+ Constructor constructor,
+ int size, TypeFlags flags, const QMetaObject *metaObject)
+{
+ Q_UNUSED(deleter);
+ Q_UNUSED(creator);
+ return registerNormalizedType(normalizedTypeName, destructor, constructor, size, flags, metaObject);
+}
+
+
+/*!
+ \internal
+ \since 5.5
+
+ Registers a user type for marshalling, with \a normalizedTypeName,
+ a \a destructor, a \a constructor, and a \a size. Returns the type's
+ handle, or -1 if the type could not be registered.
+
+ \note normalizedTypeName is not checked for conformance with
+ Qt's normalized format, so it must already conform.
+
+ ### TODO Qt6: remove me
+ */
+int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
+ Destructor destructor,
+ Constructor constructor,
+ int size, TypeFlags flags, const QMetaObject *metaObject)
+{
+ return NS(registerNormalizedType)(normalizedTypeName, destructor, constructor, nullptr, nullptr, size, flags, metaObject);
+}
+
+/*!
+ \internal
+ \since 5.12
+
+ Registers a user type for marshalling, with \a normalizedTypeName,
+ a \a destructor, a \a constructor, and a \a size. Returns the type's
+ handle, or -1 if the type could not be registered.
+
+ \note normalizedTypeName is not checked for conformance with
+ Qt's normalized format, so it must already conform.
+ */
+int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
+ TypedDestructor destructor,
+ TypedConstructor constructor,
+ int size, TypeFlags flags, const QMetaObject *metaObject)
+{
+ return NS(registerNormalizedType)(normalizedTypeName, nullptr, nullptr, destructor, constructor, size, flags, metaObject);
+}
+
+/*!
\internal
\since 4.7
@@ -1360,6 +1406,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 +1547,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 +1638,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 +1785,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:
@@ -1849,14 +1907,19 @@ private:
static void *customTypeConstructor(const int type, void *where, const void *copy)
{
QMetaType::Constructor ctor;
+ QMetaType::TypedConstructor tctor;
const QVector<QCustomTypeInfo> * const ct = customTypes();
{
QReadLocker locker(customTypesLock());
if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
return 0;
- ctor = ct->at(type - QMetaType::User).constructor;
+ const auto &typeInfo = ct->at(type - QMetaType::User);
+ ctor = typeInfo.constructor;
+ tctor = typeInfo.typedConstructor;
}
- Q_ASSERT_X(ctor, "void *QMetaType::construct(int type, void *where, const void *copy)", "The type was not properly registered");
+ Q_ASSERT_X((ctor || tctor) , "void *QMetaType::construct(int type, void *where, const void *copy)", "The type was not properly registered");
+ if (Q_UNLIKELY(tctor))
+ return tctor(type, where, copy);
return ctor(where, copy);
}
@@ -1942,14 +2005,19 @@ private:
static void customTypeDestructor(const int type, void *where)
{
QMetaType::Destructor dtor;
+ QMetaType::TypedDestructor tdtor;
const QVector<QCustomTypeInfo> * const ct = customTypes();
{
QReadLocker locker(customTypesLock());
if (Q_UNLIKELY(type < QMetaType::User || !ct || ct->count() <= type - QMetaType::User))
return;
- dtor = ct->at(type - QMetaType::User).destructor;
+ const auto &typeInfo = ct->at(type - QMetaType::User);
+ dtor = typeInfo.destructor;
+ tdtor = typeInfo.typedDestructor;
}
- Q_ASSERT_X(dtor, "void QMetaType::destruct(int type, void *where)", "The type was not properly registered");
+ Q_ASSERT_X((dtor || tdtor), "void QMetaType::destruct(int type, void *where)", "The type was not properly registered");
+ if (Q_UNLIKELY(tdtor))
+ return tdtor(type, where);
dtor(where);
}
@@ -2362,10 +2430,12 @@ QMetaType QMetaType::typeInfo(const int type)
{
TypeInfo typeInfo(type);
QMetaTypeSwitcher::switcher<void>(typeInfo, type, 0);
- return typeInfo.info.constructor ? QMetaType(static_cast<ExtensionFlag>(QMetaType::CreateEx | QMetaType::DestroyEx)
- , static_cast<const QMetaTypeInterface *>(0) // typeInfo::info is a temporary variable, we can't return address of it.
- , 0 // unused
- , 0 // unused
+ return (typeInfo.info.constructor || typeInfo.info.typedConstructor)
+ ? QMetaType(static_cast<ExtensionFlag>(QMetaType::CreateEx | QMetaType::DestroyEx |
+ (typeInfo.info.typedConstructor ? QMetaType::ConstructEx | QMetaType::DestructEx : 0))
+ , static_cast<const QMetaTypeInterface *>(nullptr) // typeInfo::info is a temporary variable, we can't return address of it.
+ , typeInfo.info.typedConstructor
+ , typeInfo.info.typedDestructor
, typeInfo.info.saveOp
, typeInfo.info.loadOp
, typeInfo.info.constructor
@@ -2407,8 +2477,8 @@ QMetaType::QMetaType(const int typeId)
Copy constructs a QMetaType object.
*/
QMetaType::QMetaType(const QMetaType &other)
- : m_creator_unused(other.m_creator_unused)
- , m_deleter_unused(other.m_deleter_unused)
+ : m_typedConstructor(other.m_typedConstructor)
+ , m_typedDestructor(other.m_typedDestructor)
, m_saveOp(other.m_saveOp)
, m_loadOp(other.m_loadOp)
, m_constructor(other.m_constructor)
@@ -2423,8 +2493,8 @@ QMetaType::QMetaType(const QMetaType &other)
QMetaType &QMetaType::operator =(const QMetaType &other)
{
- m_creator_unused = other.m_creator_unused;
- m_deleter_unused = other.m_deleter_unused;
+ m_typedConstructor = other.m_typedConstructor;
+ m_typedDestructor = other.m_typedDestructor;
m_saveOp = other.m_saveOp;
m_loadOp = other.m_loadOp;
m_constructor = other.m_constructor;
@@ -2480,6 +2550,8 @@ void *QMetaType::createExtended(const void *copy) const
{
if (m_typeId == QMetaType::UnknownType)
return 0;
+ if (Q_UNLIKELY(m_typedConstructor && !m_constructor))
+ return m_typedConstructor(m_typeId, operator new(m_size), copy);
return m_constructor(operator new(m_size), copy);
}
@@ -2494,7 +2566,10 @@ void *QMetaType::createExtended(const void *copy) const
*/
void QMetaType::destroyExtended(void *data) const
{
- m_destructor(data);
+ if (Q_UNLIKELY(m_typedDestructor && !m_destructor))
+ m_typedDestructor(m_typeId, data);
+ else
+ m_destructor(data);
operator delete(data);
}
@@ -2507,9 +2582,9 @@ void QMetaType::destroyExtended(void *data) const
*/
void *QMetaType::constructExtended(void *where, const void *copy) const
{
- Q_UNUSED(where);
- Q_UNUSED(copy);
- return 0;
+ if (m_typedConstructor && !m_constructor)
+ return m_typedConstructor(m_typeId, where, copy);
+ return nullptr;
}
/*!
@@ -2521,7 +2596,8 @@ void *QMetaType::constructExtended(void *where, const void *copy) const
*/
void QMetaType::destructExtended(void *data) const
{
- Q_UNUSED(data);
+ if (m_typedDestructor && !m_destructor)
+ m_typedDestructor(m_typeId, data);
}
/*!
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index cf68752f85..ed7feee775 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
};
@@ -480,8 +493,12 @@ public:
typedef void (*Deleter)(void *);
typedef void *(*Creator)(const void *);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
typedef void (*Destructor)(void *);
- typedef void *(*Constructor)(void *, const void *);
+ typedef void *(*Constructor)(void *, const void *); // TODO Qt6: remove me
+#endif
+ typedef void (*TypedDestructor)(int, void *);
+ typedef void *(*TypedConstructor)(int, void *, const void *);
typedef void (*SaveOperator)(QDataStream &, const void *);
typedef void (*LoadOperator)(QDataStream &, void *);
@@ -500,6 +517,12 @@ public:
int size,
QMetaType::TypeFlags flags,
const QMetaObject *metaObject);
+ static int registerType(const char *typeName,
+ TypedDestructor destructor,
+ TypedConstructor constructor,
+ int size,
+ QMetaType::TypeFlags flags,
+ const QMetaObject *metaObject);
static bool unregisterType(int type);
static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Deleter deleter,
Creator creator,
@@ -513,6 +536,11 @@ public:
int size,
QMetaType::TypeFlags flags,
const QMetaObject *metaObject);
+ static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, TypedDestructor destructor,
+ TypedConstructor constructor,
+ int size,
+ QMetaType::TypeFlags flags,
+ const QMetaObject *metaObject);
static int registerTypedef(const char *typeName, int aliasId);
static int registerNormalizedTypedef(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, int aliasId);
static int type(const char *typeName);
@@ -670,8 +698,8 @@ public:
private:
static QMetaType typeInfo(const int type);
inline QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
- Creator creator,
- Deleter deleter,
+ TypedConstructor creator,
+ TypedDestructor deleter,
SaveOperator saveOp,
LoadOperator loadOp,
Constructor constructor,
@@ -718,8 +746,8 @@ public:
static void unregisterConverterFunction(int from, int to);
private:
- Creator m_creator_unused;
- Deleter m_deleter_unused;
+ TypedConstructor m_typedConstructor;
+ TypedDestructor m_typedDestructor;
SaveOperator m_saveOp;
LoadOperator m_loadOp;
Constructor m_constructor;
@@ -2150,8 +2178,8 @@ QT_BEGIN_NAMESPACE
#undef Q_DECLARE_METATYPE_TEMPLATE_SMART_POINTER_ITER
inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeInterface *info,
- Creator creator,
- Deleter deleter,
+ TypedConstructor creator,
+ TypedDestructor deleter,
SaveOperator saveOp,
LoadOperator loadOp,
Constructor constructor,
@@ -2160,8 +2188,8 @@ inline QMetaType::QMetaType(const ExtensionFlag extensionFlags, const QMetaTypeI
uint theTypeFlags,
int typeId,
const QMetaObject *_metaObject)
- : m_creator_unused(creator)
- , m_deleter_unused(deleter)
+ : m_typedConstructor(creator)
+ , m_typedDestructor(deleter)
, m_saveOp(saveOp)
, m_loadOp(loadOp)
, m_constructor(constructor)
diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h
index cef20a5d12..94e9228778 100644
--- a/src/corelib/kernel/qmetatype_p.h
+++ b/src/corelib/kernel/qmetatype_p.h
@@ -126,11 +126,13 @@ class QMetaTypeInterface
public:
QMetaType::SaveOperator saveOp;
QMetaType::LoadOperator loadOp;
- QMetaType::Constructor constructor;
+ QMetaType::Constructor constructor; // TODO Qt6: remove me
QMetaType::Destructor destructor;
int size;
QMetaType::TypeFlags::Int flags;
const QMetaObject *metaObject;
+ QMetaType::TypedConstructor typedConstructor;
+ QMetaType::TypedDestructor typedDestructor;
};
#ifndef QT_NO_DATASTREAM
@@ -161,7 +163,9 @@ public:
/*destructor*/(QtMetaTypePrivate::QMetaTypeFunctionHelper<Type, QtMetaTypePrivate::TypeDefinition<Type>::IsAvailable>::Destruct), \
/*size*/(QTypeInfo<Type>::sizeOf), \
/*flags*/QtPrivate::QMetaTypeTypeFlags<Type>::Flags, \
- /*metaObject*/METAOBJECT_DELEGATE(Type) \
+ /*metaObject*/METAOBJECT_DELEGATE(Type), \
+ /*typedConstructor*/ nullptr, \
+ /*typedDestructor*/ nullptr \
}
@@ -184,7 +188,9 @@ public:
/*destructor*/ 0, \
/*size*/ 0, \
/*flags*/ 0, \
- /*metaObject*/ 0 \
+ /*metaObject*/ 0 , \
+ /*typedConstructor*/ nullptr, \
+ /*typedDestructor*/ nullptr \
}
namespace QtMetaTypePrivate {
@@ -196,6 +202,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..07208b7f40 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
@@ -523,18 +526,9 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
constructor and in the destructor it resets the state to what
it was before the constructor ran.
- \code
- {
- const QSignalBlocker blocker(someQObject);
- // no signals here
- }
- \endcode
+ \snippet code/src_corelib_kernel_qobject.cpp 53
is thus equivalent to
- \code
- const bool wasBlocked = someQObject->blockSignals(true);
- // no signals here
- someQObject->blockSignals(wasBlocked);
- \endcode
+ \snippet code/src_corelib_kernel_qobject.cpp 54
except the code using QSignalBlocker is safe in the face of
exceptions.
@@ -820,6 +814,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 +850,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 +1026,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);
}
@@ -3645,13 +3643,17 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
if (sender->d_func()->isDeclarativeSignalConnected(signal_index)
&& QAbstractDeclarativeData::signalEmitted) {
+ Q_TRACE(QMetaObject_activate_begin_declarative_signal, sender, signal_index);
QAbstractDeclarativeData::signalEmitted(sender->d_func()->declarativeData, sender,
signal_index, argv);
+ Q_TRACE(QMetaObject_activate_end_declarative_signal, sender, signal_index);
}
if (!sender->d_func()->isSignalConnected(signal_index, /*checkDeclarative =*/ false)
&& !qt_signal_spy_callback_set.signal_begin_callback
- && !qt_signal_spy_callback_set.signal_end_callback) {
+ && !qt_signal_spy_callback_set.signal_end_callback
+ && !Q_TRACE_ENABLED(QMetaObject_activate_begin_signal)
+ && !Q_TRACE_ENABLED(QMetaObject_activate_end_signal)) {
// The possible declarative connection is done, and nothing else is connected, so:
return;
}
@@ -3661,6 +3663,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
qt_signal_spy_callback_set.signal_begin_callback(sender, signal_index,
argv ? argv : empty_argv);
}
+ Q_TRACE(QMetaObject_activate_begin_signal, sender, signal_index);
{
QMutexLocker locker(signalSlotLock(sender));
@@ -3691,6 +3694,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
locker.unlock();
if (qt_signal_spy_callback_set.signal_end_callback != 0)
qt_signal_spy_callback_set.signal_end_callback(sender, signal_index);
+ Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index);
return;
}
@@ -3722,7 +3726,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: "
@@ -3751,7 +3755,9 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
c->slotObj->ref();
QScopedPointer<QtPrivate::QSlotObjectBase, QSlotObjectBaseDeleter> obj(c->slotObj);
locker.unlock();
+ Q_TRACE(QMetaObject_activate_begin_slot_functor, obj.data());
obj->call(receiver, argv ? argv : empty_argv);
+ Q_TRACE(QMetaObject_activate_end_slot_functor, obj.data());
// Make sure the slot object gets destroyed before the mutex is locked again, as the
// destructor of the slot object might also lock a mutex from the signalSlotLock() mutex pool,
@@ -3767,9 +3773,11 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
locker.unlock();
if (qt_signal_spy_callback_set.slot_begin_callback != 0)
qt_signal_spy_callback_set.slot_begin_callback(receiver, methodIndex, argv ? argv : empty_argv);
+ Q_TRACE(QMetaObject_activate_begin_slot, receiver, methodIndex);
callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv);
+ Q_TRACE(QMetaObject_activate_end_slot, receiver, methodIndex);
if (qt_signal_spy_callback_set.slot_end_callback != 0)
qt_signal_spy_callback_set.slot_end_callback(receiver, methodIndex);
locker.relock();
@@ -3782,9 +3790,11 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
method,
argv ? argv : empty_argv);
}
+ Q_TRACE(QMetaObject_activate_begin_slot, receiver, method);
metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+ Q_TRACE(QMetaObject_activate_end_slot, receiver, method);
if (qt_signal_spy_callback_set.slot_end_callback != 0)
qt_signal_spy_callback_set.slot_end_callback(receiver, method);
@@ -3805,7 +3815,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
if (qt_signal_spy_callback_set.signal_end_callback != 0)
qt_signal_spy_callback_set.signal_end_callback(sender, signal_index);
-
+ Q_TRACE(QMetaObject_activate_end_signal, sender, signal_index);
}
/*!
@@ -4534,6 +4544,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 +4696,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 +4736,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 +4819,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/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp
index be42a369c2..c1dba30e2b 100644
--- a/src/corelib/kernel/qsharedmemory_win.cpp
+++ b/src/corelib/kernel/qsharedmemory_win.cpp
@@ -101,7 +101,8 @@ HANDLE QSharedMemoryPrivate::handle()
#if defined(Q_OS_WINRT)
hand = OpenFileMappingFromApp(FILE_MAP_ALL_ACCESS, FALSE, reinterpret_cast<PCWSTR>(nativeKey.utf16()));
#else
- hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)nativeKey.utf16());
+ hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false,
+ reinterpret_cast<const wchar_t*>(nativeKey.utf16()));
#endif
if (!hand) {
setErrorString(function);
@@ -133,17 +134,16 @@ bool QSharedMemoryPrivate::create(int size)
// Create the file mapping.
#if defined(Q_OS_WINRT)
- hand = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, size, (PCWSTR)nativeKey.utf16());
+ hand = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, size,
+ reinterpret_cast<PCWSTR>(nativeKey.utf16()));
#else
- hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)nativeKey.utf16());
+ hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size,
+ reinterpret_cast<const wchar_t*>(nativeKey.utf16()));
#endif
setErrorString(function);
// hand is valid when it already exists unlike unix so explicitly check
- if (error == QSharedMemory::AlreadyExists || !hand)
- return false;
-
- return true;
+ return error != QSharedMemory::AlreadyExists && hand;
}
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
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/qsystemsemaphore_win.cpp b/src/corelib/kernel/qsystemsemaphore_win.cpp
index 3395f5641e..2b35803291 100644
--- a/src/corelib/kernel/qsystemsemaphore_win.cpp
+++ b/src/corelib/kernel/qsystemsemaphore_win.cpp
@@ -86,9 +86,12 @@ HANDLE QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode)
// Create it if it doesn't already exists.
if (semaphore == 0) {
#if defined(Q_OS_WINRT)
- semaphore = CreateSemaphoreEx(0, initialValue, MAXLONG, (wchar_t*)fileName.utf16(), 0, SEMAPHORE_ALL_ACCESS);
+ semaphore = CreateSemaphoreEx(0, initialValue, MAXLONG,
+ reinterpret_cast<const wchar_t*>(fileName.utf16()),
+ 0, SEMAPHORE_ALL_ACCESS);
#else
- semaphore = CreateSemaphore(0, initialValue, MAXLONG, (wchar_t*)fileName.utf16());
+ semaphore = CreateSemaphore(0, initialValue, MAXLONG,
+ reinterpret_cast<const wchar_t*>(fileName.utf16()));
#endif
if (semaphore == NULL)
setErrorString(QLatin1String("QSystemSemaphore::handle"));
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..d69551a227
--- /dev/null
+++ b/src/corelib/kernel/qtestsupport_core.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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:
+
+ \snippet code/src_corelib_kernel_qtestsupport_core.cpp 0
+
+ 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:
+
+ \snippet code/src_corelib_kernel_qtestsupport_core.cpp 1
+
+ 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..90f29aa630 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 callOnTimeout(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 callOnTimeout(QObject *context, Functor functor, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \since 5.12
+ \overload callOnTimeout()
+
+ 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 callOnTimeout(QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType connectionType = Qt::AutoConnection)
+ \since 5.12
+ \overload callOnTimeout()
+
+ 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..66f317c567 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 callOnTimeout(Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
+ template <typename Functor>
+ QMetaObject::Connection callOnTimeout(const QObject *context, Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection);
+ template <typename PointerToMemberFunction>
+ QMetaObject::Connection callOnTimeout(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 callOnTimeout(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 57c25a9423..0b4c3f387f 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 fe086acb5d..3c73c0b851 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