diff options
Diffstat (limited to 'src/corelib/global/qglobal.cpp')
-rw-r--r-- | src/corelib/global/qglobal.cpp | 298 |
1 files changed, 213 insertions, 85 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 997e804579..ac2f72d573 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1,8 +1,8 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Copyright (C) 2014 Intel Corporation -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** @@ -11,9 +11,9 @@ ** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -24,8 +24,8 @@ ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** $QT_END_LICENSE$ @@ -39,6 +39,7 @@ #include "qthreadstorage.h" #include "qdir.h" #include "qdatetime.h" +#include <private/qlocale_tools_p.h> #include <private/qsystemlibrary_p.h> @@ -548,9 +549,9 @@ Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits"); \snippet code/src_corelib_global_qglobal.cpp 3 <QtGlobal> also contains functions that generate messages from the - given string argument: qCritical(), qDebug(), qFatal() and - qWarning(). These functions call the message handler with the - given message. + given string argument: qDebug(), qInfo(), qWarning(), qCritical(), + and qFatal(). These functions call the message handler + with the given message. Example: @@ -769,6 +770,8 @@ Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits"); \value QtDebugMsg A message generated by the qDebug() function. + \value QtInfoMsg + A message generated by the qInfo() function. \value QtWarningMsg A message generated by the qWarning() function. \value QtCriticalMsg @@ -777,6 +780,7 @@ Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits"); A message generated by the qFatal() function. \value QtSystemMsg + \c QtInfoMsg was added in Qt 5.5. \sa QtMessageHandler, qInstallMessageHandler() */ @@ -986,9 +990,9 @@ bool qSharedBuild() Q_DECL_NOTHROW \li \l ByteOrder specifies whether the platform is big-endian or little-endian. \li \l WindowsVersion specifies the version of the Windows operating - system on which the application is run (Windows only) + system on which the application is run. \li \l MacintoshVersion specifies the version of the Macintosh - operating system on which the application is run (Mac only). + operating system on which the application is run. \endlist Some constants are defined only on certain platforms. You can use @@ -1011,7 +1015,7 @@ bool qSharedBuild() Q_DECL_NOTHROW /*! \variable QSysInfo::WindowsVersion \brief the version of the Windows operating system on which the - application is run (Windows only) + application is run. */ /*! @@ -1019,19 +1023,22 @@ bool qSharedBuild() Q_DECL_NOTHROW \since 4.4 Returns the version of the Windows operating system on which the - application is run (Windows only). + application is run, or WV_None if the operating system is not + Windows. */ /*! \variable QSysInfo::MacintoshVersion \brief the version of the Macintosh operating system on which - the application is run (Mac only). + the application is run. */ /*! \fn QSysInfo::MacVersion QSysInfo::macVersion() - Returns the version of Darwin (OS X or iOS) on which the application is run. + Returns the version of Darwin (OS X or iOS) on which the + application is run, or MV_None if the operating system + is not a version of Darwin. */ /*! @@ -1068,6 +1075,7 @@ bool qSharedBuild() Q_DECL_NOTHROW \value WV_WINDOWS7 Windows 7, Windows Server 2008 R2 (operating system version 6.1) \value WV_WINDOWS8 Windows 8 (operating system version 6.2) \value WV_WINDOWS8_1 Windows 8.1 (operating system version 6.3), introduced in Qt 5.2 + \value WV_WINDOWS10 Windows 10 (operating system version 10.0), introduced in Qt 5.5 Alternatively, you may use the following macros which correspond directly to the Windows operating system version number: @@ -1079,6 +1087,7 @@ bool qSharedBuild() Q_DECL_NOTHROW \value WV_6_1 Operating system version 6.1, corresponds to Windows 7 and Windows Server 2008 R2 \value WV_6_2 Operating system version 6.2, corresponds to Windows 8 \value WV_6_3 Operating system version 6.3, corresponds to Windows 8.1, introduced in Qt 5.2 + \value WV_10_0 Operating system version 10.0, corresponds to Windows 10, introduced in Qt 5.5 CE-based versions: @@ -1094,6 +1103,8 @@ bool qSharedBuild() Q_DECL_NOTHROW \value WV_NT_based NT-based version of Windows \value WV_CE_based CE-based version of Windows + \value WV_None Operating system other than Windows. + \sa MacVersion */ @@ -1141,6 +1152,8 @@ bool qSharedBuild() Q_DECL_NOTHROW \value MV_IOS_7_1 iOS 7.1 \value MV_IOS_8_0 iOS 8.0 + \value MV_None Not a Darwin operating system + \sa WinVersion */ @@ -1847,16 +1860,14 @@ Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr) { QSysInfo::MacVersion QSysInfo::macVersion() { + const QAppleOperatingSystemVersion version = qt_apple_os_version(); // qtcore_mac_objc.mm #if defined(Q_OS_OSX) - SInt32 gestalt_version; - if (Gestalt(gestaltSystemVersionMinor, &gestalt_version) == noErr) { - // add 2 because OS X 10.0 is 0x02 in the enum - return QSysInfo::MacVersion(gestalt_version + 2); - } + return QSysInfo::MacVersion(Q_MV_OSX(version.major, version.minor)); #elif defined(Q_OS_IOS) - return qt_ios_version(); // qtcore_mac_objc.mm -#endif + return QSysInfo::MacVersion(Q_MV_IOS(version.major, version.minor)); +#else return QSysInfo::MV_Unknown; +#endif } const QSysInfo::MacVersion QSysInfo::MacintoshVersion = QSysInfo::macVersion(); @@ -2024,6 +2035,8 @@ QSysInfo::WinVersion QSysInfo::windowsVersion() winver = QSysInfo::WV_WINDOWS8; } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3) { winver = QSysInfo::WV_WINDOWS8_1; + } else if (osver.dwMajorVersion == 10 && osver.dwMinorVersion == 0) { + winver = QSysInfo::WV_WINDOWS10; } else { qWarning("Qt: Untested Windows version %d.%d detected!", int(osver.dwMajorVersion), int(osver.dwMinorVersion)); @@ -2107,10 +2120,10 @@ const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion() # define USE_ETC_OS_RELEASE struct QUnixOSVersion { - // from /etc/os-release - QString productType; // $ID - QString productVersion; // $VERSION_ID - QString prettyName; // $PRETTY_NAME + // from /etc/os-release older /etc/lsb-release + QString productType; // $ID $DISTRIB_ID + QString productVersion; // $VERSION_ID $DISTRIB_RELEASE + QString prettyName; // $PRETTY_NAME $DISTRIB_DESCRIPTION }; static QString unquote(const char *begin, const char *end) @@ -2122,10 +2135,11 @@ static QString unquote(const char *begin, const char *end) return QString::fromLatin1(begin, end - begin); } -static bool readEtcOsRelease(QUnixOSVersion &v) +static bool readEtcFile(QUnixOSVersion &v, const char *filename, + const QByteArray &idKey, const QByteArray &versionKey, const QByteArray &prettyNameKey) { // we're avoiding QFile here - int fd = qt_safe_open("/etc/os-release", O_RDONLY); + int fd = qt_safe_open(filename, O_RDONLY); if (fd == -1) return false; @@ -2142,41 +2156,28 @@ static bool readEtcOsRelease(QUnixOSVersion &v) const char *ptr = buffer.constData(); const char *end = buffer.constEnd(); const char *eol; + QByteArray line; for ( ; ptr != end; ptr = eol + 1) { - static const char idString[] = "ID="; - static const char prettyNameString[] = "PRETTY_NAME="; - static const char versionIdString[] = "VERSION_ID="; - // find the end of the line after ptr eol = static_cast<const char *>(memchr(ptr, '\n', end - ptr)); if (!eol) eol = end - 1; + line.setRawData(ptr, eol - ptr); - // note: we're doing a binary search here, so comparison - // must always be sorted - int cmp = strncmp(ptr, idString, strlen(idString)); - if (cmp < 0) - continue; - if (cmp == 0) { - ptr += strlen(idString); + if (line.startsWith(idKey)) { + ptr += idKey.length(); v.productType = unquote(ptr, eol); continue; } - cmp = strncmp(ptr, prettyNameString, strlen(prettyNameString)); - if (cmp < 0) - continue; - if (cmp == 0) { - ptr += strlen(prettyNameString); + if (line.startsWith(prettyNameKey)) { + ptr += prettyNameKey.length(); v.prettyName = unquote(ptr, eol); continue; } - cmp = strncmp(ptr, versionIdString, strlen(versionIdString)); - if (cmp < 0) - continue; - if (cmp == 0) { - ptr += strlen(versionIdString); + if (line.startsWith(versionKey)) { + ptr += versionKey.length(); v.productVersion = unquote(ptr, eol); continue; } @@ -2184,6 +2185,45 @@ static bool readEtcOsRelease(QUnixOSVersion &v) return true; } + +static bool readEtcOsRelease(QUnixOSVersion &v) +{ + return readEtcFile(v, "/etc/os-release", QByteArrayLiteral("ID="), + QByteArrayLiteral("VERSION_ID="), QByteArrayLiteral("PRETTY_NAME=")); +} + +static bool readEtcLsbRelease(QUnixOSVersion &v) +{ + bool ok = readEtcFile(v, "/etc/lsb-release", QByteArrayLiteral("DISTRIB_ID="), + QByteArrayLiteral("DISTRIB_RELEASE="), QByteArrayLiteral("DISTRIB_DESCRIPTION=")); + if (ok && (v.prettyName.isEmpty() || v.prettyName == v.productType)) { + // some distributions have redundant information for the pretty name, + // so try /etc/<lowercasename>-release + + // we're still avoiding QFile here + QByteArray distrorelease = "/etc/" + v.productType.toLatin1().toLower() + "-release"; + int fd = qt_safe_open(distrorelease, O_RDONLY); + if (fd != -1) { + QT_STATBUF sbuf; + if (QT_FSTAT(fd, &sbuf) != -1 && sbuf.st_size > v.prettyName.length()) { + // file apparently contains interesting information + QByteArray buffer(sbuf.st_size, Qt::Uninitialized); + buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size)); + v.prettyName = QString::fromLatin1(buffer.trimmed()); + } + qt_safe_close(fd); + } + } + + return ok; +} + +static bool findUnixOsVersion(QUnixOSVersion &v) +{ + if (readEtcOsRelease(v)) + return true; + return readEtcLsbRelease(v); +} # endif // USE_ETC_OS_RELEASE #endif // Q_OS_UNIX @@ -2518,7 +2558,7 @@ QString QSysInfo::productType() #elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX QUnixOSVersion unixOsVersion; - readEtcOsRelease(unixOsVersion); + findUnixOsVersion(unixOsVersion); if (!unixOsVersion.productType.isEmpty()) return unixOsVersion.productType; #endif @@ -2551,25 +2591,9 @@ QString QSysInfo::productType() */ QString QSysInfo::productVersion() { -#if defined(Q_OS_IOS) - int major = (int(MacintoshVersion) >> 4) & 0xf; - int minor = int(MacintoshVersion) & 0xf; - if (Q_LIKELY(major < 10 && minor < 10)) { - char buf[4] = { char(major + '0'), '.', char(minor + '0'), '\0' }; - return QString::fromLatin1(buf, 3); - } - return QString::number(major) + QLatin1Char('.') + QString::number(minor); -#elif defined(Q_OS_OSX) - int minor = int(MacintoshVersion) - 2; // we're not running on Mac OS 9 - Q_ASSERT(minor < 100); - char buf[] = "10.0\0"; - if (Q_LIKELY(minor < 10)) { - buf[3] += minor; - } else { - buf[3] += minor / 10; - buf[4] = '0' + minor % 10; - } - return QString::fromLatin1(buf); +#if defined(Q_OS_MAC) + const QAppleOperatingSystemVersion version = qt_apple_os_version(); + return QString::number(version.major) + QLatin1Char('.') + QString::number(version.minor); #elif defined(Q_OS_WIN) const char *version = winVer_helper(); if (version) @@ -2590,7 +2614,7 @@ QString QSysInfo::productVersion() } #elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX QUnixOSVersion unixOsVersion; - readEtcOsRelease(unixOsVersion); + findUnixOsVersion(unixOsVersion); if (!unixOsVersion.productVersion.isEmpty()) return unixOsVersion.productVersion; #endif @@ -2662,10 +2686,12 @@ QString QSysInfo::prettyProductName() return QLatin1String("Android ") + productVersion(); #elif defined(Q_OS_BLACKBERRY) return QLatin1String("BlackBerry ") + productVersion(); +#elif defined(Q_OS_HAIKU) + return QLatin1String("Haiku ") + productVersion(); #elif defined(Q_OS_UNIX) # ifdef USE_ETC_OS_RELEASE QUnixOSVersion unixOsVersion; - readEtcOsRelease(unixOsVersion); + findUnixOsVersion(unixOsVersion); if (!unixOsVersion.prettyName.isEmpty()) return unixOsVersion.prettyName; # endif @@ -3065,6 +3091,56 @@ bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT /*! \relates <QtGlobal> + \since 5.5 + + Returns the numerical value of the environment variable \a varName. + If \a ok is not null, sets \c{*ok} to \c true or \c false depending + on the success of the conversion. + + Equivalent to + \code + qgetenv(varName).toInt() + \endcode + except that it's much faster, and can't throw exceptions. + + \sa qgetenv(), qEnvironmentVariableIsSet() +*/ +int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT +{ +#if defined(_MSC_VER) && _MSC_VER >= 1400 + // we provide a buffer that can hold any int value: + static const int NumBinaryDigitsPerOctalDigit = 3; + static const int MaxDigitsForOctalInt = + (std::numeric_limits<uint>::digits + NumBinaryDigitsPerOctalDigit - 1) / NumBinaryDigitsPerOctalDigit; + char buffer[MaxDigitsForOctalInt + 2]; // +1 for NUL +1 for optional '-' + size_t dummy; + if (getenv_s(&dummy, buffer, sizeof buffer, varName) != 0) { + if (ok) + *ok = false; + return 0; + } +#else + const char * const buffer = ::getenv(varName); + if (!buffer || !*buffer) { + if (ok) + *ok = false; + return 0; + } +#endif + bool ok_ = true; + const qlonglong value = qstrtoll(buffer, Q_NULLPTR, 0, &ok_); + if (int(value) != value) { // this is the check in QByteArray::toInt(), keep it in sync + if (ok) + *ok = false; + return 0; + } else if (ok) { + *ok = ok_; + } + return int(value); +} + +/*! + \relates <QtGlobal> \since 5.1 Returns whether the environment variable \a varName is set. @@ -3110,7 +3186,7 @@ bool qputenv(const char *varName, const QByteArray& value) { #if defined(_MSC_VER) && _MSC_VER >= 1400 return _putenv_s(varName, value.constData()) == 0; -#elif defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L +#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_HAIKU) // POSIX.1-2001 has setenv return setenv(varName, value.constData(), true) == 0; #else @@ -3140,8 +3216,8 @@ bool qunsetenv(const char *varName) { #if defined(_MSC_VER) && _MSC_VER >= 1400 return _putenv_s(varName, "") == 0; -#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_BSD4) - // POSIX.1-2001 and BSD have unsetenv +#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_BSD4) || defined(Q_OS_HAIKU) + // POSIX.1-2001, BSD and Haiku have unsetenv return unsetenv(varName) == 0; #elif defined(Q_CC_MINGW) // On mingw, putenv("var=") removes "var" from the environment @@ -3556,8 +3632,8 @@ int qrand() qPrintable() is used. This is because the array returned by QString::toLocal8Bit() will fall out of scope. - \note qDebug(), qWarning(), qCritical(), qFatal() expect %s - arguments to be UTF-8 encoded, while qPrintable() converts to + \note qDebug(), qInfo(), qWarning(), qCritical(), qFatal() expect + %s arguments to be UTF-8 encoded, while qPrintable() converts to local 8-bit encoding. Therefore qUtf8Printable() should be used for logging strings instead of qPrintable(). @@ -3580,7 +3656,7 @@ int qrand() \snippet code/src_corelib_global_qglobal.cpp 37 - \sa qPrintable(), qDebug(), qWarning(), qCritical(), qFatal() + \sa qPrintable(), qDebug(), qInfo(), qWarning(), qCritical(), qFatal() */ /*! @@ -3968,6 +4044,21 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) It expands to "constexpr" if your compiler supports that C++11 keyword, or to nothing otherwise. + + \sa Q_DECL_RELAXED_CONSTEXPR +*/ + +/*! + \macro Q_DECL_RELAXED_CONSTEXPR + \relates <QtGlobal> + + This macro can be used to declare an inline function that can be computed + at compile-time according to the relaxed rules from C++14. + + It expands to "constexpr" if your compiler supports C++14 relaxed constant + expressions, or to nothing otherwise. + + \sa Q_DECL_CONSTEXPR */ /*! @@ -3976,8 +4067,8 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) Calls the message handler with the debug message \a message. If no message handler has been installed, the message is printed to - stderr. Under Windows, the message is sent to the console, if it is a - console application; otherwise, it is sent to the debugger. On Blackberry the + stderr. Under Windows the message is sent to the console, if it is a + console application; otherwise, it is sent to the debugger. On Blackberry, the message is sent to slogger2. This function does nothing if \c QT_NO_DEBUG_OUTPUT was defined during compilation. @@ -4002,7 +4093,44 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) To suppress the output at run-time, install your own message handler with qInstallMessageHandler(). - \sa qWarning(), qCritical(), qFatal(), qInstallMessageHandler(), + \sa qInfo(), qWarning(), qCritical(), qFatal(), qInstallMessageHandler(), + {Debugging Techniques} +*/ + +/*! + \macro qInfo(const char *message, ...) + \relates <QtGlobal> + \since 5.5 + + Calls the message handler with the informational message \a message. If no + message handler has been installed, the message is printed to + stderr. Under Windows, the message is sent to the console, if it is a + console application; otherwise, it is sent to the debugger. On Blackberry the + message is sent to slogger2. This function does nothing if \c QT_NO_INFO_OUTPUT + was defined during compilation. + + If you pass the function a format string and a list of arguments, + it works in similar way to the C printf() function. The format + should be a Latin-1 string. + + Example: + + \snippet code/src_corelib_global_qglobal.cpp qInfo_printf + + If you include \c <QtDebug>, a more convenient syntax is also + available: + + \snippet code/src_corelib_global_qglobal.cpp qInfo_stream + + With this syntax, the function returns a QDebug object that is + configured to use the QtInfoMsg message type. It automatically + puts a single space between each item, and outputs a newline at + the end. It supports many C++ and Qt types. + + To suppress the output at run-time, install your own message handler + with qInstallMessageHandler(). + + \sa qDebug(), qWarning(), qCritical(), qFatal(), qInstallMessageHandler(), {Debugging Techniques} */ @@ -4036,7 +4164,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) To suppress the output at runtime, install your own message handler with qInstallMessageHandler(). - \sa qDebug(), qCritical(), qFatal(), qInstallMessageHandler(), + \sa qDebug(), qInfo(), qCritical(), qFatal(), qInstallMessageHandler(), {Debugging Techniques} */ @@ -4069,7 +4197,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) To suppress the output at runtime, install your own message handler with qInstallMessageHandler(). - \sa qDebug(), qWarning(), qFatal(), qInstallMessageHandler(), + \sa qDebug(), qInfo(), qWarning(), qFatal(), qInstallMessageHandler(), {Debugging Techniques} */ @@ -4096,7 +4224,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) To suppress the output at runtime, install your own message handler with qInstallMessageHandler(). - \sa qDebug(), qCritical(), qWarning(), qInstallMessageHandler(), + \sa qDebug(), qInfo(), qWarning(), qCritical(), qInstallMessageHandler(), {Debugging Techniques} */ |