diff options
Diffstat (limited to 'src/corelib')
57 files changed, 880 insertions, 142 deletions
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index f3f3139d1a..e5e47082d8 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -898,7 +898,7 @@ /* C11 features supported in GCC 4.7: */ # define Q_COMPILER_STATIC_ASSERT # endif -# if Q_CC_GNU >= 409 +# if Q_CC_GNU >= 409 && defined(__has_include) /* C11 features supported in GCC 4.9: */ # if __has_include(<threads.h>) # define Q_COMPILER_THREAD_LOCAL diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 31b1823690..982eb75650 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -107,6 +107,7 @@ public: KeyboardModifierMask = 0xfe000000 }; Q_DECLARE_FLAGS(KeyboardModifiers, KeyboardModifier) + Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardModifiers) //shorter names for shortcuts // The use of all-caps identifiers has the potential for clashing with @@ -163,6 +164,7 @@ public: MouseButtonMask = 0xffffffff }; Q_DECLARE_FLAGS(MouseButtons, MouseButton) + Q_DECLARE_OPERATORS_FOR_FLAGS(MouseButtons) enum Orientation { Horizontal = 0x1, @@ -170,6 +172,7 @@ public: }; Q_DECLARE_FLAGS(Orientations, Orientation) + Q_DECLARE_OPERATORS_FOR_FLAGS(Orientations) enum FocusPolicy { NoFocus = 0, @@ -225,6 +228,7 @@ public: }; Q_DECLARE_FLAGS(Alignment, AlignmentFlag) + Q_DECLARE_OPERATORS_FOR_FLAGS(Alignment) enum TextFlag { TextSingleLine = 0x0100, @@ -308,6 +312,7 @@ public: }; Q_DECLARE_FLAGS(WindowFlags, WindowType) + Q_DECLARE_OPERATORS_FOR_FLAGS(WindowFlags) enum WindowState { WindowNoState = 0x00000000, @@ -318,6 +323,7 @@ public: }; Q_DECLARE_FLAGS(WindowStates, WindowState) + Q_DECLARE_OPERATORS_FOR_FLAGS(WindowStates) enum ApplicationState { ApplicationSuspended = 0x00000000, @@ -337,6 +343,7 @@ public: }; Q_DECLARE_FLAGS(ScreenOrientations, ScreenOrientation) + Q_DECLARE_OPERATORS_FOR_FLAGS(ScreenOrientations) enum WidgetAttribute { WA_Disabled = 0, @@ -553,6 +560,7 @@ public: NoFormatConversion = 0x00000200 }; Q_DECLARE_FLAGS(ImageConversionFlags, ImageConversionFlag) + Q_DECLARE_OPERATORS_FOR_FLAGS(ImageConversionFlags) enum BGMode { TransparentMode, @@ -1210,6 +1218,7 @@ public: }; Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea) + Q_DECLARE_OPERATORS_FOR_FLAGS(DockWidgetAreas) enum ToolBarArea { LeftToolBarArea = 0x1, @@ -1227,6 +1236,7 @@ public: }; Q_DECLARE_FLAGS(ToolBarAreas, ToolBarArea) + Q_DECLARE_OPERATORS_FOR_FLAGS(ToolBarAreas) enum DateFormat { TextDate, // default Qt @@ -1285,6 +1295,7 @@ public: }; Q_DECLARE_FLAGS(Edges, Edge) + Q_DECLARE_OPERATORS_FOR_FLAGS(Edges) enum ConnectionType { AutoConnection, @@ -1387,6 +1398,7 @@ public: ImQueryAll = 0xffffffff }; Q_DECLARE_FLAGS(InputMethodQueries, InputMethodQuery) + Q_DECLARE_OPERATORS_FOR_FLAGS(InputMethodQueries) enum InputMethodHint { ImhNone = 0x0, @@ -1421,6 +1433,7 @@ public: ImhExclusiveInputMask = 0xffff0000 }; Q_DECLARE_FLAGS(InputMethodHints, InputMethodHint) + Q_DECLARE_OPERATORS_FOR_FLAGS(InputMethodHints) enum EnterKeyType { EnterKeyDefault, @@ -1471,6 +1484,7 @@ public: IgnoreAction = 0x0 }; Q_DECLARE_FLAGS(DropActions, DropAction) + Q_DECLARE_OPERATORS_FOR_FLAGS(DropActions) enum CheckState { Unchecked, @@ -1525,6 +1539,7 @@ public: ItemIsUserTristate = 256 }; Q_DECLARE_FLAGS(ItemFlags, ItemFlag) + Q_DECLARE_OPERATORS_FOR_FLAGS(ItemFlags) enum MatchFlag { MatchExactly = 0, @@ -1539,6 +1554,7 @@ public: MatchRecursive = 64 }; Q_DECLARE_FLAGS(MatchFlags, MatchFlag) + Q_DECLARE_OPERATORS_FOR_FLAGS(MatchFlags) typedef void * HANDLE; #if QT_DEPRECATED_SINCE(5, 0) @@ -1563,6 +1579,7 @@ public: TextBrowserInteraction = TextSelectableByMouse | LinksAccessibleByMouse | LinksAccessibleByKeyboard }; Q_DECLARE_FLAGS(TextInteractionFlags, TextInteractionFlag) + Q_DECLARE_OPERATORS_FOR_FLAGS(TextInteractionFlags) enum EventPriority { HighEventPriority = 1, @@ -1614,6 +1631,7 @@ public: TouchPointReleased = 0x08 }; Q_DECLARE_FLAGS(TouchPointStates, TouchPointState) + Q_DECLARE_OPERATORS_FOR_FLAGS(TouchPointStates) #ifndef QT_NO_GESTURES enum GestureState @@ -1645,6 +1663,7 @@ public: IgnoredGesturesPropagateToParent = 0x04 }; Q_DECLARE_FLAGS(GestureFlags, GestureFlag) + Q_DECLARE_OPERATORS_FOR_FLAGS(GestureFlags) enum NativeGestureType { @@ -1698,6 +1717,7 @@ public: MouseEventFlagMask = 0xFF }; Q_DECLARE_FLAGS(MouseEventFlags, MouseEventFlag) + Q_DECLARE_OPERATORS_FOR_FLAGS(MouseEventFlags) enum ChecksumType { ChecksumIso3309, @@ -1800,29 +1820,6 @@ public: #undef QT_Q_ENUM #undef QT_Q_FLAG -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MouseButtons) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::Orientations) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::KeyboardModifiers) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::WindowFlags) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::Alignment) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::Edges) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ImageConversionFlags) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::DockWidgetAreas) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ToolBarAreas) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::WindowStates) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ScreenOrientations) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::DropActions) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::ItemFlags) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MatchFlags) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TextInteractionFlags) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::InputMethodQueries) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::InputMethodHints) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TouchPointStates) -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MouseEventFlags) -#ifndef QT_NO_GESTURES -Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::GestureFlags) -#endif - typedef bool (*qInternalCallback)(void **); class Q_CORE_EXPORT QInternal { diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index e4d384e4ca..06eacf5455 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -2035,7 +2035,7 @@ QString QDir::homePath() Returns the system's temporary directory. - The directory is constructed using the absolute path of the temporary directory, + The directory is constructed using the absolute canonical path of the temporary directory, ensuring that its path() will be the same as its absolutePath(). See tempPath() for details. @@ -2044,7 +2044,7 @@ QString QDir::homePath() */ /*! - Returns the absolute path of the system's temporary directory. + Returns the absolute canonical path of the system's temporary directory. On Unix/Linux systems this is the path in the \c TMPDIR environment variable or \c{/tmp} if \c TMPDIR is not defined. On Windows this is diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index b8cf42a2e9..5cc3a5937e 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -1532,7 +1532,7 @@ QString QFileSystemEngine::tempPath() temp = QLatin1String(_PATH_TMP); } } - return QDir::cleanPath(temp); + return QDir(QDir::cleanPath(temp)).canonicalPath(); #endif } diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm index 792ea387ac..844aa9daa7 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents.mm +++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm @@ -499,7 +499,7 @@ bool QFseventsFileSystemWatcherEngine::startStream() DEBUG() << "Starting stream with paths" << watchingState.watchedPaths.keys(); - NSMutableArray *pathsToWatch = [NSMutableArray arrayWithCapacity:watchingState.watchedPaths.size()]; + NSMutableArray<NSString *> *pathsToWatch = [NSMutableArray<NSString *> arrayWithCapacity:watchingState.watchedPaths.size()]; for (PathRefCounts::const_iterator i = watchingState.watchedPaths.begin(), ei = watchingState.watchedPaths.end(); i != ei; ++i) [pathsToWatch addObject:i.key().toNSString()]; diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index 78093727b8..0025c60c3b 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -574,6 +574,19 @@ QVector<QPair<int, int > > QSortFilterProxyModelPrivate::proxy_intervals_for_sou proxy_intervals.append(QPair<int, int>(first_proxy_item, last_proxy_item)); } std::stable_sort(proxy_intervals.begin(), proxy_intervals.end()); + // Consolidate adjacent intervals + for (int i = proxy_intervals.size()-1; i > 0; --i) { + QPair<int, int> &interval = proxy_intervals[i]; + QPair<int, int> &preceeding_interval = proxy_intervals[i - 1]; + if (interval.first == preceeding_interval.second + 1) { + preceeding_interval.second = interval.second; + interval.first = interval.second = -1; + } + } + proxy_intervals.erase( + std::remove_if(proxy_intervals.begin(), proxy_intervals.end(), + [](QPair<int, int> &interval) { return interval.first < 0; }), + proxy_intervals.end()); return proxy_intervals; } diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index 5ecd86a30e..c1062e98b8 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -87,19 +87,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 diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 9c6cef68b2..e8aa24b944 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -51,18 +51,50 @@ // We mean it. // +#include "private/qglobal_p.h" + #ifndef __IMAGECAPTURE__ # define __IMAGECAPTURE__ #endif +// -------------------------------------------------------------------------- + +#if !defined(QT_BOOTSTRAPPED) && (QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) || !defined(Q_OS_MACOS)) +#define QT_USE_APPLE_ACTIVITIES + +#if defined(OS_ACTIVITY_OBJECT_API) +#error The file <os/activity.h> has already been included +#endif + +// We runtime-check all use of the activity APIs, so we can safely build +// with them included, even if the deployment target is macOS 10.11 +#if QT_MACOS_DEPLOYMENT_TARGET_BELOW(__MAC_10_12) +#undef __MAC_OS_X_VERSION_MIN_REQUIRED +#define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_12 +#define DID_OVERRIDE_DEPLOYMENT_TARGET +#endif + +#include <os/activity.h> +#if !OS_ACTIVITY_OBJECT_API +#error "Expected activity API to be available" +#endif + +#if defined(DID_OVERRIDE_DEPLOYMENT_TARGET) +#undef __MAC_OS_X_VERSION_MIN_REQUIRED +#define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_11 +#undef DID_OVERRIDE_DEPLOYMENT_TARGET +#endif + +#endif + +// -------------------------------------------------------------------------- + #if defined(QT_BOOTSTRAPPED) #include <ApplicationServices/ApplicationServices.h> #else #include <CoreFoundation/CoreFoundation.h> #endif -#include "private/qglobal_p.h" - #ifdef __OBJC__ #include <Foundation/Foundation.h> #endif @@ -190,6 +222,100 @@ private: // -------------------------------------------------------------------------- +#if defined(QT_USE_APPLE_ACTIVITIES) + +QT_END_NAMESPACE +#include <os/availability.h> +#define OS_ACTIVITY_AVAILABILITY API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)) +#define OS_ACTIVITY_AVAILABILITY_CHECK __builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *) +QT_BEGIN_NAMESPACE + +template <typename T> using QAppleOsType = QAppleRefCounted<T, void *, os_retain, os_release>; + +class Q_CORE_EXPORT QAppleLogActivity +{ +public: + QAppleLogActivity() : activity(nullptr) {} + QAppleLogActivity(os_activity_t activity) OS_ACTIVITY_AVAILABILITY : activity(activity) {} + ~QAppleLogActivity() { if (activity) leave(); } + + QAppleLogActivity(const QAppleLogActivity &) = delete; + QAppleLogActivity& operator=(const QAppleLogActivity &) = delete; + + QAppleLogActivity(QAppleLogActivity&& other) + : activity(other.activity), state(other.state) { other.activity = nullptr; } + + QAppleLogActivity& operator=(QAppleLogActivity &&other) + { + if (this != &other) { + activity = other.activity; + state = other.state; + other.activity = nullptr; + } + return *this; + } + + QAppleLogActivity&& enter() + { + if (activity) { + if (OS_ACTIVITY_AVAILABILITY_CHECK) + os_activity_scope_enter(static_cast<os_activity_t>(*this), &state); + } + return std::move(*this); + } + + void leave() { + if (activity) { + if (OS_ACTIVITY_AVAILABILITY_CHECK) + os_activity_scope_leave(&state); + } + } + + operator os_activity_t() OS_ACTIVITY_AVAILABILITY + { + return reinterpret_cast<os_activity_t>(static_cast<void *>(activity)); + } + +private: + // Work around API_AVAILABLE not working for templates by using void* + QAppleOsType<void *> activity; + os_activity_scope_state_s state; +}; + +#define QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) []() { \ + if (!(condition)) \ + return QAppleLogActivity(); \ + if (OS_ACTIVITY_AVAILABILITY_CHECK) \ + return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT)); \ + return QAppleLogActivity(); \ + }() + +#define QT_VA_ARGS_CHOOSE(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N +#define QT_VA_ARGS_COUNT(...) QT_VA_ARGS_CHOOSE(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1) + +#define QT_OVERLOADED_MACRO(MACRO, ...) _QT_OVERLOADED_MACRO(MACRO, QT_VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__) +#define _QT_OVERLOADED_MACRO(MACRO, ARGC) _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) +#define _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) MACRO##ARGC + +#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(condition, description, parent) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) +#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(true, description, parent) +#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY_WITH_PARENT, __VA_ARGS__) + +#define QT_APPLE_LOG_ACTIVITY2(condition, description) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, OS_ACTIVITY_CURRENT) +#define QT_APPLE_LOG_ACTIVITY1(description) QT_APPLE_LOG_ACTIVITY2(true, description) +#define QT_APPLE_LOG_ACTIVITY(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY, __VA_ARGS__) + +#define QT_APPLE_SCOPED_LOG_ACTIVITY(...) QAppleLogActivity scopedLogActivity = QT_APPLE_LOG_ACTIVITY(__VA_ARGS__).enter(); + +#else +// No-ops for macOS 10.11. We don't need to provide QT_APPLE_SCOPED_LOG_ACTIVITY, +// as all the call sites for that are in code that's only built on 10.12 and above. +#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...) +#define QT_APPLE_LOG_ACTIVITY(...) +#endif // QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE + +// ------------------------------------------------------------------------- + QT_END_NAMESPACE #endif // QCORE_MAC_P_H diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 4e32f90964..e0ae350f32 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1889,7 +1889,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/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp index d8a670310b..97b98a1376 100644 --- a/src/corelib/kernel/qdeadlinetimer.cpp +++ b/src/corelib/kernel/qdeadlinetimer.cpp @@ -39,7 +39,6 @@ #include "qdeadlinetimer.h" #include "qdeadlinetimer_p.h" -#include <qpair.h> QT_BEGIN_NAMESPACE diff --git a/src/corelib/kernel/qdeadlinetimer.h b/src/corelib/kernel/qdeadlinetimer.h index 6c10e1025e..1a4ee04a96 100644 --- a/src/corelib/kernel/qdeadlinetimer.h +++ b/src/corelib/kernel/qdeadlinetimer.h @@ -43,6 +43,7 @@ #include <QtCore/qelapsedtimer.h> #include <QtCore/qmetatype.h> #include <QtCore/qnamespace.h> +#include <QtCore/qpair.h> #ifdef max // un-pollute the namespace. We need std::numeric_limits::max() and std::chrono::duration::max() @@ -186,6 +187,10 @@ private: unsigned type; qint64 rawRemainingTimeNSecs() const Q_DECL_NOTHROW; + +public: + // This is not a public function, it's here only for Qt's internal convenience... + QPair<qint64, unsigned> _q_data() const { return qMakePair(t1, t2); } }; Q_DECLARE_SHARED(QDeadlineTimer) diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm index 8499b3fd57..a6c5ccd7a8 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); [[NSNotificationCenter defaultCenter] @@ -77,21 +95,21 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(RunLoopModeTracker); selector:@selector(receivedNotification:) name:nil #ifdef Q_OS_OSX - object:[NSApplication sharedApplication]]; + object:NSApplication.sharedApplication]; #elif defined(Q_OS_WATCHOS) - object:[WKExtension sharedExtension]]; + object:WKExtension.sharedExtension]; #else // Use performSelector so this can work in an App Extension - object:[[UIApplication class] performSelector:@selector(sharedApplication)]]; + object:[UIApplication.class performSelector:@selector(sharedApplication)]]; #endif } return self; } -- (void) dealloc +- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; + [NSNotificationCenter.defaultCenter removeObserver:self]; [super dealloc]; } @@ -100,13 +118,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)) @@ -116,7 +134,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" @@ -126,7 +144,7 @@ static CFStringRef runLoopMode(NSDictionary *dictionary) } } -- (CFStringRef) currentMode +- (CFStringRef)currentMode { return m_runLoopModes.top(); } @@ -238,6 +256,7 @@ 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)) @@ -390,6 +409,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; @@ -405,6 +426,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; 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/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index fc40668c9a..0e57cb8cba 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -316,7 +316,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 */ diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index dcc1bb5814..25d17ecd6b 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4802,7 +4802,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/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index c3504943c4..802c8d72f6 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -571,6 +571,48 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv */ /*! + \fn template<typename Functor> QMetaObject::Connection connectTo(Functor functor, Qt::ConnectionType connectionType = Qt::AutoConnection) + \since 5.12 + \overload + + Creates a connection from the timeout() signal to \a functor, and returns a + handle to the connection. + + This method is provided for convenience. + It's equivalent to calling \c {QObject::connect(timer, &QTimer::timeout, timer, functor, connectionType)}. + + \sa QObject::connect(), timeout() +*/ + +/*! + \fn template<typename Functor> QMetaObject::Connection connectTo(QObject *context, Functor functor, Qt::ConnectionType connectionType = Qt::AutoConnection) + \since 5.12 + \overload connectTo() + + Creates a connection from the timeout() signal to \a functor to be placed in a specific + event loop of \a context, and returns a handle to the connection. + + This method is provided for convenience. It's equivalent to calling + \c {QObject::connect(timer, &QTimer::timeout, context, functor, connectionType)}. + + \sa QObject::connect(), timeout() +*/ + +/*! + \fn template<typename PointerToMemberFunction> QMetaObject::Connection connectTo(QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType connectionType = Qt::AutoConnection) + \since 5.12 + \overload connectTo() + + Creates a connection from the timeout() signal to the \a method in the \a receiver object. Returns + a handle to the connection. + + This method is provided for convenience. It's equivalent to calling + \c {QObject::connect(timer, &QTimer::timeout, receiver, method, connectionType)}. + + \sa QObject::connect(), timeout() +*/ + +/*! \fn void QTimer::start(std::chrono::milliseconds msec) \since 5.8 \overload diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h index e6db586aa0..7825bb0798 100644 --- a/src/corelib/kernel/qtimer.h +++ b/src/corelib/kernel/qtimer.h @@ -96,6 +96,12 @@ public: static void singleShot(int msec, const QObject *context, Functor functor); template<typename Functor, int> static void singleShot(int msec, Qt::TimerType timerType, const QObject *context, Functor functor); + template <typename Functor> + QMetaObject::Connection connectTo(Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection); + template <typename Functor> + QMetaObject::Connection connectTo(const QObject *context, Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection); + template <typename PointerToMemberFunction> + QMetaObject::Connection connectTo(const QObject *receiver, PointerToMemberFunction slot, Qt::ConnectionType connectionType = Qt::AutoConnection); #else // singleShot to a QObject slot template <typename Duration, typename Func1> @@ -152,6 +158,13 @@ public: new QtPrivate::QFunctorSlotObject<Func1, 0, typename QtPrivate::List_Left<void, 0>::Value, void>(std::move(slot))); } + + template <typename ... Args> + QMetaObject::Connection connectTo(Args && ...args) + { + return QObject::connect(this, &QTimer::timeout, std::forward<Args>(args)... ); + } + #endif public Q_SLOTS: diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 6192b66487..b41a883e80 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1175,9 +1175,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,7 +1193,7 @@ 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); + QMetaType::destruct(d->type, d->data.shared->ptr); delete d->data.shared; } } diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 9a5fc63d03..ff73c27b6e 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -633,6 +633,7 @@ public: const_iterator &operator-=(int j); const_iterator operator+(int j) const; const_iterator operator-(int j) const; + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } }; friend struct const_iterator; @@ -690,6 +691,7 @@ public: const_iterator &operator-=(int j); const_iterator operator+(int j) const; const_iterator operator-(int j) const; + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } }; friend struct const_iterator; diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index 24de491326..85d4ad4fa9 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -157,7 +157,6 @@ void QWinEventNotifier::setHandle(HANDLE hEvent) Q_D(QWinEventNotifier); setEnabled(false); d->handleToEvent = hEvent; - d->signaledCount = 0; } /*! @@ -209,10 +208,12 @@ void QWinEventNotifier::setEnabled(bool enable) return; } - if (enable) + if (enable) { + d->signaledCount = 0; eventDispatcher->registerEventNotifier(this); - else + } else { eventDispatcher->unregisterEventNotifier(this); + } } /*! diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index a4be18a67f..deea7a7d17 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -117,29 +117,22 @@ void QFactoryLoader::update() QDir::Files); QLibraryPrivate *library = 0; -#ifdef Q_OS_MAC - // Loading both the debug and release version of the cocoa plugins causes the objective-c runtime - // to print "duplicate class definitions" warnings. Detect if QFactoryLoader is about to load both, - // skip one of them (below). - // - // ### FIXME find a proper solution - // - const bool isLoadingDebugAndReleaseCocoa = plugins.contains(QLatin1String("libqcocoa_debug.dylib")) - && plugins.contains(QLatin1String("libqcocoa.dylib")); -#endif for (int j = 0; j < plugins.count(); ++j) { QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j)); #ifdef Q_OS_MAC - if (isLoadingDebugAndReleaseCocoa) { -#ifdef QT_DEBUG - if (fileName.contains(QLatin1String("libqcocoa.dylib"))) - continue; // Skip release plugin in debug mode -#else - if (fileName.contains(QLatin1String("libqcocoa_debug.dylib"))) - continue; // Skip debug plugin in release mode -#endif - } + const bool isDebugPlugin = fileName.endsWith(QLatin1String("_debug.dylib")); + const bool isDebugLibrary = + #ifdef QT_DEBUG + true; + #else + false; + #endif + + // Skip mismatching plugins so that we don't end up loading both debug and release + // versions of the same Qt libraries (due to the plugin's dependencies). + if (isDebugPlugin != isDebugLibrary) + continue; #endif if (qt_debug_component()) { qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName; diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index b644d47856..07edc616df 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -105,11 +105,21 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); }; \ static Static##PLUGIN##PluginInstance static##PLUGIN##Instance; +#if defined(QT_PLUGIN_RESOURCE_INIT_FUNCTION) +# define QT_PLUGIN_RESOURCE_INIT \ + extern void QT_PLUGIN_RESOURCE_INIT_FUNCTION(); \ + QT_PLUGIN_RESOURCE_INIT_FUNCTION(); +#else +# define QT_PLUGIN_RESOURCE_INIT +#endif + #define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \ { \ static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \ - if (!_instance) \ + if (!_instance) { \ + QT_PLUGIN_RESOURCE_INIT \ _instance = new IMPLEMENTATION; \ + } \ return _instance; \ } diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp index 8f419a4a46..54d1ae816b 100644 --- a/src/corelib/serialization/qdatastream.cpp +++ b/src/corelib/serialization/qdatastream.cpp @@ -564,6 +564,7 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_5_9 Same as Qt_5_6 \value Qt_5_10 Same as Qt_5_6 \value Qt_5_11 Same as Qt_5_6 + \value Qt_5_12 Same as Qt_5_6 \omitvalue Qt_DefaultCompiledVersion \sa setVersion(), version() diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h index 1f1b13686c..85a2177652 100644 --- a/src/corelib/serialization/qdatastream.h +++ b/src/corelib/serialization/qdatastream.h @@ -98,10 +98,11 @@ public: Qt_5_9 = Qt_5_8, Qt_5_10 = Qt_5_9, Qt_5_11 = Qt_5_10, -#if QT_VERSION >= 0x050c00 + Qt_5_12 = Qt_5_11, +#if QT_VERSION >= 0x050d00 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif - Qt_DefaultCompiledVersion = Qt_5_11 + Qt_DefaultCompiledVersion = Qt_5_12 }; enum ByteOrder { diff --git a/src/corelib/thread/qfuture.h b/src/corelib/thread/qfuture.h index af599c26db..a456dd9139 100644 --- a/src/corelib/thread/qfuture.h +++ b/src/corelib/thread/qfuture.h @@ -136,6 +136,7 @@ public: inline const_iterator operator-(int j) const { return const_iterator(future, index - j); } inline const_iterator &operator+=(int j) { index += j; return *this; } inline const_iterator &operator-=(int j) { index -= j; return *this; } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } private: QFuture const * future; int index; diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h index 4e6f522a37..ec9bfc1152 100644 --- a/src/corelib/thread/qmutex_p.h +++ b/src/corelib/thread/qmutex_p.h @@ -58,6 +58,7 @@ #include <QtCore/qnamespace.h> #include <QtCore/qmutex.h> #include <QtCore/qatomic.h> +#include <QtCore/qdeadlinetimer.h> #if defined(Q_OS_MAC) # include <mach/semaphore.h> @@ -146,7 +147,7 @@ public: // helper functions for qmutex_unix.cpp and qwaitcondition_unix.cpp // they are in qwaitcondition_unix.cpp actually void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where); -void qt_abstime_for_timeout(struct timespec *ts, int timeout); +void qt_abstime_for_timeout(struct timespec *ts, QDeadlineTimer deadline); #endif QT_END_NAMESPACE diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index 3e1e531be4..91f02ba3ec 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -130,7 +130,7 @@ bool QMutexPrivate::wait(int timeout) errorCode = pthread_cond_wait(&cond, &mutex); } else { timespec ti; - qt_abstime_for_timeout(&ti, timeout); + qt_abstime_for_timeout(&ti, QDeadlineTimer(timeout)); errorCode = pthread_cond_timedwait(&cond, &mutex, &ti); } if (errorCode) { diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index e91e859975..f418ac1205 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -487,11 +487,9 @@ bool QSemaphore::tryAcquire(int n, int timeout) QDeadlineTimer timer(timeout); QMutexLocker locker(&d->mutex); - qint64 remainingTime = timer.remainingTime(); - while (n > d->avail && remainingTime != 0) { - if (!d->cond.wait(locker.mutex(), remainingTime)) + while (n > d->avail && !timer.hasExpired()) { + if (!d->cond.wait(locker.mutex(), timer)) return false; - remainingTime = timer.remainingTime(); } if (n > d->avail) return false; diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h index a0c6766833..e42efbdfca 100644 --- a/src/corelib/thread/qwaitcondition.h +++ b/src/corelib/thread/qwaitcondition.h @@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_THREAD +class QDeadlineTimer; class QWaitConditionPrivate; class QMutex; class QReadWriteLock; @@ -59,8 +60,11 @@ public: QWaitCondition(); ~QWaitCondition(); + // ### Qt 6: remove unsigned long overloads bool wait(QMutex *lockedMutex, unsigned long time = ULONG_MAX); + bool wait(QMutex *lockedMutex, QDeadlineTimer deadline); bool wait(QReadWriteLock *lockedReadWriteLock, unsigned long time = ULONG_MAX); + bool wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline); void wakeOne(); void wakeAll(); diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp index 6adee5412e..1628ede3a2 100644 --- a/src/corelib/thread/qwaitcondition_unix.cpp +++ b/src/corelib/thread/qwaitcondition_unix.cpp @@ -44,6 +44,8 @@ #include "qreadwritelock.h" #include "qatomic.h" #include "qstring.h" +#include "qdeadlinetimer.h" +#include "private/qdeadlinetimer_p.h" #include "qelapsedtimer.h" #include "private/qcore_unix_p.h" @@ -93,23 +95,25 @@ void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where) pthread_condattr_destroy(&condattr); } -void qt_abstime_for_timeout(timespec *ts, int timeout) +void qt_abstime_for_timeout(timespec *ts, QDeadlineTimer deadline) { #ifdef Q_OS_MAC // on Mac, qt_gettime() (on qelapsedtimer_mac.cpp) returns ticks related to the Mach absolute time // that doesn't work with pthread // Mac also doesn't have clock_gettime struct timeval tv; + qint64 nsec = deadline.remainingTimeNSecs(); gettimeofday(&tv, 0); - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec * 1000; -#else - *ts = qt_gettime(); -#endif + ts->tv_sec = tv.tv_sec + nsec / (1000 * 1000 * 1000); + ts->tv_nsec = tv.tv_usec * 1000 + nsec % (1000 * 1000 * 1000); - ts->tv_sec += timeout / 1000; - ts->tv_nsec += timeout % 1000 * Q_UINT64_C(1000) * 1000; normalizedTimespec(*ts); +#else + // depends on QDeadlineTimer's internals!! + Q_STATIC_ASSERT(QDeadlineTimerNanosecondsInT2); + ts->tv_sec = deadline._q_data().first; + ts->tv_nsec = deadline._q_data().second; +#endif } class QWaitConditionPrivate { @@ -119,26 +123,27 @@ public: int waiters; int wakeups; - int wait_relative(unsigned long time) + int wait_relative(QDeadlineTimer deadline) { timespec ti; #ifdef Q_OS_ANDROID - if (local_cond_timedwait_relative) { - ti.tv_sec = time / 1000; - ti.tv_nsec = time % 1000 * Q_UINT64_C(1000) * 1000; + if (!local_condattr_setclock && local_cond_timedwait_relative) { + qint64 nsec = deadline.remainingTimeNSecs(); + ti.tv_sec = nsec / (1000 * 1000 * 1000); + ti.tv_nsec = nsec - ti.tv_sec * 1000 * 1000 * 1000; return local_cond_timedwait_relative(&cond, &mutex, &ti); } #endif - qt_abstime_for_timeout(&ti, time); + qt_abstime_for_timeout(&ti, deadline); return pthread_cond_timedwait(&cond, &mutex, &ti); } - bool wait(unsigned long time) + bool wait(QDeadlineTimer deadline) { int code; forever { - if (time != ULONG_MAX) { - code = wait_relative(time); + if (!deadline.isForever()) { + code = wait_relative(deadline); } else { code = pthread_cond_wait(&cond, &mutex); } @@ -201,6 +206,13 @@ void QWaitCondition::wakeAll() bool QWaitCondition::wait(QMutex *mutex, unsigned long time) { + if (time > std::numeric_limits<qint64>::max()) + return wait(mutex, QDeadlineTimer(QDeadlineTimer::Forever)); + return wait(mutex, QDeadlineTimer(time)); +} + +bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline) +{ if (! mutex) return false; if (mutex->isRecursive()) { @@ -212,7 +224,7 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time) ++d->waiters; mutex->unlock(); - bool returnValue = d->wait(time); + bool returnValue = d->wait(deadline); mutex->lock(); @@ -221,6 +233,11 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time) bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) { + return wait(readWriteLock, QDeadlineTimer(time)); +} + +bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline) +{ if (!readWriteLock) return false; auto previousState = readWriteLock->stateForWaitCondition(); @@ -236,7 +253,7 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) readWriteLock->unlock(); - bool returnValue = d->wait(time); + bool returnValue = d->wait(deadline); if (previousState == QReadWriteLock::LockedForWrite) readWriteLock->lockForWrite(); diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index e6610f18c8..61e4c2bcb1 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qwaitcondition.h" +#include "qdeadlinetimer.h" #include "qnamespace.h" #include "qmutex.h" #include "qreadwritelock.h" @@ -184,6 +185,11 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time) return returnValue; } +bool QWaitCondition::wait(QMutex *mutex, QDeadlineTimer deadline) +{ + return wait(mutex, deadline.remainingTime()); +} + bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) { if (!readWriteLock) @@ -210,6 +216,11 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, unsigned long time) return returnValue; } +bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline) +{ + return wait(readWriteLock, deadline.remainingTime()); +} + void QWaitCondition::wakeOne() { // wake up the first waiting thread in the queue diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index f0cc56e899..a642fb9b39 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -159,6 +159,7 @@ struct QTypedArrayData inline iterator &operator-=(int j) { i-=j; return *this; } inline iterator operator+(int j) const { return iterator(i+j); } inline iterator operator-(int j) const { return iterator(i-j); } + friend inline iterator operator+(int j, iterator k) { return k + j; } inline int operator-(iterator j) const { return i - j.i; } inline operator T*() const { return i; } }; @@ -194,6 +195,7 @@ struct QTypedArrayData inline const_iterator &operator-=(int j) { i-=j; return *this; } inline const_iterator operator+(int j) const { return const_iterator(i+j); } inline const_iterator operator-(int j) const { return const_iterator(i-j); } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } inline int operator-(const_iterator j) const { return i - j.i; } inline operator const T*() const { return i; } }; diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 83b9f19094..d9cd20ffbf 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -963,7 +963,7 @@ static inline char qToLower(char c) $LC_CTYPE is set, most Unix systems do "the right thing".) Functions that this affects include contains(), indexOf(), lastIndexOf(), operator<(), operator<=(), operator>(), - operator>=(), toLower() and toUpper(). + operator>=(), isLower(), isUpper(), toLower() and toUpper(). This issue does not apply to \l{QString}s since they represent characters using Unicode. @@ -2954,6 +2954,78 @@ bool QByteArray::endsWith(const char *str) const return qstrncmp(d->data() + d->size - len, str, len) == 0; } +/*! + Returns true if \a c is an uppercase Latin1 letter. + \note The multiplication sign 0xD7 and the sz ligature 0xDF are not + treated as uppercase Latin1. + */ +static inline bool isUpperCaseLatin1(char c) +{ + if (c >= 'A' && c <= 'Z') + return true; + + return (uchar(c) >= 0xC0 && uchar(c) <= 0xDE && uchar(c) != 0xD7); +} + +/*! + Returns \c true if this byte array contains only uppercase letters, + otherwise returns \c false. The byte array is interpreted as a Latin-1 + encoded string. + \since 5.12 + + \sa isLower(), toUpper() +*/ +bool QByteArray::isUpper() const +{ + if (isEmpty()) + return false; + + const char *d = data(); + + for (int i = 0, max = size(); i < max; ++i) { + if (!isUpperCaseLatin1(d[i])) + return false; + } + + return true; +} + +/*! + Returns true if \a c is an lowercase Latin1 letter. + \note The division sign 0xF7 is not treated as lowercase Latin1, + but the small y dieresis 0xFF is. + */ +static inline bool isLowerCaseLatin1(char c) +{ + if (c >= 'a' && c <= 'z') + return true; + + return (uchar(c) >= 0xD0 && uchar(c) != 0xF7); +} + +/*! + Returns \c true if this byte array contains only lowercase letters, + otherwise returns \c false. The byte array is interpreted as a Latin-1 + encoded string. + \since 5.12 + + \sa isUpper(), toLower() + */ +bool QByteArray::isLower() const +{ + if (isEmpty()) + return false; + + const char *d = data(); + + for (int i = 0, max = size(); i < max; ++i) { + if (!isLowerCaseLatin1(d[i])) + return false; + } + + return true; +} + /*! \overload Returns \c true if this byte array ends with character \a ch; @@ -3065,7 +3137,7 @@ QByteArray QByteArray::mid(int pos, int len) const Example: \snippet code/src_corelib_tools_qbytearray.cpp 30 - \sa toUpper(), {8-bit Character Comparisons} + \sa isLower(), toUpper(), {8-bit Character Comparisons} */ // prevent the compiler from inlining the function in each of @@ -3119,7 +3191,7 @@ QByteArray QByteArray::toLower_helper(QByteArray &a) Example: \snippet code/src_corelib_tools_qbytearray.cpp 31 - \sa toLower(), {8-bit Character Comparisons} + \sa isUpper(), toLower(), {8-bit Character Comparisons} */ QByteArray QByteArray::toUpper_helper(const QByteArray &a) diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 300f795469..bed710c597 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -245,6 +245,9 @@ public: bool endsWith(char c) const; bool endsWith(const char *c) const; + bool isUpper() const; + bool isLower() const; + void truncate(int pos); void chop(int n); diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index a1b121f1ee..3c79bb797d 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -544,6 +544,46 @@ QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method) return hash.result(); } +/*! + Returns the size of the output of the selected hash \a method in bytes. + + \since 5.12 +*/ +int QCryptographicHash::hashLength(QCryptographicHash::Algorithm method) +{ + switch (method) { + case QCryptographicHash::Sha1: + return 20; +#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 + case QCryptographicHash::Md4: + return 16; + case QCryptographicHash::Md5: + return 16; + case QCryptographicHash::Sha224: + return SHA224HashSize; + case QCryptographicHash::Sha256: + return SHA256HashSize; + case QCryptographicHash::Sha384: + return SHA384HashSize; + case QCryptographicHash::Sha512: + return SHA512HashSize; + case QCryptographicHash::RealSha3_224: + case QCryptographicHash::Keccak_224: + return 224 / 8; + case QCryptographicHash::RealSha3_256: + case QCryptographicHash::Keccak_256: + return 256 / 8; + case QCryptographicHash::RealSha3_384: + case QCryptographicHash::Keccak_384: + return 384 / 8; + case QCryptographicHash::RealSha3_512: + case QCryptographicHash::Keccak_512: + return 512 / 8; +#endif + } + return 0; +} + QT_END_NAMESPACE #ifndef QT_NO_QOBJECT diff --git a/src/corelib/tools/qcryptographichash.h b/src/corelib/tools/qcryptographichash.h index 2f74d42405..ad1de7c756 100644 --- a/src/corelib/tools/qcryptographichash.h +++ b/src/corelib/tools/qcryptographichash.h @@ -101,6 +101,7 @@ public: QByteArray result() const; static QByteArray hash(const QByteArray &data, Algorithm method); + static int hashLength(Algorithm method); private: Q_DISABLE_COPY(QCryptographicHash) QCryptographicHashPrivate *d; diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index ce663ce2ca..a586ca5671 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -348,6 +348,7 @@ public: inline iterator operator-(int j) const { return operator+(-j); } inline iterator &operator+=(int j) { return *this = *this + j; } inline iterator &operator-=(int j) { return *this = *this - j; } + friend inline iterator operator+(int j, iterator k) { return k + j; } #ifndef QT_STRICT_ITERATORS public: @@ -413,6 +414,7 @@ public: inline const_iterator operator-(int j) const { return operator+(-j); } inline const_iterator &operator+=(int j) { return *this = *this + j; } inline const_iterator &operator-=(int j) { return *this = *this - j; } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } // ### Qt 5: not sure this is necessary anymore #ifdef QT_STRICT_ITERATORS diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index c8f3f4c8c3..1e6d4df474 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -159,6 +159,7 @@ public: inline iterator operator-(int j) const { return operator+(-j); } inline iterator &operator+=(int j) { return *this = *this + j; } inline iterator &operator-=(int j) { return *this = *this - j; } + friend inline iterator operator+(int j, iterator k) { return k + j; } }; friend class iterator; @@ -193,6 +194,7 @@ public: inline const_iterator operator-(int j) const { return operator+(-j); } inline const_iterator &operator+=(int j) { return *this = *this + j; } inline const_iterator &operator-=(int j) { return *this = *this - j; } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } }; friend class const_iterator; diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index af7659e995..c00220ad3a 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -269,6 +269,7 @@ public: inline iterator &operator-=(difference_type j) { i-=j; return *this; } inline iterator operator+(difference_type j) const { return iterator(i+j); } inline iterator operator-(difference_type j) const { return iterator(i-j); } + friend inline iterator operator+(difference_type j, iterator k) { return k + j; } inline int operator-(iterator j) const { return int(i - j.i); } }; friend class iterator; @@ -312,6 +313,7 @@ public: inline const_iterator &operator-=(difference_type j) { i-=j; return *this; } inline const_iterator operator+(difference_type j) const { return const_iterator(i+j); } inline const_iterator operator-(difference_type j) const { return const_iterator(i-j); } + friend inline const_iterator operator+(difference_type j, const_iterator k) { return k + j; } inline int operator-(const_iterator j) const { return int(i - j.i); } }; friend class const_iterator; diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 09b148ea9e..9c1e78ee61 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -233,14 +233,6 @@ QLocaleId QLocaleId::withLikelySubtagsAdded() const if (addLikelySubtags(id)) return id; } - // language_script - if (country_id) { - QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0); - if (addLikelySubtags(id)) { - id.country_id = country_id; - return id; - } - } // language_region if (script_id) { QLocaleId id = QLocaleId::fromIds(language_id, 0, country_id); @@ -249,6 +241,14 @@ QLocaleId QLocaleId::withLikelySubtagsAdded() const return id; } } + // language_script + if (country_id) { + QLocaleId id = QLocaleId::fromIds(language_id, script_id, 0); + if (addLikelySubtags(id)) { + id.country_id = country_id; + return id; + } + } // language if (script_id && country_id) { QLocaleId id = QLocaleId::fromIds(language_id, 0, 0); @@ -258,6 +258,14 @@ QLocaleId QLocaleId::withLikelySubtagsAdded() const return id; } } + // und_script + if (language_id) { + QLocaleId id = QLocaleId::fromIds(0, script_id, 0); + if (addLikelySubtags(id)) { + id.language_id = language_id; + return id; + } + } return *this; } @@ -382,6 +390,13 @@ const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLoca QList<QLocaleId> tried; tried.push_back(likelyId); + // No match; try again with raw data: + if (!tried.contains(localeId)) { + if (const QLocaleData *const data = findLocaleDataById(localeId)) + return data; + tried.push_back(localeId); + } + // No match; try again with likely country if (country != QLocale::AnyCountry && (language != QLocale::AnyLanguage || script != QLocale::AnyScript)) { diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index a5b9096835..1cf9299e26 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -449,6 +449,7 @@ public: inline iterator operator-(int j) const { return operator+(-j); } inline iterator &operator+=(int j) { return *this = *this + j; } inline iterator &operator-=(int j) { return *this = *this - j; } + friend inline iterator operator+(int j, iterator k) { return k + j; } #ifndef QT_STRICT_ITERATORS public: @@ -512,6 +513,7 @@ public: inline const_iterator operator-(int j) const { return operator+(-j); } inline const_iterator &operator+=(int j) { return *this = *this + j; } inline const_iterator &operator-=(int j) { return *this = *this - j; } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } #ifdef QT_STRICT_ITERATORS private: diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index 96ddca56af..43e31ddb8e 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -3813,8 +3813,10 @@ struct QRegExpPrivate }; #if !defined(QT_NO_REGEXP_OPTIM) -typedef QCache<QRegExpEngineKey, QRegExpEngine> EngineCache; +typedef QHash<QRegExpEngineKey, QRegExpEngine *> EngineCache; Q_GLOBAL_STATIC(EngineCache, globalEngineCache) +typedef QCache<QRegExpEngineKey, QRegExpEngine> UnusedEngineCache; +Q_GLOBAL_STATIC(UnusedEngineCache, globalUnusedEngineCache) static QBasicMutex globalEngineCacheMutex; #endif // QT_NO_REGEXP_OPTIM @@ -3822,14 +3824,16 @@ static void derefEngine(QRegExpEngine *eng, const QRegExpEngineKey &key) { if (!eng->ref.deref()) { #if !defined(QT_NO_REGEXP_OPTIM) - if (globalEngineCache()) { + if (globalUnusedEngineCache()) { QMutexLocker locker(&globalEngineCacheMutex); QT_TRY { - globalEngineCache()->insert(key, eng, 4 + key.pattern.length() / 4); + globalUnusedEngineCache()->insert(key, eng, 4 + key.pattern.length() / 4); } QT_CATCH(const std::bad_alloc &) { // in case of an exception (e.g. oom), just delete the engine delete eng; } + if (globalEngineCache()) + globalEngineCache()->remove(key); } else { delete eng; } @@ -3844,9 +3848,11 @@ static void prepareEngine_helper(QRegExpPrivate *priv) { bool initMatchState = !priv->eng; #if !defined(QT_NO_REGEXP_OPTIM) - if (!priv->eng && globalEngineCache()) { + if (!priv->eng && globalUnusedEngineCache()) { QMutexLocker locker(&globalEngineCacheMutex); - priv->eng = globalEngineCache()->take(priv->engineKey); + priv->eng = globalUnusedEngineCache()->take(priv->engineKey); + if (!priv->eng && globalEngineCache()) + priv->eng = globalEngineCache()->value(priv->engineKey); if (priv->eng != 0) priv->eng->ref.ref(); } @@ -3854,6 +3860,10 @@ static void prepareEngine_helper(QRegExpPrivate *priv) if (!priv->eng) priv->eng = new QRegExpEngine(priv->engineKey); +#if !defined(QT_NO_REGEXP_OPTIM) + if (globalEngineCache()) + globalEngineCache()->insert(priv->engineKey, priv->eng); +#endif if (initMatchState) priv->matchState.prepareForMatch(priv->eng); diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 13eff07c04..29ad578013 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -798,6 +798,83 @@ Q_AUTOTEST_EXPORT unsigned int qt_qregularexpression_optimize_after_use_count = static const unsigned int qt_qregularexpression_optimize_after_use_count = 10; #endif // QT_BUILD_INTERNAL + +namespace QtPrivate { +/*! + internal +*/ +QString wildcardToRegularExpression(const QString &wildcardString) +{ + const int wclen = wildcardString.length(); + QString rx; + int i = 0; + bool hasNegativeBracket = false; + const QChar *wc = wildcardString.unicode(); + + while (i < wclen) { + const QChar c = wc[i++]; + switch (c.unicode()) { + case '*': + rx += QLatin1String(".*"); + break; + case '?': + rx += QLatin1Char('.'); + break; + case '$': + case '(': + case ')': + case '+': + case '.': + case '^': + case '{': + case '|': + case '}': + rx += QLatin1Char('\\'); + rx += c; + break; + case '[': + // Support for the [!abc] or [!a-c] syntax + // Implements a negative look-behind for one char. + if (wc[i] == QLatin1Char(']')) { + rx += c; + rx += wc[i++]; + } else if (wc[i] == QLatin1Char('!')) { + rx += QLatin1String(".(?<"); + rx += wc[i++]; + rx += c; + hasNegativeBracket = true; + } else { + rx += c; + } + + if (i < wclen) { + if (rx[i] == QLatin1Char(']')) + rx += wc[i++]; + while (i < wclen && wc[i] != QLatin1Char(']')) { + if (wc[i] == QLatin1Char('\\')) + rx += QLatin1Char('\\'); + rx += wc[i++]; + } + } + break; + case ']': + rx += c; + // Closes the negative look-behind expression. + if (hasNegativeBracket) { + rx += QLatin1Char(')'); + hasNegativeBracket = false; + } + break; + default: + rx += c; + break; + } + } + + return rx; +} +} + /*! \internal */ @@ -1554,6 +1631,47 @@ void QRegularExpression::setPattern(const QString &pattern) } /*! + \since 5.12 + + Sets the pattern string of the regular expression to \a wildcard pattern. + The pattern options are left unchanged. + + \warning Unlike QRegExp, this implementation follows closely the definition + of wildcard for glob patterns: + \table + \row \li \b{c} + \li Any character represents itself apart from those mentioned + below. Thus \b{c} matches the character \e c. + \row \li \b{?} + \li Matches any single character. It is the same as + \b{.} in full regexps. + \row \li \b{*} + \li Matches zero or more of any characters. It is the + same as \b{.*} in full regexps. + \row \li \b{[abc]} + \li Matches one character given in the bracket. + \row \li \b{[a-c]} + \li Matches one character from the range given in the bracket. + \row \li \b{[!abc]} + \li Matches one character that is not given in the bracket. + \row \li \b{[!a-c]} + \li matches one character that is not from the range given in the + bracket. + \endtable + + \note This function generates a regular expression that will act following + the wildcard pattern given. However the content of the regular expression + will not be the same as the one set. + + \sa pattern(), setPattern() +*/ +void QRegularExpression::setWildcardPattern(const QString &pattern) +{ + setPattern(QtPrivate::wildcardToRegularExpression(pattern)); +} + + +/*! Returns the pattern options for the regular expression. \sa setPatternOptions(), pattern() diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index 398fc9ec9c..f26f52d427 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -96,6 +96,7 @@ public: QString pattern() const; void setPattern(const QString &pattern); + void setWildcardPattern(const QString &pattern); bool isValid() const; int patternErrorOffset() const; diff --git a/src/corelib/tools/qregularexpression_p.h b/src/corelib/tools/qregularexpression_p.h new file mode 100644 index 0000000000..f5455de853 --- /dev/null +++ b/src/corelib/tools/qregularexpression_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Samuel Gaist <samuel.gaist@edeltech.ch> +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore 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 QREGULAREXPRESSION_P_H +#define QREGULAREXPRESSION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qglobal_p.h> + +#include <qregularexpression.h> +#include <qstring.h> + +QT_REQUIRE_CONFIG(regularexpression); + +QT_BEGIN_NAMESPACE + +namespace QtPrivate { +QString wildcardToRegularExpression(const QString &expression); +} + +QT_END_NAMESPACE + +#endif diff --git a/src/corelib/tools/qringbuffer.cpp b/src/corelib/tools/qringbuffer.cpp index eb7bdfe95c..59650ed2f7 100644 --- a/src/corelib/tools/qringbuffer.cpp +++ b/src/corelib/tools/qringbuffer.cpp @@ -312,12 +312,14 @@ qint64 QRingBuffer::peek(char *data, qint64 maxLength, qint64 pos) const Q_ASSERT(maxLength >= 0 && pos >= 0); qint64 readSoFar = 0; - for (int i = 0; readSoFar < maxLength && i < buffers.size(); ++i) { - qint64 blockLength = buffers[i].size(); + for (const QRingChunk &chunk : buffers) { + if (readSoFar == maxLength) + break; + qint64 blockLength = chunk.size(); if (pos < blockLength) { blockLength = qMin(blockLength - pos, maxLength - readSoFar); - memcpy(data + readSoFar, buffers[i].data() + pos, blockLength); + memcpy(data + readSoFar, chunk.data() + pos, blockLength); readSoFar += blockLength; pos = 0; } else { diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 7ded120ab7..6640c8486d 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -131,6 +131,7 @@ public: inline iterator operator--(int) { iterator r = *this; --i; return r; } inline iterator operator+(int j) const { return i + j; } inline iterator operator-(int j) const { return i - j; } + friend inline iterator operator+(int j, iterator k) { return k + j; } inline iterator &operator+=(int j) { i += j; return *this; } inline iterator &operator-=(int j) { i -= j; return *this; } }; @@ -165,6 +166,7 @@ public: inline const_iterator operator--(int) { const_iterator r = *this; --i; return r; } inline const_iterator operator+(int j) const { return i + j; } inline const_iterator operator-(int j) const { return i - j; } + friend inline const_iterator operator+(int j, const_iterator k) { return k + j; } inline const_iterator &operator+=(int j) { i += j; return *this; } inline const_iterator &operator-=(int j) { i -= j; return *this; } }; diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 780f2331a8..3ef134a99d 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -136,6 +136,18 @@ private: T *d; }; +template <class T> inline bool operator==(std::nullptr_t p1, const QSharedDataPointer<T> &p2) +{ + Q_UNUSED(p1); + return !p2; +} + +template <class T> inline bool operator==(const QSharedDataPointer<T> &p1, std::nullptr_t p2) +{ + Q_UNUSED(p2); + return !p1; +} + template <class T> class QExplicitlySharedDataPointer { public: @@ -271,6 +283,18 @@ Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer( : d(adata) { if (d) d->ref.ref(); } +template <class T> inline bool operator==(std::nullptr_t p1, const QExplicitlySharedDataPointer<T> &p2) +{ + Q_UNUSED(p1); + return !p2; +} + +template <class T> inline bool operator==(const QExplicitlySharedDataPointer<T> &p1, std::nullptr_t p2) +{ + Q_UNUSED(p2); + return !p1; +} + template <class T> Q_INLINE_TEMPLATE void qSwap(QSharedDataPointer<T> &p1, QSharedDataPointer<T> &p2) { p1.swap(p2); } diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index f6360f5504..46ec8b072c 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -4883,6 +4883,50 @@ bool QString::endsWith(QChar c, Qt::CaseSensitivity cs) const return qt_ends_with(*this, c, cs); } +/*! + Returns \c true if the string only contains uppercase letters, + otherwise returns \c false. + \since 5.12 + + \sa QChar::isUpper(), isLower() +*/ +bool QString::isUpper() const +{ + if (isEmpty()) + return false; + + const QChar *d = data(); + + for (int i = 0, max = size(); i < max; ++i) { + if (!d[i].isUpper()) + return false; + } + + return true; +} + +/*! + Returns \c true if the string only contains lowercase letters, + otherwise returns \c false. + \since 5.12 + + \sa QChar::isLower(), isUpper() + */ +bool QString::isLower() const +{ + if (isEmpty()) + return false; + + const QChar *d = data(); + + for (int i = 0, max = size(); i < max; ++i) { + if (!d[i].isLower()) + return false; + } + + return true; +} + static QByteArray qt_convert_to_latin1(QStringView string); QByteArray QString::toLatin1_helper(const QString &string) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index f27f7efa2b..447f000486 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -409,6 +409,9 @@ public: bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool isUpper() const; + bool isLower() const; + Q_REQUIRED_RESULT QString leftJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const; Q_REQUIRED_RESULT QString rightJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const; diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index daa7dc1531..db6be581ec 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -66,11 +66,10 @@ static QTimeZonePrivate *newBackendTimeZone() return new QAndroidTimeZonePrivate(); #elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED) return new QTzTimeZonePrivate(); - // Registry based timezone backend not available on WinRT -#elif defined Q_OS_WIN - return new QWinTimeZonePrivate(); #elif QT_CONFIG(icu) return new QIcuTimeZonePrivate(); +#elif defined Q_OS_WIN + return new QWinTimeZonePrivate(); #else return new QUtcTimeZonePrivate(); #endif // System Locales @@ -93,11 +92,10 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId) return new QAndroidTimeZonePrivate(ianaId); #elif defined(Q_OS_UNIX) || defined(Q_OS_ANDROID_EMBEDDED) return new QTzTimeZonePrivate(ianaId); - // Registry based timezone backend not available on WinRT -#elif defined Q_OS_WIN - return new QWinTimeZonePrivate(ianaId); #elif QT_CONFIG(icu) return new QIcuTimeZonePrivate(ianaId); +#elif defined Q_OS_WIN + return new QWinTimeZonePrivate(ianaId); #else return new QUtcTimeZonePrivate(ianaId); #endif // System Locales @@ -822,8 +820,8 @@ bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId) // IDs as availableTimeZoneIds() may be slow if (!QTimeZonePrivate::isValidId(ianaId)) return false; - const QList<QByteArray> tzIds = availableTimeZoneIds(); - return std::binary_search(tzIds.begin(), tzIds.end(), ianaId); + return QUtcTimeZonePrivate().isTimeZoneIdAvailable(ianaId) || + global_tz->backend->isTimeZoneIdAvailable(ianaId); } static QList<QByteArray> set_union(const QList<QByteArray> &l1, const QList<QByteArray> &l2) diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp index 1a5135f103..2b6c2ea6a5 100644 --- a/src/corelib/tools/qtimezoneprivate.cpp +++ b/src/corelib/tools/qtimezoneprivate.cpp @@ -486,6 +486,13 @@ QByteArray QTimeZonePrivate::systemTimeZoneId() const return QByteArray(); } +bool QTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray& ianaId) const +{ + // Fall-back implementation, can be made faster in subclasses + const QList<QByteArray> tzIds = availableTimeZoneIds(); + return std::binary_search(tzIds.begin(), tzIds.end(), ianaId); +} + QList<QByteArray> QTimeZonePrivate::availableTimeZoneIds() const { return QList<QByteArray>(); @@ -864,6 +871,17 @@ QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const return utcQByteArray(); } +bool QUtcTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const +{ + for (int i = 0; i < utcDataTableSize; ++i) { + const QUtcData *data = utcData(i); + if (utcId(data) == ianaId) { + return true; + } + } + return false; +} + QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds() const { QList<QByteArray> result; diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/tools/qtimezoneprivate_p.h index 4d357111f2..c9a5726216 100644 --- a/src/corelib/tools/qtimezoneprivate_p.h +++ b/src/corelib/tools/qtimezoneprivate_p.h @@ -128,6 +128,7 @@ public: virtual QByteArray systemTimeZoneId() const; + virtual bool isTimeZoneIdAvailable(const QByteArray &ianaId) const; virtual QList<QByteArray> availableTimeZoneIds() const; virtual QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const; virtual QList<QByteArray> availableTimeZoneIds(int utcOffset) const; @@ -204,6 +205,7 @@ public: QByteArray systemTimeZoneId() const override; + bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override; QList<QByteArray> availableTimeZoneIds() const override; QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override; QList<QByteArray> availableTimeZoneIds(int utcOffset) const override; @@ -323,6 +325,7 @@ public: QByteArray systemTimeZoneId() const override; + bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override; QList<QByteArray> availableTimeZoneIds() const override; QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override; diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index 6a5df6272a..f1735a80e7 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -1098,6 +1098,11 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const return ianaId; } +bool QTzTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const +{ + return tzZones->contains(ianaId); +} + QList<QByteArray> QTzTimeZonePrivate::availableTimeZoneIds() const { QList<QByteArray> result = tzZones->keys(); diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp index 8bde07c710..ec91b7e8a8 100644 --- a/src/corelib/tools/qtimezoneprivate_win.cpp +++ b/src/corelib/tools/qtimezoneprivate_win.cpp @@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE #ifndef Q_OS_WINRT +// The registry-based timezone backend is not available on WinRT, which falls back to equivalent APIs. #define QT_USE_REGISTRY_TIMEZONE 1 #endif diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 72224f280d..30f7edb5f2 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -159,16 +159,18 @@ qtConfig(timezone) { SOURCES += \ tools/qtimezone.cpp \ tools/qtimezoneprivate.cpp - !nacl:darwin: \ + !nacl:darwin: { SOURCES += tools/qtimezoneprivate_mac.mm - else: android:!android-embedded: \ + } else: android:!android-embedded: { SOURCES += tools/qtimezoneprivate_android.cpp - else: unix: \ + } else: unix: { SOURCES += tools/qtimezoneprivate_tz.cpp - else: win32: \ - SOURCES += tools/qtimezoneprivate_win.cpp - qtConfig(icu): \ + qtConfig(icu): SOURCES += tools/qtimezoneprivate_icu.cpp + } else: qtConfig(icu): { SOURCES += tools/qtimezoneprivate_icu.cpp + } else: win32: { + SOURCES += tools/qtimezoneprivate_win.cpp + } } qtConfig(datetimeparser) { @@ -179,7 +181,9 @@ qtConfig(datetimeparser) { qtConfig(regularexpression) { QMAKE_USE_PRIVATE += pcre2 - HEADERS += tools/qregularexpression.h + HEADERS += \ + tools/qregularexpression.h \ + tools/qregularexpression_p.h SOURCES += tools/qregularexpression.cpp } |