diff options
Diffstat (limited to 'src')
118 files changed, 1281 insertions, 647 deletions
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 86d027eb35..9a61efd1b2 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1059,16 +1059,18 @@ # define Q_COMPILER_DEFAULT_DELETE_MEMBERS #endif -#if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304 -# define Q_DECL_CONSTEXPR constexpr -# define Q_DECL_RELAXED_CONSTEXPR constexpr -# define Q_CONSTEXPR constexpr -# define Q_RELAXED_CONSTEXPR constexpr -#elif defined Q_COMPILER_CONSTEXPR -# define Q_DECL_CONSTEXPR constexpr -# define Q_DECL_RELAXED_CONSTEXPR -# define Q_CONSTEXPR constexpr -# define Q_RELAXED_CONSTEXPR const +#if defined Q_COMPILER_CONSTEXPR +# if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304 +# define Q_DECL_CONSTEXPR constexpr +# define Q_DECL_RELAXED_CONSTEXPR constexpr +# define Q_CONSTEXPR constexpr +# define Q_RELAXED_CONSTEXPR constexpr +# else +# define Q_DECL_CONSTEXPR constexpr +# define Q_DECL_RELAXED_CONSTEXPR +# define Q_CONSTEXPR constexpr +# define Q_RELAXED_CONSTEXPR const +# endif #else # define Q_DECL_CONSTEXPR # define Q_DECL_RELAXED_CONSTEXPR diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index e4cd3b3509..76d173bb3e 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -91,10 +91,11 @@ public: Qt_5_5 = Qt_5_4, Qt_5_6 = 17, Qt_5_7 = Qt_5_6, -#if QT_VERSION >= 0x050800 + Qt_5_8 = Qt_5_7, +#if QT_VERSION >= 0x050900 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif - Qt_DefaultCompiledVersion = Qt_5_7 + Qt_DefaultCompiledVersion = Qt_5_8 }; enum ByteOrder { diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index fd204b00de..ee004b4293 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1148,13 +1148,24 @@ QByteArray QIODevice::read(qint64 maxSize) Q_D(QIODevice); QByteArray result; - CHECK_MAXLEN(read, result); - #if defined QIODEVICE_DEBUG printf("%p QIODevice::read(%lld), d->pos = %lld, d->buffer.size() = %lld\n", this, maxSize, d->pos, d->buffer.size()); #endif + // Try to prevent the data from being copied, if we have a chunk + // with the same size in the read buffer. + if (maxSize == d->buffer.nextDataBlockSize() && !d->transactionStarted + && (d->openMode & (QIODevice::ReadOnly | QIODevice::Text)) == QIODevice::ReadOnly) { + result = d->buffer.read(); + if (!d->isSequential()) + d->pos += maxSize; + if (d->buffer.isEmpty()) + readData(nullptr, 0); + return result; + } + + CHECK_MAXLEN(read, result); if (maxSize >= MaxByteArraySize) { checkWarnMessage(this, "read", "maxSize argument exceeds QByteArray size limit"); maxSize = MaxByteArraySize - 1; diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h index 947b3bbb55..d9d4fd906a 100644 --- a/src/corelib/io/qurl.h +++ b/src/corelib/io/qurl.h @@ -48,9 +48,9 @@ #include <QtCore/qpair.h> #include <QtCore/qglobal.h> -#ifdef Q_OS_MAC +#if defined(Q_OS_MAC) || defined(Q_QDOC) Q_FORWARD_DECLARE_CF_TYPE(CFURL); -# ifdef __OBJC__ +# if defined(__OBJC__) || defined(Q_QDOC) Q_FORWARD_DECLARE_OBJC_CLASS(NSURL); # endif #endif diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 6ccc7b729b..330a1eb0f5 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2497,6 +2497,26 @@ QStringList QCoreApplication::libraryPaths() } } +#ifdef Q_OS_DARWIN + // Check the main bundle's PlugIns directory as this is a standard location for Apple OSes. + // Note that the QLibraryInfo::PluginsPath below will coincidentally be the same as this value + // but with a different casing, so it can't be relied upon when the underlying filesystem + // is case sensitive (and this is always the case on newer OSes like iOS). + if (CFBundleRef bundleRef = CFBundleGetMainBundle()) { + if (QCFType<CFURLRef> urlRef = CFBundleCopyBuiltInPlugInsURL(bundleRef)) { + if (QCFType<CFURLRef> absoluteUrlRef = CFURLCopyAbsoluteURL(urlRef)) { + if (QCFString path = CFURLCopyFileSystemPath(absoluteUrlRef, kCFURLPOSIXPathStyle)) { + if (QFile::exists(path)) { + path = QDir(path).canonicalPath(); + if (!app_libpaths->contains(path)) + app_libpaths->append(path); + } + } + } + } + } +#endif // Q_OS_DARWIN + QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath); if (QFile::exists(installPathPlugins)) { // Make sure we convert from backslashes to slashes. diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm index 55f27a5b60..437e4062ad 100644 --- a/src/corelib/kernel/qeventdispatcher_cf.mm +++ b/src/corelib/kernel/qeventdispatcher_cf.mm @@ -210,6 +210,13 @@ QEventDispatcherCoreFoundation::~QEventDispatcherCoreFoundation() m_cfSocketNotifier.removeSocketNotifiers(); } +QEventLoop *QEventDispatcherCoreFoundation::currentEventLoop() const +{ + QEventLoop *eventLoop = QThreadData::current()->eventLoops.top(); + Q_ASSERT(eventLoop); + return eventLoop; +} + /*! Processes all pending events that match \a flags until there are no more events to process. Returns \c true if pending events were handled; @@ -302,10 +309,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag // to exit, and then unwind back to the previous event loop which will break // immediately, since it has already been exited. - QEventLoop *currentEventLoop = QThreadData::current()->eventLoops.top(); - Q_ASSERT(currentEventLoop); - - if (!currentEventLoop->isRunning()) { + if (!currentEventLoop()->isRunning()) { qEventDispatcherDebug() << "Top level event loop was exited"; break; } else { diff --git a/src/corelib/kernel/qeventdispatcher_cf_p.h b/src/corelib/kernel/qeventdispatcher_cf_p.h index c2592cacc8..e6581e2bac 100644 --- a/src/corelib/kernel/qeventdispatcher_cf_p.h +++ b/src/corelib/kernel/qeventdispatcher_cf_p.h @@ -228,6 +228,8 @@ public: void flush(); protected: + QEventLoop *currentEventLoop() const; + virtual bool processPostedEvents(); struct ProcessEventsState diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 69f884f4ed..54cc9d33c3 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -167,6 +167,7 @@ class QMutex; struct QMetaObjectPrivate { + // revision 7 is Qt 5.0 everything lower is not supported enum { OutputRevision = 7 }; // Used by moc, qmetaobjectbuilder and qdbus int revision; @@ -175,12 +176,9 @@ struct QMetaObjectPrivate int methodCount, methodData; int propertyCount, propertyData; int enumeratorCount, enumeratorData; - int constructorCount, constructorData; //since revision 2 - int flags; //since revision 3 - int signalCount; //since revision 4 - // revision 5 introduces changes in normalized signatures, no new members - // revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself - // revision 7 is Qt 5 + int constructorCount, constructorData; + int flags; + int signalCount; static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject) { return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index e3e536d7e1..a6baff8a49 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3662,15 +3662,31 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i return; } - const QObjectPrivate::ConnectionList *list; - if (signal_index < connectionLists->count()) - list = &connectionLists->at(signal_index); - else - list = &connectionLists->allsignals; + // contains the non-empty connection lists + const QObjectPrivate::ConnectionList *lists[2]; + int numLists = 0; + if (signal_index < connectionLists->count()) { + const auto *list = &connectionLists->at(signal_index); + if (list->first) // only add if non-empty + lists[numLists++] = list; + } + if (connectionLists->allsignals.first) // only add if non-empty + lists[numLists++] = &connectionLists->allsignals; + + for (int i = 0; i < numLists; ++i) { + const auto *list = lists[i]; + if (i == 0) { + // on the first iteration, the mutex must be locked already + Q_ASSERT(!locker.mutex()->tryLock()); + } else { + // otherwise the mutex is unlocked and must be relocked + locker.relock(); + if (connectionLists->orphaned) + break; + } - do { QObjectPrivate::Connection *c = list->first; - if (!c) continue; + Q_ASSERT(c); // We need to check against last here to ensure that signals added // during the signal emission are not emitted in this emission. QObjectPrivate::Connection *last = list->last; @@ -3723,8 +3739,6 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i // destructor of the slot object might also lock a mutex from the signalSlotLock() mutex pool, // and that would deadlock if the pool happens to return the same mutex. obj.reset(); - - locker.relock(); } else if (c->callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) { //we compare the vtable to make sure we are not in the destructor of the object. const int methodIndex = c->method(); @@ -3738,7 +3752,6 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i if (qt_signal_spy_callback_set.slot_end_callback != 0) qt_signal_spy_callback_set.slot_end_callback(receiver, methodIndex); - locker.relock(); } else { const int method = c->method_relative + c->method_offset; locker.unlock(); @@ -3753,19 +3766,17 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i if (qt_signal_spy_callback_set.slot_end_callback != 0) qt_signal_spy_callback_set.slot_end_callback(receiver, method); - - locker.relock(); } - if (connectionLists->orphaned) + if (c == last) // early break without relock for the last signal break; - } while (c != last && (c = c->nextConnectionList) != 0); - if (connectionLists->orphaned) - break; - } while (list != &connectionLists->allsignals && - //start over for all signals; - ((list = &connectionLists->allsignals), true)); + locker.relock(); + + if (connectionLists->orphaned) + break; + } while ((c = c->nextConnectionList) != 0); + } } diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index dce750b5ad..53b38c3be2 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -120,7 +120,11 @@ void QFactoryLoader::update() if (!QDir(path).exists(QLatin1String("."))) continue; - QStringList plugins = QDir(path).entryList(QDir::Files); + QStringList plugins = QDir(path).entryList( +#ifdef Q_OS_WIN + QStringList(QStringLiteral("*.dll")), +#endif + QDir::Files); QLibraryPrivate *library = 0; #ifdef Q_OS_MAC diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h index a1d16b449e..409eec1989 100644 --- a/src/corelib/plugin/quuid.h +++ b/src/corelib/plugin/quuid.h @@ -55,9 +55,9 @@ typedef struct _GUID #endif #endif -#ifdef Q_OS_DARWIN +#if defined(Q_OS_DARWIN) || defined(Q_QDOC) Q_FORWARD_DECLARE_CF_TYPE(CFUUID); -# ifdef __OBJC__ +# if defined(__OBJC__) || defined(Q_QDOC) Q_FORWARD_DECLARE_OBJC_CLASS(NSUUID); # endif #endif diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 19c1f25bc7..40ea7646fc 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -56,9 +56,9 @@ #error qbytearray.h must be included before any header file that defines truncate #endif -#ifdef Q_OS_MAC +#if defined(Q_OS_MAC) || defined(Q_QDOC) Q_FORWARD_DECLARE_CF_TYPE(CFData); -# ifdef __OBJC__ +# if defined(__OBJC__) || defined(Q_QDOC) Q_FORWARD_DECLARE_OBJC_CLASS(NSData); # endif #endif diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index ee3be5553b..7955160c93 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -46,9 +46,9 @@ #include <limits> -#ifdef Q_OS_MAC +#if defined(Q_OS_MAC) || defined(Q_QDOC) Q_FORWARD_DECLARE_CF_TYPE(CFDate); -# ifdef __OBJC__ +# if defined(__OBJC__) || defined(Q_QDOC) Q_FORWARD_DECLARE_OBJC_CLASS(NSDate); # endif #endif diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index c7cd1a7751..5c6ce179d0 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -8324,6 +8324,78 @@ QString &QString::setRawData(const QChar *unicode, int size) Returns the size of the Latin-1 string stored in this object. */ +/*! \fn QLatin1Char QLatin1String::at(int pos) const + \since 5.8 + + Returns the character at position \a pos in this object. + + \note This function performs no error checking. + The behavior is undefined when \a pos < 0 or \a pos ≥ size(). + + \sa operator[]() +*/ + +/*! \fn QLatin1Char QLatin1String::operator[](int pos) const + \since 5.8 + + Returns the character at position \a pos in this object. + + \note This function performs no error checking. + The behavior is undefined when \a pos < 0 or \a pos ≥ size(). + + \sa at() +*/ + +/*! \fn QLatin1String QLatin1String::mid(int start) const + \since 5.8 + + Returns the substring starting at position \a start in this object, + and extending to the end of the string. + + \note This function performs no error checking. + The behavior is undefined when \a start < 0 or \a start > size(). + + \sa left(), right() +*/ + +/*! \fn QLatin1String QLatin1String::mid(int start, int length) const + \since 5.8 + \overload + + Returns the substring of length \a length starting at position + \a start in this object. + + \note This function performs no error checking. + The behavior is undefined when \a start < 0, \length < 0, + or \a start + \a length > size(). + + \sa left(), right() +*/ + +/*! \fn QLatin1String QLatin1String::left(int length) const + \since 5.8 + + Returns the substring of length \a length starting at position + 0 in this object. + + \note This function performs no error checking. + The behavior is undefined when \length < 0 or \a length > size(). + + \sa mid(), right() +*/ + +/*! \fn QLatin1String QLatin1String::right(int length) const + \since 5.8 + + Returns the substring of length \a length starting at position + size() - \a length in this object. + + \note This function performs no error checking. + The behavior is undefined when \length < 0 or \a length > size(). + + \sa mid(), left() +*/ + /*! \fn bool QLatin1String::operator==(const QString &other) const Returns \c true if this string is equal to string \a other; diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index ddaab1f544..7a30316f25 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -68,9 +68,9 @@ namespace std #error qstring.h must be included before any header file that defines truncate #endif -#ifdef Q_OS_MAC +#if defined(Q_OS_MAC) || defined(Q_QDOC) Q_FORWARD_DECLARE_CF_TYPE(CFString); -# ifdef __OBJC__ +# if defined(__OBJC__) || defined(Q_QDOC) Q_FORWARD_DECLARE_OBJC_CLASS(NSString); # endif #endif @@ -99,6 +99,18 @@ public: Q_DECL_CONSTEXPR int size() const Q_DECL_NOTHROW { return m_size; } Q_DECL_CONSTEXPR const char *data() const Q_DECL_NOTHROW { return m_data; } + Q_DECL_CONSTEXPR QLatin1Char at(int i) const { return QLatin1Char(m_data[i]); } + Q_DECL_CONSTEXPR QLatin1Char operator[](int i) const { return at(i); } + + Q_DECL_CONSTEXPR QLatin1String mid(int pos) const + { return QLatin1String(m_data + pos, m_size - pos); } + Q_DECL_CONSTEXPR QLatin1String mid(int pos, int n) const + { return QLatin1String(m_data + pos, n); } + Q_DECL_CONSTEXPR QLatin1String left(int n) const + { return QLatin1String(m_data, n); } + Q_DECL_CONSTEXPR QLatin1String right(int n) const + { return QLatin1String(m_data + m_size - n, n); } + inline bool operator==(const QString &s) const Q_DECL_NOTHROW; inline bool operator!=(const QString &s) const Q_DECL_NOTHROW; inline bool operator>(const QString &s) const Q_DECL_NOTHROW; @@ -1512,24 +1524,10 @@ inline QStringRef::QStringRef(const QString *aString, int aPosition, int aSize) inline QStringRef::QStringRef(const QString *aString) :m_string(aString), m_position(0), m_size(aString?aString->size() : 0){} +// QStringRef <> QStringRef Q_CORE_EXPORT bool operator==(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW; inline bool operator!=(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW { return !(s1 == s2); } -Q_CORE_EXPORT bool operator==(const QString &s1, const QStringRef &s2) Q_DECL_NOTHROW; -inline bool operator!=(const QString &s1, const QStringRef &s2) Q_DECL_NOTHROW -{ return !(s1 == s2); } -inline bool operator==(const QStringRef &s1, const QString &s2) Q_DECL_NOTHROW -{ return s2 == s1; } -inline bool operator!=(const QStringRef &s1, const QString &s2) Q_DECL_NOTHROW -{ return s2 != s1; } -Q_CORE_EXPORT bool operator==(QLatin1String s1, const QStringRef &s2) Q_DECL_NOTHROW; -inline bool operator!=(QLatin1String s1, const QStringRef &s2) Q_DECL_NOTHROW -{ return !(s1 == s2); } -inline bool operator==(const QStringRef &s1, QLatin1String s2) Q_DECL_NOTHROW -{ return s2 == s1; } -inline bool operator!=(const QStringRef &s1, QLatin1String s2) Q_DECL_NOTHROW -{ return s2 != s1; } - Q_CORE_EXPORT bool operator<(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW; inline bool operator>(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW { return s2 < s1; } @@ -1538,6 +1536,53 @@ inline bool operator<=(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHRO inline bool operator>=(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW { return !(s1 < s2); } +// QString <> QStringRef +Q_CORE_EXPORT bool operator==(const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW; +inline bool operator!=(const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return lhs.compare(rhs) != 0; } +inline bool operator< (const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return lhs.compare(rhs) < 0; } +inline bool operator> (const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return lhs.compare(rhs) > 0; } +inline bool operator<=(const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return lhs.compare(rhs) <= 0; } +inline bool operator>=(const QString &lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return lhs.compare(rhs) >= 0; } + +inline bool operator==(const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs == lhs; } +inline bool operator!=(const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs != lhs; } +inline bool operator< (const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs > lhs; } +inline bool operator> (const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs < lhs; } +inline bool operator<=(const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs >= lhs; } +inline bool operator>=(const QStringRef &lhs, const QString &rhs) Q_DECL_NOTHROW { return rhs <= lhs; } + +inline int QString::compare(const QStringRef &s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW +{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); } +inline int QString::compare(const QString &s1, const QStringRef &s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW +{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); } +inline int QStringRef::compare(const QString &s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW +{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); } +inline int QStringRef::compare(const QStringRef &s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW +{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); } +inline int QStringRef::compare(QLatin1String s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW +{ return QString::compare_helper(constData(), length(), s, cs); } +inline int QStringRef::compare(const QStringRef &s1, const QString &s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW +{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); } +inline int QStringRef::compare(const QStringRef &s1, const QStringRef &s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW +{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); } +inline int QStringRef::compare(const QStringRef &s1, QLatin1String s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW +{ return QString::compare_helper(s1.constData(), s1.length(), s2, cs); } + +// QLatin1String <> QStringRef +Q_CORE_EXPORT bool operator==(QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW; +inline bool operator!=(QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return rhs.compare(lhs) != 0; } +inline bool operator< (QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return rhs.compare(lhs) > 0; } +inline bool operator> (QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return rhs.compare(lhs) < 0; } +inline bool operator<=(QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return rhs.compare(lhs) >= 0; } +inline bool operator>=(QLatin1String lhs, const QStringRef &rhs) Q_DECL_NOTHROW { return rhs.compare(lhs) <= 0; } + +inline bool operator==(const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs == lhs; } +inline bool operator!=(const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs != lhs; } +inline bool operator< (const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs > lhs; } +inline bool operator> (const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs < lhs; } +inline bool operator<=(const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs >= lhs; } +inline bool operator>=(const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW { return rhs <= lhs; } + #if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) inline QT_ASCII_CAST_WARN bool QStringRef::operator==(const char *s) const { return QString::compare_helper(constData(), size(), s, -1) == 0; } @@ -1566,23 +1611,6 @@ inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QStringRef &s2) { return QString::compare_helper(s2.constData(), s2.size(), s1, -1) >= 0; } #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) -inline int QString::compare(const QStringRef &s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW -{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); } -inline int QString::compare(const QString &s1, const QStringRef &s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW -{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); } -inline int QStringRef::compare(const QString &s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW -{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); } -inline int QStringRef::compare(const QStringRef &s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW -{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); } -inline int QStringRef::compare(QLatin1String s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW -{ return QString::compare_helper(constData(), length(), s, cs); } -inline int QStringRef::compare(const QStringRef &s1, const QString &s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW -{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); } -inline int QStringRef::compare(const QStringRef &s1, const QStringRef &s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW -{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); } -inline int QStringRef::compare(const QStringRef &s1, QLatin1String s2, Qt::CaseSensitivity cs) Q_DECL_NOTHROW -{ return QString::compare_helper(s1.constData(), s1.length(), s2, cs); } - inline int QString::localeAwareCompare(const QStringRef &s) const { return localeAwareCompare_helper(constData(), length(), s.constData(), s.length()); } inline int QString::localeAwareCompare(const QString& s1, const QStringRef& s2) diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 93dc71c3d8..95a7ece67c 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -152,10 +152,10 @@ else:win32 { } else:integrity:SOURCES += tools/qelapsedtimer_unix.cpp tools/qlocale_unix.cpp else:SOURCES += tools/qelapsedtimer_generic.cpp -contains(QT_CONFIG, zlib) { - include($$PWD/../../3rdparty/zlib.pri) -} else { +contains(QT_CONFIG, system-zlib) { include($$PWD/../../3rdparty/zlib_dependency.pri) +} else { + include($$PWD/../../3rdparty/zlib.pri) } contains(QT_CONFIG,icu) { diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index 0906b65d96..2a17edd038 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -298,10 +298,8 @@ QRectF QBlittablePlatformPixmap::clipAndTransformRect(const QRectF &rect) const if (clipData->hasRectClip) { transformationRect &= clipData->clipRect; } else if (clipData->hasRegionClip) { - const QVector<QRect> rects = clipData->clipRegion.rects(); - for (int i = 0; i < rects.size(); i++) { - transformationRect &= rects.at(i); - } + for (const QRect &rect : clipData->clipRegion) + transformationRect &= rect; } } } diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 78a4dc4f35..2b3b153537 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -2065,6 +2065,16 @@ QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos) */ /*! + \fn QInputMethodEvent::Attribute::Attribute(AttributeType type, int start, int length) + \overload + \since 5.7 + + Constructs an input method attribute with no value. \a type + specifies the type of attribute, and \a start and \a length + the position of the attribute. +*/ + +/*! Constructs an event of type QEvent::InputMethod. The attributes(), preeditString(), commitString(), replacementStart(), and replacementLength() are initialized to default values. diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 0a207667ad..1c42c61e85 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -535,8 +535,9 @@ public: class Attribute { public: Attribute(AttributeType t, int s, int l, QVariant val) : type(t), start(s), length(l), value(qMove(val)) {} - AttributeType type; + Attribute(AttributeType t, int s, int l) : type(t), start(s), length(l), value() {} + AttributeType type; int start; int length; QVariant value; diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h index eb3a9d5545..e790e3094f 100644 --- a/src/gui/kernel/qhighdpiscaling_p.h +++ b/src/gui/kernel/qhighdpiscaling_p.h @@ -382,8 +382,7 @@ inline QRegion fromNativeLocalRegion(const QRegion &pixelRegion, const QWindow * qreal scaleFactor = QHighDpiScaling::factor(window); QRegion pointRegion; - const auto rects = pixelRegion.rects(); - for (const QRect &rect : rects) { + for (const QRect &rect : pixelRegion) { pointRegion += QRect(fromNative(rect.topLeft(), scaleFactor), fromNative(rect.size(), scaleFactor)); } @@ -399,7 +398,7 @@ inline QRegion fromNativeLocalExposedRegion(const QRegion &pixelRegion, const QW const qreal scaleFactor = QHighDpiScaling::factor(window); QRegion pointRegion; - foreach (const QRect &rect, pixelRegion.rects()) { + for (const QRect &rect : pixelRegion) { const QPointF topLeftP = QPointF(rect.topLeft()) / scaleFactor; const QPointF bottomRightP = QPointF(rect.bottomRight()) / scaleFactor; pointRegion += QRect(QPoint(qFloor(topLeftP.x()), qFloor(topLeftP.y())), @@ -415,8 +414,7 @@ inline QRegion toNativeLocalRegion(const QRegion &pointRegion, const QWindow *wi qreal scaleFactor = QHighDpiScaling::factor(window); QRegion pixelRegon; - const auto rects = pointRegion.rects(); - for (const QRect &rect : rects) { + for (const QRect &rect : pointRegion) { pixelRegon += QRect(toNative(rect.topLeft(), scaleFactor), toNative(rect.size(), scaleFactor)); } diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index fe4d167078..c36186b815 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -156,23 +156,33 @@ public: QString windowTitle; }; -QFontDialogOptions::QFontDialogOptions() : d(new QFontDialogOptionsPrivate) +QFontDialogOptions::QFontDialogOptions(QFontDialogOptionsPrivate *dd) + : d(dd) { } -QFontDialogOptions::QFontDialogOptions(const QFontDialogOptions &rhs) : d(rhs.d) +QFontDialogOptions::~QFontDialogOptions() { } -QFontDialogOptions &QFontDialogOptions::operator=(const QFontDialogOptions &rhs) +namespace { + struct FontDialogCombined : QFontDialogOptionsPrivate, QFontDialogOptions + { + FontDialogCombined() : QFontDialogOptionsPrivate(), QFontDialogOptions(this) {} + FontDialogCombined(const FontDialogCombined &other) + : QFontDialogOptionsPrivate(other), QFontDialogOptions(this) {} + }; +} + +// static +QSharedPointer<QFontDialogOptions> QFontDialogOptions::create() { - if (this != &rhs) - d = rhs.d; - return *this; + return QSharedPointer<FontDialogCombined>::create(); } -QFontDialogOptions::~QFontDialogOptions() +QSharedPointer<QFontDialogOptions> QFontDialogOptions::clone() const { + return QSharedPointer<FontDialogCombined>::create(*static_cast<const FontDialogCombined*>(this)); } QString QFontDialogOptions::windowTitle() const @@ -289,23 +299,33 @@ public: QString windowTitle; }; -QColorDialogOptions::QColorDialogOptions() : d(new QColorDialogOptionsPrivate) +QColorDialogOptions::QColorDialogOptions(QColorDialogOptionsPrivate *dd) + : d(dd) { } -QColorDialogOptions::QColorDialogOptions(const QColorDialogOptions &rhs) : d(rhs.d) +QColorDialogOptions::~QColorDialogOptions() { } -QColorDialogOptions &QColorDialogOptions::operator=(const QColorDialogOptions &rhs) +namespace { + struct ColorDialogCombined : QColorDialogOptionsPrivate, QColorDialogOptions + { + ColorDialogCombined() : QColorDialogOptionsPrivate(), QColorDialogOptions(this) {} + ColorDialogCombined(const ColorDialogCombined &other) + : QColorDialogOptionsPrivate(other), QColorDialogOptions(this) {} + }; +} + +// static +QSharedPointer<QColorDialogOptions> QColorDialogOptions::create() { - if (this != &rhs) - d = rhs.d; - return *this; + return QSharedPointer<ColorDialogCombined>::create(); } -QColorDialogOptions::~QColorDialogOptions() +QSharedPointer<QColorDialogOptions> QColorDialogOptions::clone() const { + return QSharedPointer<ColorDialogCombined>::create(*static_cast<const ColorDialogCombined*>(this)); } QString QColorDialogOptions::windowTitle() const @@ -436,23 +456,32 @@ public: QStringList supportedSchemes; }; -QFileDialogOptions::QFileDialogOptions() : d(new QFileDialogOptionsPrivate) +QFileDialogOptions::QFileDialogOptions(QFileDialogOptionsPrivate *dd) + : d(dd) { } -QFileDialogOptions::QFileDialogOptions(const QFileDialogOptions &rhs) : d(rhs.d) +QFileDialogOptions::~QFileDialogOptions() { } -QFileDialogOptions &QFileDialogOptions::operator=(const QFileDialogOptions &rhs) +namespace { + struct FileDialogCombined : QFileDialogOptionsPrivate, QFileDialogOptions + { + FileDialogCombined() : QFileDialogOptionsPrivate(), QFileDialogOptions(this) {} + FileDialogCombined(const FileDialogCombined &other) : QFileDialogOptionsPrivate(other), QFileDialogOptions(this) {} + }; +} + +// static +QSharedPointer<QFileDialogOptions> QFileDialogOptions::create() { - if (this != &rhs) - d = rhs.d; - return *this; + return QSharedPointer<FileDialogCombined>::create(); } -QFileDialogOptions::~QFileDialogOptions() +QSharedPointer<QFileDialogOptions> QFileDialogOptions::clone() const { + return QSharedPointer<FileDialogCombined>::create(*static_cast<const FileDialogCombined*>(this)); } QString QFileDialogOptions::windowTitle() const @@ -728,23 +757,33 @@ public: QPlatformDialogHelper::StandardButtons buttons; }; -QMessageDialogOptions::QMessageDialogOptions() : d(new QMessageDialogOptionsPrivate) +QMessageDialogOptions::QMessageDialogOptions(QMessageDialogOptionsPrivate *dd) + : d(dd) { } -QMessageDialogOptions::QMessageDialogOptions(const QMessageDialogOptions &rhs) : d(rhs.d) +QMessageDialogOptions::~QMessageDialogOptions() { } -QMessageDialogOptions &QMessageDialogOptions::operator=(const QMessageDialogOptions &rhs) +namespace { + struct MessageDialogCombined : QMessageDialogOptionsPrivate, QMessageDialogOptions + { + MessageDialogCombined() : QMessageDialogOptionsPrivate(), QMessageDialogOptions(this) {} + MessageDialogCombined(const MessageDialogCombined &other) + : QMessageDialogOptionsPrivate(other), QMessageDialogOptions(this) {} + }; +} + +// static +QSharedPointer<QMessageDialogOptions> QMessageDialogOptions::create() { - if (this != &rhs) - d = rhs.d; - return *this; + return QSharedPointer<MessageDialogCombined>::create(); } -QMessageDialogOptions::~QMessageDialogOptions() +QSharedPointer<QMessageDialogOptions> QMessageDialogOptions::clone() const { + return QSharedPointer<MessageDialogCombined>::create(*static_cast<const MessageDialogCombined*>(this)); } QString QMessageDialogOptions::windowTitle() const diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h index 825dcf293d..78667643fe 100644 --- a/src/gui/kernel/qplatformdialoghelper.h +++ b/src/gui/kernel/qplatformdialoghelper.h @@ -72,6 +72,8 @@ class QFontDialogOptionsPrivate; class QFileDialogOptionsPrivate; class QMessageDialogOptionsPrivate; +#define QPLATFORMDIALOGHELPERS_HAS_CREATE + class Q_GUI_EXPORT QPlatformDialogHelper : public QObject { Q_OBJECT @@ -176,6 +178,10 @@ QT_BEGIN_NAMESPACE class Q_GUI_EXPORT QColorDialogOptions { Q_GADGET + Q_DISABLE_COPY(QColorDialogOptions) +protected: + explicit QColorDialogOptions(QColorDialogOptionsPrivate *dd); + ~QColorDialogOptions(); public: enum ColorDialogOption { ShowAlphaChannel = 0x00000001, @@ -186,12 +192,8 @@ public: Q_DECLARE_FLAGS(ColorDialogOptions, ColorDialogOption) Q_FLAG(ColorDialogOptions) - QColorDialogOptions(); - QColorDialogOptions(const QColorDialogOptions &rhs); - QColorDialogOptions &operator=(const QColorDialogOptions &rhs); - ~QColorDialogOptions(); - - void swap(QColorDialogOptions &other) { qSwap(d, other.d); } + static QSharedPointer<QColorDialogOptions> create(); + QSharedPointer<QColorDialogOptions> clone() const; QString windowTitle() const; void setWindowTitle(const QString &); @@ -211,11 +213,9 @@ public: static void setStandardColor(int index, QRgb color); private: - QSharedDataPointer<QColorDialogOptionsPrivate> d; + QColorDialogOptionsPrivate *d; }; -Q_DECLARE_SHARED(QColorDialogOptions) - class Q_GUI_EXPORT QPlatformColorDialogHelper : public QPlatformDialogHelper { Q_OBJECT @@ -237,6 +237,11 @@ private: class Q_GUI_EXPORT QFontDialogOptions { Q_GADGET + Q_DISABLE_COPY(QFontDialogOptions) +protected: + explicit QFontDialogOptions(QFontDialogOptionsPrivate *dd); + ~QFontDialogOptions(); + public: enum FontDialogOption { NoButtons = 0x00000001, @@ -250,12 +255,8 @@ public: Q_DECLARE_FLAGS(FontDialogOptions, FontDialogOption) Q_FLAG(FontDialogOptions) - QFontDialogOptions(); - QFontDialogOptions(const QFontDialogOptions &rhs); - QFontDialogOptions &operator=(const QFontDialogOptions &rhs); - ~QFontDialogOptions(); - - void swap(QFontDialogOptions &other) { qSwap(d, other.d); } + static QSharedPointer<QFontDialogOptions> create(); + QSharedPointer<QFontDialogOptions> clone() const; QString windowTitle() const; void setWindowTitle(const QString &); @@ -266,11 +267,9 @@ public: FontDialogOptions options() const; private: - QSharedDataPointer<QFontDialogOptionsPrivate> d; + QFontDialogOptionsPrivate *d; }; -Q_DECLARE_SHARED(QFontDialogOptions) - class Q_GUI_EXPORT QPlatformFontDialogHelper : public QPlatformDialogHelper { Q_OBJECT @@ -292,6 +291,11 @@ private: class Q_GUI_EXPORT QFileDialogOptions { Q_GADGET + Q_DISABLE_COPY(QFileDialogOptions) +protected: + QFileDialogOptions(QFileDialogOptionsPrivate *dd); + ~QFileDialogOptions(); + public: enum ViewMode { Detail, List }; Q_ENUM(ViewMode) @@ -319,12 +323,8 @@ public: Q_DECLARE_FLAGS(FileDialogOptions, FileDialogOption) Q_FLAG(FileDialogOptions) - QFileDialogOptions(); - QFileDialogOptions(const QFileDialogOptions &rhs); - QFileDialogOptions &operator=(const QFileDialogOptions &rhs); - ~QFileDialogOptions(); - - void swap(QFileDialogOptions &other) { qSwap(d, other.d); } + static QSharedPointer<QFileDialogOptions> create(); + QSharedPointer<QFileDialogOptions> clone() const; QString windowTitle() const; void setWindowTitle(const QString &); @@ -383,11 +383,9 @@ public: static QString defaultNameFilterString(); private: - QSharedDataPointer<QFileDialogOptionsPrivate> d; + QFileDialogOptionsPrivate *d; }; -Q_DECLARE_SHARED(QFileDialogOptions) - class Q_GUI_EXPORT QPlatformFileDialogHelper : public QPlatformDialogHelper { Q_OBJECT @@ -423,17 +421,18 @@ private: class Q_GUI_EXPORT QMessageDialogOptions { Q_GADGET + Q_DISABLE_COPY(QMessageDialogOptions) +protected: + QMessageDialogOptions(QMessageDialogOptionsPrivate *dd); + ~QMessageDialogOptions(); + public: // Keep in sync with QMessageBox::Icon enum Icon { NoIcon, Information, Warning, Critical, Question }; Q_ENUM(Icon) - QMessageDialogOptions(); - QMessageDialogOptions(const QMessageDialogOptions &rhs); - QMessageDialogOptions &operator=(const QMessageDialogOptions &rhs); - ~QMessageDialogOptions(); - - void swap(QMessageDialogOptions &other) { qSwap(d, other.d); } + static QSharedPointer<QMessageDialogOptions> create(); + QSharedPointer<QMessageDialogOptions> clone() const; QString windowTitle() const; void setWindowTitle(const QString &); @@ -454,11 +453,9 @@ public: QPlatformDialogHelper::StandardButtons standardButtons() const; private: - QSharedDataPointer<QMessageDialogOptionsPrivate> d; + QMessageDialogOptionsPrivate *d; }; -Q_DECLARE_SHARED(QMessageDialogOptions) - class Q_GUI_EXPORT QPlatformMessageDialogHelper : public QPlatformDialogHelper { Q_OBJECT diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp index d93871c99b..5c05a05d80 100644 --- a/src/gui/opengl/qopenglpaintengine.cpp +++ b/src/gui/opengl/qopenglpaintengine.cpp @@ -1012,11 +1012,11 @@ void QOpenGL2PaintEngineExPrivate::fillStencilWithVertexArray(const float *data, funcs.glStencilMask(0xff); // Enable stencil writes if (dirtyStencilRegion.intersects(currentScissorBounds)) { - QVector<QRect> clearRegion = dirtyStencilRegion.intersected(currentScissorBounds).rects(); + const QRegion clearRegion = dirtyStencilRegion.intersected(currentScissorBounds); funcs.glClearStencil(0); // Clear to zero - for (int i = 0; i < clearRegion.size(); ++i) { + for (const QRect &rect : clearRegion) { #ifndef QT_GL_NO_SCISSOR_TEST - setScissor(clearRegion.at(i)); + setScissor(rect); #endif funcs.glClear(GL_STENCIL_BUFFER_BIT); } diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index a325ee923e..29c3ba3480 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -4032,7 +4032,7 @@ template<typename T> struct QBlendBase { typedef T BlendType; - QBlendBase(QSpanData *d, Operator o) + QBlendBase(QSpanData *d, const Operator &o) : data(d) , op(o) , dest(0) @@ -4051,7 +4051,7 @@ struct QBlendBase class BlendSrcGeneric : public QBlendBase<uint> { public: - BlendSrcGeneric(QSpanData *d, Operator o) + BlendSrcGeneric(QSpanData *d, const Operator &o) : QBlendBase<uint>(d, o) { } @@ -4077,7 +4077,7 @@ public: class BlendSrcGenericRGB64 : public QBlendBase<QRgba64> { public: - BlendSrcGenericRGB64(QSpanData *d, Operator o) + BlendSrcGenericRGB64(QSpanData *d, const Operator &o) : QBlendBase<QRgba64>(d, o) { } diff --git a/src/gui/painting/qpaintengine_blitter.cpp b/src/gui/painting/qpaintengine_blitter.cpp index 81191d07b8..a50d1dfd73 100644 --- a/src/gui/painting/qpaintengine_blitter.cpp +++ b/src/gui/painting/qpaintengine_blitter.cpp @@ -312,7 +312,7 @@ void QBlitterPaintEnginePrivate::updateBrushState(QPainterState *s) { Qt::BrushStyle style = qbrush_style(s->brush); - caps.updateState(STATE_BRUSH_PATTERN, style > Qt::SolidPattern); + caps.updateState(STATE_BRUSH_PATTERN, style != Qt::SolidPattern); caps.updateState(STATE_BRUSH_ALPHA, qbrush_color(s->brush).alpha() < 255); } @@ -374,9 +374,8 @@ void QBlitterPaintEnginePrivate::fillRect(const QRectF &rect, const QColor &colo else pmData->blittable()->fillRect(targetRect & clipData->clipRect, color); } else if (clipData->hasRegionClip) { - QVector<QRect> rects = clipData->clipRegion.rects(); - for (int i = 0; i < rects.size(); ++i) { - QRect intersectRect = rects.at(i).intersected(targetRect.toRect()); + for (const QRect &rect : clipData->clipRegion) { + QRect intersectRect = rect.intersected(targetRect.toRect()); if (!intersectRect.isEmpty()) { unlock(); if (alpha) @@ -609,10 +608,8 @@ void QBlitterPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) } } else if (clipData->hasRegionClip) { QRect unclippedTargetRect(x, y, blitWidth, blitHeight); - const QVector<QRect> intersectedRects = clipData->clipRegion.intersected(unclippedTargetRect).rects(); - const int intersectedSize = intersectedRects.size(); - for (int i = 0; i < intersectedSize; ++i) { - const QRect &targetRect = intersectedRects.at(i); + const QRegion targetRegion = clipData->clipRegion.intersected(unclippedTargetRect); + for (const QRect &targetRect : targetRegion) { if (!targetRect.isValid() || targetRect.isEmpty()) continue; int tmpSrcX = srcX + (targetRect.x() - x); @@ -686,9 +683,8 @@ void QBlitterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const Q if (clipData->hasRectClip) { d->clipAndDrawPixmap(clipData->clipRect, targetRect, pm, sr, canDrawOpacity); } else if (clipData->hasRegionClip) { - QVector<QRect>rects = clipData->clipRegion.rects(); - for (int i = 0; i<rects.size(); ++i) - d->clipAndDrawPixmap(rects.at(i), targetRect, pm, sr, canDrawOpacity); + for (const QRect &rect : clipData->clipRegion) + d->clipAndDrawPixmap(rect, targetRect, pm, sr, canDrawOpacity); } } else { QRectF deviceRect(0, 0, paintDevice()->width(), paintDevice()->height()); diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 4ab029cf7a..00dc4ccb81 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -3893,7 +3893,7 @@ void QClipData::setClipRect(const QRect &rect) void QClipData::setClipRegion(const QRegion ®ion) { if (region.rectCount() == 1) { - setClipRect(region.rects().at(0)); + setClipRect(*region.begin()); return; } diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index bcef14ca61..e70079915a 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -2835,7 +2835,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) QRect rect = r.boundingRect(); if (qt_show_painter_debug_output) printf("QPainter::setClipRegion(), size=%d, [%d,%d,%d,%d]\n", - r.rects().size(), rect.x(), rect.y(), rect.width(), rect.height()); + r.rectCount(), rect.x(), rect.y(), rect.width(), rect.height()); #endif if (!d->engine) { qWarning("QPainter::setClipRegion: Painter not active"); @@ -6473,6 +6473,8 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText extended->drawTextItem(QPointF(x, y), ti2); else engine->drawTextItem(QPointF(x, y), ti2); + drawTextItemDecoration(q, p, ti2.fontEngine, textEngine, ti2.underlineStyle, + ti2.flags, ti2.width.toReal(), ti2.charFormat); if (!rtl) x += ti2.width.toReal(); @@ -6504,6 +6506,8 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText extended->drawTextItem(QPointF(x, y), ti2); else engine->drawTextItem(QPointF(x,y), ti2); + drawTextItemDecoration(q, p, ti2.fontEngine, textEngine, ti2.underlineStyle, + ti2.flags, ti2.width.toReal(), ti2.charFormat); // reset the high byte for all glyphs const int hi = which << 24; @@ -6515,9 +6519,9 @@ void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QText extended->drawTextItem(p, ti); else engine->drawTextItem(p, ti); + drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle, + ti.flags, ti.width.toReal(), ti.charFormat); } - drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle, - ti.flags, ti.width.toReal(), ti.charFormat); if (state->renderHints != oldRenderHints) { state->renderHints = oldRenderHints; diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index ba14a45d4a..7072a2d79c 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -1294,10 +1294,9 @@ void QPainterPath::addRegion(const QRegion ®ion) ensureData(); detach(); - QVector<QRect> rects = region.rects(); - d_func()->elements.reserve(rects.size() * 5); - for (int i=0; i<rects.size(); ++i) - addRect(rects.at(i)); + d_func()->elements.reserve(region.rectCount() * 5); + for (const QRect &rect : region) + addRect(rect); } diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index f83f1c997e..86f176bc99 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1078,9 +1078,8 @@ void QPdfEngine::updateState(const QPaintEngineState &state) } else if (flags & DirtyClipRegion) { d->clipEnabled = true; QPainterPath path; - QVector<QRect> rects = state.clipRegion().rects(); - for (int i = 0; i < rects.size(); ++i) - path.addRect(rects.at(i)); + for (const QRect &rect : state.clipRegion()) + path.addRect(rect); updateClipPath(path, state.clipOperation()); flags |= DirtyClipPath; } else if (flags & DirtyClipEnabled) { diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 6cec4a0a8d..61975ee045 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -250,9 +250,8 @@ static QRegion deviceRegion(const QRegion ®ion, QWindow *window, const QPoint return region; QVector<QRect> rects; - const QVector<QRect> regionRects = region.rects(); - rects.reserve(regionRects.count()); - for (const QRect &rect : regionRects) + rects.reserve(region.rectCount()); + for (const QRect &rect : region) rects.append(deviceRect(rect.translated(offset), window)); QRegion deviceRegion; diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index 35c4abb3ac..b70257a00f 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -81,8 +81,8 @@ QT_BEGIN_NAMESPACE contains() a QPoint or QRect. The bounding rectangle can be found with boundingRect(). - The function rects() gives a decomposition of the region into - rectangles. + Iteration over the region (with begin(), end()) gives a decomposition of + the region into rectangles. The same sequence of rectangles is returned by rects(). Example of using complex regions: \snippet code/src_gui_painting_qregion.cpp 0 @@ -395,23 +395,24 @@ void QRegion::exec(const QByteArray &buffer, int ver, QDataStream::ByteOrder byt QDataStream &operator<<(QDataStream &s, const QRegion &r) { - QVector<QRect> a = r.rects(); - if (a.isEmpty()) { + auto b = r.begin(), e = r.end(); + if (b == e) { s << (quint32)0; } else { + const auto size = e - b; if (s.version() == 1) { - int i; - for (i = a.size() - 1; i > 0; --i) { + for (auto i = size - 1; i > 0; --i) { s << (quint32)(12 + i * 24); s << (int)QRGN_OR; } - for (i = 0; i < a.size(); ++i) { - s << (quint32)(4+8) << (int)QRGN_SETRECT << a[i]; - } + for (auto it = b; it != e; ++it) + s << (quint32)(4+8) << (int)QRGN_SETRECT << *it; } else { - s << (quint32)(4 + 4 + 16 * a.size()); // 16: storage size of QRect + s << quint32(4 + 4 + 16 * size); // 16: storage size of QRect s << (qint32)QRGN_RECTS; - s << a; + s << quint32(size); + for (auto it = b; it != e; ++it) + s << *it; } } return s; @@ -722,12 +723,9 @@ bool QRegion::intersects(const QRegion ®ion) const if (rectCount() == 1 && region.rectCount() == 1) return true; - const QVector<QRect> myRects = rects(); - const QVector<QRect> otherRects = region.rects(); - - for (QVector<QRect>::const_iterator i1 = myRects.constBegin(); i1 < myRects.constEnd(); ++i1) - for (QVector<QRect>::const_iterator i2 = otherRects.constBegin(); i2 < otherRects.constEnd(); ++i2) - if (rect_intersects(*i1, *i2)) + for (const QRect &myRect : *this) + for (const QRect &otherRect : region) + if (rect_intersects(myRect, otherRect)) return true; return false; } @@ -928,6 +926,100 @@ QRegion QRegion::intersect(const QRect &r) const */ /*! + \typedef QRegion::const_iterator + \since 5.8 + + An iterator over the QRects that make up the region. + + QRegion does not offer mutable iterators. + + \sa begin(), end() +*/ + +/*! + \typedef QRegion::const_reverse_iterator + \since 5.8 + + A reverse iterator over the QRects that make up the region. + + QRegion does not offer mutable iterators. + + \sa rbegin(), rend() +*/ + +/*! + \fn QRegion::begin() const + \since 5.8 + + Returns a const_iterator pointing to the beginning of the range of + rectangles that make up this range, in the order in which rects() + returns them. + + \sa rbegin(), cbegin(), end() +*/ + +/*! + \fn QRegion::cbegin() const + \since 5.8 + + Same as begin(). +*/ + +/*! + \fn QRegion::end() const + \since 5.8 + + Returns a const_iterator pointing to one past the end of the range of + rectangles that make up this range, in the order in which rects() + returns them. + + \sa rend(), cend(), begin() +*/ + +/*! + \fn QRegion::cend() const + \since 5.8 + + Same as end(). +*/ + +/*! + \fn QRegion::rbegin() const + \since 5.8 + + Returns a const_reverse_iterator pointing to the beginning of the range of + rectangles that make up this range, in the reverse order in which rects() + returns them. + + \sa begin(), crbegin(), rend() +*/ + +/*! + \fn QRegion::crbegin() const + \since 5.8 + + Same as rbegin(). +*/ + +/*! + \fn QRegion::rend() const + \since 5.8 + + Returns a const_reverse_iterator pointing to one past the end of the range of + rectangles that make up this range, in the reverse order in which rects() + returns them. + + \sa end(), crend(), rbegin() +*/ + +/*! + \fn QRegion::crend() const + \since 5.8 + + Same as rend(). +*/ + +/*! \fn void QRegion::setRects(const QRect *rects, int number) Sets the region using the array of rectangles specified by \a rects and @@ -1057,13 +1149,11 @@ Q_GUI_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion) return result; } - const QVector<QRect> rects = region.rects(); + auto rect = region.begin(); + const auto end = region.end(); QVarLengthArray<Segment> segments; - segments.resize(4 * rects.size()); - - const QRect *rect = rects.constData(); - const QRect *end = rect + rects.size(); + segments.resize(4 * (end - rect)); int lastRowSegmentCount = 0; Segment *lastRowSegments = 0; @@ -1171,6 +1261,12 @@ struct QRegionPrivate { } } + const QRect *begin() const Q_DECL_NOTHROW + { return numRects == 1 ? &extents : rects.data(); } // avoid vectorize() + + const QRect *end() const Q_DECL_NOTHROW + { return begin() + numRects; } + inline void append(const QRect *r); void append(const QRegionPrivate *r); void prepend(const QRect *r); @@ -4248,6 +4344,16 @@ QVector<QRect> QRegion::rects() const } } +QRegion::const_iterator QRegion::begin() const Q_DECL_NOTHROW +{ + return d->qt_rgn ? d->qt_rgn->begin() : nullptr; +} + +QRegion::const_iterator QRegion::end() const Q_DECL_NOTHROW +{ + return d->qt_rgn ? d->qt_rgn->end() : nullptr; +} + void QRegion::setRects(const QRect *rects, int num) { *this = QRegion(); @@ -4310,10 +4416,10 @@ bool QRegion::intersects(const QRect &rect) const if (d->qt_rgn->numRects == 1) return true; - const QVector<QRect> myRects = rects(); - for (QVector<QRect>::const_iterator it = myRects.constBegin(); it < myRects.constEnd(); ++it) - if (rect_intersects(r, *it)) + for (const QRect &rect : *this) { + if (rect_intersects(r, rect)) return true; + } return false; } diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index d66f80fcde..f00b1fd284 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -81,6 +81,18 @@ public: bool isEmpty() const; bool isNull() const; + typedef const QRect *const_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + const_iterator begin() const Q_DECL_NOTHROW; + const_iterator cbegin() const Q_DECL_NOTHROW { return begin(); } + const_iterator end() const Q_DECL_NOTHROW; + const_iterator cend() const Q_DECL_NOTHROW { return end(); } + const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); } + const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return rbegin(); } + const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); } + const_reverse_iterator crend() const Q_DECL_NOTHROW { return rend(); } + bool contains(const QPoint &p) const; bool contains(const QRect &r) const; diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index d2c3eceeef..bfc8551a9b 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -247,6 +247,7 @@ void QTextureGlyphCache::fillInPendingGlyphs() resizeCache(qNextPowerOfTwo(requiredWidth - 1), qNextPowerOfTwo(requiredHeight - 1)); } + beginFillTexture(); { QHash<GlyphAndSubPixelPosition, Coord>::iterator iter = m_pendingGlyphs.begin(); while (iter != m_pendingGlyphs.end()) { @@ -256,6 +257,7 @@ void QTextureGlyphCache::fillInPendingGlyphs() ++iter; } } + endFillTexture(); m_pendingGlyphs.clear(); } diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index 14271ccc65..a8efb4abb1 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -117,7 +117,9 @@ public: virtual void resizeTextureData(int width, int height) = 0; virtual int glyphPadding() const { return 0; } + virtual void beginFillTexture() { } virtual void fillTexture(const Coord &coord, glyph_t glyph, QFixed subPixelPosition) = 0; + virtual void endFillTexture() { } inline void createCache(int width, int height) { m_w = width; diff --git a/src/gui/text/qabstracttextdocumentlayout.cpp b/src/gui/text/qabstracttextdocumentlayout.cpp index ff2497817e..2278378613 100644 --- a/src/gui/text/qabstracttextdocumentlayout.cpp +++ b/src/gui/text/qabstracttextdocumentlayout.cpp @@ -602,9 +602,32 @@ QTextDocument *QAbstractTextDocumentLayout::document() const */ QString QAbstractTextDocumentLayout::anchorAt(const QPointF& pos) const { + QTextCharFormat fmt = formatAt(pos).toCharFormat(); + return fmt.anchorHref(); +} + +/*! + \since 5.8 + + Returns the source of the image at the given position \a pos, or an empty + string if no image exists at that point. +*/ +QString QAbstractTextDocumentLayout::imageAt(const QPointF &pos) const +{ + QTextImageFormat fmt = formatAt(pos).toImageFormat(); + return fmt.name(); +} + +/*! + \since 5.8 + + Returns the text format at the given position \a pos. +*/ +QTextFormat QAbstractTextDocumentLayout::formatAt(const QPointF &pos) const +{ int cursorPos = hitTest(pos, Qt::ExactHit); if (cursorPos == -1) - return QString(); + return QTextFormat(); // compensate for preedit in the hit text block QTextBlock block = document()->firstBlock(); @@ -623,8 +646,7 @@ QString QAbstractTextDocumentLayout::anchorAt(const QPointF& pos) const QTextDocumentPrivate *pieceTable = qobject_cast<const QTextDocument *>(parent())->docHandle(); QTextDocumentPrivate::FragmentIterator it = pieceTable->find(cursorPos); - QTextCharFormat fmt = pieceTable->formatCollection()->charFormat(it->format); - return fmt.anchorHref(); + return pieceTable->formatCollection()->format(it->format); } /*! diff --git a/src/gui/text/qabstracttextdocumentlayout.h b/src/gui/text/qabstracttextdocumentlayout.h index 01704fe37b..e2fad12ad3 100644 --- a/src/gui/text/qabstracttextdocumentlayout.h +++ b/src/gui/text/qabstracttextdocumentlayout.h @@ -82,7 +82,10 @@ public: virtual void draw(QPainter *painter, const PaintContext &context) = 0; virtual int hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const = 0; + QString anchorAt(const QPointF& pos) const; + QString imageAt(const QPointF &pos) const; + QTextFormat formatAt(const QPointF &pos) const; virtual int pageCount() const = 0; virtual QSizeF documentSize() const = 0; diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index b9e05e726e..4782ef5e20 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -899,7 +899,7 @@ static QBrush brushFromData(const BrushData& c, const QPalette &pal) } } -static BorderStyle parseStyleValue(QCss::Value v) +static BorderStyle parseStyleValue(const QCss::Value &v) { if (v.type == Value::KnownIdentifier) { switch (v.variant.toInt()) { diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp index 473ddd0172..bca4a38b56 100644 --- a/src/gui/text/qdistancefield.cpp +++ b/src/gui/text/qdistancefield.cpp @@ -45,6 +45,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcDistanceField, "qt.distanceField"); + namespace { enum FillHDir @@ -732,8 +734,45 @@ static bool imageHasNarrowOutlines(const QImage &im) return minHThick == 1 || minVThick == 1; } +static int QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE = 54; +static int QT_DISTANCEFIELD_DEFAULT_TILESIZE = 64; +static int QT_DISTANCEFIELD_DEFAULT_SCALE = 16; +static int QT_DISTANCEFIELD_DEFAULT_RADIUS = 80; +static int QT_DISTANCEFIELD_DEFAULT_HIGHGLYPHCOUNT = 2000; + +static void initialDistanceFieldFactor() +{ + static bool initialized = false; + if (initialized) + return; + initialized = true; + + if (qEnvironmentVariableIsSet("QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE")) { + QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE = qEnvironmentVariableIntValue("QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE"); + qCDebug(lcDistanceField) << "set the QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE:" << QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE; + } + + if (qEnvironmentVariableIsSet("QT_DISTANCEFIELD_DEFAULT_TILESIZE")) { + QT_DISTANCEFIELD_DEFAULT_TILESIZE = qEnvironmentVariableIntValue("QT_DISTANCEFIELD_DEFAULT_TILESIZE"); + qCDebug(lcDistanceField) << "set the QT_DISTANCEFIELD_DEFAULT_TILESIZE:" << QT_DISTANCEFIELD_DEFAULT_TILESIZE; + } + if (qEnvironmentVariableIsSet("QT_DISTANCEFIELD_DEFAULT_SCALE")) { + QT_DISTANCEFIELD_DEFAULT_SCALE = qEnvironmentVariableIntValue("QT_DISTANCEFIELD_DEFAULT_SCALE"); + qCDebug(lcDistanceField) << "set the QT_DISTANCEFIELD_DEFAULT_SCALE:" << QT_DISTANCEFIELD_DEFAULT_SCALE; + } + if (qEnvironmentVariableIsSet("QT_DISTANCEFIELD_DEFAULT_RADIUS")) { + QT_DISTANCEFIELD_DEFAULT_RADIUS = qEnvironmentVariableIntValue("QT_DISTANCEFIELD_DEFAULT_RADIUS"); + qDebug(lcDistanceField) << "set the QT_DISTANCEFIELD_DEFAULT_RADIUS:" << QT_DISTANCEFIELD_DEFAULT_RADIUS; + } + if (qEnvironmentVariableIsSet("QT_DISTANCEFIELD_DEFAULT_HIGHGLYPHCOUNT")) { + QT_DISTANCEFIELD_DEFAULT_HIGHGLYPHCOUNT = qEnvironmentVariableIntValue("QT_DISTANCEFIELD_DEFAULT_HIGHGLYPHCOUNT"); + qCDebug(lcDistanceField) << "set the QT_DISTANCEFIELD_DEFAULT_HIGHGLYPHCOUNT:" << QT_DISTANCEFIELD_DEFAULT_HIGHGLYPHCOUNT; + } +} + bool qt_fontHasNarrowOutlines(QFontEngine *fontEngine) { + initialDistanceFieldFactor(); QFontEngine *fe = fontEngine->cloneWithSize(QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE); if (!fe) return false; @@ -753,6 +792,7 @@ bool qt_fontHasNarrowOutlines(QFontEngine *fontEngine) bool qt_fontHasNarrowOutlines(const QRawFont &f) { QRawFont font = f; + initialDistanceFieldFactor(); font.setPixelSize(QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE); if (!font.isValid()) return false; @@ -765,6 +805,51 @@ bool qt_fontHasNarrowOutlines(const QRawFont &f) QRawFont::PixelAntialiasing)); } +int QT_DISTANCEFIELD_BASEFONTSIZE(bool narrowOutlineFont) +{ + initialDistanceFieldFactor(); + + if (Q_UNLIKELY(narrowOutlineFont)) + return QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE * 2; + else + return QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE; +} + +int QT_DISTANCEFIELD_TILESIZE(bool narrowOutlineFont) +{ + initialDistanceFieldFactor(); + + if (Q_UNLIKELY(narrowOutlineFont)) + return QT_DISTANCEFIELD_DEFAULT_TILESIZE * 2; + else + return QT_DISTANCEFIELD_DEFAULT_TILESIZE; +} + +int QT_DISTANCEFIELD_SCALE(bool narrowOutlineFont) +{ + initialDistanceFieldFactor(); + + if (Q_UNLIKELY(narrowOutlineFont)) + return QT_DISTANCEFIELD_DEFAULT_SCALE / 2; + else + return QT_DISTANCEFIELD_DEFAULT_SCALE; +} + +int QT_DISTANCEFIELD_RADIUS(bool narrowOutlineFont) +{ + initialDistanceFieldFactor(); + + if (Q_UNLIKELY(narrowOutlineFont)) + return QT_DISTANCEFIELD_DEFAULT_RADIUS / 2; + else + return QT_DISTANCEFIELD_DEFAULT_RADIUS; +} + +int QT_DISTANCEFIELD_HIGHGLYPHCOUNT() +{ + initialDistanceFieldFactor(); + return QT_DISTANCEFIELD_DEFAULT_HIGHGLYPHCOUNT; +} QDistanceFieldData::QDistanceFieldData(const QDistanceFieldData &other) : QSharedData(other) diff --git a/src/gui/text/qdistancefield_p.h b/src/gui/text/qdistancefield_p.h index 7cd385587b..3076a90b9d 100644 --- a/src/gui/text/qdistancefield_p.h +++ b/src/gui/text/qdistancefield_p.h @@ -54,31 +54,20 @@ #include <qrawfont.h> #include <private/qfontengine_p.h> #include <QtCore/qshareddata.h> +#include <QtCore/qglobal.h> +#include <QLoggingCategory> QT_BEGIN_NAMESPACE -#define QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE 54 -#define QT_DISTANCEFIELD_DEFAULT_TILESIZE 64 -#define QT_DISTANCEFIELD_DEFAULT_SCALE 16 -#define QT_DISTANCEFIELD_DEFAULT_RADIUS 80 -#define QT_DISTANCEFIELD_HIGHGLYPHCOUNT 2000 - -#define QT_DISTANCEFIELD_BASEFONTSIZE(NarrowOutlineFont) \ - (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE * 2 : \ - QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE) -#define QT_DISTANCEFIELD_TILESIZE(NarrowOutlineFont) \ - (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_TILESIZE * 2 : \ - QT_DISTANCEFIELD_DEFAULT_TILESIZE) -#define QT_DISTANCEFIELD_SCALE(NarrowOutlineFont) \ - (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_SCALE / 2 : \ - QT_DISTANCEFIELD_DEFAULT_SCALE) -#define QT_DISTANCEFIELD_RADIUS(NarrowOutlineFont) \ - (NarrowOutlineFont ? QT_DISTANCEFIELD_DEFAULT_RADIUS / 2 : \ - QT_DISTANCEFIELD_DEFAULT_RADIUS) - bool Q_GUI_EXPORT qt_fontHasNarrowOutlines(const QRawFont &f); bool Q_GUI_EXPORT qt_fontHasNarrowOutlines(QFontEngine *fontEngine); +int Q_GUI_EXPORT QT_DISTANCEFIELD_BASEFONTSIZE(bool narrowOutlineFont); +int Q_GUI_EXPORT QT_DISTANCEFIELD_TILESIZE(bool narrowOutlineFont); +int Q_GUI_EXPORT QT_DISTANCEFIELD_SCALE(bool narrowOutlineFont); +int Q_GUI_EXPORT QT_DISTANCEFIELD_RADIUS(bool narrowOutlineFont); +int Q_GUI_EXPORT QT_DISTANCEFIELD_HIGHGLYPHCOUNT(); + class Q_GUI_EXPORT QDistanceFieldData : public QSharedData { public: diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index f50f771c07..3a08176044 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -3141,7 +3141,7 @@ void QTextHtmlExporter::emitTable(const QTextTable *table) html += QLatin1String("</table>"); } -void QTextHtmlExporter::emitFrame(QTextFrame::Iterator frameIt) +void QTextHtmlExporter::emitFrame(const QTextFrame::Iterator &frameIt) { if (!frameIt.atEnd()) { QTextFrame::Iterator next = frameIt; diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 93071aaf59..df0d52d8e9 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -1077,8 +1077,9 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c) QTextUndoCommand &last = undoStack[undoState - 1]; if ( (last.block_part && c.block_part && !last.block_end) // part of the same block => can merge - || (!c.block_part && !last.block_part)) { // two single undo items => can merge - + || (!c.block_part && !last.block_part) // two single undo items => can merge + || (c.command == QTextUndoCommand::Inserted && last.command == c.command && (last.block_part && !c.block_part))) { + // two sequential inserts that are not part of the same block => can merge if (last.tryMerge(c)) return; } diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h index 34849df0bb..caa63e15d2 100644 --- a/src/gui/text/qtextdocument_p.h +++ b/src/gui/text/qtextdocument_p.h @@ -378,7 +378,7 @@ private: enum StyleMode { EmitStyleTag, OmitStyleTag }; enum FrameType { TextFrame, TableFrame, RootFrame }; - void emitFrame(QTextFrame::Iterator frameIt); + void emitFrame(const QTextFrame::Iterator &frameIt); void emitTextFrame(const QTextFrame *frame); void emitBlock(const QTextBlock &block); void emitTable(const QTextTable *table); diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index c26fd08c41..a8b57d6dfd 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -295,7 +295,7 @@ static inline bool isEmptyBlockBeforeTable(const QTextBlock &block, const QTextB ; } -static inline bool isEmptyBlockBeforeTable(QTextFrame::Iterator it) +static inline bool isEmptyBlockBeforeTable(const QTextFrame::Iterator &it) { QTextFrame::Iterator next = it; ++next; if (it.currentFrame()) @@ -419,7 +419,7 @@ static bool operator<(int pos, const QCheckPoint &checkPoint) #endif -static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, const QPointF &origin, QRectF gradientRect = QRectF()) +static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, const QPointF &origin, const QRectF &gradientRect = QRectF()) { p->save(); if (brush.style() >= Qt::LinearGradientPattern && brush.style() <= Qt::ConicalGradientPattern) { @@ -1504,7 +1504,7 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p painter->restore(); } -static QFixed flowPosition(const QTextFrame::iterator it) +static QFixed flowPosition(const QTextFrame::iterator &it) { if (it.atEnd()) return 0; diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index fa73507c16..8e03797080 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -843,7 +843,7 @@ enum JustificationClass { Adds an inter character justification opportunity after the number or letter character and a space justification opportunity after the space character. */ -static inline void qt_getDefaultJustificationOpportunities(const ushort *string, int length, QGlyphLayout g, ushort *log_clusters, int spaceAs) +static inline void qt_getDefaultJustificationOpportunities(const ushort *string, int length, const QGlyphLayout &g, ushort *log_clusters, int spaceAs) { int str_pos = 0; while (str_pos < length) { @@ -877,7 +877,7 @@ static inline void qt_getDefaultJustificationOpportunities(const ushort *string, } } -static inline void qt_getJustificationOpportunities(const ushort *string, int length, const QScriptItem &si, QGlyphLayout g, ushort *log_clusters) +static inline void qt_getJustificationOpportunities(const ushort *string, int length, const QScriptItem &si, const QGlyphLayout &g, ushort *log_clusters) { Q_ASSERT(length > 0 && g.numGlyphs > 0); @@ -3508,7 +3508,7 @@ QTextItemInt QTextItemInt::midItem(QFontEngine *fontEngine, int firstGlyphIndex, } -QTransform qt_true_matrix(qreal w, qreal h, QTransform x) +QTransform qt_true_matrix(qreal w, qreal h, const QTransform &x) { QRectF rect = x.mapRect(QRectF(0, 0, w, h)); return x * QTransform::fromTranslate(-rect.x(), -rect.y()); diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 128966a35a..83f2a9bc25 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -975,7 +975,7 @@ void QTextLayout::setFlags(int flags) } static void addSelectedRegionsToPath(QTextEngine *eng, int lineNumber, const QPointF &pos, QTextLayout::FormatRange *selection, - QPainterPath *region, QRectF boundingRect) + QPainterPath *region, const QRectF &boundingRect) { const QScriptLine &line = eng->lines[lineNumber]; @@ -1326,7 +1326,11 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition && (p->transform().type() > QTransform::TxTranslate); if (toggleAntialiasing) p->setRenderHint(QPainter::Antialiasing); + QPainter::CompositionMode origCompositionMode = p->compositionMode(); + if (p->paintEngine()->hasFeature(QPaintEngine::RasterOpModes)) + p->setCompositionMode(QPainter::RasterOp_NotDestination); p->fillRect(QRectF(x, y, qreal(width), (base + descent).toReal()), p->pen().brush()); + p->setCompositionMode(origCompositionMode); if (toggleAntialiasing) p->setRenderHint(QPainter::Antialiasing, false); if (d->layoutData->hasBidi) { diff --git a/src/network/access/access.pri b/src/network/access/access.pri index 42c7c80f3b..17897ca869 100644 --- a/src/network/access/access.pri +++ b/src/network/access/access.pri @@ -37,7 +37,8 @@ HEADERS += \ access/qnetworkdiskcache.h \ access/qhttpthreaddelegate_p.h \ access/qhttpmultipart.h \ - access/qhttpmultipart_p.h + access/qhttpmultipart_p.h \ + access/qnetworkfile_p.h SOURCES += \ access/qftp.cpp \ @@ -68,7 +69,8 @@ SOURCES += \ access/qabstractnetworkcache.cpp \ access/qnetworkdiskcache.cpp \ access/qhttpthreaddelegate.cpp \ - access/qhttpmultipart.cpp + access/qhttpmultipart.cpp \ + access/qnetworkfile.cpp mac: LIBS_PRIVATE += -framework Security diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index d2b1a8a912..ed586c1de5 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1523,27 +1523,35 @@ void QNetworkAccessManagerPrivate::clearCache(QNetworkAccessManager *manager) manager->d_func()->objectCache.clear(); manager->d_func()->authenticationManager->clearCache(); - if (manager->d_func()->httpThread) { - manager->d_func()->httpThread->quit(); - manager->d_func()->httpThread->wait(5000); - if (manager->d_func()->httpThread->isFinished()) - delete manager->d_func()->httpThread; - else - QObject::connect(manager->d_func()->httpThread, SIGNAL(finished()), manager->d_func()->httpThread, SLOT(deleteLater())); - manager->d_func()->httpThread = 0; - } + manager->d_func()->destroyThread(); } QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate() { - if (httpThread) { - httpThread->quit(); - httpThread->wait(5000); - if (httpThread->isFinished()) - delete httpThread; + destroyThread(); +} + +QThread * QNetworkAccessManagerPrivate::createThread() +{ + if (!thread) { + thread = new QThread; + thread->setObjectName(QStringLiteral("QNetworkAccessManager thread")); + thread->start(); + } + Q_ASSERT(thread); + return thread; +} + +void QNetworkAccessManagerPrivate::destroyThread() +{ + if (thread) { + thread->quit(); + thread->wait(5000); + if (thread->isFinished()) + delete thread; else - QObject::connect(httpThread, SIGNAL(finished()), httpThread, SLOT(deleteLater())); - httpThread = 0; + QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + thread = 0; } } diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 4efa30df49..9d02fd7c34 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -172,6 +172,7 @@ private: friend class QNetworkReplyImplPrivate; friend class QNetworkReplyHttpImpl; friend class QNetworkReplyHttpImplPrivate; + friend class QNetworkReplyFileImpl; Q_DECLARE_PRIVATE(QNetworkAccessManager) Q_PRIVATE_SLOT(d_func(), void _q_replyFinished()) diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index 413de2a4fe..48270f0c17 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -74,7 +74,7 @@ class QNetworkAccessManagerPrivate: public QObjectPrivate public: QNetworkAccessManagerPrivate() : networkCache(0), cookieJar(0), - httpThread(0), + thread(0), #ifndef QT_NO_NETWORKPROXY proxyFactory(0), #endif @@ -107,6 +107,9 @@ public: } ~QNetworkAccessManagerPrivate(); + QThread * createThread(); + void destroyThread(); + void _q_replyFinished(); void _q_replyEncrypted(); void _q_replySslErrors(const QList<QSslError> &errors); @@ -158,7 +161,7 @@ public: QNetworkCookieJar *cookieJar; - QThread *httpThread; + QThread *thread; #ifndef QT_NO_NETWORKPROXY diff --git a/src/network/access/qnetworkfile.cpp b/src/network/access/qnetworkfile.cpp new file mode 100644 index 0000000000..374dd26e2e --- /dev/null +++ b/src/network/access/qnetworkfile.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnetworkfile_p.h" + +#include <QtCore/QDebug> +#include <QNetworkReply> +#include <QtCore/QDateTime> +#include <QtCore/QFileInfo> +#include <QtCore/QMetaObject> +#include <QtCore/QCoreApplication> + +QT_BEGIN_NAMESPACE + +QNetworkFile::QNetworkFile() + : QFile() +{ +} + +QNetworkFile::QNetworkFile(const QString &name) + : QFile(name) +{ +} + +void QNetworkFile::open() +{ + bool opened = false; + QFileInfo fi(fileName()); + if (fi.isDir()) { + QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", + "Cannot open %1: Path is a directory").arg(fileName()); + error(QNetworkReply::ContentOperationNotPermittedError, msg); + } else { + headerRead(QNetworkRequest::LastModifiedHeader, QVariant::fromValue(fi.lastModified())); + headerRead(QNetworkRequest::ContentLengthHeader, QVariant::fromValue(fi.size())); + opened = QFile::open(QIODevice::ReadOnly | QIODevice::Unbuffered); + if (!opened) { + QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", + "Error opening %1: %2").arg(fileName(), errorString()); + if (exists()) + error(QNetworkReply::ContentAccessDenied, msg); + else + error(QNetworkReply::ContentNotFoundError, msg); + } + } + finished(opened); +} + +void QNetworkFile::close() +{ + // This override is needed because 'using' keyword cannot be used for slots. And the base + // function is not an invokable/slot function. + QFile::close(); +} + +QT_END_NAMESPACE diff --git a/src/network/access/qnetworkfile_p.h b/src/network/access/qnetworkfile_p.h new file mode 100644 index 0000000000..7794c0f18a --- /dev/null +++ b/src/network/access/qnetworkfile_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNETWORKFILE_H +#define QNETWORKFILE_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 <QFile> +#include <qnetworkreply.h> + +QT_BEGIN_NAMESPACE + +class QNetworkFile : public QFile +{ + Q_OBJECT +public: + QNetworkFile(); + QNetworkFile(const QString &name); + using QFile::open; + +public Q_SLOTS: + void open(); + void close() Q_DECL_OVERRIDE; + +Q_SIGNALS: + void finished(bool ok); + void headerRead(QNetworkRequest::KnownHeaders header, const QVariant &value); + void error(QNetworkReply::NetworkError error, const QString &message); +}; + +QT_END_NAMESPACE + +#endif // QNETWORKFILE_H diff --git a/src/network/access/qnetworkreplyfileimpl.cpp b/src/network/access/qnetworkreplyfileimpl.cpp index 36bc4b41df..ef319ebf0d 100644 --- a/src/network/access/qnetworkreplyfileimpl.cpp +++ b/src/network/access/qnetworkreplyfileimpl.cpp @@ -40,31 +40,45 @@ #include "qnetworkreplyfileimpl_p.h" #include "QtCore/qdatetime.h" +#include "qnetworkaccessmanager_p.h" #include <QtCore/QCoreApplication> #include <QtCore/QFileInfo> +#include <QtCore/QThread> +#include "qnetworkfile_p.h" +#include "qnetworkrequest.h" QT_BEGIN_NAMESPACE QNetworkReplyFileImplPrivate::QNetworkReplyFileImplPrivate() - : QNetworkReplyPrivate(), realFileSize(0) + : QNetworkReplyPrivate(), managerPrivate(0), realFile(0) { + qRegisterMetaType<QNetworkRequest::KnownHeaders>(); + qRegisterMetaType<QNetworkReply::NetworkError>(); } QNetworkReplyFileImpl::~QNetworkReplyFileImpl() { + QNetworkReplyFileImplPrivate *d = (QNetworkReplyFileImplPrivate*) d_func(); + if (d->realFile) { + if (d->realFile->thread() == QThread::currentThread()) + delete d->realFile; + else + QMetaObject::invokeMethod(d->realFile, "deleteLater", Qt::QueuedConnection); + } } -QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op) - : QNetworkReply(*new QNetworkReplyFileImplPrivate(), parent) +QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, const QNetworkRequest &req, const QNetworkAccessManager::Operation op) + : QNetworkReply(*new QNetworkReplyFileImplPrivate(), manager) { setRequest(req); setUrl(req.url()); setOperation(op); - setFinished(true); QNetworkReply::open(QIODevice::ReadOnly); QNetworkReplyFileImplPrivate *d = (QNetworkReplyFileImplPrivate*) d_func(); + d->managerPrivate = manager->d_func(); + QUrl url = req.url(); if (url.host() == QLatin1String("localhost")) url.setHost(QString()); @@ -77,7 +91,7 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequ setError(QNetworkReply::ProtocolInvalidOperationError, msg); QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolInvalidOperationError)); - QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + fileOpenFinished(false); return; } #endif @@ -85,7 +99,6 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequ url.setPath(QLatin1String("/")); setUrl(url); - QString fileName = url.toLocalFile(); if (fileName.isEmpty()) { const QString scheme = url.scheme(); @@ -101,68 +114,85 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QObject *parent, const QNetworkRequ } } - QFileInfo fi(fileName); - if (fi.isDir()) { - QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString()); - setError(QNetworkReply::ContentOperationNotPermittedError, msg); - QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, - Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentOperationNotPermittedError)); - QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); - return; - } - - d->realFile.setFileName(fileName); - bool opened = d->realFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered); - - // could we open the file? - if (!opened) { - QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2") - .arg(d->realFile.fileName(), d->realFile.errorString()); - - if (d->realFile.exists()) { - setError(QNetworkReply::ContentAccessDenied, msg); - QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, - Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentAccessDenied)); - } else { - setError(QNetworkReply::ContentNotFoundError, msg); + if (req.attribute(QNetworkRequest::BackgroundRequestAttribute).toBool()) { // Asynchronous open + auto realFile = new QNetworkFile(fileName); + connect(realFile, &QNetworkFile::headerRead, this, &QNetworkReplyFileImpl::setHeader, + Qt::QueuedConnection); + connect(realFile, &QNetworkFile::error, this, &QNetworkReplyFileImpl::setError, + Qt::QueuedConnection); + connect(realFile, SIGNAL(finished(bool)), SLOT(fileOpenFinished(bool)), + Qt::QueuedConnection); + + realFile->moveToThread(d->managerPrivate->createThread()); + QMetaObject::invokeMethod(realFile, "open", Qt::QueuedConnection); + + d->realFile = realFile; + } else { // Synch open + setFinished(true); + + QFileInfo fi(fileName); + if (fi.isDir()) { + QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString()); + setError(QNetworkReply::ContentOperationNotPermittedError, msg); QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, - Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentNotFoundError)); + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentOperationNotPermittedError)); + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + return; + } + d->realFile = new QFile(fileName, this); + bool opened = d->realFile->open(QIODevice::ReadOnly | QIODevice::Unbuffered); + + // could we open the file? + if (!opened) { + QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Error opening %1: %2") + .arg(d->realFile->fileName(), d->realFile->errorString()); + + if (fi.exists()) { + setError(QNetworkReply::ContentAccessDenied, msg); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentAccessDenied)); + } else { + setError(QNetworkReply::ContentNotFoundError, msg); + QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentNotFoundError)); + } + QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); + return; } + setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified()); + setHeader(QNetworkRequest::ContentLengthHeader, fi.size()); + + QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection); + QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection, + Q_ARG(qint64, fi.size()), Q_ARG(qint64, fi.size())); + QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); - return; } - - setHeader(QNetworkRequest::LastModifiedHeader, fi.lastModified()); - d->realFileSize = fi.size(); - setHeader(QNetworkRequest::ContentLengthHeader, d->realFileSize); - - QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection); - QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection, - Q_ARG(qint64, d->realFileSize), Q_ARG(qint64, d->realFileSize)); - QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); - QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); } void QNetworkReplyFileImpl::close() { Q_D(QNetworkReplyFileImpl); QNetworkReply::close(); - d->realFile.close(); + if (d->realFile) { + if (d->realFile->thread() == thread()) + d->realFile->close(); + else + QMetaObject::invokeMethod(d->realFile, "close", Qt::QueuedConnection); + } } void QNetworkReplyFileImpl::abort() { - Q_D(QNetworkReplyFileImpl); - QNetworkReply::close(); - d->realFile.close(); + close(); } qint64 QNetworkReplyFileImpl::bytesAvailable() const { Q_D(const QNetworkReplyFileImpl); - if (!d->realFile.isOpen()) + if (!d->isFinished || !d->realFile || !d->realFile->isOpen()) return QNetworkReply::bytesAvailable(); - return QNetworkReply::bytesAvailable() + d->realFile.bytesAvailable(); + return QNetworkReply::bytesAvailable() + d->realFile->bytesAvailable(); } bool QNetworkReplyFileImpl::isSequential () const @@ -172,8 +202,9 @@ bool QNetworkReplyFileImpl::isSequential () const qint64 QNetworkReplyFileImpl::size() const { - Q_D(const QNetworkReplyFileImpl); - return d->realFileSize; + bool ok; + int size = header(QNetworkRequest::ContentLengthHeader).toInt(&ok); + return ok ? size : 0; } /*! @@ -182,11 +213,11 @@ qint64 QNetworkReplyFileImpl::size() const qint64 QNetworkReplyFileImpl::readData(char *data, qint64 maxlen) { Q_D(QNetworkReplyFileImpl); - if (!d->realFile.isOpen()) + if (!d->isFinished || !d->realFile || !d->realFile->isOpen()) return -1; - qint64 ret = d->realFile.read(data, maxlen); - if (bytesAvailable() == 0 && d->realFile.isOpen()) - d->realFile.close(); + qint64 ret = d->realFile->read(data, maxlen); + if (bytesAvailable() == 0) + d->realFile->close(); if (ret == 0 && bytesAvailable() == 0) return -1; else { @@ -196,6 +227,17 @@ qint64 QNetworkReplyFileImpl::readData(char *data, qint64 maxlen) } } +void QNetworkReplyFileImpl::fileOpenFinished(bool isOpen) +{ + setFinished(true); + if (isOpen) { + const auto fileSize = size(); + Q_EMIT metaDataChanged(); + Q_EMIT downloadProgress(fileSize, fileSize); + Q_EMIT readyRead(); + } + Q_EMIT finished(); +} QT_END_NAMESPACE diff --git a/src/network/access/qnetworkreplyfileimpl_p.h b/src/network/access/qnetworkreplyfileimpl_p.h index bac00881a8..1f1be40bc8 100644 --- a/src/network/access/qnetworkreplyfileimpl_p.h +++ b/src/network/access/qnetworkreplyfileimpl_p.h @@ -59,13 +59,12 @@ QT_BEGIN_NAMESPACE - class QNetworkReplyFileImplPrivate; class QNetworkReplyFileImpl: public QNetworkReply { Q_OBJECT public: - QNetworkReplyFileImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op); + QNetworkReplyFileImpl(QNetworkAccessManager *manager, const QNetworkRequest &req, const QNetworkAccessManager::Operation op); ~QNetworkReplyFileImpl(); virtual void abort() Q_DECL_OVERRIDE; @@ -77,6 +76,9 @@ public: virtual qint64 readData(char *data, qint64 maxlen) Q_DECL_OVERRIDE; +private Q_SLOTS: + void fileOpenFinished(bool isOpen); + Q_DECLARE_PRIVATE(QNetworkReplyFileImpl) }; @@ -85,12 +87,14 @@ class QNetworkReplyFileImplPrivate: public QNetworkReplyPrivate public: QNetworkReplyFileImplPrivate(); - QFile realFile; - qint64 realFileSize; + QNetworkAccessManagerPrivate *managerPrivate; + QPointer<QFile> realFile; Q_DECLARE_PUBLIC(QNetworkReplyFileImpl) }; QT_END_NAMESPACE +Q_DECLARE_METATYPE(QNetworkRequest::KnownHeaders) + #endif // QNETWORKREPLYFILEIMPL_H diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index e1323527f6..6b77ab303f 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -617,17 +617,10 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq thread->setObjectName(QStringLiteral("Qt HTTP synchronous thread")); QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start(); - } else if (!managerPrivate->httpThread) { + } else { // We use the manager-global thread. // At some point we could switch to having multiple threads if it makes sense. - managerPrivate->httpThread = new QThread(); - managerPrivate->httpThread->setObjectName(QStringLiteral("Qt HTTP thread")); - managerPrivate->httpThread->start(); - - thread = managerPrivate->httpThread; - } else { - // Asynchronous request, thread already exists - thread = managerPrivate->httpThread; + thread = managerPrivate->createThread(); } QUrl url = newHttpRequest.url(); @@ -1137,8 +1130,8 @@ void QNetworkReplyHttpImplPrivate::onRedirected(const QUrl &redirectUrl, int htt cookedHeaders.clear(); - if (managerPrivate->httpThread) - managerPrivate->httpThread->disconnect(); + if (managerPrivate->thread) + managerPrivate->thread->disconnect(); // Recurse QMetaObject::invokeMethod(q, "start", Qt::QueuedConnection, diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 802b623375..3ce2d63a39 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -691,6 +691,7 @@ bool QAbstractSocketPrivate::canReadNotification() if (isBuffered) { // Return if there is no space in the buffer if (readBufferMaxSize && buffer.size() >= readBufferMaxSize) { + socketEngine->setReadNotificationEnabled(false); #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canReadNotification() buffer is full"); #endif @@ -708,11 +709,6 @@ bool QAbstractSocketPrivate::canReadNotification() return false; } newBytes = buffer.size() - newBytes; - - // If read buffer is full, disable the read socket notifier. - if (readBufferMaxSize && buffer.size() == readBufferMaxSize) { - socketEngine->setReadNotificationEnabled(false); - } } // Only emit readyRead() if there is data available. @@ -728,10 +724,6 @@ bool QAbstractSocketPrivate::canReadNotification() return true; } - // turn the socket engine off if we've reached the buffer size limit - if (socketEngine && isBuffered) - socketEngine->setReadNotificationEnabled(readBufferMaxSize == 0 || readBufferMaxSize > q->bytesAvailable()); - return true; } @@ -788,12 +780,8 @@ bool QAbstractSocketPrivate::canWriteNotification() #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canWriteNotification() flushing"); #endif - bool dataWasWritten = writeToSocket(); - - if (socketEngine && writeBuffer.isEmpty() && socketEngine->bytesToWrite() == 0) - socketEngine->setWriteNotificationEnabled(false); - return dataWasWritten; + return writeToSocket(); } /*! \internal @@ -833,8 +821,12 @@ bool QAbstractSocketPrivate::writeToSocket() #endif // this covers the case when the buffer was empty, but we had to wait for the socket engine to finish - if (state == QAbstractSocket::ClosingState) + if (state == QAbstractSocket::ClosingState) { q->disconnectFromHost(); + } else { + if (socketEngine) + socketEngine->setWriteNotificationEnabled(false); + } return false; } @@ -872,8 +864,7 @@ bool QAbstractSocketPrivate::writeToSocket() emit q->channelBytesWritten(0, written); } - if (writeBuffer.isEmpty() && socketEngine && socketEngine->isWriteNotificationEnabled() - && !socketEngine->bytesToWrite()) + if (writeBuffer.isEmpty() && socketEngine && !socketEngine->bytesToWrite()) socketEngine->setWriteNotificationEnabled(false); if (state == QAbstractSocket::ClosingState) q->disconnectFromHost(); @@ -2430,15 +2421,7 @@ bool QAbstractSocket::atEnd() const // Note! docs copied to QSslSocket::flush() bool QAbstractSocket::flush() { - Q_D(QAbstractSocket); -#ifndef QT_NO_SSL - // Manual polymorphism; flush() isn't virtual, but QSslSocket overloads - // it. - if (QSslSocket *socket = qobject_cast<QSslSocket *>(this)) - return socket->flush(); -#endif - Q_CHECK_SOCKETENGINE(false); - return d->flush(); + return d_func()->flush(); } /*! \reimp @@ -2461,7 +2444,7 @@ qint64 QAbstractSocket::readData(char *data, qint64 maxSize) d->setError(d->socketEngine->error(), d->socketEngine->errorString()); d->resetSocketLayer(); d->state = QAbstractSocket::UnconnectedState; - } else if (!d->socketEngine->isReadNotificationEnabled()) { + } else { // Only do this when there was no error d->socketEngine->setReadNotificationEnabled(true); } @@ -2828,12 +2811,12 @@ void QAbstractSocket::setReadBufferSize(qint64 size) if (d->readBufferMaxSize == size) return; d->readBufferMaxSize = size; - if (!d->emittedReadyRead && d->socketEngine) { - // ensure that the read notification is enabled if we've now got - // room in the read buffer - // but only if we're not inside canReadNotification -- that will take care on its own - if ((size == 0 || d->buffer.size() < size) && d->state == QAbstractSocket::ConnectedState) // Do not change the notifier unless we are connected. - d->socketEngine->setReadNotificationEnabled(true); + + // Do not change the notifier unless we are connected. + if (d->socketEngine && d->state == QAbstractSocket::ConnectedState) { + // Ensure that the read notification is enabled if we've now got + // room in the read buffer. + d->socketEngine->setReadNotificationEnabled(size == 0 || d->buffer.size() < size); } } diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index b718c21ff5..ab642e039b 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -128,13 +128,12 @@ public: inline void resolveProxy(quint16 port) { resolveProxy(QString(), port); } void resetSocketLayer(); - bool flush(); + virtual bool flush(); bool initSocketLayer(QAbstractSocket::NetworkLayerProtocol protocol); virtual void configureCreatedSocket(); void startConnectingByName(const QString &host); void fetchConnectionParameters(); - void setupSocketNotifiers(); bool readFromSocket(); bool writeToSocket(); void emitReadyRead(); diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp index 7dd884c16a..809b603403 100644 --- a/src/network/socket/qtcpserver.cpp +++ b/src/network/socket/qtcpserver.cpp @@ -543,8 +543,11 @@ QTcpSocket *QTcpServer::nextPendingConnection() if (d->pendingConnections.isEmpty()) return 0; - if (!d->socketEngine->isReadNotificationEnabled()) + if (!d->socketEngine) { + qWarning("QTcpServer::nextPendingConnection() called while not listening"); + } else if (!d->socketEngine->isReadNotificationEnabled()) { d->socketEngine->setReadNotificationEnabled(true); + } return d->pendingConnections.takeFirst(); } diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp index f9bb28e033..1fff2c31dd 100644 --- a/src/network/ssl/qsslconfiguration.cpp +++ b/src/network/ssl/qsslconfiguration.cpp @@ -119,7 +119,8 @@ const char QSslConfiguration::NextProtocolHttp1_1[] = "http/1.1"; /*! \enum QSslConfiguration::NextProtocolNegotiationStatus - Describes the status of the Next Protocol Negotiation (NPN). + Describes the status of the Next Protocol Negotiation (NPN) or + Application-Layer Protocol Negotiation (ALPN). \value NextProtocolNegotiationNone No application protocol has been negotiated (yet). @@ -812,8 +813,9 @@ QVector<QSslEllipticCurve> QSslConfiguration::supportedEllipticCurves() \since 5.3 This function returns the protocol negotiated with the server - if the Next Protocol Negotiation (NPN) TLS extension was enabled. - In order for the NPN extension to be enabled, setAllowedNextProtocols() + if the Next Protocol Negotiation (NPN) or Application-Layer Protocol + Negotiation (ALPN) TLS extension was enabled. + In order for the NPN/ALPN extension to be enabled, setAllowedNextProtocols() needs to be called explicitly before connecting to the server. If no protocol could be negotiated or the extension was not enabled, @@ -830,9 +832,10 @@ QByteArray QSslConfiguration::nextNegotiatedProtocol() const \since 5.3 This function sets the allowed \a protocols to be negotiated with the - server through the Next Protocol Negotiation (NPN) TLS extension; each + server through the Next Protocol Negotiation (NPN) or Application-Layer + Protocol Negotiation (ALPN) TLS extension; each element in \a protocols must define one allowed protocol. - The function must be called explicitly before connecting to send the NPN + The function must be called explicitly before connecting to send the NPN/ALPN extension in the SSL handshake. Whether or not the negotiation succeeded can be queried through nextProtocolNegotiationStatus(). @@ -852,8 +855,8 @@ void QSslConfiguration::setAllowedNextProtocols(QList<QByteArray> protocols) \since 5.3 This function returns the allowed protocols to be negotiated with the - server through the Next Protocol Negotiation (NPN) TLS extension, as set - by setAllowedNextProtocols(). + server through the Next Protocol Negotiation (NPN) or Application-Layer + Protocol Negotiation (ALPN) TLS extension, as set by setAllowedNextProtocols(). \sa nextNegotiatedProtocol(), nextProtocolNegotiationStatus(), setAllowedNextProtocols(), QSslConfiguration::NextProtocolSpdy3_0, QSslConfiguration::NextProtocolHttp1_1 */ @@ -865,7 +868,8 @@ QList<QByteArray> QSslConfiguration::allowedNextProtocols() const /*! \since 5.3 - This function returns the status of the Next Protocol Negotiation (NPN). + This function returns the status of the Next Protocol Negotiation (NPN) + or Application-Layer Protocol Negotiation (ALPN). If the feature has not been enabled through setAllowedNextProtocols(), this function returns NextProtocolNegotiationNone. The status will be set before emitting the encrypted() signal. diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index b3786f989e..543e87c0ca 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -457,7 +457,25 @@ SSL* QSslContext::createSsl() m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data()); m_npnContext.len = m_supportedNPNVersions.count(); m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone; - q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext); +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + if (q_SSLeay() >= 0x10002000L) { + // Callback's type has a parameter 'const unsigned char ** out' + // since it was introduced in 1.0.2. Internally, OpenSSL's own code + // (tests/examples) cast it to unsigned char * (since it's 'out'). + // We just re-use our NPN callback and cast here: + typedef int (*alpn_callback_t) (SSL *, const unsigned char **, unsigned char *, + const unsigned char *, unsigned int, void *); + // With ALPN callback is for a server side only, for a client m_npnContext.status + // will stay in NextProtocolNegotiationNone. + q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext); + // Client: + q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len); + } else { +#else + { +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... + q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext); + } } #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 3e7a30aa9f..bbc62c47ff 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -836,15 +836,7 @@ bool QSslSocket::atEnd() const // Note! docs copied from QAbstractSocket::flush() bool QSslSocket::flush() { - Q_D(QSslSocket); -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << "QSslSocket::flush()"; -#endif - if (d->mode != UnencryptedMode) - // encrypt any unencrypted bytes in our buffer - d->transmit(); - - return d->plainSocket ? d->plainSocket->flush() : false; + return d_func()->flush(); } /*! @@ -2614,6 +2606,22 @@ QByteArray QSslSocketPrivate::peek(qint64 maxSize) /*! \internal */ +bool QSslSocketPrivate::flush() +{ +#ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << "QSslSocketPrivate::flush()"; +#endif + if (mode != QSslSocket::UnencryptedMode) { + // encrypt any unencrypted bytes in our buffer + transmit(); + } + + return plainSocket && plainSocket->flush(); +} + +/*! + \internal +*/ bool QSslSocketPrivate::rootCertOnDemandLoadingSupported() { return s_loadRootCertsOnDemand; diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index c069ff2f9d..1f2ed7687b 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -116,7 +116,7 @@ public: bool canReadLine() const Q_DECL_OVERRIDE; void close() Q_DECL_OVERRIDE; bool atEnd() const Q_DECL_OVERRIDE; - bool flush(); + bool flush(); // ### Qt6: remove me (implementation moved to private flush()) void abort(); // From QAbstractSocket: diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index b86b69cad4..e164e1be61 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1573,7 +1573,20 @@ void QSslSocketBackendPrivate::continueHandshake() } else { const unsigned char *proto = 0; unsigned int proto_len = 0; - q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len); +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + if (q_SSLeay() >= 0x10002000L) { + q_SSL_get0_alpn_selected(ssl, &proto, &proto_len); + if (proto_len && mode == QSslSocket::SslClientMode) { + // Client does not have a callback that sets it ... + configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated; + } + } else { +#else + { +#endif + q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len); + } + if (proto_len) configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len); else diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index d0982377fb..05b7e2da7f 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -418,6 +418,18 @@ DEFINEFUNC3(void, SSL_CTX_set_next_proto_select_cb, SSL_CTX *s, s, void *arg, arg, return, DUMMYARG) DEFINEFUNC3(void, SSL_get0_next_proto_negotiated, const SSL *s, s, const unsigned char **data, data, unsigned *len, len, return, DUMMYARG) +#if OPENSSL_VERSION_NUMBER >= 0x10002000L +DEFINEFUNC3(int, SSL_set_alpn_protos, SSL *s, s, const unsigned char *protos, protos, + unsigned protos_len, protos_len, return -1, return) +DEFINEFUNC3(void, SSL_CTX_set_alpn_select_cb, SSL_CTX *s, s, + int (*cb) (SSL *ssl, const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, void *arg), cb, + void *arg, arg, return, DUMMYARG) +DEFINEFUNC3(void, SSL_get0_alpn_selected, const SSL *s, s, const unsigned char **data, data, + unsigned *len, len, return, DUMMYARG) +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index 36e041b6cb..5a6c934d1a 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -558,6 +558,19 @@ void q_SSL_CTX_set_next_proto_select_cb(SSL_CTX *s, void *arg); void q_SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, unsigned *len); +#if OPENSSL_VERSION_NUMBER >= 0x10002000L +int q_SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, + unsigned protos_len); +void q_SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, + int (*cb) (SSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +void q_SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, + unsigned *len); +#endif #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... // Helper function diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 018da2ffdb..7f8dc375b6 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -193,6 +193,7 @@ public: virtual qint64 peek(char *data, qint64 maxSize) Q_DECL_OVERRIDE; virtual QByteArray peek(qint64 maxSize) Q_DECL_OVERRIDE; + bool flush() Q_DECL_OVERRIDE; // Platform specific functions virtual void startClientEncryption() = 0; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 868e9ed265..6365a7421b 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1006,11 +1006,11 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(const float *data, glStencilMask(0xff); // Enable stencil writes if (dirtyStencilRegion.intersects(currentScissorBounds)) { - QVector<QRect> clearRegion = dirtyStencilRegion.intersected(currentScissorBounds).rects(); + const QRegion clearRegion = dirtyStencilRegion.intersected(currentScissorBounds); glClearStencil(0); // Clear to zero - for (int i = 0; i < clearRegion.size(); ++i) { + for (const QRect &rect : clearRegion) { #ifndef QT_GL_NO_SCISSOR_TEST - setScissor(clearRegion.at(i)); + setScissor(rect); #endif glClear(GL_STENCIL_BUFFER_BIT); } diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp index d631849775..ee8183c896 100644 --- a/src/platformsupport/fbconvenience/qfbscreen.cpp +++ b/src/platformsupport/fbconvenience/qfbscreen.cpp @@ -206,15 +206,13 @@ void QFbScreen::generateRects() remainingScreen -= localGeometry; QRegion windowRegion(localGeometry); windowRegion -= remainingScreen; - foreach (const QRect &rect, windowRegion.rects()) { + for (const QRect &rect : windowRegion) mCachedRects += QPair<QRect, int>(rect, i); - } } #endif } - const QVector<QRect> remainingScreenRects = remainingScreen.rects(); - mCachedRects.reserve(mCachedRects.count() + remainingScreenRects.count()); - foreach (const QRect &rect, remainingScreenRects) + mCachedRects.reserve(mCachedRects.count() + remainingScreen.rectCount()); + for (const QRect &rect : remainingScreen) mCachedRects += QPair<QRect, int>(rect, -1); mIsUpToDate = true; } @@ -253,7 +251,7 @@ QRegion QFbScreen::doRedraw() rectRegion -= intersect; // we only expect one rectangle, but defensive coding... - foreach (const QRect &rect, intersect.rects()) { + for (const QRect &rect : intersect) { bool firstLayer = true; if (layer == -1) { mCompositePainter->fillRect(rect, Qt::black); diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 92430c35bd..400a5ea805 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -215,6 +215,9 @@ void QCoreTextFontEngine::init() } else avgCharWidth = QFontEngine::averageCharWidth(); + underlineThickness = QFixed::fromReal(CTFontGetUnderlineThickness(ctfont)); + underlinePos = -QFixed::fromReal(CTFontGetUnderlinePosition(ctfont)); + cache_cost = (CTFontGetAscent(ctfont) + CTFontGetDescent(ctfont)) * avgCharWidth.toInt() * 2000; // HACK hb_coretext requires both CTFont and CGFont but user_data is only void* @@ -757,6 +760,16 @@ bool QCoreTextFontEngine::supportsTransformation(const QTransform &transform) co return false; } +QFixed QCoreTextFontEngine::lineThickness() const +{ + return underlineThickness; +} + +QFixed QCoreTextFontEngine::underlinePosition() const +{ + return underlinePos; +} + QFontEngine::Properties QCoreTextFontEngine::properties() const { Properties result; diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 6f12f5a705..5681347931 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -92,6 +92,9 @@ public: int synthesized() const Q_DECL_OVERRIDE { return synthesisFlags; } bool supportsSubPixelPositions() const Q_DECL_OVERRIDE { return true; } + QFixed lineThickness() const Q_DECL_OVERRIDE; + QFixed underlinePosition() const Q_DECL_OVERRIDE; + void draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight); FaceId faceId() const Q_DECL_OVERRIDE; @@ -140,6 +143,8 @@ private: int synthesisFlags; CGAffineTransform transform; QFixed avgCharWidth; + QFixed underlineThickness; + QFixed underlinePos; QFontEngine::FaceId face_id; mutable bool kerningPairsLoaded; }; diff --git a/src/platformsupport/graphics/qrasterbackingstore.cpp b/src/platformsupport/graphics/qrasterbackingstore.cpp index 3b1a87b8cd..58e811dff1 100644 --- a/src/platformsupport/graphics/qrasterbackingstore.cpp +++ b/src/platformsupport/graphics/qrasterbackingstore.cpp @@ -89,7 +89,7 @@ bool QRasterBackingStore::scroll(const QRegion ®ion, int dx, int dy) const qreal devicePixelRatio = m_image.devicePixelRatio(); const QPoint delta(dx * devicePixelRatio, dy * devicePixelRatio); - foreach (const QRect &rect, region.rects()) + for (const QRect &rect : region) qt_scrollRectInImage(m_image, QRect(rect.topLeft() * devicePixelRatio, rect.size() * devicePixelRatio), delta); return true; @@ -103,7 +103,7 @@ void QRasterBackingStore::beginPaint(const QRegion ®ion) QPainter painter(&m_image); painter.setCompositionMode(QPainter::CompositionMode_Source); const QColor blank = Qt::transparent; - foreach (const QRect &rect, region.rects()) + for (const QRect &rect : region) painter.fillRect(rect, blank); } diff --git a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp index 7c29be7804..dbaaf524e8 100644 --- a/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp +++ b/src/platformsupport/platformcompositor/qopenglcompositorbackingstore.cpp @@ -140,7 +140,7 @@ void QOpenGLCompositorBackingStore::updateTexture() QOpenGLContext *ctx = QOpenGLContext::currentContext(); if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { - foreach (const QRect &rect, m_dirty.rects()) { + for (const QRect &rect : m_dirty) { QRect r = imageRect & rect; glPixelStorei(GL_UNPACK_ROW_LENGTH, m_image.width()); glTexSubImage2D(GL_TEXTURE_2D, 0, r.x(), r.y(), r.width(), r.height(), GL_RGBA, GL_UNSIGNED_BYTE, @@ -148,7 +148,7 @@ void QOpenGLCompositorBackingStore::updateTexture() glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } } else { - foreach (const QRect &rect, m_dirty.rects()) { + for (const QRect &rect : m_dirty) { // intersect with image rect to be sure QRect r = imageRect & rect; @@ -161,7 +161,7 @@ void QOpenGLCompositorBackingStore::updateTexture() fixed |= r; } - foreach (const QRect &rect, fixed.rects()) { + for (const QRect &rect : fixed) { // if the sub-rect is full-width we can pass the image data directly to // OpenGL instead of copying, since there's no gap between scanlines if (rect.width() == imageRect.width()) { @@ -258,7 +258,7 @@ void QOpenGLCompositorBackingStore::beginPaint(const QRegion ®ion) if (m_image.hasAlphaChannel()) { QPainter p(&m_image); p.setCompositionMode(QPainter::CompositionMode_Source); - foreach (const QRect &r, region.rects()) + for (const QRect &r : region) p.fillRect(r, Qt::transparent); } } diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index 200d5789a8..994fe8386b 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -278,7 +278,7 @@ void QIBusPlatformInputContext::updatePreeditText(const QDBusVariant &text, uint QList<QInputMethodEvent::Attribute> attributes = t.attributes.imAttributes(); if (!t.text.isEmpty()) - attributes += QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursorPos, visible ? 1 : 0, QVariant()); + attributes += QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursorPos, visible ? 1 : 0); QInputMethodEvent event(t.text, attributes); QCoreApplication::sendEvent(input, &event); diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index eb9e95508c..c09dfeda43 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -640,7 +640,7 @@ jboolean QAndroidInputContext::commitText(const QString &text, jint newCursorPos : localPos - text.length() + newCursorPosition; //move the cursor attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, - newLocalPos, 0, QVariant())); + newLocalPos, 0)); } } m_blockUpdateSelection = updateSelectionWasBlocked; @@ -686,7 +686,7 @@ jboolean QAndroidInputContext::finishComposingText() // Moving Qt's cursor to where the preedit cursor used to be QList<QInputMethodEvent::Attribute> attributes; - attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, 0, QVariant())); + attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, 0)); QInputMethodEvent event(QString(), attributes); event.setCommitString(m_composingText); @@ -843,8 +843,7 @@ jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCur QList<QInputMethodEvent::Attribute> attributes; attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, newCursorPosition, - 1, - QVariant())); + 1)); // Show compose text underlined QTextCharFormat underlined; underlined.setFontUnderline(true); @@ -916,7 +915,7 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end) QVariant(underlined))); // Keep the cursor position unchanged (don't move to end of preedit) - attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, currentCursor - start, 1, QVariant())); + attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, currentCursor - start, 1)); QInputMethodEvent event(m_composingText, attributes); event.setCommitString(QString(), relativeStart, length); @@ -950,7 +949,7 @@ jboolean QAndroidInputContext::setSelection(jint start, jint end) // preedit cursor int localOldPos = query->value(Qt::ImCursorPosition).toInt(); int pos = localCursorPos - localOldPos; - attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, pos, 1, QVariant())); + attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, pos, 1)); //but we have to tell Qt about the compose text all over again @@ -965,8 +964,7 @@ jboolean QAndroidInputContext::setSelection(jint start, jint end) // actually changing the selection attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, - end - start, - QVariant())); + end - start)); } QInputMethodEvent event(m_composingText, attributes); sendInputMethodEventThreadSafe(&event); diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index aa4fa94f0a..35a93bb847 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -379,9 +379,8 @@ void QAndroidPlatformScreen::doRedraw() } } - foreach (const QRect &rect, visibleRegion.rects()) { + for (const QRect &rect : visibleRegion) compositePainter.fillRect(rect, QColor(Qt::transparent)); - } ret = ANativeWindow_unlockAndPost(m_nativeSurface); if (ret >= 0) diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index b060d6a082..20233518b3 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -96,9 +96,8 @@ bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy) extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); const qreal devicePixelRatio = m_qImage.devicePixelRatio(); QPoint qpoint(dx * devicePixelRatio, dy * devicePixelRatio); - const QVector<QRect> qrects = area.rects(); - for (int i = 0; i < qrects.count(); ++i) { - const QRect &qrect = QRect(qrects.at(i).topLeft() * devicePixelRatio, qrects.at(i).size() * devicePixelRatio); + for (const QRect &rect : area) { + const QRect qrect(rect.topLeft() * devicePixelRatio, rect.size() * devicePixelRatio); qt_scrollRectInImage(m_qImage, qrect, qpoint); } return true; @@ -109,10 +108,9 @@ void QCocoaBackingStore::beginPaint(const QRegion ®ion) if (m_qImage.hasAlphaChannel()) { QPainter p(&m_qImage); p.setCompositionMode(QPainter::CompositionMode_Source); - const QVector<QRect> rects = region.rects(); const QColor blank = Qt::transparent; - for (QVector<QRect>::const_iterator it = rects.begin(), end = rects.end(); it != end; ++it) - p.fillRect(*it, blank); + for (const QRect &rect : region) + p.fillRect(rect, blank); } } diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 4eb35f5495..0375dd85f2 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -61,6 +61,8 @@ #include <qvarlengtharray.h> #include <stdlib.h> #include <qabstracteventdispatcher.h> +#include <qsysinfo.h> +#include <qglobal.h> #include <QDir> #include <qpa/qplatformnativeinterface.h> @@ -160,6 +162,11 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate); // here to make sure it gets the correct value. [mSavePanel setDelegate:self]; +#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_11) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_11) + mOpenPanel.accessoryViewDisclosed = YES; +#endif + if (mOptions->isLabelExplicitlySet(QFileDialogOptions::Accept)) [mSavePanel setPrompt:[self strip:options->labelText(QFileDialogOptions::Accept)]]; if (mOptions->isLabelExplicitlySet(QFileDialogOptions::FileName)) diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 7480d99d19..c91c67fe79 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -202,15 +202,9 @@ NSImage *qt_mac_create_nsimage(const QIcon &icon) HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion ®ion) { HIMutableShapeRef shape = HIShapeCreateMutable(); - QVector<QRect> rects = region.rects(); - if (!rects.isEmpty()) { - int n = rects.count(); - const QRect *qt_r = rects.constData(); - while (n--) { - CGRect cgRect = CGRectMake(qt_r->x(), qt_r->y(), qt_r->width(), qt_r->height()); - HIShapeUnionWithRect(shape, &cgRect); - ++qt_r; - } + for (const QRect &rect : region) { + CGRect cgRect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); + HIShapeUnionWithRect(shape, &cgRect); } return shape; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 4d2af84e8e..4d5f5d74f2 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -72,6 +72,7 @@ typedef NSWindow<QNSWindowProtocol> QCocoaNSWindow; QCocoaWindow *_platformWindow; BOOL _grabbingMouse; BOOL _releaseOnMouseUp; + QPointer<QObject> _watcher; } @property (nonatomic, readonly) QCocoaNSWindow *window; @@ -321,6 +322,11 @@ public: // for QNSView }; QHash<quintptr, BorderRange> m_contentBorderAreas; // identifer -> uppper/lower QHash<quintptr, bool> m_enabledContentBorderAreas; // identifer -> enabled state (true/false) + + // This object is tracked by a 'watcher' + // object in a window helper, preventing use of dangling + // pointers. + QObject sentinel; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 29cc4130ed..01e72303be 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -99,6 +99,7 @@ static bool isMouseEvent(NSEvent *ev) // make sure that m_nsWindow stays valid until the // QCocoaWindow is deleted by Qt. [_window setReleasedWhenClosed:NO]; + _watcher = &_platformWindow->sentinel; } return self; @@ -107,7 +108,7 @@ static bool isMouseEvent(NSEvent *ev) - (void)handleWindowEvent:(NSEvent *)theEvent { QCocoaWindow *pw = self.platformWindow; - if (pw && pw->m_forwardWindow) { + if (_watcher && pw && pw->m_forwardWindow) { if (theEvent.type == NSLeftMouseUp || theEvent.type == NSLeftMouseDragged) { QNSView *forwardView = pw->m_qtView; if (theEvent.type == NSLeftMouseUp) { @@ -146,7 +147,7 @@ static bool isMouseEvent(NSEvent *ev) if (!self.window.delegate) return; // Already detached, pending NSAppKitDefined event - if (pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) { + if (_watcher && pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) { NSPoint loc = [theEvent locationInWindow]; NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]]; NSRect contentFrame = [[self.window contentView] frame]; @@ -162,6 +163,7 @@ static bool isMouseEvent(NSEvent *ev) - (void)detachFromPlatformWindow { _platformWindow = 0; + _watcher.clear(); [self.window.delegate release]; self.window.delegate = nil; } diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 9905c85d77..bb12c30fa3 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -425,7 +425,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; // set the active window to zero here, the new key window's // NSWindowDidBecomeKeyNotification hander will change the active window NSWindow *keyWindow = [NSApp keyWindow]; - if (!keyWindow) { + if (!keyWindow || keyWindow == windowNotification.object) { // no new key window, go ahead and set the active window to zero if (!m_platformWindow->windowIsPopupType() && !m_isMenuView) QWindowSystemInterface::handleWindowActivated(0); @@ -518,7 +518,7 @@ QT_WARNING_POP m_backingStore = backingStore; m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio(); - foreach (QRect rect, region.rects()) + for (const QRect &rect : region) [self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; } diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index 395c25c915..759c4d26a5 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -88,10 +88,7 @@ static void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransfor if (rgn.isEmpty()) { CGContextAddRect(hd, CGRectMake(0, 0, 0, 0)); } else { - QVector<QRect> rects = rgn.rects(); - const int count = rects.size(); - for (int i = 0; i < count; i++) { - const QRect &r = rects[i]; + for (const QRect &r : rgn) { CGRect mac_r = CGRectMake(r.x(), r.y(), r.width(), r.height()); CGContextAddRect(hd, mac_r); } diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp index 97eadb207b..565d46a424 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp @@ -95,7 +95,7 @@ void QWindowsDirect2DBackingStore::beginPaint(const QRegion ®ion) painter.setCompositionMode(QPainter::CompositionMode_Source); - foreach (const QRect &r, region.rects()) + for (const QRect &r, region) painter.fillRect(r, clear); } @@ -127,9 +127,8 @@ void QWindowsDirect2DBackingStore::resize(const QSize &size, const QRegion ®i QPixmap *newPixmap = nativeWindow(window())->pixmap(); if (!old.isNull()) { - foreach (const QRect &rect, region.rects()) { + for (const QRect &rect : region) platformPixmap(newPixmap)->copy(old.handle(), rect); - } } } diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp index 4e677166b2..c750b02078 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp @@ -122,7 +122,7 @@ void QWindowsDirect2DWindow::flush(QWindowsDirect2DBitmap *bitmap, const QRegion QRegion clipped = region; clipped &= QRect(QPoint(), size); - foreach (const QRect &rect, clipped.rects()) { + for (const QRect &rect : clipped) { QRectF rectF(rect); dc->DrawBitmap(bitmap->bitmap(), to_d2d_rect_f(rectF), diff --git a/src/plugins/platforms/directfb/qdirectfbbackingstore.cpp b/src/plugins/platforms/directfb/qdirectfbbackingstore.cpp index 0bcf93aa3d..9786f66b7c 100644 --- a/src/plugins/platforms/directfb/qdirectfbbackingstore.cpp +++ b/src/plugins/platforms/directfb/qdirectfbbackingstore.cpp @@ -70,9 +70,7 @@ void QDirectFbBackingStore::flush(QWindow *, const QRegion ®ion, const QPoint { m_pmdata->blittable()->unlock(); - QVector<QRect> rects = region.rects(); - for (int i = 0 ; i < rects.size(); i++) { - const QRect rect = rects.at(i); + for (const QRect &rect : region) { DFBRegion dfbReg(rect.x() + offset.x(),rect.y() + offset.y(),rect.right() + offset.x(),rect.bottom() + offset.y()); m_dfbSurface->Flip(m_dfbSurface.data(), &dfbReg, DFBSurfaceFlipFlags(DSFLIP_BLIT|DSFLIP_ONSYNC)); } @@ -108,11 +106,8 @@ bool QDirectFbBackingStore::scroll(const QRegion &area, int dx, int dy) if (area.rectCount() == 1) { scrollSurface(m_dfbSurface.data(), area.boundingRect(), dx, dy); } else { - const QVector<QRect> rects = area.rects(); - const int n = rects.size(); - for (int i=0; i<n; ++i) { - scrollSurface(m_dfbSurface.data(), rects.at(i), dx, dy); - } + for (const QRect &rect : area) + scrollSurface(m_dfbSurface.data(), rect, dx, dy); } return true; } diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm index 8d82364cc0..f49f81912e 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.mm +++ b/src/plugins/platforms/ios/qioseventdispatcher.mm @@ -493,7 +493,7 @@ void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity) Q_UNUSED(activity); Q_ASSERT(activity == kCFRunLoopExit); - if (m_processEventLevel == 1 && !QThreadData::current()->eventLoops.top()->isRunning()) { + if (m_processEventLevel == 1 && !currentEventLoop()->isRunning()) { qEventDispatcherDebug() << "Root runloop level exited"; interruptEventLoopExec(); } diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp index d123bdf82d..025dc22111 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp @@ -414,9 +414,8 @@ QRegion QLinuxFbScreen::doRedraw() if (!mBlitter) mBlitter = new QPainter(&mFbScreenImage); - QVector<QRect> rects = touched.rects(); - for (int i = 0; i < rects.size(); i++) - mBlitter->drawImage(rects[i], *mScreenImage, rects[i]); + for (const QRect &rect : touched) + mBlitter->drawImage(rect, *mScreenImage, rect); return touched; } diff --git a/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp b/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp index daa0b229ec..c4169affdd 100644 --- a/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp +++ b/src/plugins/platforms/mirclient/qmirclientbackingstore.cpp @@ -97,7 +97,7 @@ void QMirClientBackingStore::updateTexture() QRegion fixed; QRect imageRect = mImage.rect(); - Q_FOREACH (const QRect &rect, mDirty.rects()) { + for (const QRect &rect : mDirty) { // intersect with image rect to be sure QRect r = imageRect & rect; @@ -110,7 +110,7 @@ void QMirClientBackingStore::updateTexture() fixed |= r; } - Q_FOREACH (const QRect &rect, fixed.rects()) { + for (const QRect &rect : fixed) { // if the sub-rect is full-width we can pass the image data directly to // OpenGL instead of copying, since there is no gap between scanlines if (rect.width() == imageRect.width()) { diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.cpp b/src/plugins/platforms/offscreen/qoffscreencommon.cpp index ed1a81c2b3..a63aacdbfe 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.cpp +++ b/src/plugins/platforms/offscreen/qoffscreencommon.cpp @@ -179,9 +179,8 @@ bool QOffscreenBackingStore::scroll(const QRegion &area, int dx, int dy) if (m_image.isNull()) return false; - const QVector<QRect> rects = area.rects(); - for (int i = 0; i < rects.size(); ++i) - qt_scrollRectInImage(m_image, rects.at(i), QPoint(dx, dy)); + for (const QRect &rect : area) + qt_scrollRectInImage(m_image, rect, QPoint(dx, dy)); return true; } diff --git a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp index c9a89def41..a758bdf7f4 100644 --- a/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp +++ b/src/plugins/platforms/qnx/qqnxrasterbackingstore.cpp @@ -139,7 +139,7 @@ void QQnxRasterBackingStore::beginPaint(const QRegion ®ion) platformWindow()->adjustBufferSize(); if (window()->requestedFormat().alphaBufferSize() > 0) { - foreach (const QRect &r, region.rects()) { + for (const QRect &r : region) { // Clear transparent regions const int bg[] = { SCREEN_BLIT_COLOR, 0x00000000, diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp index 0fe80d856d..b075690e3d 100644 --- a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp @@ -208,10 +208,9 @@ void QQnxRasterWindow::blitPreviousToCurrent(const QRegion ®ion, int dx, int QQnxBuffer &previousBuffer = m_buffers[m_previousBufferIndex]; // Break down region into non-overlapping rectangles - const QVector<QRect> rects = region.rects(); - for (int i = rects.size() - 1; i >= 0; i--) { + for (auto rit = region.rbegin(), rend = region.rend(); rit != rend; ++rit) { // Clip rectangle to bounds of target - const QRect rect = rects[i].intersected(currentBuffer.rect()); + const QRect rect = rit->intersected(currentBuffer.rect()); if (rect.isEmpty()) continue; diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index 7123ed826d..ea7a5e3c75 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -175,7 +175,7 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion ®ion) staticRegion &= QRect(0, 0, newimg.width(), newimg.height()); QPainter painter(&newimg); painter.setCompositionMode(QPainter::CompositionMode_Source); - foreach (const QRect &rect, staticRegion.rects()) + for (const QRect &rect : staticRegion) painter.drawImage(rect, oldimg, rect); } @@ -190,10 +190,9 @@ bool QWindowsBackingStore::scroll(const QRegion &area, int dx, int dy) if (m_image.isNull() || m_image->image().isNull()) return false; - const QVector<QRect> rects = area.rects(); const QPoint offset(dx, dy); - for (int i = 0; i < rects.size(); ++i) - qt_scrollRectInImage(m_image->image(), rects.at(i), offset); + for (const QRect &rect : area) + qt_scrollRectInImage(m_image->image(), rect, offset); return true; } @@ -207,7 +206,7 @@ void QWindowsBackingStore::beginPaint(const QRegion ®ion) QPainter p(&m_image->image()); p.setCompositionMode(QPainter::CompositionMode_Source); const QColor blank = Qt::transparent; - foreach (const QRect &r, region.rects()) + for (const QRect &r : region) p.fillRect(r, blank); } } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 79f41bb6ec..cb48e13934 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -2047,15 +2047,13 @@ static inline void addRectToWinRegion(const QRect &rect, HRGN *winRegion) static HRGN qRegionToWinRegion(const QRegion ®ion) { - const QVector<QRect> rects = region.rects(); - if (rects.isEmpty()) - return NULL; - const int rectCount = rects.size(); - if (rectCount == 1) - return createRectRegion(region.boundingRect()); - HRGN hRegion = createRectRegion(rects.front()); - for (int i = 1; i < rectCount; ++i) - addRectToWinRegion(rects.at(i), &hRegion); + auto it = region.begin(); + const auto end = region.end(); + if (it == end) + return nullptr; + HRGN hRegion = createRectRegion(*it); + while (++it != end) + addRectToWinRegion(*it, &hRegion); return hRegion; } diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 896eb61970..9ea1f5c33d 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -419,11 +419,9 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion) if (m_image->hasAlpha()) { QPainter p(paintDevice()); p.setCompositionMode(QPainter::CompositionMode_Source); - const QVector<QRect> rects = m_paintRegion.rects(); const QColor blank = Qt::transparent; - for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) { - p.fillRect(*it, blank); - } + for (const QRect &rect : m_paintRegion) + p.fillRect(rect, blank); } } @@ -435,11 +433,12 @@ void QXcbBackingStore::endPaint() // Slow path: the paint device was m_rgbImage. Now copy with swapping red // and blue into m_image. - const QVector<QRect> rects = m_paintRegion.rects(); - if (rects.isEmpty()) + auto it = m_paintRegion.begin(); + const auto end = m_paintRegion.end(); + if (it == end) return; QPainter p(m_image->image()); - for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) { + while (it != end) { const QRect rect = *it; p.drawImage(rect.topLeft(), m_rgbImage.copy(rect).rgbSwapped()); } @@ -543,9 +542,8 @@ bool QXcbBackingStore::scroll(const QRegion &area, int dx, int dy) m_image->preparePaint(area); QPoint delta(dx, dy); - const QVector<QRect> rects = area.rects(); - for (int i = 0; i < rects.size(); ++i) - qt_scrollRectInImage(*m_image->image(), rects.at(i), delta); + for (const QRect &rect : area) + qt_scrollRectInImage(*m_image->image(), rect, delta); return true; } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 13eecbfb4f..a426e04721 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2786,9 +2786,8 @@ void QXcbWindow::setMask(const QRegion ®ion) XCB_SHAPE_SK_BOUNDING, xcb_window(), 0, 0, XCB_NONE); } else { QVector<xcb_rectangle_t> rects; - const QVector<QRect> regionRects = region.rects(); - rects.reserve(regionRects.count()); - foreach (const QRect &r, regionRects) + rects.reserve(region.rectCount()); + for (const QRect &r : region) rects.push_back(qRectToXCBRectangle(r)); xcb_shape_rectangles(connection()->xcb_connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, diff --git a/src/src.pro b/src/src.pro index 167133859b..999fc2ce90 100644 --- a/src/src.pro +++ b/src/src.pro @@ -129,7 +129,7 @@ src_plugins.depends = src_sql src_xml src_network src_android.subdir = $$PWD/android # this order is important -contains(QT_CONFIG, zlib)|cross_compile: SUBDIRS += src_qtzlib +!contains(QT_CONFIG, system-zlib)|cross_compile: SUBDIRS += src_qtzlib SUBDIRS += src_tools_bootstrap src_tools_moc src_tools_rcc !contains(QT_DISABLED_FEATURES, regularexpression):pcre { SUBDIRS += src_3rdparty_pcre diff --git a/src/testlib/qbenchmarkmetric.cpp b/src/testlib/qbenchmarkmetric.cpp index 0a9072907f..0ba55dbeb7 100644 --- a/src/testlib/qbenchmarkmetric.cpp +++ b/src/testlib/qbenchmarkmetric.cpp @@ -56,6 +56,7 @@ \value CPUTicks CPU time \value CPUMigrations Process migrations between CPUs \value CPUCycles CPU cycles + \value RefCPUCycles Reference CPU cycles \value BusCycles Bus cycles \value StalledCycles Cycles stalled \value InstructionReads Instruction reads @@ -108,6 +109,8 @@ const char * QTest::benchmarkMetricName(QBenchmarkMetric metric) return "CPUMigrations"; case CPUCycles: return "CPUCycles"; + case RefCPUCycles: + return "RefCPUCycles"; case BusCycles: return "BusCycles"; case StalledCycles: @@ -180,6 +183,8 @@ const char * QTest::benchmarkMetricUnit(QBenchmarkMetric metric) return "CPU migrations"; case CPUCycles: return "CPU cycles"; + case RefCPUCycles: + return "Reference CPU cycles"; case BusCycles: return "bus cycles"; case StalledCycles: diff --git a/src/testlib/qbenchmarkmetric.h b/src/testlib/qbenchmarkmetric.h index 44bf14b9b6..6e423473b1 100644 --- a/src/testlib/qbenchmarkmetric.h +++ b/src/testlib/qbenchmarkmetric.h @@ -78,7 +78,8 @@ enum QBenchmarkMetric { MinorPageFaults, MajorPageFaults, AlignmentFaults, - EmulationFaults + EmulationFaults, + RefCPUCycles, }; } diff --git a/src/testlib/qbenchmarkperfevents.cpp b/src/testlib/qbenchmarkperfevents.cpp index 587d3e0124..d6db40ce52 100644 --- a/src/testlib/qbenchmarkperfevents.cpp +++ b/src/testlib/qbenchmarkperfevents.cpp @@ -153,6 +153,7 @@ bool QBenchmarkPerfEventsMeasurer::isAvailable() Event type Event counter Unit Name and aliases HARDWARE CPU_CYCLES CPUCycles cycles cpu-cycles + HARDWARE REF_CPU_CYCLES RefCPUCycles ref-cycles HARDWARE INSTRUCTIONS Instructions instructions HARDWARE CACHE_REFERENCES CacheReferences cache-references HARDWARE CACHE_MISSES CacheMisses cache-misses @@ -321,6 +322,7 @@ static const char eventlist_strings[] = "migrations\0" "minor-faults\0" "page-faults\0" + "ref-cycles\0" "stalled-cycles-backend\0" "stalled-cycles-frontend\0" "task-clock\0" @@ -407,9 +409,10 @@ static const Events eventlist[] = { { 1256, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS, QTest::CPUMigrations }, { 1267, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN, QTest::MinorPageFaults }, { 1280, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS, QTest::PageFaults }, - { 1292, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND, QTest::StalledCycles }, - { 1315, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND, QTest::StalledCycles }, - { 1339, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK, QTest::WalltimeMilliseconds }, + { 1292, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES, QTest::RefCPUCycles }, + { 1303, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND, QTest::StalledCycles }, + { 1326, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND, QTest::StalledCycles }, + { 1350, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK, QTest::WalltimeMilliseconds }, { 0, PERF_TYPE_MAX, 0, QTest::Events } }; /* -- END GENERATED CODE -- */ diff --git a/src/testlib/qxunittestlogger.cpp b/src/testlib/qxunittestlogger.cpp index 72faaeb9b1..ec33c29ae5 100644 --- a/src/testlib/qxunittestlogger.cpp +++ b/src/testlib/qxunittestlogger.cpp @@ -256,7 +256,7 @@ void QXunitTestLogger::addBenchmarkResult(const QBenchmarkResult &result) benchmarkElement->addAttribute( QTest::AI_Metric, - QTest::benchmarkMetricName(QBenchmarkTestMethodData::current->result.metric)); + QTest::benchmarkMetricName(result.metric)); benchmarkElement->addAttribute(QTest::AI_Tag, result.context.tag.toUtf8().data()); const qreal valuePerIteration = qreal(result.value) / qreal(result.iterations); diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 3cfdbf3429..47aa886568 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -133,7 +133,7 @@ macx { ../../corelib/io/qstandardpaths_win.cpp } -if(contains(QT_CONFIG, zlib)|cross_compile):include(../../3rdparty/zlib.pri) +!contains(QT_CONFIG, system-zlib)|cross_compile:include(../../3rdparty/zlib.pri) else:include(../../3rdparty/zlib_dependency.pri) win32:LIBS += -luser32 -lole32 -ladvapi32 -lshell32 diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index 026d099dc0..8c8141f9e5 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -770,22 +770,22 @@ void WriteInitialization::acceptWidget(DomWidget *node) // // Special handling for qtableview/qtreeview fake header attributes // - static QStringList realPropertyNames = - (QStringList() << QLatin1String("visible") - << QLatin1String("cascadingSectionResizes") - << QLatin1String("defaultSectionSize") - << QLatin1String("highlightSections") - << QLatin1String("minimumSectionSize") - << QLatin1String("showSortIndicator") - << QLatin1String("stretchLastSection")); + static const QLatin1String realPropertyNames[] = { + QLatin1String("visible"), + QLatin1String("cascadingSectionResizes"), + QLatin1String("defaultSectionSize"), + QLatin1String("highlightSections"), + QLatin1String("minimumSectionSize"), + QLatin1String("showSortIndicator"), + QLatin1String("stretchLastSection"), + }; if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTreeView")) || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTreeWidget"))) { DomPropertyList headerProperties; - foreach (const QString &realPropertyName, realPropertyNames) { - const QString upperPropertyName = realPropertyName.at(0).toUpper() - + realPropertyName.mid(1); - const QString fakePropertyName = QLatin1String("header") + upperPropertyName; + for (auto realPropertyName : realPropertyNames) { + const QString fakePropertyName = QLatin1String("header") + + QChar(realPropertyName.at(0)).toUpper() + realPropertyName.mid(1); if (DomProperty *fakeProperty = attributes.value(fakePropertyName)) { fakeProperty->setAttributeName(realPropertyName); headerProperties << fakeProperty; @@ -797,16 +797,16 @@ void WriteInitialization::acceptWidget(DomWidget *node) } else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableView")) || m_uic->customWidgetsInfo()->extends(className, QLatin1String("QTableWidget"))) { - static QStringList headerPrefixes = - (QStringList() << QLatin1String("horizontalHeader") - << QLatin1String("verticalHeader")); + static const QLatin1String headerPrefixes[] = { + QLatin1String("horizontalHeader"), + QLatin1String("verticalHeader"), + }; - foreach (const QString &headerPrefix, headerPrefixes) { + for (auto headerPrefix : headerPrefixes) { DomPropertyList headerProperties; - foreach (const QString &realPropertyName, realPropertyNames) { - const QString upperPropertyName = realPropertyName.at(0).toUpper() - + realPropertyName.mid(1); - const QString fakePropertyName = headerPrefix + upperPropertyName; + for (auto realPropertyName : realPropertyNames) { + const QString fakePropertyName = headerPrefix + + QChar(realPropertyName.at(0)).toUpper() + realPropertyName.mid(1); if (DomProperty *fakeProperty = attributes.value(fakePropertyName)) { fakeProperty->setAttributeName(realPropertyName); headerProperties << fakeProperty; diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index 98f1f4870d..ad13deb044 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -92,7 +92,7 @@ public: SetColorAll = ShowColor | SelectColor }; - QColorDialogPrivate() : options(new QColorDialogOptions) + QColorDialogPrivate() : options(QColorDialogOptions::create()) #ifdef Q_OS_WIN32 , updateTimer(0) #endif diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index c4ed72edc3..defc0539c9 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -533,7 +533,7 @@ QFileDialogPrivate::QFileDialogPrivate() showHiddenAction(0), useDefaultCaption(true), qFileDialogUi(0), - options(new QFileDialogOptions) + options(QFileDialogOptions::create()) { } diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp index a0525f6fbd..c130998198 100644 --- a/src/widgets/dialogs/qfontdialog.cpp +++ b/src/widgets/dialogs/qfontdialog.cpp @@ -110,7 +110,7 @@ static const Qt::WindowFlags DefaultWindowFlags = QFontDialogPrivate::QFontDialogPrivate() : writingSystem(QFontDatabase::Any), - options(QSharedPointer<QFontDialogOptions>::create()) + options(QFontDialogOptions::create()) { } diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index 207b6e3919..ee760c38a0 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -200,7 +200,7 @@ public: #endif compatMode(false), autoAddOkButton(true), detectedEscapeButton(0), informativeLabel(0), - options(new QMessageDialogOptions) { } + options(QMessageDialogOptions::create()) { } void init(const QString &title = QString(), const QString &text = QString()); void setupLayout(); diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index db683a4e4d..b00a950823 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -1439,9 +1439,8 @@ void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, con // Determine the item's exposed area option->exposedRect = QRectF(); const QTransform reverseMap = worldTransform.inverted(); - const QVector<QRect> exposedRects(exposedRegion.rects()); - for (int i = 0; i < exposedRects.size(); ++i) { - option->exposedRect |= reverseMap.mapRect(QRectF(exposedRects.at(i))); + for (const QRect &exposedRect : exposedRegion) { + option->exposedRect |= reverseMap.mapRect(QRectF(exposedRect)); if (option->exposedRect.contains(brect)) break; } @@ -5350,8 +5349,7 @@ QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) c QTransform unscale = QTransform::fromScale(1 / granularity, 1 / granularity); QRegion r; QBitmap colorMask = QBitmap::fromImage(mask.createMaskFromColor(0)); - const auto rects = QRegion(colorMask).rects(); - for (const QRect &rect : rects) { + for (const QRect &rect : QRegion(colorMask)) { QRect xrect = unscale.mapRect(rect).translated(deviceRect.topLeft() - QPoint(pad, pad)); r += xrect.adjusted(-1, -1, 1, 1) & deviceRect; } @@ -5915,9 +5913,8 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) // Append newly exposed areas. Note that the exposed region is currently // in pixmap coordinates, so we have to translate it to item coordinates. exposed.translate(cache->boundingRect.topLeft()); - const QVector<QRect> exposedRects = exposed.rects(); - for (int i = 0; i < exposedRects.size(); ++i) - cache->exposed += exposedRects.at(i); + for (const QRect &exposedRect : exposed) + cache->exposed += exposedRect; // Trigger update. This will redraw the newly exposed area and make sure // the pixmap is re-blitted in case there are overlapping items. diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index cb1d1e68d1..7b67f332e1 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -4657,8 +4657,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte for (int i = 0; i < exposed.size(); ++i) br |= exposed.at(i); QTransform pixmapToItem = itemToPixmap.inverted(); - const auto rects = scrollExposure.rects(); - for (const QRect &r : rects) + for (const QRect &r : scrollExposure) br |= pixmapToItem.mapRect(r); } styleOptionTmp = *option; diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp index 450d5a7d9c..84fff31b99 100644 --- a/src/widgets/graphicsview/qgraphicsview.cpp +++ b/src/widgets/graphicsview/qgraphicsview.cpp @@ -1029,9 +1029,7 @@ bool QGraphicsViewPrivate::updateRegion(const QRectF &rect, const QTransform &xf if (!intersectsViewport(viewRect, viewport->width(), viewport->height())) return false; // Update region for sure outside viewport. - const QVector<QRect> &rects = region.rects(); - for (int i = 0; i < rects.size(); ++i) { - viewRect = rects.at(i); + for (QRect viewRect : region) { if (dontAdjustForAntialiasing) viewRect.adjust(-1, -1, 1, 1); else @@ -1146,8 +1144,7 @@ QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedReg // the expose region, convert it to a path, and then search for items // using QGraphicsScene::items(QPainterPath); QRegion adjustedRegion; - const auto rects = exposedRegion.rects(); - for (const QRect &r : rects) + for (const QRect &r : exposedRegion) adjustedRegion += r.adjusted(-1, -1, 1, 1); const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion))); @@ -2676,11 +2673,9 @@ void QGraphicsView::updateScene(const QList<QRectF> &rects) // Extract and reset dirty scene rect info. QVector<QRect> dirtyViewportRects; - const QVector<QRect> &dirtyRects = d->dirtyRegion.rects(); - const int dirtyRectsCount = dirtyRects.size(); - dirtyViewportRects.reserve(dirtyRectsCount + rects.count()); - for (int i = 0; i < dirtyRectsCount; ++i) - dirtyViewportRects += dirtyRects.at(i); + dirtyViewportRects.reserve(d->dirtyRegion.rectCount() + rects.count()); + for (const QRect &dirtyRect : d->dirtyRegion) + dirtyViewportRects += dirtyRect; d->dirtyRegion = QRegion(); d->dirtyBoundingRect = QRect(); diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index e045d60fc8..ff3832e499 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -1398,8 +1398,7 @@ void QTableView::paintEvent(QPaintEvent *event) firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn); } - const QVector<QRect> rects = region.rects(); - for (auto dirtyArea : rects) { + for (QRect dirtyArea : region) { dirtyArea.setBottom(qMin(dirtyArea.bottom(), int(y))); if (rightToLeft) { dirtyArea.setLeft(qMax(dirtyArea.left(), d->viewport->width() - int(x))); diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 95f14bec78..3568d937ff 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -1473,13 +1473,12 @@ void QTreeView::drawTree(QPainter *painter, const QRegion ®ion) const QPoint hoverPos = d->viewport->mapFromGlobal(QCursor::pos()); d->hoverBranch = d->itemDecorationAt(hoverPos); - QVector<QRect> rects = region.rects(); QVector<int> drawn; - bool multipleRects = (rects.size() > 1); - for (int a = 0; a < rects.size(); ++a) { + bool multipleRects = (region.rectCount() > 1); + for (const QRect &a : region) { const QRect area = (multipleRects - ? QRect(0, rects.at(a).y(), viewportWidth, rects.at(a).height()) - : rects.at(a)); + ? QRect(0, a.y(), viewportWidth, a.height()) + : a); d->leftAndRight = d->startAndEndColumns(area); int i = firstVisibleItem; // the first item at the top of the viewport diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 027bf63a2e..598991bd98 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -2397,9 +2397,8 @@ static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrus painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush); painter->restore(); } else { - const QVector<QRect> &rects = rgn.rects(); - for (int i = 0; i < rects.size(); ++i) - painter->fillRect(rects.at(i), brush); + for (const QRect &rect : rgn) + painter->fillRect(rect, brush); } } @@ -10747,10 +10746,8 @@ void QWidget::scroll(int dx, int dy) // Graphics View maintains its own dirty region as a list of rects; // until we can connect item updates directly to the view, we must // separately add a translated dirty region. - if (!d->dirty.isEmpty()) { - foreach (const QRect &rect, (d->dirty.translated(dx, dy)).rects()) - proxy->update(rect); - } + for (const QRect &rect : d->dirty) + proxy->update(rect.translated(dx, dy)); proxy->scroll(dx, dy, proxy->subWidgetRect(this)); return; } @@ -10790,7 +10787,7 @@ void QWidget::scroll(int dx, int dy, const QRect &r) // until we can connect item updates directly to the view, we must // separately add a translated dirty region. if (!d->dirty.isEmpty()) { - foreach (const QRect &rect, (d->dirty.translated(dx, dy) & r).rects()) + for (const QRect &rect : d->dirty.translated(dx, dy) & r) proxy->update(rect); } proxy->scroll(dx, dy, r.translated(proxy->subWidgetRect(this).topLeft().toPoint())); diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 9025160e5c..7a4a6d862d 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -158,7 +158,7 @@ static void showYellowThing_win(QWidget *widget, const QRegion ®ion, int msec } i = (i + 1) & 3; - foreach (const QRect &rect, region.rects()) { + for (const QRect &rect : region) { RECT winRect; SetRect(&winRect, rect.left(), rect.top(), rect.right(), rect.bottom()); FillRect(hdc, &winRect, brush); @@ -1311,9 +1311,8 @@ void QWidgetBackingStore::doSync() updateStaticContentsSize(); dirty = QRegion(); updateRequestSent = false; - const QVector<QRect> rects(toClean.rects()); - for (int i = 0; i < rects.size(); ++i) - tlw->d_func()->extra->proxyWidget->update(rects.at(i)); + for (const QRect &rect : toClean) + tlw->d_func()->extra->proxyWidget->update(rect); return; } #endif diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index d29ff93382..3d03ed5323 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -587,7 +587,7 @@ HIMutableShapeRef qt_mac_toHIMutableShape(const QRegion ®ion) CGRect cgRect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height()); HIShapeUnionWithRect(shape, &cgRect); } else { - foreach (const QRect &qtRect, region.rects()) { + for (const QRect &qtRect : region) { CGRect cgRect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height()); HIShapeUnionWithRect(shape, &cgRect); } @@ -2253,9 +2253,7 @@ void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush CGContextSaveGState(cg); HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationInverted); - const QVector<QRect> &rects = rgn.rects(); - for (int i = 0; i < rects.size(); ++i) { - const QRect rect(rects.at(i)); + for (const QRect &rect : rgn) { // Anchor the pattern to the top so it stays put when the window is resized. CGContextSetPatternPhase(cg, CGSizeMake(rect.width(), rect.height())); CGRect mac_rect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); @@ -7114,11 +7112,11 @@ void qt_mac_scale_region(QRegion *region, qreal scaleFactor) return; QVector<QRect> scaledRects; - scaledRects.reserve(region->rects().count()); + scaledRects.reserve(region->rectCount()); - foreach (const QRect &rect, region->rects()) { + for (const QRect &rect : *region) scaledRects.append(QRect(rect.topLeft() * scaleFactor, rect.size() * scaleFactor)); - } + region->setRects(&scaledRects[0], scaledRects.count()); } diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index c33e4167c1..c3072303de 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -269,7 +269,7 @@ static HRGN qt_hrgn_from_qregion(const QRegion ®ion) qt_add_rect(hRegion, region.boundingRect()); return hRegion; } - foreach (const QRect &rect, region.rects()) + for (const QRect &rect : region) qt_add_rect(hRegion, rect); return hRegion; } @@ -1087,11 +1087,8 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa painter->setClipRegion(newRegion); #if defined(DEBUG_XP_STYLE) && 0 printf("Using region:\n"); - QVector<QRect> rects = newRegion.rects(); - for (int i = 0; i < rects.count(); ++i) { - const QRect &r = rects.at(i); + for (const QRect &r : newRegion) printf(" (%d, %d, %d, %d)\n", r.x(), r.y(), r.right(), r.bottom()); - } #endif } diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 3cdd7dc0f0..e93ed11930 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -1899,13 +1899,19 @@ void QLineEdit::paintEvent(QPaintEvent *) if (d->shouldShowPlaceholderText()) { if (!d->placeholderText.isEmpty()) { + const Qt::LayoutDirection layoutDir = d->placeholderText.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; + const Qt::Alignment alignPhText = QStyle::visualAlignment(layoutDir, QFlag(d->alignment)); QColor col = pal.text().color(); col.setAlpha(128); QPen oldpen = p.pen(); p.setPen(col); - QString elidedText = fm.elidedText(d->placeholderText, Qt::ElideRight, lineRect.width()); - p.drawText(lineRect, va, elidedText); + Qt::LayoutDirection oldLayoutDir = p.layoutDirection(); + p.setLayoutDirection(layoutDir); + + const QString elidedText = fm.elidedText(d->placeholderText, Qt::ElideRight, lineRect.width()); + p.drawText(lineRect, alignPhText, elidedText); p.setPen(oldpen); + p.setLayoutDirection(oldLayoutDir); } } diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp index b42ebe7e48..5f3aff5e10 100644 --- a/src/widgets/widgets/qmdiarea.cpp +++ b/src/widgets/widgets/qmdiarea.cpp @@ -2670,9 +2670,8 @@ void QMdiArea::paintEvent(QPaintEvent *paintEvent) { Q_D(QMdiArea); QPainter painter(d->viewport); - const QVector<QRect> &exposedRects = paintEvent->region().rects(); - for (int i = 0; i < exposedRects.size(); ++i) - painter.fillRect(exposedRects.at(i), d->background); + for (const QRect &exposedRect : paintEvent->region()) + painter.fillRect(exposedRect, d->background); } /*! diff --git a/src/winmain/qtmain_win.cpp b/src/winmain/qtmain_win.cpp index 2944e07e00..e357814d0a 100644 --- a/src/winmain/qtmain_win.cpp +++ b/src/winmain/qtmain_win.cpp @@ -43,9 +43,7 @@ #include "qstring.h" #include "qvector.h" -#ifndef Q_OS_WINCE -# include <shlobj.h> -#endif +#include <shlobj.h> /* This file contains the code in the qtmain library for Windows. @@ -59,11 +57,7 @@ QT_BEGIN_NAMESPACE -#if defined(Q_OS_WINCE) -extern void __cdecl qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector<char *> &); -#else extern void qWinMain(HINSTANCE, HINSTANCE, LPSTR, int, int &, QVector<char *> &); -#endif QT_END_NAMESPACE @@ -74,12 +68,8 @@ QT_USE_NAMESPACE int qMain(int, char **); #define main qMain #else -#ifdef Q_OS_WINCE -extern "C" int __cdecl main(int, char **); -#else extern "C" int main(int, char **); #endif -#endif /* WinMain() - Initializes Windows and calls user's startup function main(). @@ -87,8 +77,6 @@ extern "C" int main(int, char **); application. */ -#ifndef Q_OS_WINCE - // Convert a wchar_t to char string, equivalent to QString::toLocal8Bit() // when passed CP_ACP. static inline char *wideToMulti(int codePage, const wchar_t *aw) @@ -116,48 +104,3 @@ extern "C" int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR /*cmdParamarg*/, int delete [] argv; return exitCode; } - -#else // !Q_OS_WINCE - -int WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR /*wCmdParam*/, int cmdShow) -{ - QByteArray cmdParam = QString::fromWCharArray(GetCommandLine()).toLocal8Bit(); - - wchar_t appName[MAX_PATH]; - GetModuleFileName(0, appName, MAX_PATH); - cmdParam.prepend(QString(QLatin1String("\"%1\" ")).arg(QString::fromWCharArray(appName)).toLocal8Bit()); - - int argc = 0; - QVector<char *> argv(8); - qWinMain(instance, prevInstance, cmdParam.data(), cmdShow, argc, argv); - - wchar_t uniqueAppID[MAX_PATH]; - GetModuleFileName(0, uniqueAppID, MAX_PATH); - QString uid = QString::fromWCharArray(uniqueAppID).toLower().replace(QLatin1String("\\"), QLatin1String("_")); - - // If there exists an other instance of this application - // it will be the owner of a mutex with the unique ID. - HANDLE mutex = CreateMutex(NULL, TRUE, (LPCWSTR)uid.utf16()); - if (mutex && ERROR_ALREADY_EXISTS == GetLastError()) { - CloseHandle(mutex); - - // The app is already running, so we use the unique - // ID to create a unique messageNo, which is used - // as the registered class name for the windows - // created. Set the first instance's window to the - // foreground, else just terminate. - // Use bitwise 0x01 OR to reactivate window state if - // it was hidden - UINT msgNo = RegisterWindowMessage((LPCWSTR)uid.utf16()); - HWND aHwnd = FindWindow((LPCWSTR)QString::number(msgNo).utf16(), 0); - if (aHwnd) - SetForegroundWindow((HWND)(((ULONG)aHwnd) | 0x01)); - return 0; - } - - int result = main(argc, argv.data()); - CloseHandle(mutex); - return result; -} - -#endif // Q_OS_WINCE diff --git a/src/winmain/winmain.pro b/src/winmain/winmain.pro index e8c9ace03b..828ef6cf5a 100644 --- a/src/winmain/winmain.pro +++ b/src/winmain/winmain.pro @@ -21,7 +21,7 @@ winrt { } else { SOURCES = qtmain_win.cpp - !wince: LIBS += -lshell32 + LIBS += -lshell32 } load(qt_installs) @@ -31,5 +31,3 @@ TARGET = $$qtLibraryTarget($$TARGET$$QT_LIBINFIX) #do this towards the end load(qt_targets) load(qt_build_paths) load(qt_common) - -wince: QMAKE_POST_LINK = |