diff options
author | Oswald Buddenhagen <oswald.buddenhagen@digia.com> | 2013-03-20 13:46:57 +0100 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@digia.com> | 2013-03-20 13:49:28 +0100 |
commit | 76c0be34cd4ff4564693162fa7528463e23ce9d8 (patch) | |
tree | f165b7bc319548fb0082365411a871028f92e89e /src/corelib/global | |
parent | 27b4fe96b59e9e63d1e570e802c072e9afdfb2d4 (diff) | |
parent | 36cb3f3f655a9090c82de609010cbfb88651a0f3 (diff) |
Merge branch 'dev' into stable
This starts Qt 5.1 release cycle
Conflicts:
src/gui/text/qfontdatabase.cpp
src/gui/text/qharfbuzz_copy_p.h
src/widgets/kernel/qapplication.cpp
src/widgets/kernel/qcoreapplication.cpp
Change-Id: I72fbf83ab3c2206aeea1b089428b0fc2a89bd62b
Diffstat (limited to 'src/corelib/global')
23 files changed, 980 insertions, 208 deletions
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 01756c8419..6ac32cd35d 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -9,6 +9,7 @@ HEADERS += \ global/qendian.h \ global/qnumeric_p.h \ global/qnumeric.h \ + global/qglobalstatic.h \ global/qlibraryinfo.h \ global/qlogging.h \ global/qtypeinfo.h \ @@ -19,6 +20,7 @@ HEADERS += \ SOURCES += \ global/qglobal.cpp \ + global/qglobalstatic.cpp \ global/qlibraryinfo.cpp \ global/qmalloc.cpp \ global/qnumeric.cpp \ diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 15229e03a0..e547d58c2e 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -157,6 +157,10 @@ # define Q_CC_CLANG # define Q_ASSUME_IMPL(expr) if (expr){} else __builtin_unreachable() # define Q_UNREACHABLE_IMPL() __builtin_unreachable() +# if !defined(__has_extension) +# /* Compatibility with older Clang versions */ +# define __has_extension __has_feature +# endif # else /* Plain GCC */ # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 @@ -179,6 +183,7 @@ # define Q_TYPEOF(expr) __typeof__(expr) # define Q_DECL_DEPRECATED __attribute__ ((__deprecated__)) # define Q_DECL_ALIGN(n) __attribute__((__aligned__(n))) +# define Q_DECL_UNUSED __attribute__((__unused__)) # define Q_LIKELY(expr) __builtin_expect(!!(expr), true) # define Q_UNLIKELY(expr) __builtin_expect(!!(expr), false) # define Q_NORETURN __attribute__((__noreturn__)) @@ -816,6 +821,9 @@ #ifndef Q_DECL_HIDDEN # define Q_DECL_HIDDEN #endif +#ifndef Q_DECL_UNUSED +# define Q_DECL_UNUSED +#endif #ifndef Q_FUNC_INFO # if defined(Q_OS_SOLARIS) || defined(Q_CC_XLC) # define Q_FUNC_INFO __FILE__ "(line number unavailable)" diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index cdffb10d5a..c9c4d23aab 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -52,8 +52,6 @@ #include <byteswap.h> #endif -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -386,6 +384,4 @@ template <> inline qint8 qbswap<qint8>(qint8 source) QT_END_NAMESPACE -QT_END_HEADER - #endif // QENDIAN_H diff --git a/src/corelib/global/qfeatures.h b/src/corelib/global/qfeatures.h index 7ae4863da3..daf853b916 100644 --- a/src/corelib/global/qfeatures.h +++ b/src/corelib/global/qfeatures.h @@ -154,6 +154,9 @@ // Properties //#define QT_NO_PROPERTIES +// QRegularExpression +//#define QT_NO_REGULAREXPRESSION + // Resize Handler //#define QT_NO_RESIZEHANDLER @@ -235,7 +238,7 @@ // QWheelEvent //#define QT_NO_WHEELEVENT -// +// //#define QT_NO_XMLSTREAM // Animation diff --git a/src/corelib/global/qfeatures.txt b/src/corelib/global/qfeatures.txt index a97309b876..43db585643 100644 --- a/src/corelib/global/qfeatures.txt +++ b/src/corelib/global/qfeatures.txt @@ -28,6 +28,13 @@ Requires: Name: CssParser SeeAlso: ??? +Feature: REGULAREXPRESSION +Description: Perl-compatible regular expression APIs +Section: Kernel +Requires: +Name: QRegularExpression +SeeAlso: ??? + Feature: CONCURRENT Description: Provides a high-level multi-threaded APIs Section: Kernel @@ -318,7 +325,7 @@ SeeAlso: ??? Feature: COMBOBOX Description: Supports comboboxes presenting a list of options to the user. Section: Widgets -Requires: LINEEDIT STANDARDITEMMODEL LISTVIEW +Requires: LINEEDIT STANDARDITEMMODEL LISTVIEW Name: QComboBox SeeAlso: ??? @@ -509,7 +516,7 @@ SeeAlso: ??? Feature: WHATSTHIS Description: Supports displaying "What's this" help. Section: Widgets -Requires: TOOLBUTTON +Requires: TOOLBUTTON Name: QWhatsThis SeeAlso: ??? @@ -629,7 +636,7 @@ SeeAlso: ??? Feature: DIRMODEL Description: Supports a data model for the local filesystem. Section: ItemViews -Requires: ITEMVIEWS FILESYSTEMMODEL +Requires: ITEMVIEWS FILESYSTEMMODEL Name: QDirModel SeeAlso: ??? @@ -1023,7 +1030,7 @@ SeeAlso: ??? Feature: SYSTEMTRAYICON Description: Provides an icon for an application in the system tray. Section: Utilities -Requires: +Requires: Name: QSystemTrayIcon SeeAlso: ??? diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h index 4b75383213..4722fe2282 100644 --- a/src/corelib/global/qflags.h +++ b/src/corelib/global/qflags.h @@ -47,8 +47,6 @@ #include <QtCore/qtypeinfo.h> #include <QtCore/qtypetraits.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class QFlag @@ -152,6 +150,4 @@ typedef uint Flags; QT_END_NAMESPACE -QT_END_HEADER - #endif // QFLAGS_H diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index f0fb9c1a02..c591cc5b49 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -68,7 +68,7 @@ # endif #endif -#if defined(Q_OS_VXWORKS) +#if defined(Q_OS_VXWORKS) && defined(_WRS_KERNEL) # include <envLib.h> #endif @@ -2193,6 +2193,10 @@ bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT \a varName. It will create the variable if it does not exist. It returns 0 if the variable could not be set. + Calling qputenv with an empty value removes the environment variable on + Windows, and makes it set (but empty) on Unix. Prefer using qunsetenv() + for fully portable behavior. + \note qputenv() was introduced because putenv() from the standard C library was deprecated in VC2005 (and later versions). qputenv() uses the replacement function in VC, and calls the standard C @@ -2219,6 +2223,39 @@ bool qputenv(const char *varName, const QByteArray& value) #endif } +/*! + \relates <QtGlobal> + + This function deletes the variable \a varName from the environment. + + Returns true on success. + + \since 5.1 + + \sa qputenv(), qgetenv() +*/ +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 + return unsetenv(varName) == 0; +#elif defined(Q_CC_MINGW) + // On mingw, putenv("var=") removes "var" from the environment + QByteArray buffer(varName); + buffer += '='; + return putenv(buffer.constData()) == 0; +#else + // Fallback to putenv("var=") which will insert an empty var into the + // environment and leak it + QByteArray buffer(varName); + buffer += '='; + char *envVar = qstrdup(buffer.constData()); + return putenv(envVar) == 0; +#endif +} + #if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) # if defined(Q_OS_INTEGRITY) && defined(__GHS_VERSION_NUMBER) && (__GHS_VERSION_NUMBER < 500) @@ -2814,8 +2851,7 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) As a rule of thumb, \c QT_BEGIN_NAMESPACE should appear in all Qt header and Qt source files after the last \c{#include} line and before the first - declaration. In Qt headers using \c QT_BEGIN_HEADER, \c QT_BEGIN_NAMESPACE - follows \c QT_BEGIN_HEADER immediately. + declaration. If that rule can't be followed because, e.g., \c{#include} lines and declarations are wildly mixed, place \c QT_BEGIN_NAMESPACE before diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 13bdc7553f..c45ad12e99 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -45,11 +45,11 @@ #include <stddef.h> -#define QT_VERSION_STR "5.0.2" +#define QT_VERSION_STR "5.1.0" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x050002 +#define QT_VERSION 0x050100 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ @@ -151,6 +151,7 @@ namespace QT_NAMESPACE {} #endif /* __cplusplus */ +// ### Qt6: remove me. #define QT_BEGIN_HEADER #define QT_END_HEADER @@ -158,7 +159,6 @@ namespace QT_NAMESPACE {} # define QT_LARGEFILE_SUPPORT 64 #endif -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE /* @@ -470,7 +470,7 @@ typedef qptrdiff qintptr; # else # define QT_ENSURE_STACK_ALIGNED_FOR_SSE # endif -# define QT_WIN_CALLBACK CALLBACK QT_ENSURE_STACK_ALIGNED_FOR_SSE +# define QT_WIN_CALLBACK CALLBACK QT_ENSURE_STACK_ALIGNED_FOR_SSE #endif typedef int QNoImplicitBoolCast; @@ -512,6 +512,16 @@ template <typename T> Q_DECL_CONSTEXPR inline const T &qBound(const T &min, const T &val, const T &max) { return qMax(min, qMin(max, val)); } +#ifdef Q_OS_DARWIN +# define QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(osx, ios) \ + (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= osx) || \ + (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= ios) + +# define QT_MAC_DEPLOYMENT_TARGET_BELOW(osx, ios) \ + (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && osx != __MAC_NA && __MAC_OS_X_VERSION_MIN_REQUIRED < osx) || \ + (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && ios != __IPHONE_NA && __IPHONE_OS_VERSION_MIN_REQUIRED < ios) +#endif + /* Data stream functions are provided by many classes (defined in qdatastream.h) */ @@ -664,125 +674,6 @@ typedef void (*QFunctionPointer)(); # define Q_UNIMPLEMENTED() qWarning("%s:%d: %s: Unimplemented code.", __FILE__, __LINE__, Q_FUNC_INFO) #endif -#if defined(QT_NO_THREAD) - -template <typename T> -class QGlobalStatic -{ -public: - T *pointer; - inline QGlobalStatic(T *p) : pointer(p) { } - inline ~QGlobalStatic() { pointer = 0; } -}; - -#define Q_GLOBAL_STATIC(TYPE, NAME) \ - static TYPE *NAME() \ - { \ - static TYPE thisVariable; \ - static QGlobalStatic<TYPE > thisGlobalStatic(&thisVariable); \ - return thisGlobalStatic.pointer; \ - } - -#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \ - static TYPE *NAME() \ - { \ - static TYPE thisVariable ARGS; \ - static QGlobalStatic<TYPE > thisGlobalStatic(&thisVariable); \ - return thisGlobalStatic.pointer; \ - } - -#define Q_GLOBAL_STATIC_WITH_INITIALIZER(TYPE, NAME, INITIALIZER) \ - static TYPE *NAME() \ - { \ - static TYPE thisVariable; \ - static QGlobalStatic<TYPE > thisGlobalStatic(0); \ - if (!thisGlobalStatic.pointer) { \ - TYPE *x = thisGlobalStatic.pointer = &thisVariable; \ - INITIALIZER; \ - } \ - return thisGlobalStatic.pointer; \ - } - -#else - -// forward declaration, since qatomic.h needs qglobal.h -template <typename T> class QBasicAtomicPointer; - -// POD for Q_GLOBAL_STATIC -template <typename T> -class QGlobalStatic -{ -public: - QBasicAtomicPointer<T> pointer; - bool destroyed; -}; - -// Created as a function-local static to delete a QGlobalStatic<T> -template <typename T> -class QGlobalStaticDeleter -{ -public: - QGlobalStatic<T> &globalStatic; - QGlobalStaticDeleter(QGlobalStatic<T> &_globalStatic) - : globalStatic(_globalStatic) - { } - - inline ~QGlobalStaticDeleter() - { - delete globalStatic.pointer.load(); - globalStatic.pointer.store(0); - globalStatic.destroyed = true; - } -}; - -#define Q_GLOBAL_STATIC(TYPE, NAME) \ - static TYPE *NAME() \ - { \ - static QGlobalStatic<TYPE > thisGlobalStatic \ - = { Q_BASIC_ATOMIC_INITIALIZER(0), false }; \ - if (!thisGlobalStatic.pointer.load() && !thisGlobalStatic.destroyed) { \ - TYPE *x = new TYPE; \ - if (!thisGlobalStatic.pointer.testAndSetOrdered(0, x)) \ - delete x; \ - else \ - static QGlobalStaticDeleter<TYPE > cleanup(thisGlobalStatic); \ - } \ - return thisGlobalStatic.pointer.load(); \ - } - -#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \ - static TYPE *NAME() \ - { \ - static QGlobalStatic<TYPE > thisGlobalStatic \ - = { Q_BASIC_ATOMIC_INITIALIZER(0), false }; \ - if (!thisGlobalStatic.pointer.load() && !thisGlobalStatic.destroyed) { \ - TYPE *x = new TYPE ARGS; \ - if (!thisGlobalStatic.pointer.testAndSetOrdered(0, x)) \ - delete x; \ - else \ - static QGlobalStaticDeleter<TYPE > cleanup(thisGlobalStatic); \ - } \ - return thisGlobalStatic.pointer.load(); \ - } - -#define Q_GLOBAL_STATIC_WITH_INITIALIZER(TYPE, NAME, INITIALIZER) \ - static TYPE *NAME() \ - { \ - static QGlobalStatic<TYPE > thisGlobalStatic \ - = { Q_BASIC_ATOMIC_INITIALIZER(0), false }; \ - if (!thisGlobalStatic.pointer.load() && !thisGlobalStatic.destroyed) { \ - QScopedPointer<TYPE > x(new TYPE); \ - INITIALIZER; \ - if (thisGlobalStatic.pointer.testAndSetOrdered(0, x.data())) { \ - static QGlobalStaticDeleter<TYPE > cleanup(thisGlobalStatic); \ - x.take(); \ - } \ - } \ - return thisGlobalStatic.pointer.load(); \ - } - -#endif - Q_DECL_CONSTEXPR static inline bool qFuzzyCompare(double p1, double p2) { return (qAbs(p1 - p2) <= 0.000000000001 * qMin(qAbs(p1), qAbs(p2))); @@ -1053,6 +944,7 @@ Q_CORE_EXPORT QString qtTrId(const char *id, int n = -1); class QByteArray; Q_CORE_EXPORT QByteArray qgetenv(const char *varName); Q_CORE_EXPORT bool qputenv(const char *varName, const QByteArray& value); +Q_CORE_EXPORT bool qunsetenv(const char *varName); Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT; Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT; @@ -1087,7 +979,8 @@ template <typename T> struct QEnableIf<true, T> { typedef T Type; }; } QT_END_NAMESPACE -QT_END_HEADER +// Q_GLOBAL_STATIC +#include <QtCore/qglobalstatic.h> // qDebug and friends #include <QtCore/qlogging.h> diff --git a/src/corelib/global/qglobalstatic.cpp b/src/corelib/global/qglobalstatic.cpp new file mode 100644 index 0000000000..8474d132b4 --- /dev/null +++ b/src/corelib/global/qglobalstatic.cpp @@ -0,0 +1,524 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Intel Corporation. +** Contact: http://www.qt-project.org/legal +** +** 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 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. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: 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 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglobalstatic.h" + +/*! + \macro Q_GLOBAL_STATIC(Type, VariableName) + \since 5.1 + \relates QGlobalStatic + + Creates a global and static object of type \l QGlobalStatic, of name \a + VariableName and that behaves as a pointer to \a Type. The object created + by Q_GLOBAL_STATIC initializes itself on the first use, which means that it + will not increase the application or the library's load time. Additionally, + the object is initialized in a thread-safe manner on all platforms. + + The typical use of this macro is as follows, in a global context (that is, + outside of any function bodies): + + \code + Q_GLOBAL_STATIC(MyType, staticType) + \endcode + + This macro is intended to replace global static objects that are not POD + (Plain Old Data, or in C++11 terms, not made of a trivial type), hence the + name. For example, the following C++ code creates a global static: + + \code + static MyType staticType; + \endcode + + Compared to Q_GLOBAL_STATIC, and assuming that \c MyType is a class or + struct that has a constructor, a destructor, or is otherwise non-POD, the + above has the following drawbacks: + + \list + \li it requires load-time initialization of \c MyType (that is, the + default constructor for \c MyType is called when the library or + application is loaded); + + \li the type will be initialized even if it is never used; + + \li the order of initialization and destruction among different + translation units is not determined, leading to possible uses before + initialization or after destruction; + + \li if it is found inside a function (that is, not global), it will be + initialized on first use, but many current compilers (as of 2013) do + not guarantee that the initialization will be thread-safe; + \endlist + + The Q_GLOBAL_STATIC macro solves all of the above problems by guaranteeing + thread-safe initialization on first use and allowing the user to query for + whether the type has already been destroyed, to avoid the + use-after-destruction problem (see QGlobalStatic::isDestroyed()). + + \section1 Constructor and destructor + + For Q_GLOBAL_STATIC, the type \c Type must be publicly + default-constructible and publicly destructible. For + Q_GLOBAL_STATIC_WITH_ARGS(), there must be a public constructor that + matches the arguments passed. + + It is not possible to use Q_GLOBAL_STATIC with types that have protected or + private default constructors or destructors (for Q_GLOBAL_STATIC_WITH_ARGS(), + a protected or private constructor matching the arguments). If the type in + question has those members as protected, it is possible to overcome the + issue by deriving from the type and creating public a constructor and + destructor. If the type has them as private, a friend declaration is + necessary before deriving. + + For example, the following is enough to create \c MyType based on a + previously-defined \c MyOtherType which has a protected default constructor + and/or a protected destructor (or has them as private, but that defines \c + MyType as a friend). + + \code + class MyType : public MyOtherType { }; + Q_GLOBAL_STATIC(MyType, staticType) + \endcode + + No body for \c MyType is required since the destructor is an implicit + member and so is the default constructor if no other constructors are + defined. For use with Q_GLOBAL_STATIC_WITH_ARGS(), however, a suitable + constructor body is necessary: + + \code + class MyType : public MyOtherType + { + public: + MyType(int i) : MyOtherType(i) {} + }; + Q_GLOBAL_STATIC_WITH_ARGS(MyType, staticType, (42)) + \endcode + + Alternatively, if the compiler supports C++11 inheriting constructors, one could write: + + \code + class MyType : public MyOtherType + { + public: + using MyOtherType::MyOtherType; + }; + Q_GLOBAL_STATIC_WITH_ARGS(MyType, staticType, (42)) + \endcode + + \section1 Placement + + The Q_GLOBAL_STATIC macro creates a type that is necessarily static, at the + global scope. It is not possible to place the Q_GLOBAL_STATIC macro inside + a function (doing so will result in compilation errors). + + More importantly, this macro should be placed in source files, never in + headers. Since the resulting object is has static linkage, if the macro is + placed in a header and included by multiple source files, the object will + be defined multiple times and will not cause linking errors. Instead, each + translation unit will refer to a different object, which could lead to + subtle and hard-to-track errors. + + \section1 Non-recommended uses + + Note that the macro is not recommended for use with types that are POD or + that have C++11 constexpr constructors (trivially constructible and + destructible). For those types, it is still recommended to use regular + static, whether global or function-local. + + This macro will work, but it will add unnecessary overhead. + + \section1 Reentrancy, thread-safety, deadlocks, and exception-safety on construction + + The Q_GLOBAL_STATIC macro creates an object that initializes itself on + first use in a thread-safe manner: if multiple threads attempt to + initialize the object at the same time, only one thread will proceed to + initialize, while all other threads wait for completion. + + If the initialization process throws an exception, the initialization is + deemed not complete and will be attempted again when control reaches any + use of the object. If there are any threads waiting for initialization, one + of them will be woken up to attempt to initialize. + + The macro makes no guarantee about reentrancy from the same thread. If the + global static object is accessed directly or indirectly from inside the + constructor, a deadlock will surely happen. + + In addition, if two Q_GLOBAL_STATIC objects are being initialized on two + different threads and each one's initialization sequence accesses the + other, a deadlock might happen. For that reason, it is recommended to keep + global static constructors simple or, failing that, to ensure that there's + no cross-dependency of uses of global static during construction. + + \section1 Destruction + + If the object is never used during the lifetime of the program, aside from + the QGlobalStatic::exists() and QGlobalStatic::isDestroyed() functions, the + contents of type \a Type will not be created and there will not be any + exit-time operation. + + If the object is created, it will be destroyed at exit-time, similar to the + C \c atexit function. On most systems, in fact, the destructor will also be + called if the library or plugin is unloaded from memory before exit. + + Since the destruction is meant to happen at program exit, no thread-safety + is provided. This includes the case of plugin or library unload. In + addition, since destructors are not supposed to throw exceptions, no + exception safety is provided either. + + However, reentrancy is permitted: during destruction, it is possible to + access the global static object and the pointer returned will be the same + as it was before destruction began. After the destruction has completed, + accessing the global static object is not permitted, except as noted in the + \l QGlobalStatic API. + + \omit + \section1 Compatibility with Qt 4 and Qt 5.0 + + This macro, in its current form and behavior, was introduced in Qt 5.1. + Prior to that version, Qt had another macro with the same name that was + private API. This section is not meant to document how to use + Q_GLOBAL_STATIC in those versions, but instead to serve as a porting guide + for Qt code that used those macros. + + The Qt 4 Q_GLOBAL_STATIC macro differed in behavior in the following ways: + + \list + \li the object created was not of type \l QGlobalStatic, but instead + it was a function that returned a pointer to \a Type; that means the + \l QGlobalStatic API was not present; + + \li the initialization was thread-safe, but not guaranteed to be + unique: instead, if N threads tried to initialize the object at the + same time, N objects would be created on the heap and N-1 would be + destroyed; + + \li the object was always created on the heap. + \endlist + + \section1 Implementation details + + Q_GLOBAL_STATIC is implemented by creating a QBasicAtomicInt called the \c + guard and a free, inline function called \c innerFunction. The guard + variable is initialized to value 0 (chosen so that the guard can be placed + in the .bss section of the binary file), which denotes that construction + has not yet taken place (uninitialized). The inner function is implemented + by the helper macro Q_GLOBAL_STATIC_INTERNAL. + + Both the guard variable and the inner function are passed as template + parameters to QGlobalStatic, along with the type \a Type. Both should also + have static linkage or be placed inside an anonymous namespace, so that the + visibility of Q_GLOBAL_STATIC is that of a global static. To permit + multiple Q_GLOBAL_STATIC per translation unit, the guard variable and the + inner function must have unique names, which can be accomplished by + concatenating with \a VariableName or by placing them in a namespace that + has \a VariableName as part of the name. To simplify and improve + readability on Q_GLOBAL_STATIC_INTERNAL, we chose the namespace solution. + It's also required for C++98 builds, since static symbols cannot be used as + template parameters. + + The guard variable can assume the following values: + + \list + \li -2: object was once initialized but has been destroyed already; + \li -1: object was initialized and is still valid; + \li 0: object was not initialized yet; + \li +1: object is being initialized and any threads encountering this + value must wait for completion (not used in the current implementation). + \endlist + + Collectively, all positive values indicate that the initialization is + progressing and must be waited on, whereas all negative values indicate + that the initialization has terminated and must not be attempted again. + Positive values are not used in the current implementation, but were in + earlier versions. They could be used again in the future. + + The QGlobalStatic::exists() and QGlobalStatic::isDestroyed() functions + operate solely on the guard variable: the former returns true if the guard + is negative, whereas the latter returns true only if it is -2. + + The Q_GLOBAL_STATIC_INTERNAL macro implements the actual construction and + destruction. There are two implementations of it: one for compilers that + support thread-safe initialization of function-local statics and one for + compilers that don't. Thread-safe initialization is required by C++11 in + [stmt.decl], but as of the time of this writing, only compilers based on + the IA-64 C++ ABI implemented it properly. The implementation requiring + thread-safe initialization is also used on the Qt bootstrapped tools, which + define QT_NO_THREAD. + + The implementation requiring thread-safe initialization from the compiler + is the simplest: it creates the \a Type object as a function-local static + and returns its address. The actual object is actually inside a holder + structure so holder's destructor can set the guard variable to the value -2 + (destroyed) when the type has finished destruction. Since we need to set + the guard \b after the destruction has finished, this code needs to be in a + base struct's destructor. And it only sets to -2 (destroyed) if it finds + the guard at -1 (initialized): this is done to ensure that the guard isn't + set to -2 in the event the type's constructor threw an exception. A holder + structure is used to avoid creating two statics, which the ABI might + require duplicating the thread-safe control structures for. + + The other implementation is similar to Qt 4's Q_GLOBAL_STATIC, but unlike + that one, it uses a \l QBasicMutex to provide locking. It is also more + efficient memory-wise. It use a simple double-checked locking of the mutex + and then creates the contents on the heap. After that, it creates a + function-local structure called "Cleanup", whose destructor will be run at + program exit and will actually destroy the contents. + + \endomit + + \sa Q_GLOBAL_STATIC_WITH_ARGS(), QGlobalStatic +*/ + +/*! + \macro Q_GLOBAL_STATIC_WITH_ARGS(Type, VariableName, Arguments) + \since 5.1 + \relates QGlobalStatic + + Creates a global and static object of type \l QGlobalStatic, of name \a + VariableName, initialized by the arguments \a Arguments and that behaves as + a pointer to \a Type. The object created by Q_GLOBAL_STATIC_WITH_ARGS + initializes itself on the first use, which means that it will not increase + the application or the library's load time. Additionally, the object is + initialized in a thread-safe manner on all platforms. + + The typical use of this macro is as follows, in a global context (that is, + outside of any function bodies): + + \code + Q_GLOBAL_STATIC_WITH_ARGS(MyType, staticType, (42, "Hello", "World")) + \endcode + + The \a Arguments macro parameter must always include the parentheses or, if + C++11 uniform initialization is allowed, the braces. + + Aside from the actual initialization of the contents with the supplied + arguments, this macro behaves identically to Q_GLOBAL_STATIC(). Please + see that macro's documentation for more information. + + \sa Q_GLOBAL_STATIC(), QGlobalStatic +*/ + +/*! + \class QGlobalStatic + \threadsafe + \inmodule QtCore + \since 5.1 + \brief The QGlobalStatic class is used to implement a global static object + + The QGlobalStatic class is the front-end API exported when + Q_GLOBAL_STATIC() is used. See the documentation for the macro for a + discussion on when to use it and its requirements. + + Normally, you will never use this class directly, but instead you will use + the Q_GLOBAL_STATIC() or Q_GLOBAL_STATIC_WITH_ARGS() macros, as + follows: + + \code + Q_GLOBAL_STATIC(MyType, staticType) + \endcode + + The above example creates an object of type QGlobalStatic called \c + staticType. After the above declaration, the \c staticType object may be + used as if it were a pointer, guaranteed to be initialized exactly once. In + addition to the use as a pointer, the object offers two methods to + determine the current status of the global: exists() and isDestroyed(). + + \sa Q_GLOBAL_STATIC(), Q_GLOBAL_STATIC_WITH_ARGS() +*/ + +/*! + \typedef QGlobalStatic::Type + + This type is equivalent to the \c Type parameter passed to the + Q_GLOBAL_STATIC() or Q_GLOBAL_STATIC_WITH_ARGS() macros. It is used in the + return types of some functions. +*/ + +/*! + \fn bool QGlobalStatic::isDestroyed() const + + This function returns true if the global static object has already + completed destruction (that is, if the destructor for the type has already + returned). In specific, note that this function returns false if + the destruction is still in progress. + + Once this function has returned true once, it will never return + false again until either the program is restarted or the plugin or library + containing the global static is unloaded and reloaded. + + This function is safe to call at any point in the program execution: it + cannot fail and cannot cause a deadlock. Additionally, it will not cause + the contents to be created if they have not yet been created. + + This function is useful in code that may be executed at program shutdown, + to determine whether the contents may still be accessed or not. + + \omit + Due to the non-atomic nature of destruction, it's possible that + QGlobalStatic::isDestroyed might return false for a short time after the + destructor has finished. However, since the destructor is only run in an + environment where concurrent multithreaded access is impossible, no one can + see that state. (omitted because it's useless information) + \endomit + + \sa exists() +*/ + +/*! + \fn bool QGlobalStatic::exists() const + + This function returns true if the global static object has already + completed initialization (that is, if the constructor for the type has + already returned). In specific, note that this function returns false if + the initialization is still in progress. + + Once this function has returned true once, it will never return false again + until either the program is restarted or the plugin or library containing + the global static is unloaded and reloaded. + + This function is safe to call at any point in the program execution: it + cannot fail and cannot cause a deadlock. Additionally, it will not cause + the contents to be created if they have not yet been created. + + This function is useful if one can determine the initial conditions of the + global static object and would prefer to avoid a possibly expensive + construction operation. + + For example, in the following code sample, this function is used to + short-circuit the creation of the global static called \c globalState and + returns a default value: + + \code + Q_GLOBAL_STATIC(MyType, globalState) + QString someState() + { + if (globalState.exists()) + return globalState->someState; + return QString(); + } + \endcode + + \b{Thread-safety notice:} this function is thread-safe in the sense that it + may be called from any thread at any time and will always return a valid + reply. But due to the non-atomic nature of construction, this function may + return false for a short time after the construction has completed. + + \b{Memory ordering notice:} this function does not impose any memory + ordering guarantees. That is instead provided by the accessor functions + that return the pointer or reference to the contents. If you bypass the + accessor functions and attempt to access some global state set by the + constructor, be sure to use the correct memory ordering semantics provided + by \l QAtomicInt or \l QAtomicPointer. + + \sa isDestroyed() +*/ + +/*! + \fn QGlobalStatic::operator Type*() + + This function returns the address of the contents of this global static. If + the contents have not yet been created, they will be created thread-safely + by this function. If the contents have already been destroyed, this + function will return a null pointer. + + This function can be used, for example, to store the pointer to the + contents of the global static in a local variable, thus avoiding multiple + calls to the function. The implementation of Q_GLOBAL_STATIC() is quite + efficient already, but in performance-critical sections it might be useful + to help the compiler a little. For example: + + \code + Q_GLOBAL_STATIC(MyType, globalState) + QString someState() + { + MyType *state = globalState; + if (!state) { + // we're in a post-destruction state + return QString(); + } + if (state->condition) + return state->value1; + else + return state->value2; + } + \endcode + + \sa operator->(), operator*() +*/ + +/*! + \fn Type *QGlobalStatic::operator()() + \deprecated + + This function returns the address of the contents of this global static. If + the contents have not yet been created, they will be created thread-safely + by this function. If the contents have already been destroyed, this + function will return a null pointer. + + This function is equivalent to \l {operator Type *()}. It is provided for + compatibility with the private Q_GLOBAL_STATIC implementation that existed + in Qt 4.x and 5.0. New code should avoid using it and should instead treat + the object as a smart pointer. +*/ + +/*! + \fn Type *QGlobalStatic::operator->() + + This function returns the address of the contents of this global static. If + the contents have not yet been created, they will be created thread-safely + by this function. + + This function does not check if the contents have already been destroyed and + will never return null. If this function is called after the object has + been destroyed, it will return a dangling pointer that should not be + dereferenced. +*/ + +/*! + \fn Type &QGlobalStatic::operator*() + + This function returns a reference to the contents of this global static. If + the contents have not yet been created, they will be created thread-safely + by this function. + + This function does not check if the contents have already been destroyed. + If this function is called after the object has been destroyed, it will + return an invalid reference that must not be used. +*/ diff --git a/src/corelib/global/qglobalstatic.h b/src/corelib/global/qglobalstatic.h new file mode 100644 index 0000000000..a6268e057e --- /dev/null +++ b/src/corelib/global/qglobalstatic.h @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Intel Corporation +** Contact: http://www.qt-project.org/legal +** +** 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 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. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: 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 +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qglobal.h> + +#ifndef QGLOBALSTATIC_H +#define QGLOBALSTATIC_H + +#include <QtCore/qatomic.h> + +QT_BEGIN_NAMESPACE + +namespace QtGlobalStatic { +enum GuardValues { + Destroyed = -2, + Initialized = -1, + Uninitialized = 0, + Initializing = 1 +}; +} + +#if defined(QT_NO_THREAD) || defined(Q_CC_GNU) +// some compilers support thread-safe statics +// The IA-64 C++ ABI requires this, so we know that all GCC versions since 3.4 +// support it. C++11 also requires this behavior. +// Clang and Intel CC masquerade as GCC when compiling on Linux and Mac OS X. + +#define Q_GLOBAL_STATIC_INTERNAL(ARGS) \ + Q_DECL_HIDDEN inline Type *innerFunction() \ + { \ + struct HolderBase { \ + ~HolderBase() Q_DECL_NOTHROW \ + { if (guard.load() == QtGlobalStatic::Initialized) \ + guard.store(QtGlobalStatic::Destroyed); } \ + }; \ + static struct Holder : public HolderBase { \ + Type value; \ + Holder() \ + Q_DECL_NOEXCEPT_EXPR(noexcept(Type ARGS)) \ + : value ARGS \ + { guard.store(QtGlobalStatic::Initialized); } \ + } holder; \ + return &holder.value; \ + } +#else +// We don't know if this compiler supports thread-safe global statics +// so use our own locked implementation + +QT_END_NAMESPACE +#include <QtCore/qmutex.h> +QT_BEGIN_NAMESPACE + +#define Q_GLOBAL_STATIC_INTERNAL(ARGS) \ + Q_DECL_HIDDEN inline Type *innerFunction() \ + { \ + static Type *d; \ + static QBasicMutex mutex; \ + int x = guard.loadAcquire(); \ + if (Q_UNLIKELY(x >= QtGlobalStatic::Uninitialized)) { \ + QMutexLocker locker(&mutex); \ + if (guard.load() == QtGlobalStatic::Uninitialized) { \ + d = new Type ARGS; \ + static struct Cleanup { \ + ~Cleanup() { \ + delete d; \ + guard.store(QtGlobalStatic::Destroyed); \ + } \ + } cleanup; \ + guard.store(QtGlobalStatic::Initialized); \ + } \ + } \ + return d; \ + } +#endif + +// this class must be POD, unless the compiler supports thread-safe statics +template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> +struct QGlobalStatic +{ + typedef T Type; + + bool isDestroyed() const { return guard.load() <= QtGlobalStatic::Destroyed; } + bool exists() const { return guard.load() == QtGlobalStatic::Initialized; } + operator Type *() { if (isDestroyed()) return 0; return innerFunction(); } + Type *operator()() { if (isDestroyed()) return 0; return innerFunction(); } + Type *operator->() { return innerFunction(); } + Type &operator*() { return *innerFunction(); } +}; + +#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS) \ + namespace { namespace Q_QGS_ ## NAME { \ + typedef TYPE Type; \ + QBasicAtomicInt guard = Q_BASIC_ATOMIC_INITIALIZER(QtGlobalStatic::Uninitialized); \ + Q_GLOBAL_STATIC_INTERNAL(ARGS) \ + } } \ + static QGlobalStatic<TYPE, \ + Q_QGS_ ## NAME::innerFunction, \ + Q_QGS_ ## NAME::guard> NAME; + +#define Q_GLOBAL_STATIC(TYPE, NAME) \ + Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ()) + +QT_END_NAMESPACE +#endif // QGLOBALSTATIC_H diff --git a/src/corelib/global/qisenum.h b/src/corelib/global/qisenum.h index 073d5a591f..577007b455 100644 --- a/src/corelib/global/qisenum.h +++ b/src/corelib/global/qisenum.h @@ -62,9 +62,6 @@ #endif // shut up syncqt -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_END_NAMESPACE -QT_END_HEADER - #endif // QISENUM_H diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index 054231b084..1a00a14caf 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -45,8 +45,6 @@ #include <QtCore/qstring.h> #include <QtCore/qdatetime.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE class Q_CORE_EXPORT QLibraryInfo @@ -103,6 +101,4 @@ private: QT_END_NAMESPACE -QT_END_HEADER - #endif // QLIBRARYINFO_H diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 60ba19e625..f95e1e9447 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -57,6 +57,10 @@ #include <slog2.h> #endif +#ifdef Q_OS_ANDROID +#include <android/log.h> +#endif + #include <stdio.h> QT_BEGIN_NAMESPACE @@ -72,8 +76,8 @@ static bool isFatal(QtMsgType msgType) if (msgType == QtFatalMsg) return true; - if (msgType == QtWarningMsg) { - static bool fatalWarnings = qEnvironmentVariableIsSet("QT_FATAL_WARNINGS"); + if (msgType == QtWarningMsg || msgType == QtCriticalMsg) { + static bool fatalWarnings = !qEnvironmentVariableIsEmpty("QT_FATAL_WARNINGS"); return fatalWarnings; } @@ -115,6 +119,7 @@ static bool isFatal(QtMsgType msgType) extern bool usingWinMain; #endif +#ifdef Q_OS_WIN static inline void convert_to_wchar_t_elided(wchar_t *d, size_t space, const char *s) Q_DECL_NOEXCEPT { size_t len = qstrlen(s); @@ -128,6 +133,7 @@ static inline void convert_to_wchar_t_elided(wchar_t *d, size_t space, const cha *d++ = *s++; *d++ = 0; } +#endif #if !defined(QT_NO_EXCEPTIONS) /*! @@ -165,9 +171,7 @@ static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap) Q_DECL fflush(stderr); #endif - if (msgType == QtFatalMsg - || (msgType == QtWarningMsg - && qEnvironmentVariableIsSet("QT_FATAL_WARNINGS"))) { + if (isFatal(msgType)) { #if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) // get the current report mode int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW); @@ -521,6 +525,11 @@ static const char functionTokenC[] = "%{function}"; static const char pidTokenC[] = "%{pid}"; static const char appnameTokenC[] = "%{appname}"; static const char threadidTokenC[] = "%{threadid}"; +static const char ifDebugTokenC[] = "%{if-debug}"; +static const char ifWarningTokenC[] = "%{if-warning}"; +static const char ifCriticalTokenC[] = "%{if-critical}"; +static const char ifFatalTokenC[] = "%{if-fatal}"; +static const char endifTokenC[] = "%{endif}"; static const char emptyTokenC[] = ""; static const char defaultPattern[] = "%{message}"; @@ -607,6 +616,10 @@ void QMessagePattern::setPattern(const QString &pattern) tokens = new const char*[lexemes.size() + 1]; tokens[lexemes.size()] = 0; + bool nestedIfError = false; + bool inIf = false; + QString error; + for (int i = 0; i < lexemes.size(); ++i) { const QString lexeme = lexemes.at(i); if (lexeme.startsWith(QLatin1String("%{")) @@ -630,23 +643,28 @@ void QMessagePattern::setPattern(const QString &pattern) tokens[i] = appnameTokenC; else if (lexeme == QLatin1String(threadidTokenC)) tokens[i] = threadidTokenC; - else { - tokens[i] = emptyTokenC; - QString error = QStringLiteral("QT_MESSAGE_PATTERN: Unknown placeholder %1\n") +#define IF_TOKEN(LEVEL) \ + else if (lexeme == QLatin1String(LEVEL)) { \ + if (inIf) \ + nestedIfError = true; \ + tokens[i] = LEVEL; \ + inIf = true; \ + } + IF_TOKEN(ifDebugTokenC) + IF_TOKEN(ifWarningTokenC) + IF_TOKEN(ifCriticalTokenC) + IF_TOKEN(ifFatalTokenC) +#undef IF_TOKEN + else if (lexeme == QLatin1String(endifTokenC)) { + tokens[i] = endifTokenC; + if (!inIf && !nestedIfError) + error += QStringLiteral("QT_MESSAGE_PATTERN: %{endif} without an %{if-*}\n"); + inIf = false; + } else { + tokens[i] = emptyTokenC; + error += QStringLiteral("QT_MESSAGE_PATTERN: Unknown placeholder %1\n") .arg(lexeme); - -#if defined(Q_OS_WINCE) - OutputDebugString(reinterpret_cast<const wchar_t*>(error.utf16())); - continue; -#elif defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) - if (usingWinMain) { - OutputDebugString(reinterpret_cast<const wchar_t*>(error.utf16())); - continue; - } -#endif - fprintf(stderr, "%s", error.toLocal8Bit().constData()); - fflush(stderr); } } else { char *literal = new char[lexeme.size() + 1]; @@ -656,6 +674,24 @@ void QMessagePattern::setPattern(const QString &pattern) tokens[i] = literal; } } + if (nestedIfError) + error += QStringLiteral("QT_MESSAGE_PATTERN: %{if-*} cannot be nested\n"); + else if (inIf) + error += QStringLiteral("QT_MESSAGE_PATTERN: missing %{endif}\n"); + if (!error.isEmpty()) { +#if defined(Q_OS_WINCE) + OutputDebugString(reinterpret_cast<const wchar_t*>(error.utf16())); + if (0) +#elif defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) + if (usingWinMain) { + OutputDebugString(reinterpret_cast<const wchar_t*>(error.utf16())); + } else +#endif + { + fprintf(stderr, "%s", error.toLocal8Bit().constData()); + fflush(stderr); + } + } literals = new const char*[literalsVar.size() + 1]; literals[literalsVar.size()] = 0; memcpy(literals, literalsVar.constData(), literalsVar.size() * sizeof(const char*)); @@ -735,10 +771,16 @@ Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogCont if (pattern->tokens[0] == 0) return message; + bool skip = false; + // we do not convert file, function, line literals to local encoding due to overhead for (int i = 0; pattern->tokens[i] != 0; ++i) { const char *token = pattern->tokens[i]; - if (token == messageTokenC) { + if (token == endifTokenC) { + skip = false; + } else if (skip) { + // do nothing + } else if (token == messageTokenC) { message.append(str); } else if (token == categoryTokenC) { message.append(QLatin1String(context.category)); @@ -770,6 +812,14 @@ Q_CORE_EXPORT QString qMessageFormatString(QtMsgType type, const QMessageLogCont message.append(QLatin1String("0x")); message.append(QString::number(qlonglong(QThread::currentThread()->currentThread()), 16)); #endif +#define HANDLE_IF_TOKEN(LEVEL) \ + } else if (token == if##LEVEL##TokenC) { \ + skip = type != Qt##LEVEL##Msg; + HANDLE_IF_TOKEN(Debug) + HANDLE_IF_TOKEN(Warning) + HANDLE_IF_TOKEN(Critical) + HANDLE_IF_TOKEN(Fatal) +#undef HANDLE_IF_TOKEN } else { message.append(QLatin1String(token)); } @@ -787,6 +837,24 @@ Q_CORE_EXPORT QtMsgHandler qInstallMsgHandler(QtMsgHandler); static QtMsgHandler msgHandler = 0; // pointer to debug handler (without context) static QtMessageHandler messageHandler = 0; // pointer to debug handler (with context) +#ifdef Q_OS_ANDROID +static void android_default_message_handler(QtMsgType type, + const QMessageLogContext &context, + const QString &message) +{ + android_LogPriority priority; + switch (type) { + case QtDebugMsg: priority = ANDROID_LOG_DEBUG; break; + case QtWarningMsg: priority = ANDROID_LOG_WARN; break; + case QtCriticalMsg: priority = ANDROID_LOG_ERROR; break; + case QtFatalMsg: priority = ANDROID_LOG_FATAL; break; + }; + + __android_log_print(priority, "Qt", "%s:%d (%s): %s", qPrintable(context.file), context.line, + qPrintable(context.function), qPrintable(message)); +} +#endif //Q_OS_ANDROID + /*! \internal */ @@ -807,6 +875,8 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con #if defined(QT_USE_SLOG2) slog2_default_handler(type, logMessage.toLocal8Bit().constData()); +#elif defined(Q_OS_ANDROID) + android_default_message_handler(type, context, logMessage); #else fprintf(stderr, "%s", logMessage.toLocal8Bit().constData()); fflush(stderr); @@ -819,7 +889,7 @@ static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &con static void qDefaultMsgHandler(QtMsgType type, const char *buf) { QMessageLogContext emptyContext; - qDefaultMessageHandler(type, emptyContext, QLatin1String(buf)); + qDefaultMessageHandler(type, emptyContext, QString::fromLocal8Bit(buf)); } static void qt_message_print(QtMsgType msgType, const QMessageLogContext &context, const QString &message) @@ -1009,6 +1079,15 @@ void qErrnoWarning(int code, const char *msg, ...) \row \li \c %{type} \li "debug", "warning", "critical" or "fatal" \endtable + You can also use conditionals on the type of the message using \c %{if-debug}, + \c %{if-warning}, \c %{if-critical} or \c %{if-fatal} followed by an \c %{endif}. + What is inside the \c %{if-*} and \c %{endif} will only be printed if the type matches. + + Example: + \code + QT_MESSAGE_PATTERN="[%{if-debug}D%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}" + \endcode + The default \a pattern is "%{message}". The \a pattern can also be changed at runtime by setting the QT_MESSAGE_PATTERN diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h index 7d8f7313c8..a6f244698d 100644 --- a/src/corelib/global/qlogging.h +++ b/src/corelib/global/qlogging.h @@ -49,7 +49,6 @@ #pragma qt_no_master_include #endif -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE /* @@ -172,6 +171,4 @@ Q_CORE_EXPORT QtMessageHandler qInstallMessageHandler(QtMessageHandler); Q_CORE_EXPORT void qSetMessagePattern(const QString &messagePattern); QT_END_NAMESPACE -QT_END_HEADER - #endif // QLOGGING_H diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index e6cd166832..f130288a24 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -44,8 +44,6 @@ #include <QtCore/qglobal.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -65,7 +63,7 @@ Qt { Q_ENUMS(ScrollBarPolicy FocusPolicy ContextMenuPolicy) Q_ENUMS(ArrowType ToolButtonStyle PenStyle PenCapStyle PenJoinStyle BrushStyle) Q_ENUMS(FillRule MaskMode BGMode ClipOperation SizeMode) - Q_ENUMS(Axis Corner LayoutDirection SizeHint Orientation DropAction) + Q_ENUMS(Axis Corner Edge LayoutDirection SizeHint Orientation DropAction) Q_FLAGS(Alignment Orientations DropActions) Q_FLAGS(DockWidgetAreas ToolBarAreas) Q_ENUMS(DockWidgetArea ToolBarArea) @@ -286,6 +284,7 @@ public: SplashScreen = ToolTip | Dialog, Desktop = 0x00000010 | Window, SubWindow = 0x00000012, + ForeignWindow = 0x00000020 | Window, WindowType_Mask = 0x000000ff, MSWindowsFixedSizeDialogHint = 0x00000100, @@ -327,6 +326,15 @@ public: Q_DECLARE_FLAGS(WindowStates, WindowState) + enum ApplicationState { + ApplicationSuspended = 0x00000000, + ApplicationHidden = 0x00000001, + ApplicationInactive = 0x00000002, + ApplicationActive = 0x00000004 + }; + + Q_DECLARE_FLAGS(ApplicationStates, ApplicationState) + enum ScreenOrientation { PrimaryOrientation = 0x00000000, PortraitOrientation = 0x00000001, @@ -490,6 +498,7 @@ public: AA_X11InitThreads = 10, AA_SynthesizeTouchForUnhandledMouseEvents = 11, AA_SynthesizeMouseForUnhandledTouchEvents = 12, + AA_UseHighDpiPixmaps = 13, // Add new attributes before this line AA_AttributeCount @@ -1194,6 +1203,13 @@ public: BottomRightCorner = 0x00003 }; + enum Edge { + TopEdge = 0x00001, + LeftEdge = 0x00002, + RightEdge = 0x00004, + BottomEdge = 0x00008 + }; + enum ConnectionType { AutoConnection, DirectConnection, @@ -1300,6 +1316,8 @@ public: ImhPreferLatin = 0x200, + ImhMultiLine = 0x400, + ImhDigitsOnly = 0x10000, ImhFormattedNumbersOnly = 0x20000, ImhUppercaseOnly = 0x40000, @@ -1397,7 +1415,8 @@ public: ItemIsDropEnabled = 8, ItemIsUserCheckable = 16, ItemIsEnabled = 32, - ItemIsTristate = 64 + ItemIsTristate = 64, + ItemNeverHasChildren = 128 }; Q_DECLARE_FLAGS(ItemFlags, ItemFlag) @@ -1603,6 +1622,4 @@ public: QT_END_NAMESPACE -QT_END_HEADER - #endif // QNAMESPACE_H diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index cb18dde724..0d9cacdb1f 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -167,6 +167,14 @@ to left button mouse events instead. This attribute is enabled by default. + \value AA_UseHighDpiPixmaps Make QIcon::pixmap() generate high-dpi pixmaps + that can be larger than the requested size. Such pixmaps will have + devicePixelRatio set to a value higher than 1. + + After setting this attribute application code that uses pixmap + sizes in layout geometry calculations should typically divide by + QPixmap::devicePixelRatio() to get device-independent layout geometry. + \omitvalue AA_AttributeCount */ @@ -1710,6 +1718,17 @@ */ /*! + \enum Qt::Edge + + This enum type specifies an edge in a rectangle: + + \value TopEdge The top edge of the rectangle. + \value LeftEdge The left edge of the rectangle. + \value RightEdge The right edge of the rectangle. + \value BottomEdge The bottom edge of the rectangle. +*/ + +/*! \enum Qt::ScrollBarPolicy This enum type describes the various modes of QAbstractScrollArea's scroll @@ -1783,6 +1802,36 @@ */ /*! + \enum Qt::ApplicationState + + \keyword application state + + This enum type is used to specify the current state of the application. + + The states are + + \value ApplicationSuspended The application is about to suspend. When entering this state, the + application should save its state, cease all activities, and be + prepared for code execution to stop. While suspended, the + application can be killed at any time without further warnings + (e.g. when low memory forces the OS to purge suspended applications). + \value ApplicationHidden The application is hidden and runs in the background. This + is the normal state for applications that need to do background + processing, like playing music, while the user interacts with + other applications. The application should free up all graphical + resources when entering this state. + \value ApplicationInactive The application is visible, but not selected to be in front. + On desktop platforms, this typically means that the user + activated another application. On mobile platforms, it is + more common to enter this state when the OS is interrupting + the user with e.g. incoming calls or SMS-messages. + While in this state, consider reducing CPU-intensive tasks. + \value ApplicationActive The application is visible and selected to be in front. + + \since 5.1 +*/ + +/*! \enum Qt::ScreenOrientation This enum type specifies the various orientations a screen might have. @@ -1936,6 +1985,10 @@ \value SubWindow Indicates that this widget is a sub-window, such as a QMdiSubWindow widget. + \value ForeignWindow Indicates that this window object is a handle + representing a native platform window created by + another process or by manually using native code. + There are also a number of flags which you can use to customize the appearance of top-level windows. These have no effect on other windows: @@ -2315,6 +2368,8 @@ \value ImhTime The text editor functions as a time field. \value ImhPreferLatin Latin characters are preferred (but not required). + \value ImhMultiLine Multiple lines can be entered into the text field. + Flags that restrict input (exclusive flags): \value ImhDigitsOnly Only digits are allowed. @@ -2441,6 +2496,7 @@ \value ItemIsUserCheckable It can be checked or unchecked by the user. \value ItemIsEnabled The user can interact with the item. \value ItemIsTristate The item is checkable with three separate states. + \value ItemNeverHasChildren The item never has child items. Note that checkable items need to be given both a suitable set of flags and an initial state, indicating whether the item is checked or not. diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h index f8e84825c0..25db5443eb 100644 --- a/src/corelib/global/qnumeric.h +++ b/src/corelib/global/qnumeric.h @@ -44,8 +44,6 @@ #include <QtCore/qglobal.h> -QT_BEGIN_HEADER - QT_BEGIN_NAMESPACE @@ -65,6 +63,4 @@ Q_CORE_EXPORT double qInf(); QT_END_NAMESPACE -QT_END_HEADER - #endif // QNUMERIC_H diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h index c005c5446e..178afb1db6 100644 --- a/src/corelib/global/qprocessordetection.h +++ b/src/corelib/global/qprocessordetection.h @@ -118,6 +118,7 @@ # define Q_PROCESSOR_ARM_V6 # define Q_PROCESSOR_ARM_V5 # elif defined(__ARM_ARCH_5TEJ__) \ + || defined(__ARM_ARCH_5TE__) \ || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5) \ || (defined(_M_ARM) && _M_ARM-0 >= 5) # define Q_PROCESSOR_ARM_V5 @@ -279,9 +280,9 @@ # if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == Q_BIG_ENDIAN || __BYTE_ORDER__ == Q_LITTLE_ENDIAN) // Reuse __BYTE_ORDER__ as-is, since our Q_*_ENDIAN #defines match the preprocessor defaults # define Q_BYTE_ORDER __BYTE_ORDER__ -# elif defined(__BIG_ENDIAN__) +# elif defined(__BIG_ENDIAN__) || defined(_big_endian__) || defined(_BIG_ENDIAN) # define Q_BYTE_ORDER Q_BIG_ENDIAN -# elif defined(__LITTLE_ENDIAN__) \ +# elif defined(__LITTLE_ENDIAN__) || defined(_little_endian__) || defined(_LITTLE_ENDIAN) \ || defined(_WIN32_WCE) // Windows CE is always little-endian according to MSDN. # define Q_BYTE_ORDER Q_LITTLE_ENDIAN # else diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h index c95c1674eb..edeef3c461 100644 --- a/src/corelib/global/qsysinfo.h +++ b/src/corelib/global/qsysinfo.h @@ -44,7 +44,6 @@ #ifndef QSYSINFO_H #define QSYSINFO_H -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE /* @@ -151,6 +150,4 @@ public: }; QT_END_NAMESPACE -QT_END_HEADER - #endif // QSYSINFO_H diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index 5f9671932f..0caac3d797 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -50,6 +50,8 @@ The operating system, must be one of: (Q_OS_x) DARWIN - Darwin OS (synonym for Q_OS_MAC) + MAC - Mac OS X or iOS (iPhoneOS) + IOS - iOS (treated as a variant of Mac OS) MSDOS - MS-DOS and Windows OS2 - OS/2 OS2EMX - XFree86 on OS/2 (not PM) @@ -78,6 +80,7 @@ LYNX - LynxOS BSD4 - Any BSD 4.4 system UNIX - Any UNIX BSD/SYSV system + ANDROID - Android platform */ #if defined(__APPLE__) && (defined(__GNUC__) || defined(__xlC__) || defined(__xlc__)) @@ -88,6 +91,9 @@ # else # define Q_OS_DARWIN32 # endif +#elif defined(ANDROID) +# define Q_OS_ANDROID +# define Q_OS_LINUX #elif defined(__CYGWIN__) # define Q_OS_CYGWIN #elif !defined(SAG_COM) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__)) @@ -166,6 +172,10 @@ # elif defined(Q_OS_DARWIN32) # define Q_OS_MAC32 # endif +# include <TargetConditionals.h> +# if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +# define Q_OS_IOS +# endif #endif #if defined(Q_OS_WIN) @@ -175,30 +185,50 @@ #endif #ifdef Q_OS_DARWIN -# ifdef MAC_OS_X_VERSION_MIN_REQUIRED -# undef MAC_OS_X_VERSION_MIN_REQUIRED +# include <Availability.h> +# if !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_6 +# undef __MAC_OS_X_VERSION_MIN_REQUIRED +# define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_6 # endif -# define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_4 # include <AvailabilityMacros.h> -# if !defined(MAC_OS_X_VERSION_10_3) -# define MAC_OS_X_VERSION_10_3 MAC_OS_X_VERSION_10_2 + 1 +# if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 +# undef MAC_OS_X_VERSION_MIN_REQUIRED +# define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6 # endif -# if !defined(MAC_OS_X_VERSION_10_4) -# define MAC_OS_X_VERSION_10_4 MAC_OS_X_VERSION_10_3 + 1 +# +# // Numerical checks are preferred to named checks, but to be safe +# // we define the missing version names in case Qt uses them. +# +# if !defined(__MAC_10_7) +# define __MAC_10_7 1070 # endif -# if !defined(MAC_OS_X_VERSION_10_5) -# define MAC_OS_X_VERSION_10_5 MAC_OS_X_VERSION_10_4 + 1 -# endif -# if !defined(MAC_OS_X_VERSION_10_6) -# define MAC_OS_X_VERSION_10_6 MAC_OS_X_VERSION_10_5 + 1 +# if !defined(__MAC_10_8) +# define __MAC_10_8 1080 # endif # if !defined(MAC_OS_X_VERSION_10_7) -# define MAC_OS_X_VERSION_10_7 MAC_OS_X_VERSION_10_6 + 1 +# define MAC_OS_X_VERSION_10_7 1070 # endif # if !defined(MAC_OS_X_VERSION_10_8) -# define MAC_OS_X_VERSION_10_8 MAC_OS_X_VERSION_10_7 + 1 +# define MAC_OS_X_VERSION_10_8 1080 +# endif +# +# if !defined(__IPHONE_4_3) +# define __IPHONE_4_3 40300 +# endif +# if !defined(__IPHONE_5_0) +# define __IPHONE_5_0 50000 +# endif +# if !defined(__IPHONE_5_1) +# define __IPHONE_5_1 50100 +# endif +# if !defined(__IPHONE_6_0) +# define __IPHONE_6_0 60000 +# endif +# if !defined(__IPHONE_6_1) +# define __IPHONE_6_1 60100 # endif -# if (MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_8) +# +# if (__MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_8) # warning "This version of Mac OS X is unsupported" # endif #endif diff --git a/src/corelib/global/qt_windows.h b/src/corelib/global/qt_windows.h index 26b55336ed..c3266c5487 100644 --- a/src/corelib/global/qt_windows.h +++ b/src/corelib/global/qt_windows.h @@ -42,6 +42,11 @@ #ifndef QT_WINDOWS_H #define QT_WINDOWS_H +#if 0 +#pragma qt_sync_skip_header_check +#pragma qt_sync_stop_processing +#endif + #if defined(Q_CC_BOR) // Borland's windows.h does not set these correctly, resulting in // unusable WinSDK standard dialogs diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index 754aa6712b..8e34c9792d 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -44,7 +44,6 @@ #ifndef QTYPEINFO_H #define QTYPEINFO_H -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE /* @@ -241,6 +240,4 @@ Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE); #endif QT_END_NAMESPACE -QT_END_HEADER - #endif // QTYPEINFO_H diff --git a/src/corelib/global/qtypetraits.h b/src/corelib/global/qtypetraits.h index 692a982adf..2ae66da92b 100644 --- a/src/corelib/global/qtypetraits.h +++ b/src/corelib/global/qtypetraits.h @@ -109,7 +109,6 @@ #include <utility> // For pair -QT_BEGIN_HEADER QT_BEGIN_NAMESPACE namespace QtPrivate { @@ -509,6 +508,4 @@ Q_STATIC_ASSERT(( is_signed<qint64>::value)); } // namespace QtPrivate QT_END_NAMESPACE -QT_END_HEADER - #endif // QTYPETRAITS_H |