diff options
Diffstat (limited to 'src')
73 files changed, 1109 insertions, 2465 deletions
diff --git a/src/corelib/concurrent/qtconcurrentexception.cpp b/src/corelib/concurrent/qtconcurrentexception.cpp index 933ad3c264..237152c0d3 100644 --- a/src/corelib/concurrent/qtconcurrentexception.cpp +++ b/src/corelib/concurrent/qtconcurrentexception.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qtconcurrentexception.h" +#include "QtCore/qshareddata.h" #ifndef QT_NO_QFUTURE #ifndef QT_NO_EXCEPTIONS @@ -141,15 +142,14 @@ Exception *UnhandledException::clone() const namespace internal { -class Base +class Base : public QSharedData { public: Base(Exception *exception) - : exception(exception), refCount(1), hasThrown(false) { } + : exception(exception), hasThrown(false) { } ~Base() { delete exception; } Exception *exception; - QAtomicInt refCount; bool hasThrown; }; @@ -158,27 +158,15 @@ ExceptionHolder::ExceptionHolder(Exception *exception) ExceptionHolder::ExceptionHolder(const ExceptionHolder &other) : base(other.base) -{ - base->refCount.ref(); -} +{} void ExceptionHolder::operator=(const ExceptionHolder &other) { - if (base == other.base) - return; - - if (base->refCount.deref() == false) - delete base; - base = other.base; - base->refCount.ref(); } ExceptionHolder::~ExceptionHolder() -{ - if (base->refCount.deref() == 0) - delete base; -} +{} Exception *ExceptionHolder::exception() const { diff --git a/src/corelib/concurrent/qtconcurrentexception.h b/src/corelib/concurrent/qtconcurrentexception.h index b58b3ba23a..1c100a5206 100644 --- a/src/corelib/concurrent/qtconcurrentexception.h +++ b/src/corelib/concurrent/qtconcurrentexception.h @@ -47,6 +47,7 @@ #ifndef QT_NO_QFUTURE #include <QtCore/qatomic.h> +#include <QtCore/qshareddata.h> #ifndef QT_NO_EXCEPTIONS # include <exception> @@ -87,7 +88,7 @@ public: void operator=(const ExceptionHolder &other); ~ExceptionHolder(); Exception *exception() const; - Base *base; + QExplicitlySharedDataPointer<Base> base; }; class Q_CORE_EXPORT ExceptionStore diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index ca8b30fc00..bbc9a15e74 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1642,6 +1642,21 @@ bool qSharedBuild() \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QWS */ +/*! + \macro QT_DISABLE_DEPRECATED_BEFORE + \relates <QtGlobal> + + This macro can be defined in the project file to disable functions deprecated in + a specified version of Qt or any earlier version. The default version number is 5.0, + meaning that functions deprecated in or before Qt 5.0 will not be included. + + Examples: + When using a future release of Qt 5, set QT_DISABLE_DEPRECATED_BEFORE=0x050100 to + disable functions deprecated in Qt 5.1 and earlier. In any release, set + QT_DISABLE_DEPRECATED_BEFORE=0x000000 to enable any functions, including the ones + deprecated in Qt 5.0 + */ + #if defined(QT_BUILD_QMAKE) // needed to bootstrap qmake static const unsigned int qt_one = 1; diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index af9d86c2ca..844fe0528e 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -54,6 +54,23 @@ */ #define QT_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) +#ifndef QT_DISABLE_DEPRECATED_BEFORE +#define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(5, 0, 0) +#endif + +/* + QT_DEPRECATED_SINCE(major, minor) evaluates as true if the Qt version is greater than + the deprecation point specified. + + Use it to specify from which version of Qt a function or class has been deprecated + + Example: + #if QT_DEPRECATED_SINCE(5,1) + QT_DEPRECATED void deprecatedFunction(); //function deprecated sine Qt 5.1 + #endif + */ +#define QT_DEPRECATED_SINCE(major, minor) (QT_VERSION_CHECK(major, minor, 0) > QT_DISABLE_DEPRECATED_BEFORE) + #define QT_PACKAGEDATE_STR "YYYY-MM-DD" #define QT_PACKAGE_TAG "" @@ -516,6 +533,7 @@ namespace QT_NAMESPACE {} # endif # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 /* C++0x features supported in GCC 4.4: */ +# define Q_COMPILER_UNICODE_STRINGS # define Q_COMPILER_VARIADIC_TEMPLATES # define Q_COMPILER_AUTO_TYPE # define Q_COMPILER_EXTERN_TEMPLATES @@ -526,8 +544,12 @@ namespace QT_NAMESPACE {} # if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 /* C++0x features supported in GCC 4.5: */ # define Q_COMPILER_LAMBDA -# define Q_COMPILER_UNICODE_STRINGS # endif +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 + /* C++0x features supported in GCC 4.6: */ +# define Q_COMPILER_CONSTEXPR +# endif + # endif /* IBM compiler versions are a bit messy. There are actually two products: @@ -961,6 +983,7 @@ QT_END_INCLUDE_NAMESPACE #error "Compiler doesn't support the bool type" #endif + /* Constant bool values */ @@ -1091,6 +1114,12 @@ redefine to built-in booleans to make autotests work properly */ # define QT_FASTCALL #endif +#ifdef Q_COMPILER_CONSTEXPR +# define Q_DECL_CONSTEXPR constexpr +#else +# define Q_DECL_CONSTEXPR +#endif + //defines the type for the WNDPROC on windows //the alignment needs to be forced for sse2 to not crash with mingw #if defined(Q_OS_WIN) @@ -1104,10 +1133,6 @@ redefine to built-in booleans to make autotests work properly */ typedef int QNoImplicitBoolCast; -#if defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A) -#define QT_NO_FPU -#endif - // This logic must match the one in qmetatype.h #if defined(QT_COORD_TYPE) typedef QT_COORD_TYPE qreal; @@ -1122,25 +1147,25 @@ typedef double qreal; */ template <typename T> -inline T qAbs(const T &t) { return t >= 0 ? t : -t; } +Q_DECL_CONSTEXPR inline T qAbs(const T &t) { return t >= 0 ? t : -t; } -inline int qRound(qreal d) +Q_DECL_CONSTEXPR inline int qRound(qreal d) { return d >= qreal(0.0) ? int(d + qreal(0.5)) : int(d - int(d-1) + qreal(0.5)) + int(d-1); } #if defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) || defined(QT_ARCH_SYMBIAN) -inline qint64 qRound64(double d) +Q_DECL_CONSTEXPR inline qint64 qRound64(double d) { return d >= 0.0 ? qint64(d + 0.5) : qint64(d - qreal(qint64(d-1)) + 0.5) + qint64(d-1); } #else -inline qint64 qRound64(qreal d) +Q_DECL_CONSTEXPR inline qint64 qRound64(qreal d) { return d >= qreal(0.0) ? qint64(d + qreal(0.5)) : qint64(d - qreal(qint64(d-1)) + qreal(0.5)) + qint64(d-1); } #endif template <typename T> -inline const T &qMin(const T &a, const T &b) { if (a < b) return a; return b; } +Q_DECL_CONSTEXPR inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; } template <typename T> -inline const T &qMax(const T &a, const T &b) { if (a < b) return b; return a; } +Q_DECL_CONSTEXPR inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; } template <typename T> -inline const T &qBound(const T &min, const T &val, const T &max) +Q_DECL_CONSTEXPR inline const T &qBound(const T &min, const T &val, const T &max) { return qMax(min, qMin(max, val)); } /* @@ -1914,12 +1939,12 @@ inline bool operator!=(QBool b1, bool b2) { return !b1 != !b2; } inline bool operator!=(bool b1, QBool b2) { return !b1 != !b2; } inline bool operator!=(QBool b1, QBool b2) { return !b1 != !b2; } -static inline bool qFuzzyCompare(double p1, double p2) +Q_DECL_CONSTEXPR static inline bool qFuzzyCompare(double p1, double p2) { return (qAbs(p1 - p2) <= 0.000000000001 * qMin(qAbs(p1), qAbs(p2))); } -static inline bool qFuzzyCompare(float p1, float p2) +Q_DECL_CONSTEXPR static inline bool qFuzzyCompare(float p1, float p2) { return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2))); } @@ -1927,7 +1952,7 @@ static inline bool qFuzzyCompare(float p1, float p2) /*! \internal */ -static inline bool qFuzzyIsNull(double d) +Q_DECL_CONSTEXPR static inline bool qFuzzyIsNull(double d) { return qAbs(d) <= 0.000000000001; } @@ -1935,7 +1960,7 @@ static inline bool qFuzzyIsNull(double d) /*! \internal */ -static inline bool qFuzzyIsNull(float f) +Q_DECL_CONSTEXPR static inline bool qFuzzyIsNull(float f) { return qAbs(f) <= 0.00001f; } @@ -2203,9 +2228,9 @@ class QFlags int i; public: typedef Enum enum_type; - inline QFlags(const QFlags &f) : i(f.i) {} - inline QFlags(Enum f) : i(f) {} - inline QFlags(Zero = 0) : i(0) {} + Q_DECL_CONSTEXPR inline QFlags(const QFlags &f) : i(f.i) {} + Q_DECL_CONSTEXPR inline QFlags(Enum f) : i(f) {} + Q_DECL_CONSTEXPR inline QFlags(Zero = 0) : i(0) {} inline QFlags(QFlag f) : i(f) {} inline QFlags &operator=(const QFlags &f) { i = f.i; return *this; } @@ -2216,18 +2241,18 @@ public: inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; } inline QFlags &operator^=(Enum f) { i ^= f; return *this; } - inline operator int() const { return i; } + Q_DECL_CONSTEXPR inline operator int() const { return i; } - inline QFlags operator|(QFlags f) const { QFlags g; g.i = i | f.i; return g; } - inline QFlags operator|(Enum f) const { QFlags g; g.i = i | f; return g; } - inline QFlags operator^(QFlags f) const { QFlags g; g.i = i ^ f.i; return g; } - inline QFlags operator^(Enum f) const { QFlags g; g.i = i ^ f; return g; } - inline QFlags operator&(int mask) const { QFlags g; g.i = i & mask; return g; } - inline QFlags operator&(uint mask) const { QFlags g; g.i = i & mask; return g; } - inline QFlags operator&(Enum f) const { QFlags g; g.i = i & f; return g; } - inline QFlags operator~() const { QFlags g; g.i = ~i; return g; } + Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(Enum(i | f.i)); } + Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(Enum(i | f)); } + Q_DECL_CONSTEXPR inline QFlags operator^(QFlags f) const { return QFlags(Enum(i ^ f.i)); } + Q_DECL_CONSTEXPR inline QFlags operator^(Enum f) const { return QFlags(Enum(i ^ f)); } + Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const { return QFlags(Enum(i & mask)); } + Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const { return QFlags(Enum(i & mask)); } + Q_DECL_CONSTEXPR inline QFlags operator&(Enum f) const { return QFlags(Enum(i & f)); } + Q_DECL_CONSTEXPR inline QFlags operator~() const { return QFlags(Enum(~i)); } - inline bool operator!() const { return !i; } + Q_DECL_CONSTEXPR inline bool operator!() const { return !i; } inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == int(f) ); } }; @@ -2240,9 +2265,9 @@ inline QIncompatibleFlag operator|(Flags::enum_type f1, int f2) \ { return QIncompatibleFlag(int(f1) | f2); } #define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \ -inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \ +Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \ { return QFlags<Flags::enum_type>(f1) | f2; } \ -inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) \ +Q_DECL_CONSTEXPR inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) \ { return f2 | f1; } Q_DECLARE_INCOMPATIBLE_FLAGS(Flags) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 5333b71d7b..88f12ab1f7 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -297,11 +297,6 @@ QLibraryInfo::location(LibraryLocation loc) path = QT_CONFIGURE_EXAMPLES_PATH; break; #endif -#ifdef QT_CONFIGURE_DEMOS_PATH - case DemosPath: - path = QT_CONFIGURE_DEMOS_PATH; - break; -#endif default: break; } @@ -352,9 +347,6 @@ QLibraryInfo::location(LibraryLocation loc) case ExamplesPath: key = QLatin1String("Examples"); break; - case DemosPath: - key = QLatin1String("Demos"); - break; default: break; } @@ -500,7 +492,6 @@ QLibraryInfo::location(LibraryLocation loc) \value TranslationsPath The location of translation information for Qt strings. \value SettingsPath The location for Qt settings. \value ExamplesPath The location for examples upon install. - \value DemosPath The location for demos upon install. \sa location() */ diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index 9af53c315c..a8fb90968c 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -75,7 +75,6 @@ public: DataPath, TranslationsPath, SettingsPath, - DemosPath, ExamplesPath, ImportsPath }; diff --git a/src/corelib/io/qtldurl.cpp b/src/corelib/io/qtldurl.cpp index 7db4bbddd5..7d06ca4b17 100644 --- a/src/corelib/io/qtldurl.cpp +++ b/src/corelib/io/qtldurl.cpp @@ -7,29 +7,29 @@ ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** ** 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. +** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** +** 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. ** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. ** ** ** diff --git a/src/corelib/io/qtldurl_p.h b/src/corelib/io/qtldurl_p.h index 152ffa0f63..77c0a15823 100644 --- a/src/corelib/io/qtldurl_p.h +++ b/src/corelib/io/qtldurl_p.h @@ -7,29 +7,29 @@ ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** ** 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. +** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** +** 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. ** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. ** ** ** diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index c134881f31..d12391914b 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -805,7 +805,16 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) // call overhead. QObjectPrivate *d = receiver->d_func(); QThreadData *threadData = d->threadData; - ++threadData->loopLevel; + + // Exception-safety without try/catch + struct Incrementer { + int &variable; + inline Incrementer(int &variable) : variable(variable) + { ++variable; } + inline ~Incrementer() + { --variable; } + }; + Incrementer inc(threadData->loopLevel); #ifdef QT_JAMBI_BUILD int deleteWatch = 0; @@ -816,12 +825,7 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) #endif bool returnValue; - QT_TRY { - returnValue = notify(receiver, event); - } QT_CATCH (...) { - --threadData->loopLevel; - QT_RETHROW; - } + returnValue = notify(receiver, event); #ifdef QT_JAMBI_BUILD // Restore the previous state if the object was not deleted.. @@ -830,7 +834,6 @@ bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event) } QObjectPrivate::resetDeleteWatch(d, oldDeleteWatch, deleteWatch); #endif - --threadData->loopLevel; return returnValue; } @@ -1373,6 +1376,40 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type int &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset; data->postEventList.insertionOffset = data->postEventList.size(); + // Exception-safe cleaning up without the need for a try/catch block + struct CleanUp { + QObject *receiver; + int event_type; + QThreadData *data; + bool exceptionCaught; + + inline CleanUp(QObject *receiver, int event_type, QThreadData *data) : + receiver(receiver), event_type(event_type), data(data), exceptionCaught(true) + {} + inline ~CleanUp() + { + if (exceptionCaught) { + // since we were interrupted, we need another pass to make sure we clean everything up + data->canWait = false; + } + + --data->postEventList.recursion; + if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher) + data->eventDispatcher->wakeUp(); + + // clear the global list, i.e. remove everything that was + // delivered. + if (!event_type && !receiver && data->postEventList.startOffset >= 0) { + const QPostEventList::iterator it = data->postEventList.begin(); + data->postEventList.erase(it, it + data->postEventList.startOffset); + data->postEventList.insertionOffset -= data->postEventList.startOffset; + Q_ASSERT(data->postEventList.insertionOffset >= 0); + data->postEventList.startOffset = 0; + } + } + }; + CleanUp cleanup(receiver, event_type, data); + while (i < data->postEventList.size()) { // avoid live-lock if (i >= data->postEventList.insertionOffset) @@ -1411,7 +1448,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type // first, we diddle the event so that we can deliver // it, and that no one will try to touch it later. pe.event->posted = false; - QEvent * e = pe.event; + QScopedPointer<QEvent> e(pe.event); QObject * r = pe.receiver; --r->d_func()->postedEvents; @@ -1421,49 +1458,23 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type // for the next event. const_cast<QPostEvent &>(pe).event = 0; - locker.unlock(); - // after all that work, it's time to deliver the event. -#ifdef QT_NO_EXCEPTIONS - QCoreApplication::sendEvent(r, e); -#else - try { - QCoreApplication::sendEvent(r, e); - } catch (...) { - delete e; - locker.relock(); - - // since we were interrupted, we need another pass to make sure we clean everything up - data->canWait = false; - - // uglehack: copied from below - --data->postEventList.recursion; - if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher) - data->eventDispatcher->wakeUp(); - throw; // rethrow - } -#endif + struct MutexUnlocker + { + QMutexLocker &m; + MutexUnlocker(QMutexLocker &m) : m(m) { m.unlock(); } + ~MutexUnlocker() { m.relock(); } + }; + MutexUnlocker unlocker(locker); - delete e; - locker.relock(); + // after all that work, it's time to deliver the event. + QCoreApplication::sendEvent(r, e.data()); // careful when adding anything below this point - the // sendEvent() call might invalidate any invariants this // function depends on. } - --data->postEventList.recursion; - if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher) - data->eventDispatcher->wakeUp(); - - // clear the global list, i.e. remove everything that was - // delivered. - if (!event_type && !receiver && data->postEventList.startOffset >= 0) { - const QPostEventList::iterator it = data->postEventList.begin(); - data->postEventList.erase(it, it + data->postEventList.startOffset); - data->postEventList.insertionOffset -= data->postEventList.startOffset; - Q_ASSERT(data->postEventList.insertionOffset >= 0); - data->postEventList.startOffset = 0; - } + cleanup.exceptionCaught = false; } /*! diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index 5a4ce973bc..37c06a2093 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -184,49 +184,47 @@ int QEventLoop::exec(ProcessEventsFlags flags) qWarning("QEventLoop::exec: instance %p has already called exec()", this); return -1; } - d->inExec = true; - d->exit = false; - ++d->threadData->loopLevel; - d->threadData->eventLoops.push(this); - locker.unlock(); + + struct LoopReference { + QEventLoopPrivate *d; + QMutexLocker &locker; + + bool exceptionCaught; + LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true) + { + d->inExec = true; + d->exit = false; + ++d->threadData->loopLevel; + d->threadData->eventLoops.push(d->q_func()); + locker.unlock(); + } + + ~LoopReference() + { + if (exceptionCaught) { + qWarning("Qt has caught an exception thrown from an event handler. Throwing\n" + "exceptions from an event handler is not supported in Qt. You must\n" + "reimplement QApplication::notify() and catch all exceptions there.\n"); + } + locker.relock(); + QEventLoop *eventLoop = d->threadData->eventLoops.pop(); + Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error"); + Q_UNUSED(eventLoop); // --release warning + d->inExec = false; + --d->threadData->loopLevel; + } + }; + LoopReference ref(d, locker); // remove posted quit events when entering a new event loop QCoreApplication *app = QCoreApplication::instance(); if (app && app->thread() == thread()) QCoreApplication::removePostedEvents(app, QEvent::Quit); -#if defined(QT_NO_EXCEPTIONS) while (!d->exit) processEvents(flags | WaitForMoreEvents | EventLoopExec); -#else - try { - while (!d->exit) - processEvents(flags | WaitForMoreEvents | EventLoopExec); - } catch (...) { - qWarning("Qt has caught an exception thrown from an event handler. Throwing\n" - "exceptions from an event handler is not supported in Qt. You must\n" - "reimplement QApplication::notify() and catch all exceptions there.\n"); - - // copied from below - locker.relock(); - QEventLoop *eventLoop = d->threadData->eventLoops.pop(); - Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error"); - Q_UNUSED(eventLoop); // --release warning - d->inExec = false; - --d->threadData->loopLevel; - - throw; - } -#endif - - // copied above - locker.relock(); - QEventLoop *eventLoop = d->threadData->eventLoops.pop(); - Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error"); - Q_UNUSED(eventLoop); // --release warning - d->inExec = false; - --d->threadData->loopLevel; + ref.exceptionCaught = false; return d->returnCode; } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index d573741654..08236a3fec 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -125,6 +125,39 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) } } +struct QConnectionSenderSwitcher { + QObject *receiver; + QObjectPrivate::Sender *previousSender; + QObjectPrivate::Sender currentSender; + bool switched; + + inline QConnectionSenderSwitcher() : switched(false) {} + + inline QConnectionSenderSwitcher(QObject *receiver, QObject *sender, int signal_absolute_id) + { + switchSender(receiver, sender, signal_absolute_id); + } + + inline void switchSender(QObject *receiver, QObject *sender, int signal_absolute_id) + { + this->receiver = receiver; + currentSender.sender = sender; + currentSender.signal = signal_absolute_id; + currentSender.ref = 1; + previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender); + switched = true; + } + + inline ~QConnectionSenderSwitcher() + { + if (switched) + QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); + } +private: + Q_DISABLE_COPY(QConnectionSenderSwitcher) +}; + + void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0; void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0; void (*QAbstractDeclarativeData::objectNameChanged)(QAbstractDeclarativeData *, QObject *) = 0; @@ -1084,23 +1117,10 @@ bool QObject::event(QEvent *e) d_func()->inEventHandler = false; #endif QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e); - QObjectPrivate::Sender currentSender; - currentSender.sender = const_cast<QObject*>(mce->sender()); - currentSender.signal = mce->signalId(); - currentSender.ref = 1; - QObjectPrivate::Sender * const previousSender = - QObjectPrivate::setCurrentSender(this, ¤tSender); -#if defined(QT_NO_EXCEPTIONS) + + QConnectionSenderSwitcher sw(this, const_cast<QObject*>(mce->sender()), mce->signalId()); + mce->placeMetaCall(this); -#else - QT_TRY { - mce->placeMetaCall(this); - } QT_CATCH(...) { - QObjectPrivate::resetCurrentSender(this, ¤tSender, previousSender); - QT_RETHROW; - } -#endif - QObjectPrivate::resetCurrentSender(this, ¤tSender, previousSender); break; } @@ -2977,7 +2997,7 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index, type &= Qt::UniqueConnection - 1; } - QObjectPrivate::Connection *c = new QObjectPrivate::Connection; + QScopedPointer<QObjectPrivate::Connection> c(new QObjectPrivate::Connection); c->sender = s; c->receiver = r; c->method_relative = method_index; @@ -2987,16 +3007,11 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index, c->nextConnectionList = 0; c->callFunction = callFunction; - QT_TRY { - QObjectPrivate::get(s)->addConnection(signal_index, c); - } QT_CATCH(...) { - delete c; - QT_RETHROW; - } + QObjectPrivate::get(s)->addConnection(signal_index, c.data()); c->prev = &(QObjectPrivate::get(r)->senders); c->next = *c->prev; - *c->prev = c; + *c->prev = c.data(); if (c->next) c->next->prev = &c->next; @@ -3007,6 +3022,7 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index, sender_d->connectedSignals[signal_index >> 5] |= (1 << (signal_index & 0x1f)); } + c.take(); // stop tracking return true; } @@ -3265,16 +3281,37 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign Qt::HANDLE currentThreadId = QThread::currentThreadId(); + { QMutexLocker locker(signalSlotLock(sender)); - QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists; - if (!connectionLists) { + struct ConnectionListsRef { + QObjectConnectionListVector *connectionLists; + ConnectionListsRef(QObjectConnectionListVector *connectionLists) : connectionLists(connectionLists) + { + if (connectionLists) + ++connectionLists->inUse; + } + ~ConnectionListsRef() + { + if (!connectionLists) + return; + + --connectionLists->inUse; + Q_ASSERT(connectionLists->inUse >= 0); + if (connectionLists->orphaned) { + if (!connectionLists->inUse) + delete connectionLists; + } + } + + QObjectConnectionListVector *operator->() const { return connectionLists; } + }; + ConnectionListsRef connectionLists = sender->d_func()->connectionLists; + if (!connectionLists.connectionLists) { locker.unlock(); if (qt_signal_spy_callback_set.signal_end_callback != 0) qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index); return; } - ++connectionLists->inUse; - const QObjectPrivate::ConnectionList *list; if (signal_index < connectionLists->count()) @@ -3324,13 +3361,10 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign #endif } - QObjectPrivate::Sender currentSender; - QObjectPrivate::Sender *previousSender = 0; + QConnectionSenderSwitcher sw; + if (receiverInSameThread) { - currentSender.sender = sender; - currentSender.signal = signal_absolute_index; - currentSender.ref = 1; - previousSender = QObjectPrivate::setCurrentSender(receiver, ¤tSender); + sw.switchSender(receiver, sender, signal_absolute_index); } const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction; const int method_relative = c->method_relative; @@ -3355,23 +3389,7 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign argv ? argv : empty_argv); } -#if defined(QT_NO_EXCEPTIONS) metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); -#else - QT_TRY { - metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); - } QT_CATCH(...) { - locker.relock(); - if (receiverInSameThread) - QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); - - --connectionLists->inUse; - Q_ASSERT(connectionLists->inUse >= 0); - if (connectionLists->orphaned && !connectionLists->inUse) - delete connectionLists; - QT_RETHROW; - } -#endif if (qt_signal_spy_callback_set.slot_end_callback != 0) qt_signal_spy_callback_set.slot_end_callback(receiver, method); @@ -3379,9 +3397,6 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign locker.relock(); } - if (receiverInSameThread) - QObjectPrivate::resetCurrentSender(receiver, ¤tSender, previousSender); - if (connectionLists->orphaned) break; } while (c != last && (c = c->nextConnectionList) != 0); @@ -3392,17 +3407,8 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign //start over for all signals; ((list = &connectionLists->allsignals), true)); - --connectionLists->inUse; - Q_ASSERT(connectionLists->inUse >= 0); - if (connectionLists->orphaned) { - if (!connectionLists->inUse) - delete connectionLists; - } else if (connectionLists->dirty) { - sender->d_func()->cleanConnectionLists(); } - locker.unlock(); - if (qt_signal_spy_callback_set.signal_end_callback != 0) qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index); diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 9f54f1a831..26cf2af59c 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -172,15 +172,9 @@ public: inline bool isSharedWith(const QByteArray &other) const { return d == other.d; } void clear(); -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE - const char at(int i) const; - const char operator[](int i) const; - const char operator[](uint i) const; -#else char at(int i) const; char operator[](int i) const; char operator[](uint i) const; -#endif QByteRef operator[](int i); QByteRef operator[](uint i); @@ -359,21 +353,12 @@ inline QByteArray::~QByteArray() { if (!d->ref.deref()) qFree(d); } inline int QByteArray::size() const { return d->size; } -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE -inline const char QByteArray::at(int i) const -{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } -inline const char QByteArray::operator[](int i) const -{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } -inline const char QByteArray::operator[](uint i) const -{ Q_ASSERT(i < uint(size())); return d->data[i]; } -#else inline char QByteArray::at(int i) const { Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } inline char QByteArray::operator[](int i) const { Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } inline char QByteArray::operator[](uint i) const { Q_ASSERT(i < uint(size())); return d->data[i]; } -#endif inline bool QByteArray::isEmpty() const { return d->size == 0; } @@ -412,13 +397,8 @@ class Q_CORE_EXPORT QByteRef { : a(array),i(idx) {} friend class QByteArray; public: -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE - inline operator const char() const - { return i < a.d->size ? a.d->data[i] : char(0); } -#else inline operator char() const { return i < a.d->size ? a.d->data[i] : char(0); } -#endif inline QByteRef &operator=(char c) { if (i >= a.d->size) a.expand(i); else a.detach(); a.d->data[i] = c; return *this; } diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index 9db7d1ae83..475bd55de4 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -1295,11 +1295,7 @@ ushort QChar::toCaseFolded(ushort ucs2) \sa toLatin1(), unicode(), QTextCodec::codecForCStrings() */ -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE -const char QChar::toAscii() const -#else char QChar::toAscii() const -#endif { #ifndef QT_NO_CODEC_FOR_C_STRINGS if (QTextCodec::codecForCStrings()) diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h index b7793403bd..d6db72d5ac 100644 --- a/src/corelib/tools/qchar.h +++ b/src/corelib/tools/qchar.h @@ -56,13 +56,8 @@ struct QLatin1Char { public: inline explicit QLatin1Char(char c) : ch(c) {} -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE - inline const char toLatin1() const { return ch; } - inline const ushort unicode() const { return ushort(uchar(ch)); } -#else inline char toLatin1() const { return ch; } inline ushort unicode() const { return ushort(uchar(ch)); } -#endif private: char ch; @@ -230,20 +225,10 @@ public: UnicodeVersion unicodeVersion() const; -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE - const char toAscii() const; - inline const char toLatin1() const; - inline const ushort unicode() const { return ucs; } -#else char toAscii() const; inline char toLatin1() const; inline ushort unicode() const { return ucs; } -#endif -#ifdef Q_NO_PACKED_REFERENCE - inline ushort &unicode() { return const_cast<ushort&>(ucs); } -#else inline ushort &unicode() { return ucs; } -#endif static QChar fromAscii(char c); static QChar fromLatin1(char c); @@ -339,11 +324,7 @@ Q_DECLARE_TYPEINFO(QChar, Q_MOVABLE_TYPE); inline QChar::QChar() : ucs(0) {} -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE -inline const char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); } -#else inline char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); } -#endif inline QChar QChar::fromLatin1(char c) { return QChar(ushort(uchar(c))); } inline QChar::QChar(uchar c, uchar r) : ucs(ushort((r << 8) | c)){} diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 80c610be36..14dfc6a139 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -164,7 +164,7 @@ void **QListData::append(int n) if (b - n >= 2 * d->alloc / 3) { // we have enough space. Just not at the end -> move it. e -= b; - ::memcpy(d->array, d->array + b, e * sizeof(void *)); + ::memmove(d->array, d->array + b, e * sizeof(void *)); d->begin = 0; } else { realloc(grow(d->alloc + n)); diff --git a/src/corelib/tools/qrefcount.cpp b/src/corelib/tools/qrefcount.cpp new file mode 100644 index 0000000000..c40214b2ab --- /dev/null +++ b/src/corelib/tools/qrefcount.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QtPrivate::RefCount + \internal + + QRefCount implements atomic ref counting for Qt's shared classes. It behaves very similar + to QAtomicInt, but ignores negative ref counts. + + This can be used to allow to implement e.g. const read-only QStringData objects. QString::shared_null and + the qs(...) macro make use of this feature. +*/ diff --git a/src/corelib/tools/qrefcount.h b/src/corelib/tools/qrefcount.h new file mode 100644 index 0000000000..9223cfe352 --- /dev/null +++ b/src/corelib/tools/qrefcount.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia 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. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QREFCOUNT_H +#define QREFCOUNT_H + +#include <QtCore/qatomic.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +namespace QtPrivate +{ + +class RefCount +{ +public: + inline void ref() { + if (atomic >= 0) + atomic.ref(); + } + + inline bool deref() { + if (atomic < 0) + return true; + return atomic.deref(); + } + + inline bool operator==(int value) const + { return atomic.operator ==(value); } + inline bool operator!=(int value) const + { return atomic.operator !=(value); } + inline bool operator!() const + { return atomic.operator !(); } + inline operator int() const + { return atomic.operator int(); } + inline RefCount &operator=(int value) + { atomic = value; return *this; } + + QBasicAtomicInt atomic; +}; + +#define Q_REFCOUNT_INITIALIZER(a) { Q_BASIC_ATOMIC_INITIALIZER(a) } + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index afb396ce50..dab281cdf8 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -720,6 +720,18 @@ const QString::Null QString::null = { }; \section1 More Efficient String Construction + Many strings are known at compile time. But the trivial + constructor QString("Hello"), will convert the string literal + to a QString using the codecForCStrings(). To avoid this one + can use the QStringLiteral macro to directly create the required + data at compile time. Constructing a QString out of the literal + does then not cause any overhead at runtime. + + A slightly less efficient way is to use QLatin1String. This class wraps + a C string literal, precalculates it length at compile time and can + then be used for faster comparison with QStrings and conversion to + QStrings than a regular C string literal. + Using the QString \c{'+'} operator, it is easy to construct a complex string from multiple substrings. You will often write code like this: @@ -735,9 +747,6 @@ const QString::Null QString::null = { }; where \e{n > 2}, there can be as many as \e{n - 1} calls to the memory allocator. - Second, QLatin1String does not store its length internally but - calls qstrlen() when it needs to know its length. - In 4.6, an internal template class \c{QStringBuilder} has been added along with a few helper functions. This class is marked internal and does not appear in the documentation, because you @@ -755,12 +764,6 @@ const QString::Null QString::null = { }; then called \e{once} to get the required space, and the substrings are copied into it one by one. - \c{QLatin1Literal} is a second internal class that can replace - QLatin1String, which can't be changed for compatibility reasons. - \c{QLatin1Literal} stores its length, thereby saving time when - \c{QStringBuilder} computes the amount of memory required for the - final string. - Additional efficiency is gained by inlining and reduced reference counting (the QString created from a \c{QStringBuilder} typically has a ref count of 1, whereas QString::append() needs an extra @@ -797,10 +800,8 @@ const QString::Null QString::null = { }; \sa split() */ -QString::Data QString::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), - 0, 0, shared_null.array, 0, 0, 0, 0, 0, {0} }; -QString::Data QString::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), - 0, 0, shared_empty.array, 0, 0, 0, 0, 0, {0} }; +const QConstStringData<1> QString::shared_null = { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } }; +const QConstStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZER(-1), 0, 0, false, { 0 } }, { 0 } }; int QString::grow(int size) { @@ -1044,20 +1045,15 @@ int QString::toWCharArray(wchar_t *array) const QString::QString(const QChar *unicode, int size) { if (!unicode) { - d = &shared_null; - d->ref.ref(); + d = const_cast<Data *>(&shared_null.str); } else if (size <= 0) { - d = &shared_empty; - d->ref.ref(); + d = const_cast<Data *>(&shared_empty.str); } else { - d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar)); + d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar)); Q_CHECK_PTR(d); - d->ref = 1; - d->alloc = d->size = size; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - memcpy(d->array, unicode, size * sizeof(QChar)); - d->array[size] = '\0'; + *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } }; + memcpy(d->data(), unicode, size * sizeof(QChar)); + d->data()[size] = '\0'; } } @@ -1073,24 +1069,19 @@ QString::QString(const QChar *unicode, int size) QString::QString(const QChar *unicode) { if (!unicode) { - d = &shared_null; - d->ref.ref(); + d = const_cast<Data *>(&shared_null.str); } else { int size = 0; while (unicode[size] != 0) ++size; if (!size) { - d = &shared_empty; - d->ref.ref(); + d = const_cast<Data *>(&shared_empty.str); } else { - d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar)); + d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar)); Q_CHECK_PTR(d); - d->ref = 1; - d->alloc = d->size = size; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - memcpy(d->array, unicode, size * sizeof(QChar)); - d->array[size] = '\0'; + *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } }; + memcpy(d->data(), unicode, size * sizeof(QChar)); + d->data()[size] = '\0'; } } } @@ -1105,18 +1096,14 @@ QString::QString(const QChar *unicode) QString::QString(int size, QChar ch) { if (size <= 0) { - d = &shared_empty; - d->ref.ref(); + d = const_cast<Data *>(&shared_empty.str); } else { - d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar)); + d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar)); Q_CHECK_PTR(d); - d->ref = 1; - d->alloc = d->size = size; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - d->array[size] = '\0'; - ushort *i = d->array + size; - ushort *b = d->array; + *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } }; + d->data()[size] = '\0'; + ushort *i = d->data() + size; + ushort *b = d->data(); const ushort value = ch.unicode(); while (i != b) *--i = value; @@ -1131,13 +1118,10 @@ QString::QString(int size, QChar ch) */ QString::QString(int size, Qt::Initialization) { - d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar)); + d = (Data*) qMalloc(sizeof(Data)+(size+1)*sizeof(QChar)); Q_CHECK_PTR(d); - d->ref = 1; - d->alloc = d->size = size; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - d->array[size] = '\0'; + *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } }; + d->data()[size] = '\0'; } /*! \fn QString::QString(const QLatin1String &str) @@ -1152,15 +1136,11 @@ QString::QString(int size, Qt::Initialization) */ QString::QString(QChar ch) { - void *buf = qMalloc(sizeof(Data) + sizeof(QChar)); - Q_CHECK_PTR(buf); - d = reinterpret_cast<Data *>(buf); - d->ref = 1; - d->alloc = d->size = 1; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - d->array[0] = ch.unicode(); - d->array[1] = '\0'; + d = (Data *) qMalloc(sizeof(Data) + 2*sizeof(QChar)); + Q_CHECK_PTR(d); + *d = (Data) { Q_REFCOUNT_INITIALIZER(1), 1, 1, false, { 0 } }; + d->data()[0] = ch.unicode(); + d->data()[1] = '\0'; } /*! \fn QString::QString(const QByteArray &ba) @@ -1256,21 +1236,23 @@ void QString::resize(int size) if (size < 0) size = 0; - if (size == 0 && !d->capacity) { - Data *x = &shared_empty; - x->ref.ref(); + if (d->offset && d->ref == 1 && size < d->size) { + d->size = size; + return; + } + + if (size == 0 && !d->capacityReserved) { + Data *x = const_cast<Data *>(&shared_empty.str); if (!d->ref.deref()) QString::free(d); d = x; } else { if (d->ref != 1 || size > d->alloc || - (!d->capacity && size < d->size && size < d->alloc >> 1)) + (!d->capacityReserved && size < d->size && size < d->alloc >> 1)) realloc(grow(size)); if (d->alloc >= size) { d->size = size; - if (d->data == d->array) { - d->array[size] = '\0'; - } + d->data()[size] = '\0'; } } } @@ -1328,28 +1310,21 @@ void QString::resize(int size) // ### Qt 5: rename reallocData() to avoid confusion. 197625 void QString::realloc(int alloc) { - if (d->ref != 1 || d->data != d->array) { - Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc * sizeof(QChar))); + if (d->ref != 1 || d->offset) { + Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + (alloc+1) * sizeof(QChar))); Q_CHECK_PTR(x); - x->size = qMin(alloc, d->size); - ::memcpy(x->array, d->data, x->size * sizeof(QChar)); - x->array[x->size] = 0; - x->ref = 1; - x->alloc = alloc; - x->clean = d->clean; - x->simpletext = d->simpletext; - x->righttoleft = d->righttoleft; - x->capacity = d->capacity; - x->data = x->array; + *x = (Data){ Q_REFCOUNT_INITIALIZER(1), qMin(alloc, d->size), alloc, d->capacityReserved, { 0 } }; + ::memcpy(x->data(), d->data(), x->size * sizeof(QChar)); + x->data()[x->size] = 0; if (!d->ref.deref()) QString::free(d); d = x; } else { - Data *p = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar))); + Data *p = static_cast<Data *>(qRealloc(d, sizeof(Data) + (alloc+1) * sizeof(QChar))); Q_CHECK_PTR(p); d = p; d->alloc = alloc; - d->data = d->array; + d->offset = 0; } } @@ -1363,8 +1338,8 @@ void QString::expand(int i) int sz = d->size; resize(qMax(i + 1, sz)); if (d->size - 1 > sz) { - ushort *n = d->data + d->size - 1; - ushort *e = d->data + sz; + ushort *n = d->data() + d->size - 1; + ushort *e = d->data() + sz; while (n != e) * --n = ' '; } @@ -1482,9 +1457,9 @@ QString &QString::insert(int i, const QLatin1String &str) int len = qstrlen(str.latin1()); expand(qMax(d->size, i) + len - 1); - ::memmove(d->data + i + len, d->data + i, (d->size - i - len) * sizeof(QChar)); + ::memmove(d->data() + i + len, d->data() + i, (d->size - i - len) * sizeof(QChar)); for (int j = 0; j < len; ++j) - d->data[i + j] = s[j]; + d->data()[i + j] = s[j]; return *this; } @@ -1501,7 +1476,7 @@ QString& QString::insert(int i, const QChar *unicode, int size) return *this; const ushort *s = (const ushort *)unicode; - if (s >= d->data && s < d->data + d->alloc) { + if (s >= d->data() && s < d->data() + d->alloc) { // Part of me - take a copy ushort *tmp = static_cast<ushort *>(qMalloc(size * sizeof(QChar))); Q_CHECK_PTR(tmp); @@ -1513,8 +1488,8 @@ QString& QString::insert(int i, const QChar *unicode, int size) expand(qMax(d->size, i) + size - 1); - ::memmove(d->data + i + size, d->data + i, (d->size - i - size) * sizeof(QChar)); - memcpy(d->data + i, s, size * sizeof(QChar)); + ::memmove(d->data() + i + size, d->data() + i, (d->size - i - size) * sizeof(QChar)); + memcpy(d->data() + i, s, size * sizeof(QChar)); return *this; } @@ -1532,8 +1507,8 @@ QString& QString::insert(int i, QChar ch) if (i < 0) return *this; expand(qMax(i, d->size)); - ::memmove(d->data + i + 1, d->data + i, (d->size - i) * sizeof(QChar)); - d->data[i] = ch.unicode(); + ::memmove(d->data() + i + 1, d->data() + i, (d->size - i) * sizeof(QChar)); + d->data()[i] = ch.unicode(); return *this; } @@ -1557,15 +1532,15 @@ QString& QString::insert(int i, QChar ch) */ QString &QString::append(const QString &str) { - if (str.d != &shared_null) { - if (d == &shared_null) { + if (str.d != &shared_null.str) { + if (d == &shared_null.str) { operator=(str); } else { if (d->ref != 1 || d->size + str.d->size > d->alloc) realloc(grow(d->size + str.d->size)); - memcpy(d->data + d->size, str.d->data, str.d->size * sizeof(QChar)); + memcpy(d->data() + d->size, str.d->data(), str.d->size * sizeof(QChar)); d->size += str.d->size; - d->data[d->size] = '\0'; + d->data()[d->size] = '\0'; } } return *this; @@ -1583,7 +1558,7 @@ QString &QString::append(const QLatin1String &str) int len = qstrlen((char *)s); if (d->ref != 1 || d->size + len > d->alloc) realloc(grow(d->size + len)); - ushort *i = d->data + d->size; + ushort *i = d->data() + d->size; while ((*i++ = *s++)) ; d->size += len; @@ -1626,8 +1601,8 @@ QString &QString::append(QChar ch) { if (d->ref != 1 || d->size + 1 > d->alloc) realloc(grow(d->size + 1)); - d->data[d->size++] = ch.unicode(); - d->data[d->size] = '\0'; + d->data()[d->size++] = ch.unicode(); + d->data()[d->size] = '\0'; return *this; } @@ -1707,7 +1682,7 @@ QString &QString::remove(int pos, int len) resize(pos); // truncate } else if (len > 0) { detach(); - memmove(d->data + pos, d->data + pos + len, + memmove(d->data() + pos, d->data() + pos + len, (d->size - pos - len + 1) * sizeof(ushort)); d->size -= len; } @@ -1756,14 +1731,14 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs) ushort c = ch.unicode(); if (cs == Qt::CaseSensitive) { while (i < d->size) - if (d->data[i] == ch) + if (d->data()[i] == ch) remove(i, 1); else i++; } else { c = foldCase(c); while (i < d->size) - if (foldCase(d->data[i]) == c) + if (foldCase(d->data()[i]) == c) remove(i, 1); else i++; @@ -1859,10 +1834,10 @@ QString &QString::replace(const QString &before, const QString &after, Qt::CaseS */ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen) { - // copy *after in case it lies inside our own d->data area + // copy *after in case it lies inside our own d->data() area // (which we could possibly invalidate via a realloc or corrupt via memcpy operations.) QChar *afterBuffer = const_cast<QChar *>(after); - if (after >= reinterpret_cast<QChar *>(d->data) && after < reinterpret_cast<QChar *>(d->data) + d->size) { + if (after >= reinterpret_cast<QChar *>(d->data()) && after < reinterpret_cast<QChar *>(d->data()) + d->size) { afterBuffer = static_cast<QChar *>(qMalloc(alen*sizeof(QChar))); Q_CHECK_PTR(afterBuffer); ::memcpy(afterBuffer, after, alen*sizeof(QChar)); @@ -1873,30 +1848,30 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar // replace in place detach(); for (int i = 0; i < nIndices; ++i) - memcpy(d->data + indices[i], afterBuffer, alen * sizeof(QChar)); + memcpy(d->data() + indices[i], afterBuffer, alen * sizeof(QChar)); } else if (alen < blen) { // replace from front detach(); uint to = indices[0]; if (alen) - memcpy(d->data+to, after, alen*sizeof(QChar)); + memcpy(d->data()+to, after, alen*sizeof(QChar)); to += alen; uint movestart = indices[0] + blen; for (int i = 1; i < nIndices; ++i) { int msize = indices[i] - movestart; if (msize > 0) { - memmove(d->data + to, d->data + movestart, msize * sizeof(QChar)); + memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar)); to += msize; } if (alen) { - memcpy(d->data + to, afterBuffer, alen*sizeof(QChar)); + memcpy(d->data() + to, afterBuffer, alen*sizeof(QChar)); to += alen; } movestart = indices[i] + blen; } int msize = d->size - movestart; if (msize > 0) - memmove(d->data + to, d->data + movestart, msize * sizeof(QChar)); + memmove(d->data() + to, d->data() + movestart, msize * sizeof(QChar)); resize(d->size - nIndices*(blen-alen)); } else { // replace from back @@ -1910,9 +1885,9 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar int movestart = indices[nIndices] + blen; int insertstart = indices[nIndices] + nIndices*(alen-blen); int moveto = insertstart + alen; - memmove(d->data + moveto, d->data + movestart, + memmove(d->data() + moveto, d->data() + movestart, (moveend - movestart)*sizeof(QChar)); - memcpy(d->data + insertstart, afterBuffer, alen*sizeof(QChar)); + memcpy(d->data() + insertstart, afterBuffer, alen*sizeof(QChar)); moveend = movestart-blen; } } @@ -1994,7 +1969,7 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs return remove(ch, cs); if (after.d->size == 1) - return replace(ch, after.d->data[0], cs); + return replace(ch, after.d->data()[0], cs); if (d->size == 0) return *this; @@ -2007,13 +1982,13 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs uint pos = 0; if (cs == Qt::CaseSensitive) { while (pos < 1023 && index < d->size) { - if (d->data[index] == cc) + if (d->data()[index] == cc) indices[pos++] = index; index++; } } else { while (pos < 1023 && index < d->size) { - if (QChar::toCaseFolded(d->data[index]) == cc) + if (QChar::toCaseFolded(d->data()[index]) == cc) indices[pos++] = index; index++; } @@ -2045,7 +2020,7 @@ QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs) ushort b = before.unicode(); if (d->size) { detach(); - ushort *i = d->data; + ushort *i = d->data(); const ushort *e = i + d->size; if (cs == Qt::CaseSensitive) { for (; i != e; ++i) @@ -2104,7 +2079,7 @@ QString &QString::replace(const QLatin1String &before, const QString &after, Qt::CaseSensitivity cs) { - int blen = qstrlen(before.latin1()); + int blen = before.size(); QVarLengthArray<ushort> b(blen); for (int i = 0; i < blen; ++i) b[i] = (uchar)before.latin1()[i]; @@ -2127,7 +2102,7 @@ QString &QString::replace(const QString &before, const QLatin1String &after, Qt::CaseSensitivity cs) { - int alen = qstrlen(after.latin1()); + int alen = after.size(); QVarLengthArray<ushort> a(alen); for (int i = 0; i < alen; ++i) a[i] = (uchar)after.latin1()[i]; @@ -2148,7 +2123,7 @@ QString &QString::replace(const QString &before, */ QString &QString::replace(QChar c, const QLatin1String &after, Qt::CaseSensitivity cs) { - int alen = qstrlen(after.latin1()); + int alen = after.size(); QVarLengthArray<ushort> a(alen); for (int i = 0; i < alen; ++i) a[i] = (uchar)after.latin1()[i]; @@ -2170,7 +2145,7 @@ bool QString::operator==(const QString &other) const if (d->size != other.d->size) return false; - return qMemEquals(d->data, other.d->data, d->size); + return qMemEquals(d->data(), other.d->data(), d->size); } /*! @@ -2178,20 +2153,23 @@ bool QString::operator==(const QString &other) const */ bool QString::operator==(const QLatin1String &other) const { - const ushort *uc = d->data; - const ushort *e = uc + d->size; - const uchar *c = (uchar *)other.latin1(); + if (d->size != other.size()) + return false; - if (!c) + if (!other.size()) return isEmpty(); - while (*c) { - if (uc == e || *uc != *c) + const ushort *uc = d->data(); + const ushort *e = uc + d->size; + const uchar *c = (uchar *)other.latin1(); + + while (uc < e) { + if (*uc != *c) return false; ++uc; ++c; } - return (uc == e); + return true; } /*! \fn bool QString::operator==(const QByteArray &other) const @@ -2240,20 +2218,20 @@ bool QString::operator<(const QString &other) const */ bool QString::operator<(const QLatin1String &other) const { - const ushort *uc = d->data; - const ushort *e = uc + d->size; const uchar *c = (uchar *) other.latin1(); - if (!c || *c == 0) return false; - while (*c) { - if (uc == e || *uc != *c) + const ushort *uc = d->data(); + const ushort *e = uc + qMin(d->size, other.size()); + + while (uc < e) { + if (*uc != *c) break; ++uc; ++c; } - return (uc == e ? *c : *uc < *c); + return (uc == (d->data() + d->size) ? *c : *uc < *c); } /*! \fn bool QString::operator<(const QByteArray &other) const @@ -2342,20 +2320,20 @@ bool QString::operator<(const QLatin1String &other) const */ bool QString::operator>(const QLatin1String &other) const { - const ushort *uc = d->data;; - const ushort *e = uc + d->size; const uchar *c = (uchar *) other.latin1(); - if (!c || *c == '\0') return !isEmpty(); - while (*c) { - if (uc == e || *uc != *c) + const ushort *uc = d->data();; + const ushort *e = uc + qMin(d->size, other.size()); + + while (uc < e) { + if (*uc != *c) break; ++uc; ++c; } - return (uc == e ? false : *uc > *c); + return (uc == (d->data() + d->size) ? false : *uc > *c); } /*! \fn bool QString::operator>(const QByteArray &other) const @@ -2687,7 +2665,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c { const int sl = str.d->size; if (sl == 1) - return lastIndexOf(QChar(str.d->data[0]), from, cs); + return lastIndexOf(QChar(str.d->data()[0]), from, cs); const int l = d->size; if (from < 0) @@ -2700,7 +2678,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c if (from > delta) from = delta; - return lastIndexOfHelper(d->data, from, str.d->data, str.d->size, cs); + return lastIndexOfHelper(d->data(), from, str.d->data(), str.d->size, cs); } /*! @@ -2724,7 +2702,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c */ int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) const { - const int sl = qstrlen(str.latin1()); + const int sl = str.size(); if (sl == 1) return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs); @@ -2743,7 +2721,7 @@ int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity for (int i = 0; i < sl; ++i) s[i] = str.latin1()[i]; - return lastIndexOfHelper(d->data, from, s.data(), sl, cs); + return lastIndexOfHelper(d->data(), from, s.data(), sl, cs); } /*! @@ -2789,7 +2767,7 @@ int QString::lastIndexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs if (from > delta) from = delta; - return lastIndexOfHelper(d->data, from, reinterpret_cast<const ushort*>(str.unicode()), + return lastIndexOfHelper(d->data(), from, reinterpret_cast<const ushort*>(str.unicode()), str.size(), cs); } @@ -2940,14 +2918,14 @@ QString& QString::replace(const QRegExp &rx, const QString &after) while (i < pos) { int copyend = replacements[i].pos; int size = copyend - copystart; - memcpy(uc, d->data + copystart, size * sizeof(QChar)); + memcpy(uc, d->data() + copystart, size * sizeof(QChar)); uc += size; - memcpy(uc, after.d->data, al * sizeof(QChar)); + memcpy(uc, after.d->data(), al * sizeof(QChar)); uc += al; copystart = copyend + replacements[i].length; i++; } - memcpy(uc, d->data + copystart, (d->size - copystart) * sizeof(QChar)); + memcpy(uc, d->data() + copystart, (d->size - copystart) * sizeof(QChar)); newstring.resize(newlen); *this = newstring; caretMode = QRegExp::CaretWontMatch; @@ -3366,7 +3344,7 @@ QString QString::left(int n) const { if (n >= d->size || n < 0) return *this; - return QString((const QChar*) d->data, n); + return QString((const QChar*) d->data(), n); } /*! @@ -3384,7 +3362,7 @@ QString QString::right(int n) const { if (n >= d->size || n < 0) return *this; - return QString((const QChar*) d->data + d->size - n, n); + return QString((const QChar*) d->data() + d->size - n, n); } /*! @@ -3406,7 +3384,7 @@ QString QString::right(int n) const QString QString::mid(int position, int n) const { - if (d == &shared_null || position >= d->size) + if (d == &shared_null.str || position >= d->size) return QString(); if (n < 0) n = d->size - position; @@ -3418,7 +3396,7 @@ QString QString::mid(int position, int n) const n = d->size - position; if (position == 0 && n == d->size) return *this; - return QString((const QChar*) d->data + position, n); + return QString((const QChar*) d->data() + position, n); } /*! @@ -3456,8 +3434,8 @@ bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const { return d->size && (cs == Qt::CaseSensitive - ? d->data[0] == c - : foldCase(d->data[0]) == foldCase(c.unicode())); + ? d->data()[0] == c + : foldCase(d->data()[0]) == foldCase(c.unicode())); } /*! @@ -3530,8 +3508,8 @@ bool QString::endsWith(const QChar &c, Qt::CaseSensitivity cs) const { return d->size && (cs == Qt::CaseSensitive - ? d->data[d->size - 1] == c - : foldCase(d->data[d->size - 1]) == foldCase(c.unicode())); + ? d->data()[d->size - 1] == c + : foldCase(d->data()[d->size - 1]) == foldCase(c.unicode())); } /*! \fn const char *QString::ascii() const @@ -3658,10 +3636,6 @@ QByteArray QString::toLatin1() const return toLatin1_helper(unicode(), length()); } -// ### Qt 5: Change the return type of at least toAscii(), -// toLatin1() and unicode() such that the use of Q_COMPILER_MANGLES_RETURN_TYPE -// isn't necessary in the header. See task 177402. - /*! Returns an 8-bit representation of the string as a QByteArray. @@ -3765,22 +3739,17 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size) { Data *d; if (!str) { - d = &shared_null; - d->ref.ref(); + d = const_cast<Data *>(&shared_null.str); } else if (size == 0 || (!*str && size < 0)) { - d = &shared_empty; - d->ref.ref(); + d = const_cast<Data *>(&shared_empty.str); } else { if (size < 0) size = qstrlen(str); - d = static_cast<Data *>(qMalloc(sizeof(Data) + size * sizeof(QChar))); + d = static_cast<Data *>(qMalloc(sizeof(Data) + (size+1) * sizeof(QChar))); Q_CHECK_PTR(d); - d->ref = 1; - d->alloc = d->size = size; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; - d->data = d->array; - d->array[size] = '\0'; - ushort *dst = d->data; + *d = (Data){ Q_REFCOUNT_INITIALIZER(1), size, size, false, { 0 } }; + d->data()[size] = '\0'; + ushort *dst = d->data(); /* SIMD: * Unpacking with SSE has been shown to improve performance on recent CPUs * The same method gives no improvement with NEON. @@ -3818,11 +3787,9 @@ QString::Data *QString::fromAscii_helper(const char *str, int size) if (codecForCStrings) { Data *d; if (!str) { - d = &shared_null; - d->ref.ref(); + d = const_cast<Data *>(&shared_null.str); } else if (size == 0 || (!*str && size < 0)) { - d = &shared_empty; - d->ref.ref(); + d = const_cast<Data *>(&shared_empty.str); } else { if (size < 0) size = qstrlen(str); @@ -3867,7 +3834,7 @@ QString QString::fromLocal8Bit(const char *str, int size) if (!str) return QString(); if (size == 0 || (!*str && size < 0)) - return QLatin1String(""); + return QString(shared_empty); #if !defined(QT_NO_TEXTCODEC) if (size < 0) size = qstrlen(str); @@ -3995,7 +3962,7 @@ QString& QString::setUnicode(const QChar *unicode, int size) { resize(size); if (unicode && size) - memcpy(d->data, unicode, size * sizeof(QChar)); + memcpy(d->data(), unicode, size * sizeof(QChar)); return *this; } @@ -4034,7 +4001,7 @@ QString QString::simplified() const if (d->size == 0) return *this; - const QChar * const start = reinterpret_cast<QChar *>(d->data); + const QChar * const start = reinterpret_cast<QChar *>(d->data()); const QChar *from = start; const QChar *fromEnd = start + d->size; forever { @@ -4043,8 +4010,7 @@ QString QString::simplified() const break; if (++from == fromEnd) { // All-whitespace string - shared_empty.ref.ref(); - return QString(&shared_empty, 0); + return QString(shared_empty); } } // This loop needs no underflow check, as we already determined that @@ -4079,7 +4045,7 @@ QString QString::simplified() const // of already simplified characters - at least one, obviously - // without a trailing space. QString result((fromEnd - from) + copyCount, Qt::Uninitialized); - QChar *to = reinterpret_cast<QChar *>(result.d->data); + QChar *to = reinterpret_cast<QChar *>(result.d->data()); ::memcpy(to, copyFrom, copyCount * 2); to += copyCount; fromEnd--; @@ -4100,7 +4066,7 @@ QString QString::simplified() const } done: *to++ = ch; - result.truncate(to - reinterpret_cast<QChar *>(result.d->data)); + result.truncate(to - reinterpret_cast<QChar *>(result.d->data())); return result; } @@ -4124,7 +4090,7 @@ QString QString::trimmed() const { if (d->size == 0) return *this; - const QChar *s = (const QChar*)d->data; + const QChar *s = (const QChar*)d->data(); if (!s->isSpace() && !s[d->size-1].isSpace()) return *this; int start = 0; @@ -4137,8 +4103,7 @@ QString QString::trimmed() const } int l = end - start + 1; if (l <= 0) { - shared_empty.ref.ref(); - return QString(&shared_empty, 0); + return QString(shared_empty); } return QString(s + start, l); } @@ -4250,8 +4215,8 @@ QString& QString::fill(QChar ch, int size) { resize(size < 0 ? d->size : size); if (d->size) { - QChar *i = (QChar*)d->data + d->size; - QChar *b = (QChar*)d->data; + QChar *i = (QChar*)d->data() + d->size; + QChar *b = (QChar*)d->data(); while (i != b) *--i = ch; } @@ -4597,7 +4562,7 @@ int QString::compare(const QString &other, Qt::CaseSensitivity cs) const { if (cs == Qt::CaseSensitive) return ucstrcmp(constData(), length(), other.constData(), other.length()); - return ucstricmp(d->data, d->data + d->size, other.d->data, other.d->data + other.d->size); + return ucstricmp(d->data(), d->data() + d->size, other.d->data(), other.d->data() + other.d->size); } /*! @@ -4828,12 +4793,9 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, const ushort *QString::utf16() const { - if (d->data != d->array) { - QString *that = const_cast<QString*>(this); - that->realloc(); // ensure '\\0'-termination for ::fromRawData strings - return that->d->data; - } - return d->array; + if (d->offset) + const_cast<QString*>(this)->realloc(); // ensure '\\0'-termination for ::fromRawData strings + return d->data(); } /*! @@ -4862,8 +4824,8 @@ QString QString::leftJustified(int width, QChar fill, bool truncate) const if (padlen > 0) { result.resize(len+padlen); if (len) - memcpy(result.d->data, d->data, sizeof(QChar)*len); - QChar *uc = (QChar*)result.d->data + len; + memcpy(result.d->data(), d->data(), sizeof(QChar)*len); + QChar *uc = (QChar*)result.d->data() + len; while (padlen--) * uc++ = fill; } else { @@ -4900,11 +4862,11 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const int padlen = width - len; if (padlen > 0) { result.resize(len+padlen); - QChar *uc = (QChar*)result.d->data; + QChar *uc = (QChar*)result.d->data(); while (padlen--) * uc++ = fill; if (len) - memcpy(uc, d->data, sizeof(QChar)*len); + memcpy(uc, d->data(), sizeof(QChar)*len); } else { if (truncate) result = left(width); @@ -4924,7 +4886,7 @@ QString QString::rightJustified(int width, QChar fill, bool truncate) const QString QString::toLower() const { - const ushort *p = d->data; + const ushort *p = d->data(); if (!p) return *this; if (!d->size) @@ -4939,7 +4901,7 @@ QString QString::toLower() const } #endif - const ushort *e = d->data + d->size; + const ushort *e = d->data() + d->size; // this avoids one out of bounds check in the loop if (QChar(*p).isLowSurrogate()) @@ -4952,17 +4914,17 @@ QString QString::toLower() const const QUnicodeTables::Properties *prop = qGetProp(c); if (prop->lowerCaseDiff || prop->lowerCaseSpecial) { QString s(d->size, Qt::Uninitialized); - memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort)); - ushort *pp = s.d->data + (p - d->data); + memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort)); + ushort *pp = s.d->data() + (p - d->data()); while (p < e) { uint c = *p; if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate()) c = QChar::surrogateToUcs4(*(p - 1), c); prop = qGetProp(c); if (prop->lowerCaseSpecial) { - int pos = pp - s.d->data; + int pos = pp - s.d->data(); s.resize(s.d->size + SPECIAL_CASE_MAX_LEN); - pp = s.d->data + pos; + pp = s.d->data() + pos; const ushort *specialCase = specialCaseMap + prop->lowerCaseDiff; while (*specialCase) *pp++ = *specialCase++; @@ -4971,7 +4933,7 @@ QString QString::toLower() const } ++p; } - s.truncate(pp - s.d->data); + s.truncate(pp - s.d->data()); return s; } ++p; @@ -4988,11 +4950,11 @@ QString QString::toCaseFolded() const if (!d->size) return *this; - const ushort *p = d->data; + const ushort *p = d->data(); if (!p) return *this; - const ushort *e = d->data + d->size; + const ushort *e = d->data() + d->size; uint last = 0; while (p < e) { @@ -5000,9 +4962,9 @@ QString QString::toCaseFolded() const if (folded != *p) { QString s(*this); s.detach(); - ushort *pp = s.d->data + (p - d->data); - const ushort *ppe = s.d->data + s.d->size; - last = pp > s.d->data ? *(pp - 1) : 0; + ushort *pp = s.d->data() + (p - d->data()); + const ushort *ppe = s.d->data() + s.d->size; + last = pp > s.d->data() ? *(pp - 1) : 0; while (pp < ppe) { *pp = foldCase(*pp, last); ++pp; @@ -5024,7 +4986,7 @@ QString QString::toCaseFolded() const QString QString::toUpper() const { - const ushort *p = d->data; + const ushort *p = d->data(); if (!p) return *this; if (!d->size) @@ -5039,7 +5001,7 @@ QString QString::toUpper() const } #endif - const ushort *e = d->data + d->size; + const ushort *e = d->data() + d->size; // this avoids one out of bounds check in the loop if (QChar(*p).isLowSurrogate()) @@ -5052,17 +5014,17 @@ QString QString::toUpper() const const QUnicodeTables::Properties *prop = qGetProp(c); if (prop->upperCaseDiff || prop->upperCaseSpecial) { QString s(d->size, Qt::Uninitialized); - memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort)); - ushort *pp = s.d->data + (p - d->data); + memcpy(s.d->data(), d->data(), (p - d->data())*sizeof(ushort)); + ushort *pp = s.d->data() + (p - d->data()); while (p < e) { uint c = *p; if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate()) c = QChar::surrogateToUcs4(*(p - 1), c); prop = qGetProp(c); if (prop->upperCaseSpecial) { - int pos = pp - s.d->data; + int pos = pp - s.d->data(); s.resize(s.d->size + SPECIAL_CASE_MAX_LEN); - pp = s.d->data + pos; + pp = s.d->data() + pos; const ushort *specialCase = specialCaseMap + prop->upperCaseDiff; while (*specialCase) *pp++ = *specialCase++; @@ -5071,7 +5033,7 @@ QString QString::toUpper() const } ++p; } - s.truncate(pp - s.d->data); + s.truncate(pp - s.d->data()); return s; } ++p; @@ -6196,19 +6158,19 @@ QString QString::repeated(int times) const if (result.d->alloc != resultSize) return QString(); // not enough memory - memcpy(result.d->data, d->data, d->size * sizeof(ushort)); + memcpy(result.d->data(), d->data(), d->size * sizeof(ushort)); int sizeSoFar = d->size; - ushort *end = result.d->data + sizeSoFar; + ushort *end = result.d->data() + sizeSoFar; const int halfResultSize = resultSize >> 1; while (sizeSoFar <= halfResultSize) { - memcpy(end, result.d->data, sizeSoFar * sizeof(ushort)); + memcpy(end, result.d->data(), sizeSoFar * sizeof(ushort)); end += sizeSoFar; sizeSoFar <<= 1; } - memcpy(end, result.d->data, (resultSize - sizeSoFar) * sizeof(ushort)); - result.d->data[resultSize] = '\0'; + memcpy(end, result.d->data(), (resultSize - sizeSoFar) * sizeof(ushort)); + result.d->data()[resultSize] = '\0'; result.d->size = resultSize; return result; } @@ -6902,7 +6864,7 @@ QString QString::multiArg(int numArgs, const QString **args) const { QString result; QMap<int, int> numbersUsed; - const QChar *uc = (const QChar *) d->data; + const QChar *uc = (const QChar *) d->data(); const int len = d->size; const int end = len - 1; int lastNumber = -1; @@ -6951,62 +6913,50 @@ QString QString::multiArg(int numArgs, const QString **args) const return result; } -static bool isStringRightToLeft(const ushort *p, const ushort *end) -{ - bool righttoleft = false; - while (p < end) { - switch(QChar::direction(*p)) - { - case QChar::DirL: - goto end; - case QChar::DirR: - case QChar::DirAL: - righttoleft = true; - goto end; - default: - break; - } - ++p; - } - end: - return righttoleft; -} -/*! \internal - */ -void QString::updateProperties() const +/*! \fn bool QString::isSimpleText() const + + \internal +*/ +bool QString::isSimpleText() const { - ushort *p = d->data; - ushort *end = p + d->size; - d->simpletext = true; + const ushort *p = d->data(); + const ushort * const end = p + d->size; while (p < end) { ushort uc = *p; // sort out regions of complex text formatting if (uc > 0x058f && (uc < 0x1100 || uc > 0xfb0f)) { - d->simpletext = false; + return false; } p++; } - d->righttoleft = isStringRightToLeft(d->data, d->data + d->size); - d->clean = true; -} - -bool QString::isRightToLeft() const -{ - return isStringRightToLeft(d->data, d->data + d->size); + return true; } -/*! \fn bool QString::isSimpleText() const - - \internal -*/ - /*! \fn bool QString::isRightToLeft() const Returns true if the string is read right to left. */ - +bool QString::isRightToLeft() const +{ + const ushort *p = d->data(); + const ushort * const end = p + d->size; + while (p < end) { + switch(QChar::direction(*p)) + { + case QChar::DirL: + return false; + case QChar::DirR: + case QChar::DirAL: + return true; + default: + break; + } + ++p; + } + return false; +} /*! \fn QChar *QString::data() @@ -7122,17 +7072,13 @@ bool QString::isRightToLeft() const QString QString::fromRawData(const QChar *unicode, int size) { Data *x = static_cast<Data *>(qMalloc(sizeof(Data))); + *x = (Data){ Q_REFCOUNT_INITIALIZER(1), size, 0, false, { 0 } }; Q_CHECK_PTR(x); if (unicode) { - x->data = (ushort *)unicode; + x->offset = (const ushort *)unicode - (x->d + sizeof(qptrdiff)/sizeof(ushort)); } else { - x->data = x->array; size = 0; } - x->ref = 1; - x->alloc = x->size = size; - *x->array = '\0'; - x->clean = x->simpletext = x->righttoleft = x->capacity = 0; return QString(x, 0); } @@ -7152,18 +7098,16 @@ QString QString::fromRawData(const QChar *unicode, int size) */ QString &QString::setRawData(const QChar *unicode, int size) { - if (d->ref != 1 || (d->data == d->array && d->alloc)) { + if (d->ref != 1 || d->alloc) { *this = fromRawData(unicode, size); } else { if (unicode) { - d->data = (ushort *)unicode; + d->size = size; + d->offset = (const ushort *)unicode - (d->d + sizeof(qptrdiff)/sizeof(ushort)); } else { - d->data = d->array; - size = 0; + d->offset = 0; + d->size = 0; } - d->alloc = d->size = size; - *d->array = '\0'; - d->clean = d->simpletext = d->righttoleft = d->capacity = 0; } return *this; } @@ -7212,7 +7156,7 @@ QString &QString::setRawData(const QChar *unicode, int size) \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 6 - \sa QString, QLatin1Char + \sa QString, QLatin1Char, QStringLiteral */ /*! \fn QLatin1String::QLatin1String(const char *str) @@ -7526,7 +7470,7 @@ QDataStream &operator>>(QDataStream &in, QString &str) } } } else { - str = QLatin1String(""); + str = QString(QLatin1String("")); } } return in; @@ -8345,7 +8289,7 @@ QStringRef QString::rightRef(int n) const QStringRef QString::midRef(int position, int n) const { - if (d == &shared_null || position >= d->size) + if (d == &shared_null.str || position >= d->size) return QStringRef(); if (n < 0) n = d->size - position; @@ -8498,7 +8442,7 @@ int QStringRef::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const */ int QStringRef::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) const { - const int sl = qstrlen(str.latin1()); + const int sl = str.size(); if (sl == 1) return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs); @@ -8851,7 +8795,7 @@ static inline int qt_find_latin1_string(const QChar *haystack, int size, int from, Qt::CaseSensitivity cs) { const char *latin1 = needle.latin1(); - int len = qstrlen(latin1); + int len = needle.size(); QVarLengthArray<ushort> s(len); for (int i = 0; i < len; ++i) s[i] = latin1[i]; @@ -8892,7 +8836,7 @@ static inline bool qt_starts_with(const QChar *haystack, int haystackLen, return !needle.latin1(); if (haystackLen == 0) return !needle.latin1() || *needle.latin1() == 0; - const int slen = qstrlen(needle.latin1()); + const int slen = needle.size(); if (slen > haystackLen) return false; const ushort *data = reinterpret_cast<const ushort*>(haystack); @@ -8943,7 +8887,7 @@ static inline bool qt_ends_with(const QChar *haystack, int haystackLen, return !needle.latin1(); if (haystackLen == 0) return !needle.latin1() || *needle.latin1() == 0; - const int slen = qstrlen(needle.latin1()); + const int slen = needle.size(); int pos = haystackLen - slen; if (pos < 0) return false; @@ -9071,4 +9015,21 @@ QVector<uint> QStringRef::toUcs4() const return v; } +/*! + \macro QStringLiteral(str) + \relates QString + + The macro generates the data for a QString out of \a str at compile time if the compiler supports it. + Creating a QString from it is free in this case, and the generated string data is stored in + the read-only segment of the compiled object file. + + Using QStringLiteral instead of a double quoted ascii literal can significantly speed up creation + of QString's from data known at compile time. + + If the compiler is c++0x enabled the string \a str can actually contain unicode data. + + For compilers not supporting the creation of compile time strings, QStringLiteral will fall back to + QLatin1String. +*/ + QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 154012d132..27948e04ea 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -44,7 +44,7 @@ #include <QtCore/qchar.h> #include <QtCore/qbytearray.h> -#include <QtCore/qatomic.h> +#include <QtCore/qrefcount.h> #include <QtCore/qnamespace.h> #ifndef QT_NO_STL @@ -77,9 +77,86 @@ class QLatin1String; class QStringRef; template <typename T> class QVector; +struct QStringData { + QtPrivate::RefCount ref; + int size; + uint alloc : 31; + uint capacityReserved : 1; + union { + qptrdiff offset; // will always work as we add/subtract from a ushort ptr + ushort d[sizeof(qptrdiff)/sizeof(ushort)]; + }; + inline ushort *data() { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; } + inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; } +}; + +template<int N> struct QConstStringData; +template<int N> struct QConstStringDataPtr +{ + const QConstStringData<N> *ptr; +}; + +#if defined(Q_COMPILER_UNICODE_STRINGS) +template<int n> struct QConstStringData +{ + const QStringData str; + const char16_t data[n]; +}; +#define QT_QSTRING_UNICODE_MARKER u"" + +#elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536) +// wchar_t is 2 bytes +template<int n> struct QConstStringData +{ + const QStringData str; + const wchar_t data[n]; +}; +#define QT_QSTRING_UNICODE_MARKER L"" + +#else +template<int n> struct QConstStringData +{ + const QStringData str; + const ushort data[n]; +}; +#endif + +#if defined(QT_QSTRING_UNICODE_MARKER) +# if defined(Q_COMPILER_LAMBDA) +# define QStringLiteral(str) ([]() { \ + enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \ + static const QConstStringData<Size> qstring_literal = \ + { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \ + QConstStringDataPtr<Size> holder = { &qstring_literal }; \ + return holder; }()) + +# elif defined(Q_CC_GNU) +// We need to create a QStringData in the .rodata section of memory +// and the only way to do that is to create a "static const" variable. +// To do that, we need the __extension__ {( )} trick which only GCC supports + +# define QStringLiteral(str) \ + __extension__ ({ \ + enum { Size = sizeof(QT_QSTRING_UNICODE_MARKER str)/2 }; \ + static const QConstStringData<Size> qstring_literal = \ + { { Q_REFCOUNT_INITIALIZER(-1), Size -1, 0, 0, { 0 } }, QT_QSTRING_UNICODE_MARKER str }; \ + QConstStringDataPtr<Size> holder = { &qstring_literal }; \ + holder; }) +# endif +#endif + +#ifndef QStringLiteral +// no lambdas, not GCC, or GCC in C++98 mode with 4-byte wchar_t +// fallback, uses QLatin1String as next best options + +# define QStringLiteral(str) QLatin1String(str) +#endif + class Q_CORE_EXPORT QString { public: + typedef QStringData Data; + inline QString(); QString(const QChar *unicode, int size); // Qt5: don't cap size < 0 explicit QString(const QChar *unicode); // Qt5: merge with the above @@ -108,7 +185,7 @@ public: int capacity() const; inline void reserve(int size); - inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacity = 0;} + inline void squeeze() { if (d->size < d->alloc || d->ref != 1) realloc(); d->capacityReserved = false;} inline const QChar *unicode() const; inline QChar *data(); @@ -262,8 +339,8 @@ public: inline QString &operator+=(QChar c) { if (d->ref != 1 || d->size + 1 > d->alloc) realloc(grow(d->size + 1)); - d->data[d->size++] = c.unicode(); - d->data[d->size] = '\0'; + d->data()[d->size++] = c.unicode(); + d->data()[d->size] = '\0'; return *this; } @@ -491,15 +568,19 @@ public: // compatibility struct Null { }; static const Null null; - inline QString(const Null &): d(&shared_null) { d->ref.ref(); } + inline QString(const Null &): d(const_cast<Data *>(&shared_null.str)) {} inline QString &operator=(const Null &) { *this = QString(); return *this; } - inline bool isNull() const { return d == &shared_null; } + inline bool isNull() const { return d == &shared_null.str; } - bool isSimpleText() const { if (!d->clean) updateProperties(); return d->simpletext; } + bool isSimpleText() const; bool isRightToLeft() const; QString(int size, Qt::Initialization); + template <int n> + inline QString(const QConstStringData<n> &dd) : d(const_cast<QStringData *>(&dd.str)) {} + template <int N> + Q_DECL_CONSTEXPR inline QString(QConstStringDataPtr<N> dd) : d(const_cast<QStringData *>(&dd.ptr->str)) {} private: #if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED) @@ -511,22 +592,11 @@ private: QString &operator=(const QByteArray &a); #endif - struct Data { - QBasicAtomicInt ref; - int alloc, size; - ushort *data; // QT5: put that after the bit field to fill alignment gap; don't use sizeof any more then - ushort clean : 1; - ushort simpletext : 1; - ushort righttoleft : 1; - ushort capacity : 1; - ushort reserved : 11; - // ### Qt5: try to ensure that "array" is aligned to 16 bytes on both 32- and 64-bit - ushort array[1]; - }; - static Data shared_null; - static Data shared_empty; + static const QConstStringData<1> shared_null; + static const QConstStringData<1> shared_empty; Data *d; - QString(Data *dd, int /*dummy*/) : d(dd) {} + inline QString(Data *dd, int /*dummy*/) : d(dd) {} + #ifndef QT_NO_TEXTCODEC static QTextCodec *codecForCStrings; #endif @@ -563,11 +633,11 @@ public: class Q_CORE_EXPORT QLatin1String { public: - inline explicit QLatin1String(const char *s) : chars(s) {} - inline QLatin1String &operator=(const QLatin1String &other) - { chars = other.chars; return *this; } + inline explicit QLatin1String(const char *s) : m_size(s ? strlen(s) : 0), m_data(s) {} - inline const char *latin1() const { return chars; } + inline const char *latin1() const { return m_data; } + inline int size() const { return m_size; } + inline const char *data() const { return m_data; } inline bool operator==(const QString &s) const { return s == *this; } @@ -595,9 +665,12 @@ public: inline QT_ASCII_CAST_WARN bool operator>=(const char *s) const { return QString::fromAscii(s) <= *this; } private: - const char *chars; + int m_size; + const char *m_data; }; +// Qt 4.x compatibility +typedef QLatin1String QLatin1Literal; inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLatin1.latin1())) @@ -605,23 +678,23 @@ inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLat inline int QString::length() const { return d->size; } inline const QChar QString::at(int i) const -{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; } +{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; } inline const QChar QString::operator[](int i) const -{ Q_ASSERT(uint(i) < uint(size())); return d->data[i]; } +{ Q_ASSERT(uint(i) < uint(size())); return d->data()[i]; } inline const QChar QString::operator[](uint i) const -{ Q_ASSERT(i < uint(size())); return d->data[i]; } +{ Q_ASSERT(i < uint(size())); return d->data()[i]; } inline bool QString::isEmpty() const { return d->size == 0; } inline const QChar *QString::unicode() const -{ return reinterpret_cast<const QChar*>(d->data); } +{ return reinterpret_cast<const QChar*>(d->data()); } inline const QChar *QString::data() const -{ return reinterpret_cast<const QChar*>(d->data); } +{ return reinterpret_cast<const QChar*>(d->data()); } inline QChar *QString::data() -{ detach(); return reinterpret_cast<QChar*>(d->data); } +{ detach(); return reinterpret_cast<QChar*>(d->data()); } inline const QChar *QString::constData() const -{ return reinterpret_cast<const QChar*>(d->data); } +{ return reinterpret_cast<const QChar*>(d->data()); } inline void QString::detach() -{ if (d->ref != 1 || d->data != d->array) realloc(); } +{ if (d->ref != 1 || d->offset) realloc(); } inline bool QString::isDetached() const { return d->ref == 1; } inline QString &QString::operator=(const QLatin1String &s) @@ -703,10 +776,10 @@ public: // all this is not documented: We just say "like QChar" and let it be. inline operator QChar() const - { return i < s.d->size ? s.d->data[i] : 0; } + { return i < s.d->size ? s.d->data()[i] : 0; } inline QCharRef &operator=(const QChar &c) { if (i >= s.d->size) s.expand(i); else s.detach(); - s.d->data[i] = c.unicode(); return *this; } + s.d->data()[i] = c.unicode(); return *this; } // An operator= for each QChar cast constructors #ifndef QT_NO_CAST_FROM_ASCII @@ -756,15 +829,9 @@ public: inline void setCell(uchar cell); inline void setRow(uchar row); -#ifdef Q_COMPILER_MANGLES_RETURN_TYPE - const char toAscii() const { return QChar(*this).toAscii(); } - const char toLatin1() const { return QChar(*this).toLatin1(); } - const ushort unicode() const { return QChar(*this).unicode(); } -#else char toAscii() const { return QChar(*this).toAscii(); } char toLatin1() const { return QChar(*this).toLatin1(); } ushort unicode() const { return QChar(*this).unicode(); } -#endif ushort& unicode() { return s.data()[i].unicode(); } }; @@ -773,9 +840,9 @@ inline void QCharRef::setRow(uchar arow) { QChar(*this).setRow(arow); } inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); } -inline QString::QString() : d(&shared_null) { d->ref.ref(); } +inline QString::QString() : d(const_cast<Data *>(&shared_null.str)) {} inline QString::~QString() { if (!d->ref.deref()) free(d); } -inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacity = 1;} +inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacityReserved = true;} inline QString &QString::setUtf16(const ushort *autf16, int asize) { return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); } inline QCharRef QString::operator[](int i) @@ -783,17 +850,17 @@ inline QCharRef QString::operator[](int i) inline QCharRef QString::operator[](uint i) { return QCharRef(*this, i); } inline QString::iterator QString::begin() -{ detach(); return reinterpret_cast<QChar*>(d->data); } +{ detach(); return reinterpret_cast<QChar*>(d->data()); } inline QString::const_iterator QString::begin() const -{ return reinterpret_cast<const QChar*>(d->data); } +{ return reinterpret_cast<const QChar*>(d->data()); } inline QString::const_iterator QString::constBegin() const -{ return reinterpret_cast<const QChar*>(d->data); } +{ return reinterpret_cast<const QChar*>(d->data()); } inline QString::iterator QString::end() -{ detach(); return reinterpret_cast<QChar*>(d->data + d->size); } +{ detach(); return reinterpret_cast<QChar*>(d->data() + d->size); } inline QString::const_iterator QString::end() const -{ return reinterpret_cast<const QChar*>(d->data + d->size); } +{ return reinterpret_cast<const QChar*>(d->data() + d->size); } inline QString::const_iterator QString::constEnd() const -{ return reinterpret_cast<const QChar*>(d->data + d->size); } +{ return reinterpret_cast<const QChar*>(d->data() + d->size); } inline QBool QString::contains(const QString &s, Qt::CaseSensitivity cs) const { return QBool(indexOf(s, 0, cs) != -1); } inline QBool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const @@ -1024,7 +1091,7 @@ public: inline const QChar *unicode() const { if (!m_string) - return reinterpret_cast<const QChar *>(QString::shared_null.data); + return reinterpret_cast<const QChar *>(QString::shared_null.str.data()); return m_string->unicode() + m_position; } inline const QChar *data() const { return unicode(); } @@ -1154,7 +1221,6 @@ inline QBool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) c { return QBool(indexOf(s, 0, cs) != -1); } - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp index 1cc7e5d2c3..4c6848498b 100644 --- a/src/corelib/tools/qstringbuilder.cpp +++ b/src/corelib/tools/qstringbuilder.cpp @@ -45,47 +45,6 @@ QT_BEGIN_NAMESPACE /*! - \class QLatin1Literal - \internal - \reentrant - \since 4.6 - - \brief The QLatin1Literal class provides a thin wrapper around string - literals used in source code. - - \ingroup tools - \ingroup shared - \ingroup string-processing - - - Unlike \c QLatin1String, a \c QLatin1Literal can retrieve its size - without iterating over the literal. - - The main use of \c QLatin1Literal is in conjunction with \c QStringBuilder - to reduce the number of reallocations needed to build up a string from - smaller chunks. - - \sa QStringBuilder, QLatin1String, QString, QStringRef -*/ - -/*! \fn int QLatin1Literal::size() const - - Returns the number of characters in the literal \e{excluding} the trailing - NULL char. -*/ - -/*! \fn QLatin1Literal::QLatin1Literal(const char str) - - Constructs a new literal from the string \a str. -*/ - -/*! \fn const char *QLatin1Literal::data() const - - Returns a pointer to the first character of the string literal. - The string literal is terminated by a NUL character. -*/ - -/*! \class QStringBuilder \internal \reentrant @@ -110,7 +69,7 @@ QT_BEGIN_NAMESPACE The QStringBuilder class is not to be used explicitly in user code. Instances of the class are created as return values of the operator%() function, acting on objects of type QString, - QLatin1String, QLatin1Literal, QStringRef, QChar, QCharRef, + QLatin1String, QStringRef, QChar, QCharRef, QLatin1Char, and \c char. Concatenating strings with operator%() generally yields better @@ -118,7 +77,7 @@ QT_BEGIN_NAMESPACE if there are three or more of them, and performs equally well in other cases. - \sa QLatin1Literal, QString + \sa QLatin1String, QString */ /*! \fn QStringBuilder::QStringBuilder(const A &a, const B &b) @@ -132,7 +91,7 @@ QT_BEGIN_NAMESPACE takes a QString parameter. This function is usable with arguments of type \c QString, - \c QLatin1String, \c QLatin1Literal, \c QStringRef, + \c QLatin1String, \c QStringRef, \c QChar, \c QCharRef, \c QLatin1Char, and \c char. */ @@ -145,7 +104,7 @@ QT_BEGIN_NAMESPACE /*! \fn operator QStringBuilder::QString() const - Converts the \c QLatin1Literal into a \c QString object. + Converts the \c QLatin1String into a \c QString object. */ /*! \internal diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 594ab2f183..6d998b62aa 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -59,22 +59,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) -// ### Qt 5: merge with QLatin1String -class QLatin1Literal -{ -public: - int size() const { return m_size; } - const char *data() const { return m_data; } - - template <int N> - QLatin1Literal(const char (&str)[N]) - : m_size(N - 1), m_data(str) {} - -private: - const int m_size; - const char * const m_data; -}; - struct Q_CORE_EXPORT QAbstractConcatenable { protected: @@ -234,31 +218,13 @@ template <> struct QConcatenable<QLatin1String> typedef QLatin1String type; typedef QString ConvertTo; enum { ExactSize = true }; - static int size(const QLatin1String &a) { return qstrlen(a.latin1()); } + static int size(const QLatin1String &a) { return a.size(); } static inline void appendTo(const QLatin1String &a, QChar *&out) { - for (const char *s = a.latin1(); *s; ) - *out++ = QLatin1Char(*s++); - } - static inline void appendTo(const QLatin1String &a, char *&out) - { - for (const char *s = a.latin1(); *s; ) - *out++ = *s++; - } -}; - -template <> struct QConcatenable<QLatin1Literal> -{ - typedef QLatin1Literal type; - typedef QString ConvertTo; - enum { ExactSize = true }; - static int size(const QLatin1Literal &a) { return a.size(); } - static inline void appendTo(const QLatin1Literal &a, QChar *&out) - { for (const char *s = a.data(); *s; ) *out++ = QLatin1Char(*s++); } - static inline void appendTo(const QLatin1Literal &a, char *&out) + static inline void appendTo(const QLatin1String &a, char *&out) { for (const char *s = a.data(); *s; ) *out++ = *s++; @@ -283,6 +249,23 @@ template <> struct QConcatenable<QString> : private QAbstractConcatenable #endif }; +template <int N> struct QConcatenable<QConstStringDataPtr<N> > : private QAbstractConcatenable +{ + typedef QConstStringDataPtr<N> type; + typedef QString ConvertTo; + enum { ExactSize = true }; + static int size(const type &) { return N; } + static inline void appendTo(const type &a, QChar *&out) + { + memcpy(out, reinterpret_cast<const char*>(a.ptr->data), sizeof(QChar) * N); + out += N; + } +#ifndef QT_NO_CAST_TO_ASCII + static inline QT_ASCII_CAST_WARN void appendTo(const type &a, char *&out) + { convertToAscii(a.ptr->data, N, out); } +#endif +}; + template <> struct QConcatenable<QStringRef> : private QAbstractConcatenable { typedef QStringRef type; diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index efb7f46c9b..bded94399d 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -68,7 +68,7 @@ public: inline QStringList(const QStringList &l) : QList<QString>(l) { } inline QStringList(const QList<QString> &l) : QList<QString>(l) { } #ifdef Q_COMPILER_INITIALIZER_LISTS - inline QStringList(std::initializer_list<QString> args) : QList(args) { } + inline QStringList(std::initializer_list<QString> args) : QList<QString>(args) { } #endif inline void sort(); diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 42cab84cc0..f5b38eb1c0 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -30,6 +30,7 @@ HEADERS += \ tools/qrect.h \ tools/qregexp.h \ tools/qringbuffer_p.h \ + tools/qrefcount.h \ tools/qscopedpointer.h \ tools/qscopedpointer_p.h \ tools/qscopedvaluerollback.h \ @@ -72,6 +73,7 @@ SOURCES += \ tools/qcontiguouscache.cpp \ tools/qrect.cpp \ tools/qregexp.cpp \ + tools/qrefcount.cpp \ tools/qshareddata.cpp \ tools/qsharedpointer.cpp \ tools/qsimd.cpp \ diff --git a/src/dbus/qdbus_symbols.cpp b/src/dbus/qdbus_symbols.cpp index 44597c39b6..fed18350bb 100644 --- a/src/dbus/qdbus_symbols.cpp +++ b/src/dbus/qdbus_symbols.cpp @@ -62,6 +62,12 @@ void qdbus_unloadLibDBus() bool qdbus_loadLibDBus() { +#ifdef QT_BUILD_INTERNAL + // this is to simulate a library load failure for our autotest suite. + if (!qgetenv("QT_SIMULATE_DBUS_LIBFAIL").isEmpty()) + return false; +#endif + static volatile bool triedToLoadLibrary = false; #ifndef QT_NO_THREAD QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&qdbus_resolve_me)); diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 0b4133c8dd..9656903846 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -1061,7 +1061,7 @@ public: if (!instance) { qWarning("QDBusConnection: %s D-Bus connection created before QCoreApplication. Application may misbehave.", type == SessionBus ? "session" : type == SystemBus ? "system" : "generic"); - } else { + } else if (QDBusConnectionPrivate::d(*this)) { QDBusConnectionPrivate::d(*this)->moveToThread(instance->thread()); } } diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp index cdc0978ed7..dbe957e68d 100644 --- a/src/gui/painting/qcosmeticstroker.cpp +++ b/src/gui/painting/qcosmeticstroker.cpp @@ -7,29 +7,29 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** ** 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. +** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** +** 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. ** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. ** ** ** diff --git a/src/gui/painting/qcosmeticstroker_p.h b/src/gui/painting/qcosmeticstroker_p.h index 0aa71fc9cd..d7bd79ad15 100644 --- a/src/gui/painting/qcosmeticstroker_p.h +++ b/src/gui/painting/qcosmeticstroker_p.h @@ -7,29 +7,29 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** ** 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. +** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** +** 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. ** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. ** ** ** diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index be5c41ce76..d5b9f97378 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1291,7 +1291,7 @@ void QPainterPrivate::updateState(QPainterState *newState) \o \inlineimage qpainter-compositiondemo.png \o - \bold {Composition Modes Demo} + \bold {Composition Modes Example} The \l {painting/composition}{Composition Modes} example, available in Qt's examples directory, allows you to experiment with the various @@ -6503,6 +6503,10 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) qreal x = p.x(); qreal y = p.y(); + bool rtl = ti.flags & QTextItem::RightToLeft; + if (rtl) + x += ti.width.toReal(); + int start = 0; int end, i; for (end = 0; end < ti.glyphs.numGlyphs; ++end) { @@ -6519,14 +6523,19 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) ti2.width += ti.glyphs.effectiveAdvance(i); } + if (rtl) + x -= ti2.width.toReal(); + d->engine->drawTextItem(QPointF(x, y), ti2); + if (!rtl) + x += ti2.width.toReal(); + // reset the high byte for all glyphs and advance to the next sub-string const int hi = which << 24; for (i = start; i < end; ++i) { glyphs.glyphs[i] = hi | glyphs.glyphs[i]; } - x += ti2.width.toReal(); // change engine start = end; @@ -6541,6 +6550,9 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) ti2.width += ti.glyphs.effectiveAdvance(i); } + if (rtl) + x -= ti2.width.toReal(); + if (d->extended) d->extended->drawTextItem(QPointF(x, y), ti2); else diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 98b43d5b5e..655042a22c 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -218,17 +218,14 @@ struct QtFontStyle Key(const QString &styleString); Key() : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0) { } - Key(const Key &o) : styleName(o.styleName), style(o.style), - weight(o.weight), stretch(o.stretch) { } - QString styleName; + Key(const Key &o) : style(o.style), weight(o.weight), stretch(o.stretch) { } uint style : 2; signed int weight : 8; signed int stretch : 12; bool operator==(const Key & other) { - return styleName == other.styleName && style == other.style && - weight == other.weight && - (stretch == 0 || other.stretch == 0 || stretch == other.stretch); + return (style == other.style && weight == other.weight && + (stretch == 0 || other.stretch == 0 || stretch == other.stretch)); } bool operator!=(const Key &other) { return !operator==(other); @@ -280,6 +277,7 @@ struct QtFontStyle bool smoothScalable : 1; signed int count : 30; QtFontSize *pixelSizes; + QString styleName; #ifdef Q_WS_X11 const char *weightName; @@ -293,7 +291,7 @@ struct QtFontStyle }; QtFontStyle::Key::Key(const QString &styleString) - : styleName(styleString), style(QFont::StyleNormal), weight(QFont::Normal), stretch(0) + : style(QFont::StyleNormal), weight(QFont::Normal), stretch(0) { weight = getFontWeight(styleString); @@ -354,13 +352,20 @@ struct QtFontFoundry int count; QtFontStyle **styles; - QtFontStyle *style(const QtFontStyle::Key &, bool = false); + QtFontStyle *style(const QtFontStyle::Key &, const QString & = QString(), bool = false); }; -QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create) +QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, const QString &styleName, bool create) { int pos = 0; if (count) { + // if styleName for searching first if possible + if (!styleName.isEmpty()) { + for (; pos < count; pos++) { + if (styles[pos]->styleName == styleName) + return styles[pos]; + } + } int low = 0; int high = count; pos = count / 2; @@ -387,6 +392,7 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create) } QtFontStyle *style = new QtFontStyle(key); + style->styleName = styleName; memmove(styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *)); styles[pos] = style; count++; @@ -815,7 +821,7 @@ void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundr } QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); style->smoothScalable = (pixelSize == 0); style->antialiased = antialiased; QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true); @@ -1132,7 +1138,8 @@ QString QFontDatabase::resolveFontFamilyAlias(const QString &family) } #endif -static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey) +static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey, + const QString &styleName = QString()) { int best = 0; int dist = 0xffff; @@ -1140,7 +1147,7 @@ static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &st for ( int i = 0; i < foundry->count; i++ ) { QtFontStyle *style = foundry->styles[i]; - if (!styleKey.styleName.isEmpty() && styleKey.styleName == style->key.styleName) { + if (!styleName.isEmpty() && styleName == style->styleName) { dist = 0; best = i; break; @@ -1797,16 +1804,16 @@ QStringList QFontDatabase::styles(const QString &family) const for (int k = 0; k < foundry->count; k++) { QtFontStyle::Key ke(foundry->styles[k]->key); ke.stretch = 0; - allStyles.style(ke, true); + allStyles.style(ke, foundry->styles[k]->styleName, true); } } } for (int i = 0; i < allStyles.count; i++) { - l.append(allStyles.styles[i]->key.styleName.isEmpty() ? + l.append(allStyles.styles[i]->styleName.isEmpty() ? styleStringHelper(allStyles.styles[i]->key.weight, (QFont::Style)allStyles.styles[i]->key.style) : - allStyles.styles[i]->key.styleName); + allStyles.styles[i]->styleName); } return l; } @@ -1865,7 +1872,9 @@ bool QFontDatabase::isBitmapScalable(const QString &family, QtFontFoundry *foundry = f->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - if ((style.isEmpty() || foundry->styles[k]->key == styleKey) + if ((style.isEmpty() || + foundry->styles[k]->styleName == style || + foundry->styles[k]->key == styleKey) && foundry->styles[k]->bitmapScalable && !foundry->styles[k]->smoothScalable) { bitmapScalable = true; goto end; @@ -1904,7 +1913,9 @@ bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &sty QtFontFoundry *foundry = f->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - if ((style.isEmpty() || foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) { + if ((style.isEmpty() || + foundry->styles[k]->styleName == style || + foundry->styles[k]->key == styleKey) && foundry->styles[k]->smoothScalable) { smoothScalable = true; goto end; } @@ -1937,12 +1948,12 @@ bool QFontDatabase::isScalable(const QString &family, \sa smoothSizes(), standardSizes() */ QList<int> QFontDatabase::pointSizes(const QString &family, - const QString &style) + const QString &styleName) { #if defined(Q_WS_WIN) // windows and macosx are always smoothly scalable Q_UNUSED(family); - Q_UNUSED(style); + Q_UNUSED(styleName); return standardSizes(); #else bool smoothScalable = false; @@ -1953,7 +1964,7 @@ QList<int> QFontDatabase::pointSizes(const QString &family, QT_PREPEND_NAMESPACE(load)(familyName); - QtFontStyle::Key styleKey(style); + QtFontStyle::Key styleKey(styleName); QList<int> sizes; @@ -1970,7 +1981,7 @@ QList<int> QFontDatabase::pointSizes(const QString &family, for (int j = 0; j < fam->count; j++) { QtFontFoundry *foundry = fam->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { - QtFontStyle *style = foundry->style(styleKey); + QtFontStyle *style = foundry->style(styleKey, styleName); if (!style) continue; if (style->smoothScalable) { @@ -2021,25 +2032,21 @@ QFont QFontDatabase::font(const QString &family, const QString &style, QtFontFoundry *foundry = f->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - allStyles.style(foundry->styles[k]->key, true); + allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); } } QtFontStyle::Key styleKey(style); - QtFontStyle *s = bestStyle(&allStyles, styleKey); + QtFontStyle *s = bestStyle(&allStyles, styleKey, style); if (!s) // no styles found? return QGuiApplication::font(); - if (s->key.styleName.isEmpty()) { - QFont fnt(family, pointSize, s->key.weight); - fnt.setStyle((QFont::Style)s->key.style); - return fnt; - } else { - // found a perfect match - QFont fnt(family, pointSize); - fnt.setStyleName(s->key.styleName); - return fnt; - } + + QFont fnt(family, pointSize, s->key.weight); + fnt.setStyle((QFont::Style)s->key.style); + if (!s->styleName.isEmpty()) + fnt.setStyleName(s->styleName); + return fnt; } @@ -2052,11 +2059,11 @@ QFont QFontDatabase::font(const QString &family, const QString &style, \sa pointSizes(), standardSizes() */ QList<int> QFontDatabase::smoothSizes(const QString &family, - const QString &style) + const QString &styleName) { #ifdef Q_WS_WIN Q_UNUSED(family); - Q_UNUSED(style); + Q_UNUSED(styleName); return QFontDatabase::standardSizes(); #else bool smoothScalable = false; @@ -2067,7 +2074,7 @@ QList<int> QFontDatabase::smoothSizes(const QString &family, QT_PREPEND_NAMESPACE(load)(familyName); - QtFontStyle::Key styleKey(style); + QtFontStyle::Key styleKey(styleName); QList<int> sizes; @@ -2084,7 +2091,7 @@ QList<int> QFontDatabase::smoothSizes(const QString &family, for (int j = 0; j < fam->count; j++) { QtFontFoundry *foundry = fam->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { - QtFontStyle *style = foundry->style(styleKey); + QtFontStyle *style = foundry->style(styleKey, styleName); if (!style) continue; if (style->smoothScalable) { @@ -2151,12 +2158,12 @@ bool QFontDatabase::italic(const QString &family, const QString &style) const QtFontFoundry *foundry = f->foundries[j]; if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - allStyles.style(foundry->styles[k]->key, true); + allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); } } QtFontStyle::Key styleKey(style); - QtFontStyle *s = allStyles.style(styleKey); + QtFontStyle *s = allStyles.style(styleKey, style); return s && s->key.style == QFont::StyleItalic; } @@ -2186,12 +2193,12 @@ bool QFontDatabase::bold(const QString &family, if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - allStyles.style(foundry->styles[k]->key, true); + allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); } } QtFontStyle::Key styleKey(style); - QtFontStyle *s = allStyles.style(styleKey); + QtFontStyle *s = allStyles.style(styleKey, style); return s && s->key.weight >= QFont::Bold; } @@ -2222,12 +2229,12 @@ int QFontDatabase::weight(const QString &family, if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) { for (int k = 0; k < foundry->count; k++) - allStyles.style(foundry->styles[k]->key, true); + allStyles.style(foundry->styles[k]->key, foundry->styles[k]->styleName, true); } } QtFontStyle::Key styleKey(style); - QtFontStyle *s = allStyles.style(styleKey); + QtFontStyle *s = allStyles.style(styleKey, style); return s ? s->key.weight : -1; } diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp index d2adf7c6b4..c0392e798b 100644 --- a/src/gui/text/qfontdatabase_qpa.cpp +++ b/src/gui/text/qfontdatabase_qpa.cpp @@ -73,7 +73,7 @@ Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &fou } QtFontFoundry *foundry = f->foundry(foundryname, true); - QtFontStyle *fontStyle = foundry->style(styleKey, true); + QtFontStyle *fontStyle = foundry->style(styleKey, QString(), true); fontStyle->smoothScalable = scalable; fontStyle->antialiased = antialiased; QtFontSize *size = fontStyle->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true); diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index a488c13156..08b6e0bf14 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -2711,7 +2711,7 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block) html += QLatin1Char('>'); if (block.begin().atEnd()) - html += "<br />"; + html += QLatin1String("<br />"); QTextBlock::Iterator it = block.begin(); if (fragmentMarkers && !it.atEnd() && block == doc->begin()) diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 8400f62ab9..c159f1a0c5 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -163,8 +163,6 @@ public: bool isSocketWaiting() const; bool isSocketReading() const; - friend class QNetworkAccessHttpBackend; - protected slots: void _q_receiveReply(); void _q_bytesWritten(qint64 bytes); // proceed sending diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp deleted file mode 100644 index 64a22aa0e8..0000000000 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ /dev/null @@ -1,1189 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//#define QNETWORKACCESSHTTPBACKEND_DEBUG - -#include "qnetworkaccesshttpbackend_p.h" -#include "qnetworkaccessmanager_p.h" -#include "qnetworkaccesscache_p.h" -#include "qabstractnetworkcache.h" -#include "qnetworkrequest.h" -#include "qnetworkreply.h" -#include "QtNetwork/private/qnetworksession_p.h" -#include "qnetworkrequest_p.h" -#include "qnetworkcookie_p.h" -#include "QtCore/qdatetime.h" -#include "QtCore/qelapsedtimer.h" -#include "QtNetwork/qsslconfiguration.h" -#include "qhttpthreaddelegate_p.h" -#include "qthread.h" - -#ifndef QT_NO_HTTP - -#include <string.h> // for strchr - -Q_DECLARE_METATYPE(QSharedPointer<char>) - -QT_BEGIN_NAMESPACE - -class QNetworkProxy; - -static inline bool isSeparator(register char c) -{ - static const char separators[] = "()<>@,;:\\\"/[]?={}"; - return isLWS(c) || strchr(separators, c) != 0; -} - -// ### merge with nextField in cookiejar.cpp -static QHash<QByteArray, QByteArray> parseHttpOptionHeader(const QByteArray &header) -{ - // The HTTP header is of the form: - // header = #1(directives) - // directives = token | value-directive - // value-directive = token "=" (token | quoted-string) - QHash<QByteArray, QByteArray> result; - - int pos = 0; - while (true) { - // skip spaces - pos = nextNonWhitespace(header, pos); - if (pos == header.length()) - return result; // end of parsing - - // pos points to a non-whitespace - int comma = header.indexOf(',', pos); - int equal = header.indexOf('=', pos); - if (comma == pos || equal == pos) - // huh? Broken header. - return result; - - // The key name is delimited by either a comma, an equal sign or the end - // of the header, whichever comes first - int end = comma; - if (end == -1) - end = header.length(); - if (equal != -1 && end > equal) - end = equal; // equal sign comes before comma/end - QByteArray key = QByteArray(header.constData() + pos, end - pos).trimmed().toLower(); - pos = end + 1; - - if (uint(equal) < uint(comma)) { - // case: token "=" (token | quoted-string) - // skip spaces - pos = nextNonWhitespace(header, pos); - if (pos == header.length()) - // huh? Broken header - return result; - - QByteArray value; - value.reserve(header.length() - pos); - if (header.at(pos) == '"') { - // case: quoted-string - // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) - // qdtext = <any TEXT except <">> - // quoted-pair = "\" CHAR - ++pos; - while (pos < header.length()) { - register char c = header.at(pos); - if (c == '"') { - // end of quoted text - break; - } else if (c == '\\') { - ++pos; - if (pos >= header.length()) - // broken header - return result; - c = header.at(pos); - } - - value += c; - ++pos; - } - } else { - // case: token - while (pos < header.length()) { - register char c = header.at(pos); - if (isSeparator(c)) - break; - value += c; - ++pos; - } - } - - result.insert(key, value); - - // find the comma now: - comma = header.indexOf(',', pos); - if (comma == -1) - return result; // end of parsing - pos = comma + 1; - } else { - // case: token - // key is already set - result.insert(key, QByteArray()); - } - } -} - -QNetworkAccessBackend * -QNetworkAccessHttpBackendFactory::create(QNetworkAccessManager::Operation op, - const QNetworkRequest &request) const -{ - // check the operation - switch (op) { - case QNetworkAccessManager::GetOperation: - case QNetworkAccessManager::PostOperation: - case QNetworkAccessManager::HeadOperation: - case QNetworkAccessManager::PutOperation: - case QNetworkAccessManager::DeleteOperation: - case QNetworkAccessManager::CustomOperation: - break; - - default: - // no, we can't handle this request - return 0; - } - - QUrl url = request.url(); - QString scheme = url.scheme().toLower(); - if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) - return new QNetworkAccessHttpBackend; - - return 0; -} - -QNetworkAccessHttpBackend::QNetworkAccessHttpBackend() - : QNetworkAccessBackend() - , statusCode(0) - , pendingDownloadDataEmissions(new QAtomicInt()) - , pendingDownloadProgressEmissions(new QAtomicInt()) - , loadingFromCache(false) - , usingZerocopyDownloadBuffer(false) -#ifndef QT_NO_OPENSSL - , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false) -#endif - , resumeOffset(0) -{ -} - -QNetworkAccessHttpBackend::~QNetworkAccessHttpBackend() -{ - // This will do nothing if the request was already finished or aborted - emit abortHttpRequest(); - -#ifndef QT_NO_OPENSSL - delete pendingSslConfiguration; -#endif -} - -/* - For a given httpRequest - 1) If AlwaysNetwork, return - 2) If we have a cache entry for this url populate headers so the server can return 304 - 3) Calculate if response_is_fresh and if so send the cache and set loadedFromCache to true - */ -bool QNetworkAccessHttpBackend::loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest) -{ - QNetworkRequest::CacheLoadControl CacheLoadControlAttribute = - (QNetworkRequest::CacheLoadControl)request().attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(); - if (CacheLoadControlAttribute == QNetworkRequest::AlwaysNetwork) { - // If the request does not already specify preferred cache-control - // force reload from the network and tell any caching proxy servers to reload too - if (!request().rawHeaderList().contains("Cache-Control")) { - httpRequest.setHeaderField("Cache-Control", "no-cache"); - httpRequest.setHeaderField("Pragma", "no-cache"); - } - return false; - } - - // The disk cache API does not currently support partial content retrieval. - // That is why we don't use the disk cache for any such requests. - if (request().hasRawHeader("Range")) - return false; - - QAbstractNetworkCache *nc = networkCache(); - if (!nc) - return false; // no local cache - - QNetworkCacheMetaData metaData = nc->metaData(url()); - if (!metaData.isValid()) - return false; // not in cache - - if (!metaData.saveToDisk()) - return false; - - QNetworkHeadersPrivate cacheHeaders; - QNetworkHeadersPrivate::RawHeadersList::ConstIterator it; - cacheHeaders.setAllRawHeaders(metaData.rawHeaders()); - - it = cacheHeaders.findRawHeader("etag"); - if (it != cacheHeaders.rawHeaders.constEnd()) - httpRequest.setHeaderField("If-None-Match", it->second); - - QDateTime lastModified = metaData.lastModified(); - if (lastModified.isValid()) - httpRequest.setHeaderField("If-Modified-Since", QNetworkHeadersPrivate::toHttpDate(lastModified)); - - it = cacheHeaders.findRawHeader("Cache-Control"); - if (it != cacheHeaders.rawHeaders.constEnd()) { - QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second); - if (cacheControl.contains("must-revalidate")) - return false; - } - - QDateTime currentDateTime = QDateTime::currentDateTime(); - QDateTime expirationDate = metaData.expirationDate(); - -#if 0 - /* - * age_value - * is the value of Age: header received by the cache with - * this response. - * date_value - * is the value of the origin server's Date: header - * request_time - * is the (local) time when the cache made the request - * that resulted in this cached response - * response_time - * is the (local) time when the cache received the - * response - * now - * is the current (local) time - */ - int age_value = 0; - it = cacheHeaders.findRawHeader("age"); - if (it != cacheHeaders.rawHeaders.constEnd()) - age_value = it->second.toInt(); - - QDateTime dateHeader; - int date_value = 0; - it = cacheHeaders.findRawHeader("date"); - if (it != cacheHeaders.rawHeaders.constEnd()) { - dateHeader = QNetworkHeadersPrivate::fromHttpDate(it->second); - date_value = dateHeader.toTime_t(); - } - - int now = currentDateTime.toUTC().toTime_t(); - int request_time = now; - int response_time = now; - - // Algorithm from RFC 2616 section 13.2.3 - int apparent_age = qMax(0, response_time - date_value); - int corrected_received_age = qMax(apparent_age, age_value); - int response_delay = response_time - request_time; - int corrected_initial_age = corrected_received_age + response_delay; - int resident_time = now - response_time; - int current_age = corrected_initial_age + resident_time; - - // RFC 2616 13.2.4 Expiration Calculations - if (!expirationDate.isValid()) { - if (lastModified.isValid()) { - int diff = currentDateTime.secsTo(lastModified); - expirationDate = lastModified; - expirationDate.addSecs(diff / 10); - if (httpRequest.headerField("Warning").isEmpty()) { - QDateTime dt; - dt.setTime_t(current_age); - if (dt.daysTo(currentDateTime) > 1) - httpRequest.setHeaderField("Warning", "113"); - } - } - } - - // the cache-saving code below sets the expirationDate with date+max_age - // if "max-age" is present, or to Expires otherwise - int freshness_lifetime = dateHeader.secsTo(expirationDate); - bool response_is_fresh = (freshness_lifetime > current_age); -#else - bool response_is_fresh = currentDateTime.secsTo(expirationDate) >= 0; -#endif - - if (!response_is_fresh) - return false; - -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "response_is_fresh" << CacheLoadControlAttribute; -#endif - return sendCacheContents(metaData); -} - -static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio) -{ - switch (prio) { - case QNetworkRequest::LowPriority: - return QHttpNetworkRequest::LowPriority; - case QNetworkRequest::HighPriority: - return QHttpNetworkRequest::HighPriority; - case QNetworkRequest::NormalPriority: - default: - return QHttpNetworkRequest::NormalPriority; - } -} - -void QNetworkAccessHttpBackend::postRequest() -{ - QThread *thread = 0; - if (isSynchronous()) { - // A synchronous HTTP request uses its own thread - thread = new QThread(); - QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); - thread->start(); - } else if (!manager->httpThread) { - // We use the manager-global thread. - // At some point we could switch to having multiple threads if it makes sense. - manager->httpThread = new QThread(); - QObject::connect(manager->httpThread, SIGNAL(finished()), manager->httpThread, SLOT(deleteLater())); - manager->httpThread->start(); -#ifndef QT_NO_NETWORKPROXY - qRegisterMetaType<QNetworkProxy>("QNetworkProxy"); -#endif -#ifndef QT_NO_OPENSSL - qRegisterMetaType<QList<QSslError> >("QList<QSslError>"); - qRegisterMetaType<QSslConfiguration>("QSslConfiguration"); -#endif - qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >("QList<QPair<QByteArray,QByteArray> >"); - qRegisterMetaType<QHttpNetworkRequest>("QHttpNetworkRequest"); - qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError"); - qRegisterMetaType<QSharedPointer<char> >("QSharedPointer<char>"); - - thread = manager->httpThread; - } else { - // Asynchronous request, thread already exists - thread = manager->httpThread; - } - - QUrl url = request().url(); - httpRequest.setUrl(url); - - bool ssl = url.scheme().toLower() == QLatin1String("https"); - setAttribute(QNetworkRequest::ConnectionEncryptedAttribute, ssl); - httpRequest.setSsl(ssl); - - -#ifndef QT_NO_NETWORKPROXY - QNetworkProxy transparentProxy, cacheProxy; - - foreach (const QNetworkProxy &p, proxyList()) { - // use the first proxy that works - // for non-encrypted connections, any transparent or HTTP proxy - // for encrypted, only transparent proxies - if (!ssl - && (p.capabilities() & QNetworkProxy::CachingCapability) - && (p.type() == QNetworkProxy::HttpProxy || - p.type() == QNetworkProxy::HttpCachingProxy)) { - cacheProxy = p; - transparentProxy = QNetworkProxy::NoProxy; - break; - } - if (p.isTransparentProxy()) { - transparentProxy = p; - cacheProxy = QNetworkProxy::NoProxy; - break; - } - } - - // check if at least one of the proxies - if (transparentProxy.type() == QNetworkProxy::DefaultProxy && - cacheProxy.type() == QNetworkProxy::DefaultProxy) { - // unsuitable proxies - QMetaObject::invokeMethod(this, "error", isSynchronous() ? Qt::DirectConnection : Qt::QueuedConnection, - Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProxyNotFoundError), - Q_ARG(QString, tr("No suitable proxy found"))); - QMetaObject::invokeMethod(this, "finished", isSynchronous() ? Qt::DirectConnection : Qt::QueuedConnection); - return; - } -#endif - - - bool loadedFromCache = false; - httpRequest.setPriority(convert(request().priority())); - - switch (operation()) { - case QNetworkAccessManager::GetOperation: - httpRequest.setOperation(QHttpNetworkRequest::Get); - loadedFromCache = loadFromCacheIfAllowed(httpRequest); - break; - - case QNetworkAccessManager::HeadOperation: - httpRequest.setOperation(QHttpNetworkRequest::Head); - loadedFromCache = loadFromCacheIfAllowed(httpRequest); - break; - - case QNetworkAccessManager::PostOperation: - invalidateCache(); - httpRequest.setOperation(QHttpNetworkRequest::Post); - createUploadByteDevice(); - break; - - case QNetworkAccessManager::PutOperation: - invalidateCache(); - httpRequest.setOperation(QHttpNetworkRequest::Put); - createUploadByteDevice(); - break; - - case QNetworkAccessManager::DeleteOperation: - invalidateCache(); - httpRequest.setOperation(QHttpNetworkRequest::Delete); - break; - - case QNetworkAccessManager::CustomOperation: - invalidateCache(); // for safety reasons, we don't know what the operation does - httpRequest.setOperation(QHttpNetworkRequest::Custom); - createUploadByteDevice(); - httpRequest.setCustomVerb(request().attribute( - QNetworkRequest::CustomVerbAttribute).toByteArray()); - break; - - default: - break; // can't happen - } - - if (loadedFromCache) { - // commented this out since it will be called later anyway - // by copyFinished() - //QNetworkAccessBackend::finished(); - return; // no need to send the request! :) - } - - QList<QByteArray> headers = request().rawHeaderList(); - if (resumeOffset != 0) { - if (headers.contains("Range")) { - // Need to adjust resume offset for user specified range - - headers.removeOne("Range"); - - // We've already verified that requestRange starts with "bytes=", see canResume. - QByteArray requestRange = request().rawHeader("Range").mid(6); - - int index = requestRange.indexOf('-'); - - quint64 requestStartOffset = requestRange.left(index).toULongLong(); - quint64 requestEndOffset = requestRange.mid(index + 1).toULongLong(); - - requestRange = "bytes=" + QByteArray::number(resumeOffset + requestStartOffset) + - '-' + QByteArray::number(requestEndOffset); - - httpRequest.setHeaderField("Range", requestRange); - } else { - httpRequest.setHeaderField("Range", "bytes=" + QByteArray::number(resumeOffset) + '-'); - } - } - - foreach (const QByteArray &header, headers) - httpRequest.setHeaderField(header, request().rawHeader(header)); - - if (request().attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true) - httpRequest.setPipeliningAllowed(true); - - if (static_cast<QNetworkRequest::LoadControl> - (request().attribute(QNetworkRequest::AuthenticationReuseAttribute, - QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Manual) - httpRequest.setWithCredentials(false); - - - // Create the HTTP thread delegate - QHttpThreadDelegate *delegate = new QHttpThreadDelegate; -#ifndef Q_NO_BEARERMANAGEMENT - QVariant v(property("_q_networksession")); - if (v.isValid()) - delegate->networkSession = qvariant_cast<QSharedPointer<QNetworkSession> >(v); -#endif - - // For the synchronous HTTP, this is the normal way the delegate gets deleted - // For the asynchronous HTTP this is a safety measure, the delegate deletes itself when HTTP is finished - connect(thread, SIGNAL(finished()), delegate, SLOT(deleteLater())); - - // Set the properties it needs - delegate->httpRequest = httpRequest; -#ifndef QT_NO_NETWORKPROXY - delegate->cacheProxy = cacheProxy; - delegate->transparentProxy = transparentProxy; -#endif - delegate->ssl = ssl; -#ifndef QT_NO_OPENSSL - if (ssl) - delegate->incomingSslConfiguration = request().sslConfiguration(); -#endif - - // Do we use synchronous HTTP? - delegate->synchronous = isSynchronous(); - - // The authentication manager is used to avoid the BlockingQueuedConnection communication - // from HTTP thread to user thread in some cases. - delegate->authenticationManager = manager->authenticationManager; - - if (!isSynchronous()) { - // Tell our zerocopy policy to the delegate - delegate->downloadBufferMaximumSize = - request().attribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute).toLongLong(); - - // These atomic integers are used for signal compression - delegate->pendingDownloadData = pendingDownloadDataEmissions; - delegate->pendingDownloadProgress = pendingDownloadProgressEmissions; - - // Connect the signals of the delegate to us - connect(delegate, SIGNAL(downloadData(QByteArray)), - this, SLOT(replyDownloadData(QByteArray)), - Qt::QueuedConnection); - connect(delegate, SIGNAL(downloadFinished()), - this, SLOT(replyFinished()), - Qt::QueuedConnection); - connect(delegate, SIGNAL(downloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64)), - this, SLOT(replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64)), - Qt::QueuedConnection); - connect(delegate, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(replyDownloadProgressSlot(qint64,qint64)), - Qt::QueuedConnection); - connect(delegate, SIGNAL(error(QNetworkReply::NetworkError,QString)), - this, SLOT(httpError(QNetworkReply::NetworkError, const QString)), - Qt::QueuedConnection); -#ifndef QT_NO_OPENSSL - connect(delegate, SIGNAL(sslConfigurationChanged(QSslConfiguration)), - this, SLOT(replySslConfigurationChanged(QSslConfiguration)), - Qt::QueuedConnection); -#endif - // Those need to report back, therefire BlockingQueuedConnection - connect(delegate, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)), - this, SLOT(httpAuthenticationRequired(QHttpNetworkRequest,QAuthenticator*)), - Qt::BlockingQueuedConnection); -#ifndef QT_NO_NETWORKPROXY - connect (delegate, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), - this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), - Qt::BlockingQueuedConnection); -#endif -#ifndef QT_NO_OPENSSL - connect(delegate, SIGNAL(sslErrors(QList<QSslError>,bool*,QList<QSslError>*)), - this, SLOT(replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *)), - Qt::BlockingQueuedConnection); -#endif - // This signal we will use to start the request. - connect(this, SIGNAL(startHttpRequest()), delegate, SLOT(startRequest())); - connect(this, SIGNAL(abortHttpRequest()), delegate, SLOT(abortRequest())); - - if (uploadByteDevice) { - QNonContiguousByteDeviceThreadForwardImpl *forwardUploadDevice = - new QNonContiguousByteDeviceThreadForwardImpl(uploadByteDevice->atEnd(), uploadByteDevice->size()); - if (uploadByteDevice->isResetDisabled()) - forwardUploadDevice->disableReset(); - forwardUploadDevice->setParent(delegate); // needed to make sure it is moved on moveToThread() - delegate->httpRequest.setUploadByteDevice(forwardUploadDevice); - - // From main thread to user thread: - QObject::connect(this, SIGNAL(haveUploadData(QByteArray, bool, qint64)), - forwardUploadDevice, SLOT(haveDataSlot(QByteArray, bool, qint64)), Qt::QueuedConnection); - QObject::connect(uploadByteDevice.data(), SIGNAL(readyRead()), - forwardUploadDevice, SIGNAL(readyRead()), - Qt::QueuedConnection); - - // From http thread to user thread: - QObject::connect(forwardUploadDevice, SIGNAL(wantData(qint64)), - this, SLOT(wantUploadDataSlot(qint64))); - QObject::connect(forwardUploadDevice, SIGNAL(processedData(qint64)), - this, SLOT(sentUploadDataSlot(qint64))); - connect(forwardUploadDevice, SIGNAL(resetData(bool*)), - this, SLOT(resetUploadDataSlot(bool*)), - Qt::BlockingQueuedConnection); // this is the only one with BlockingQueued! - } - } else if (isSynchronous()) { - connect(this, SIGNAL(startHttpRequestSynchronously()), delegate, SLOT(startRequestSynchronously()), Qt::BlockingQueuedConnection); - - if (uploadByteDevice) { - // For the synchronous HTTP use case the use thread (this one here) is blocked - // so we cannot use the asynchronous upload architecture. - // We therefore won't use the QNonContiguousByteDeviceThreadForwardImpl but directly - // use the uploadByteDevice provided to us by the QNetworkReplyImpl. - // The code that is in QNetworkReplyImplPrivate::setup() makes sure it is safe to use from a thread - // since it only wraps a QRingBuffer - delegate->httpRequest.setUploadByteDevice(uploadByteDevice.data()); - } - } - - - // Move the delegate to the http thread - delegate->moveToThread(thread); - // This call automatically moves the uploadDevice too for the asynchronous case. - - // Send an signal to the delegate so it starts working in the other thread - if (isSynchronous()) { - emit startHttpRequestSynchronously(); // This one is BlockingQueuedConnection, so it will return when all work is done - - if (delegate->incomingErrorCode != QNetworkReply::NoError) { - replyDownloadMetaData - (delegate->incomingHeaders, - delegate->incomingStatusCode, - delegate->incomingReasonPhrase, - delegate->isPipeliningUsed, - QSharedPointer<char>(), - delegate->incomingContentLength); - httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail); - } else { - replyDownloadMetaData - (delegate->incomingHeaders, - delegate->incomingStatusCode, - delegate->incomingReasonPhrase, - delegate->isPipeliningUsed, - QSharedPointer<char>(), - delegate->incomingContentLength); - replyDownloadData(delegate->synchronousDownloadData); - } - - // End the thread. It will delete itself from the finished() signal - thread->quit(); - - finished(); - } else { - emit startHttpRequest(); // Signal to the HTTP thread and go back to user. - } -} - -void QNetworkAccessHttpBackend::invalidateCache() -{ - QAbstractNetworkCache *nc = networkCache(); - if (nc) - nc->remove(url()); -} - -void QNetworkAccessHttpBackend::open() -{ - postRequest(); -} - -void QNetworkAccessHttpBackend::closeDownstreamChannel() -{ - // FIXME Maybe we can get rid of this whole architecture part -} - -void QNetworkAccessHttpBackend::downstreamReadyWrite() -{ - // FIXME Maybe we can get rid of this whole architecture part -} - -void QNetworkAccessHttpBackend::setDownstreamLimited(bool b) -{ - Q_UNUSED(b); - // We know that readBuffer maximum size limiting is broken since quite a while. - // The task to fix this is QTBUG-15065 -} - -void QNetworkAccessHttpBackend::replyDownloadData(QByteArray d) -{ - int pendingSignals = (int)pendingDownloadDataEmissions->fetchAndAddAcquire(-1) - 1; - - if (pendingSignals > 0) { - // Some more signal emissions to this slot are pending. - // Instead of writing the downstream data, we wait - // and do it in the next call we get - // (signal comppression) - pendingDownloadData.append(d); - return; - } - - pendingDownloadData.append(d); - d.clear(); - // We need to usa a copy for calling writeDownstreamData as we could - // possibly recurse into this this function when we call - // appendDownstreamDataSignalEmissions because the user might call - // processEvents() or spin an event loop when this occur. - QByteDataBuffer pendingDownloadDataCopy = pendingDownloadData; - pendingDownloadData.clear(); - writeDownstreamData(pendingDownloadDataCopy); -} - -void QNetworkAccessHttpBackend::replyFinished() -{ - // We are already loading from cache, we still however - // got this signal because it was posted already - if (loadingFromCache) - return; - - finished(); -} - -void QNetworkAccessHttpBackend::checkForRedirect(const int statusCode) -{ - switch (statusCode) { - case 301: // Moved Permanently - case 302: // Found - case 303: // See Other - case 307: // Temporary Redirect - // What do we do about the caching of the HTML note? - // The response to a 303 MUST NOT be cached, while the response to - // all of the others is cacheable if the headers indicate it to be - QByteArray header = rawHeader("location"); - QUrl url = QUrl::fromEncoded(header); - if (!url.isValid()) - url = QUrl(QLatin1String(header)); - redirectionRequested(url); - } -} - -void QNetworkAccessHttpBackend::replyDownloadMetaData - (QList<QPair<QByteArray,QByteArray> > hm, - int sc,QString rp,bool pu, - QSharedPointer<char> db, - qint64 contentLength) -{ - statusCode = sc; - reasonPhrase = rp; - - // Download buffer - if (!db.isNull()) { - reply->setDownloadBuffer(db, contentLength); - usingZerocopyDownloadBuffer = true; - } else { - usingZerocopyDownloadBuffer = false; - } - - setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, pu); - - // reconstruct the HTTP header - QList<QPair<QByteArray, QByteArray> > headerMap = hm; - QList<QPair<QByteArray, QByteArray> >::ConstIterator it = headerMap.constBegin(), - end = headerMap.constEnd(); - QByteArray header; - - for (; it != end; ++it) { - QByteArray value = rawHeader(it->first); - if (!value.isEmpty()) { - if (qstricmp(it->first.constData(), "set-cookie") == 0) - value += '\n'; - else - value += ", "; - } - value += it->second; - setRawHeader(it->first, value); - } - - setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode); - setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase); - - // is it a redirection? - checkForRedirect(statusCode); - - if (statusCode >= 500 && statusCode < 600) { - QAbstractNetworkCache *nc = networkCache(); - if (nc) { - QNetworkCacheMetaData metaData = nc->metaData(url()); - QNetworkHeadersPrivate cacheHeaders; - cacheHeaders.setAllRawHeaders(metaData.rawHeaders()); - QNetworkHeadersPrivate::RawHeadersList::ConstIterator it; - it = cacheHeaders.findRawHeader("Cache-Control"); - bool mustReValidate = false; - if (it != cacheHeaders.rawHeaders.constEnd()) { - QHash<QByteArray, QByteArray> cacheControl = parseHttpOptionHeader(it->second); - if (cacheControl.contains("must-revalidate")) - mustReValidate = true; - } - if (!mustReValidate && sendCacheContents(metaData)) - return; - } - } - - if (statusCode == 304) { -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "Received a 304 from" << url(); -#endif - QAbstractNetworkCache *nc = networkCache(); - if (nc) { - QNetworkCacheMetaData oldMetaData = nc->metaData(url()); - QNetworkCacheMetaData metaData = fetchCacheMetaData(oldMetaData); - if (oldMetaData != metaData) - nc->updateMetaData(metaData); - if (sendCacheContents(metaData)) - return; - } - } - - - if (statusCode != 304 && statusCode != 303) { - if (!isCachingEnabled()) - setCachingEnabled(true); - } - - metaDataChanged(); -} - -void QNetworkAccessHttpBackend::replyDownloadProgressSlot(qint64 received, qint64 total) -{ - // we can be sure here that there is a download buffer - - int pendingSignals = (int)pendingDownloadProgressEmissions->fetchAndAddAcquire(-1) - 1; - if (pendingSignals > 0) { - // Let's ignore this signal and look at the next one coming in - // (signal comppression) - return; - } - - // Now do the actual notification of new bytes - writeDownstreamDataDownloadBuffer(received, total); -} - -void QNetworkAccessHttpBackend::httpAuthenticationRequired(const QHttpNetworkRequest &, - QAuthenticator *auth) -{ - authenticationRequired(auth); -} - -void QNetworkAccessHttpBackend::httpError(QNetworkReply::NetworkError errorCode, - const QString &errorString) -{ -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "http error!" << errorCode << errorString; -#endif - - error(errorCode, errorString); -} - -#ifndef QT_NO_OPENSSL -void QNetworkAccessHttpBackend::replySslErrors( - const QList<QSslError> &list, bool *ignoreAll, QList<QSslError> *toBeIgnored) -{ - // Go to generic backend - sslErrors(list); - // Check if the callback set any ignore and return this here to http thread - if (pendingIgnoreAllSslErrors) - *ignoreAll = true; - if (!pendingIgnoreSslErrorsList.isEmpty()) - *toBeIgnored = pendingIgnoreSslErrorsList; -} - -void QNetworkAccessHttpBackend::replySslConfigurationChanged(const QSslConfiguration &c) -{ - // Receiving the used SSL configuration from the HTTP thread - if (pendingSslConfiguration) - *pendingSslConfiguration = c; - else if (!c.isNull()) - pendingSslConfiguration = new QSslConfiguration(c); -} -#endif - -// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread -void QNetworkAccessHttpBackend::resetUploadDataSlot(bool *r) -{ - *r = uploadByteDevice->reset(); -} - -// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread -void QNetworkAccessHttpBackend::sentUploadDataSlot(qint64 amount) -{ - uploadByteDevice->advanceReadPointer(amount); -} - -// Coming from QNonContiguousByteDeviceThreadForwardImpl in HTTP thread -void QNetworkAccessHttpBackend::wantUploadDataSlot(qint64 maxSize) -{ - // call readPointer - qint64 currentUploadDataLength = 0; - char *data = const_cast<char*>(uploadByteDevice->readPointer(maxSize, currentUploadDataLength)); - // Let's make a copy of this data - QByteArray dataArray(data, currentUploadDataLength); - - // Communicate back to HTTP thread - emit haveUploadData(dataArray, uploadByteDevice->atEnd(), uploadByteDevice->size()); -} - -/* - A simple web page that can be used to test us: http://www.procata.com/cachetest/ - */ -bool QNetworkAccessHttpBackend::sendCacheContents(const QNetworkCacheMetaData &metaData) -{ - setCachingEnabled(false); - if (!metaData.isValid()) - return false; - - QAbstractNetworkCache *nc = networkCache(); - Q_ASSERT(nc); - QIODevice *contents = nc->data(url()); - if (!contents) { -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "Can not send cache, the contents are 0" << url(); -#endif - return false; - } - contents->setParent(this); - - QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes(); - int status = attributes.value(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if (status < 100) - status = 200; // fake it - - setAttribute(QNetworkRequest::HttpStatusCodeAttribute, status); - setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, attributes.value(QNetworkRequest::HttpReasonPhraseAttribute)); - setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true); - - QNetworkCacheMetaData::RawHeaderList rawHeaders = metaData.rawHeaders(); - QNetworkCacheMetaData::RawHeaderList::ConstIterator it = rawHeaders.constBegin(), - end = rawHeaders.constEnd(); - for ( ; it != end; ++it) - setRawHeader(it->first, it->second); - - checkForRedirect(status); - - // This needs to be emitted in the event loop because it can be reached at - // the direct code path of qnam.get(...) before the user has a chance - // to connect any signals. - QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection); - qRegisterMetaType<QIODevice*>("QIODevice*"); - QMetaObject::invokeMethod(this, "writeDownstreamData", Qt::QueuedConnection, Q_ARG(QIODevice*, contents)); - - -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - qDebug() << "Successfully sent cache:" << url() << contents->size() << "bytes"; -#endif - - // Set the following flag so we can ignore some signals from HTTP thread - // that would still come - loadingFromCache = true; - return true; -} - -void QNetworkAccessHttpBackend::copyFinished(QIODevice *dev) -{ - delete dev; - finished(); -} - -#ifndef QT_NO_OPENSSL -void QNetworkAccessHttpBackend::ignoreSslErrors() -{ - pendingIgnoreAllSslErrors = true; -} - -void QNetworkAccessHttpBackend::ignoreSslErrors(const QList<QSslError> &errors) -{ - // the pending list is set if QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors) - // is called before QNetworkAccessManager::get() (or post(), etc.) - pendingIgnoreSslErrorsList = errors; -} - -void QNetworkAccessHttpBackend::fetchSslConfiguration(QSslConfiguration &config) const -{ - if (pendingSslConfiguration) - config = *pendingSslConfiguration; - else - config = request().sslConfiguration(); -} - -void QNetworkAccessHttpBackend::setSslConfiguration(const QSslConfiguration &newconfig) -{ - // Setting a SSL configuration on a reply is not supported. The user needs to set - // her/his QSslConfiguration on the QNetworkRequest. - Q_UNUSED(newconfig); -} -#endif - -QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetworkCacheMetaData &oldMetaData) const -{ - QNetworkCacheMetaData metaData = oldMetaData; - - QNetworkHeadersPrivate cacheHeaders; - cacheHeaders.setAllRawHeaders(metaData.rawHeaders()); - QNetworkHeadersPrivate::RawHeadersList::ConstIterator it; - - QList<QByteArray> newHeaders = rawHeaderList(); - foreach (QByteArray header, newHeaders) { - QByteArray originalHeader = header; - header = header.toLower(); - bool hop_by_hop = - (header == "connection" - || header == "keep-alive" - || header == "proxy-authenticate" - || header == "proxy-authorization" - || header == "te" - || header == "trailers" - || header == "transfer-encoding" - || header == "upgrade"); - if (hop_by_hop) - continue; - - // we are currently not using the date header to determine the expiration time of a page, - // but only the "Expires", "max-age" and "s-maxage" headers, see - // QNetworkAccessHttpBackend::validateCache() and below ("metaData.setExpirationDate()"). - if (header == "date") - continue; - - // Don't store Warning 1xx headers - if (header == "warning") { - QByteArray v = rawHeader(header); - if (v.length() == 3 - && v[0] == '1' - && v[1] >= '0' && v[1] <= '9' - && v[2] >= '0' && v[2] <= '9') - continue; - } - - it = cacheHeaders.findRawHeader(header); - if (it != cacheHeaders.rawHeaders.constEnd()) { - // Match the behavior of Firefox and assume Cache-Control: "no-transform" - if (header == "content-encoding" - || header == "content-range" - || header == "content-type") - continue; - - // For MS servers that send "Content-Length: 0" on 304 responses - // ignore this too - if (header == "content-length") - continue; - } - -#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG) - QByteArray n = rawHeader(header); - QByteArray o; - if (it != cacheHeaders.rawHeaders.constEnd()) - o = (*it).second; - if (n != o && header != "date") { - qDebug() << "replacing" << header; - qDebug() << "new" << n; - qDebug() << "old" << o; - } -#endif - cacheHeaders.setRawHeader(originalHeader, rawHeader(header)); - } - metaData.setRawHeaders(cacheHeaders.rawHeaders); - - bool checkExpired = true; - - QHash<QByteArray, QByteArray> cacheControl; - it = cacheHeaders.findRawHeader("Cache-Control"); - if (it != cacheHeaders.rawHeaders.constEnd()) { - cacheControl = parseHttpOptionHeader(it->second); - QByteArray maxAge = cacheControl.value("max-age"); - if (!maxAge.isEmpty()) { - checkExpired = false; - QDateTime dt = QDateTime::currentDateTime(); - dt = dt.addSecs(maxAge.toInt()); - metaData.setExpirationDate(dt); - } - } - if (checkExpired) { - it = cacheHeaders.findRawHeader("expires"); - if (it != cacheHeaders.rawHeaders.constEnd()) { - QDateTime expiredDateTime = QNetworkHeadersPrivate::fromHttpDate(it->second); - metaData.setExpirationDate(expiredDateTime); - } - } - - it = cacheHeaders.findRawHeader("last-modified"); - if (it != cacheHeaders.rawHeaders.constEnd()) - metaData.setLastModified(QNetworkHeadersPrivate::fromHttpDate(it->second)); - - bool canDiskCache; - // only cache GET replies by default, all other replies (POST, PUT, DELETE) - // are not cacheable by default (according to RFC 2616 section 9) - if (httpRequest.operation() == QHttpNetworkRequest::Get) { - - canDiskCache = true; - // 14.32 - // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client - // had sent "Cache-Control: no-cache". - it = cacheHeaders.findRawHeader("pragma"); - if (it != cacheHeaders.rawHeaders.constEnd() - && it->second == "no-cache") - canDiskCache = false; - - // HTTP/1.1. Check the Cache-Control header - if (cacheControl.contains("no-cache")) - canDiskCache = false; - else if (cacheControl.contains("no-store")) - canDiskCache = false; - - // responses to POST might be cacheable - } else if (httpRequest.operation() == QHttpNetworkRequest::Post) { - - canDiskCache = false; - // some pages contain "expires:" and "cache-control: no-cache" field, - // so we only might cache POST requests if we get "cache-control: max-age ..." - if (cacheControl.contains("max-age")) - canDiskCache = true; - - // responses to PUT and DELETE are not cacheable - } else { - canDiskCache = false; - } - - metaData.setSaveToDisk(canDiskCache); - QNetworkCacheMetaData::AttributesMap attributes; - if (statusCode != 304) { - // update the status code - attributes.insert(QNetworkRequest::HttpStatusCodeAttribute, statusCode); - attributes.insert(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase); - } else { - // this is a redirection, keep the attributes intact - attributes = oldMetaData.attributes(); - } - metaData.setAttributes(attributes); - return metaData; -} - -bool QNetworkAccessHttpBackend::canResume() const -{ - // Only GET operation supports resuming. - if (operation() != QNetworkAccessManager::GetOperation) - return false; - - // Can only resume if server/resource supports Range header. - QByteArray acceptRangesheaderName("Accept-Ranges"); - if (!hasRawHeader(acceptRangesheaderName) || rawHeader(acceptRangesheaderName) == "none") - return false; - - // We only support resuming for byte ranges. - if (request().hasRawHeader("Range")) { - QByteArray range = request().rawHeader("Range"); - if (!range.startsWith("bytes=")) - return false; - } - - // If we're using a download buffer then we don't support resuming/migration - // right now. Too much trouble. - if (usingZerocopyDownloadBuffer) - return false; - - return true; -} - -void QNetworkAccessHttpBackend::setResumeOffset(quint64 offset) -{ - resumeOffset = offset; -} - -QT_END_NAMESPACE - -#endif // QT_NO_HTTP diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h deleted file mode 100644 index 7d4ea56260..0000000000 --- a/src/network/access/qnetworkaccesshttpbackend_p.h +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia 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. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QNETWORKACCESSHTTPBACKEND_P_H -#define QNETWORKACCESSHTTPBACKEND_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the Network Access API. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include "qhttpnetworkconnection_p.h" -#include "qnetworkaccessbackend_p.h" -#include "qnetworkrequest.h" -#include "qnetworkreply.h" -#include "qabstractsocket.h" - -#include "QtCore/qpointer.h" -#include "QtCore/qdatetime.h" -#include "QtCore/qsharedpointer.h" -#include "qatomic.h" - -#ifndef QT_NO_HTTP - -QT_BEGIN_NAMESPACE - -class QNetworkAccessCachedHttpConnection; - -class QNetworkAccessHttpBackendIODevice; - -class QNetworkAccessHttpBackend: public QNetworkAccessBackend -{ - Q_OBJECT -public: - QNetworkAccessHttpBackend(); - virtual ~QNetworkAccessHttpBackend(); - - virtual void open(); - virtual void closeDownstreamChannel(); - - virtual void downstreamReadyWrite(); - virtual void setDownstreamLimited(bool b); - - virtual void copyFinished(QIODevice *); -#ifndef QT_NO_OPENSSL - virtual void ignoreSslErrors(); - virtual void ignoreSslErrors(const QList<QSslError> &errors); - - virtual void fetchSslConfiguration(QSslConfiguration &configuration) const; - virtual void setSslConfiguration(const QSslConfiguration &configuration); -#endif - QNetworkCacheMetaData fetchCacheMetaData(const QNetworkCacheMetaData &metaData) const; - - // we return true since HTTP needs to send PUT/POST data again after having authenticated - bool needsResetableUploadData() { return true; } - - bool canResume() const; - void setResumeOffset(quint64 offset); - -signals: - // To HTTP thread: - void startHttpRequest(); - void abortHttpRequest(); - - void startHttpRequestSynchronously(); - - void haveUploadData(QByteArray dataArray, bool dataAtEnd, qint64 dataSize); -private slots: - // From HTTP thread: - void replyDownloadData(QByteArray); - void replyFinished(); - void replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >,int,QString,bool,QSharedPointer<char>,qint64); - void replyDownloadProgressSlot(qint64,qint64); - void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth); - void httpError(QNetworkReply::NetworkError error, const QString &errorString); -#ifndef QT_NO_OPENSSL - void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *); - void replySslConfigurationChanged(const QSslConfiguration&); -#endif - - // From QNonContiguousByteDeviceThreadForwardImpl in HTTP thread: - void resetUploadDataSlot(bool *r); - void wantUploadDataSlot(qint64); - void sentUploadDataSlot(qint64); - - bool sendCacheContents(const QNetworkCacheMetaData &metaData); - -private: - QHttpNetworkRequest httpRequest; // There is also a copy in the HTTP thread - int statusCode; - QString reasonPhrase; - // Will be increased by HTTP thread: - QSharedPointer<QAtomicInt> pendingDownloadDataEmissions; - QSharedPointer<QAtomicInt> pendingDownloadProgressEmissions; - bool loadingFromCache; - QByteDataBuffer pendingDownloadData; - bool usingZerocopyDownloadBuffer; - -#ifndef QT_NO_OPENSSL - QSslConfiguration *pendingSslConfiguration; - bool pendingIgnoreAllSslErrors; - QList<QSslError> pendingIgnoreSslErrorsList; -#endif - - quint64 resumeOffset; - - bool loadFromCacheIfAllowed(QHttpNetworkRequest &httpRequest); - void invalidateCache(); - void postRequest(); - void readFromHttp(); - void checkForRedirect(const int statusCode); -}; - -class QNetworkAccessHttpBackendFactory : public QNetworkAccessBackendFactory -{ -public: - virtual QNetworkAccessBackend *create(QNetworkAccessManager::Operation op, - const QNetworkRequest &request) const; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_HTTP - -#endif diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 0b51f7255b..eba5880352 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -50,7 +50,6 @@ #include "QtNetwork/qnetworksession.h" #include "QtNetwork/private/qsharednetworksession_p.h" -#include "qnetworkaccesshttpbackend_p.h" #include "qnetworkaccessftpbackend_p.h" #include "qnetworkaccessfilebackend_p.h" #include "qnetworkaccessdebugpipebackend_p.h" diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index ea295dbe97..8ce6080d3a 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -159,7 +159,6 @@ protected: private: friend class QNetworkReplyImplPrivate; - friend class QNetworkAccessHttpBackend; friend class QNetworkReplyHttpImpl; Q_DECLARE_PRIVATE(QNetworkAccessManager) diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 7f61ef9239..21b1d84a78 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -105,6 +105,10 @@ QT_BEGIN_NAMESPACE header and contains a QList<QNetworkCookie> representing the cookies sent by the server to be stored locally. + \value UserAgentHeader The User-Agent header sent by HTTP clients. + + \value ServerHeader The Server header received by HTTP clients. + \sa header(), setHeader(), rawHeader(), setRawHeader() */ @@ -650,6 +654,12 @@ static QByteArray headerName(QNetworkRequest::KnownHeaders header) case QNetworkRequest::ContentDispositionHeader: return "Content-Disposition"; + case QNetworkRequest::UserAgentHeader: + return "User-Agent"; + + case QNetworkRequest::ServerHeader: + return "Server"; + // no default: // if new values are added, this will generate a compiler warning } @@ -663,6 +673,8 @@ static QByteArray headerValue(QNetworkRequest::KnownHeaders header, const QVaria case QNetworkRequest::ContentTypeHeader: case QNetworkRequest::ContentLengthHeader: case QNetworkRequest::ContentDispositionHeader: + case QNetworkRequest::UserAgentHeader: + case QNetworkRequest::ServerHeader: return value.toByteArray(); case QNetworkRequest::LocationHeader: @@ -745,6 +757,13 @@ static QNetworkRequest::KnownHeaders parseHeaderName(const QByteArray &headerNam case 's': if (qstricmp(headerName.constData(), "set-cookie") == 0) return QNetworkRequest::SetCookieHeader; + else if (qstricmp(headerName.constData(), "server") == 0) + return QNetworkRequest::ServerHeader; + break; + + case 'u': + if (qstricmp(headerName.constData(), "user-agent") == 0) + return QNetworkRequest::UserAgentHeader; break; } @@ -778,6 +797,8 @@ static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QBy { // header is always a valid value switch (header) { + case QNetworkRequest::UserAgentHeader: + case QNetworkRequest::ServerHeader: case QNetworkRequest::ContentTypeHeader: // copy exactly, convert to QString return QString::fromLatin1(value); diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index eedb0f6592..aa86007127 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -66,7 +66,9 @@ public: LastModifiedHeader, CookieHeader, SetCookieHeader, - ContentDispositionHeader // added for QMultipartMessage + ContentDispositionHeader, // added for QMultipartMessage + UserAgentHeader, + ServerHeader }; enum Attribute { HttpStatusCodeAttribute, diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index df7766e2c5..d42c2598f8 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -527,6 +527,7 @@ void QHostInfoRunnable::run() iterator.remove(); hostInfo.setLookupId(postponed->id); postponed->resultEmitter.emitResultsReady(hostInfo); + delete postponed; } } } diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 7403590f8c..839a253b99 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -128,7 +128,7 @@ QT_BEGIN_NAMESPACE // forward declaration -static QMap<QString, QString> _q_mapFromX509Name(X509_NAME *name); +static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name); /*! Constructs a QSslCertificate by reading \a format encoded data @@ -297,19 +297,19 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons return QCryptographicHash::hash(toDer(), algorithm); } -static QString _q_SubjectInfoToString(QSslCertificate::SubjectInfo info) +static QByteArray _q_SubjectInfoToString(QSslCertificate::SubjectInfo info) { - QString str; + QByteArray str; switch (info) { - case QSslCertificate::Organization: str = QLatin1String("O"); break; - case QSslCertificate::CommonName: str = QLatin1String("CN"); break; - case QSslCertificate::LocalityName: str = QLatin1String("L"); break; - case QSslCertificate::OrganizationalUnitName: str = QLatin1String("OU"); break; - case QSslCertificate::CountryName: str = QLatin1String("C"); break; - case QSslCertificate::StateOrProvinceName: str = QLatin1String("ST"); break; - case QSslCertificate::DistinguishedNameQualifier: str = QLatin1String("dnQualifier"); break; - case QSslCertificate::SerialNumber: str = QLatin1String("serialNumber"); break; - case QSslCertificate::EmailAddress: str = QLatin1String("emailAddress"); break; + case QSslCertificate::Organization: str = QByteArray("O"); break; + case QSslCertificate::CommonName: str = QByteArray("CN"); break; + case QSslCertificate::LocalityName: str = QByteArray("L"); break; + case QSslCertificate::OrganizationalUnitName: str = QByteArray("OU"); break; + case QSslCertificate::CountryName: str = QByteArray("C"); break; + case QSslCertificate::StateOrProvinceName: str = QByteArray("ST"); break; + case QSslCertificate::DistinguishedNameQualifier: str = QByteArray("dnQualifier"); break; + case QSslCertificate::SerialNumber: str = QByteArray("serialNumber"); break; + case QSslCertificate::EmailAddress: str = QByteArray("emailAddress"); break; } return str; } @@ -334,20 +334,20 @@ QStringList QSslCertificate::issuerInfo(SubjectInfo info) const } /*! - Returns the issuer information for \a tag from the certificate, - or an empty string if there is no information for \a tag in the + Returns the issuer information for \a attribute from the certificate, + or an empty string if there is no information for \a attribute in the certificate. \sa subjectInfo() */ -QStringList QSslCertificate::issuerInfo(const QByteArray &tag) const +QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const { // lazy init if (d->issuerInfo.isEmpty() && d->x509) d->issuerInfo = _q_mapFromX509Name(q_X509_get_issuer_name(d->x509)); - return d->issuerInfo.values(QString::fromLatin1(tag)); + return d->issuerInfo.values(attribute); } /*! @@ -370,19 +370,57 @@ QStringList QSslCertificate::subjectInfo(SubjectInfo info) const } /*! - Returns the subject information for \a tag, or an empty string if - there is no information for \a tag in the certificate. + Returns the subject information for \a attribute, or an empty string if + there is no information for \a attribute in the certificate. \sa issuerInfo() */ -QStringList QSslCertificate::subjectInfo(const QByteArray &tag) const +QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const { // lazy init if (d->subjectInfo.isEmpty() && d->x509) d->subjectInfo = _q_mapFromX509Name(q_X509_get_subject_name(d->x509)); - return d->subjectInfo.values(QString::fromLatin1(tag)); + return d->subjectInfo.values(attribute); +} + +/*! + Returns a list of the attributes that have values in the subject + information of this certificate. The information associated + with a given attribute can be accessed using the subjectInfo() + method. Note that this list may include the OIDs for any + elements that are not known by the SSL backend. + + \sa subjectInfo() +*/ +QList<QByteArray> QSslCertificate::subjectInfoAttributes() const +{ + // lazy init + if (d->subjectInfo.isEmpty() && d->x509) + d->subjectInfo = + _q_mapFromX509Name(q_X509_get_subject_name(d->x509)); + + return d->subjectInfo.uniqueKeys(); +} + +/*! + Returns a list of the attributes that have values in the issuer + information of this certificate. The information associated + with a given attribute can be accessed using the issuerInfo() + method. Note that this list may include the OIDs for any + elements that are not known by the SSL backend. + + \sa subjectInfo() +*/ +QList<QByteArray> QSslCertificate::issuerInfoAttributes() const +{ + // lazy init + if (d->issuerInfo.isEmpty() && d->x509) + d->issuerInfo = + _q_mapFromX509Name(q_X509_get_issuer_name(d->x509)); + + return d->issuerInfo.uniqueKeys(); } /*! @@ -706,17 +744,32 @@ QByteArray QSslCertificatePrivate::text_from_X509(X509 *x509) return result; } -static QMap<QString, QString> _q_mapFromX509Name(X509_NAME *name) +QByteArray QSslCertificatePrivate::asn1ObjectName(ASN1_OBJECT *object) { - QMap<QString, QString> info; + int nid = q_OBJ_obj2nid(object); + if (nid != NID_undef) + return QByteArray(q_OBJ_nid2sn(nid)); + + // This is used for unknown info so we get the OID as text + char buf[80]; + q_i2t_ASN1_OBJECT(buf, sizeof(buf), object); + + return QByteArray(buf); +} + +static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name) +{ + QMap<QByteArray, QString> info; for (int i = 0; i < q_X509_NAME_entry_count(name); ++i) { X509_NAME_ENTRY *e = q_X509_NAME_get_entry(name, i); - const char *obj = q_OBJ_nid2sn(q_OBJ_obj2nid(q_X509_NAME_ENTRY_get_object(e))); + + QByteArray name = QSslCertificatePrivate::asn1ObjectName(q_X509_NAME_ENTRY_get_object(e)); unsigned char *data = 0; int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e)); - info.insertMulti(QString::fromUtf8(obj), QString::fromUtf8((char*)data, size)); + info.insertMulti(name, QString::fromUtf8((char*)data, size)); q_CRYPTO_free(data); } + return info; } diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index 8abaa3f73e..4de84dd4ba 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -100,9 +100,11 @@ public: QByteArray serialNumber() const; QByteArray digest(QCryptographicHash::Algorithm algorithm = QCryptographicHash::Md5) const; QStringList issuerInfo(SubjectInfo info) const; - QStringList issuerInfo(const QByteArray &tag) const; + QStringList issuerInfo(const QByteArray &attribute) const; QStringList subjectInfo(SubjectInfo info) const; - QStringList subjectInfo(const QByteArray &tag) const; + QStringList subjectInfo(const QByteArray &attribute) const; + QList<QByteArray> subjectInfoAttributes() const; + QList<QByteArray> issuerInfoAttributes() const; QMultiMap<QSsl::AlternateNameEntryType, QString> alternateSubjectNames() const; QDateTime effectiveDate() const; QDateTime expiryDate() const; diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h index eb192968c5..3cfcef7b57 100644 --- a/src/network/ssl/qsslcertificate_p.h +++ b/src/network/ssl/qsslcertificate_p.h @@ -83,8 +83,8 @@ public: QByteArray versionString; QByteArray serialNumberString; - QMap<QString, QString> issuerInfo; - QMap<QString, QString> subjectInfo; + QMap<QByteArray, QString> issuerInfo; + QMap<QByteArray, QString> subjectInfo; QDateTime notValidAfter; QDateTime notValidBefore; @@ -92,6 +92,7 @@ public: void init(const QByteArray &data, QSsl::EncodingFormat format); + static QByteArray asn1ObjectName(ASN1_OBJECT *object); static QByteArray QByteArray_from_X509(X509 *x509, QSsl::EncodingFormat format); static QByteArray text_from_X509(X509 *x509); static QSslCertificate QSslCertificate_from_X509(X509 *x509); diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index f191ed9324..294e2508d8 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1599,6 +1599,27 @@ bool QSslSocket::supportsSsl() } /*! + Returns the version number of the SSL library in use. Note that + this is the version of the library in use at run-time not compile + time. If no SSL support is available then this will return an + undefined value. +*/ +long QSslSocket::sslLibraryVersionNumber() +{ + return QSslSocketPrivate::sslLibraryVersionNumber(); +} + +/*! + Returns the version string of the SSL library in use. Note that + this is the version of the library in use at run-time not compile + time. If no SSL support is available then this will return an empty value. +*/ +QString QSslSocket::sslLibraryVersionString() +{ + return QSslSocketPrivate::sslLibraryVersionString(); +} + +/*! Starts a delayed SSL handshake for a client connection. This function can be called when the socket is in the \l ConnectedState but still in the \l UnencryptedMode. If it is not yet connected, diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index f175ffd946..803e79e0c4 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -176,6 +176,9 @@ public: QList<QSslError> sslErrors() const; static bool supportsSsl(); + static long sslLibraryVersionNumber(); + static QString sslLibraryVersionString(); + void ignoreSslErrors(const QList<QSslError> &errors); public Q_SLOTS: diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 479a6bd60e..c7e938a705 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -602,6 +602,23 @@ void QSslSocketPrivate::ensureInitialized() ensureCiphersAndCertsLoaded(); } +long QSslSocketPrivate::sslLibraryVersionNumber() +{ + return q_SSLeay(); +} + +QString QSslSocketPrivate::sslLibraryVersionString() +{ + if (!supportsSsl()) + return QString(); + + const char *versionString = q_SSLeay_version(SSLEAY_VERSION); + if (!versionString) + return QString(); + + return QString::fromLatin1(versionString); +} + /*! \internal diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index b652833b45..31afab003f 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -133,6 +133,10 @@ DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return) DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return) DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return 0, return) +DEFINEFUNC(const char *, OBJ_nid2ln, int a, a, return 0, return) +DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, return -1, return) + + DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return) #ifdef SSLEAY_MACROS DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return) @@ -276,6 +280,7 @@ DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMM DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG) DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return) DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return) +DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return) #ifdef Q_OS_SYMBIAN #define RESOLVEFUNC(func, ordinal, lib) \ @@ -687,6 +692,8 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(EVP_PKEY_new) RESOLVEFUNC(EVP_PKEY_type) RESOLVEFUNC(OBJ_nid2sn) + RESOLVEFUNC(OBJ_nid2ln) + RESOLVEFUNC(i2t_ASN1_OBJECT) RESOLVEFUNC(OBJ_obj2nid) #ifdef SSLEAY_MACROS // ### verify RESOLVEFUNC(PEM_ASN1_read_bio) @@ -788,6 +795,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(OPENSSL_add_all_algorithms_conf) RESOLVEFUNC(SSL_CTX_load_verify_locations) RESOLVEFUNC(SSLeay) + RESOLVEFUNC(SSLeay_version) #endif // Q_OS_SYMBIAN symbolsResolved = true; delete libs.first; diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index 658aa144a7..cd3aa07bc0 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -237,6 +237,8 @@ int q_EVP_PKEY_type(int a); EVP_PKEY *q_EVP_PKEY_new(); int q_i2d_X509(X509 *a, unsigned char **b); const char *q_OBJ_nid2sn(int a); +const char *q_OBJ_nid2ln(int a); +int q_i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *obj); int q_OBJ_obj2nid(const ASN1_OBJECT *a); #ifdef SSLEAY_MACROS // ### verify @@ -426,6 +428,7 @@ void q_OPENSSL_add_all_algorithms_noconf(); void q_OPENSSL_add_all_algorithms_conf(); int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath); long q_SSLeay(); +const char *q_SSLeay_version(int type); // Helper function class QDateTime; diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 86ecba07ce..b1dc656e88 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -116,6 +116,8 @@ public: bool allowRootCertOnDemandLoading; static bool supportsSsl(); + static long sslLibraryVersionNumber(); + static QString sslLibraryVersionString(); static void ensureInitialized(); static void deinitialize(); static QList<QSslCipher> defaultCiphers(); diff --git a/src/plugins/bearer/connman/qofonoservice_linux.cpp b/src/plugins/bearer/connman/qofonoservice_linux.cpp index 7c0a255c17..d862456ddc 100644 --- a/src/plugins/bearer/connman/qofonoservice_linux.cpp +++ b/src/plugins/bearer/connman/qofonoservice_linux.cpp @@ -57,8 +57,6 @@ #ifndef QT_NO_DBUS QT_BEGIN_NAMESPACE -static QDBusConnection dbusConnection = QDBusConnection::systemBus(); - QOfonoManagerInterface::QOfonoManagerInterface( QObject *parent) : QDBusAbstractInterface(QLatin1String(OFONO_SERVICE), @@ -106,7 +104,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), QLatin1String(OFONO_MANAGER_PATH), QLatin1String(OFONO_MANAGER_INTERFACE), QLatin1String("PropertyChanged"), @@ -256,7 +254,7 @@ void QOfonoModemInterface::connectNotify(const char *signal) QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_MODEM_INTERFACE), QLatin1String("PropertyChanged"), @@ -379,7 +377,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_NETWORK_REGISTRATION_INTERFACE), QLatin1String("PropertyChanged"), @@ -477,7 +475,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_NETWORK_OPERATOR_INTERFACE), QLatin1String("PropertyChanged"), @@ -580,7 +578,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_SIM_MANAGER_INTERFACE), QLatin1String("PropertyChanged"), @@ -669,7 +667,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_DATA_CONNECTION_MANAGER_INTERFACE), QLatin1String("PropertyChanged"), @@ -788,7 +786,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_DATA_CONTEXT_INTERFACE), QLatin1String("PropertyChanged"), @@ -870,7 +868,7 @@ void QOfonoSmsInterface::connectNotify(const char *signal) QOfonoDBusHelper *helper; helper = new QOfonoDBusHelper(this); - dbusConnection.connect(QLatin1String(OFONO_SERVICE), + QDBusConnection::systemBus().connect(QLatin1String(OFONO_SERVICE), this->path(), QLatin1String(OFONO_SMS_MANAGER_INTERFACE), QLatin1String("PropertyChanged"), diff --git a/src/plugins/platforms/uikit/README b/src/plugins/platforms/uikit/README index a101a3ac0b..f878cce50e 100644 --- a/src/plugins/platforms/uikit/README +++ b/src/plugins/platforms/uikit/README @@ -18,11 +18,11 @@ After configuring and building Qt you need to also build src/plugins/platforms/u Simulator: ---------- -configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations +configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake docs -nomake examples -nomake translations Device: ------- -configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations +configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -opengl es1 -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -static -nomake tools -nomake docs -nomake examples -nomake translations 2) XCode setup: - there are examples in the examples subdirectory of the platform plugin diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp index 9bf857d734..320113f58d 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.cpp @@ -48,6 +48,8 @@ #include "wayland-xcomposite-client-protocol.h" #include <X11/extensions/Xcomposite.h> +#include "qwaylandxcompositeeglintegration.h" +#include "windowmanager_integration/qwaylandwindowmanagerintegration.h" #include <QtCore/QDebug> @@ -147,3 +149,12 @@ void QWaylandXCompositeEGLWindow::sync_function(void *data) QWaylandXCompositeEGLWindow *that = static_cast<QWaylandXCompositeEGLWindow *>(data); that->m_waitingForSync = false; } + +void QWaylandXCompositeEGLWindow::requestActivateWindow() +{ +#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT + mDisplay->windowManagerIntegration()->authenticateWithToken(); +#endif + + QWaylandWindow::requestActivateWindow(); +} diff --git a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h index 535498a722..b2f8fbe6c4 100644 --- a/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h +++ b/src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglwindow.h @@ -55,6 +55,7 @@ public: WindowType windowType() const; void setGeometry(const QRect &rect); + void requestActivateWindow(); EGLSurface eglSurface() const; diff --git a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp index 7390c52740..60b0a5605e 100644 --- a/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp +++ b/src/plugins/platforms/wayland/windowmanager_integration/qwaylandwindowmanagerintegration.cpp @@ -99,19 +99,18 @@ void QWaylandWindowManagerIntegration::authenticateWithToken(const QByteArray &t QByteArray authToken = token; if (authToken.isEmpty()) authToken = qgetenv("WL_AUTHENTICATION_TOKEN"); - if (mWaylandWindowManager) + + if (mWaylandWindowManager && !authToken.isEmpty()) { wl_windowmanager_authenticate_with_token(mWaylandWindowManager, authToken.constData()); + } } void QWaylandWindowManagerIntegration::wlHandleOnScreenVisibilityChange(void *data, struct wl_windowmanager *wl_windowmanager, int visible) { Q_UNUSED(data); Q_UNUSED(wl_windowmanager); - QEvent evt(visible != 0 ? QEvent::ApplicationActivated : QEvent::ApplicationDeactivated); - + QEvent evt(visible != 0 ? QEvent::ApplicationActivate : QEvent::ApplicationDeactivate); QCoreApplication::sendEvent(QCoreApplication::instance(), &evt); - - qDebug() << "OnScreenVisibility" << (visible != 0); } void QWaylandWindowManagerIntegration::wlHandleScreenOrientationChange(void *data, struct wl_windowmanager *wl_windowmanager, int screenOrientation) diff --git a/src/sql/kernel/qsql.h b/src/sql/kernel/qsql.h index 5a1c32381d..f23b518bfb 100644 --- a/src/sql/kernel/qsql.h +++ b/src/sql/kernel/qsql.h @@ -56,10 +56,6 @@ namespace QSql { BeforeFirstRow = -1, AfterLastRow = -2 -#ifdef QT3_SUPPORT - , BeforeFirst = BeforeFirstRow, - AfterLast = AfterLastRow -#endif }; enum ParamTypeFlag @@ -87,21 +83,6 @@ namespace QSql HighPrecision = 0 }; - -#ifdef QT3_SUPPORT - enum Op { - None = -1, - Insert = 0, - Update = 1, - Delete = 2 - }; - - enum Confirm { - Cancel = -1, - No = 0, - Yes = 1 - }; -#endif } Q_DECLARE_OPERATORS_FOR_FLAGS(QSql::ParamType) diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index c5eac194f5..cd36d5d591 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -1434,26 +1434,6 @@ bool QSqlDatabase::isValid() const return d->driver && d->driver != d->shared_null()->driver; } -#ifdef QT3_SUPPORT -/*! - Use query.record() instead. -*/ -QSqlRecord QSqlDatabase::record(const QSqlQuery& query) const -{ return query.record(); } - -/*! - Use query.record() instead. -*/ -QSqlRecord QSqlDatabase::recordInfo(const QSqlQuery& query) const -{ return query.record(); } - -/*! - \fn QSqlRecord QSqlDatabase::recordInfo(const QString& tablename) const - - Use record() instead. -*/ -#endif - /*! Clones the database connection \a other and and stores it as \a connectionName. All the settings from the original database, e.g. diff --git a/src/sql/kernel/qsqldatabase.h b/src/sql/kernel/qsqldatabase.h index c8cde8557e..72c5694ceb 100644 --- a/src/sql/kernel/qsqldatabase.h +++ b/src/sql/kernel/qsqldatabase.h @@ -44,9 +44,6 @@ #include <QtCore/qstring.h> #include <QtSql/qsql.h> -#ifdef QT3_SUPPORT -#include <QtSql/qsqlrecord.h> -#endif QT_BEGIN_HEADER @@ -92,12 +89,6 @@ public: QStringList tables(QSql::TableType type = QSql::Tables) const; QSqlIndex primaryIndex(const QString& tablename) const; QSqlRecord record(const QString& tablename) const; -#ifdef QT3_SUPPORT - QT3_SUPPORT QSqlRecord record(const QSqlQuery& query) const; - inline QT3_SUPPORT QSqlRecord recordInfo(const QString& tablename) const - { return record(tablename); } - QT3_SUPPORT QSqlRecord recordInfo(const QSqlQuery& query) const; -#endif QSqlQuery exec(const QString& query = QString()) const; QSqlError lastError() const; bool isValid() const; diff --git a/src/sql/kernel/qsqldriver.h b/src/sql/kernel/qsqldriver.h index 479d3ac990..ee1e52538a 100644 --- a/src/sql/kernel/qsqldriver.h +++ b/src/sql/kernel/qsqldriver.h @@ -46,9 +46,6 @@ #include <QtCore/qstring.h> #include <QtCore/qstringlist.h> #include <QtSql/qsql.h> -#ifdef QT3_SUPPORT -#include <QtSql/qsqlquery.h> -#endif QT_BEGIN_HEADER @@ -93,17 +90,6 @@ public: virtual QStringList tables(QSql::TableType tableType) const; virtual QSqlIndex primaryIndex(const QString &tableName) const; virtual QSqlRecord record(const QString &tableName) const; -#ifdef QT3_SUPPORT - inline QT3_SUPPORT QSqlRecord record(const QSqlQuery& query) const - { return query.record(); } - inline QT3_SUPPORT QSqlRecord recordInfo(const QString& tablename) const - { return record(tablename); } - inline QT3_SUPPORT QSqlRecord recordInfo(const QSqlQuery& query) const - { return query.record(); } - inline QT3_SUPPORT QString nullText() const { return QLatin1String("NULL"); } - inline QT3_SUPPORT QString formatValue(const QSqlField *field, bool trimStrings = false) const - { return field ? formatValue(*field, trimStrings) : QString(); } -#endif virtual QString formatValue(const QSqlField& field, bool trimStrings = false) const; virtual QString escapeIdentifier(const QString &identifier, IdentifierType type) const; diff --git a/src/sql/kernel/qsqlerror.h b/src/sql/kernel/qsqlerror.h index 87136ecda9..fea3ca8526 100644 --- a/src/sql/kernel/qsqlerror.h +++ b/src/sql/kernel/qsqlerror.h @@ -59,13 +59,6 @@ public: StatementError, TransactionError, UnknownError -#ifdef QT3_SUPPORT - , None = NoError, - Connection = ConnectionError, - Statement = StatementError, - Transaction = TransactionError, - Unknown = UnknownError -#endif }; QSqlError( const QString& driverText = QString(), const QString& databaseText = QString(), diff --git a/src/sql/kernel/qsqlfield.h b/src/sql/kernel/qsqlfield.h index 182b5318e2..93992ea9d4 100644 --- a/src/sql/kernel/qsqlfield.h +++ b/src/sql/kernel/qsqlfield.h @@ -98,10 +98,6 @@ public: bool isGenerated() const; bool isValid() const; -#ifdef QT3_SUPPORT - inline QT3_SUPPORT void setNull() { clear(); } -#endif - private: void detach(); QVariant val; diff --git a/src/sql/kernel/qsqlindex.cpp b/src/sql/kernel/qsqlindex.cpp index 33e3c1ce34..764e93a678 100644 --- a/src/sql/kernel/qsqlindex.cpp +++ b/src/sql/kernel/qsqlindex.cpp @@ -164,60 +164,6 @@ void QSqlIndex::setDescending(int i, bool desc) sorts[i] = desc; } -#ifdef QT3_SUPPORT - -/*! - Returns a comma-separated list of all the index's field names as a - string. This string is suitable, for example, for generating a - SQL SELECT statement. Only generated fields are included in the - list (see \l{isGenerated()}). If a \a prefix is specified, e.g. a - table name, it is prepended before all field names in the form: - - "\a{prefix}.<fieldname>" - - If \a sep is specified, each field is separated by \a sep. If \a - verbose is true (the default), each field contains a suffix - indicating an ASCending or DESCending sort order. -*/ - -QString QSqlIndex::toString(const QString& prefix, const QString& sep, bool verbose) const -{ - QString s; - bool comma = false; - for (int i = 0; i < count(); ++i) { - if(comma) - s += sep + QLatin1Char(' '); - s += createField(i, prefix, verbose); - comma = true; - } - return s; -} - -/*! - Returns a list of all the index's field names. Only generated - fields are included in the list (see \l{isGenerated()}). If a \a - prefix is specified, e.g. a table name, all fields are prefixed in - the form: - - "\a{prefix}.<fieldname>" - - If \a verbose is true (the default), each field contains a suffix - indicating an ASCending or DESCending sort order. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet doc/src/snippets/code/src_sql_kernel_qsqlindex.cpp 0 - -*/ -QStringList QSqlIndex::toStringList(const QString& prefix, bool verbose) const -{ - QStringList s; - for (int i = 0; i < count(); ++i) - s += createField(i, prefix, verbose); - return s; -} -#endif - /*! \internal Creates a string representing the field number \a i using prefix \a diff --git a/src/sql/kernel/qsqlindex.h b/src/sql/kernel/qsqlindex.h index 97874e24f6..c88e30603f 100644 --- a/src/sql/kernel/qsqlindex.h +++ b/src/sql/kernel/qsqlindex.h @@ -70,14 +70,6 @@ public: bool isDescending(int i) const; void setDescending(int i, bool desc); -#ifdef QT3_SUPPORT - QT3_SUPPORT QString toString(const QString &prefix = QString(), - const QString &sep = QLatin1String(","), - bool verbose = true) const; - QT3_SUPPORT QStringList toStringList(const QString& prefix = QString(), - bool verbose = true) const; -#endif - private: QString createField(int i, const QString& prefix, bool verbose) const; QString cursor; diff --git a/src/sql/kernel/qsqlquery.h b/src/sql/kernel/qsqlquery.h index e82380956c..bd498f344a 100644 --- a/src/sql/kernel/qsqlquery.h +++ b/src/sql/kernel/qsqlquery.h @@ -94,9 +94,6 @@ public: bool seek(int i, bool relative = false); bool next(); bool previous(); -#ifdef QT3_SUPPORT - inline QT3_SUPPORT bool prev() { return previous(); } -#endif bool first(); bool last(); diff --git a/src/sql/kernel/qsqlrecord.cpp b/src/sql/kernel/qsqlrecord.cpp index dfeb3e0622..944f2fc9bc 100644 --- a/src/sql/kernel/qsqlrecord.cpp +++ b/src/sql/kernel/qsqlrecord.cpp @@ -244,34 +244,6 @@ int QSqlRecord::indexOf(const QString& name) const return -1; } -#ifdef QT3_SUPPORT -/*! - \obsolete - Use field() instead -*/ -const QSqlField* QSqlRecord::fieldPtr(int index) const -{ - if (!d->contains(index)) - return 0; - - return &d->fields.at(index); -} - -/*! - \obsolete - Use field() instead -*/ - -const QSqlField* QSqlRecord::fieldPtr(const QString& name) const -{ - int i = indexOf(name); - if (!d->contains(i)) - return 0; - - return &d->fields.at(i); -} -#endif //QT3_SUPPORT - /*! Returns the field at position \a index. If the position is out of range, an empty field is returned. @@ -496,49 +468,6 @@ bool QSqlRecord::isGenerated(int index) const return d->fields.value(index).isGenerated(); } -#ifdef QT3_SUPPORT -/*! - Returns a list of all the record's field names as a string - separated by \a sep. - - In the unlikely event that you used this function in Qt 3, you - can simulate it using the rest of the QSqlRecord public API. -*/ - -QString QSqlRecord::toString(const QString& prefix, const QString& sep) const -{ - QString pflist; - bool comma = false; - for (int i = 0; i < count(); ++i) { - if (!d->fields.value(i).isGenerated()) { - if (comma) - pflist += sep + QLatin1Char(' '); - pflist += d->createField(i, prefix); - comma = true; - } - } - return pflist; -} - -/*! - Returns a list of all the record's field names, each having the - prefix \a prefix. - - In the unlikely event that you used this function in Qt 3, you - can simulate it using the rest of the QSqlRecord public API. -*/ - -QStringList QSqlRecord::toStringList(const QString& prefix) const -{ - QStringList s; - for (int i = 0; i < count(); ++i) { - if (!d->fields.value(i).isGenerated()) - s += d->createField(i, prefix); - } - return s; -} -#endif // QT3_SUPPORT - /*! Returns the number of fields in the record. diff --git a/src/sql/kernel/qsqlrecord.h b/src/sql/kernel/qsqlrecord.h index e697e8e170..8c7a17ab1d 100644 --- a/src/sql/kernel/qsqlrecord.h +++ b/src/sql/kernel/qsqlrecord.h @@ -87,15 +87,6 @@ public: void setGenerated(const QString& name, bool generated); void setGenerated(int i, bool generated); -#ifdef QT3_SUPPORT - QT3_SUPPORT const QSqlField* fieldPtr(int i) const; - QT3_SUPPORT const QSqlField* fieldPtr(const QString& name) const; - inline QT3_SUPPORT int position(const QString& name) const { return indexOf(name); } - QT3_SUPPORT QString toString(const QString& prefix = QString(), - const QString& sep = QLatin1String(",")) const; - QT3_SUPPORT QStringList toStringList(const QString& prefix = QString()) const; -#endif - void append(const QSqlField& field); void replace(int pos, const QSqlField& field); void insert(int pos, const QSqlField& field); diff --git a/src/sql/kernel/qsqlresult.h b/src/sql/kernel/qsqlresult.h index 58b19c193d..984bd5e03f 100644 --- a/src/sql/kernel/qsqlresult.h +++ b/src/sql/kernel/qsqlresult.h @@ -74,10 +74,6 @@ protected: enum BindingSyntax { PositionalBinding, NamedBinding -#ifdef QT3_SUPPORT - , BindByPosition = PositionalBinding, - BindByName = NamedBinding -#endif }; explicit QSqlResult(const QSqlDriver * db); diff --git a/src/widgets/platforms/mac/qfontdatabase_mac.cpp b/src/widgets/platforms/mac/qfontdatabase_mac.cpp index b7335d684e..e1e59b79eb 100644 --- a/src/widgets/platforms/mac/qfontdatabase_mac.cpp +++ b/src/widgets/platforms/mac/qfontdatabase_mac.cpp @@ -113,7 +113,7 @@ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { QtFontFoundry *foundry = family->foundry(foundry_name, true); QtFontStyle::Key styleKey; - styleKey.styleName = style_name; + QString styleName = style_name; if(QCFType<CFDictionaryRef> styles = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)) { if(CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontWeightTrait)) { Q_ASSERT(CFNumberIsFloatType(weight)); @@ -134,7 +134,7 @@ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { } } - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, styleName, true); style->smoothScalable = true; if(QCFType<CFNumberRef> size = (CFNumberRef)CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) { //qDebug() << "WHEE"; @@ -207,7 +207,7 @@ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { QtFontFamily *family = db->family(familyName, true); QtFontFoundry *foundry = family->foundry(QString(), true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); style->pixelSize(0, true); style->smoothScalable = true; diff --git a/src/widgets/platforms/mac/qfontengine_coretext.mm b/src/widgets/platforms/mac/qfontengine_coretext.mm index a68a1551d9..303da8d363 100644 --- a/src/widgets/platforms/mac/qfontengine_coretext.mm +++ b/src/widgets/platforms/mac/qfontengine_coretext.mm @@ -492,17 +492,6 @@ void QCoreTextFontEngine::init() avgCharWidth = QFixed::fromReal(width * fontDef.pixelSize / emSize); } else avgCharWidth = QFontEngine::averageCharWidth(); - - ctMaxCharWidth = ctMinLeftBearing = ctMinRightBearing = 0; - QByteArray hheaTable = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a')); - if (hheaTable.size() >= 16) { - quint16 width = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 10)); - ctMaxCharWidth = width * fontDef.pixelSize / emSize; - qint16 bearing = qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 12)); - ctMinLeftBearing = bearing * fontDef.pixelSize / emSize; - bearing = qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 14)); - ctMinRightBearing = bearing * fontDef.pixelSize / emSize; - } } bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, @@ -599,20 +588,17 @@ QFixed QCoreTextFontEngine::averageCharWidth() const qreal QCoreTextFontEngine::maxCharWidth() const { - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMaxCharWidth) : ctMaxCharWidth; + return 0; } qreal QCoreTextFontEngine::minLeftBearing() const { - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMinLeftBearing) : ctMinLeftBearing; + return 0; } qreal QCoreTextFontEngine::minRightBearing() const { - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMinRightBearing) : ctMinLeftBearing; + return 0; } void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight) diff --git a/src/widgets/platforms/mac/qfontengine_coretext_p.h b/src/widgets/platforms/mac/qfontengine_coretext_p.h index b531856a27..d8a3033be6 100644 --- a/src/widgets/platforms/mac/qfontengine_coretext_p.h +++ b/src/widgets/platforms/mac/qfontengine_coretext_p.h @@ -107,9 +107,6 @@ private: int synthesisFlags; CGAffineTransform transform; QFixed avgCharWidth; - qreal ctMaxCharWidth; - qreal ctMinLeftBearing; - qreal ctMinRightBearing; friend class QCoreTextFontEngineMulti; }; diff --git a/src/widgets/platforms/s60/qfontdatabase_s60.cpp b/src/widgets/platforms/s60/qfontdatabase_s60.cpp index eea075fc47..cfa405dbc1 100644 --- a/src/widgets/platforms/s60/qfontdatabase_s60.cpp +++ b/src/widgets/platforms/s60/qfontdatabase_s60.cpp @@ -508,7 +508,7 @@ static bool registerScreenDeviceFont(int screenDeviceFontIndex, QtFontFamily *family = privateDb()->family(familyName, true); family->fixedPitch = faceAttrib.IsMonoWidth(); QtFontFoundry *foundry = family->foundry(QString(), true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); style->smoothScalable = typefaceSupport.iIsScalable; style->pixelSize(0, true); diff --git a/src/widgets/platforms/win/qfontdatabase_win.cpp b/src/widgets/platforms/win/qfontdatabase_win.cpp index 20f945a6c9..788eb307c3 100644 --- a/src/widgets/platforms/win/qfontdatabase_win.cpp +++ b/src/widgets/platforms/win/qfontdatabase_win.cpp @@ -284,7 +284,7 @@ void addFontToDatabase(QString familyName, const QString &scriptName, family->english_name = getEnglishName(familyName); QtFontFoundry *foundry = family->foundry(foundryName, true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); @@ -292,14 +292,14 @@ void addFontToDatabase(QString familyName, const QString &scriptName, if (styleKey.weight <= QFont::DemiBold) { QtFontStyle::Key key(styleKey); key.weight = QFont::Bold; - QtFontStyle *style = foundry->style(key, true); + QtFontStyle *style = foundry->style(key, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); } if (styleKey.style != QFont::StyleItalic) { QtFontStyle::Key key(styleKey); key.style = QFont::StyleItalic; - QtFontStyle *style = foundry->style(key, true); + QtFontStyle *style = foundry->style(key, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); } @@ -307,7 +307,7 @@ void addFontToDatabase(QString familyName, const QString &scriptName, QtFontStyle::Key key(styleKey); key.weight = QFont::Bold; key.style = QFont::StyleItalic; - QtFontStyle *style = foundry->style(key, true); + QtFontStyle *style = foundry->style(key, QString(), true); style->smoothScalable = scalable; style->pixelSize( size, TRUE); } diff --git a/src/widgets/platforms/x11/qfontdatabase_x11.cpp b/src/widgets/platforms/x11/qfontdatabase_x11.cpp index ed94fa6be1..922a97f3aa 100644 --- a/src/widgets/platforms/x11/qfontdatabase_x11.cpp +++ b/src/widgets/platforms/x11/qfontdatabase_x11.cpp @@ -680,7 +680,7 @@ static void loadXlfds(const char *reqFamily, int encoding_id) family->fontFileIndex = -1; family->symbol_checked = true; QtFontFoundry *foundry = family->foundry(QLatin1String(foundryName), true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); delete [] style->weightName; style->weightName = qstrdup(tokens[Weight]); @@ -1145,7 +1145,7 @@ static void loadFontConfig() family->fontFileIndex = index_value; QtFontStyle::Key styleKey; - styleKey.styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); + QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); styleKey.style = (slant_value == FC_SLANT_ITALIC) ? QFont::StyleItalic : ((slant_value == FC_SLANT_OBLIQUE) @@ -1160,7 +1160,7 @@ static void loadFontConfig() QtFontFoundry *foundry = family->foundry(foundry_value ? QString::fromUtf8((const char *)foundry_value) : QString(), true); - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, styleName, true); if (spacing_value < FC_MONO) family->fixedPitch = false; @@ -1212,7 +1212,7 @@ static void loadFontConfig() for (int i = 0; i < 4; ++i) { styleKey.style = (i%2) ? QFont::StyleNormal : QFont::StyleItalic; styleKey.weight = (i > 1) ? QFont::Bold : QFont::Normal; - QtFontStyle *style = foundry->style(styleKey, true); + QtFontStyle *style = foundry->style(styleKey, QString(), true); style->smoothScalable = true; QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE, true); QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true); @@ -1360,7 +1360,7 @@ static void initializeDb() if (equiv) continue; // let's fake one... - equiv = foundry->style(key, true); + equiv = foundry->style(key, QString(), true); equiv->smoothScalable = true; QtFontSize *equiv_size = equiv->pixelSize(SMOOTH_SCALABLE, true); diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index 2f5384b902..671adafcbd 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -1324,29 +1324,6 @@ QXmlInputSource::QXmlInputSource(QIODevice *dev) d->inputDevice->setTextModeEnabled(false); } -#ifdef QT3_SUPPORT -/*! - Use the QXmlInputSource(QIODevice *) constructor instead, with - the device used by \a stream. - - \sa QTextStream::device() -*/ -QXmlInputSource::QXmlInputSource(QTextStream& stream) -{ - init(); - d->inputStream = &stream; -} - -/*! - Use QXmlInputSource(&\a file) instead. -*/ -QXmlInputSource::QXmlInputSource(QFile& file) -{ - init(); - d->inputDevice = &file; -} -#endif - /*! Destructor. */ diff --git a/src/xml/sax/qxml.h b/src/xml/sax/qxml.h index 8b402dfedb..52eea6ce76 100644 --- a/src/xml/sax/qxml.h +++ b/src/xml/sax/qxml.h @@ -172,11 +172,6 @@ public: static const ushort EndOfData; static const ushort EndOfDocument; -#ifdef QT3_SUPPORT - QT3_SUPPORT_CONSTRUCTOR QXmlInputSource(QFile& file); - QT3_SUPPORT_CONSTRUCTOR QXmlInputSource(QTextStream& stream); -#endif - protected: virtual QString fromRawData(const QByteArray &data, bool beginning = false); |