summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro12
-rw-r--r--src/corelib/global/global.pri6
-rw-r--r--src/corelib/global/qglobal.cpp304
-rw-r--r--src/corelib/global/qoperatingsystemversion.cpp394
-rw-r--r--src/corelib/global/qoperatingsystemversion.h125
-rw-r--r--src/corelib/global/qoperatingsystemversion_darwin.mm101
-rw-r--r--src/corelib/global/qoperatingsystemversion_p.h71
-rw-r--r--src/corelib/global/qoperatingsystemversion_win.cpp171
-rw-r--r--src/corelib/global/qsysinfo.h34
-rw-r--r--src/corelib/io/qdatastream.h281
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp4
-rw-r--r--src/corelib/io/qfilesystemiterator_win.cpp3
-rw-r--r--src/corelib/io/qsettings.cpp250
-rw-r--r--src/corelib/io/qsettings_mac.cpp13
-rw-r--r--src/corelib/io/qsettings_p.h18
-rw-r--r--src/corelib/io/qstorageinfo.cpp22
-rw-r--r--src/corelib/io/qstorageinfo.h3
-rw-r--r--src/corelib/io/qstorageinfo_p.h1
-rw-r--r--src/corelib/io/qstorageinfo_unix.cpp51
-rw-r--r--src/corelib/io/qtemporarydir.cpp27
-rw-r--r--src/corelib/io/qtemporarydir.h1
-rw-r--r--src/corelib/io/qtextstream.cpp15
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm54
-rw-r--r--src/corelib/kernel/qcore_mac_p.h6
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp3
-rw-r--r--src/corelib/kernel/qobject.cpp15
-rw-r--r--src/corelib/tools/qarraydata.cpp51
-rw-r--r--src/corelib/tools/qarraydata.h11
-rw-r--r--src/corelib/tools/qbytearray.cpp86
-rw-r--r--src/corelib/tools/qdatetime.cpp9
-rw-r--r--src/corelib/tools/qlocale.cpp66
-rw-r--r--src/corelib/tools/qlocale.h4
-rw-r--r--src/corelib/tools/qlocale.qdoc11
-rw-r--r--src/corelib/tools/qlocale_p.h4
-rw-r--r--src/corelib/tools/qstring.cpp30
-rw-r--r--src/gui/image/qicon.cpp42
-rw-r--r--src/gui/image/qicon_p.h2
-rw-r--r--src/gui/opengl/qopengl.cpp21
-rw-r--r--src/gui/opengl/qopenglshaderprogram.cpp221
-rw-r--r--src/gui/painting/qcoregraphics.mm3
-rw-r--r--src/gui/util/qdesktopservices.cpp9
-rw-r--r--src/network/access/qhttpnetworkreply.cpp8
-rw-r--r--src/network/access/qhttpnetworkreply_p.h2
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp3
-rw-r--r--src/network/access/qhttpthreaddelegate_p.h3
-rw-r--r--src/network/access/qnetworkaccessbackend_p.h1
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp13
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h4
-rw-r--r--src/network/access/qnetworkrequest.cpp7
-rw-r--r--src/network/access/qnetworkrequest.h1
-rw-r--r--src/network/kernel/kernel.pri3
-rw-r--r--src/network/ssl/qsslsocket_winrt.cpp8
-rw-r--r--src/platformsupport/fontdatabases/fontdatabases.pri2
-rw-r--r--src/platformsupport/fontdatabases/mac/coretext.pri10
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm4
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm8
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm3
-rw-r--r--src/plugins/platforms/ios/qiosmessagedialog.mm3
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm7
-rw-r--r--src/plugins/platforms/ios/qiostextinputoverlay.mm4
-rw-r--r--src/plugins/platforms/ios/quiview.mm3
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp17
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp27
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp45
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h2
-rw-r--r--src/testlib/qtestcase.cpp37
-rw-r--r--src/tools/bootstrap/bootstrap.pro5
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.cpp24
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.h4
-rw-r--r--src/widgets/accessible/simplewidgets.cpp12
-rw-r--r--src/widgets/dialogs/qwizard_win.cpp3
-rw-r--r--src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp10
-rw-r--r--src/widgets/kernel/qapplication_p.h6
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm24
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp3
-rw-r--r--src/widgets/util/qsystemtrayicon.cpp117
-rw-r--r--src/widgets/util/qsystemtrayicon.h1
-rw-r--r--src/widgets/util/qsystemtrayicon_p.h19
-rw-r--r--src/widgets/util/qsystemtrayicon_qpa.cpp17
-rw-r--r--src/widgets/util/qsystemtrayicon_win.cpp57
-rw-r--r--src/widgets/util/qsystemtrayicon_x11.cpp17
84 files changed, 2056 insertions, 1051 deletions
diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
index 1bfeabb8c4..5ec86bf78f 100644
--- a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
+++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
@@ -11,7 +11,7 @@ load(qt_helper_lib)
SHAPERS += opentype # HB's main shaper; enabling it should be enough most of the time
# native shaper on Apple platforms; could be used alone to handle both OT and AAT fonts
-darwin:!if(watchos:CONFIG(simulator, simulator|device)): SHAPERS += coretext
+darwin: SHAPERS += coretext
DEFINES += HAVE_CONFIG_H
DEFINES += HB_NO_UNICODE_FUNCS HB_DISABLE_DEPRECATED
@@ -155,4 +155,14 @@ contains(SHAPERS, coretext) {
# On Mac OS they are part of the ApplicationServices umbrella framework,
# even in 10.8 where they were also made available stand-alone.
LIBS_PRIVATE += -framework ApplicationServices
+
+ # CoreText is documented to be available on watchOS, but the headers aren't present
+ # in the watchOS Simulator SDK like they are supposed to be. Work around the problem
+ # by adding the device SDK's headers to the search path as a fallback.
+ # rdar://25314492, rdar://27844864
+ watchos:CONFIG(simulator, simulator|device) {
+ QMAKE_CXXFLAGS += \
+ -F$$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks \
+ -F$$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks
+ }
}
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index 6a8948822c..afcd20a9c1 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -2,6 +2,8 @@
HEADERS += \
global/qglobal.h \
+ global/qoperatingsystemversion.h \
+ global/qoperatingsystemversion_p.h \
global/qsystemdetection.h \
global/qcompilerdetection.h \
global/qprocessordetection.h \
@@ -27,11 +29,15 @@ SOURCES += \
global/qlibraryinfo.cpp \
global/qmalloc.cpp \
global/qnumeric.cpp \
+ global/qoperatingsystemversion.cpp \
global/qlogging.cpp \
global/qhooks.cpp
VERSIONTAGGING_SOURCES = global/qversiontagging.cpp
+darwin: SOURCES += global/qoperatingsystemversion_darwin.mm
+win32: SOURCES += global/qoperatingsystemversion_win.cpp
+
# qlibraryinfo.cpp includes qconfig.cpp
INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 743d9d14a5..c78e6f2482 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -45,6 +45,8 @@
#include "qthreadstorage.h"
#include "qdir.h"
#include "qdatetime.h"
+#include "qoperatingsystemversion.h"
+#include "qoperatingsystemversion_p.h"
#include <private/qlocale_tools_p.h>
#include <qmutex.h>
@@ -1088,12 +1090,14 @@ bool qSharedBuild() Q_DECL_NOTHROW
*/
/*!
+ \deprecated
\variable QSysInfo::WindowsVersion
\brief the version of the Windows operating system on which the
application is run.
*/
/*!
+ \deprecated
\fn QSysInfo::WindowsVersion QSysInfo::windowsVersion()
\since 4.4
@@ -1103,12 +1107,14 @@ bool qSharedBuild() Q_DECL_NOTHROW
*/
/*!
+ \deprecated
\variable QSysInfo::MacintoshVersion
\brief the version of the Macintosh operating system on which
the application is run.
*/
/*!
+ \deprecated
\fn QSysInfo::MacVersion QSysInfo::macVersion()
Returns the version of Darwin (\macos or iOS) on which the
@@ -1126,6 +1132,7 @@ bool qSharedBuild() Q_DECL_NOTHROW
*/
/*!
+ \deprecated
\enum QSysInfo::WinVersion
This enum provides symbolic names for the various versions of the
@@ -1182,6 +1189,7 @@ bool qSharedBuild() Q_DECL_NOTHROW
*/
/*!
+ \deprecated
\enum QSysInfo::MacVersion
This enum provides symbolic names for the various versions of the
@@ -1943,28 +1951,31 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qnamespace.h"
QT_END_INCLUDE_NAMESPACE
+#if QT_DEPRECATED_SINCE(5, 9)
QSysInfo::MacVersion QSysInfo::macVersion()
{
- const QAppleOperatingSystemVersion version = qt_apple_os_version(); // qtcore_mac_objc.mm
+ const auto version = QOperatingSystemVersion::current();
#if defined(Q_OS_OSX)
- return QSysInfo::MacVersion(Q_MV_OSX(version.major, version.minor));
+ return QSysInfo::MacVersion(Q_MV_OSX(version.majorVersion(), version.minorVersion()));
#elif defined(Q_OS_IOS)
- return QSysInfo::MacVersion(Q_MV_IOS(version.major, version.minor));
+ return QSysInfo::MacVersion(Q_MV_IOS(version.majorVersion(), version.minorVersion()));
#elif defined(Q_OS_TVOS)
- return QSysInfo::MacVersion(Q_MV_TVOS(version.major, version.minor));
+ return QSysInfo::MacVersion(Q_MV_TVOS(version.majorVersion(), version.minorVersion()));
#elif defined(Q_OS_WATCHOS)
- return QSysInfo::MacVersion(Q_MV_WATCHOS(version.major, version.minor));
+ return QSysInfo::MacVersion(Q_MV_WATCHOS(version.majorVersion(), version.minorVersion()));
#else
return QSysInfo::MV_Unknown;
#endif
}
const QSysInfo::MacVersion QSysInfo::MacintoshVersion = QSysInfo::macVersion();
+#endif
-#ifdef Q_OS_OSX
-static const char *osxVer_helper(QAppleOperatingSystemVersion version = qt_apple_os_version())
+#ifdef Q_OS_DARWIN
+static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
{
- if (version.major == 10) {
- switch (version.minor) {
+#ifdef Q_OS_MACOS
+ if (version.majorVersion() == 10) {
+ switch (version.minorVersion()) {
case 9:
return "Mavericks";
case 10:
@@ -1976,6 +1987,9 @@ static const char *osxVer_helper(QAppleOperatingSystemVersion version = qt_apple
}
}
// unknown, future version
+#else
+ Q_UNUSED(version);
+#endif
return 0;
}
#endif
@@ -2016,140 +2030,30 @@ QWindowsSockInit::~QWindowsSockInit()
Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit)
# endif // QT_BOOTSTRAPPED
-#ifdef Q_OS_WINRT
-static inline HMODULE moduleHandleForFunction(LPCVOID address)
-{
- // This is a widely used, decades-old technique for retrieving the handle
- // of a module and is effectively equivalent to GetModuleHandleEx
- // (which is unavailable on WinRT)
- MEMORY_BASIC_INFORMATION mbi = { 0, 0, 0, 0, 0, 0, 0 };
- if (VirtualQuery(address, &mbi, sizeof(mbi)) == 0)
- return 0;
- return reinterpret_cast<HMODULE>(mbi.AllocationBase);
-}
-#endif
-
-static inline OSVERSIONINFOEX determineWinOsVersion()
-{
- OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0};
-
-#define GetProcAddressA GetProcAddress
-
- // GetModuleHandle is not supported in WinRT and linking to it at load time
- // will not pass the Windows App Certification Kit... but it exists and is functional,
- // so use some unusual but widely used techniques to get a pointer to it
-#ifdef Q_OS_WINRT
- // 1. Get HMODULE of kernel32.dll, using the address of some function exported by that DLL
- HMODULE kernelModule = moduleHandleForFunction(reinterpret_cast<LPCVOID>(VirtualQuery));
- if (Q_UNLIKELY(!kernelModule))
- return result;
-
- // 2. Get pointer to GetModuleHandle so we can then load other arbitrary modules (DLLs)
- typedef HMODULE(WINAPI *GetModuleHandleFunction)(LPCWSTR);
- GetModuleHandleFunction pGetModuleHandle = reinterpret_cast<GetModuleHandleFunction>(
- GetProcAddressA(kernelModule, "GetModuleHandleW"));
- if (Q_UNLIKELY(!pGetModuleHandle))
- return result;
-#else
-#define pGetModuleHandle GetModuleHandleW
-#endif
-
-#ifndef Q_OS_WINCE
- HMODULE ntdll = pGetModuleHandle(L"ntdll.dll");
- if (Q_UNLIKELY(!ntdll))
- return result;
-
- // NTSTATUS is not defined on WinRT
- typedef LONG NTSTATUS;
- typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO);
-
- // RtlGetVersion is documented public API but we must load it dynamically
- // because linking to it at load time will not pass the Windows App Certification Kit
- // https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx
- RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(
- GetProcAddressA(ntdll, "RtlGetVersion"));
- if (Q_UNLIKELY(!pRtlGetVersion))
- return result;
-
- // GetVersionEx() has been deprecated in Windows 8.1 and will return
- // only Windows 8 from that version on, so use the kernel API function.
- pRtlGetVersion((LPOSVERSIONINFO) &result); // always returns STATUS_SUCCESS
-#else // !Q_OS_WINCE
- GetVersionEx(&result);
-#endif
- return result;
-}
-
-static OSVERSIONINFOEX winOsVersion()
-{
- OSVERSIONINFOEX realResult = determineWinOsVersion();
-#ifdef QT_DEBUG
- {
- if (Q_UNLIKELY(qEnvironmentVariableIsSet("QT_WINVER_OVERRIDE"))) {
- OSVERSIONINFOEX result = realResult;
- result.dwMajorVersion = 0;
- result.dwMinorVersion = 0;
-
- // Erase any build number and service pack information
- result.dwBuildNumber = 0;
- result.szCSDVersion[0] = L'\0';
- result.wServicePackMajor = 0;
- result.wServicePackMinor = 0;
-
- const QByteArray winVerOverride = qgetenv("QT_WINVER_OVERRIDE");
- if (winVerOverride == "WINDOWS7" || winVerOverride == "2008_R2") {
- result.dwMajorVersion = 6;
- result.dwMinorVersion = 1;
- } else if (winVerOverride == "WINDOWS8" || winVerOverride == "2012") {
- result.dwMajorVersion = 6;
- result.dwMinorVersion = 2;
- } else if (winVerOverride == "WINDOWS8_1" || winVerOverride == "2012_R2") {
- result.dwMajorVersion = 6;
- result.dwMinorVersion = 3;
- } else if (winVerOverride == "WINDOWS10" || winVerOverride == "2016") {
- result.dwMajorVersion = 10;
- } else {
- return realResult;
- }
-
- if (winVerOverride == "2008_R2"
- || winVerOverride == "2012"
- || winVerOverride == "2012_R2"
- || winVerOverride == "2016") {
- // If the current host OS is a domain controller and the override OS
- // is also a server type OS, preserve that information
- if (result.wProductType == VER_NT_WORKSTATION)
- result.wProductType = VER_NT_SERVER;
- } else {
- // Any other OS must be a workstation OS type
- result.wProductType = VER_NT_WORKSTATION;
- }
- }
- }
-#endif
- return realResult;
-}
-
+#if QT_DEPRECATED_SINCE(5, 9)
QSysInfo::WinVersion QSysInfo::windowsVersion()
{
- const OSVERSIONINFOEX osver = winOsVersion();
- if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1)
+ const auto version = QOperatingSystemVersion::current();
+ if (version.majorVersion() == 6 && version.minorVersion() == 1)
return QSysInfo::WV_WINDOWS7;
- if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2)
+ if (version.majorVersion() == 6 && version.minorVersion() == 2)
return QSysInfo::WV_WINDOWS8;
- if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3)
+ if (version.majorVersion() == 6 && version.minorVersion() == 3)
return QSysInfo::WV_WINDOWS8_1;
- if (osver.dwMajorVersion == 10 && osver.dwMinorVersion == 0)
+ if (version.majorVersion() == 10 && version.minorVersion() == 0)
return QSysInfo::WV_WINDOWS10;
return QSysInfo::WV_NT_based;
}
+const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion();
+#endif
static QString winSp_helper()
{
- const qint16 major = winOsVersion().wServicePackMajor;
+ const auto osv = qWindowsVersionInfo();
+ const qint16 major = osv.wServicePackMajor;
if (major) {
QString sp = QStringLiteral(" SP ") + QString::number(major);
- const qint16 minor = winOsVersion().wServicePackMinor;
+ const qint16 minor = osv.wServicePackMinor;
if (minor)
sp += QLatin1Char('.') + QString::number(minor);
@@ -2158,9 +2062,10 @@ static QString winSp_helper()
return QString();
}
-static const char *winVer_helper()
+static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current())
{
- const OSVERSIONINFOEX osver = winOsVersion();
+ Q_UNUSED(version);
+ const OSVERSIONINFOEX osver = qWindowsVersionInfo();
const bool workstation = osver.wProductType == VER_NT_WORKSTATION;
#define Q_WINVER(major, minor) (major << 8 | minor)
@@ -2179,8 +2084,6 @@ static const char *winVer_helper()
return 0;
}
-const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion();
-
#endif
#if defined(Q_OS_UNIX)
# if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
@@ -2361,6 +2264,67 @@ static bool findUnixOsVersion(QUnixOSVersion &v)
# endif // USE_ETC_OS_RELEASE
#endif // Q_OS_UNIX
+#ifdef Q_OS_ANDROID
+static const char *osVer_helper(QOperatingSystemVersion)
+{
+/* Data:
+
+
+
+Cupcake
+Donut
+Eclair
+Eclair
+Eclair
+Froyo
+Gingerbread
+Gingerbread
+Honeycomb
+Honeycomb
+Honeycomb
+Ice Cream Sandwich
+Ice Cream Sandwich
+Jelly Bean
+Jelly Bean
+Jelly Bean
+KitKat
+KitKat
+Lollipop
+Lollipop
+Marshmallow
+Nougat
+ */
+ static const char versions_string[] =
+ "\0"
+ "Cupcake\0"
+ "Donut\0"
+ "Eclair\0"
+ "Froyo\0"
+ "Gingerbread\0"
+ "Honeycomb\0"
+ "Ice Cream Sandwich\0"
+ "Jelly Bean\0"
+ "KitKat\0"
+ "Lollipop\0"
+ "Marshmallow\0"
+ "Nougat\0"
+ "\0";
+
+ static const int versions_indices[] = {
+ 0, 0, 0, 1, 9, 15, 15, 15,
+ 22, 28, 28, 40, 40, 40, 50, 50,
+ 69, 69, 69, 80, 80, 87, 87, 96,
+ 108, -1
+ };
+
+ static const int versions_count = (sizeof versions_indices) / (sizeof versions_indices[0]);
+
+ // https://source.android.com/source/build-numbers.html
+ // https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels
+ const int sdk_int = QJNIObjectPrivate::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT");
+ return &versions_string[versions_indices[qBound(0, sdk_int, versions_count - 1)]];
+}
+#endif
/*!
\since 5.4
@@ -2609,9 +2573,9 @@ QString QSysInfo::kernelType()
QString QSysInfo::kernelVersion()
{
#ifdef Q_OS_WIN
- const OSVERSIONINFOEX osver = winOsVersion();
- return QString::number(int(osver.dwMajorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwMinorVersion))
- + QLatin1Char('.') + QString::number(int(osver.dwBuildNumber));
+ const auto osver = QOperatingSystemVersion::current();
+ return QString::number(osver.majorVersion()) + QLatin1Char('.') + QString::number(osver.minorVersion())
+ + QLatin1Char('.') + QString::number(osver.microVersion());
#else
struct utsname u;
if (uname(&u) == 0)
@@ -2679,8 +2643,8 @@ QString QSysInfo::productType()
#elif defined(Q_OS_WATCHOS)
return QStringLiteral("watchos");
#elif defined(Q_OS_MACOS)
- const QAppleOperatingSystemVersion version = qt_apple_os_version();
- if (version.major == 10 && version.minor < 12)
+ const auto version = QOperatingSystemVersion::current();
+ if (version.majorVersion() == 10 && version.minorVersion() < 12)
return QStringLiteral("osx");
return QStringLiteral("macos");
#elif defined(Q_OS_DARWIN)
@@ -2720,20 +2684,17 @@ QString QSysInfo::productType()
*/
QString QSysInfo::productVersion()
{
-#if defined(Q_OS_MAC)
- const QAppleOperatingSystemVersion version = qt_apple_os_version();
- return QString::number(version.major) + QLatin1Char('.') + QString::number(version.minor);
+#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN)
+ const auto version = QOperatingSystemVersion::current();
+ return QString::number(version.majorVersion()) + QLatin1Char('.') + QString::number(version.minorVersion());
#elif defined(Q_OS_WIN)
- const char *version = winVer_helper();
+ const char *version = osVer_helper();
if (version) {
const QLatin1Char spaceChar(' ');
return QString::fromLatin1(version).remove(spaceChar).toLower() + winSp_helper().remove(spaceChar).toLower();
}
// fall through
-// Android should not fall through to the Unix code
-#elif defined(Q_OS_ANDROID)
- return QJNIObjectPrivate::getStaticObjectField("android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString();
#elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX
QUnixOSVersion unixOsVersion;
findUnixOsVersion(unixOsVersion);
@@ -2761,44 +2722,23 @@ QString QSysInfo::productVersion()
*/
QString QSysInfo::prettyProductName()
{
-#if defined(Q_OS_IOS)
- return QLatin1String("iOS ") + productVersion();
-#elif defined(Q_OS_TVOS)
- return QLatin1String("tvOS ") + productVersion();
-#elif defined(Q_OS_WATCHOS)
- return QLatin1String("watchOS ") + productVersion();
-#elif defined(Q_OS_MACOS)
- const QAppleOperatingSystemVersion version = qt_apple_os_version();
- const char *name = osxVer_helper(version);
- if (name) {
- return (version.major == 10 && version.minor < 12
- ? QLatin1String("OS X ")
- : QLatin1String("macOS "))
- + QLatin1String(name)
- + QLatin1String(" (") + QString::number(version.major)
- + QLatin1Char('.') + QString::number(version.minor)
- + QLatin1Char(')');
- } else {
- return QLatin1String("macOS ")
- + QString::number(version.major) + QLatin1Char('.')
- + QString::number(version.minor);
- }
-#elif defined(Q_OS_WINPHONE)
- return QLatin1String("Windows Phone ") + QLatin1String(winVer_helper());
-#elif defined(Q_OS_WIN)
- const char *name = winVer_helper();
- const OSVERSIONINFOEX osver = winOsVersion();
+#if defined(Q_OS_WINPHONE)
+ return QLatin1String("Windows Phone ") + QLatin1String(osVer_helper());
+#elif defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN)
+ const auto version = QOperatingSystemVersion::current();
+ const char *name = osVer_helper(version);
if (name)
- return QLatin1String("Windows ") + QLatin1String(name) + winSp_helper()
- + QLatin1String(" (") + QString::number(osver.dwMajorVersion)
- + QLatin1Char('.') + QString::number(osver.dwMinorVersion)
+ return version.name() + QLatin1Char(' ') + QLatin1String(name)
+# if defined(Q_OS_WIN)
+ + winSp_helper()
+# endif
+ + QLatin1String(" (") + QString::number(version.majorVersion())
+ + QLatin1Char('.') + QString::number(version.minorVersion())
+ QLatin1Char(')');
- else
- return QLatin1String("Windows ")
- + QString::number(osver.dwMajorVersion) + QLatin1Char('.')
- + QString::number(osver.dwMinorVersion);
-#elif defined(Q_OS_ANDROID)
- return QLatin1String("Android ") + productVersion();
+ else
+ return version.name() + QLatin1Char(' ')
+ + QString::number(version.majorVersion()) + QLatin1Char('.')
+ + QString::number(version.minorVersion());
#elif defined(Q_OS_HAIKU)
return QLatin1String("Haiku ") + productVersion();
#elif defined(Q_OS_UNIX)
diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp
new file mode 100644
index 0000000000..14dc109b3e
--- /dev/null
+++ b/src/corelib/global/qoperatingsystemversion.cpp
@@ -0,0 +1,394 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "qoperatingsystemversion.h"
+#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
+#include "qoperatingsystemversion_p.h"
+#endif
+
+#include <qversionnumber.h>
+
+#if defined(Q_OS_ANDROID)
+#include <private/qjni_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QOperatingSystemVersion
+ \inmodule QtCore
+ \since 5.9
+ \brief The QOperatingSystemVersion class provides information about the operating system version.
+
+ Unlike other version functions in QSysInfo, QOperatingSystemVersion provides access to the full
+ version number that \a developers typically use to vary behavior or determine whether to enable
+ APIs or features based on the operating system version (as opposed to the kernel version number
+ or marketing version).
+
+ This class is also a complete replacement for QSysInfo::macVersion and QSysInfo::windowsVersion,
+ additionally providing access to the third (micro) version number component.
+
+ Presently, Android, Apple Platforms (iOS, macOS, tvOS, and watchOS), and Windows are supported.
+
+ The \a majorVersion(), \a minorVersion(), and \a microVersion() functions return the parts of
+ the operating system version number based on:
+
+ \table
+ \header \li Platforms \li Value
+ \row \li Android \li result of parsing
+ \l{https://developer.android.com/reference/android/os/Build.VERSION.html#RELEASE}{"android.os.Build.VERSION.RELEASE"}
+ using QVersionNumber, with a fallback to
+ \l{https://developer.android.com/reference/android/os/Build.VERSION.html#SDK_INT}{"android.os.Build.VERSION.SDK_INT"}
+ to determine the major and minor version component if the former fails
+ \row \li Apple Platforms \li majorVersion, minorVersion, and patchVersion from
+ \l{https://developer.apple.com/reference/foundation/nsprocessinfo/1410906-operatingsystemversion?language=objc}{"NSProcessInfo.operatingSystemVersion"}
+ \row \li Windows \li dwMajorVersion, dwMinorVersion, and dwBuildNumber from
+ \l{https://msdn.microsoft.com/en-us/library/mt723418.aspx}{"RtlGetVersion"} -
+ note that this function ALWAYS return the version number of the underlying operating system,
+ as opposed to the shim underneath GetVersionEx that hides the real version number
+ if the application is not manifested for that version of the OS
+ \endtable
+*/
+
+/*!
+ \fn QOperatingSystemVersion::QOperatingSystemVersion(int maj, int min, int mic)
+
+ Constructs a QOperatingSystemVersion consisting of the OS type \a os, and
+ major, minor, and micro version numbers \a maj, \a min and \a mic, respectively.
+*/
+
+/*!
+ \fn QOperatingSystemVersion QOperatingSystemVersion::current()
+
+ Returns a QOperatingSystemVersion indicating the current OS and its version number.
+*/
+#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
+QOperatingSystemVersion QOperatingSystemVersion::current()
+{
+ QOperatingSystemVersion version;
+ version.m_os = currentType();
+#if defined(Q_OS_ANDROID)
+#ifndef QT_BOOTSTRAPPED
+ const QVersionNumber v = QVersionNumber::fromString(QJNIObjectPrivate::getStaticObjectField(
+ "android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString());
+ if (!v.isNull()) {
+ version.m_major = v.majorVersion();
+ version.m_minor = v.minorVersion();
+ version.m_micro = v.microVersion();
+ return version;
+ }
+#endif
+
+ version.m_major = -1;
+ version.m_minor = -1;
+
+ static const int versions[][2] = {
+ { 1, 0 }, // API level 1
+ { 1, 1 }, // API level 2
+ { 1, 5 }, // API level 3
+ { 1, 6 }, // API level 4
+ { 2, 0 }, // API level 5
+ { 2, 0 }, // API level 6
+ { 2, 1 }, // API level 7
+ { 2, 2 }, // API level 8
+ { 2, 3 }, // API level 9
+ { 2, 3 }, // API level 10
+ { 3, 0 }, // API level 11
+ { 3, 1 }, // API level 12
+ { 3, 2 }, // API level 13
+ { 4, 0 }, // API level 14
+ { 4, 0 }, // API level 15
+ { 4, 1 }, // API level 16
+ { 4, 2 }, // API level 17
+ { 4, 3 }, // API level 18
+ { 4, 4 }, // API level 19
+ { 4, 4 }, // API level 20
+ { 5, 0 }, // API level 21
+ { 5, 1 }, // API level 22
+ { 6, 0 }, // API level 23
+ { 7, 0 }, // API level 24
+ };
+
+ // This will give us at least the first 2 version components
+ const int sdk = static_cast<int>(QJNIObjectPrivate::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT"));
+ if (sdk >= 1 && sdk <= sizeof(versions) / sizeof(versions[0])) {
+ version.m_major = versions[sdk - 1][0];
+ version.m_minor = versions[sdk - 1][1];
+ }
+
+ // API level 6 was exactly version 2.0.1
+ version.m_micro = sdk == 6 ? 1 : -1;
+#else
+ version.m_major = -1;
+ version.m_minor = -1;
+ version.m_micro = -1;
+#endif
+ return version;
+}
+#endif
+
+static inline int compareVersionComponents(int lhs, int rhs)
+{
+ return lhs >= 0 && rhs >= 0 ? lhs - rhs : 0;
+}
+
+/*!
+ \fn int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
+ const QOperatingSystemVersion &v2)
+
+ Compares \a v1 with \a v2 and returns an integer less than, equal to, or
+ greater than zero, depending on whether \a v1 is less than, equal to, or
+ greater than \a v2, respectively.
+
+ Comparisons are performed by comparing the version number components of
+ \a v1 and \a v2.
+
+ \note This function cannot take the OS type into account; you should use
+ the overloaded comparison operators to compare QOperatingSystemVersions
+ in a safe manner.
+*/
+int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1, const QOperatingSystemVersion &v2)
+{
+ if (v1.m_major == v2.m_major) {
+ if (v1.m_minor == v2.m_minor) {
+ return compareVersionComponents(v1.m_micro, v2.m_micro);
+ }
+ return compareVersionComponents(v1.m_minor, v2.m_minor);
+ }
+ return compareVersionComponents(v1.m_major, v2.m_major);
+}
+
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \fn QOperatingSystemVersion QOperatingSystemVersion::fromVersionNumber(const QVersionNumber &version,
+ QOperatingSystemVersion::OSType os)
+
+ Returns a QOperatingSystemVersion consisting of the OS type \a os and version number \a version.
+*/
+QOperatingSystemVersion QOperatingSystemVersion::fromVersionNumber(const QVersionNumber &version,
+ QOperatingSystemVersion::OSType os)
+{
+ return QOperatingSystemVersion(os, version.majorVersion(), version.minorVersion(), version.microVersion());
+}
+
+/*!
+ \fn QOperatingSystemVersion QOperatingSystemVersion::toVersionNumber() const
+
+ Returns the QOperatingSystemVersion's version number as a QVersionNumber.
+*/
+QVersionNumber QOperatingSystemVersion::toVersionNumber() const
+{
+ return QVersionNumber(m_major, m_minor, m_micro);
+}
+#endif
+
+/*!
+ \fn int QOperatingSystemVersion::majorVersion() const
+
+ Returns the major version number, that is, the first segment of the operating system's version number.
+
+ See the main class documentation for what the major version number is on a given operating system.
+
+ -1 indicates an unknown or absent version number component.
+
+ \sa minorVersion(), microVersion()
+*/
+
+/*!
+ \fn int QOperatingSystemVersion::minorVersion() const
+
+ Returns the minor version number, that is, the second segment of the operating system's version number.
+
+ See the main class documentation for what the minor version number is on a given operating system.
+
+ -1 indicates an unknown or absent version number component.
+
+ \sa majorVersion(), macro()
+*/
+
+/*!
+ \fn int QOperatingSystemVersion::microVersion() const
+
+ Returns the micro version number, that is, the third segment of the operating system's version number.
+
+ See the main class documentation for what the micro version number is on a given operating system.
+
+ -1 indicates an unknown or absent version number component.
+
+ \sa majorVersion(), minorVersion()
+*/
+
+/*!
+ \fn QOperatingSystemVersion::OSType QOperatingSystemVersion::type() const
+
+ Returns the OS type identified by the QOperatingSystemVersion.
+
+ \sa typeName()
+*/
+
+/*!
+ \fn QString QOperatingSystemVersion::name() const
+
+ Returns a string representation of the OS type identified by the QOperatingSystemVersion.
+
+ \sa type()
+*/
+QString QOperatingSystemVersion::name() const
+{
+ switch (type()) {
+ case QOperatingSystemVersion::Windows:
+ return QStringLiteral("Windows");
+ case QOperatingSystemVersion::MacOS: {
+ if (majorVersion() < 10)
+ return QStringLiteral("Mac OS");
+ if (majorVersion() == 10 && minorVersion() < 8)
+ return QStringLiteral("Mac OS X");
+ if (majorVersion() == 10 && minorVersion() < 12)
+ return QStringLiteral("OS X");
+ return QStringLiteral("macOS");
+ }
+ case QOperatingSystemVersion::IOS: {
+ if (majorVersion() < 4)
+ return QStringLiteral("iPhone OS");
+ return QStringLiteral("iOS");
+ }
+ case QOperatingSystemVersion::TvOS:
+ return QStringLiteral("tvOS");
+ case QOperatingSystemVersion::WatchOS:
+ return QStringLiteral("watchOS");
+ case QOperatingSystemVersion::Android:
+ return QStringLiteral("Android");
+ case QOperatingSystemVersion::Unknown:
+ default:
+ return QString();
+ }
+}
+
+/*!
+ \variable QOperatingSystemVersion::Windows7
+ \brief a version corresponding to Windows 7 (version 6.1).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::Windows7 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 1);
+
+/*!
+ \variable QOperatingSystemVersion::Windows8
+ \brief a version corresponding to Windows 8 (version 6.2).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::Windows8 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 2);
+
+/*!
+ \variable QOperatingSystemVersion::Windows8_1
+ \brief a version corresponding to Windows 8.1 (version 6.3).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::Windows8_1 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 3);
+
+/*!
+ \variable QOperatingSystemVersion::Windows10
+ \brief a version corresponding to Windows 10 (version 10.0).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::Windows10 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10);
+
+/*!
+ \variable QOperatingSystemVersion::OSXMavericks
+ \brief a version corresponding to OS X Mavericks (version 10.9).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::OSXMavericks = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 9);
+
+/*!
+ \variable QOperatingSystemVersion::OSXYosemite
+ \brief a version corresponding to OS X Yosemite (version 10.10).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::OSXYosemite = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 10);
+
+/*!
+ \variable QOperatingSystemVersion::OSXElCapitan
+ \brief a version corresponding to OS X El Capitan (version 10.11).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::OSXElCapitan = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 11);
+
+/*!
+ \variable QOperatingSystemVersion::MacOSSierra
+ \brief a version corresponding to macOS Sierra (version 10.12).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::MacOSSierra = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 12);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidJellyBean
+ \brief a version corresponding to Android Jelly Bean (versions 4.1 - 4.3).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean = QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 1);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidKitKat
+ \brief a version corresponding to Android KitKat (version 4.4).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidKitKat = QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 4);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidLollipop
+ \brief a version corresponding to Android Lollipop (versions 5.0 - 5.1).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidLollipop = QOperatingSystemVersion(QOperatingSystemVersion::Android, 5, 0);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidMarshmallow
+ \brief a version corresponding to Android Marshmallow (version 6.0).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidMarshmallow = QOperatingSystemVersion(QOperatingSystemVersion::Android, 6);
+
+/*!
+ \variable QOperatingSystemVersion::AndroidNougat
+ \brief a version corresponding to Android Nougat (version 7.0).
+ \since 5.9
+ */
+const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat = QOperatingSystemVersion(QOperatingSystemVersion::Android, 7);
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qoperatingsystemversion.h b/src/corelib/global/qoperatingsystemversion.h
new file mode 100644
index 0000000000..33c3d33bcc
--- /dev/null
+++ b/src/corelib/global/qoperatingsystemversion.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+
+#ifndef QOPERATINGSYSTEMVERSION_H
+#define QOPERATINGSYSTEMVERSION_H
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QVersionNumber;
+
+class Q_CORE_EXPORT QOperatingSystemVersion
+{
+public:
+ enum OSType {
+ Unknown = 0,
+ Windows,
+ MacOS,
+ IOS,
+ TvOS,
+ WatchOS,
+ Android
+ };
+
+ static const QOperatingSystemVersion Windows7;
+ static const QOperatingSystemVersion Windows8;
+ static const QOperatingSystemVersion Windows8_1;
+ static const QOperatingSystemVersion Windows10;
+
+ static const QOperatingSystemVersion OSXMavericks;
+ static const QOperatingSystemVersion OSXYosemite;
+ static const QOperatingSystemVersion OSXElCapitan;
+ static const QOperatingSystemVersion MacOSSierra;
+
+ static const QOperatingSystemVersion AndroidJellyBean;
+ static const QOperatingSystemVersion AndroidKitKat;
+ static const QOperatingSystemVersion AndroidLollipop;
+ static const QOperatingSystemVersion AndroidMarshmallow;
+ static const QOperatingSystemVersion AndroidNougat;
+
+ QOperatingSystemVersion(const QOperatingSystemVersion &other) = default;
+ Q_DECL_CONSTEXPR QOperatingSystemVersion(OSType osType, int vmajor, int vminor = -1, int vmicro = -1)
+ : m_os(osType), m_major(vmajor), m_minor(vminor), m_micro(vmicro) { }
+
+ static QOperatingSystemVersion current();
+
+ static int compare(const QOperatingSystemVersion &v1, const QOperatingSystemVersion &v2);
+
+ QOperatingSystemVersion fromVersionNumber(const QVersionNumber &version, OSType os);
+ QVersionNumber toVersionNumber() const;
+
+ Q_DECL_CONSTEXPR int majorVersion() const { return m_major; }
+ Q_DECL_CONSTEXPR int minorVersion() const { return m_minor; }
+ Q_DECL_CONSTEXPR int microVersion() const { return m_micro; }
+
+ Q_DECL_CONSTEXPR OSType type() const { return m_os; }
+ QString name() const;
+
+private:
+ QOperatingSystemVersion() = default;
+ OSType m_os;
+ int m_major;
+ int m_minor;
+ int m_micro;
+};
+
+inline bool operator>(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) > 0; }
+
+inline bool operator>=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) >= 0; }
+
+inline bool operator<(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) < 0; }
+
+inline bool operator<=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) <= 0; }
+
+inline bool operator==(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) == 0; }
+
+inline bool operator!=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
+{ return !(lhs == rhs); }
+
+QT_END_NAMESPACE
+
+#endif // QOPERATINGSYSTEMVERSION_H
diff --git a/src/corelib/global/qoperatingsystemversion_darwin.mm b/src/corelib/global/qoperatingsystemversion_darwin.mm
new file mode 100644
index 0000000000..3dd007cbb3
--- /dev/null
+++ b/src/corelib/global/qoperatingsystemversion_darwin.mm
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "qoperatingsystemversion_p.h"
+#import <Foundation/Foundation.h>
+
+#ifdef Q_OS_IOS
+#import <UIKit/UIKit.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+typedef qint16 (*GestaltFunction)(quint32 selector, qint32 *response);
+
+QOperatingSystemVersion QOperatingSystemVersion::current()
+{
+ QOperatingSystemVersion v;
+ v.m_os = currentType();
+ v.m_major = -1;
+ v.m_minor = -1;
+ v.m_micro = -1;
+#if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_8_0) || defined(Q_OS_TVOS) || defined(Q_OS_WATCHOS)
+ if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) {
+ NSOperatingSystemVersion osv = NSProcessInfo.processInfo.operatingSystemVersion;
+ v.m_major = osv.majorVersion;
+ v.m_minor = osv.minorVersion;
+ v.m_micro = osv.patchVersion;
+ return v;
+ }
+#endif
+ // Use temporary variables so we can return 0.0.0 (unknown version)
+ // in case of an error partway through determining the OS version
+ qint32 major = 0, minor = 0, patch = 0;
+#if QT_MACOS_IOS_DEPLOYMENT_TARGET_BELOW(__MAC_10_10, __IPHONE_8_0)
+#if defined(Q_OS_IOS)
+ @autoreleasepool {
+ NSArray *parts = [UIDevice.currentDevice.systemVersion componentsSeparatedByString:@"."];
+ major = parts.count > 0 ? [[parts objectAtIndex:0] intValue] : 0;
+ minor = parts.count > 1 ? [[parts objectAtIndex:1] intValue] : 0;
+ patch = parts.count > 2 ? [[parts objectAtIndex:2] intValue] : 0;
+ }
+#elif defined(Q_OS_MACOS)
+ static GestaltFunction pGestalt = 0;
+ if (!pGestalt) {
+ CFBundleRef b = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreServices"));
+ pGestalt = reinterpret_cast<GestaltFunction>(CFBundleGetFunctionPointerForName(b,
+ CFSTR("Gestalt")));
+ }
+ if (!pGestalt)
+ return v;
+ if (pGestalt('sys1', &major) != 0)
+ return v;
+ if (pGestalt('sys2', &minor) != 0)
+ return v;
+ if (pGestalt('sys3', &patch) != 0)
+ return v;
+#endif
+#endif
+ v.m_major = major;
+ v.m_minor = minor;
+ v.m_micro = patch;
+ return v;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qoperatingsystemversion_p.h b/src/corelib/global/qoperatingsystemversion_p.h
new file mode 100644
index 0000000000..f227e98dd1
--- /dev/null
+++ b/src/corelib/global/qoperatingsystemversion_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "qoperatingsystemversion.h"
+
+#ifdef Q_OS_WIN
+#include <qt_windows.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WIN
+OSVERSIONINFOEX qWindowsVersionInfo();
+#endif
+
+static inline QOperatingSystemVersion::OSType currentType()
+{
+#if defined(Q_OS_WIN)
+ return QOperatingSystemVersion::Windows;
+#elif defined(Q_OS_MACOS)
+ return QOperatingSystemVersion::MacOS;
+#elif defined(Q_OS_IOS)
+ return QOperatingSystemVersion::IOS;
+#elif defined(Q_OS_TVOS)
+ return QOperatingSystemVersion::TvOS;
+#elif defined(Q_OS_WATCHOS)
+ return QOperatingSystemVersion::WatchOS;
+#elif defined(Q_OS_ANDROID)
+ return QOperatingSystemVersion::Android;
+#else
+ return QOperatingSystemVersion::Unknown;
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qoperatingsystemversion_win.cpp b/src/corelib/global/qoperatingsystemversion_win.cpp
new file mode 100644
index 0000000000..060ca2f7da
--- /dev/null
+++ b/src/corelib/global/qoperatingsystemversion_win.cpp
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include "qoperatingsystemversion_p.h"
+#include <qt_windows.h>
+#include <qbytearray.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_OS_WINRT
+static inline HMODULE moduleHandleForFunction(LPCVOID address)
+{
+ // This is a widely used, decades-old technique for retrieving the handle
+ // of a module and is effectively equivalent to GetModuleHandleEx
+ // (which is unavailable on WinRT)
+ MEMORY_BASIC_INFORMATION mbi = { 0, 0, 0, 0, 0, 0, 0 };
+ if (VirtualQuery(address, &mbi, sizeof(mbi)) == 0)
+ return 0;
+ return reinterpret_cast<HMODULE>(mbi.AllocationBase);
+}
+#endif
+
+static inline OSVERSIONINFOEX determineWinOsVersion()
+{
+ OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0};
+
+#define GetProcAddressA GetProcAddress
+
+ // GetModuleHandle is not supported in WinRT and linking to it at load time
+ // will not pass the Windows App Certification Kit... but it exists and is functional,
+ // so use some unusual but widely used techniques to get a pointer to it
+#ifdef Q_OS_WINRT
+ // 1. Get HMODULE of kernel32.dll, using the address of some function exported by that DLL
+ HMODULE kernelModule = moduleHandleForFunction(reinterpret_cast<LPCVOID>(VirtualQuery));
+ if (Q_UNLIKELY(!kernelModule))
+ return result;
+
+ // 2. Get pointer to GetModuleHandle so we can then load other arbitrary modules (DLLs)
+ typedef HMODULE(WINAPI *GetModuleHandleFunction)(LPCWSTR);
+ GetModuleHandleFunction pGetModuleHandle = reinterpret_cast<GetModuleHandleFunction>(
+ GetProcAddressA(kernelModule, "GetModuleHandleW"));
+ if (Q_UNLIKELY(!pGetModuleHandle))
+ return result;
+#else
+#define pGetModuleHandle GetModuleHandleW
+#endif
+
+#ifndef Q_OS_WINCE
+ HMODULE ntdll = pGetModuleHandle(L"ntdll.dll");
+ if (Q_UNLIKELY(!ntdll))
+ return result;
+
+ // NTSTATUS is not defined on WinRT
+ typedef LONG NTSTATUS;
+ typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO);
+
+ // RtlGetVersion is documented public API but we must load it dynamically
+ // because linking to it at load time will not pass the Windows App Certification Kit
+ // https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx
+ RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(
+ GetProcAddressA(ntdll, "RtlGetVersion"));
+ if (Q_UNLIKELY(!pRtlGetVersion))
+ return result;
+
+ // GetVersionEx() has been deprecated in Windows 8.1 and will return
+ // only Windows 8 from that version on, so use the kernel API function.
+ pRtlGetVersion((LPOSVERSIONINFO) &result); // always returns STATUS_SUCCESS
+#else // !Q_OS_WINCE
+ GetVersionEx(&result);
+#endif
+ return result;
+}
+
+OSVERSIONINFOEX qWindowsVersionInfo()
+{
+ OSVERSIONINFOEX realResult = determineWinOsVersion();
+#ifdef QT_DEBUG
+ {
+ if (Q_UNLIKELY(qEnvironmentVariableIsSet("QT_WINVER_OVERRIDE"))) {
+ OSVERSIONINFOEX result = realResult;
+ result.dwMajorVersion = 0;
+ result.dwMinorVersion = 0;
+
+ // Erase any build number and service pack information
+ result.dwBuildNumber = 0;
+ result.szCSDVersion[0] = L'\0';
+ result.wServicePackMajor = 0;
+ result.wServicePackMinor = 0;
+
+ const QByteArray winVerOverride = qgetenv("QT_WINVER_OVERRIDE");
+ if (winVerOverride == "WINDOWS7" || winVerOverride == "2008_R2") {
+ result.dwMajorVersion = 6;
+ result.dwMinorVersion = 1;
+ } else if (winVerOverride == "WINDOWS8" || winVerOverride == "2012") {
+ result.dwMajorVersion = 6;
+ result.dwMinorVersion = 2;
+ } else if (winVerOverride == "WINDOWS8_1" || winVerOverride == "2012_R2") {
+ result.dwMajorVersion = 6;
+ result.dwMinorVersion = 3;
+ } else if (winVerOverride == "WINDOWS10" || winVerOverride == "2016") {
+ result.dwMajorVersion = 10;
+ } else {
+ return realResult;
+ }
+
+ if (winVerOverride == "2008_R2"
+ || winVerOverride == "2012"
+ || winVerOverride == "2012_R2"
+ || winVerOverride == "2016") {
+ // If the current host OS is a domain controller and the override OS
+ // is also a server type OS, preserve that information
+ if (result.wProductType == VER_NT_WORKSTATION)
+ result.wProductType = VER_NT_SERVER;
+ } else {
+ // Any other OS must be a workstation OS type
+ result.wProductType = VER_NT_WORKSTATION;
+ }
+ }
+ }
+#endif
+ return realResult;
+}
+
+QOperatingSystemVersion QOperatingSystemVersion::current()
+{
+ QOperatingSystemVersion v;
+ v.m_os = currentType();
+ const OSVERSIONINFOEX osv = qWindowsVersionInfo();
+ v.m_major = osv.dwMajorVersion;
+ v.m_minor = osv.dwMinorVersion;
+ v.m_micro = osv.dwBuildNumber;
+ return v;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h
index 23f412aa6a..5ec55d467c 100644
--- a/src/corelib/global/qsysinfo.h
+++ b/src/corelib/global/qsysinfo.h
@@ -79,7 +79,8 @@ public:
# endif
};
#endif
- enum WinVersion {
+#if QT_DEPRECATED_SINCE(5, 9)
+ enum QT_DEPRECATED_X("Use QOperatingSystemVersion") WinVersion {
WV_None = 0x0000,
WV_32s = 0x0001,
@@ -117,19 +118,25 @@ public:
WV_CE_6 = 0x0400,
WV_CE_based = 0x0f00
};
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
+QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
+QT_WARNING_DISABLE_INTEL(1478)
+QT_WARNING_DISABLE_MSVC(4996)
#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
- static const WinVersion WindowsVersion;
- static WinVersion windowsVersion();
+ QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion;
+ QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion();
#else
- static const WinVersion WindowsVersion = WV_None;
- static WinVersion windowsVersion() { return WV_None; }
+ QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion = WV_None;
+ QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion() { return WV_None; }
#endif
+QT_WARNING_POP
#define Q_MV_OSX(major, minor) (major == 10 ? minor + 2 : (major == 9 ? 1 : 0))
#define Q_MV_IOS(major, minor) (QSysInfo::MV_IOS | major << 4 | minor)
#define Q_MV_TVOS(major, minor) (QSysInfo::MV_TVOS | major << 4 | minor)
#define Q_MV_WATCHOS(major, minor) (QSysInfo::MV_WATCHOS | major << 4 | minor)
- enum MacVersion {
+ enum QT_DEPRECATED_X("Use QOperatingSystemVersion") MacVersion {
MV_None = 0xffff,
MV_Unknown = 0x0000,
@@ -198,13 +205,20 @@ public:
MV_WATCHOS_2_2 = Q_MV_WATCHOS(2, 2),
MV_WATCHOS_3_0 = Q_MV_WATCHOS(3, 0)
};
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
+QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
+QT_WARNING_DISABLE_INTEL(1478)
+QT_WARNING_DISABLE_MSVC(4996)
#if defined(Q_OS_MAC)
- static const MacVersion MacintoshVersion;
- static MacVersion macVersion();
+ QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const MacVersion MacintoshVersion;
+ QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static MacVersion macVersion();
#else
- static const MacVersion MacintoshVersion = MV_None;
- static MacVersion macVersion() { return MV_None; }
+ QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const MacVersion MacintoshVersion = MV_None;
+ QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static MacVersion macVersion() { return MV_None; }
#endif
+QT_WARNING_POP
+#endif // QT_DEPRECATED_SINCE(5, 9)
static QString buildCpuArchitecture();
static QString currentCpuArchitecture();
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index ac58677b77..994ed88791 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -95,10 +95,11 @@ public:
Qt_5_6 = 17,
Qt_5_7 = Qt_5_6,
Qt_5_8 = Qt_5_7,
-#if QT_VERSION >= 0x050900
+ Qt_5_9 = Qt_5_8,
+#if QT_VERSION >= 0x050a00
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
- Qt_DefaultCompiledVersion = Qt_5_8
+ Qt_DefaultCompiledVersion = Qt_5_9
};
enum ByteOrder {
@@ -222,6 +223,98 @@ private:
QDataStream::Status oldStatus;
};
+template <typename Container>
+QDataStream &readArrayBasedContainer(QDataStream &s, Container &c)
+{
+ StreamStateSaver stateSaver(&s);
+
+ c.clear();
+ quint32 n;
+ s >> n;
+ c.reserve(n);
+ for (quint32 i = 0; i < n; ++i) {
+ typename Container::value_type t;
+ s >> t;
+ if (s.status() != QDataStream::Ok) {
+ c.clear();
+ break;
+ }
+ c.append(t);
+ }
+
+ return s;
+}
+
+template <typename Container>
+QDataStream &readListBasedContainer(QDataStream &s, Container &c)
+{
+ StreamStateSaver stateSaver(&s);
+
+ c.clear();
+ quint32 n;
+ s >> n;
+ for (quint32 i = 0; i < n; ++i) {
+ typename Container::value_type t;
+ s >> t;
+ if (s.status() != QDataStream::Ok) {
+ c.clear();
+ break;
+ }
+ c << t;
+ }
+
+ return s;
+}
+
+template <typename Container>
+QDataStream &readAssociativeContainer(QDataStream &s, Container &c)
+{
+ StreamStateSaver stateSaver(&s);
+
+ c.clear();
+ quint32 n;
+ s >> n;
+ for (quint32 i = 0; i < n; ++i) {
+ typename Container::key_type k;
+ typename Container::mapped_type t;
+ s >> k >> t;
+ if (s.status() != QDataStream::Ok) {
+ c.clear();
+ break;
+ }
+ c.insertMulti(k, t);
+ }
+
+ return s;
+}
+
+template <typename Container>
+QDataStream &writeSequentialContainer(QDataStream &s, const Container &c)
+{
+ s << quint32(c.size());
+ for (const typename Container::value_type &t : c)
+ s << t;
+
+ return s;
+}
+
+template <typename Container>
+QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c)
+{
+ s << quint32(c.size());
+ // Deserialization should occur in the reverse order.
+ // Otherwise, value() will return the least recently inserted
+ // value instead of the most recently inserted one.
+ auto it = c.constEnd();
+ auto begin = c.constBegin();
+ while (it != begin) {
+ --it;
+ s << it.key() << it.value();
+ }
+
+ return s;
+}
+
} // QtPrivate namespace
/*****************************************************************************
@@ -265,209 +358,75 @@ inline QDataStream &QDataStream::operator<<(quint64 i)
{ return *this << qint64(i); }
template <typename T>
-QDataStream& operator>>(QDataStream& s, QList<T>& l)
+inline QDataStream &operator>>(QDataStream &s, QList<T> &l)
{
- QtPrivate::StreamStateSaver stateSaver(&s);
-
- l.clear();
- quint32 c;
- s >> c;
- l.reserve(c);
- for(quint32 i = 0; i < c; ++i)
- {
- T t;
- s >> t;
- if (s.status() != QDataStream::Ok) {
- l.clear();
- break;
- }
- l.append(t);
- }
-
- return s;
+ return QtPrivate::readArrayBasedContainer(s, l);
}
template <typename T>
-QDataStream& operator<<(QDataStream& s, const QList<T>& l)
+inline QDataStream &operator<<(QDataStream &s, const QList<T> &l)
{
- s << quint32(l.size());
- for (int i = 0; i < l.size(); ++i)
- s << l.at(i);
- return s;
+ return QtPrivate::writeSequentialContainer(s, l);
}
template <typename T>
-QDataStream& operator>>(QDataStream& s, QLinkedList<T>& l)
+inline QDataStream &operator>>(QDataStream &s, QLinkedList<T> &l)
{
- QtPrivate::StreamStateSaver stateSaver(&s);
-
- l.clear();
- quint32 c;
- s >> c;
- for(quint32 i = 0; i < c; ++i)
- {
- T t;
- s >> t;
- if (s.status() != QDataStream::Ok) {
- l.clear();
- break;
- }
- l.append(t);
- }
-
- return s;
+ return QtPrivate::readListBasedContainer(s, l);
}
template <typename T>
-QDataStream& operator<<(QDataStream& s, const QLinkedList<T>& l)
+inline QDataStream &operator<<(QDataStream &s, const QLinkedList<T> &l)
{
- s << quint32(l.size());
- typename QLinkedList<T>::ConstIterator it = l.constBegin();
- for(; it != l.constEnd(); ++it)
- s << *it;
- return s;
+ return QtPrivate::writeSequentialContainer(s, l);
}
template<typename T>
-QDataStream& operator>>(QDataStream& s, QVector<T>& v)
+inline QDataStream &operator>>(QDataStream &s, QVector<T> &v)
{
- QtPrivate::StreamStateSaver stateSaver(&s);
-
- v.clear();
- quint32 c;
- s >> c;
- v.resize(c);
- for(quint32 i = 0; i < c; ++i) {
- T t;
- s >> t;
- if (s.status() != QDataStream::Ok) {
- v.clear();
- break;
- }
- v[i] = t;
- }
-
- return s;
+ return QtPrivate::readArrayBasedContainer(s, v);
}
template<typename T>
-QDataStream& operator<<(QDataStream& s, const QVector<T>& v)
+inline QDataStream &operator<<(QDataStream &s, const QVector<T> &v)
{
- s << quint32(v.size());
- for (typename QVector<T>::const_iterator it = v.begin(); it != v.end(); ++it)
- s << *it;
- return s;
+ return QtPrivate::writeSequentialContainer(s, v);
}
template <typename T>
-QDataStream &operator>>(QDataStream &in, QSet<T> &set)
+inline QDataStream &operator>>(QDataStream &s, QSet<T> &set)
{
- QtPrivate::StreamStateSaver stateSaver(&in);
-
- set.clear();
- quint32 c;
- in >> c;
- for (quint32 i = 0; i < c; ++i) {
- T t;
- in >> t;
- if (in.status() != QDataStream::Ok) {
- set.clear();
- break;
- }
- set << t;
- }
-
- return in;
+ return QtPrivate::readListBasedContainer(s, set);
}
template <typename T>
-QDataStream& operator<<(QDataStream &out, const QSet<T> &set)
+inline QDataStream &operator<<(QDataStream &s, const QSet<T> &set)
{
- out << quint32(set.size());
- typename QSet<T>::const_iterator i = set.constBegin();
- while (i != set.constEnd()) {
- out << *i;
- ++i;
- }
- return out;
+ return QtPrivate::writeSequentialContainer(s, set);
}
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QHash<Key, T> &hash)
+inline QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash)
{
- QtPrivate::StreamStateSaver stateSaver(&in);
-
- hash.clear();
- quint32 n;
- in >> n;
-
- for (quint32 i = 0; i < n; ++i) {
- if (in.status() != QDataStream::Ok)
- break;
-
- Key k;
- T t;
- in >> k >> t;
- hash.insertMulti(k, t);
- }
-
- if (in.status() != QDataStream::Ok)
- hash.clear();
- return in;
+ return QtPrivate::readAssociativeContainer(s, hash);
}
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash)
+inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash)
{
- out << quint32(hash.size());
- typename QHash<Key, T>::ConstIterator it = hash.end();
- typename QHash<Key, T>::ConstIterator begin = hash.begin();
- while (it != begin) {
- --it;
- out << it.key() << it.value();
- }
- return out;
+ return QtPrivate::writeAssociativeContainer(s, hash);
}
-#ifdef Q_QDOC
+
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<Key, T> &map)
-#else
-template <class aKey, class aT>
-Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<aKey, aT> &map)
-#endif
+inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map)
{
- QtPrivate::StreamStateSaver stateSaver(&in);
-
- map.clear();
- quint32 n;
- in >> n;
-
- map.detach();
- for (quint32 i = 0; i < n; ++i) {
- if (in.status() != QDataStream::Ok)
- break;
-
- aKey key;
- aT value;
- in >> key >> value;
- map.insertMulti(key, value);
- }
- if (in.status() != QDataStream::Ok)
- map.clear();
- return in;
+ return QtPrivate::readAssociativeContainer(s, map);
}
template <class Key, class T>
-Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QMap<Key, T> &map)
+inline QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map)
{
- out << quint32(map.size());
- typename QMap<Key, T>::ConstIterator it = map.end();
- typename QMap<Key, T>::ConstIterator begin = map.begin();
- while (it != begin) {
- --it;
- out << it.key() << it.value();
- }
- return out;
+ return QtPrivate::writeAssociativeContainer(s, map);
}
#ifndef QT_NO_DATASTREAM
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index cdb64d08e1..663d9cd61d 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -38,7 +38,7 @@
****************************************************************************/
#include "qfilesystemengine_p.h"
-
+#include "qoperatingsystemversion.h"
#include "qplatformdefs.h"
#include "qsysinfo.h"
#include "private/qabstractfileengine_p.h"
@@ -637,7 +637,7 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
FILE_SHARE_READ, OPEN_EXISTING, NULL);
#endif // Q_OS_WINRT
if (handle) {
- result = QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS8 ?
+ result = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ?
fileIdWin8(handle) : fileId(handle);
CloseHandle(handle);
}
diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp
index 2ce7bd7a4b..9140118872 100644
--- a/src/corelib/io/qfilesystemiterator_win.cpp
+++ b/src/corelib/io/qfilesystemiterator_win.cpp
@@ -39,6 +39,7 @@
#include "qfilesystemiterator_p.h"
#include "qfilesystemengine_p.h"
+#include "qoperatingsystemversion.h"
#include "qplatformdefs.h"
#include "qvector.h"
@@ -93,7 +94,7 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa
haveData = true;
int infoLevel = 0 ; // FindExInfoStandard;
DWORD dwAdditionalFlags = 0;
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) {
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows7) {
dwAdditionalFlags = 2; // FIND_FIRST_EX_LARGE_FETCH
infoLevel = 1 ; // FindExInfoBasic;
}
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index fcdc1e362b..b67afe0e0f 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -136,7 +136,18 @@ Q_DECLARE_TYPEINFO(QConfFileCustomFormat, Q_MOVABLE_TYPE);
typedef QHash<QString, QConfFile *> ConfFileHash;
typedef QCache<QString, QConfFile> ConfFileCache;
-typedef QHash<int, QString> PathHash;
+namespace {
+ struct Path
+ {
+ // Note: Defining constructors explicitly because of buggy C++11
+ // implementation in MSVC (uniform initialization).
+ Path() {}
+ Path(const QString & p, bool ud) : path(p), userDefined(ud) {}
+ QString path;
+ bool userDefined; //!< true - user defined, overridden by setPath
+ };
+}
+typedef QHash<int, Path> PathHash;
typedef QVector<QConfFileCustomFormat> CustomFormatVector;
Q_GLOBAL_STATIC(ConfFileHash, usedHashFunc)
@@ -228,7 +239,7 @@ void QConfFile::clearCache()
// QSettingsPrivate
QSettingsPrivate::QSettingsPrivate(QSettings::Format format)
- : format(format), scope(QSettings::UserScope /* nothing better to put */), iniCodec(0), spec(0), fallbacks(true),
+ : format(format), scope(QSettings::UserScope /* nothing better to put */), iniCodec(0), fallbacks(true),
pendingChanges(false), status(QSettings::NoError)
{
}
@@ -236,7 +247,7 @@ QSettingsPrivate::QSettingsPrivate(QSettings::Format format)
QSettingsPrivate::QSettingsPrivate(QSettings::Format format, QSettings::Scope scope,
const QString &organization, const QString &application)
: format(format), scope(scope), organizationName(organization), applicationName(application),
- iniCodec(0), spec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError)
+ iniCodec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError)
{
}
@@ -944,7 +955,7 @@ void QConfFileSettingsPrivate::initFormat()
void QConfFileSettingsPrivate::initAccess()
{
- if (confFiles[spec]) {
+ if (!confFiles.isEmpty()) {
if (format > QSettings::IniFormat) {
if (!readFunc)
setStatus(QSettings::AccessError);
@@ -1065,22 +1076,22 @@ static void initDefaultPaths(QMutexLocker *locker)
*/
#ifdef Q_OS_WIN
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope),
- windowsConfigPath(CSIDL_APPDATA) + QDir::separator());
+ Path(windowsConfigPath(CSIDL_APPDATA) + QDir::separator(), false));
pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope),
- windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator());
+ Path(windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator(), false));
#else
const QString userPath = make_user_path();
- pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), userPath);
- pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), systemPath);
+ pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), Path(userPath, false));
+ pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), Path(systemPath, false));
#ifndef Q_OS_MAC
- pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::UserScope), userPath);
- pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::SystemScope), systemPath);
+ pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::UserScope), Path(userPath, false));
+ pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::SystemScope), Path(systemPath, false));
#endif
#endif // Q_OS_WIN
}
}
-static QString getPath(QSettings::Format format, QSettings::Scope scope)
+static Path getPath(QSettings::Format format, QSettings::Scope scope)
{
Q_ASSERT((int)QSettings::NativeFormat == 0);
Q_ASSERT((int)QSettings::IniFormat == 1);
@@ -1090,14 +1101,23 @@ static QString getPath(QSettings::Format format, QSettings::Scope scope)
if (pathHash->isEmpty())
initDefaultPaths(&locker);
- QString result = pathHash->value(pathHashKey(format, scope));
- if (!result.isEmpty())
+ Path result = pathHash->value(pathHashKey(format, scope));
+ if (!result.path.isEmpty())
return result;
// fall back on INI path
return pathHash->value(pathHashKey(QSettings::IniFormat, scope));
}
+#if defined(QT_BUILD_INTERNAL) && defined(Q_XDG_PLATFORM) && !defined(QT_NO_STANDARDPATHS)
+// Note: Suitable only for autotests.
+void Q_AUTOTEST_EXPORT clearDefaultPaths()
+{
+ QMutexLocker locker(&settingsGlobalMutex);
+ pathHashFunc()->clear();
+}
+#endif // QT_BUILD_INTERNAL && Q_XDG_PLATFORM && !QT_NO_STANDARDPATHS
+
QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
QSettings::Scope scope,
const QString &organization,
@@ -1105,7 +1125,6 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
: QSettingsPrivate(format, scope, organization, application),
nextPosition(0x40000000) // big positive number
{
- int i;
initFormat();
QString org = organization;
@@ -1118,22 +1137,43 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format,
QString orgFile = org + extension;
if (scope == QSettings::UserScope) {
- QString userPath = getPath(format, QSettings::UserScope);
+ Path userPath = getPath(format, QSettings::UserScope);
if (!application.isEmpty())
- confFiles[F_User | F_Application].reset(QConfFile::fromName(userPath + appFile, true));
- confFiles[F_User | F_Organization].reset(QConfFile::fromName(userPath + orgFile, true));
+ confFiles.append(QConfFile::fromName(userPath.path + appFile, true));
+ confFiles.append(QConfFile::fromName(userPath.path + orgFile, true));
}
- QString systemPath = getPath(format, QSettings::SystemScope);
- if (!application.isEmpty())
- confFiles[F_System | F_Application].reset(QConfFile::fromName(systemPath + appFile, false));
- confFiles[F_System | F_Organization].reset(QConfFile::fromName(systemPath + orgFile, false));
-
- for (i = 0; i < NumConfFiles; ++i) {
- if (confFiles[i]) {
- spec = i;
- break;
+ Path systemPath = getPath(format, QSettings::SystemScope);
+#if defined(Q_XDG_PLATFORM) && !defined(QT_NO_STANDARDPATHS)
+ // check if the systemPath wasn't overridden by QSettings::setPath()
+ if (!systemPath.userDefined) {
+ // Note: We can't use QStandardPaths::locateAll() as we need all the
+ // possible files (not just the existing ones) and there is no way
+ // to exclude user specific (XDG_CONFIG_HOME) directory from the search.
+ QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation);
+ // remove the QStandardLocation::writableLocation() (XDG_CONFIG_HOME)
+ if (!dirs.isEmpty())
+ dirs.takeFirst();
+ QStringList paths;
+ if (!application.isEmpty()) {
+ paths.reserve(dirs.size() * 2);
+ for (const auto &dir : qAsConst(dirs))
+ paths.append(dir + QLatin1Char('/') + appFile);
+ } else {
+ paths.reserve(dirs.size());
}
+ for (const auto &dir : qAsConst(dirs))
+ paths.append(dir + QLatin1Char('/') + orgFile);
+
+ // Note: No check for existence of files is done intentionaly.
+ for (const auto &path : qAsConst(paths))
+ confFiles.append(QConfFile::fromName(path, false));
+ } else
+#endif // Q_XDG_PLATFORM && !QT_NO_STANDARDPATHS
+ {
+ if (!application.isEmpty())
+ confFiles.append(QConfFile::fromName(systemPath.path + appFile, false));
+ confFiles.append(QConfFile::fromName(systemPath.path + orgFile, false));
}
initAccess();
@@ -1146,7 +1186,7 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(const QString &fileName,
{
initFormat();
- confFiles[0].reset(QConfFile::fromName(fileName, true));
+ confFiles.append(QConfFile::fromName(fileName, true));
initAccess();
}
@@ -1157,40 +1197,39 @@ QConfFileSettingsPrivate::~QConfFileSettingsPrivate()
ConfFileHash *usedHash = usedHashFunc();
ConfFileCache *unusedCache = unusedCacheFunc();
- for (int i = 0; i < NumConfFiles; ++i) {
- if (confFiles[i] && !confFiles[i]->ref.deref()) {
- if (confFiles[i]->size == 0) {
- delete confFiles[i].take();
+ for (auto conf_file : qAsConst(confFiles)) {
+ if (!conf_file->ref.deref()) {
+ if (conf_file->size == 0) {
+ delete conf_file;
} else {
if (usedHash)
- usedHash->remove(confFiles[i]->name);
+ usedHash->remove(conf_file->name);
if (unusedCache) {
QT_TRY {
// compute a better size?
- unusedCache->insert(confFiles[i]->name, confFiles[i].data(),
- 10 + (confFiles[i]->originalKeys.size() / 4));
- confFiles[i].take();
+ unusedCache->insert(conf_file->name, conf_file,
+ 10 + (conf_file->originalKeys.size() / 4));
} QT_CATCH(...) {
// out of memory. Do not cache the file.
- delete confFiles[i].take();
+ delete conf_file;
}
} else {
// unusedCache is gone - delete the entry to prevent a memory leak
- delete confFiles[i].take();
+ delete conf_file;
}
}
}
- // prevent the ScopedPointer to deref it again.
- confFiles[i].take();
}
}
void QConfFileSettingsPrivate::remove(const QString &key)
{
- QConfFile *confFile = confFiles[spec].data();
- if (!confFile)
+ if (confFiles.isEmpty())
return;
+ // Note: First config file is always the most specific.
+ QConfFile *confFile = confFiles.at(0);
+
QSettingsKey theKey(key, caseSensitivity);
QSettingsKey prefix(key + QLatin1Char('/'), caseSensitivity);
QMutexLocker locker(&confFile->mutex);
@@ -1214,10 +1253,12 @@ void QConfFileSettingsPrivate::remove(const QString &key)
void QConfFileSettingsPrivate::set(const QString &key, const QVariant &value)
{
- QConfFile *confFile = confFiles[spec].data();
- if (!confFile)
+ if (confFiles.isEmpty())
return;
+ // Note: First config file is always the most specific.
+ QConfFile *confFile = confFiles.at(0);
+
QSettingsKey theKey(key, caseSensitivity, nextPosition++);
QMutexLocker locker(&confFile->mutex);
confFile->removedKeys.remove(theKey);
@@ -1230,29 +1271,27 @@ bool QConfFileSettingsPrivate::get(const QString &key, QVariant *value) const
ParsedSettingsMap::const_iterator j;
bool found = false;
- for (int i = 0; i < NumConfFiles; ++i) {
- if (QConfFile *confFile = confFiles[i].data()) {
- QMutexLocker locker(&confFile->mutex);
+ for (auto confFile : qAsConst(confFiles)) {
+ QMutexLocker locker(&confFile->mutex);
- if (!confFile->addedKeys.isEmpty()) {
- j = confFile->addedKeys.constFind(theKey);
- found = (j != confFile->addedKeys.constEnd());
- }
- if (!found) {
- ensureSectionParsed(confFile, theKey);
- j = confFile->originalKeys.constFind(theKey);
- found = (j != confFile->originalKeys.constEnd()
- && !confFile->removedKeys.contains(theKey));
- }
+ if (!confFile->addedKeys.isEmpty()) {
+ j = confFile->addedKeys.constFind(theKey);
+ found = (j != confFile->addedKeys.constEnd());
+ }
+ if (!found) {
+ ensureSectionParsed(confFile, theKey);
+ j = confFile->originalKeys.constFind(theKey);
+ found = (j != confFile->originalKeys.constEnd()
+ && !confFile->removedKeys.contains(theKey));
+ }
- if (found && value)
- *value = *j;
+ if (found && value)
+ *value = *j;
- if (found)
- return true;
- if (!fallbacks)
- break;
- }
+ if (found)
+ return true;
+ if (!fallbacks)
+ break;
}
return false;
}
@@ -1265,34 +1304,31 @@ QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec
QSettingsKey thePrefix(prefix, caseSensitivity);
int startPos = prefix.size();
- for (int i = 0; i < NumConfFiles; ++i) {
- if (QConfFile *confFile = confFiles[i].data()) {
- QMutexLocker locker(&confFile->mutex);
+ for (auto confFile : qAsConst(confFiles)) {
+ QMutexLocker locker(&confFile->mutex);
- if (thePrefix.isEmpty()) {
- ensureAllSectionsParsed(confFile);
- } else {
- ensureSectionParsed(confFile, thePrefix);
- }
-
- j = const_cast<const ParsedSettingsMap *>(
- &confFile->originalKeys)->lowerBound( thePrefix);
- while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) {
- if (!confFile->removedKeys.contains(j.key()))
- processChild(j.key().originalCaseKey().midRef(startPos), spec, result);
- ++j;
- }
+ if (thePrefix.isEmpty())
+ ensureAllSectionsParsed(confFile);
+ else
+ ensureSectionParsed(confFile, thePrefix);
- j = const_cast<const ParsedSettingsMap *>(
- &confFile->addedKeys)->lowerBound(thePrefix);
- while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) {
+ j = const_cast<const ParsedSettingsMap *>(
+ &confFile->originalKeys)->lowerBound( thePrefix);
+ while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) {
+ if (!confFile->removedKeys.contains(j.key()))
processChild(j.key().originalCaseKey().midRef(startPos), spec, result);
- ++j;
- }
+ ++j;
+ }
- if (!fallbacks)
- break;
+ j = const_cast<const ParsedSettingsMap *>(
+ &confFile->addedKeys)->lowerBound(thePrefix);
+ while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) {
+ processChild(j.key().originalCaseKey().midRef(startPos), spec, result);
+ ++j;
}
+
+ if (!fallbacks)
+ break;
}
std::sort(result.begin(), result.end());
result.erase(std::unique(result.begin(), result.end()),
@@ -1302,10 +1338,12 @@ QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec
void QConfFileSettingsPrivate::clear()
{
- QConfFile *confFile = confFiles[spec].data();
- if (!confFile)
+ if (confFiles.isEmpty())
return;
+ // Note: First config file is always the most specific.
+ QConfFile *confFile = confFiles.at(0);
+
QMutexLocker locker(&confFile->mutex);
ensureAllSectionsParsed(confFile);
confFile->addedKeys.clear();
@@ -1317,12 +1355,9 @@ void QConfFileSettingsPrivate::sync()
// people probably won't be checking the status a whole lot, so in case of
// error we just try to go on and make the best of it
- for (int i = 0; i < NumConfFiles; ++i) {
- QConfFile *confFile = confFiles[i].data();
- if (confFile) {
- QMutexLocker locker(&confFile->mutex);
- syncConfFile(i);
- }
+ for (auto confFile : qAsConst(confFiles)) {
+ QMutexLocker locker(&confFile->mutex);
+ syncConfFile(confFile);
}
}
@@ -1333,10 +1368,11 @@ void QConfFileSettingsPrivate::flush()
QString QConfFileSettingsPrivate::fileName() const
{
- QConfFile *confFile = confFiles[spec].data();
- if (!confFile)
+ if (confFiles.isEmpty())
return QString();
- return confFile->name;
+
+ // Note: First config file is always the most specific.
+ return confFiles.at(0)->name;
}
bool QConfFileSettingsPrivate::isWritable() const
@@ -1344,16 +1380,14 @@ bool QConfFileSettingsPrivate::isWritable() const
if (format > QSettings::IniFormat && !writeFunc)
return false;
- QConfFile *confFile = confFiles[spec].data();
- if (!confFile)
+ if (confFiles.isEmpty())
return false;
- return confFile->isWritable();
+ return confFiles.at(0)->isWritable();
}
-void QConfFileSettingsPrivate::syncConfFile(int confFileNo)
+void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
{
- QConfFile *confFile = confFiles[confFileNo].data();
bool readOnly = confFile->addedKeys.isEmpty() && confFile->removedKeys.isEmpty();
/*
@@ -2183,9 +2217,10 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\list 1
\li \c{$HOME/.config/MySoft/Star Runner.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.conf})
\li \c{$HOME/.config/MySoft.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.conf})
- \li \c{/etc/xdg/MySoft/Star Runner.conf}
- \li \c{/etc/xdg/MySoft.conf}
+ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft/Star Runner.conf}
+ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft.conf}
\endlist
+ \note If XDG_CONFIG_DIRS is unset, the default value of \c{/etc/xdg} is used.
On \macos versions 10.2 and 10.3, these files are used by
default:
@@ -2220,9 +2255,10 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\list 1
\li \c{$HOME/.config/MySoft/Star Runner.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.ini})
\li \c{$HOME/.config/MySoft.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.ini})
- \li \c{/etc/xdg/MySoft/Star Runner.ini}
- \li \c{/etc/xdg/MySoft.ini}
+ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft/Star Runner.ini}
+ \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft.ini}
\endlist
+ \note If XDG_CONFIG_DIRS is unset, the default value of \c{/etc/xdg} is used.
On Windows, the following files are used:
@@ -3374,7 +3410,7 @@ void QSettings::setPath(Format format, Scope scope, const QString &path)
PathHash *pathHash = pathHashFunc();
if (pathHash->isEmpty())
initDefaultPaths(&locker);
- pathHash->insert(pathHashKey(format, scope), path + QDir::separator());
+ pathHash->insert(pathHashKey(format, scope), Path(path + QDir::separator(), true));
}
/*!
diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp
index bc397055ff..4ad5a7b398 100644
--- a/src/corelib/io/qsettings_mac.cpp
+++ b/src/corelib/io/qsettings_mac.cpp
@@ -419,20 +419,15 @@ QMacSettingsPrivate::QMacSettingsPrivate(QSettings::Scope scope, const QString &
javaPackageName.prepend(QLatin1String("com."));
suiteId = javaPackageName;
- if (scope == QSettings::SystemScope)
- spec |= F_System;
-
- if (application.isEmpty()) {
- spec |= F_Organization;
- } else {
+ if (!application.isEmpty()) {
javaPackageName += QLatin1Char('.');
javaPackageName += application;
applicationId = javaPackageName;
}
numDomains = 0;
- for (int i = (spec & F_System) ? 1 : 0; i < 2; ++i) {
- for (int j = (spec & F_Organization) ? 1 : 0; j < 3; ++j) {
+ for (int i = (scope == QSettings::SystemScope) ? 1 : 0; i < 2; ++i) {
+ for (int j = (application.isEmpty()) ? 1 : 0; j < 3; ++j) {
SearchDomain &domain = domains[numDomains++];
domain.userName = (i == 0) ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser;
if (j == 0)
@@ -573,7 +568,7 @@ bool QMacSettingsPrivate::isWritable() const
QString QMacSettingsPrivate::fileName() const
{
QString result;
- if ((spec & F_System) == 0)
+ if (scope == QSettings::UserScope)
result = QDir::homePath();
result += QLatin1String("/Library/Preferences/");
result += QCFString::toQString(domains[0].applicationOrSuiteId);
diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h
index e6d3413bab..639605d8c4 100644
--- a/src/corelib/io/qsettings_p.h
+++ b/src/corelib/io/qsettings_p.h
@@ -236,19 +236,6 @@ public:
QTextCodec *codec);
static QStringList splitArgs(const QString &s, int idx);
- /*
- The numeric values of these enums define their search order. For example,
- F_User | F_Organization is searched before F_System | F_Application,
- because their values are respectively 1 and 2.
- */
- enum {
- F_Application = 0x0,
- F_Organization = 0x1,
- F_User = 0x0,
- F_System = 0x2,
- NumConfFiles = 4
- };
-
QSettings::Format format;
QSettings::Scope scope;
QString organizationName;
@@ -258,7 +245,6 @@ public:
protected:
QStack<QSettingsGroup> groupStack;
QString groupPrefix;
- int spec;
bool fallbacks;
bool pendingChanges;
mutable QSettings::Status status;
@@ -293,7 +279,7 @@ public:
private:
void initFormat();
void initAccess();
- void syncConfFile(int confFileNo);
+ void syncConfFile(QConfFile *confFile);
bool writeIniFile(QIODevice &device, const ParsedSettingsMap &map);
#ifdef Q_OS_MAC
bool readPlistFile(const QByteArray &data, ParsedSettingsMap *map) const;
@@ -302,7 +288,7 @@ private:
void ensureAllSectionsParsed(QConfFile *confFile) const;
void ensureSectionParsed(QConfFile *confFile, const QSettingsKey &key) const;
- QScopedSharedPointer<QConfFile> confFiles[NumConfFiles];
+ QVector<QConfFile *> confFiles;
QSettings::ReadFunc readFunc;
QSettings::WriteFunc writeFunc;
QString extension;
diff --git a/src/corelib/io/qstorageinfo.cpp b/src/corelib/io/qstorageinfo.cpp
index 3773b72606..9885da1af9 100644
--- a/src/corelib/io/qstorageinfo.cpp
+++ b/src/corelib/io/qstorageinfo.cpp
@@ -260,7 +260,7 @@ QByteArray QStorageInfo::fileSystemType() const
devpath like \c /dev/sda0 for local storages. On Windows, it returns the UNC
path starting with \c \\\\?\\ for local storages (in other words, the volume GUID).
- \sa rootPath()
+ \sa rootPath(), subvolume()
*/
QByteArray QStorageInfo::device() const
{
@@ -268,6 +268,26 @@ QByteArray QStorageInfo::device() const
}
/*!
+ \since 5.8
+ Returns the subvolume name for this volume.
+
+ Some filesystem types allow multiple subvolumes inside one device, which
+ may be mounted in different paths. If the subvolume could be detected, it
+ is returned here. The format of the subvolume name is specific to each
+ filesystem type.
+
+ If this volume was not mounted from a subvolume of a larger filesystem or
+ if the subvolume could not be detected, this function returns an empty byte
+ array.
+
+ \sa device()
+*/
+QByteArray QStorageInfo::subvolume() const
+{
+ return d->subvolume;
+}
+
+/*!
Returns the human-readable name of a filesystem, usually called \c label.
Not all filesystems support this feature. In this case, the value returned by
diff --git a/src/corelib/io/qstorageinfo.h b/src/corelib/io/qstorageinfo.h
index 8941c11a16..e2d9747ceb 100644
--- a/src/corelib/io/qstorageinfo.h
+++ b/src/corelib/io/qstorageinfo.h
@@ -71,6 +71,7 @@ public:
QString rootPath() const;
QByteArray device() const;
+ QByteArray subvolume() const;
QByteArray fileSystemType() const;
QString name() const;
QString displayName() const;
@@ -100,7 +101,7 @@ inline bool operator==(const QStorageInfo &first, const QStorageInfo &second)
{
if (first.d == second.d)
return true;
- return first.device() == second.device();
+ return first.device() == second.device() && first.rootPath() == second.rootPath();
}
inline bool operator!=(const QStorageInfo &first, const QStorageInfo &second)
diff --git a/src/corelib/io/qstorageinfo_p.h b/src/corelib/io/qstorageinfo_p.h
index a14fa8480a..ec5bb785e3 100644
--- a/src/corelib/io/qstorageinfo_p.h
+++ b/src/corelib/io/qstorageinfo_p.h
@@ -85,6 +85,7 @@ protected:
public:
QString rootPath;
QByteArray device;
+ QByteArray subvolume;
QByteArray fileSystemType;
QString name;
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index ae5c42ffd1..fcc7b8ca50 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -120,6 +120,7 @@ public:
inline QString rootPath() const;
inline QByteArray fileSystemType() const;
inline QByteArray device() const;
+ inline QByteArray options() const;
private:
#if defined(Q_OS_BSD4)
QT_STATFSBUF *stat_buf;
@@ -133,6 +134,7 @@ private:
QByteArray m_rootPath;
QByteArray m_fileSystemType;
QByteArray m_device;
+ QByteArray m_options;
#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
FILE *fp;
mntent mnt;
@@ -228,6 +230,11 @@ inline QByteArray QStorageIterator::device() const
return QByteArray(stat_buf[currentIndex].f_mntfromname);
}
+inline QByteArray QStorageIterator::options() const
+{
+ return QByteArray();
+}
+
#elif defined(Q_OS_SOLARIS)
static const char pathMounted[] = "/etc/mnttab";
@@ -301,6 +308,7 @@ inline bool QStorageIterator::next()
m_device = data.at(0);
m_rootPath = data.at(1);
m_fileSystemType = data.at(2);
+ m_options = data.at(3);
return true;
}
@@ -320,6 +328,11 @@ inline QByteArray QStorageIterator::device() const
return m_device;
}
+inline QByteArray QStorageIterator::options() const
+{
+ return m_options;
+}
+
#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
static const char pathMounted[] = "/etc/mtab";
@@ -363,6 +376,11 @@ inline QByteArray QStorageIterator::device() const
return QByteArray(mnt.mnt_fsname);
}
+inline QByteArray QStorageIterator::options() const
+{
+ return QByteArray(mnt.mnt_opts);
+}
+
#elif defined(Q_OS_HAIKU)
inline QStorageIterator::QStorageIterator()
{
@@ -420,6 +438,11 @@ inline QByteArray QStorageIterator::device() const
return m_device;
}
+inline QByteArray QStorageIterator::options() const
+{
+ return QByteArray();
+}
+
#else
inline QStorageIterator::QStorageIterator()
@@ -455,8 +478,35 @@ inline QByteArray QStorageIterator::device() const
return QByteArray();
}
+inline QByteArray QStorageIterator::options() const
+{
+ return QByteArray();
+}
+
#endif
+static QByteArray extractSubvolume(const QStorageIterator &it)
+{
+#ifdef Q_OS_LINUX
+ if (it.fileSystemType() == "btrfs") {
+ const QByteArrayList opts = it.options().split(',');
+ QByteArray id;
+ for (const QByteArray &opt : opts) {
+ static const char subvol[] = "subvol=";
+ static const char subvolid[] = "subvolid=";
+ if (opt.startsWith(subvol))
+ return std::move(opt).mid(strlen(subvol));
+ if (opt.startsWith(subvolid))
+ id = std::move(opt).mid(strlen(subvolid));
+ }
+
+ // if we didn't find the subvolume name, return the subvolume ID
+ return id;
+ }
+#endif
+ return QByteArray();
+}
+
void QStorageInfoPrivate::initRootPath()
{
rootPath = QFileInfo(rootPath).canonicalFilePath();
@@ -483,6 +533,7 @@ void QStorageInfoPrivate::initRootPath()
rootPath = mountDir;
device = it.device();
fileSystemType = fsName;
+ subvolume = extractSubvolume(it);
}
}
}
diff --git a/src/corelib/io/qtemporarydir.cpp b/src/corelib/io/qtemporarydir.cpp
index 6e50a8513e..b2bf9fce97 100644
--- a/src/corelib/io/qtemporarydir.cpp
+++ b/src/corelib/io/qtemporarydir.cpp
@@ -305,6 +305,33 @@ QString QTemporaryDir::path() const
}
/*!
+ \since 5.9
+
+ Returns the path name of a file in the temporary directory.
+ Does \e not check if the file actually exists in the directory.
+ Redundant multiple separators or "." and ".." directories in
+ \a fileName are not removed (see QDir::cleanPath()). Absolute
+ paths are not allowed.
+*/
+QString QTemporaryDir::filePath(const QString &fileName) const
+{
+ if (QDir::isAbsolutePath(fileName)) {
+ qWarning("QTemporaryDir::filePath: Absolute paths are not allowed: %s", qUtf8Printable(fileName));
+ return QString();
+ }
+
+ if (!d_ptr->success)
+ return QString();
+
+ QString ret = d_ptr->pathOrError;
+ if (!fileName.isEmpty()) {
+ ret += QLatin1Char('/');
+ ret += fileName;
+ }
+ return ret;
+}
+
+/*!
Returns \c true if the QTemporaryDir is in auto remove
mode. Auto-remove mode will automatically delete the directory from
disk upon destruction. This makes it very easy to create your
diff --git a/src/corelib/io/qtemporarydir.h b/src/corelib/io/qtemporarydir.h
index 2e70d34ae4..3f6b70a2eb 100644
--- a/src/corelib/io/qtemporarydir.h
+++ b/src/corelib/io/qtemporarydir.h
@@ -65,6 +65,7 @@ public:
bool remove();
QString path() const;
+ QString filePath(const QString &fileName) const;
private:
QScopedPointer<QTemporaryDirPrivate> d_ptr;
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 4fdb1505ff..9b565bff9d 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -2547,6 +2547,7 @@ QTextStream &QTextStream::operator<<(double f)
}
uint flags = 0;
+ const QLocale::NumberOptions numberOptions = locale().numberOptions();
if (numberFlags() & ShowBase)
flags |= QLocaleData::ShowBase;
if (numberFlags() & ForceSign)
@@ -2555,12 +2556,18 @@ QTextStream &QTextStream::operator<<(double f)
flags |= QLocaleData::UppercaseBase;
if (numberFlags() & UppercaseDigits)
flags |= QLocaleData::CapitalEorX;
- if (numberFlags() & ForcePoint)
- flags |= QLocaleData::Alternate;
- if (locale() != QLocale::c() && !(locale().numberOptions() & QLocale::OmitGroupSeparator))
+ if (numberFlags() & ForcePoint) {
+ flags |= QLocaleData::ForcePoint;
+
+ // Only for backwards compatibility
+ flags |= QLocaleData::AddTrailingZeroes | QLocaleData::ShowBase;
+ }
+ if (locale() != QLocale::c() && !(numberOptions & QLocale::OmitGroupSeparator))
flags |= QLocaleData::ThousandsGroup;
- if (!(locale().numberOptions() & QLocale::OmitLeadingZeroInExponent))
+ if (!(numberOptions & QLocale::OmitLeadingZeroInExponent))
flags |= QLocaleData::ZeroPadExponent;
+ if (numberOptions & QLocale::IncludeTrailingZeroesAfterDot)
+ flags |= QLocaleData::AddTrailingZeroes;
const QLocaleData *dd = d->locale.d->m_data;
QString num = dd->doubleToString(f, d->params.realNumberPrecision, form, -1, flags);
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index ee1a290386..42f5699928 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -47,14 +47,8 @@
#include <qdebug.h>
-#if defined(Q_OS_IOS)
-#import <UIKit/UIKit.h>
-#endif
-
QT_BEGIN_NAMESPACE
-typedef qint16 (*GestaltFunction)(quint32 selector, qint32 *response);
-
NSString *QCFString::toNSString(const QString &string)
{
// The const cast below is safe: CfStringRef is immutable and so is NSString.
@@ -98,54 +92,6 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TY
// -------------------------------------------------------------------------
-QAppleOperatingSystemVersion qt_apple_os_version()
-{
- QAppleOperatingSystemVersion v = {0, 0, 0};
-#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_8_0) || defined(Q_OS_TVOS) || defined(Q_OS_WATCHOS)
- if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) {
- NSOperatingSystemVersion osv = NSProcessInfo.processInfo.operatingSystemVersion;
- v.major = osv.majorVersion;
- v.minor = osv.minorVersion;
- v.patch = osv.patchVersion;
- return v;
- }
-#endif
- // Use temporary variables so we can return 0.0.0 (unknown version)
- // in case of an error partway through determining the OS version
- qint32 major = 0, minor = 0, patch = 0;
-#if QT_MAC_DEPLOYMENT_TARGET_BELOW(__MAC_10_10, __IPHONE_8_0)
-#if defined(Q_OS_IOS)
- @autoreleasepool {
- NSArray *parts = [UIDevice.currentDevice.systemVersion componentsSeparatedByString:@"."];
- major = parts.count > 0 ? [[parts objectAtIndex:0] intValue] : 0;
- minor = parts.count > 1 ? [[parts objectAtIndex:1] intValue] : 0;
- patch = parts.count > 2 ? [[parts objectAtIndex:2] intValue] : 0;
- }
-#elif defined(Q_OS_OSX)
- static GestaltFunction pGestalt = 0;
- if (!pGestalt) {
- CFBundleRef b = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreServices"));
- pGestalt = reinterpret_cast<GestaltFunction>(CFBundleGetFunctionPointerForName(b,
- CFSTR("Gestalt")));
- }
- if (!pGestalt)
- return v;
- if (pGestalt('sys1', &major) != 0)
- return v;
- if (pGestalt('sys2', &minor) != 0)
- return v;
- if (pGestalt('sys3', &patch) != 0)
- return v;
-#endif
-#endif
- v.major = major;
- v.minor = minor;
- v.patch = patch;
- return v;
-}
-
-// -------------------------------------------------------------------------
-
QMacAutoReleasePool::QMacAutoReleasePool()
: pool([[NSAutoreleasePool alloc] init])
{
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index 63e1cb48dc..8a710a8a1f 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -137,12 +137,6 @@ private:
QString string;
};
-typedef struct {
- int major, minor, patch;
-} QAppleOperatingSystemVersion;
-
-QAppleOperatingSystemVersion qt_apple_os_version();
-
#ifdef Q_OS_OSX
Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 1a0efae2dc..ebeb083abf 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -42,6 +42,7 @@
#include "qcoreapplication.h"
#include <private/qsystemlibrary_p.h>
+#include "qoperatingsystemversion.h"
#include "qpair.h"
#include "qset.h"
#include "qsocketnotifier.h"
@@ -236,7 +237,7 @@ static inline UINT inputTimerMask()
// QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of
// QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8.
#if WINVER > 0x0601
- if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8)
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8)
result &= ~(QS_TOUCH | QS_POINTER);
#endif // WINVER > 0x0601
return result;
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 63b02d2c0c..d7cc0bce46 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -3943,7 +3943,6 @@ QList<QByteArray> QObject::dynamicPropertyNames() const
static void dumpRecursive(int level, QObject *object)
{
-#if defined(QT_DEBUG)
if (object) {
QByteArray buf;
buf.fill(' ', level / 2 * 8);
@@ -3972,19 +3971,11 @@ static void dumpRecursive(int level, QObject *object)
dumpRecursive(level+1, children.at(i));
}
}
-#else
- Q_UNUSED(level)
- Q_UNUSED(object)
-#endif
}
/*!
Dumps a tree of children to the debug output.
- This function is useful for debugging, but does nothing if the
- library has been compiled in release mode (i.e. without debugging
- information).
-
\sa dumpObjectInfo()
*/
@@ -3997,16 +3988,11 @@ void QObject::dumpObjectTree()
Dumps information about signal connections, etc. for this object
to the debug output.
- This function is useful for debugging, but does nothing if the
- library has been compiled in release mode (i.e. without debugging
- information).
-
\sa dumpObjectTree()
*/
void QObject::dumpObjectInfo()
{
-#if defined(QT_DEBUG)
qDebug("OBJECT %s::%s", metaObject()->className(),
objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
@@ -4066,7 +4052,6 @@ void QObject::dumpObjectInfo()
} else {
qDebug(" <None>");
}
-#endif
}
#ifndef QT_NO_USERDATA
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 55af7256be..a04536b18b 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -63,6 +63,29 @@ QT_WARNING_POP
static const QArrayData &qt_array_empty = qt_array[0];
static const QArrayData &qt_array_unsharable_empty = qt_array[1];
+static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, size_t headerSize,
+ uint options)
+{
+ // Calculate the byte size
+ // allocSize = objectSize * capacity + headerSize, but checked for overflow
+ // plus padded to grow in size
+ if (options & QArrayData::Grow) {
+ auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
+ capacity = r.elementCount;
+ return r.size;
+ } else {
+ return qCalculateBlockSize(capacity, objectSize, headerSize);
+ }
+}
+
+static QArrayData *reallocateData(QArrayData *header, size_t allocSize, uint options)
+{
+ header = static_cast<QArrayData *>(::realloc(header, allocSize));
+ if (header)
+ header->capacityReserved = bool(options & QArrayData::CapacityReserved);
+ return header;
+}
+
QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
size_t capacity, AllocationOptions options) Q_DECL_NOTHROW
{
@@ -91,18 +114,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
if (headerSize > size_t(MaxAllocSize))
return 0;
- // Calculate the byte size
- // allocSize = objectSize * capacity + headerSize, but checked for overflow
- // plus padded to grow in size
- size_t allocSize;
- if (options & Grow) {
- auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
- capacity = r.elementCount;
- allocSize = r.size;
- } else {
- allocSize = qCalculateBlockSize(capacity, objectSize, headerSize);
- }
-
+ size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize));
if (header) {
quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)
@@ -122,6 +134,21 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
return header;
}
+QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize, size_t capacity,
+ AllocationOptions options) Q_DECL_NOTHROW
+{
+ Q_ASSERT(data);
+ Q_ASSERT(data->isMutable());
+ Q_ASSERT(!data->ref.isShared());
+
+ size_t headerSize = sizeof(QArrayData);
+ size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);
+ QArrayData *header = static_cast<QArrayData *>(reallocateData(data, allocSize, options));
+ if (header)
+ header->alloc = capacity;
+ return header;
+}
+
void QArrayData::deallocate(QArrayData *data, size_t objectSize,
size_t alignment) Q_DECL_NOTHROW
{
diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h
index 5a369baf08..bc20932cca 100644
--- a/src/corelib/tools/qarraydata.h
+++ b/src/corelib/tools/qarraydata.h
@@ -115,6 +115,9 @@ struct Q_CORE_EXPORT QArrayData
static QArrayData *allocate(size_t objectSize, size_t alignment,
size_t capacity, AllocationOptions options = Default)
Q_DECL_NOTHROW Q_REQUIRED_RESULT;
+ static QArrayData *reallocateUnaligned(QArrayData *data, size_t objectSize,
+ size_t newCapacity, AllocationOptions newOptions = Default)
+ Q_DECL_NOTHROW Q_REQUIRED_RESULT;
static void deallocate(QArrayData *data, size_t objectSize,
size_t alignment) Q_DECL_NOTHROW;
@@ -222,6 +225,14 @@ struct QTypedArrayData
Q_ALIGNOF(AlignmentDummy), capacity, options));
}
+ static QTypedArrayData *reallocateUnaligned(QTypedArrayData *data, size_t capacity,
+ AllocationOptions options = Default)
+ {
+ Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
+ return static_cast<QTypedArrayData *>(QArrayData::reallocateUnaligned(data, sizeof(T),
+ capacity, options));
+ }
+
static void deallocate(QArrayData *data)
{
Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData));
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 9298472305..7d9c5dc325 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -663,6 +663,20 @@ QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel)
*/
#ifndef QT_NO_COMPRESS
+namespace {
+struct QByteArrayDataDeleter
+{
+ static inline void cleanup(QTypedArrayData<char> *d)
+ { if (d) QTypedArrayData<char>::deallocate(d); }
+};
+}
+
+static QByteArray invalidCompressedData()
+{
+ qWarning("qUncompress: Input data is corrupted");
+ return QByteArray();
+}
+
QByteArray qUncompress(const uchar* data, int nbytes)
{
if (!data) {
@@ -677,53 +691,29 @@ QByteArray qUncompress(const uchar* data, int nbytes)
ulong expectedSize = uint((data[0] << 24) | (data[1] << 16) |
(data[2] << 8) | (data[3] ));
ulong len = qMax(expectedSize, 1ul);
- QScopedPointer<QByteArray::Data, QScopedPointerPodDeleter> d;
+ const ulong maxPossibleSize = MaxAllocSize - sizeof(QByteArray::Data);
+ if (Q_UNLIKELY(len >= maxPossibleSize)) {
+ // QByteArray does not support that huge size anyway.
+ return invalidCompressedData();
+ }
+ QScopedPointer<QByteArray::Data, QByteArrayDataDeleter> d(QByteArray::Data::allocate(expectedSize + 1));
+ if (Q_UNLIKELY(d.data() == nullptr))
+ return invalidCompressedData();
+
+ d->size = expectedSize;
forever {
ulong alloc = len;
- if (len >= (1u << 31u) - sizeof(QByteArray::Data)) {
- //QByteArray does not support that huge size anyway.
- qWarning("qUncompress: Input data is corrupted");
- return QByteArray();
- }
- QByteArray::Data *p = static_cast<QByteArray::Data *>(::realloc(d.data(), sizeof(QByteArray::Data) + alloc + 1));
- if (!p) {
- // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
- qWarning("qUncompress: could not allocate enough memory to uncompress data");
- return QByteArray();
- }
- d.take(); // realloc was successful
- d.reset(p);
- d->offset = sizeof(QByteArrayData);
- d->size = 0; // Shut up valgrind "uninitialized variable" warning
int res = ::uncompress((uchar*)d->data(), &len,
data+4, nbytes-4);
switch (res) {
case Z_OK:
- if (len != alloc) {
- if (len >= (1u << 31u) - sizeof(QByteArray::Data)) {
- //QByteArray does not support that huge size anyway.
- qWarning("qUncompress: Input data is corrupted");
- return QByteArray();
- }
- QByteArray::Data *p = static_cast<QByteArray::Data *>(::realloc(d.data(), sizeof(QByteArray::Data) + len + 1));
- if (!p) {
- // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS
- qWarning("qUncompress: could not allocate enough memory to uncompress data");
- return QByteArray();
- }
- d.take(); // realloc was successful
- d.reset(p);
- }
- d->ref.initializeOwned();
+ Q_ASSERT(len <= alloc);
+ Q_UNUSED(alloc);
d->size = len;
- d->alloc = uint(len) + 1u;
- d->capacityReserved = false;
- d->offset = sizeof(QByteArrayData);
d->data()[len] = 0;
-
{
QByteArrayDataPtr dataPtr = { d.take() };
return QByteArray(dataPtr);
@@ -735,6 +725,17 @@ QByteArray qUncompress(const uchar* data, int nbytes)
case Z_BUF_ERROR:
len *= 2;
+ if (Q_UNLIKELY(len >= maxPossibleSize)) {
+ // QByteArray does not support that huge size anyway.
+ return invalidCompressedData();
+ } else {
+ // grow the block
+ QByteArray::Data *p = QByteArray::Data::reallocateUnaligned(d.data(), len + 1);
+ if (Q_UNLIKELY(p == nullptr))
+ return invalidCompressedData();
+ d.take(); // don't free
+ d.reset(p);
+ }
continue;
case Z_DATA_ERROR:
@@ -1707,19 +1708,8 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options)
Data::deallocate(d);
d = x;
} else {
- size_t blockSize;
- if (options & Data::Grow) {
- auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data));
- blockSize = r.size;
- alloc = uint(r.elementCount);
- } else {
- blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data));
- }
-
- Data *x = static_cast<Data *>(::realloc(d, blockSize));
+ Data *x = Data::reallocateUnaligned(d, alloc, options);
Q_CHECK_PTR(x);
- x->alloc = alloc;
- x->capacityReserved = (options & Data::CapacityReserved) ? 1 : 0;
d = x;
}
}
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index f8611b3e68..ac8054ce82 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -926,7 +926,7 @@ QString QDate::toString(Qt::DateFormat format) const
*/
QString QDate::toString(const QString& format) const
{
- return QLocale::system().toString(*this, format);
+ return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
}
#endif //QT_NO_DATESTRING
@@ -1330,6 +1330,7 @@ QDate QDate::fromString(const QString &string, const QString &format)
QDate date;
#ifndef QT_BOOTSTRAPPED
QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
+ // dt.setDefaultLocale(QLocale::c()); ### Qt 6
if (dt.parseFormat(format))
dt.fromString(string, &date, 0);
#else
@@ -1666,7 +1667,7 @@ QString QTime::toString(Qt::DateFormat format) const
*/
QString QTime::toString(const QString& format) const
{
- return QLocale::system().toString(*this, format);
+ return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
}
#endif //QT_NO_DATESTRING
/*!
@@ -2018,6 +2019,7 @@ QTime QTime::fromString(const QString &string, const QString &format)
QTime time;
#ifndef QT_BOOTSTRAPPED
QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
+ // dt.setDefaultLocale(QLocale::c()); ### Qt 6
if (dt.parseFormat(format))
dt.fromString(string, 0, &time);
#else
@@ -3881,7 +3883,7 @@ QString QDateTime::toString(Qt::DateFormat format) const
*/
QString QDateTime::toString(const QString& format) const
{
- return QLocale::system().toString(*this, format);
+ return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
}
#endif //QT_NO_DATESTRING
@@ -4934,6 +4936,7 @@ QDateTime QDateTime::fromString(const QString &string, const QString &format)
QDate date;
QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
+ // dt.setDefaultLocale(QLocale::c()); ### Qt 6
if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
return QDateTime(date, time);
#else
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 7809c513d6..c25ee5ffbe 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -2024,6 +2024,8 @@ QString QLocale::toString(double i, char f, int prec) const
flags |= QLocaleData::ThousandsGroup;
if (!(d->m_numberOptions & OmitLeadingZeroInExponent))
flags |= QLocaleData::ZeroPadExponent;
+ if (d->m_numberOptions & IncludeTrailingZeroesAfterDot)
+ flags |= QLocaleData::AddTrailingZeroes;
return d->m_data->doubleToString(i, prec, form, -1, flags);
}
@@ -2785,7 +2787,7 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
reinterpret_cast<ushort *>(digits.data())[i] += z;
}
- bool always_show_decpt = (flags & Alternate || flags & ForcePoint);
+ bool always_show_decpt = (flags & ForcePoint);
switch (form) {
case DFExponent: {
num_str = exponentForm(_zero, decimal, exponential, group, plus, minus,
@@ -2800,7 +2802,7 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q
break;
}
case DFSignificantDigits: {
- PrecisionMode mode = (flags & Alternate) ?
+ PrecisionMode mode = (flags & AddTrailingZeroes) ?
PMSignificantDigits : PMChopTrailingZeros;
int cutoff = precision < 0 ? 6 : precision;
@@ -2905,7 +2907,7 @@ QString QLocaleData::longLongToString(const QChar zero, const QChar group,
for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
- if ((flags & Alternate || flags & ShowBase)
+ if ((flags & ShowBase)
&& base == 8
&& (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0')))
num_str.prepend(QLatin1Char('0'));
@@ -2926,10 +2928,10 @@ QString QLocaleData::longLongToString(const QChar zero, const QChar group,
--num_pad_chars;
// leave space for optional '0x' in hex form
- if (base == 16 && (flags & Alternate || flags & ShowBase))
+ if (base == 16 && (flags & ShowBase))
num_pad_chars -= 2;
// leave space for optional '0b' in binary form
- else if (base == 2 && (flags & Alternate || flags & ShowBase))
+ else if (base == 2 && (flags & ShowBase))
num_pad_chars -= 2;
for (int i = 0; i < num_pad_chars; ++i)
@@ -2939,9 +2941,9 @@ QString QLocaleData::longLongToString(const QChar zero, const QChar group,
if (flags & CapitalEorX)
num_str = num_str.toUpper();
- if (base == 16 && (flags & Alternate || flags & ShowBase))
+ if (base == 16 && (flags & ShowBase))
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
- if (base == 2 && (flags & Alternate || flags & ShowBase))
+ if (base == 2 && (flags & ShowBase))
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
// add sign
@@ -2988,7 +2990,7 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0'));
- if ((flags & Alternate || flags & ShowBase)
+ if ((flags & ShowBase)
&& base == 8
&& (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0')))
num_str.prepend(QLatin1Char('0'));
@@ -3003,10 +3005,10 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
int num_pad_chars = width - num_str.length();
// leave space for optional '0x' in hex form
- if (base == 16 && flags & Alternate)
+ if (base == 16 && flags & ShowBase)
num_pad_chars -= 2;
// leave space for optional '0b' in binary form
- else if (base == 2 && flags & Alternate)
+ else if (base == 2 && flags & ShowBase)
num_pad_chars -= 2;
for (int i = 0; i < num_pad_chars; ++i)
@@ -3016,9 +3018,9 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
if (flags & CapitalEorX)
num_str = num_str.toUpper();
- if (base == 16 && (flags & Alternate || flags & ShowBase))
+ if (base == 16 && flags & ShowBase)
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
- else if (base == 2 && (flags & Alternate || flags & ShowBase))
+ else if (base == 2 && flags & ShowBase)
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
// add sign
@@ -3079,25 +3081,37 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOpti
out = in.toLatin1();
else
break;
+ } else if (out == '.') {
+ // Fail if more than one decimal point or point after e
+ if (decpt_idx != -1 || exponent_idx != -1)
+ return false;
+ decpt_idx = idx;
+ } else if (out == 'e' || out == 'E') {
+ exponent_idx = idx;
}
if (number_options & QLocale::RejectLeadingZeroInExponent) {
- if (out == 'e' || out == 'E') {
- exponent_idx = idx;
- } else if (exponent_idx != -1) {
- if (out >= '1' && out <= '9')
- exponent_idx = -1; // leading digit is not 0, forget exponent_idx
- else if (out == '0' && idx < l - 1)
+ if (exponent_idx != -1 && out == '0' && idx < l - 1) {
+ // After the exponent there can only be '+', '-' or digits.
+ // If we find a '0' directly after some non-digit, then that is a leading zero.
+ if (result->last() < '0' || result->last() > '9')
return false;
}
}
+ if (number_options & QLocale::RejectTrailingZeroesAfterDot) {
+ // If we've seen a decimal point and the last character after the exponent is 0, then
+ // that is a trailing zero.
+ if (decpt_idx >= 0 && idx == exponent_idx && result->last() == '0')
+ return false;
+ }
+
if (!(number_options & QLocale::RejectGroupSeparator)) {
if (start_of_digits_idx == -1 && out >= '0' && out <= '9') {
start_of_digits_idx = idx;
} else if (out == ',') {
- // Don't allow group chars after the decimal point
- if (decpt_idx != -1)
+ // Don't allow group chars after the decimal point or exponent
+ if (decpt_idx != -1 || exponent_idx != -1)
return false;
// check distance from the last separator or from the beginning of the digits
@@ -3114,12 +3128,6 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOpti
++idx;
continue;
} else if (out == '.' || out == 'e' || out == 'E') {
- // Fail if more than one decimal point
- if (out == '.' && decpt_idx != -1)
- return false;
- if (decpt_idx == -1)
- decpt_idx = idx;
-
// check distance from the last separator
// ### FIXME: Some locales allow other groupings! See https://en.wikipedia.org/wiki/Thousands_separator
if (last_separator_idx != -1 && idx - last_separator_idx != 4)
@@ -3145,6 +3153,12 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOpti
return false;
}
+ if (number_options & QLocale::RejectTrailingZeroesAfterDot) {
+ // In decimal form, the last character can be a trailing zero if we've seen a decpt.
+ if (decpt_idx != -1 && exponent_idx == -1 && result->last() == '0')
+ return false;
+ }
+
result->append('\0');
return idx == l;
}
diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h
index 657fce9fa1..bd89e48234 100644
--- a/src/corelib/tools/qlocale.h
+++ b/src/corelib/tools/qlocale.h
@@ -897,7 +897,9 @@ public:
OmitGroupSeparator = 0x01,
RejectGroupSeparator = 0x02,
OmitLeadingZeroInExponent = 0x04,
- RejectLeadingZeroInExponent = 0x08
+ RejectLeadingZeroInExponent = 0x08,
+ IncludeTrailingZeroesAfterDot = 0x10,
+ RejectTrailingZeroesAfterDot = 0x20
};
Q_DECLARE_FLAGS(NumberOptions, NumberOption)
diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc
index f4b49095df..88b071e161 100644
--- a/src/corelib/tools/qlocale.qdoc
+++ b/src/corelib/tools/qlocale.qdoc
@@ -969,7 +969,8 @@
setNumberOptions().
\value DefaultNumberOptions This option represents the default behavior, with
- group separators and with one leading zero in single digit exponents.
+ group separators, with one leading zero in single digit exponents, and
+ without trailing zeroes after the decimal dot.
\value OmitGroupSeparator If this option is set, the number-to-string functions
will not insert group separators in their return values. The default
is to insert group separators.
@@ -984,6 +985,14 @@
functions will fail if they encounter an exponent padded with zeroes when
parsing a floating point number in scientific notation. The default is to
accept such padding.
+ \value IncludeTrailingZeroesAfterDot If this option is set, the number-to-string
+ functions will pad numbers with zeroes to the requested precision in "g"
+ or "most concise" mode, even if the number of significant digits is lower
+ than the requested precision. The default is to omit trailing zeroes.
+ \value RejectTrailingZeroesAfterDot If this option is set, the string-to-number
+ functions will fail if they encounter trailing zeroes after the decimal
+ dot when parsing a number in scientific or decimal representation. The
+ default is to accept trailing zeroes.
\sa setNumberOptions(), numberOptions()
*/
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index c83c9d3333..74d8e5f381 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -193,7 +193,7 @@ public:
enum Flags {
NoFlags = 0,
- Alternate = 0x01,
+ AddTrailingZeroes = 0x01,
ZeroPadded = 0x02,
LeftAdjusted = 0x04,
BlankBeforePositive = 0x08,
@@ -204,7 +204,7 @@ public:
ShowBase = 0x80,
UppercaseBase = 0x100,
ZeroPadExponent = 0x200,
- ForcePoint = Alternate
+ ForcePoint = 0x400
};
enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode };
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index bf1bc3e650..942df9e0dd 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -1758,17 +1758,11 @@ void QString::resize(int size, QChar fillChar)
void QString::reallocData(uint alloc, bool grow)
{
- size_t blockSize;
- if (grow) {
- auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data));
- blockSize = r.size;
- alloc = uint(r.elementCount);
- } else {
- blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data));
- }
+ auto allocOptions = d->detachFlags();
+ if (grow)
+ allocOptions |= QArrayData::Grow;
if (d->ref.isShared() || IS_RAW_DATA(d)) {
- Data::AllocationOptions allocOptions(d->capacityReserved ? Data::CapacityReserved : 0);
Data *x = Data::allocate(alloc, allocOptions);
Q_CHECK_PTR(x);
x->size = qMin(int(alloc) - 1, d->size);
@@ -1778,11 +1772,9 @@ void QString::reallocData(uint alloc, bool grow)
Data::deallocate(d);
d = x;
} else {
- Data *p = static_cast<Data *>(::realloc(d, blockSize));
+ Data *p = Data::reallocateUnaligned(d, alloc, allocOptions);
Q_CHECK_PTR(p);
d = p;
- d->alloc = alloc;
- d->offset = sizeof(QStringData);
}
}
@@ -5916,7 +5908,10 @@ static uint parse_flag_characters(const char * &c) Q_DECL_NOTHROW
uint flags = QLocaleData::ZeroPadExponent;
while (true) {
switch (*c) {
- case '#': flags |= QLocaleData::Alternate; break;
+ case '#':
+ flags |= QLocaleData::ShowBase | QLocaleData::AddTrailingZeroes
+ | QLocaleData::ForcePoint;
+ break;
case '0': flags |= QLocaleData::ZeroPadded; break;
case '-': flags |= QLocaleData::LeftAdjusted; break;
case ' ': flags |= QLocaleData::BlankBeforePositive; break;
@@ -6174,7 +6169,7 @@ QString QString::vasprintf(const char *cformat, va_list ap)
case 'p': {
void *arg = va_arg(ap, void*);
const quint64 i = reinterpret_cast<quintptr>(arg);
- flags |= QLocaleData::Alternate;
+ flags |= QLocaleData::ShowBase;
subst = QLocaleData::c()->unsLongLongToString(i, precision, 16, width, flags);
++c;
break;
@@ -7749,10 +7744,13 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha
if (d.locale_occurrences > 0) {
QLocale locale;
- if (!(locale.numberOptions() & QLocale::OmitGroupSeparator))
+ const QLocale::NumberOptions numberOptions = locale.numberOptions();
+ if (!(numberOptions & QLocale::OmitGroupSeparator))
flags |= QLocaleData::ThousandsGroup;
- if (!(locale.numberOptions() & QLocale::OmitLeadingZeroInExponent))
+ if (!(numberOptions & QLocale::OmitLeadingZeroInExponent))
flags |= QLocaleData::ZeroPadExponent;
+ if (numberOptions & QLocale::IncludeTrailingZeroesAfterDot)
+ flags |= QLocaleData::AddTrailingZeroes;
locale_arg = locale.d->m_data->doubleToString(a, prec, form, fieldWidth, flags);
}
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index db118edf04..094f44b2ab 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -137,8 +137,8 @@ static qreal qt_effective_device_pixel_ratio(QWindow *window = 0)
return qApp->devicePixelRatio(); // Don't know which window to target.
}
-QIconPrivate::QIconPrivate()
- : engine(0), ref(1),
+QIconPrivate::QIconPrivate(QIconEngine *e)
+ : engine(e), ref(1),
serialNum(serialNumCounter.fetchAndAddRelaxed(1)),
detach_no(0),
is_mask(false)
@@ -673,9 +673,8 @@ QIcon::QIcon(const QString &fileName)
ownership of the engine.
*/
QIcon::QIcon(QIconEngine *engine)
- :d(new QIconPrivate)
+ :d(new QIconPrivate(engine))
{
- d->engine = engine;
}
/*!
@@ -950,8 +949,7 @@ void QIcon::detach()
d = 0;
return;
} else if (d->ref.load() != 1) {
- QIconPrivate *x = new QIconPrivate;
- x->engine = d->engine->clone();
+ QIconPrivate *x = new QIconPrivate(d->engine->clone());
if (!d->ref.deref())
delete d;
d = x;
@@ -974,10 +972,8 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state)
if (pixmap.isNull())
return;
detach();
- if (!d) {
- d = new QIconPrivate;
- d->engine = new QPixmapIconEngine;
- }
+ if (!d)
+ d = new QIconPrivate(new QPixmapIconEngine);
d->engine->addPixmap(pixmap, mode, state);
}
@@ -1037,8 +1033,7 @@ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State
if (!engine)
engine = iconEngineFromSuffix(fileName, QMimeDatabase().mimeTypeForFile(info).preferredSuffix());
#endif // !QT_NO_MIMETYPE
- d = new QIconPrivate;
- d->engine = engine ? engine : new QPixmapIconEngine;
+ d = new QIconPrivate(engine ? engine : new QPixmapIconEngine);
}
d->engine->addFile(fileName, size, mode, state);
@@ -1240,12 +1235,10 @@ bool QIcon::hasThemeIcon(const QString &name)
*/
void QIcon::setIsMask(bool isMask)
{
- if (!d) {
- d = new QIconPrivate;
- d->engine = new QPixmapIconEngine;
- } else {
+ if (!d)
+ d = new QIconPrivate(new QPixmapIconEngine);
+ else
detach();
- }
d->is_mask = isMask;
}
@@ -1326,22 +1319,17 @@ QDataStream &operator>>(QDataStream &s, QIcon &icon)
QString key;
s >> key;
if (key == QLatin1String("QPixmapIconEngine")) {
- icon.d = new QIconPrivate;
- QIconEngine *engine = new QPixmapIconEngine;
- icon.d->engine = engine;
- engine->read(s);
+ icon.d = new QIconPrivate(new QPixmapIconEngine);
+ icon.d->engine->read(s);
} else if (key == QLatin1String("QIconLoaderEngine")) {
- icon.d = new QIconPrivate;
- QIconEngine *engine = new QIconLoaderEngine();
- icon.d->engine = engine;
- engine->read(s);
+ icon.d = new QIconPrivate(new QIconLoaderEngine());
+ icon.d->engine->read(s);
} else {
const int index = loader()->indexOf(key);
if (index != -1) {
if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(loader()->instance(index))) {
if (QIconEngine *engine= factory->create()) {
- icon.d = new QIconPrivate;
- icon.d->engine = engine;
+ icon.d = new QIconPrivate(engine);
engine->read(s);
} // factory
} // instance
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index a978a72192..aa358e88af 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE
class QIconPrivate
{
public:
- QIconPrivate();
+ explicit QIconPrivate(QIconEngine *e);
~QIconPrivate() {
delete engine;
diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp
index 1a8fc599ce..4f4f543ba8 100644
--- a/src/gui/opengl/qopengl.cpp
+++ b/src/gui/opengl/qopengl.cpp
@@ -42,6 +42,7 @@
#include "qopenglcontext.h"
#include "qopenglfunctions.h"
+#include "qoperatingsystemversion.h"
#include "qoffscreensurface.h"
#include <QtCore/QDebug>
@@ -221,29 +222,25 @@ struct OsTypeTerm
static QString hostOsRelease() {
QString ver;
#ifdef Q_OS_WIN
- switch (QSysInfo::windowsVersion()) {
- case QSysInfo::WV_XP:
- case QSysInfo::WV_2003:
- ver = QStringLiteral("xp");
- break;
- case QSysInfo::WV_VISTA:
- ver = QStringLiteral("vista");
- break;
- case QSysInfo::WV_WINDOWS7:
+ const auto osver = QOperatingSystemVersion::current();
+#define Q_WINVER(major, minor) (major << 8 | minor)
+ switch (Q_WINVER(osver.majorVersion(), osver.minorVersion())) {
+ case Q_WINVER(6, 1):
ver = QStringLiteral("7");
break;
- case QSysInfo::WV_WINDOWS8:
+ case Q_WINVER(6, 2):
ver = QStringLiteral("8");
break;
- case QSysInfo::WV_WINDOWS8_1:
+ case Q_WINVER(6, 3):
ver = QStringLiteral("8.1");
break;
- case QSysInfo::WV_WINDOWS10:
+ case Q_WINVER(10, 0):
ver = QStringLiteral("10");
break;
default:
break;
}
+#undef Q_WINVER
#endif
return ver;
}
diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp
index 61343e5f5a..6f5aff14aa 100644
--- a/src/gui/opengl/qopenglshaderprogram.cpp
+++ b/src/gui/opengl/qopenglshaderprogram.cpp
@@ -162,6 +162,79 @@ QT_BEGIN_NAMESPACE
based on the core feature (requires OpenGL >= 4.3).
*/
+
+// For GLES 3.1/3.2
+#ifndef GL_GEOMETRY_SHADER
+#define GL_GEOMETRY_SHADER 0x8DD9
+#endif
+#ifndef GL_TESS_CONTROL_SHADER
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#endif
+#ifndef GL_TESS_EVALUATION_SHADER
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#endif
+#ifndef GL_COMPUTE_SHADER
+#define GL_COMPUTE_SHADER 0x91B9
+#endif
+#ifndef GL_MAX_GEOMETRY_OUTPUT_VERTICES
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#endif
+#ifndef GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#endif
+#ifndef GL_PATCH_VERTICES
+#define GL_PATCH_VERTICES 0x8E72
+#endif
+#ifndef GL_PATCH_DEFAULT_OUTER_LEVEL
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#endif
+#ifndef GL_PATCH_DEFAULT_INNER_LEVEL
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#endif
+
+static inline bool isFormatGLES(const QSurfaceFormat &f)
+{
+ return (f.renderableType() == QSurfaceFormat::OpenGLES);
+}
+
+static inline bool supportsGeometry(const QSurfaceFormat &f)
+{
+#ifndef QT_OPENGL_ES_2
+ if (!isFormatGLES(f))
+ return (f.version() >= qMakePair<int, int>(3, 2));
+ else
+ return false;
+#else
+ Q_UNUSED(f);
+ return false;
+#endif
+}
+
+static inline bool supportsCompute(const QSurfaceFormat &f)
+{
+#ifndef QT_OPENGL_ES_2
+ if (!isFormatGLES(f))
+ return (f.version() >= qMakePair<int, int>(4, 3));
+ else
+ return (f.version() >= qMakePair<int, int>(3, 1));
+#else
+ return (f.version() >= qMakePair<int, int>(3, 1));
+#endif
+}
+
+static inline bool supportsTessellation(const QSurfaceFormat &f)
+{
+#ifndef QT_OPENGL_ES_2
+ if (!isFormatGLES(f))
+ return (f.version() >= qMakePair<int, int>(4, 0));
+ else
+ return false;
+#else
+ Q_UNUSED(f);
+ return false;
+#endif
+}
+
class QOpenGLShaderPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QOpenGLShader)
@@ -171,22 +244,16 @@ public:
, shaderType(type)
, compiled(false)
, glfuncs(new QOpenGLFunctions(ctx))
-#ifndef QT_OPENGL_ES_2
, supportsGeometryShaders(false)
, supportsTessellationShaders(false)
-#endif
+ , supportsComputeShaders(false)
{
-#ifndef QT_OPENGL_ES_2
- if (!ctx->isOpenGLES()) {
- QSurfaceFormat f = ctx->format();
-
- // Geometry shaders require OpenGL >= 3.2
- if (shaderType & QOpenGLShader::Geometry)
- supportsGeometryShaders = (f.version() >= qMakePair<int, int>(3, 2));
- else if (shaderType & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation))
- supportsTessellationShaders = (f.version() >= qMakePair<int, int>(4, 0));
- }
-#endif
+ if (shaderType & QOpenGLShader::Geometry)
+ supportsGeometryShaders = supportsGeometry(ctx->format());
+ else if (shaderType & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation))
+ supportsTessellationShaders = supportsTessellation(ctx->format());
+ else if (shaderType & QOpenGLShader::Compute)
+ supportsComputeShaders = supportsCompute(ctx->format());
}
~QOpenGLShaderPrivate();
@@ -197,13 +264,13 @@ public:
QOpenGLFunctions *glfuncs;
-#ifndef QT_OPENGL_ES_2
// Support for geometry shaders
bool supportsGeometryShaders;
-
// Support for tessellation shaders
bool supportsTessellationShaders;
-#endif
+ // Support for compute shaders
+ bool supportsComputeShaders;
+
bool create();
bool compile(QOpenGLShader *q);
@@ -232,21 +299,15 @@ bool QOpenGLShaderPrivate::create()
GLuint shader;
if (shaderType == QOpenGLShader::Vertex) {
shader = glfuncs->glCreateShader(GL_VERTEX_SHADER);
-#if defined(QT_OPENGL_3_2)
} else if (shaderType == QOpenGLShader::Geometry && supportsGeometryShaders) {
shader = glfuncs->glCreateShader(GL_GEOMETRY_SHADER);
-#endif
-#if defined(QT_OPENGL_4)
} else if (shaderType == QOpenGLShader::TessellationControl && supportsTessellationShaders) {
shader = glfuncs->glCreateShader(GL_TESS_CONTROL_SHADER);
} else if (shaderType == QOpenGLShader::TessellationEvaluation && supportsTessellationShaders) {
shader = glfuncs->glCreateShader(GL_TESS_EVALUATION_SHADER);
-#endif
-#if defined(QT_OPENGL_4_3)
- } else if (shaderType == QOpenGLShader::Compute) {
+ } else if (shaderType == QOpenGLShader::Compute && supportsComputeShaders) {
shader = glfuncs->glCreateShader(GL_COMPUTE_SHADER);
-#endif
- } else {
+ } else if (shaderType == QOpenGLShader::Fragment) {
shader = glfuncs->glCreateShader(GL_FRAGMENT_SHADER);
}
if (!shader) {
@@ -3219,10 +3280,8 @@ void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4
int QOpenGLShaderProgram::maxGeometryOutputVertices() const
{
GLint n = 0;
-#if defined(QT_OPENGL_3_2)
Q_D(const QOpenGLShaderProgram);
d->glfuncs->glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &n);
-#endif
return n;
}
@@ -3246,7 +3305,7 @@ int QOpenGLShaderProgram::maxGeometryOutputVertices() const
*/
void QOpenGLShaderProgram::setPatchVertexCount(int count)
{
-#if defined(QT_OPENGL_4)
+#ifndef QT_OPENGL_ES_2
Q_D(QOpenGLShaderProgram);
if (d->tessellationFuncs)
d->tessellationFuncs->glPatchParameteri(GL_PATCH_VERTICES, count);
@@ -3265,13 +3324,15 @@ void QOpenGLShaderProgram::setPatchVertexCount(int count)
*/
int QOpenGLShaderProgram::patchVertexCount() const
{
+#ifndef QT_OPENGL_ES_2
int patchVertices = 0;
-#if defined(QT_OPENGL_4)
Q_D(const QOpenGLShaderProgram);
if (d->tessellationFuncs)
d->tessellationFuncs->glGetIntegerv(GL_PATCH_VERTICES, &patchVertices);
-#endif
return patchVertices;
+#else
+ return 0;
+#endif
}
/*!
@@ -3293,21 +3354,21 @@ int QOpenGLShaderProgram::patchVertexCount() const
*/
void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QVector<float> &levels)
{
-#if defined(QT_OPENGL_4)
- QVector<float> tessLevels = levels;
-
- // Ensure we have the required 4 outer tessellation levels
- // Use default of 1 for missing entries (same as spec)
- const int argCount = 4;
- if (tessLevels.size() < argCount) {
- tessLevels.reserve(argCount);
- for (int i = tessLevels.size(); i < argCount; ++i)
- tessLevels.append(1.0f);
- }
-
+#ifndef QT_OPENGL_ES_2
Q_D(QOpenGLShaderProgram);
- if (d->tessellationFuncs)
+ if (d->tessellationFuncs) {
+ QVector<float> tessLevels = levels;
+
+ // Ensure we have the required 4 outer tessellation levels
+ // Use default of 1 for missing entries (same as spec)
+ const int argCount = 4;
+ if (tessLevels.size() < argCount) {
+ tessLevels.reserve(argCount);
+ for (int i = tessLevels.size(); i < argCount; ++i)
+ tessLevels.append(1.0f);
+ }
d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, tessLevels.data());
+ }
#else
Q_UNUSED(levels);
#endif
@@ -3330,13 +3391,15 @@ void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QVector<float
*/
QVector<float> QOpenGLShaderProgram::defaultOuterTessellationLevels() const
{
+#ifndef QT_OPENGL_ES_2
QVector<float> tessLevels(4, 1.0f);
-#if defined(QT_OPENGL_4)
Q_D(const QOpenGLShaderProgram);
if (d->tessellationFuncs)
d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_OUTER_LEVEL, tessLevels.data());
-#endif
return tessLevels;
+#else
+ return QVector<float>();
+#endif
}
/*!
@@ -3358,21 +3421,21 @@ QVector<float> QOpenGLShaderProgram::defaultOuterTessellationLevels() const
*/
void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QVector<float> &levels)
{
-#if defined(QT_OPENGL_4)
- QVector<float> tessLevels = levels;
-
- // Ensure we have the required 2 inner tessellation levels
- // Use default of 1 for missing entries (same as spec)
- const int argCount = 2;
- if (tessLevels.size() < argCount) {
- tessLevels.reserve(argCount);
- for (int i = tessLevels.size(); i < argCount; ++i)
- tessLevels.append(1.0f);
- }
-
+#ifndef QT_OPENGL_ES_2
Q_D(QOpenGLShaderProgram);
- if (d->tessellationFuncs)
+ if (d->tessellationFuncs) {
+ QVector<float> tessLevels = levels;
+
+ // Ensure we have the required 2 inner tessellation levels
+ // Use default of 1 for missing entries (same as spec)
+ const int argCount = 2;
+ if (tessLevels.size() < argCount) {
+ tessLevels.reserve(argCount);
+ for (int i = tessLevels.size(); i < argCount; ++i)
+ tessLevels.append(1.0f);
+ }
d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, tessLevels.data());
+ }
#else
Q_UNUSED(levels);
#endif
@@ -3395,13 +3458,15 @@ void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QVector<float
*/
QVector<float> QOpenGLShaderProgram::defaultInnerTessellationLevels() const
{
+#ifndef QT_OPENGL_ES_2
QVector<float> tessLevels(2, 1.0f);
-#if defined(QT_OPENGL_4)
Q_D(const QOpenGLShaderProgram);
if (d->tessellationFuncs)
d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_INNER_LEVEL, tessLevels.data());
-#endif
return tessLevels;
+#else
+ return QVector<float>();
+#endif
}
@@ -3414,16 +3479,11 @@ QVector<float> QOpenGLShaderProgram::defaultInnerTessellationLevels() const
*/
bool QOpenGLShaderProgram::hasOpenGLShaderPrograms(QOpenGLContext *context)
{
-#if !defined(QT_OPENGL_ES_2)
if (!context)
context = QOpenGLContext::currentContext();
if (!context)
return false;
return QOpenGLFunctions(context).hasOpenGLFeature(QOpenGLFunctions::Shaders);
-#else
- Q_UNUSED(context);
- return true;
-#endif
}
/*!
@@ -3454,33 +3514,12 @@ bool QOpenGLShader::hasOpenGLShaders(ShaderType type, QOpenGLContext *context)
if ((type & ~(Geometry | Vertex | Fragment | TessellationControl | TessellationEvaluation | Compute)) || type == 0)
return false;
- QSurfaceFormat format = context->format();
- if (type == Geometry) {
-#ifndef QT_OPENGL_ES_2
- // Geometry shaders require OpenGL 3.2 or newer
- QSurfaceFormat format = context->format();
- return (!context->isOpenGLES())
- && (format.version() >= qMakePair<int, int>(3, 2));
-#else
- // No geometry shader support in OpenGL ES2
- return false;
-#endif
- } else if (type == TessellationControl || type == TessellationEvaluation) {
-#if !defined(QT_OPENGL_ES_2)
- return (!context->isOpenGLES())
- && (format.version() >= qMakePair<int, int>(4, 0));
-#else
- // No tessellation shader support in OpenGL ES2
- return false;
-#endif
- } else if (type == Compute) {
-#if defined(QT_OPENGL_4_3)
- return (format.version() >= qMakePair<int, int>(4, 3));
-#else
- // No compute shader support without OpenGL 4.3 or newer
- return false;
-#endif
- }
+ if (type & QOpenGLShader::Geometry)
+ return supportsGeometry(context->format());
+ else if (type & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation))
+ return supportsTessellation(context->format());
+ else if (type & QOpenGLShader::Compute)
+ return supportsCompute(context->format());
// Unconditional support of vertex and fragment shaders implicitly assumes
// a minimum OpenGL version of 2.0
diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm
index 6af12c19d8..a29d60ca6e 100644
--- a/src/gui/painting/qcoregraphics.mm
+++ b/src/gui/painting/qcoregraphics.mm
@@ -39,6 +39,7 @@
#include <QtGui/private/qpaintengine_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qcoreapplication.h>
+#include <QtCore/qoperatingsystemversion.h>
QT_BEGIN_NAMESPACE
@@ -119,7 +120,7 @@ QT_END_NAMESPACE
+ (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState
{
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_NA)
- if (QT_PREPEND_NAMESPACE(QSysInfo::MacintoshVersion) >= QT_PREPEND_NAMESPACE(QSysInfo::MV_10_10))
+ if (QT_PREPEND_NAMESPACE(QOperatingSystemVersion::current()) >= QT_PREPEND_NAMESPACE(QOperatingSystemVersion::OSXYosemite))
return [self graphicsContextWithCGContext:graphicsPort flipped:initialFlippedState];
#endif
return [self graphicsContextWithGraphicsPort:graphicsPort flipped:initialFlippedState];
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 085c073bb1..c9747877f7 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -198,8 +198,15 @@ bool QDesktopServices::openUrl(const QUrl &url)
return false;
QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
- if (!platformIntegration)
+ if (Q_UNLIKELY(!platformIntegration)) {
+ QCoreApplication *application = QCoreApplication::instance();
+ if (Q_UNLIKELY(!application))
+ qWarning("QDesktopServices::openUrl: Please instantiate the QGuiApplication object "
+ "first");
+ else if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(application)))
+ qWarning("QDesktopServices::openUrl: Application is not a GUI application");
return false;
+ }
QPlatformServices *platformServices = platformIntegration->services();
if (!platformServices) {
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index 24ada3a81f..612abb9044 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -299,6 +299,11 @@ void QHttpNetworkReply::setSpdyWasUsed(bool spdy)
d_func()->spdyUsed = spdy;
}
+qint64 QHttpNetworkReply::removedContentLength() const
+{
+ return d_func()->removedContentLength;
+}
+
bool QHttpNetworkReply::isRedirecting() const
{
return d_func()->isRedirecting();
@@ -326,6 +331,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
currentlyReceivedDataInWindow(0),
currentlyUploadedDataInWindow(0),
totallyUploadedData(0),
+ removedContentLength(-1),
connection(0),
autoDecompress(false), responseData(), requestIsPrepared(false)
,pipeliningUsed(false), spdyUsed(false), downstreamLimited(false)
@@ -398,12 +404,12 @@ void QHttpNetworkReplyPrivate::removeAutoDecompressHeader()
end = fields.end();
while (it != end) {
if (qstricmp(name.constData(), it->first.constData()) == 0) {
+ removedContentLength = strtoull(it->second.constData(), nullptr, 0);
fields.erase(it);
break;
}
++it;
}
-
}
bool QHttpNetworkReplyPrivate::findChallenge(bool forProxy, QByteArray &challenge) const
diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h
index f3b007f594..faab03f056 100644
--- a/src/network/access/qhttpnetworkreply_p.h
+++ b/src/network/access/qhttpnetworkreply_p.h
@@ -139,6 +139,7 @@ public:
bool isPipeliningUsed() const;
bool isSpdyUsed() const;
void setSpdyWasUsed(bool spdy);
+ qint64 removedContentLength() const;
bool isRedirecting() const;
@@ -255,6 +256,7 @@ public:
qint32 currentlyReceivedDataInWindow; // only for SPDY
qint32 currentlyUploadedDataInWindow; // only for SPDY
qint64 totallyUploadedData; // only for SPDY
+ qint64 removedContentLength;
QPointer<QHttpNetworkConnection> connection;
QPointer<QHttpNetworkConnectionChannel> connectionChannel;
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 1dca7f02fb..e71911cec2 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -234,6 +234,7 @@ QHttpThreadDelegate::QHttpThreadDelegate(QObject *parent) :
, isPipeliningUsed(false)
, isSpdyUsed(false)
, incomingContentLength(-1)
+ , removedContentLength(-1)
, incomingErrorCode(QNetworkReply::NoError)
, downloadBuffer()
, httpConnection(0)
@@ -623,6 +624,7 @@ void QHttpThreadDelegate::headerChangedSlot()
incomingReasonPhrase = httpReply->reasonPhrase();
isPipeliningUsed = httpReply->isPipeliningUsed();
incomingContentLength = httpReply->contentLength();
+ removedContentLength = httpReply->removedContentLength();
isSpdyUsed = httpReply->isSpdyUsed();
emit downloadMetaData(incomingHeaders,
@@ -631,6 +633,7 @@ void QHttpThreadDelegate::headerChangedSlot()
isPipeliningUsed,
downloadBuffer,
incomingContentLength,
+ removedContentLength,
isSpdyUsed);
}
diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h
index 64c58cf648..6d1ea11f29 100644
--- a/src/network/access/qhttpthreaddelegate_p.h
+++ b/src/network/access/qhttpthreaddelegate_p.h
@@ -112,6 +112,7 @@ public:
bool isPipeliningUsed;
bool isSpdyUsed;
qint64 incomingContentLength;
+ qint64 removedContentLength;
QNetworkReply::NetworkError incomingErrorCode;
QString incomingErrorDetail;
#ifndef QT_NO_BEARERMANAGEMENT
@@ -141,7 +142,7 @@ signals:
void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *);
#endif
void downloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &, bool,
- QSharedPointer<char>, qint64, bool);
+ QSharedPointer<char>, qint64, qint64, bool);
void downloadProgress(qint64, qint64);
void downloadData(const QByteArray &);
void error(QNetworkReply::NetworkError, const QString &);
diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h
index 7f39c942a3..4b5422ce29 100644
--- a/src/network/access/qnetworkaccessbackend_p.h
+++ b/src/network/access/qnetworkaccessbackend_p.h
@@ -63,7 +63,6 @@ class QNetworkProxyQuery;
class QNetworkRequest;
class QStringList;
class QUrl;
-class QUrlInfo;
class QSslConfiguration;
class QNetworkAccessManagerPrivate;
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index b5e44fa29a..f70f11d384 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -805,10 +805,11 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
Qt::QueuedConnection);
QObject::connect(delegate, SIGNAL(downloadMetaData(QList<QPair<QByteArray,QByteArray> >,
int, QString, bool,
- QSharedPointer<char>, qint64, bool)),
+ QSharedPointer<char>, qint64, qint64,
+ bool)),
q, SLOT(replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,
int, QString, bool,
- QSharedPointer<char>, qint64, bool)),
+ QSharedPointer<char>, qint64, qint64, bool)),
Qt::QueuedConnection);
QObject::connect(delegate, SIGNAL(downloadProgress(qint64,qint64)),
q, SLOT(replyDownloadProgressSlot(qint64,qint64)),
@@ -913,6 +914,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
delegate->isPipeliningUsed,
QSharedPointer<char>(),
delegate->incomingContentLength,
+ delegate->removedContentLength,
delegate->isSpdyUsed);
replyDownloadData(delegate->synchronousDownloadData);
httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail);
@@ -924,6 +926,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
delegate->isPipeliningUsed,
QSharedPointer<char>(),
delegate->incomingContentLength,
+ delegate->removedContentLength,
delegate->isSpdyUsed);
replyDownloadData(delegate->synchronousDownloadData);
}
@@ -1151,7 +1154,9 @@ void QNetworkReplyHttpImplPrivate::checkForRedirect(const int statusCode)
void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &hm,
int sc, const QString &rp, bool pu,
QSharedPointer<char> db,
- qint64 contentLength, bool spdyWasUsed)
+ qint64 contentLength,
+ qint64 removedContentLength,
+ bool spdyWasUsed)
{
Q_Q(QNetworkReplyHttpImpl);
Q_UNUSED(contentLength);
@@ -1197,6 +1202,8 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByte
q->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode);
q->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase);
+ if (removedContentLength != -1)
+ q->setAttribute(QNetworkRequest::OriginalContentLengthAttribute, removedContentLength);
// is it a redirection?
if (!isHttpRedirectResponse())
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 868fa617b6..255c23006e 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -114,7 +114,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void replyFinished())
Q_PRIVATE_SLOT(d_func(), void replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,
int, QString, bool, QSharedPointer<char>,
- qint64, bool))
+ qint64, qint64, bool))
Q_PRIVATE_SLOT(d_func(), void replyDownloadProgressSlot(qint64,qint64))
Q_PRIVATE_SLOT(d_func(), void httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *))
Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &))
@@ -280,7 +280,7 @@ public:
void replyDownloadData(QByteArray);
void replyFinished();
void replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &,
- bool, QSharedPointer<char>, qint64, bool);
+ bool, QSharedPointer<char>, qint64, qint64, bool);
void replyDownloadProgressSlot(qint64,qint64);
void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth);
void httpError(QNetworkReply::NetworkError error, const QString &errorString);
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index 29362b81e2..bc2507ca51 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -282,6 +282,13 @@ QT_BEGIN_NAMESPACE
that is redirecting from "https" to "http" protocol, are not allowed.
(This value was introduced in 5.6.)
+ \value OriginalContentLengthAttribute
+ Replies only, type QMetaType::Int
+ Holds the original content-length attribute before being invalidated and
+ removed from the header when the data is compressed and the request was
+ marked to be decompressed automatically.
+ (This value was introduced in 5.9.)
+
\value User
Special type. Additional information can be passed in
QVariants with types ranging from User to UserMax. The default
diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h
index ad8f5bddd9..9a3a7f0fb5 100644
--- a/src/network/access/qnetworkrequest.h
+++ b/src/network/access/qnetworkrequest.h
@@ -91,6 +91,7 @@ public:
FollowRedirectsAttribute,
HTTP2AllowedAttribute,
HTTP2WasUsedAttribute,
+ OriginalContentLengthAttribute,
User = 1000,
UserMax = 32767
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri
index 8f37e28669..7ef387beb4 100644
--- a/src/network/kernel/kernel.pri
+++ b/src/network/kernel/kernel.pri
@@ -57,8 +57,7 @@ win32: {
mac {
LIBS_PRIVATE += -framework CoreFoundation
- !uikit: LIBS_PRIVATE += -framework CoreServices
- !if(watchos:CONFIG(device, simulator|device)): LIBS_PRIVATE += -framework SystemConfiguration
+ !uikit: LIBS_PRIVATE += -framework CoreServices -framework SystemConfiguration
}
osx:SOURCES += kernel/qnetworkproxy_mac.cpp
diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp
index f5dc9fcdcd..ca65f8a015 100644
--- a/src/network/ssl/qsslsocket_winrt.cpp
+++ b/src/network/ssl/qsslsocket_winrt.cpp
@@ -181,13 +181,7 @@ long QSslSocketPrivate::sslLibraryVersionNumber()
QString QSslSocketPrivate::sslLibraryVersionString()
{
- switch (QSysInfo::windowsVersion()) {
- case QSysInfo::WV_WINDOWS8_1:
- return QStringLiteral("Windows Runtime 8.1 SSL library");
- default:
- break;
- }
- return QStringLiteral("Windows Runtime SSL library");
+ return QStringLiteral("Windows Runtime, ") + QSysInfo::prettyProductName();
}
long QSslSocketPrivate::sslLibraryBuildVersionNumber()
diff --git a/src/platformsupport/fontdatabases/fontdatabases.pri b/src/platformsupport/fontdatabases/fontdatabases.pri
index f8e51f2a6d..1ea7f42204 100644
--- a/src/platformsupport/fontdatabases/fontdatabases.pri
+++ b/src/platformsupport/fontdatabases/fontdatabases.pri
@@ -1,4 +1,4 @@
-darwin:!if(watchos:CONFIG(simulator, simulator|device)) {
+darwin {
include($$PWD/mac/coretext.pri)
} else {
!win32|qtConfig(freetype) {
diff --git a/src/platformsupport/fontdatabases/mac/coretext.pri b/src/platformsupport/fontdatabases/mac/coretext.pri
index 4d19a59226..e1132cfcbe 100644
--- a/src/platformsupport/fontdatabases/mac/coretext.pri
+++ b/src/platformsupport/fontdatabases/mac/coretext.pri
@@ -14,3 +14,13 @@ else: \
# On Mac OS they are part of the ApplicationServices umbrella framework,
# even in 10.8 where they were also made available stand-alone.
LIBS_PRIVATE += -framework ApplicationServices
+
+# CoreText is documented to be available on watchOS, but the headers aren't present
+# in the watchOS Simulator SDK like they are supposed to be. Work around the problem
+# by adding the device SDK's headers to the search path as a fallback.
+# rdar://25314492, rdar://27844864
+watchos:CONFIG(simulator, simulator|device) {
+ QMAKE_CXXFLAGS += \
+ -F$$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks \
+ -F$$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks
+}
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm
index 7d11023b78..de4fa95530 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.mm
+++ b/src/plugins/platforms/cocoa/qcocoadrag.mm
@@ -132,7 +132,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
QPixmap pm = dragPixmap(m_drag, hotSpot);
QSize pmDeviceIndependentSize = pm.size() / pm.devicePixelRatio();
NSImage *nsimage = qt_mac_create_nsimage(pm);
- [nsimage setSize:pmDeviceIndependentSize.toCGSize()];
+ [nsimage setSize:NSSizeFromCGSize(pmDeviceIndependentSize.toCGSize())];
QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacInternalPasteboardMime::MIME_DND);
m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy"));
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 0375dd85f2..c0055852c2 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -62,6 +62,7 @@
#include <stdlib.h>
#include <qabstracteventdispatcher.h>
#include <qsysinfo.h>
+#include <qoperatingsystemversion.h>
#include <qglobal.h>
#include <QDir>
@@ -163,7 +164,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate);
[mSavePanel setDelegate:self];
#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_11)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_11)
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXElCapitan)
mOpenPanel.accessoryViewDisclosed = YES;
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index b2fd0580bc..87a0991098 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -514,7 +514,7 @@ QRect QCocoaWindow::geometry() const
NSRect screenRect = [[m_contentView window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
NSPoint screenPoint = screenRect.origin;
QPoint position = qt_mac_flipPoint(screenPoint).toPoint();
- QSize size = QRectF::fromCGRect([m_contentView bounds]).toRect().size();
+ QSize size = QRectF::fromCGRect(NSRectToCGRect([m_contentView bounds])).toRect().size();
return QRect(position, size);
}
@@ -1117,7 +1117,7 @@ void QCocoaWindow::propagateSizeHints()
QSize sizeIncrement = windowSizeIncrement();
if (sizeIncrement.isEmpty())
sizeIncrement = QSize(1, 1);
- [m_nsWindow setResizeIncrements:sizeIncrement.toCGSize()];
+ [m_nsWindow setResizeIncrements:NSSizeFromCGSize(sizeIncrement.toCGSize())];
QRect rect = geometry();
QSize baseSize = windowBaseSize();
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 8d3b970158..ee0bf75606 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -340,10 +340,10 @@ static bool _q_dontOverrideCtrlLMB = false;
geometry = QRect(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height);
} else if (m_platformWindow->m_contentViewIsToBeEmbedded) {
// embedded child window, use the frame rect ### merge with case below
- geometry = QRectF::fromCGRect([self bounds]).toRect();
+ geometry = QRectF::fromCGRect(NSRectToCGRect([self bounds])).toRect();
} else {
// child window, use the frame rect
- geometry = QRectF::fromCGRect([self frame]).toRect();
+ geometry = QRectF::fromCGRect(NSRectToCGRect([self frame])).toRect();
}
if (m_platformWindow->m_nsWindow && geometry == m_platformWindow->geometry())
@@ -557,7 +557,7 @@ static bool _q_dontOverrideCtrlLMB = false;
- (void) drawRect:(NSRect)dirtyRect
{
- qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:]" << m_window << QRectF::fromCGRect(dirtyRect);
+ qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:]" << m_window << QRectF::fromCGRect(NSRectToCGRect(dirtyRect));
#ifndef QT_NO_OPENGL
if (m_glContext && m_shouldSetGLContextinDrawRect) {
@@ -1347,7 +1347,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
- (bool)handleGestureAsBeginEnd:(NSEvent *)event
{
- if (QSysInfo::QSysInfo::MacintoshVersion < QSysInfo::MV_10_11)
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXElCapitan)
return false;
if ([event phase] == NSEventPhaseBegan) {
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 94dd643116..9799e29cf2 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -60,6 +60,7 @@
#include <QtPlatformSupport/private/qcoretextfontdatabase_p.h>
#include <QtPlatformSupport/private/qmacmime_p.h>
#include <QDir>
+#include <QOperatingSystemVersion>
#import <AudioToolbox/AudioServices.h>
@@ -117,7 +118,7 @@ QIOSIntegration::QIOSIntegration()
m_touchDevice = new QTouchDevice;
m_touchDevice->setType(QTouchDevice::TouchScreen);
QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition;
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_9_0) {
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)) {
if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
touchCapabilities |= QTouchDevice::Pressure;
}
diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm
index 50d5442f17..4f0c667861 100644
--- a/src/plugins/platforms/ios/qiosmessagedialog.mm
+++ b/src/plugins/platforms/ios/qiosmessagedialog.mm
@@ -39,6 +39,7 @@
#import <UIKit/UIKit.h>
+#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qwindow.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformtheme.h>
@@ -109,7 +110,7 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win
if (m_alertController // Ensure that the dialog is not showing already
|| !options() // Some message dialogs don't have options (QErrorMessage)
|| windowModality == Qt::NonModal // We can only do modal dialogs
- || QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_8_0) // API limitation
+ || QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) // API limitation
return false;
m_alertController = [[UIAlertController
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index 013061a6d2..86bce0d70b 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -45,6 +45,7 @@
#include "qiosapplicationdelegate.h"
#include "qiosviewcontroller.h"
#include "quiview.h"
+#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/private/qwindow_p.h>
#include <private/qcoregraphics_p.h>
@@ -274,7 +275,7 @@ void QIOSScreen::updateProperties()
if (m_uiScreen == [UIScreen mainScreen]) {
Qt::ScreenOrientation statusBarOrientation = toQtScreenOrientation(UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation));
- if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_8_0) {
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) {
// On iOS < 8.0 the UIScreen geometry is always in portait, and the system applies
// the screen rotation to the root view-controller's view instead of directly to the
// screen, like iOS 8 and above does.
@@ -302,7 +303,7 @@ void QIOSScreen::updateProperties()
if (m_geometry != previousGeometry) {
QRectF physicalGeometry;
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) {
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) {
// We can't use the primaryOrientation of screen(), as we haven't reported the new geometry yet
Qt::ScreenOrientation primaryOrientation = m_geometry.width() >= m_geometry.height() ?
Qt::LandscapeOrientation : Qt::PortraitOrientation;
@@ -407,7 +408,7 @@ Qt::ScreenOrientation QIOSScreen::nativeOrientation() const
{
CGRect nativeBounds =
#if !defined(Q_OS_TVOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0)
- QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0 ? m_uiScreen.nativeBounds :
+ QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8) ? m_uiScreen.nativeBounds :
#endif
m_uiScreen.bounds;
diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm
index 9d73a296fa..462da0a978 100644
--- a/src/plugins/platforms/ios/qiostextinputoverlay.mm
+++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm
@@ -219,7 +219,7 @@ static void executeBlockWithoutAnimation(Block block)
borderLayer.borderColor = [[UIColor lightGrayColor] CGColor];
[self addSublayer:borderLayer];
- if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0) {
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 7)) {
// [UIView snapshotViewAfterScreenUpdates:] is available since iOS 7.0.
// Just silently ignore showing the loupe for older versions.
self.hidden = YES;
@@ -267,7 +267,7 @@ static void executeBlockWithoutAnimation(Block block)
- (void)display
{
- if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0)
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 7))
return;
// Take a snapshow of the target view, magnify the area around the focal
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 5c493617b1..25bfa2ad90 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -48,6 +48,7 @@
#include "qiosmenu.h"
#endif
+#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qwindow_p.h>
#include <qpa/qwindowsysteminterface_p.h>
@@ -298,7 +299,7 @@
QTouchDevice *touchDevice = QIOSIntegration::instance()->touchDevice();
QTouchDevice::Capabilities touchCapabilities = touchDevice->capabilities();
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_9_0) {
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)) {
if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
touchCapabilities |= QTouchDevice::Pressure;
else
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
index ff115a2249..5d4afe8fb2 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
@@ -1053,11 +1053,24 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BS
return S_FALSE;
}
-HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR value)
{
QAccessibleInterface *accessible = accessibleInterface();
accessibleDebugClientCalls(accessible);
- return DISP_E_MEMBERNOTFOUND;
+
+ if (!accessible || !accessible->isValid()) {
+ return E_FAIL;
+ }
+
+ QString qstrValue = QString::fromWCharArray(value);
+
+ if (accessible->valueInterface()) {
+ accessible->valueInterface()->setCurrentValue(qstrValue);
+ } else {
+ accessible->setText(QAccessible::Value, qstrValue);
+ }
+
+ return S_OK;
}
// moz: [important]
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index d4cdf3ef3c..10d38f2a0c 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -68,6 +68,7 @@
#include <QtCore/QHash>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
+#include <QtCore/QOperatingSystemVersion>
#include <QtCore/QSysInfo>
#include <QtCore/QScopedArrayPointer>
#include <QtCore/private/qsystemlibrary_p.h>
@@ -186,7 +187,7 @@ QWindowsShcoreDLL::QWindowsShcoreDLL()
void QWindowsShcoreDLL::init()
{
- if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS8_1)
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1)
return;
QSystemLibrary library(QStringLiteral("SHCore"));
getProcessDpiAwareness = (GetProcessDpiAwareness)library.resolve("GetProcessDpiAwareness");
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 26a5131927..9519b509bc 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -190,6 +190,20 @@ static inline Qt::KeyboardModifiers toQtKeyboardModifiers(DWORD keyState)
return modifiers;
}
+static inline Qt::MouseButtons toQtMouseButtons(DWORD keyState)
+{
+ Qt::MouseButtons buttons = Qt::NoButton;
+
+ if (keyState & MK_LBUTTON)
+ buttons |= Qt::LeftButton;
+ if (keyState & MK_RBUTTON)
+ buttons |= Qt::RightButton;
+ if (keyState & MK_MBUTTON)
+ buttons |= Qt::MidButton;
+
+ return buttons;
+}
+
/*!
\class QWindowsOleDropSource
\brief Implementation of IDropSource
@@ -405,16 +419,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
break;
}
- // grfKeyState is broken on CE & some Windows XP versions,
- // therefore we need to check the state manually
- if ((GetAsyncKeyState(VK_LBUTTON) == 0)
- && (GetAsyncKeyState(VK_MBUTTON) == 0)
- && (GetAsyncKeyState(VK_RBUTTON) == 0)) {
- hr = ResultFromScode(DRAGDROP_S_DROP);
- break;
- }
-
- const Qt::MouseButtons buttons = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState);
+ const Qt::MouseButtons buttons = toQtMouseButtons(grfKeyState);
if (m_currentButtons == Qt::NoButton) {
m_currentButtons = buttons;
} else {
@@ -538,7 +543,7 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState,
QWindowsDrag *windowsDrag = QWindowsDrag::instance();
const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect);
QGuiApplicationPrivate::modifier_buttons = toQtKeyboardModifiers(grfKeyState);
- QGuiApplicationPrivate::mouse_buttons = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState);
+ QGuiApplicationPrivate::mouse_buttons = toQtMouseButtons(grfKeyState);
const QPlatformDragQtResponse response =
QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(), m_lastPoint, actions);
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index d577d46b96..d1d7be123d 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -130,7 +130,7 @@ typedef struct qt_xcb_ge_event_t {
static inline bool isXIEvent(xcb_generic_event_t *event, int opCode)
{
- qt_xcb_ge_event_t *e = (qt_xcb_ge_event_t *)event;
+ qt_xcb_ge_event_t *e = reinterpret_cast<qt_xcb_ge_event_t *>(event);
return e->extension == opCode;
}
@@ -249,7 +249,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
// Find a fake screen
const auto scrs = virtualDesktop->screens();
for (QPlatformScreen *scr : scrs) {
- QXcbScreen *xcbScreen = (QXcbScreen *)scr;
+ QXcbScreen *xcbScreen = static_cast<QXcbScreen *>(scr);
if (xcbScreen->output() == XCB_NONE) {
screen = xcbScreen;
break;
@@ -375,7 +375,7 @@ void QXcbConnection::destroyScreen(QXcbScreen *screen)
// When primary screen is removed, set the new primary screen
// which belongs to the primary virtual desktop.
if (screen->isPrimary()) {
- QXcbScreen *newPrimary = (QXcbScreen *)virtualDesktop->screens().at(0);
+ QXcbScreen *newPrimary = static_cast<QXcbScreen *>(virtualDesktop->screens().at(0));
newPrimary->setPrimary(true);
const int idx = m_screens.indexOf(newPrimary);
if (idx > 0)
@@ -709,7 +709,7 @@ QXcbConnection::~QXcbConnection()
delete m_glIntegration;
#ifdef XCB_USE_XLIB
- XCloseDisplay((Display *)m_xlib_display);
+ XCloseDisplay(static_cast<Display *>(m_xlib_display));
#else
xcb_disconnect(xcb_connection());
#endif
@@ -752,7 +752,7 @@ QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id)
#define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \
{ \
- event_t *e = (event_t *)event; \
+ event_t *e = reinterpret_cast<event_t *>(event); \
if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->windowMember)) { \
handled = eventListener->handleGenericEvent(event, &result); \
if (!handled) \
@@ -763,7 +763,7 @@ break;
#define HANDLE_KEYBOARD_EVENT(event_t, handler) \
{ \
- event_t *e = (event_t *)event; \
+ event_t *e = reinterpret_cast<event_t *>(event); \
if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \
handled = eventListener->handleGenericEvent(event, &result); \
if (!handled) \
@@ -1182,11 +1182,11 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state);
HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
case XCB_MAPPING_NOTIFY:
- m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
+ m_keyboard->handleMappingNotifyEvent(reinterpret_cast<xcb_mapping_notify_event_t *>(event));
break;
case XCB_SELECTION_REQUEST:
{
- xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event;
+ xcb_selection_request_event_t *sr = reinterpret_cast<xcb_selection_request_event_t *>(event);
#ifndef QT_NO_DRAGANDDROP
if (sr->selection == atom(QXcbAtom::XdndSelection))
m_drag->handleSelectionRequest(sr);
@@ -1200,19 +1200,19 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
break;
}
case XCB_SELECTION_CLEAR:
- setTime(((xcb_selection_clear_event_t *)event)->time);
+ setTime((reinterpret_cast<xcb_selection_clear_event_t *>(event))->time);
#ifndef QT_NO_CLIPBOARD
- m_clipboard->handleSelectionClearRequest((xcb_selection_clear_event_t *)event);
+ m_clipboard->handleSelectionClearRequest(reinterpret_cast<xcb_selection_clear_event_t *>(event));
#endif
handled = true;
break;
case XCB_SELECTION_NOTIFY:
- setTime(((xcb_selection_notify_event_t *)event)->time);
+ setTime((reinterpret_cast<xcb_selection_notify_event_t *>(event))->time);
handled = false;
break;
case XCB_PROPERTY_NOTIFY:
{
- xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event;
+ xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event);
if (pn->atom == atom(QXcbAtom::_NET_WORKAREA)) {
QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(pn->window);
if (virtualDesktop)
@@ -1237,7 +1237,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
if (!handled) {
if (response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) {
- xcb_xfixes_selection_notify_event_t *notify_event = (xcb_xfixes_selection_notify_event_t *)event;
+ xcb_xfixes_selection_notify_event_t *notify_event = reinterpret_cast<xcb_xfixes_selection_notify_event_t *>(event);
setTime(notify_event->timestamp);
#ifndef QT_NO_CLIPBOARD
m_clipboard->handleXFixesSelectionRequest(notify_event);
@@ -1247,10 +1247,10 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
handled = true;
} else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) {
- updateScreens((xcb_randr_notify_event_t *)event);
+ updateScreens(reinterpret_cast<xcb_randr_notify_event_t *>(event));
handled = true;
} else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
- xcb_randr_screen_change_notify_event_t *change_event = (xcb_randr_screen_change_notify_event_t *)event;
+ xcb_randr_screen_change_notify_event_t *change_event = reinterpret_cast<xcb_randr_screen_change_notify_event_t *>(event);
for (QXcbScreen *s : qAsConst(m_screens)) {
if (s->root() == change_event->root )
s->handleScreenChange(change_event);
@@ -1359,7 +1359,7 @@ void QXcbEventReader::run()
void QXcbEventReader::addEvent(xcb_generic_event_t *event)
{
if ((event->response_type & ~0x80) == XCB_CLIENT_MESSAGE
- && ((xcb_client_message_event_t *)event)->type == m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION))
+ && (reinterpret_cast<xcb_client_message_event_t *>(event))->type == m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION))
m_connection = 0;
m_events << event;
}
@@ -1425,7 +1425,7 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id)
event.type = atom(a);
event.data.data32[0] = id;
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event));
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char *>(&event)));
Q_XCB_CALL(xcb_destroy_window(m_connection, eventListener));
xcb_flush(xcb_connection());
}
@@ -1445,7 +1445,7 @@ namespace
if ((event->response_type & ~0x80) != type) {
return false;
} else {
- xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event;
+ xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event);
if ((pn->window == window) && (pn->atom == atom))
return true;
}
@@ -1473,7 +1473,7 @@ xcb_timestamp_t QXcbConnection::getTimestamp()
event = checkEvent(checker);
}
- xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event;
+ xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event);
xcb_timestamp_t timestamp = pn->time;
free(event);
@@ -1497,7 +1497,8 @@ xcb_window_t QXcbConnection::getQtSelectionOwner()
{
if (!m_qtSelectionOwner) {
xcb_screen_t *xcbScreen = primaryVirtualDesktop()->screen();
- int x = 0, y = 0, w = 3, h = 3;
+ int16_t x = 0, y = 0;
+ uint16_t w = 3, h = 3;
m_qtSelectionOwner = xcb_generate_id(xcb_connection());
Q_XCB_CALL(xcb_create_window(xcb_connection(),
XCB_COPY_FROM_PARENT, // depth -- same as root
@@ -1686,7 +1687,7 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex,
for (int j = nextIndex; j < eventqueue->size(); ++j) {
xcb_generic_event_t *next = eventqueue->at(j);
if (isValid(next) && next->response_type == XCB_CONFIGURE_NOTIFY
- && ((xcb_configure_notify_event_t *)next)->event == ((xcb_configure_notify_event_t*)event)->event)
+ && reinterpret_cast<xcb_configure_notify_event_t *>(next)->event == reinterpret_cast<xcb_configure_notify_event_t *>(event)->event)
{
return true;
}
@@ -1715,7 +1716,7 @@ void QXcbConnection::processXcbEvents()
(*eventqueue)[i] = 0;
if (!(event->response_type & ~0x80)) {
- handleXcbError((xcb_generic_error_t *)event);
+ handleXcbError(reinterpret_cast<xcb_generic_error_t *>(event));
continue;
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index f6ba828a15..c9fc27997b 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -694,7 +694,7 @@ Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_MOVABLE_TYPE);
#endif
#endif
-#define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display()))
+#define DISPLAY_FROM_XCB(object) (reinterpret_cast<Display *>(object->connection()->xlib_display()))
#define CREATE_VISUALINFO_FROM_DEFAULT_VISUALID(object) ((XVisualInfo *)(object->connection()->createVisualInfoForDefaultVisualId()))
template<typename T>
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 1c13f8edc2..c175967054 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -103,6 +103,9 @@
#if defined(Q_OS_MACX)
#include <IOKit/pwr_mgt/IOPMLib.h>
+#include <mach/task.h>
+#include <mach/mach_init.h>
+#include <CoreFoundation/CFPreferences.h>
#endif
#include <vector>
@@ -137,6 +140,40 @@ static bool debuggerPresent()
return pid != 0;
#elif defined(Q_OS_WIN)
return IsDebuggerPresent();
+#elif defined(Q_OS_MACOS)
+ auto equals = [](CFStringRef str1, CFStringRef str2) -> bool {
+ return CFStringCompare(str1, str2, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
+ };
+
+ // Check if there is an exception handler for the process:
+ mach_msg_type_number_t portCount = 0;
+ exception_mask_t masks[EXC_TYPES_COUNT];
+ mach_port_t ports[EXC_TYPES_COUNT];
+ exception_behavior_t behaviors[EXC_TYPES_COUNT];
+ thread_state_flavor_t flavors[EXC_TYPES_COUNT];
+ exception_mask_t mask = EXC_MASK_ALL & ~(EXC_MASK_RESOURCE | EXC_MASK_GUARD);
+ kern_return_t result = task_get_exception_ports(mach_task_self(), mask, masks, &portCount,
+ ports, behaviors, flavors);
+ if (result == KERN_SUCCESS) {
+ for (mach_msg_type_number_t portIndex = 0; portIndex < portCount; ++portIndex) {
+ if (MACH_PORT_VALID(ports[portIndex])) {
+ return true;
+ }
+ }
+ }
+
+ // Ok, no debugger attached. So, let's see if CrashReporter will throw up a dialog. If so, we
+ // leave it to the OS to do the stack trace.
+ CFStringRef crashReporterType = static_cast<CFStringRef>(
+ CFPreferencesCopyAppValue(CFSTR("DialogType"), CFSTR("com.apple.CrashReporter")));
+ if (crashReporterType == nullptr)
+ return true;
+
+ const bool createsStackTrace =
+ !equals(crashReporterType, CFSTR("server")) &&
+ !equals(crashReporterType, CFSTR("none"));
+ CFRelease(crashReporterType);
+ return createsStackTrace;
#else
// TODO
return false;
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index 8a1e1fd6e3..68b6b28945 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -40,6 +40,7 @@ SOURCES += \
../../corelib/global/qlogging.cpp \
../../corelib/global/qmalloc.cpp \
../../corelib/global/qnumeric.cpp \
+ ../../corelib/global/qoperatingsystemversion.cpp \
../../corelib/io/qabstractfileengine.cpp \
../../corelib/io/qbuffer.cpp \
../../corelib/io/qdatastream.cpp \
@@ -108,7 +109,8 @@ unix:SOURCES += ../../corelib/io/qfilesystemengine_unix.cpp \
../../corelib/io/qfilesystemiterator_unix.cpp \
../../corelib/io/qfsfileengine_unix.cpp
-win32:SOURCES += ../../corelib/io/qfilesystemengine_win.cpp \
+win32:SOURCES += ../../corelib/global/qoperatingsystemversion_win.cpp \
+ ../../corelib/io/qfilesystemengine_win.cpp \
../../corelib/io/qfilesystemiterator_win.cpp \
../../corelib/io/qfsfileengine_win.cpp \
../../corelib/kernel/qcoreapplication_win.cpp \
@@ -119,6 +121,7 @@ mac {
../../corelib/kernel/qcoreapplication_mac.cpp \
../../corelib/kernel/qcore_mac.cpp
OBJECTIVE_SOURCES += \
+ ../../corelib/global/qoperatingsystemversion_darwin.mm \
../../corelib/kernel/qcore_mac_objc.mm \
../../corelib/kernel/qcore_foundation.mm
diff --git a/src/tools/uic/cpp/cppwriteincludes.cpp b/src/tools/uic/cpp/cppwriteincludes.cpp
index a99d6adf07..dcbe400224 100644
--- a/src/tools/uic/cpp/cppwriteincludes.cpp
+++ b/src/tools/uic/cpp/cppwriteincludes.cpp
@@ -114,8 +114,9 @@ void WriteIncludes::acceptUI(DomUI *node)
TreeWalker::acceptUI(node);
- if (!m_uic->option().includeFile.isEmpty())
- m_globalIncludes.insert(m_uic->option().includeFile, true);
+ const auto includeFile = m_uic->option().includeFile;
+ if (!includeFile.isEmpty())
+ m_globalIncludes.insert(includeFile);
writeHeaders(m_globalIncludes, true);
writeHeaders(m_localIncludes, false);
@@ -272,10 +273,11 @@ void WriteIncludes::insertInclude(const QString &header, bool global)
fprintf(stderr, "%s %s %d\n", Q_FUNC_INFO, qPrintable(header), global);
OrderedSet &includes = global ? m_globalIncludes : m_localIncludes;
- if (includes.contains(header))
+ // Insert (if not already done).
+ const bool isNewHeader = includes.insert(header).second;
+ if (!isNewHeader)
return;
- // Insert. Also remember base name for quick check of suspicious custom plugins
- includes.insert(header, false);
+ // Also remember base name for quick check of suspicious custom plugins
const QString lowerBaseName = QFileInfo(header).completeBaseName ().toLower();
m_includeBaseNames.insert(lowerBaseName);
}
@@ -286,13 +288,11 @@ void WriteIncludes::writeHeaders(const OrderedSet &headers, bool global)
const QChar closingQuote = global ? QLatin1Char('>') : QLatin1Char('"');
// Check for the old headers 'qslider.h' and replace by 'QtGui/QSlider'
- const OrderedSet::const_iterator cend = headers.constEnd();
- for (OrderedSet::const_iterator sit = headers.constBegin(); sit != cend; ++sit) {
- const StringMap::const_iterator hit = m_oldHeaderToNewHeader.constFind(sit.key());
- const bool mapped = hit != m_oldHeaderToNewHeader.constEnd();
- const QString header = mapped ? hit.value() : sit.key();
- if (!QStringRef(&header).trimmed().isEmpty())
- m_output << "#include " << openingQuote << header << closingQuote << QLatin1Char('\n');
+ for (const QString &header : headers) {
+ const QString value = m_oldHeaderToNewHeader.value(header, header);
+ const auto trimmed = QStringRef(&value).trimmed();
+ if (!trimmed.isEmpty())
+ m_output << "#include " << openingQuote << trimmed << closingQuote << QLatin1Char('\n');
}
}
diff --git a/src/tools/uic/cpp/cppwriteincludes.h b/src/tools/uic/cpp/cppwriteincludes.h
index 397c6a26e1..7a6a499536 100644
--- a/src/tools/uic/cpp/cppwriteincludes.h
+++ b/src/tools/uic/cpp/cppwriteincludes.h
@@ -35,6 +35,8 @@
#include <qset.h>
#include <qstring.h>
+#include <set>
+
QT_BEGIN_NAMESPACE
class QTextStream;
@@ -72,7 +74,7 @@ private:
void add(const QString &className, bool determineHeader = true, const QString &header = QString(), bool global = false);
private:
- typedef QMap<QString, bool> OrderedSet;
+ typedef std::set<QString> OrderedSet;
void insertIncludeForClass(const QString &className, QString header = QString(), bool global = false);
void insertInclude(const QString &header, bool global);
void writeHeaders(const OrderedSet &headers, bool global);
diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
index e6fda103fb..bd9f0c6e01 100644
--- a/src/widgets/accessible/simplewidgets.cpp
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -468,21 +468,15 @@ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> >
QAccessibleDisplay::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const
{
QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > rels = QAccessibleWidget::relations(match);
- if (match & QAccessible::Labelled) {
- QVarLengthArray<QObject *, 4> relatedObjects;
-
#ifndef QT_NO_SHORTCUT
+ if (match & QAccessible::Labelled) {
if (QLabel *label = qobject_cast<QLabel*>(object())) {
- relatedObjects.append(label->buddy());
- }
-#endif
- for (int i = 0; i < relatedObjects.count(); ++i) {
const QAccessible::Relation rel = QAccessible::Labelled;
- QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(relatedObjects.at(i));
- if (iface)
+ if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(label->buddy()))
rels.append(qMakePair(iface, rel));
}
}
+#endif
return rels;
}
diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp
index 9d8e7c4b66..1a38f43d35 100644
--- a/src/widgets/dialogs/qwizard_win.cpp
+++ b/src/widgets/dialogs/qwizard_win.cpp
@@ -46,6 +46,7 @@
#include "qwizard.h"
#include "qpaintengine.h"
#include "qapplication.h"
+#include <QtCore/QOperatingSystemVersion>
#include <QtCore/QVariant>
#include <QtCore/QDebug>
#include <QtGui/QMouseEvent>
@@ -715,7 +716,7 @@ int QVistaHelper::topOffset()
if (vistaState() != VistaAero)
return titleBarSize() + 3;
static const int aeroOffset =
- QSysInfo::WindowsVersion == QSysInfo::WV_WINDOWS7 ?
+ QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8 ?
QStyleHelper::dpiScaled(4) : QStyleHelper::dpiScaled(13);
return aeroOffset + titleBarSize();
}
diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
index 6e10d18e11..6a9036997c 100644
--- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -2575,10 +2575,12 @@ void QGraphicsAnchorLayoutPrivate::identifyFloatItems(const QSet<AnchorData *> &
for (const AnchorData *ad : visited)
identifyNonFloatItems_helper(ad, &nonFloating);
- QSet<QGraphicsLayoutItem *> allItems;
- foreach (QGraphicsLayoutItem *item, items)
- allItems.insert(item);
- m_floatItems[orientation] = allItems - nonFloating;
+ QSet<QGraphicsLayoutItem *> floatItems;
+ for (QGraphicsLayoutItem *item : qAsConst(items)) {
+ if (!nonFloating.contains(item))
+ floatItems.insert(item);
+ }
+ m_floatItems[orientation] = std::move(floatItems);
}
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index dd0edc7c80..02079fb8d5 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -91,12 +91,6 @@ extern Q_GUI_EXPORT bool qt_is_gui_used;
extern QClipboard *qt_clipboard;
#endif
-#if defined (Q_OS_WIN32) || defined (Q_OS_CYGWIN)
-extern QSysInfo::WinVersion qt_winver;
-#elif defined (Q_OS_MAC)
-extern QSysInfo::MacVersion qt_macver;
-#endif
-
typedef QHash<QByteArray, QFont> FontHash;
FontHash *qt_app_fonts_hash();
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index 1f17810fc9..6fbc7c9eea 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -84,6 +84,7 @@
#include <qtoolbutton.h>
#include <qtreeview.h>
#include <qtableview.h>
+#include <qoperatingsystemversion.h>
#include <qwizard.h>
#include <qdebug.h>
#include <qlibrary.h>
@@ -1310,7 +1311,7 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem
bdi->adornment = kThemeAdornmentFocus;
if (combo->activeSubControls & QStyle::SC_ComboBoxArrow)
bdi->state = kThemeStatePressed;
- else if (tds == kThemeStateInactive && QSysInfo::MacintoshVersion < QSysInfo::MV_10_10)
+ else if (tds == kThemeStateInactive && QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite)
bdi->state = kThemeStateActive;
else
bdi->state = tds;
@@ -1632,7 +1633,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti
|| slider->tickPosition == QSlider::TicksBothSides;
tdi->bounds = qt_hirectForQRect(slider->rect);
- if (isScrollbar || QSysInfo::MacintoshVersion < QSysInfo::MV_10_10) {
+ if (isScrollbar || QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite) {
tdi->min = slider->minimum;
tdi->max = slider->maximum;
tdi->value = slider->sliderPosition;
@@ -1944,7 +1945,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD
const bool button = opt->type == QStyleOption::SO_Button;
const bool viewItem = opt->type == QStyleOption::SO_ViewItem;
const bool pressed = bdi->state == kThemeStatePressed;
- const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10;
+ const bool usingYosemiteOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite;
if (button && pressed) {
if (bdi->kind == kThemePushButton) {
@@ -3579,7 +3580,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QWindow *window = w && w->window() ? w->window()->windowHandle() :
QStyleHelper::styleObjectWindow(opt->styleObject);
const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window);
- const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10;
+ const bool usingYosemiteOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite;
switch (ce) {
case CE_HeaderSection:
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
@@ -3971,7 +3972,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
bool hasIcon = !btn.icon.isNull();
bool hasText = !btn.text.isEmpty();
- if (!hasMenu && QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) {
+ if (!hasMenu && QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite) {
if (tds == kThemeStatePressed
|| (tds == kThemeStateActive
&& ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton)
@@ -4076,8 +4077,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QStyleOptionComboBox comboCopy = *cb;
comboCopy.direction = Qt::LeftToRight;
if (opt->state & QStyle::State_Small)
- comboCopy.rect.translate(0, w ? 0 : (QSysInfo::macVersion() >= QSysInfo::MV_10_10 ? 0 : -2)); // Supports Qt Quick Controls
- else if (QSysInfo::macVersion() == QSysInfo::MV_10_9)
+ comboCopy.rect.translate(0, w ? 0 : (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite ? 0 : -2)); // Supports Qt Quick Controls
+ else if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXMavericks
+ && QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite)
comboCopy.rect.translate(0, 1);
QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w);
}
@@ -5289,7 +5291,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
QWindow *window = widget && widget->window() ? widget->window()->windowHandle() :
QStyleHelper::styleObjectWindow(opt->styleObject);
const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window);
- const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10;
+ const bool usingYosemiteOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite;
switch (cc) {
case CC_Slider:
case CC_ScrollBar:
@@ -5933,7 +5935,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
drawToolbarButtonArrow(tb->rect, tds, cg);
}
if (tb->state & State_On) {
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) {
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite) {
QWindow *window = 0;
if (widget && widget->window())
window = widget->window()->windowHandle();
@@ -6297,7 +6299,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
switch (sc) {
case SC_ComboBoxEditField:{
ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10)
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite)
ret.setHeight(ret.height() - 1);
break; }
case SC_ComboBoxArrow:{
@@ -6756,7 +6758,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
case CT_ComboBox: {
sz.rwidth() += 50;
const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt);
- if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_10 || (cb && !cb->editable))
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite || (cb && !cb->editable))
sz.rheight() += 2;
break;
}
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index bf5aad0187..8c91e3a420 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -39,6 +39,7 @@
#include "qwindowsvistastyle_p.h"
#include "qwindowsvistastyle_p_p.h"
+#include <qoperatingsystemversion.h>
#include <qscreen.h>
#include <qwindow.h>
#include <private/qstyleanimation_p.h>
@@ -1752,7 +1753,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
theme.stateId = stateId;
d->drawBackground(theme);
- if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8) {
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8) {
const QRect gripperBounds = QWindowsXPStylePrivate::scrollBarGripperBounds(flags, widget, &theme);
// Draw gripper if there is enough space
if (!gripperBounds.isEmpty() && flags & State_Enabled) {
diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp
index 2a418167f1..9dfd35cadb 100644
--- a/src/widgets/util/qsystemtrayicon.cpp
+++ b/src/widgets/util/qsystemtrayicon.cpp
@@ -59,6 +59,25 @@
QT_BEGIN_NAMESPACE
+static QIcon messageIcon2qIcon(QSystemTrayIcon::MessageIcon icon)
+{
+ QStyle::StandardPixmap stdIcon;
+ switch (icon) {
+ case QSystemTrayIcon::Information:
+ stdIcon = QStyle::SP_MessageBoxInformation;
+ break;
+ case QSystemTrayIcon::Warning:
+ stdIcon = QStyle::SP_MessageBoxWarning;
+ break;
+ case QSystemTrayIcon::Critical:
+ stdIcon = QStyle::SP_MessageBoxCritical;
+ break;
+ case QSystemTrayIcon::NoIcon:
+ return QIcon();
+ }
+ return QApplication::style()->standardIcon(stdIcon);
+}
+
/*!
\class QSystemTrayIcon
\brief The QSystemTrayIcon class provides an icon for an application in the system tray.
@@ -382,11 +401,29 @@ bool QSystemTrayIcon::supportsMessages()
\sa show(), supportsMessages()
*/
void QSystemTrayIcon::showMessage(const QString& title, const QString& msg,
- QSystemTrayIcon::MessageIcon icon, int msecs)
+ QSystemTrayIcon::MessageIcon msgIcon, int msecs)
{
Q_D(QSystemTrayIcon);
if (d->visible)
- d->showMessage_sys(title, msg, icon, msecs);
+ d->showMessage_sys(title, msg, messageIcon2qIcon(msgIcon), msgIcon, msecs);
+}
+
+/*!
+ \fn void QSystemTrayIcon::showMessage(const QString &title, const QString &message, const QIcon &icon, int millisecondsTimeoutHint)
+
+ \overload showMessage()
+
+ Shows a balloon message for the entry with the given \a title, \a message,
+ and custom icon \a icon for the time specified in \a millisecondsTimeoutHint.
+
+ \since 5.9
+*/
+void QSystemTrayIcon::showMessage(const QString &title, const QString &msg,
+ const QIcon &icon, int msecs)
+{
+ Q_D(QSystemTrayIcon);
+ if (d->visible)
+ d->showMessage_sys(title, msg, icon, QSystemTrayIcon::NoIcon, msecs);
}
void QSystemTrayIconPrivate::_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason reason)
@@ -398,9 +435,9 @@ void QSystemTrayIconPrivate::_q_emitActivated(QPlatformSystemTrayIcon::Activatio
//////////////////////////////////////////////////////////////////////
static QBalloonTip *theSolitaryBalloonTip = 0;
-void QBalloonTip::showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title,
- const QString& message, QSystemTrayIcon *trayIcon,
- const QPoint& pos, int timeout, bool showArrow)
+void QBalloonTip::showBalloon(const QIcon &icon, const QString &title,
+ const QString &message, QSystemTrayIcon *trayIcon,
+ const QPoint &pos, int timeout, bool showArrow)
{
hideBalloon();
if (message.isEmpty() && title.isEmpty())
@@ -434,8 +471,8 @@ bool QBalloonTip::isBalloonVisible()
return theSolitaryBalloonTip;
}
-QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title,
- const QString& message, QSystemTrayIcon *ti)
+QBalloonTip::QBalloonTip(const QIcon &icon, const QString &title,
+ const QString &message, QSystemTrayIcon *ti)
: QWidget(0, Qt::ToolTip), trayIcon(ti), timerId(-1)
{
setAttribute(Qt::WA_DeleteOnClose);
@@ -482,26 +519,10 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title
msgLabel->setFixedSize(limit, msgLabel->heightForWidth(limit));
}
- QIcon si;
- switch (icon) {
- case QSystemTrayIcon::Warning:
- si = style()->standardIcon(QStyle::SP_MessageBoxWarning);
- break;
- case QSystemTrayIcon::Critical:
- si = style()->standardIcon(QStyle::SP_MessageBoxCritical);
- break;
- case QSystemTrayIcon::Information:
- si = style()->standardIcon(QStyle::SP_MessageBoxInformation);
- break;
- case QSystemTrayIcon::NoIcon:
- default:
- break;
- }
-
QGridLayout *layout = new QGridLayout;
- if (!si.isNull()) {
+ if (!icon.isNull()) {
QLabel *iconLabel = new QLabel;
- iconLabel->setPixmap(si.pixmap(iconSize, iconSize));
+ iconLabel->setPixmap(icon.pixmap(iconSize, iconSize));
iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
iconLabel->setMargin(2);
layout->addWidget(iconLabel, 0, 0);
@@ -678,52 +699,6 @@ void QSystemTrayIconPrivate::remove_sys_qpa()
qpa_sys->cleanup();
}
-QRect QSystemTrayIconPrivate::geometry_sys_qpa() const
-{
- return qpa_sys->geometry();
-}
-
-void QSystemTrayIconPrivate::updateIcon_sys_qpa()
-{
- qpa_sys->updateIcon(icon);
-}
-
-void QSystemTrayIconPrivate::updateMenu_sys_qpa()
-{
- if (menu) {
- addPlatformMenu(menu);
- qpa_sys->updateMenu(menu->platformMenu());
- }
-}
-
-void QSystemTrayIconPrivate::updateToolTip_sys_qpa()
-{
- qpa_sys->updateToolTip(toolTip);
-}
-
-void QSystemTrayIconPrivate::showMessage_sys_qpa(const QString &title,
- const QString &message,
- QSystemTrayIcon::MessageIcon icon,
- int msecs)
-{
- QIcon notificationIcon;
- switch (icon) {
- case QSystemTrayIcon::Information:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
- break;
- case QSystemTrayIcon::Warning:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
- break;
- case QSystemTrayIcon::Critical:
- notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
- break;
- default:
- break;
- }
- qpa_sys->showMessage(title, message, notificationIcon,
- static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs);
-}
-
void QSystemTrayIconPrivate::addPlatformMenu(QMenu *menu) const
{
if (menu->platformMenu())
diff --git a/src/widgets/util/qsystemtrayicon.h b/src/widgets/util/qsystemtrayicon.h
index fb238c92b0..918dd0478e 100644
--- a/src/widgets/util/qsystemtrayicon.h
+++ b/src/widgets/util/qsystemtrayicon.h
@@ -101,6 +101,7 @@ public Q_SLOTS:
void setVisible(bool visible);
inline void show() { setVisible(true); }
inline void hide() { setVisible(false); }
+ void showMessage(const QString &title, const QString &msg, const QIcon &icon, int msecs = 10000);
void showMessage(const QString &title, const QString &msg,
QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::Information, int msecs = 10000);
diff --git a/src/widgets/util/qsystemtrayicon_p.h b/src/widgets/util/qsystemtrayicon_p.h
index 79e824f4b7..3f5cab40be 100644
--- a/src/widgets/util/qsystemtrayicon_p.h
+++ b/src/widgets/util/qsystemtrayicon_p.h
@@ -84,7 +84,8 @@ public:
void updateToolTip_sys();
void updateMenu_sys();
QRect geometry_sys() const;
- void showMessage_sys(const QString &title, const QString &msg, QSystemTrayIcon::MessageIcon icon, int secs);
+ void showMessage_sys(const QString &title, const QString &msg, const QIcon &icon,
+ QSystemTrayIcon::MessageIcon msgIcon, int msecs);
static bool isSystemTrayAvailable_sys();
static bool supportsMessages_sys();
@@ -101,11 +102,7 @@ public:
private:
void install_sys_qpa();
void remove_sys_qpa();
- void updateIcon_sys_qpa();
- void updateToolTip_sys_qpa();
- void updateMenu_sys_qpa();
- QRect geometry_sys_qpa() const;
- void showMessage_sys_qpa(const QString &title, const QString &msg, QSystemTrayIcon::MessageIcon icon, int secs);
+
void addPlatformMenu(QMenu *menu) const;
};
@@ -113,16 +110,16 @@ class QBalloonTip : public QWidget
{
Q_OBJECT
public:
- static void showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title,
- const QString& msg, QSystemTrayIcon *trayIcon,
- const QPoint& pos, int timeout, bool showArrow = true);
+ static void showBalloon(const QIcon &icon, const QString &title,
+ const QString &msg, QSystemTrayIcon *trayIcon,
+ const QPoint &pos, int timeout, bool showArrow = true);
static void hideBalloon();
static bool isBalloonVisible();
static void updateBalloonPosition(const QPoint& pos);
private:
- QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title,
- const QString& msg, QSystemTrayIcon *trayIcon);
+ QBalloonTip(const QIcon &icon, const QString &title,
+ const QString &msg, QSystemTrayIcon *trayIcon);
~QBalloonTip();
void balloon(const QPoint&, int, bool);
diff --git a/src/widgets/util/qsystemtrayicon_qpa.cpp b/src/widgets/util/qsystemtrayicon_qpa.cpp
index 643f17a5fe..8399732a4a 100644
--- a/src/widgets/util/qsystemtrayicon_qpa.cpp
+++ b/src/widgets/util/qsystemtrayicon_qpa.cpp
@@ -76,7 +76,7 @@ void QSystemTrayIconPrivate::remove_sys()
QRect QSystemTrayIconPrivate::geometry_sys() const
{
if (qpa_sys)
- return geometry_sys_qpa();
+ return qpa_sys->geometry();
else
return QRect();
}
@@ -84,19 +84,21 @@ QRect QSystemTrayIconPrivate::geometry_sys() const
void QSystemTrayIconPrivate::updateIcon_sys()
{
if (qpa_sys)
- updateIcon_sys_qpa();
+ qpa_sys->updateIcon(icon);
}
void QSystemTrayIconPrivate::updateMenu_sys()
{
- if (qpa_sys)
- updateMenu_sys_qpa();
+ if (qpa_sys && menu) {
+ addPlatformMenu(menu);
+ qpa_sys->updateMenu(menu->platformMenu());
+ }
}
void QSystemTrayIconPrivate::updateToolTip_sys()
{
if (qpa_sys)
- updateToolTip_sys_qpa();
+ qpa_sys->updateToolTip(toolTip);
}
bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
@@ -118,10 +120,11 @@ bool QSystemTrayIconPrivate::supportsMessages_sys()
}
void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message,
- QSystemTrayIcon::MessageIcon icon, int msecs)
+ const QIcon &icon, QSystemTrayIcon::MessageIcon msgIcon, int msecs)
{
if (qpa_sys)
- showMessage_sys_qpa(title, message, icon, msecs);
+ qpa_sys->showMessage(title, message, icon,
+ static_cast<QPlatformSystemTrayIcon::MessageIcon>(msgIcon), msecs);
}
QT_END_NAMESPACE
diff --git a/src/widgets/util/qsystemtrayicon_win.cpp b/src/widgets/util/qsystemtrayicon_win.cpp
index 2da24e482b..638d2050fb 100644
--- a/src/widgets/util/qsystemtrayicon_win.cpp
+++ b/src/widgets/util/qsystemtrayicon_win.cpp
@@ -81,11 +81,14 @@ struct Q_NOTIFYICONIDENTIFIER {
# define NIN_BALLOONTIMEOUT (WM_USER + 4)
# define NIN_BALLOONUSERCLICK (WM_USER + 5)
# define NIF_SHOWTIP 0x00000080
+# define NIIF_LARGE_ICON 0x00000020
# define NOTIFYICON_VERSION_4 4
#endif
#define Q_MSGFLT_ALLOW 1
+Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
+
typedef HRESULT (WINAPI *PtrShell_NotifyIconGetRect)(const Q_NOTIFYICONIDENTIFIER* identifier, RECT* iconLocation);
typedef BOOL (WINAPI *PtrChangeWindowMessageFilter)(UINT message, DWORD dwFlag);
typedef BOOL (WINAPI *PtrChangeWindowMessageFilterEx)(HWND hWnd, UINT message, DWORD action, void* pChangeFilterStruct);
@@ -107,7 +110,7 @@ public:
~QSystemTrayIconSys();
bool trayMessage(DWORD msg);
void setIconContents(NOTIFYICONDATA &data);
- bool showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs);
+ bool showMessage(const QString &title, const QString &message, const QIcon &icon, uint uSecs);
QRect findIconGeometry(UINT iconId);
HICON createIcon();
bool winEvent(MSG *m, long *result);
@@ -184,7 +187,7 @@ static inline HWND createTrayIconMessageWindow()
QSystemTrayIconSys::QSystemTrayIconSys(HWND hwnd, QSystemTrayIcon *object)
: m_hwnd(hwnd), hIcon(0), q(object)
- , notifyIconSize(NOTIFYICONDATA_V2_SIZE), version(NOTIFYICON_VERSION)
+ , notifyIconSize(sizeof(NOTIFYICONDATA)), version(NOTIFYICON_VERSION_4)
, ignoreNextMouseRelease(false)
{
@@ -237,11 +240,7 @@ void QSystemTrayIconSys::setIconContents(NOTIFYICONDATA &tnd)
qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip)/sizeof(wchar_t));
}
-#ifndef NIIF_LARGE_ICON
-# define NIIF_LARGE_ICON 0x00000020
-#endif
-
-bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs)
+bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, const QIcon &icon, uint uSecs)
{
NOTIFYICONDATA tnd;
memset(&tnd, 0, notifyIconSize);
@@ -249,23 +248,32 @@ bool QSystemTrayIconSys::showMessage(const QString &title, const QString &messag
qStringToLimitedWCharArray(title, tnd.szInfoTitle, 64);
tnd.uID = q_uNOTIFYICONID;
- switch (type) {
- case QSystemTrayIcon::Information:
+ tnd.dwInfoFlags = NIIF_USER;
+
+ HICON *phIcon = &tnd.hIcon;
+ QSize size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
+ if (version == NOTIFYICON_VERSION_4) {
+ const QSize largeIcon(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
+ QSize more = icon.actualSize(largeIcon);
+ if (more.height() > (largeIcon.height() * 3/4) || more.width() > (largeIcon.width() * 3/4)) {
+ tnd.dwInfoFlags |= NIIF_LARGE_ICON;
+ size = largeIcon;
+ }
+ phIcon = &tnd.hBalloonIcon;
+ }
+ QPixmap pm = icon.pixmap(size);
+ if (pm.isNull()) {
tnd.dwInfoFlags = NIIF_INFO;
- break;
- case QSystemTrayIcon::Warning:
- tnd.dwInfoFlags = NIIF_WARNING;
- break;
- case QSystemTrayIcon::Critical:
- tnd.dwInfoFlags = NIIF_ERROR;
- break;
- case QSystemTrayIcon::NoIcon:
- tnd.dwInfoFlags = hIcon ? NIIF_USER : NIIF_NONE;
- break;
+ } else {
+ if (pm.size() != size) {
+ qWarning("QSystemTrayIcon::showMessage: Wrong icon size (%dx%d), please add standard one: %dx%d",
+ pm.size().width(), pm.size().height(), size.width(), size.height());
+ pm = pm.scaled(size, Qt::IgnoreAspectRatio);
+ }
+ *phIcon = qt_pixmapToWinHICON(pm);
}
- if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
- tnd.dwInfoFlags |= NIIF_LARGE_ICON;
tnd.cbSize = notifyIconSize;
+ tnd.uVersion = version;
tnd.hWnd = m_hwnd;
tnd.uTimeout = uSecs;
tnd.uFlags = NIF_INFO | NIF_SHOWTIP;
@@ -296,8 +304,6 @@ bool QSystemTrayIconSys::trayMessage(DWORD msg)
return success;
}
-Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
-
HICON QSystemTrayIconSys::createIcon()
{
const HICON oldIcon = hIcon;
@@ -509,7 +515,8 @@ QRect QSystemTrayIconSys::findIconGeometry(UINT iconId)
void QSystemTrayIconPrivate::showMessage_sys(const QString &title,
const QString &messageIn,
- QSystemTrayIcon::MessageIcon type,
+ const QIcon &icon,
+ QSystemTrayIcon::MessageIcon,
int timeOut)
{
if (!sys || !allowsMessages())
@@ -522,7 +529,7 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &title,
if (message.isEmpty() && !title.isEmpty())
message.append(QLatin1Char(' '));
- sys->showMessage(title, message, type, uSecs);
+ sys->showMessage(title, message, icon, uSecs);
}
QRect QSystemTrayIconPrivate::geometry_sys() const
diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp
index ea0604b6ed..20ab0f6377 100644
--- a/src/widgets/util/qsystemtrayicon_x11.cpp
+++ b/src/widgets/util/qsystemtrayicon_x11.cpp
@@ -284,7 +284,7 @@ void QSystemTrayIconPrivate::install_sys()
QRect QSystemTrayIconPrivate::geometry_sys() const
{
if (qpa_sys)
- return geometry_sys_qpa();
+ return qpa_sys->geometry();
if (!sys)
return QRect();
return sys->globalGeometry();
@@ -307,7 +307,7 @@ void QSystemTrayIconPrivate::remove_sys()
void QSystemTrayIconPrivate::updateIcon_sys()
{
if (qpa_sys) {
- updateIcon_sys_qpa();
+ qpa_sys->updateIcon(icon);
return;
}
if (sys)
@@ -316,14 +316,16 @@ void QSystemTrayIconPrivate::updateIcon_sys()
void QSystemTrayIconPrivate::updateMenu_sys()
{
- if (qpa_sys)
- updateMenu_sys_qpa();
+ if (qpa_sys && menu) {
+ addPlatformMenu(menu);
+ qpa_sys->updateMenu(menu->platformMenu());
+ }
}
void QSystemTrayIconPrivate::updateToolTip_sys()
{
if (qpa_sys) {
- updateToolTip_sys_qpa();
+ qpa_sys->updateToolTip(toolTip);
return;
}
if (!sys)
@@ -357,10 +359,11 @@ bool QSystemTrayIconPrivate::supportsMessages_sys()
}
void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message,
- QSystemTrayIcon::MessageIcon icon, int msecs)
+ const QIcon &icon, QSystemTrayIcon::MessageIcon msgIcon, int msecs)
{
if (qpa_sys) {
- showMessage_sys_qpa(title, message, icon, msecs);
+ qpa_sys->showMessage(title, message, icon,
+ static_cast<QPlatformSystemTrayIcon::MessageIcon>(msgIcon), msecs);
return;
}
if (!sys)