From 2e1763d83a1dacfc5b747934fb77fa7cec7bfe47 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 3 Mar 2016 20:20:42 +0100 Subject: [PATCH 001/122] Non-associative containers: add range constructors Something nice we'd like to detect for array-backed containers is if the iterator passed is a Contiguous one; if the type is also trivially copyable / Q_PRIMITIVE_TYPE, we could memcpy() the whole range. However, there's no trait in the Standard to detect contiguous iterators (the best approximation would be detecting if the iterator is actually a pointer). Also, it's probably not smart to do the work now for QVector since QVector needs refactoring anyhow, and this work will be lost. QString and QByteArray are left in another commit. [ChangeLog][QtCore][QVector] Added range constructor. [ChangeLog][QtCore][QVarLengthArray] Added range constructor. [ChangeLog][QtCore][QList] Added range constructor. [ChangeLog][QtCore][QStringList] Added range constructor. [ChangeLog][QtCore][QLinkedList] Added range constructor. [ChangeLog][QtCore][QSet] Added range constructor. Change-Id: I220edb796053c9c4d31a6dbdc7efc5fc0f6678f9 Reviewed-by: Milian Wolff --- src/corelib/tools/qcontainertools_impl.h | 93 +++ src/corelib/tools/qlinkedlist.cpp | 8 + src/corelib/tools/qlinkedlist.h | 12 +- src/corelib/tools/qlist.cpp | 8 + src/corelib/tools/qlist.h | 16 +- src/corelib/tools/qset.h | 16 +- src/corelib/tools/qset.qdoc | 11 + src/corelib/tools/qstringlist.cpp | 7 + src/corelib/tools/qstringlist.h | 4 + src/corelib/tools/qvarlengtharray.h | 13 +- src/corelib/tools/qvarlengtharray.qdoc | 8 + src/corelib/tools/qvector.h | 13 + src/corelib/tools/qvector.qdoc | 7 + src/corelib/tools/tools.pri | 1 + .../tst_containerapisymmetry.cpp | 593 ++++++++++++++++++ .../tools/qstringlist/tst_qstringlist.cpp | 37 ++ 16 files changed, 833 insertions(+), 14 deletions(-) create mode 100644 src/corelib/tools/qcontainertools_impl.h diff --git a/src/corelib/tools/qcontainertools_impl.h b/src/corelib/tools/qcontainertools_impl.h new file mode 100644 index 0000000000..c2de50b145 --- /dev/null +++ b/src/corelib/tools/qcontainertools_impl.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz +** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if 0 +#pragma qt_sync_skip_header_check +#pragma qt_sync_stop_processing +#endif + +#ifndef QCONTAINERTOOLS_IMPL_H +#define QCONTAINERTOOLS_IMPL_H + +#include +#include + +#ifndef Q_QDOC + +QT_BEGIN_NAMESPACE + +namespace QtPrivate +{ +template +using IfIsInputIterator = typename std::enable_if< + std::is_convertible::iterator_category, std::input_iterator_tag>::value, + bool>::type; + +template +using IfIsForwardIterator = typename std::enable_if< + std::is_convertible::iterator_category, std::forward_iterator_tag>::value, + bool>::type; + +template +using IfIsNotForwardIterator = typename std::enable_if< + !std::is_convertible::iterator_category, std::forward_iterator_tag>::value, + bool>::type; + +template = true> +void reserveIfForwardIterator(Container *, InputIterator, InputIterator) +{ +} + +template = true> +void reserveIfForwardIterator(Container *c, ForwardIterator f, ForwardIterator l) +{ + c->reserve(static_cast(std::distance(f, l))); +} +} // namespace QtPrivate + +QT_END_NAMESPACE + +#endif // Q_QDOC + +#endif // QCONTAINERTOOLS_IMPL_H diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp index d9d93862e5..c0450f5cd8 100644 --- a/src/corelib/tools/qlinkedlist.cpp +++ b/src/corelib/tools/qlinkedlist.cpp @@ -153,6 +153,14 @@ const QLinkedListData QLinkedListData::shared_null = { initializer lists. */ +/*! \fn template template QLinkedList::QLinkedList(InputIterator first, InputIterator last) + \since 5.14 + + Constructs a list with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c T. +*/ + /*! \fn template QLinkedList::~QLinkedList() Destroys the list. References to the values in the list, and all diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 91367a74b3..83f70deceb 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -42,6 +42,7 @@ #include #include +#include #include #include @@ -84,11 +85,14 @@ public: inline QLinkedList(const QLinkedList &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); } #if defined(Q_COMPILER_INITIALIZER_LISTS) inline QLinkedList(std::initializer_list list) - : d(const_cast(&QLinkedListData::shared_null)) - { - std::copy(list.begin(), list.end(), std::back_inserter(*this)); - } + : QLinkedList(list.begin(), list.end()) {} #endif + template = true> + inline QLinkedList(InputIterator first, InputIterator last) + : QLinkedList() + { + std::copy(first, last, std::back_inserter(*this)); + } ~QLinkedList(); QLinkedList &operator=(const QLinkedList &); #ifdef Q_COMPILER_RVALUE_REFS diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 6f8084c676..48617f0539 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -545,6 +545,14 @@ void **QListData::erase(void **xi) \since 5.2 */ +/*! \fn template template QList::QList(InputIterator first, InputIterator last) + \since 5.14 + + Constructs a QList with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c T. +*/ + /*! \fn template QList QList::mid(int pos, int length) const diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 77d8df4a88..dfb8a8a4ab 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -169,9 +170,11 @@ public: inline void swap(QList &other) noexcept { qSwap(d, other.d); } #ifdef Q_COMPILER_INITIALIZER_LISTS inline QList(std::initializer_list args) - : d(const_cast(&QListData::shared_null)) - { reserve(int(args.size())); std::copy(args.begin(), args.end(), std::back_inserter(*this)); } + : QList(args.begin(), args.end()) {} #endif + template = true> + QList(InputIterator first, InputIterator last); + bool operator==(const QList &l) const; inline bool operator!=(const QList &l) const { return !(*this == l); } @@ -842,6 +845,15 @@ Q_OUTOFLINE_TEMPLATE QList::~QList() dealloc(d); } +template +template > +QList::QList(InputIterator first, InputIterator last) + : QList() +{ + QtPrivate::reserveIfForwardIterator(this, first, last); + std::copy(first, last, std::back_inserter(*this)); +} + template Q_OUTOFLINE_TEMPLATE bool QList::operator==(const QList &l) const { diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index aa915f7ed1..7ae715d247 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -41,6 +41,8 @@ #define QSET_H #include +#include + #ifdef Q_COMPILER_INITIALIZER_LISTS #include #endif @@ -59,12 +61,16 @@ public: inline QSet() noexcept {} #ifdef Q_COMPILER_INITIALIZER_LISTS inline QSet(std::initializer_list list) - { - reserve(int(list.size())); - for (typename std::initializer_list::const_iterator it = list.begin(); it != list.end(); ++it) - insert(*it); - } + : QSet(list.begin(), list.end()) {} #endif + template = true> + inline QSet(InputIterator first, InputIterator last) + { + QtPrivate::reserveIfForwardIterator(this, first, last); + for (; first != last; ++first) + insert(*first); + } + // compiler-generated copy/move ctor/assignment operators are fine! // compiler-generated destructor is fine! diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc index 48863f2399..2e7a5a29ce 100644 --- a/src/corelib/tools/qset.qdoc +++ b/src/corelib/tools/qset.qdoc @@ -113,6 +113,17 @@ compiled in C++11 mode. */ +/*! \fn template template QSet::QSet(InputIterator first, InputIterator last) + \since 5.14 + + Constructs a set with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c T. + + \note If the range [\a first, \a last) contains duplicate elements, + the first one is retained. +*/ + /*! \fn template void QSet::swap(QSet &other) diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index cc6eaf8ad2..49247d66b8 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -847,5 +847,12 @@ int QtPrivate::QStringList_removeDuplicates(QStringList *that) lists. */ + /*! \fn template QStringList::QStringList(InputIterator first, InputIterator last) + \since 5.14 + + Constructs a QStringList with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c QString. + */ QT_END_NAMESPACE diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index 6387161269..5ad01a0658 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -44,6 +44,7 @@ #define QSTRINGLIST_H #include +#include #include #include #include @@ -109,6 +110,9 @@ public: #ifdef Q_COMPILER_INITIALIZER_LISTS inline QStringList(std::initializer_list args) : QList(args) { } #endif + template = true> + inline QStringList(InputIterator first, InputIterator last) + : QList(first, last) { } QStringList &operator=(const QList &other) { QList::operator=(other); return *this; } diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index c03fbb2218..c81af68593 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -71,13 +72,19 @@ public: #ifdef Q_COMPILER_INITIALIZER_LISTS QVarLengthArray(std::initializer_list args) - : a(Prealloc), s(0), ptr(reinterpret_cast(array)) + : QVarLengthArray(args.begin(), args.end()) { - if (args.size()) - append(args.begin(), int(args.size())); } #endif + template = true> + inline QVarLengthArray(InputIterator first, InputIterator last) + : QVarLengthArray() + { + QtPrivate::reserveIfForwardIterator(this, first, last); + std::copy(first, last, std::back_inserter(*this)); + } + inline ~QVarLengthArray() { if (QTypeInfo::isComplex) { T *i = ptr + s; diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index bc8df82517..80769e3769 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -110,6 +110,14 @@ lists. */ +/*! \fn template template QVarLengthArray::QVarLengthArray(InputIterator first, InputIterator last) + \since 5.14 + + Constructs an array with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c T. +*/ + /*! \fn template QVarLengthArray::~QVarLengthArray() diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 096c369e51..6cbf794c6c 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -81,6 +82,9 @@ public: inline QVector(std::initializer_list args); QVector &operator=(std::initializer_list args); #endif + template = true> + inline QVector(InputIterator first, InputIterator last); + bool operator==(const QVector &v) const; inline bool operator!=(const QVector &v) const { return !(*this == v); } @@ -557,6 +561,15 @@ QT_WARNING_POP # endif // Q_CC_MSVC #endif // Q_COMPILER_INITIALIZER_LISTS +template +template > +QVector::QVector(InputIterator first, InputIterator last) + : QVector() +{ + QtPrivate::reserveIfForwardIterator(this, first, last); + std::copy(first, last, std::back_inserter(*this)); +} + template void QVector::freeData(Data *x) { diff --git a/src/corelib/tools/qvector.qdoc b/src/corelib/tools/qvector.qdoc index 69bbb5f9a2..cb47d36356 100644 --- a/src/corelib/tools/qvector.qdoc +++ b/src/corelib/tools/qvector.qdoc @@ -243,6 +243,13 @@ lists. */ +/*! \fn template template QVector::QVector(InputIterator first, InputIterator last) + \since 5.14 + + Constructs a vector with the contents in the iterator range [\a first, \a last). + + The value type of \c InputIterator must be convertible to \c T. +*/ /*! \fn template QVector::~QVector() diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 995bab694e..5dcb6c9ee0 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -18,6 +18,7 @@ HEADERS += \ tools/qcollator.h \ tools/qcollator_p.h \ tools/qcontainerfwd.h \ + tools/qcontainertools_impl.h \ tools/qcryptographichash.h \ tools/qdatetime.h \ tools/qdatetime_p.h \ diff --git a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp index 3b8111f1a3..196276c52f 100644 --- a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp +++ b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp @@ -34,13 +34,375 @@ #include "qstring.h" #include "qvarlengtharray.h" #include "qvector.h" +#include "qdebug.h" +#include +#include #include // for reference +#include +#include + +// MSVC has these containers from the Standard Library, but it lacks +// a __has_include mechanism (that we need to use for other stdlibs). +// For the sake of increasing our test coverage, work around the issue. + +#ifdef Q_CC_MSVC +#define COMPILER_HAS_STDLIB_INCLUDE(x) 1 +#else +#define COMPILER_HAS_STDLIB_INCLUDE(x) QT_HAS_INCLUDE(x) +#endif + +#if COMPILER_HAS_STDLIB_INCLUDE() +#include +#endif +#if COMPILER_HAS_STDLIB_INCLUDE() +#include +#endif + +struct Movable +{ + explicit Movable(int i = 0) Q_DECL_NOTHROW + : i(i) + { + ++instanceCount; + } + + Movable(const Movable &m) + : i(m.i) + { + ++instanceCount; + } + + ~Movable() + { + --instanceCount; + } + + int i; + static int instanceCount; +}; + +int Movable::instanceCount = 0; +bool operator==(Movable lhs, Movable rhs) Q_DECL_NOTHROW { return lhs.i == rhs.i; } +bool operator!=(Movable lhs, Movable rhs) Q_DECL_NOTHROW { return lhs.i != rhs.i; } +bool operator<(Movable lhs, Movable rhs) Q_DECL_NOTHROW { return lhs.i < rhs.i; } + +uint qHash(Movable m, uint seed = 0) Q_DECL_NOTHROW { return qHash(m.i, seed); } +QDebug &operator<<(QDebug &d, Movable m) +{ + const QDebugStateSaver saver(d); + return d.nospace() << "Movable(" << m.i << ")"; +} + +QT_BEGIN_NAMESPACE +Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE); +QT_END_NAMESPACE + +struct Complex +{ + explicit Complex(int i = 0) Q_DECL_NOTHROW + : i(i) + { + ++instanceCount; + } + + Complex(const Complex &c) + : i(c.i) + { + ++instanceCount; + } + + ~Complex() + { + --instanceCount; + } + + int i; + static int instanceCount; +}; + +int Complex::instanceCount = 0; +bool operator==(Complex lhs, Complex rhs) Q_DECL_NOTHROW { return lhs.i == rhs.i; } +bool operator!=(Complex lhs, Complex rhs) Q_DECL_NOTHROW { return lhs.i != rhs.i; } +bool operator<(Complex lhs, Complex rhs) Q_DECL_NOTHROW { return lhs.i < rhs.i; } + +uint qHash(Complex c, uint seed = 0) Q_DECL_NOTHROW { return qHash(c.i, seed); } +QDebug &operator<<(QDebug &d, Complex c) +{ + const QDebugStateSaver saver(d); + return d.nospace() << "Complex(" << c.i << ")"; +} + + +struct DuplicateStrategyTestType +{ + explicit DuplicateStrategyTestType(int i = 0) Q_DECL_NOTHROW + : i(i), + j(++counter) + { + } + + int i; + int j; + + static int counter; +}; + +int DuplicateStrategyTestType::counter = 0; + +// only look at the i member, not j. j allows us to identify which instance +// gets inserted in containers that don't allow for duplicates +bool operator==(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW +{ + return lhs.i == rhs.i; +} + +bool operator!=(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW +{ + return lhs.i != rhs.i; +} + +bool operator<(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW +{ + return lhs.i < rhs.i; +} + +uint qHash(DuplicateStrategyTestType c, uint seed = 0) Q_DECL_NOTHROW +{ + return qHash(c.i, seed); +} + +bool reallyEqual(DuplicateStrategyTestType lhs, DuplicateStrategyTestType rhs) Q_DECL_NOTHROW +{ + return lhs.i == rhs.i && lhs.j == rhs.j; +} + +QDebug &operator<<(QDebug &d, DuplicateStrategyTestType c) +{ + const QDebugStateSaver saver(d); + return d.nospace() << "DuplicateStrategyTestType(" << c.i << "," << c.j << ")"; +} + + +namespace std { +template<> +struct hash +{ + std::size_t operator()(Movable m) const Q_DECL_NOTHROW + { + return hash()(m.i); + } +}; + +template<> +struct hash +{ + std::size_t operator()(Complex m) const Q_DECL_NOTHROW + { + return hash()(m.i); + } +}; + +template<> +struct hash +{ + std::size_t operator()(DuplicateStrategyTestType m) const Q_DECL_NOTHROW + { + return hash()(m.i); + } +}; +} + +// work around the fact that QVarLengthArray has a non-type +// template parameter, and that breaks non_associative_container_duplicates_strategy +template +class VarLengthArray : public QVarLengthArray +{ +public: +#ifdef Q_COMPILER_INHERITING_CONSTRUCTORS + using QVarLengthArray::QVarLengthArray; +#else + template + VarLengthArray(InputIterator first, InputIterator last) + : QVarLengthArray(first, last) + { + } + +#ifdef Q_COMPILER_INITIALIZER_LISTS + VarLengthArray(std::initializer_list args) + : QVarLengthArray(args) + { + } +#endif +#endif +}; class tst_ContainerApiSymmetry : public QObject { Q_OBJECT + int m_movableInstanceCount; + int m_complexInstanceCount; + +private Q_SLOTS: + void init(); + void cleanup(); + +private: + template + void ranged_ctor_non_associative_impl() const; + + template class Container> + void non_associative_container_duplicates_strategy() const; + +private Q_SLOTS: + // non associative + void ranged_ctor_std_vector_int() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_vector_char() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_vector_QChar() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_vector_Movable() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_vector_Complex() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_vector_duplicates_strategy() { non_associative_container_duplicates_strategy(); } + + void ranged_ctor_QVector_int() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QVector_char() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QVector_QChar() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QVector_Movable() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QVector_Complex() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QVector_duplicates_strategy() { non_associative_container_duplicates_strategy(); } + + void ranged_ctor_QVarLengthArray_int() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QVarLengthArray_Movable() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QVarLengthArray_Complex() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QVarLengthArray_duplicates_strategy() { non_associative_container_duplicates_strategy(); } // note the VarLengthArray passed + + void ranged_ctor_QList_int() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QList_Movable() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QList_Complex() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QList_duplicates_strategy() { non_associative_container_duplicates_strategy(); } + + void ranged_ctor_std_list_int() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_list_Movable() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_list_Complex() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_list_duplicates_strategy() { non_associative_container_duplicates_strategy(); } + + void ranged_ctor_std_forward_list_int() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_non_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_std_forward_list_Movable() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_non_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_std_forward_list_Complex() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_non_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_std_forward_list_duplicates_strategy() { +#if COMPILER_HAS_STDLIB_INCLUDE() + non_associative_container_duplicates_strategy(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_QLinkedList_int() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QLinkedList_Movable() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QLinkedList_Complex() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QLinkedList_duplicates_strategy() { non_associative_container_duplicates_strategy(); } + + void ranged_ctor_std_set_int() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_set_Movable() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_set_Complex() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_set_duplicates_strategy() { non_associative_container_duplicates_strategy(); } + + void ranged_ctor_std_multiset_int() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_multiset_Movable() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_multiset_Complex() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_std_multiset_duplicates_strategy() { non_associative_container_duplicates_strategy(); } + + void ranged_ctor_std_unordered_set_int() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_non_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_std_unordered_set_Movable() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_non_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_std_unordered_set_Complex() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_non_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_unordered_set_duplicates_strategy() { +#if COMPILER_HAS_STDLIB_INCLUDE() + non_associative_container_duplicates_strategy(); +#else + QSKIP(" is needed for this test"); +#endif + } + + + void ranged_ctor_std_unordered_multiset_int() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_non_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_std_unordered_multiset_Movable() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_non_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_std_unordered_multiset_Complex() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_non_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_std_unordered_multiset_duplicates_strategy() { +#if COMPILER_HAS_STDLIB_INCLUDE() + non_associative_container_duplicates_strategy(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_QSet_int() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QSet_Movable() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QSet_Complex() { ranged_ctor_non_associative_impl>(); } + void ranged_ctor_QSet_duplicates_strategy() { non_associative_container_duplicates_strategy(); } + private: template void front_back_impl() const; @@ -58,6 +420,237 @@ private Q_SLOTS: void front_back_QByteArray() { front_back_impl(); } }; +void tst_ContainerApiSymmetry::init() +{ + m_movableInstanceCount = Movable::instanceCount; + m_complexInstanceCount = Complex::instanceCount; +} + +void tst_ContainerApiSymmetry::cleanup() +{ + // very simple leak check + QCOMPARE(Movable::instanceCount, m_movableInstanceCount); + QCOMPARE(Complex::instanceCount, m_complexInstanceCount); +} + +template +Container createContainerReference() +{ + using V = typename Container::value_type; + + return {V(0), V(1), V(2), V(0)}; +} + +template +void tst_ContainerApiSymmetry::ranged_ctor_non_associative_impl() const +{ + using V = typename Container::value_type; + + // the double V(0) is deliberate + const auto reference = createContainerReference(); + + // plain array + const V values1[] = { V(0), V(1), V(2), V(0) }; + + const Container c1(values1, values1 + sizeof(values1)/sizeof(values1[0])); + + // from QList + QList l2; + l2 << V(0) << V(1) << V(2) << V(0); + + const Container c2a(l2.begin(), l2.end()); + const Container c2b(l2.cbegin(), l2.cend()); + + // from std::list + std::list l3; + l3.push_back(V(0)); + l3.push_back(V(1)); + l3.push_back(V(2)); + l3.push_back(V(0)); + const Container c3a(l3.begin(), l3.end()); + + // from const std::list + const std::list l3c = l3; + const Container c3b(l3c.begin(), l3c.end()); + + // from itself + const Container c4(reference.begin(), reference.end()); + + QCOMPARE(c1, reference); + QCOMPARE(c2a, reference); + QCOMPARE(c2b, reference); + QCOMPARE(c3a, reference); + QCOMPARE(c3b, reference); + QCOMPARE(c4, reference); +} + + +// type traits for detecting whether a non-associative container +// accepts duplicated values, and if it doesn't, whether construction/insertion +// prefer the new values (overwriting) or the old values (rejecting) + +struct ContainerAcceptsDuplicateValues {}; +struct ContainerOverwritesDuplicateValues {}; +struct ContainerRejectsDuplicateValues {}; + +template +struct ContainerDuplicatedValuesStrategy {}; + +template +struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; + +template +struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; + +template +struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; + +template +struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; + +template +struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; + +template +struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; + +#if COMPILER_HAS_STDLIB_INCLUDE() +template +struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; +#endif + +template +struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; + +// assuming https://cplusplus.github.io/LWG/lwg-active.html#2844 resolution +template +struct ContainerDuplicatedValuesStrategy> : ContainerRejectsDuplicateValues {}; + +template +struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; + +#if COMPILER_HAS_STDLIB_INCLUDE() +// assuming https://cplusplus.github.io/LWG/lwg-active.html#2844 resolution +template +struct ContainerDuplicatedValuesStrategy> : ContainerRejectsDuplicateValues {}; + +template +struct ContainerDuplicatedValuesStrategy> : ContainerAcceptsDuplicateValues {}; +#endif + +template +struct ContainerDuplicatedValuesStrategy> : ContainerRejectsDuplicateValues {}; + +#if defined(Q_COMPILER_INITIALIZER_LISTS) +template +void non_associative_container_check_duplicates_impl(const std::initializer_list &reference, const Container &c, ContainerAcceptsDuplicateValues) +{ + // do a deep check for equality, not ordering + QVERIFY(std::distance(reference.begin(), reference.end()) == std::distance(c.begin(), c.end())); + QVERIFY(std::is_permutation(reference.begin(), reference.end(), c.begin(), &reallyEqual)); +} + +enum class IterationOnReference +{ + ForwardIteration, + ReverseIteration +}; + +template +void non_associative_container_check_duplicates_impl_no_duplicates(const std::initializer_list &reference, const Container &c, IterationOnReference ior) +{ + std::vector valuesAlreadySeen; + + // iterate on reference forward or backwards, depending on ior. this will give + // us the expected semantics when checking for duplicated values into c + auto it = [&reference, ior]() { + switch (ior) { + case IterationOnReference::ForwardIteration: return reference.begin(); + case IterationOnReference::ReverseIteration: return reference.end() - 1; + }; + return std::initializer_list::const_iterator(); + }(); + + const auto &end = [&reference, ior]() { + switch (ior) { + case IterationOnReference::ForwardIteration: return reference.end(); + case IterationOnReference::ReverseIteration: return reference.begin() - 1; + }; + return std::initializer_list::const_iterator(); + }(); + + while (it != end) { + const auto &value = *it; + + // check that there is indeed the same value in the container (using operator==) + const auto &valueInContainerIterator = std::find(c.begin(), c.end(), value); + QVERIFY(valueInContainerIterator != c.end()); + QVERIFY(value == *valueInContainerIterator); + + // if the value is a duplicate, we don't expect to find it in the container + // (when doing a deep comparison). otherwise it should be there + + const auto &valuesAlreadySeenIterator = std::find(valuesAlreadySeen.cbegin(), valuesAlreadySeen.cend(), value); + const bool valueIsDuplicated = (valuesAlreadySeenIterator != valuesAlreadySeen.cend()); + + const auto &reallyEqualCheck = [&value](const DuplicateStrategyTestType &v) { return reallyEqual(value, v); }; + QCOMPARE(std::find_if(c.begin(), c.end(), reallyEqualCheck) == c.end(), valueIsDuplicated); + + valuesAlreadySeen.push_back(value); + + switch (ior) { + case IterationOnReference::ForwardIteration: + ++it; + break; + case IterationOnReference::ReverseIteration: + --it; + break; + }; + } + +} + +template +void non_associative_container_check_duplicates_impl(const std::initializer_list &reference, const Container &c, ContainerRejectsDuplicateValues) +{ + non_associative_container_check_duplicates_impl_no_duplicates(reference, c, IterationOnReference::ForwardIteration); +} + +template +void non_associative_container_check_duplicates_impl(const std::initializer_list &reference, const Container &c, ContainerOverwritesDuplicateValues) +{ + non_associative_container_check_duplicates_impl_no_duplicates(reference, c, IterationOnReference::ReverseIteration); +} + +template +void non_associative_container_check_duplicates(const std::initializer_list &reference, const Container &c) +{ + non_associative_container_check_duplicates_impl(reference, c, ContainerDuplicatedValuesStrategy()); +} + +template class Container> +void tst_ContainerApiSymmetry::non_associative_container_duplicates_strategy() const +{ + // first and last are "duplicates" -- they compare equal for operator==, + // but they differ when using reallyEqual + const std::initializer_list reference{ DuplicateStrategyTestType{0}, + DuplicateStrategyTestType{1}, + DuplicateStrategyTestType{2}, + DuplicateStrategyTestType{0} }; + Container c1{reference}; + non_associative_container_check_duplicates(reference, c1); + + Container c2{reference.begin(), reference.end()}; + non_associative_container_check_duplicates(reference, c2); +} +#else +template class Container> +void tst_ContainerApiSymmetry::non_associative_container_duplicates_strategy() const +{ + QSKIP("Test requires a better compiler"); +} +#endif // Q_COMPILER_INITIALIZER_LISTS + template Container make(int size) { diff --git a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp index 42bdf62a93..37368c3dfc 100644 --- a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp +++ b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp @@ -30,13 +30,17 @@ #include #include #include +#include #include +#include + class tst_QStringList : public QObject { Q_OBJECT private slots: + void constructors(); void sort(); void filter(); void replaceInStrings(); @@ -66,6 +70,39 @@ private slots: extern const char email[]; +void tst_QStringList::constructors() +{ + { + QStringList list; + QVERIFY(list.isEmpty()); + QCOMPARE(list.size(), 0); + QVERIFY(list == QStringList()); + } + { + QString str = "abc"; + QStringList list(str); + QVERIFY(!list.isEmpty()); + QCOMPARE(list.size(), 1); + QCOMPARE(list.at(0), str); + } + { + QStringList list{ "a", "b", "c" }; + QVERIFY(!list.isEmpty()); + QCOMPARE(list.size(), 3); + QCOMPARE(list.at(0), "a"); + QCOMPARE(list.at(1), "b"); + QCOMPARE(list.at(2), "c"); + } + { + const QVector reference{ "a", "b", "c" }; + QCOMPARE(reference.size(), 3); + + QStringList list(reference.cbegin(), reference.cend()); + QCOMPARE(list.size(), reference.size()); + QVERIFY(std::equal(list.cbegin(), list.cend(), reference.cbegin())); + } +} + void tst_QStringList::indexOf_regExp() { QStringList list; From dea94de304e92f162ed0f1d4a30f03717a19b198 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 18 Dec 2017 07:54:00 +0100 Subject: [PATCH 002/122] Import MD4C Markdown parser into 3rdparty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It has an MIT license and will be used to add Markdown (CommonMark) support to QTextDocument. Currently this is version 0.3.0 RC plus a few more patches. [ChangeLog][Third-Party Code] Qt Gui: Added md4c markdown parser to src/3rdparty/md4c (MIT licensed). Change-Id: Ie74373c89f2a30ba76ee728aee5e1ca166829f44 Reviewed-by: Lisandro Damián Nicanor Pérez Meyer Reviewed-by: Lars Knoll Reviewed-by: Gatis Paeglis --- src/3rdparty/md4c.pri | 3 + src/3rdparty/md4c/LICENSE.md | 22 + src/3rdparty/md4c/md4c.c | 6016 +++++++++++++++++++++++++ src/3rdparty/md4c/md4c.h | 359 ++ src/3rdparty/md4c/qt_attribution.json | 15 + 5 files changed, 6415 insertions(+) create mode 100644 src/3rdparty/md4c.pri create mode 100644 src/3rdparty/md4c/LICENSE.md create mode 100644 src/3rdparty/md4c/md4c.c create mode 100644 src/3rdparty/md4c/md4c.h create mode 100644 src/3rdparty/md4c/qt_attribution.json diff --git a/src/3rdparty/md4c.pri b/src/3rdparty/md4c.pri new file mode 100644 index 0000000000..e0150dc6ed --- /dev/null +++ b/src/3rdparty/md4c.pri @@ -0,0 +1,3 @@ +INCLUDEPATH += $$PWD/md4c +HEADERS += $$PWD/md4c/md4c.h +SOURCES += $$PWD/md4c/md4c.c diff --git a/src/3rdparty/md4c/LICENSE.md b/src/3rdparty/md4c/LICENSE.md new file mode 100644 index 0000000000..d58ef9341d --- /dev/null +++ b/src/3rdparty/md4c/LICENSE.md @@ -0,0 +1,22 @@ + +# The MIT License (MIT) + +Copyright © 2016-2019 Martin Mitáš + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the “Software”), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/src/3rdparty/md4c/md4c.c b/src/3rdparty/md4c/md4c.c new file mode 100644 index 0000000000..4c0ad5c0fc --- /dev/null +++ b/src/3rdparty/md4c/md4c.c @@ -0,0 +1,6016 @@ +/* + * MD4C: Markdown parser for C + * (http://github.com/mity/md4c) + * + * Copyright (c) 2016-2019 Martin Mitas + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "md4c.h" + +#include +#include +#include + + +/***************************** + *** Miscellaneous Stuff *** + *****************************/ + +#ifdef _MSC_VER + /* MSVC does not understand "inline" when building as pure C (not C++). + * However it understands "__inline" */ + #ifndef __cplusplus + #define inline __inline + #endif +#endif + +#ifdef _T + #undef _T +#endif +#if defined MD4C_USE_UTF16 + #define _T(x) L##x +#else + #define _T(x) x +#endif + +/* Misc. macros. */ +#define SIZEOF_ARRAY(a) (sizeof(a) / sizeof(a[0])) + +#define STRINGIZE_(x) #x +#define STRINGIZE(x) STRINGIZE_(x) + +#ifndef TRUE + #define TRUE 1 + #define FALSE 0 +#endif + + +/************************ + *** Internal Types *** + ************************/ + +/* These are omnipresent so lets save some typing. */ +#define CHAR MD_CHAR +#define SZ MD_SIZE +#define OFF MD_OFFSET + +typedef struct MD_MARK_tag MD_MARK; +typedef struct MD_BLOCK_tag MD_BLOCK; +typedef struct MD_CONTAINER_tag MD_CONTAINER; +typedef struct MD_REF_DEF_tag MD_REF_DEF; + + +/* During analyzes of inline marks, we need to manage some "mark chains", + * of (yet unresolved) openers. This structure holds start/end of the chain. + * The chain internals are then realized through MD_MARK::prev and ::next. + */ +typedef struct MD_MARKCHAIN_tag MD_MARKCHAIN; +struct MD_MARKCHAIN_tag { + int head; /* Index of first mark in the chain, or -1 if empty. */ + int tail; /* Index of last mark in the chain, or -1 if empty. */ +}; + +/* Context propagated through all the parsing. */ +typedef struct MD_CTX_tag MD_CTX; +struct MD_CTX_tag { + /* Immutable stuff (parameters of md_parse()). */ + const CHAR* text; + SZ size; + MD_PARSER parser; + void* userdata; + + /* Helper temporary growing buffer. */ + CHAR* buffer; + unsigned alloc_buffer; + + /* Reference definitions. */ + MD_REF_DEF* ref_defs; + int n_ref_defs; + int alloc_ref_defs; + void** ref_def_hashtable; + int ref_def_hashtable_size; + + /* Stack of inline/span markers. + * This is only used for parsing a single block contents but by storing it + * here we may reuse the stack for subsequent blocks; i.e. we have fewer + * (re)allocations. */ + MD_MARK* marks; + int n_marks; + int alloc_marks; + +#if defined MD4C_USE_UTF16 + char mark_char_map[128]; +#else + char mark_char_map[256]; +#endif + + /* For resolving of inline spans. */ + MD_MARKCHAIN mark_chains[8]; +#define PTR_CHAIN ctx->mark_chains[0] +#define TABLECELLBOUNDARIES ctx->mark_chains[1] +#define BACKTICK_OPENERS ctx->mark_chains[2] +#define LOWERTHEN_OPENERS ctx->mark_chains[3] +#define ASTERISK_OPENERS ctx->mark_chains[4] +#define UNDERSCORE_OPENERS ctx->mark_chains[5] +#define TILDE_OPENERS ctx->mark_chains[6] +#define BRACKET_OPENERS ctx->mark_chains[7] +#define OPENERS_CHAIN_FIRST 2 +#define OPENERS_CHAIN_LAST 7 + + int n_table_cell_boundaries; + + /* For resolving links. */ + int unresolved_link_head; + int unresolved_link_tail; + + /* For block analysis. + * Notes: + * -- It holds MD_BLOCK as well as MD_LINE structures. After each + * MD_BLOCK, its (multiple) MD_LINE(s) follow. + * -- For MD_BLOCK_HTML and MD_BLOCK_CODE, MD_VERBATIMLINE(s) are used + * instead of MD_LINE(s). + */ + void* block_bytes; + MD_BLOCK* current_block; + int n_block_bytes; + int alloc_block_bytes; + + /* For container block analysis. */ + MD_CONTAINER* containers; + int n_containers; + int alloc_containers; + + int last_line_has_list_loosening_effect; + int last_list_item_starts_with_two_blank_lines; + + /* Minimal indentation to call the block "indented code block". */ + unsigned code_indent_offset; + + /* Contextual info for line analysis. */ + SZ code_fence_length; /* For checking closing fence length. */ + int html_block_type; /* For checking closing raw HTML condition. */ +}; + +typedef enum MD_LINETYPE_tag MD_LINETYPE; +enum MD_LINETYPE_tag { + MD_LINE_BLANK, + MD_LINE_HR, + MD_LINE_ATXHEADER, + MD_LINE_SETEXTHEADER, + MD_LINE_SETEXTUNDERLINE, + MD_LINE_INDENTEDCODE, + MD_LINE_FENCEDCODE, + MD_LINE_HTML, + MD_LINE_TEXT, + MD_LINE_TABLE, + MD_LINE_TABLEUNDERLINE +}; + +typedef struct MD_LINE_ANALYSIS_tag MD_LINE_ANALYSIS; +struct MD_LINE_ANALYSIS_tag { + MD_LINETYPE type : 16; + unsigned data : 16; + OFF beg; + OFF end; + unsigned indent; /* Indentation level. */ +}; + +typedef struct MD_LINE_tag MD_LINE; +struct MD_LINE_tag { + OFF beg; + OFF end; +}; + +typedef struct MD_VERBATIMLINE_tag MD_VERBATIMLINE; +struct MD_VERBATIMLINE_tag { + OFF beg; + OFF end; + OFF indent; +}; + + +/******************* + *** Debugging *** + *******************/ + +#define MD_LOG(msg) \ + do { \ + if(ctx->parser.debug_log != NULL) \ + ctx->parser.debug_log((msg), ctx->userdata); \ + } while(0) + +#ifdef DEBUG + #define MD_ASSERT(cond) \ + do { \ + if(!(cond)) { \ + MD_LOG(__FILE__ ":" STRINGIZE(__LINE__) ": " \ + "Assertion '" STRINGIZE(cond) "' failed."); \ + exit(1); \ + } \ + } while(0) + + #define MD_UNREACHABLE() MD_ASSERT(1 == 0) +#else + #ifdef __GNUC__ + #define MD_ASSERT(cond) do { if(!(cond)) __builtin_unreachable(); } while(0) + #define MD_UNREACHABLE() do { __builtin_unreachable(); } while(0) + #elif defined _MSC_VER && _MSC_VER > 120 + #define MD_ASSERT(cond) do { __assume(cond); } while(0) + #define MD_UNREACHABLE() do { __assume(0); } while(0) + #else + #define MD_ASSERT(cond) do {} while(0) + #define MD_UNREACHABLE() do {} while(0) + #endif +#endif + + +/***************** + *** Helpers *** + *****************/ + +/* Character accessors. */ +#define CH(off) (ctx->text[(off)]) +#define STR(off) (ctx->text + (off)) + +/* Character classification. + * Note we assume ASCII compatibility of code points < 128 here. */ +#define ISIN_(ch, ch_min, ch_max) ((ch_min) <= (unsigned)(ch) && (unsigned)(ch) <= (ch_max)) +#define ISANYOF_(ch, palette) (md_strchr((palette), (ch)) != NULL) +#define ISANYOF2_(ch, ch1, ch2) ((ch) == (ch1) || (ch) == (ch2)) +#define ISANYOF3_(ch, ch1, ch2, ch3) ((ch) == (ch1) || (ch) == (ch2) || (ch) == (ch3)) +#define ISASCII_(ch) ((unsigned)(ch) <= 127) +#define ISBLANK_(ch) (ISANYOF2_((ch), _T(' '), _T('\t'))) +#define ISNEWLINE_(ch) (ISANYOF2_((ch), _T('\r'), _T('\n'))) +#define ISWHITESPACE_(ch) (ISBLANK_(ch) || ISANYOF2_((ch), _T('\v'), _T('\f'))) +#define ISCNTRL_(ch) ((unsigned)(ch) <= 31 || (unsigned)(ch) == 127) +#define ISPUNCT_(ch) (ISIN_(ch, 33, 47) || ISIN_(ch, 58, 64) || ISIN_(ch, 91, 96) || ISIN_(ch, 123, 126)) +#define ISUPPER_(ch) (ISIN_(ch, _T('A'), _T('Z'))) +#define ISLOWER_(ch) (ISIN_(ch, _T('a'), _T('z'))) +#define ISALPHA_(ch) (ISUPPER_(ch) || ISLOWER_(ch)) +#define ISDIGIT_(ch) (ISIN_(ch, _T('0'), _T('9'))) +#define ISXDIGIT_(ch) (ISDIGIT_(ch) || ISIN_(ch, _T('A'), _T('F')) || ISIN_(ch, _T('a'), _T('f'))) +#define ISALNUM_(ch) (ISALPHA_(ch) || ISDIGIT_(ch)) + +#define ISANYOF(off, palette) ISANYOF_(CH(off), (palette)) +#define ISANYOF2(off, ch1, ch2) ISANYOF2_(CH(off), (ch1), (ch2)) +#define ISANYOF3(off, ch1, ch2, ch3) ISANYOF3_(CH(off), (ch1), (ch2), (ch3)) +#define ISASCII(off) ISASCII_(CH(off)) +#define ISBLANK(off) ISBLANK_(CH(off)) +#define ISNEWLINE(off) ISNEWLINE_(CH(off)) +#define ISWHITESPACE(off) ISWHITESPACE_(CH(off)) +#define ISCNTRL(off) ISCNTRL_(CH(off)) +#define ISPUNCT(off) ISPUNCT_(CH(off)) +#define ISUPPER(off) ISUPPER_(CH(off)) +#define ISLOWER(off) ISLOWER_(CH(off)) +#define ISALPHA(off) ISALPHA_(CH(off)) +#define ISDIGIT(off) ISDIGIT_(CH(off)) +#define ISXDIGIT(off) ISXDIGIT_(CH(off)) +#define ISALNUM(off) ISALNUM_(CH(off)) +static inline const CHAR* +md_strchr(const CHAR* str, CHAR ch) +{ + OFF i; + for(i = 0; str[i] != _T('\0'); i++) { + if(ch == str[i]) + return (str + i); + } + return NULL; +} + +/* Case insensitive check of string equality. */ +static inline int +md_ascii_case_eq(const CHAR* s1, const CHAR* s2, SZ n) +{ + OFF i; + for(i = 0; i < n; i++) { + CHAR ch1 = s1[i]; + CHAR ch2 = s2[i]; + + if(ISLOWER_(ch1)) + ch1 += ('A'-'a'); + if(ISLOWER_(ch2)) + ch2 += ('A'-'a'); + if(ch1 != ch2) + return FALSE; + } + return TRUE; +} + +static inline int +md_ascii_eq(const CHAR* s1, const CHAR* s2, SZ n) +{ + return memcmp(s1, s2, n * sizeof(CHAR)) == 0; +} + +static int +md_text_with_null_replacement(MD_CTX* ctx, MD_TEXTTYPE type, const CHAR* str, SZ size) +{ + OFF off = 0; + int ret = 0; + + while(1) { + while(off < size && str[off] != _T('\0')) + off++; + + if(off > 0) { + ret = ctx->parser.text(type, str, off, ctx->userdata); + if(ret != 0) + return ret; + + str += off; + size -= off; + off = 0; + } + + if(off >= size) + return 0; + + ret = ctx->parser.text(MD_TEXT_NULLCHAR, _T(""), 1, ctx->userdata); + if(ret != 0) + return ret; + off++; + } +} + + +#define MD_CHECK(func) \ + do { \ + ret = (func); \ + if(ret < 0) \ + goto abort; \ + } while(0) + + +#define MD_TEMP_BUFFER(sz) \ + do { \ + if(sz > ctx->alloc_buffer) { \ + CHAR* new_buffer; \ + SZ new_size = ((sz) + (sz) / 2 + 128) & ~127; \ + \ + new_buffer = realloc(ctx->buffer, new_size); \ + if(new_buffer == NULL) { \ + MD_LOG("realloc() failed."); \ + ret = -1; \ + goto abort; \ + } \ + \ + ctx->buffer = new_buffer; \ + ctx->alloc_buffer = new_size; \ + } \ + } while(0) + + +#define MD_ENTER_BLOCK(type, arg) \ + do { \ + ret = ctx->parser.enter_block((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from enter_block() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_LEAVE_BLOCK(type, arg) \ + do { \ + ret = ctx->parser.leave_block((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from leave_block() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_ENTER_SPAN(type, arg) \ + do { \ + ret = ctx->parser.enter_span((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from enter_span() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_LEAVE_SPAN(type, arg) \ + do { \ + ret = ctx->parser.leave_span((type), (arg), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from leave_span() callback."); \ + goto abort; \ + } \ + } while(0) + +#define MD_TEXT(type, str, size) \ + do { \ + if(size > 0) { \ + ret = ctx->parser.text((type), (str), (size), ctx->userdata); \ + if(ret != 0) { \ + MD_LOG("Aborted from text() callback."); \ + goto abort; \ + } \ + } \ + } while(0) + +#define MD_TEXT_INSECURE(type, str, size) \ + do { \ + if(size > 0) { \ + ret = md_text_with_null_replacement(ctx, type, str, size); \ + if(ret != 0) { \ + MD_LOG("Aborted from text() callback."); \ + goto abort; \ + } \ + } \ + } while(0) + + + +/************************* + *** Unicode Support *** + *************************/ + +typedef struct MD_UNICODE_FOLD_INFO_tag MD_UNICODE_FOLD_INFO; +struct MD_UNICODE_FOLD_INFO_tag { + int codepoints[3]; + int n_codepoints; +}; + + +#if defined MD4C_USE_UTF16 || defined MD4C_USE_UTF8 + static int + md_is_unicode_whitespace__(int codepoint) + { + /* The ASCII ones are the most frequently used ones, so lets check them first. */ + if(codepoint <= 0x7f) + return ISWHITESPACE_(codepoint); + + /* Check for Unicode codepoints in Zs class above 127. */ + if(codepoint == 0x00a0 || codepoint == 0x1680) + return TRUE; + if(0x2000 <= codepoint && codepoint <= 0x200a) + return TRUE; + if(codepoint == 0x202f || codepoint == 0x205f || codepoint == 0x3000) + return TRUE; + + return FALSE; + } + + static int + md_unicode_cmp__(const void* p_codepoint_a, const void* p_codepoint_b) + { + return (*(const int*)p_codepoint_a - *(const int*)p_codepoint_b); + } + + static int + md_is_unicode_punct__(int codepoint) + { + /* non-ASCII (above 127) Unicode punctuation codepoints (classes + * Pc, Pd, Pe, Pf, Pi, Po, Ps). + * + * Warning: Keep the array sorted. + */ + static const int punct_list[] = { + 0x00a1, 0x00a7, 0x00ab, 0x00b6, 0x00b7, 0x00bb, 0x00bf, 0x037e, 0x0387, 0x055a, 0x055b, 0x055c, 0x055d, 0x055e, 0x055f, 0x0589, + 0x058a, 0x05be, 0x05c0, 0x05c3, 0x05c6, 0x05f3, 0x05f4, 0x0609, 0x060a, 0x060c, 0x060d, 0x061b, 0x061e, 0x061f, 0x066a, 0x066b, + 0x066c, 0x066d, 0x06d4, 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, 0x070a, 0x070b, 0x070c, + 0x070d, 0x07f7, 0x07f8, 0x07f9, 0x0830, 0x0831, 0x0832, 0x0833, 0x0834, 0x0835, 0x0836, 0x0837, 0x0838, 0x0839, 0x083a, 0x083b, + 0x083c, 0x083d, 0x083e, 0x085e, 0x0964, 0x0965, 0x0970, 0x0af0, 0x0df4, 0x0e4f, 0x0e5a, 0x0e5b, 0x0f04, 0x0f05, 0x0f06, 0x0f07, + 0x0f08, 0x0f09, 0x0f0a, 0x0f0b, 0x0f0c, 0x0f0d, 0x0f0e, 0x0f0f, 0x0f10, 0x0f11, 0x0f12, 0x0f14, 0x0f3a, 0x0f3b, 0x0f3c, 0x0f3d, + 0x0f85, 0x0fd0, 0x0fd1, 0x0fd2, 0x0fd3, 0x0fd4, 0x0fd9, 0x0fda, 0x104a, 0x104b, 0x104c, 0x104d, 0x104e, 0x104f, 0x10fb, 0x1360, + 0x1361, 0x1362, 0x1363, 0x1364, 0x1365, 0x1366, 0x1367, 0x1368, 0x1400, 0x166d, 0x166e, 0x169b, 0x169c, 0x16eb, 0x16ec, 0x16ed, + 0x1735, 0x1736, 0x17d4, 0x17d5, 0x17d6, 0x17d8, 0x17d9, 0x17da, 0x1800, 0x1801, 0x1802, 0x1803, 0x1804, 0x1805, 0x1806, 0x1807, + 0x1808, 0x1809, 0x180a, 0x1944, 0x1945, 0x1a1e, 0x1a1f, 0x1aa0, 0x1aa1, 0x1aa2, 0x1aa3, 0x1aa4, 0x1aa5, 0x1aa6, 0x1aa8, 0x1aa9, + 0x1aaa, 0x1aab, 0x1aac, 0x1aad, 0x1b5a, 0x1b5b, 0x1b5c, 0x1b5d, 0x1b5e, 0x1b5f, 0x1b60, 0x1bfc, 0x1bfd, 0x1bfe, 0x1bff, 0x1c3b, + 0x1c3c, 0x1c3d, 0x1c3e, 0x1c3f, 0x1c7e, 0x1c7f, 0x1cc0, 0x1cc1, 0x1cc2, 0x1cc3, 0x1cc4, 0x1cc5, 0x1cc6, 0x1cc7, 0x1cd3, 0x2010, + 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2016, 0x2017, 0x2018, 0x2019, 0x201a, 0x201b, 0x201c, 0x201d, 0x201e, 0x201f, 0x2020, + 0x2021, 0x2022, 0x2023, 0x2024, 0x2025, 0x2026, 0x2027, 0x2030, 0x2031, 0x2032, 0x2033, 0x2034, 0x2035, 0x2036, 0x2037, 0x2038, + 0x2039, 0x203a, 0x203b, 0x203c, 0x203d, 0x203e, 0x203f, 0x2040, 0x2041, 0x2042, 0x2043, 0x2045, 0x2046, 0x2047, 0x2048, 0x2049, + 0x204a, 0x204b, 0x204c, 0x204d, 0x204e, 0x204f, 0x2050, 0x2051, 0x2053, 0x2054, 0x2055, 0x2056, 0x2057, 0x2058, 0x2059, 0x205a, + 0x205b, 0x205c, 0x205d, 0x205e, 0x207d, 0x207e, 0x208d, 0x208e, 0x2308, 0x2309, 0x230a, 0x230b, 0x2329, 0x232a, 0x2768, 0x2769, + 0x276a, 0x276b, 0x276c, 0x276d, 0x276e, 0x276f, 0x2770, 0x2771, 0x2772, 0x2773, 0x2774, 0x2775, 0x27c5, 0x27c6, 0x27e6, 0x27e7, + 0x27e8, 0x27e9, 0x27ea, 0x27eb, 0x27ec, 0x27ed, 0x27ee, 0x27ef, 0x2983, 0x2984, 0x2985, 0x2986, 0x2987, 0x2988, 0x2989, 0x298a, + 0x298b, 0x298c, 0x298d, 0x298e, 0x298f, 0x2990, 0x2991, 0x2992, 0x2993, 0x2994, 0x2995, 0x2996, 0x2997, 0x2998, 0x29d8, 0x29d9, + 0x29da, 0x29db, 0x29fc, 0x29fd, 0x2cf9, 0x2cfa, 0x2cfb, 0x2cfc, 0x2cfe, 0x2cff, 0x2d70, 0x2e00, 0x2e01, 0x2e02, 0x2e03, 0x2e04, + 0x2e05, 0x2e06, 0x2e07, 0x2e08, 0x2e09, 0x2e0a, 0x2e0b, 0x2e0c, 0x2e0d, 0x2e0e, 0x2e0f, 0x2e10, 0x2e11, 0x2e12, 0x2e13, 0x2e14, + 0x2e15, 0x2e16, 0x2e17, 0x2e18, 0x2e19, 0x2e1a, 0x2e1b, 0x2e1c, 0x2e1d, 0x2e1e, 0x2e1f, 0x2e20, 0x2e21, 0x2e22, 0x2e23, 0x2e24, + 0x2e25, 0x2e26, 0x2e27, 0x2e28, 0x2e29, 0x2e2a, 0x2e2b, 0x2e2c, 0x2e2d, 0x2e2e, 0x2e30, 0x2e31, 0x2e32, 0x2e33, 0x2e34, 0x2e35, + 0x2e36, 0x2e37, 0x2e38, 0x2e39, 0x2e3a, 0x2e3b, 0x2e3c, 0x2e3d, 0x2e3e, 0x2e3f, 0x2e40, 0x2e41, 0x2e42, 0x2e43, 0x2e44, 0x3001, + 0x3002, 0x3003, 0x3008, 0x3009, 0x300a, 0x300b, 0x300c, 0x300d, 0x300e, 0x300f, 0x3010, 0x3011, 0x3014, 0x3015, 0x3016, 0x3017, + 0x3018, 0x3019, 0x301a, 0x301b, 0x301c, 0x301d, 0x301e, 0x301f, 0x3030, 0x303d, 0x30a0, 0x30fb, 0xa4fe, 0xa4ff, 0xa60d, 0xa60e, + 0xa60f, 0xa673, 0xa67e, 0xa6f2, 0xa6f3, 0xa6f4, 0xa6f5, 0xa6f6, 0xa6f7, 0xa874, 0xa875, 0xa876, 0xa877, 0xa8ce, 0xa8cf, 0xa8f8, + 0xa8f9, 0xa8fa, 0xa8fc, 0xa92e, 0xa92f, 0xa95f, 0xa9c1, 0xa9c2, 0xa9c3, 0xa9c4, 0xa9c5, 0xa9c6, 0xa9c7, 0xa9c8, 0xa9c9, 0xa9ca, + 0xa9cb, 0xa9cc, 0xa9cd, 0xa9de, 0xa9df, 0xaa5c, 0xaa5d, 0xaa5e, 0xaa5f, 0xaade, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f, + 0xfe10, 0xfe11, 0xfe12, 0xfe13, 0xfe14, 0xfe15, 0xfe16, 0xfe17, 0xfe18, 0xfe19, 0xfe30, 0xfe31, 0xfe32, 0xfe33, 0xfe34, 0xfe35, + 0xfe36, 0xfe37, 0xfe38, 0xfe39, 0xfe3a, 0xfe3b, 0xfe3c, 0xfe3d, 0xfe3e, 0xfe3f, 0xfe40, 0xfe41, 0xfe42, 0xfe43, 0xfe44, 0xfe45, + 0xfe46, 0xfe47, 0xfe48, 0xfe49, 0xfe4a, 0xfe4b, 0xfe4c, 0xfe4d, 0xfe4e, 0xfe4f, 0xfe50, 0xfe51, 0xfe52, 0xfe54, 0xfe55, 0xfe56, + 0xfe57, 0xfe58, 0xfe59, 0xfe5a, 0xfe5b, 0xfe5c, 0xfe5d, 0xfe5e, 0xfe5f, 0xfe60, 0xfe61, 0xfe63, 0xfe68, 0xfe6a, 0xfe6b, 0xff01, + 0xff02, 0xff03, 0xff05, 0xff06, 0xff07, 0xff08, 0xff09, 0xff0a, 0xff0c, 0xff0d, 0xff0e, 0xff0f, 0xff1a, 0xff1b, 0xff1f, 0xff20, + 0xff3b, 0xff3c, 0xff3d, 0xff3f, 0xff5b, 0xff5d, 0xff5f, 0xff60, 0xff61, 0xff62, 0xff63, 0xff64, 0xff65, 0x10100, 0x10101, 0x10102, + 0x1039f, 0x103d0, 0x1056f, 0x10857, 0x1091f, 0x1093f, 0x10a50, 0x10a51, 0x10a52, 0x10a53, 0x10a54, 0x10a55, 0x10a56, 0x10a57, 0x10a58, 0x10a7f, + 0x10af0, 0x10af1, 0x10af2, 0x10af3, 0x10af4, 0x10af5, 0x10af6, 0x10b39, 0x10b3a, 0x10b3b, 0x10b3c, 0x10b3d, 0x10b3e, 0x10b3f, 0x10b99, 0x10b9a, + 0x10b9b, 0x10b9c, 0x11047, 0x11048, 0x11049, 0x1104a, 0x1104b, 0x1104c, 0x1104d, 0x110bb, 0x110bc, 0x110be, 0x110bf, 0x110c0, 0x110c1, 0x11140, + 0x11141, 0x11142, 0x11143, 0x11174, 0x11175, 0x111c5, 0x111c6, 0x111c7, 0x111c8, 0x111c9, 0x111cd, 0x111db, 0x111dd, 0x111de, 0x111df, 0x11238, + 0x11239, 0x1123a, 0x1123b, 0x1123c, 0x1123d, 0x112a9, 0x1144b, 0x1144c, 0x1144d, 0x1144e, 0x1144f, 0x1145b, 0x1145d, 0x114c6, 0x115c1, 0x115c2, + 0x115c3, 0x115c4, 0x115c5, 0x115c6, 0x115c7, 0x115c8, 0x115c9, 0x115ca, 0x115cb, 0x115cc, 0x115cd, 0x115ce, 0x115cf, 0x115d0, 0x115d1, 0x115d2, + 0x115d3, 0x115d4, 0x115d5, 0x115d6, 0x115d7, 0x11641, 0x11642, 0x11643, 0x11660, 0x11661, 0x11662, 0x11663, 0x11664, 0x11665, 0x11666, 0x11667, + 0x11668, 0x11669, 0x1166a, 0x1166b, 0x1166c, 0x1173c, 0x1173d, 0x1173e, 0x11c41, 0x11c42, 0x11c43, 0x11c44, 0x11c45, 0x11c70, 0x11c71, 0x12470, + 0x12471, 0x12472, 0x12473, 0x12474, 0x16a6e, 0x16a6f, 0x16af5, 0x16b37, 0x16b38, 0x16b39, 0x16b3a, 0x16b3b, 0x16b44, 0x1bc9f, 0x1da87, 0x1da88, + 0x1da89, 0x1da8a, 0x1da8b, 0x1e95e, 0x1e95f + }; + + /* The ASCII ones are the most frequently used ones, so lets check them first. */ + if(codepoint <= 0x7f) + return ISPUNCT_(codepoint); + + return (bsearch(&codepoint, punct_list, SIZEOF_ARRAY(punct_list), sizeof(int), md_unicode_cmp__) != NULL); + } + + static void + md_get_unicode_fold_info(int codepoint, MD_UNICODE_FOLD_INFO* info) + { + /* This maps single codepoint within a range to a single codepoint + * within an offseted range. */ + static const struct { + int min_codepoint; + int max_codepoint; + int offset; + } range_map[] = { + { 0x00c0, 0x00d6, 32 }, { 0x00d8, 0x00de, 32 }, { 0x0388, 0x038a, 37 }, { 0x0391, 0x03a1, 32 }, { 0x03a3, 0x03ab, 32 }, { 0x0400, 0x040f, 80 }, + { 0x0410, 0x042f, 32 }, { 0x0531, 0x0556, 48 }, { 0x1f08, 0x1f0f, -8 }, { 0x1f18, 0x1f1d, -8 }, { 0x1f28, 0x1f2f, -8 }, { 0x1f38, 0x1f3f, -8 }, + { 0x1f48, 0x1f4d, -8 }, { 0x1f68, 0x1f6f, -8 }, { 0x1fc8, 0x1fcb, -86 }, { 0x2160, 0x216f, 16 }, { 0x24b6, 0x24cf, 26 }, { 0xff21, 0xff3a, 32 }, + { 0x10400, 0x10425, 40 } + }; + + /* This maps single codepoint to another single codepoint. */ + static const struct { + int src_codepoint; + int dest_codepoint; + } single_map[] = { + { 0x00b5, 0x03bc }, { 0x0100, 0x0101 }, { 0x0102, 0x0103 }, { 0x0104, 0x0105 }, { 0x0106, 0x0107 }, { 0x0108, 0x0109 }, { 0x010a, 0x010b }, { 0x010c, 0x010d }, + { 0x010e, 0x010f }, { 0x0110, 0x0111 }, { 0x0112, 0x0113 }, { 0x0114, 0x0115 }, { 0x0116, 0x0117 }, { 0x0118, 0x0119 }, { 0x011a, 0x011b }, { 0x011c, 0x011d }, + { 0x011e, 0x011f }, { 0x0120, 0x0121 }, { 0x0122, 0x0123 }, { 0x0124, 0x0125 }, { 0x0126, 0x0127 }, { 0x0128, 0x0129 }, { 0x012a, 0x012b }, { 0x012c, 0x012d }, + { 0x012e, 0x012f }, { 0x0132, 0x0133 }, { 0x0134, 0x0135 }, { 0x0136, 0x0137 }, { 0x0139, 0x013a }, { 0x013b, 0x013c }, { 0x013d, 0x013e }, { 0x013f, 0x0140 }, + { 0x0141, 0x0142 }, { 0x0143, 0x0144 }, { 0x0145, 0x0146 }, { 0x0147, 0x0148 }, { 0x014a, 0x014b }, { 0x014c, 0x014d }, { 0x014e, 0x014f }, { 0x0150, 0x0151 }, + { 0x0152, 0x0153 }, { 0x0154, 0x0155 }, { 0x0156, 0x0157 }, { 0x0158, 0x0159 }, { 0x015a, 0x015b }, { 0x015c, 0x015d }, { 0x015e, 0x015f }, { 0x0160, 0x0161 }, + { 0x0162, 0x0163 }, { 0x0164, 0x0165 }, { 0x0166, 0x0167 }, { 0x0168, 0x0169 }, { 0x016a, 0x016b }, { 0x016c, 0x016d }, { 0x016e, 0x016f }, { 0x0170, 0x0171 }, + { 0x0172, 0x0173 }, { 0x0174, 0x0175 }, { 0x0176, 0x0177 }, { 0x0178, 0x00ff }, { 0x0179, 0x017a }, { 0x017b, 0x017c }, { 0x017d, 0x017e }, { 0x017f, 0x0073 }, + { 0x0181, 0x0253 }, { 0x0182, 0x0183 }, { 0x0184, 0x0185 }, { 0x0186, 0x0254 }, { 0x0187, 0x0188 }, { 0x0189, 0x0256 }, { 0x018a, 0x0257 }, { 0x018b, 0x018c }, + { 0x018e, 0x01dd }, { 0x018f, 0x0259 }, { 0x0190, 0x025b }, { 0x0191, 0x0192 }, { 0x0193, 0x0260 }, { 0x0194, 0x0263 }, { 0x0196, 0x0269 }, { 0x0197, 0x0268 }, + { 0x0198, 0x0199 }, { 0x019c, 0x026f }, { 0x019d, 0x0272 }, { 0x019f, 0x0275 }, { 0x01a0, 0x01a1 }, { 0x01a2, 0x01a3 }, { 0x01a4, 0x01a5 }, { 0x01a6, 0x0280 }, + { 0x01a7, 0x01a8 }, { 0x01a9, 0x0283 }, { 0x01ac, 0x01ad }, { 0x01ae, 0x0288 }, { 0x01af, 0x01b0 }, { 0x01b1, 0x028a }, { 0x01b2, 0x028b }, { 0x01b3, 0x01b4 }, + { 0x01b5, 0x01b6 }, { 0x01b7, 0x0292 }, { 0x01b8, 0x01b9 }, { 0x01bc, 0x01bd }, { 0x01c4, 0x01c6 }, { 0x01c5, 0x01c6 }, { 0x01c7, 0x01c9 }, { 0x01c8, 0x01c9 }, + { 0x01ca, 0x01cc }, { 0x01cb, 0x01cc }, { 0x01cd, 0x01ce }, { 0x01cf, 0x01d0 }, { 0x01d1, 0x01d2 }, { 0x01d3, 0x01d4 }, { 0x01d5, 0x01d6 }, { 0x01d7, 0x01d8 }, + { 0x01d9, 0x01da }, { 0x01db, 0x01dc }, { 0x01de, 0x01df }, { 0x01e0, 0x01e1 }, { 0x01e2, 0x01e3 }, { 0x01e4, 0x01e5 }, { 0x01e6, 0x01e7 }, { 0x01e8, 0x01e9 }, + { 0x01ea, 0x01eb }, { 0x01ec, 0x01ed }, { 0x01ee, 0x01ef }, { 0x01f1, 0x01f3 }, { 0x01f2, 0x01f3 }, { 0x01f4, 0x01f5 }, { 0x01f6, 0x0195 }, { 0x01f7, 0x01bf }, + { 0x01f8, 0x01f9 }, { 0x01fa, 0x01fb }, { 0x01fc, 0x01fd }, { 0x01fe, 0x01ff }, { 0x0200, 0x0201 }, { 0x0202, 0x0203 }, { 0x0204, 0x0205 }, { 0x0206, 0x0207 }, + { 0x0208, 0x0209 }, { 0x020a, 0x020b }, { 0x020c, 0x020d }, { 0x020e, 0x020f }, { 0x0210, 0x0211 }, { 0x0212, 0x0213 }, { 0x0214, 0x0215 }, { 0x0216, 0x0217 }, + { 0x0218, 0x0219 }, { 0x021a, 0x021b }, { 0x021c, 0x021d }, { 0x021e, 0x021f }, { 0x0220, 0x019e }, { 0x0222, 0x0223 }, { 0x0224, 0x0225 }, { 0x0226, 0x0227 }, + { 0x0228, 0x0229 }, { 0x022a, 0x022b }, { 0x022c, 0x022d }, { 0x022e, 0x022f }, { 0x0230, 0x0231 }, { 0x0232, 0x0233 }, { 0x0345, 0x03b9 }, { 0x0386, 0x03ac }, + { 0x038c, 0x03cc }, { 0x038e, 0x03cd }, { 0x038f, 0x03ce }, { 0x03c2, 0x03c3 }, { 0x03d0, 0x03b2 }, { 0x03d1, 0x03b8 }, { 0x03d5, 0x03c6 }, { 0x03d6, 0x03c0 }, + { 0x03d8, 0x03d9 }, { 0x03da, 0x03db }, { 0x03dc, 0x03dd }, { 0x03de, 0x03df }, { 0x03e0, 0x03e1 }, { 0x03e2, 0x03e3 }, { 0x03e4, 0x03e5 }, { 0x03e6, 0x03e7 }, + { 0x03e8, 0x03e9 }, { 0x03ea, 0x03eb }, { 0x03ec, 0x03ed }, { 0x03ee, 0x03ef }, { 0x03f0, 0x03ba }, { 0x03f1, 0x03c1 }, { 0x03f2, 0x03c3 }, { 0x03f4, 0x03b8 }, + { 0x03f5, 0x03b5 }, { 0x0460, 0x0461 }, { 0x0462, 0x0463 }, { 0x0464, 0x0465 }, { 0x0466, 0x0467 }, { 0x0468, 0x0469 }, { 0x046a, 0x046b }, { 0x046c, 0x046d }, + { 0x046e, 0x046f }, { 0x0470, 0x0471 }, { 0x0472, 0x0473 }, { 0x0474, 0x0475 }, { 0x0476, 0x0477 }, { 0x0478, 0x0479 }, { 0x047a, 0x047b }, { 0x047c, 0x047d }, + { 0x047e, 0x047f }, { 0x0480, 0x0481 }, { 0x048a, 0x048b }, { 0x048c, 0x048d }, { 0x048e, 0x048f }, { 0x0490, 0x0491 }, { 0x0492, 0x0493 }, { 0x0494, 0x0495 }, + { 0x0496, 0x0497 }, { 0x0498, 0x0499 }, { 0x049a, 0x049b }, { 0x049c, 0x049d }, { 0x049e, 0x049f }, { 0x04a0, 0x04a1 }, { 0x04a2, 0x04a3 }, { 0x04a4, 0x04a5 }, + { 0x04a6, 0x04a7 }, { 0x04a8, 0x04a9 }, { 0x04aa, 0x04ab }, { 0x04ac, 0x04ad }, { 0x04ae, 0x04af }, { 0x04b0, 0x04b1 }, { 0x04b2, 0x04b3 }, { 0x04b4, 0x04b5 }, + { 0x04b6, 0x04b7 }, { 0x04b8, 0x04b9 }, { 0x04ba, 0x04bb }, { 0x04bc, 0x04bd }, { 0x04be, 0x04bf }, { 0x04c1, 0x04c2 }, { 0x04c3, 0x04c4 }, { 0x04c5, 0x04c6 }, + { 0x04c7, 0x04c8 }, { 0x04c9, 0x04ca }, { 0x04cb, 0x04cc }, { 0x04cd, 0x04ce }, { 0x04d0, 0x04d1 }, { 0x04d2, 0x04d3 }, { 0x04d4, 0x04d5 }, { 0x04d6, 0x04d7 }, + { 0x04d8, 0x04d9 }, { 0x04da, 0x04db }, { 0x04dc, 0x04dd }, { 0x04de, 0x04df }, { 0x04e0, 0x04e1 }, { 0x04e2, 0x04e3 }, { 0x04e4, 0x04e5 }, { 0x04e6, 0x04e7 }, + { 0x04e8, 0x04e9 }, { 0x04ea, 0x04eb }, { 0x04ec, 0x04ed }, { 0x04ee, 0x04ef }, { 0x04f0, 0x04f1 }, { 0x04f2, 0x04f3 }, { 0x04f4, 0x04f5 }, { 0x04f8, 0x04f9 }, + { 0x0500, 0x0501 }, { 0x0502, 0x0503 }, { 0x0504, 0x0505 }, { 0x0506, 0x0507 }, { 0x0508, 0x0509 }, { 0x050a, 0x050b }, { 0x050c, 0x050d }, { 0x050e, 0x050f }, + { 0x1e00, 0x1e01 }, { 0x1e02, 0x1e03 }, { 0x1e04, 0x1e05 }, { 0x1e06, 0x1e07 }, { 0x1e08, 0x1e09 }, { 0x1e0a, 0x1e0b }, { 0x1e0c, 0x1e0d }, { 0x1e0e, 0x1e0f }, + { 0x1e10, 0x1e11 }, { 0x1e12, 0x1e13 }, { 0x1e14, 0x1e15 }, { 0x1e16, 0x1e17 }, { 0x1e18, 0x1e19 }, { 0x1e1a, 0x1e1b }, { 0x1e1c, 0x1e1d }, { 0x1e1e, 0x1e1f }, + { 0x1e20, 0x1e21 }, { 0x1e22, 0x1e23 }, { 0x1e24, 0x1e25 }, { 0x1e26, 0x1e27 }, { 0x1e28, 0x1e29 }, { 0x1e2a, 0x1e2b }, { 0x1e2c, 0x1e2d }, { 0x1e2e, 0x1e2f }, + { 0x1e30, 0x1e31 }, { 0x1e32, 0x1e33 }, { 0x1e34, 0x1e35 }, { 0x1e36, 0x1e37 }, { 0x1e38, 0x1e39 }, { 0x1e3a, 0x1e3b }, { 0x1e3c, 0x1e3d }, { 0x1e3e, 0x1e3f }, + { 0x1e40, 0x1e41 }, { 0x1e42, 0x1e43 }, { 0x1e44, 0x1e45 }, { 0x1e46, 0x1e47 }, { 0x1e48, 0x1e49 }, { 0x1e4a, 0x1e4b }, { 0x1e4c, 0x1e4d }, { 0x1e4e, 0x1e4f }, + { 0x1e50, 0x1e51 }, { 0x1e52, 0x1e53 }, { 0x1e54, 0x1e55 }, { 0x1e56, 0x1e57 }, { 0x1e58, 0x1e59 }, { 0x1e5a, 0x1e5b }, { 0x1e5c, 0x1e5d }, { 0x1e5e, 0x1e5f }, + { 0x1e60, 0x1e61 }, { 0x1e62, 0x1e63 }, { 0x1e64, 0x1e65 }, { 0x1e66, 0x1e67 }, { 0x1e68, 0x1e69 }, { 0x1e6a, 0x1e6b }, { 0x1e6c, 0x1e6d }, { 0x1e6e, 0x1e6f }, + { 0x1e70, 0x1e71 }, { 0x1e72, 0x1e73 }, { 0x1e74, 0x1e75 }, { 0x1e76, 0x1e77 }, { 0x1e78, 0x1e79 }, { 0x1e7a, 0x1e7b }, { 0x1e7c, 0x1e7d }, { 0x1e7e, 0x1e7f }, + { 0x1e80, 0x1e81 }, { 0x1e82, 0x1e83 }, { 0x1e84, 0x1e85 }, { 0x1e86, 0x1e87 }, { 0x1e88, 0x1e89 }, { 0x1e8a, 0x1e8b }, { 0x1e8c, 0x1e8d }, { 0x1e8e, 0x1e8f }, + { 0x1e90, 0x1e91 }, { 0x1e92, 0x1e93 }, { 0x1e94, 0x1e95 }, { 0x1e9b, 0x1e61 }, { 0x1ea0, 0x1ea1 }, { 0x1ea2, 0x1ea3 }, { 0x1ea4, 0x1ea5 }, { 0x1ea6, 0x1ea7 }, + { 0x1ea8, 0x1ea9 }, { 0x1eaa, 0x1eab }, { 0x1eac, 0x1ead }, { 0x1eae, 0x1eaf }, { 0x1eb0, 0x1eb1 }, { 0x1eb2, 0x1eb3 }, { 0x1eb4, 0x1eb5 }, { 0x1eb6, 0x1eb7 }, + { 0x1eb8, 0x1eb9 }, { 0x1eba, 0x1ebb }, { 0x1ebc, 0x1ebd }, { 0x1ebe, 0x1ebf }, { 0x1ec0, 0x1ec1 }, { 0x1ec2, 0x1ec3 }, { 0x1ec4, 0x1ec5 }, { 0x1ec6, 0x1ec7 }, + { 0x1ec8, 0x1ec9 }, { 0x1eca, 0x1ecb }, { 0x1ecc, 0x1ecd }, { 0x1ece, 0x1ecf }, { 0x1ed0, 0x1ed1 }, { 0x1ed2, 0x1ed3 }, { 0x1ed4, 0x1ed5 }, { 0x1ed6, 0x1ed7 }, + { 0x1ed8, 0x1ed9 }, { 0x1eda, 0x1edb }, { 0x1edc, 0x1edd }, { 0x1ede, 0x1edf }, { 0x1ee0, 0x1ee1 }, { 0x1ee2, 0x1ee3 }, { 0x1ee4, 0x1ee5 }, { 0x1ee6, 0x1ee7 }, + { 0x1ee8, 0x1ee9 }, { 0x1eea, 0x1eeb }, { 0x1eec, 0x1eed }, { 0x1eee, 0x1eef }, { 0x1ef0, 0x1ef1 }, { 0x1ef2, 0x1ef3 }, { 0x1ef4, 0x1ef5 }, { 0x1ef6, 0x1ef7 }, + { 0x1ef8, 0x1ef9 }, { 0x1f59, 0x1f51 }, { 0x1f5b, 0x1f53 }, { 0x1f5d, 0x1f55 }, { 0x1f5f, 0x1f57 }, { 0x1fb8, 0x1fb0 }, { 0x1fb9, 0x1fb1 }, { 0x1fba, 0x1f70 }, + { 0x1fbb, 0x1f71 }, { 0x1fbe, 0x03b9 }, { 0x1fd8, 0x1fd0 }, { 0x1fd9, 0x1fd1 }, { 0x1fda, 0x1f76 }, { 0x1fdb, 0x1f77 }, { 0x1fe8, 0x1fe0 }, { 0x1fe9, 0x1fe1 }, + { 0x1fea, 0x1f7a }, { 0x1feb, 0x1f7b }, { 0x1fec, 0x1fe5 }, { 0x1ff8, 0x1f78 }, { 0x1ff9, 0x1f79 }, { 0x1ffa, 0x1f7c }, { 0x1ffb, 0x1f7d }, { 0x2126, 0x03c9 }, + { 0x212a, 0x006b }, { 0x212b, 0x00e5 }, + }; + + /* This maps single codepoint to two codepoints. */ + static const struct { + int src_codepoint; + int dest_codepoint0; + int dest_codepoint1; + } double_map[] = { + { 0x00df, 0x0073, 0x0073 }, { 0x0130, 0x0069, 0x0307 }, { 0x0149, 0x02bc, 0x006e }, { 0x01f0, 0x006a, 0x030c }, { 0x0587, 0x0565, 0x0582 }, { 0x1e96, 0x0068, 0x0331 }, + { 0x1e97, 0x0074, 0x0308 }, { 0x1e98, 0x0077, 0x030a }, { 0x1e99, 0x0079, 0x030a }, { 0x1e9a, 0x0061, 0x02be }, { 0x1f50, 0x03c5, 0x0313 }, { 0x1f80, 0x1f00, 0x03b9 }, + { 0x1f81, 0x1f01, 0x03b9 }, { 0x1f82, 0x1f02, 0x03b9 }, { 0x1f83, 0x1f03, 0x03b9 }, { 0x1f84, 0x1f04, 0x03b9 }, { 0x1f85, 0x1f05, 0x03b9 }, { 0x1f86, 0x1f06, 0x03b9 }, + { 0x1f87, 0x1f07, 0x03b9 }, { 0x1f88, 0x1f00, 0x03b9 }, { 0x1f89, 0x1f01, 0x03b9 }, { 0x1f8a, 0x1f02, 0x03b9 }, { 0x1f8b, 0x1f03, 0x03b9 }, { 0x1f8c, 0x1f04, 0x03b9 }, + { 0x1f8d, 0x1f05, 0x03b9 }, { 0x1f8e, 0x1f06, 0x03b9 }, { 0x1f8f, 0x1f07, 0x03b9 }, { 0x1f90, 0x1f20, 0x03b9 }, { 0x1f91, 0x1f21, 0x03b9 }, { 0x1f92, 0x1f22, 0x03b9 }, + { 0x1f93, 0x1f23, 0x03b9 }, { 0x1f94, 0x1f24, 0x03b9 }, { 0x1f95, 0x1f25, 0x03b9 }, { 0x1f96, 0x1f26, 0x03b9 }, { 0x1f97, 0x1f27, 0x03b9 }, { 0x1f98, 0x1f20, 0x03b9 }, + { 0x1f99, 0x1f21, 0x03b9 }, { 0x1f9a, 0x1f22, 0x03b9 }, { 0x1f9b, 0x1f23, 0x03b9 }, { 0x1f9c, 0x1f24, 0x03b9 }, { 0x1f9d, 0x1f25, 0x03b9 }, { 0x1f9e, 0x1f26, 0x03b9 }, + { 0x1f9f, 0x1f27, 0x03b9 }, { 0x1fa0, 0x1f60, 0x03b9 }, { 0x1fa1, 0x1f61, 0x03b9 }, { 0x1fa2, 0x1f62, 0x03b9 }, { 0x1fa3, 0x1f63, 0x03b9 }, { 0x1fa4, 0x1f64, 0x03b9 }, + { 0x1fa5, 0x1f65, 0x03b9 }, { 0x1fa6, 0x1f66, 0x03b9 }, { 0x1fa7, 0x1f67, 0x03b9 }, { 0x1fa8, 0x1f60, 0x03b9 }, { 0x1fa9, 0x1f61, 0x03b9 }, { 0x1faa, 0x1f62, 0x03b9 }, + { 0x1fab, 0x1f63, 0x03b9 }, { 0x1fac, 0x1f64, 0x03b9 }, { 0x1fad, 0x1f65, 0x03b9 }, { 0x1fae, 0x1f66, 0x03b9 }, { 0x1faf, 0x1f67, 0x03b9 }, { 0x1fb2, 0x1f70, 0x03b9 }, + { 0x1fb3, 0x03b1, 0x03b9 }, { 0x1fb4, 0x03ac, 0x03b9 }, { 0x1fb6, 0x03b1, 0x0342 }, { 0x1fbc, 0x03b1, 0x03b9 }, { 0x1fc2, 0x1f74, 0x03b9 }, { 0x1fc3, 0x03b7, 0x03b9 }, + { 0x1fc4, 0x03ae, 0x03b9 }, { 0x1fc6, 0x03b7, 0x0342 }, { 0x1fcc, 0x03b7, 0x03b9 }, { 0x1fd6, 0x03b9, 0x0342 }, { 0x1fe4, 0x03c1, 0x0313 }, { 0x1fe6, 0x03c5, 0x0342 }, + { 0x1ff2, 0x1f7c, 0x03b9 }, { 0x1ff3, 0x03c9, 0x03b9 }, { 0x1ff4, 0x03ce, 0x03b9 }, { 0x1ff6, 0x03c9, 0x0342 }, { 0x1ffc, 0x03c9, 0x03b9 }, { 0xfb00, 0x0066, 0x0066 }, + { 0xfb01, 0x0066, 0x0069 }, { 0xfb02, 0x0066, 0x006c }, { 0xfb05, 0x0073, 0x0074 }, { 0xfb06, 0x0073, 0x0074 }, { 0xfb13, 0x0574, 0x0576 }, { 0xfb14, 0x0574, 0x0565 }, + { 0xfb15, 0x0574, 0x056b }, { 0xfb16, 0x057e, 0x0576 }, { 0xfb17, 0x0574, 0x056d } + }; + + /* This maps single codepoint to three codepoints. */ + static const struct { + int src_codepoint; + int dest_codepoint0; + int dest_codepoint1; + int dest_codepoint2; + } triple_map[] = { + { 0x0390, 0x03b9, 0x0308, 0x0301 }, { 0x03b0, 0x03c5, 0x0308, 0x0301 }, { 0x1f52, 0x03c5, 0x0313, 0x0300 }, { 0x1f54, 0x03c5, 0x0313, 0x0301 }, + { 0x1f56, 0x03c5, 0x0313, 0x0342 }, { 0x1fb7, 0x03b1, 0x0342, 0x03b9 }, { 0x1fc7, 0x03b7, 0x0342, 0x03b9 }, { 0x1fd2, 0x03b9, 0x0308, 0x0300 }, + { 0x1fd3, 0x03b9, 0x0308, 0x0301 }, { 0x1fd7, 0x03b9, 0x0308, 0x0342 }, { 0x1fe2, 0x03c5, 0x0308, 0x0300 }, { 0x1fe3, 0x03c5, 0x0308, 0x0301 }, + { 0x1fe7, 0x03c5, 0x0308, 0x0342 }, { 0x1ff7, 0x03c9, 0x0342, 0x03b9 }, { 0xfb03, 0x0066, 0x0066, 0x0069 }, { 0xfb04, 0x0066, 0x0066, 0x006c } + }; + + int i; + + /* Fast path for ASCII characters. */ + if(codepoint <= 0x7f) { + info->codepoints[0] = codepoint; + if(ISUPPER_(codepoint)) + info->codepoints[0] += 'a' - 'A'; + info->n_codepoints = 1; + return; + } + + for(i = 0; i < SIZEOF_ARRAY(range_map); i++) { + if(range_map[i].min_codepoint <= codepoint && codepoint <= range_map[i].max_codepoint) { + info->codepoints[0] = codepoint + range_map[i].offset; + info->n_codepoints = 1; + return; + } + } + + for(i = 0; i < SIZEOF_ARRAY(single_map); i++) { + if(codepoint == single_map[i].src_codepoint) { + info->codepoints[0] = single_map[i].dest_codepoint; + info->n_codepoints = 1; + return; + } + } + + for(i = 0; i < SIZEOF_ARRAY(double_map); i++) { + if(codepoint == double_map[i].src_codepoint) { + info->codepoints[0] = double_map[i].dest_codepoint0; + info->codepoints[1] = double_map[i].dest_codepoint1; + info->n_codepoints = 2; + return; + } + } + + for(i = 0; i < SIZEOF_ARRAY(triple_map); i++) { + if(codepoint == triple_map[i].src_codepoint) { + info->codepoints[0] = triple_map[i].dest_codepoint0; + info->codepoints[1] = triple_map[i].dest_codepoint1; + info->codepoints[2] = triple_map[i].dest_codepoint2; + info->n_codepoints = 3; + return; + } + } + + info->codepoints[0] = codepoint; + info->n_codepoints = 1; + } +#endif + + +#if defined MD4C_USE_UTF16 + #define IS_UTF16_SURROGATE_HI(word) (((WORD)(word) & 0xfc00) == 0xd800) + #define IS_UTF16_SURROGATE_LO(word) (((WORD)(word) & 0xfc00) == 0xdc00) + #define UTF16_DECODE_SURROGATE(hi, lo) (0x10000 + ((((unsigned)(hi) & 0x3ff) << 10) | (((unsigned)(lo) & 0x3ff) << 0))) + + static int + md_decode_utf16le__(const CHAR* str, SZ str_size, SZ* p_size) + { + if(IS_UTF16_SURROGATE_HI(str[0])) { + if(1 < str_size && IS_UTF16_SURROGATE_LO(str[1])) { + if(p_size != NULL) + *p_size = 2; + return UTF16_DECODE_SURROGATE(str[0], str[1]); + } + } + + if(p_size != NULL) + *p_size = 1; + return str[0]; + } + + static int + md_decode_utf16le_before__(MD_CTX* ctx, OFF off) + { + if(off > 2 && IS_UTF16_SURROGATE_HI(CH(off-2)) && IS_UTF16_SURROGATE_LO(CH(off-1))) + return UTF16_DECODE_SURROGATE(CH(off-2), CH(off-1)); + + return CH(off); + } + + /* No whitespace uses surrogates, so no decoding needed here. */ + #define ISUNICODEWHITESPACE_(codepoint) md_is_unicode_whitespace__(codepoint) + #define ISUNICODEWHITESPACE(off) md_is_unicode_whitespace__(CH(off)) + #define ISUNICODEWHITESPACEBEFORE(off) md_is_unicode_whitespace__(CH((off)-1)) + + #define ISUNICODEPUNCT(off) md_is_unicode_punct__(md_decode_utf16le__(STR(off), ctx->size - (off), NULL)) + #define ISUNICODEPUNCTBEFORE(off) md_is_unicode_punct__(md_decode_utf16le_before__(ctx, off)) + + static inline int + md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_char_size) + { + return md_decode_utf16le__(str+off, str_size-off, p_char_size); + } +#elif defined MD4C_USE_UTF8 + #define IS_UTF8_LEAD1(byte) ((unsigned char)(byte) <= 0x7f) + #define IS_UTF8_LEAD2(byte) (((unsigned char)(byte) & 0xe0) == 0xc0) + #define IS_UTF8_LEAD3(byte) (((unsigned char)(byte) & 0xf0) == 0xe0) + #define IS_UTF8_LEAD4(byte) (((unsigned char)(byte) & 0xf8) == 0xf0) + #define IS_UTF8_TAIL(byte) (((unsigned char)(byte) & 0xc0) == 0x80) + + static int + md_decode_utf8__(const CHAR* str, SZ str_size, SZ* p_size) + { + if(!IS_UTF8_LEAD1(str[0])) { + if(IS_UTF8_LEAD2(str[0])) { + if(1 < str_size && IS_UTF8_TAIL(str[1])) { + if(p_size != NULL) + *p_size = 2; + + return (((unsigned int)str[0] & 0x1f) << 6) | + (((unsigned int)str[1] & 0x3f) << 0); + } + } else if(IS_UTF8_LEAD3(str[0])) { + if(2 < str_size && IS_UTF8_TAIL(str[1]) && IS_UTF8_TAIL(str[2])) { + if(p_size != NULL) + *p_size = 3; + + return (((unsigned int)str[0] & 0x0f) << 12) | + (((unsigned int)str[1] & 0x3f) << 6) | + (((unsigned int)str[2] & 0x3f) << 0); + } + } else if(IS_UTF8_LEAD4(str[0])) { + if(3 < str_size && IS_UTF8_TAIL(str[1]) && IS_UTF8_TAIL(str[2]) && IS_UTF8_TAIL(str[3])) { + if(p_size != NULL) + *p_size = 4; + + return (((unsigned int)str[0] & 0x07) << 18) | + (((unsigned int)str[1] & 0x3f) << 12) | + (((unsigned int)str[2] & 0x3f) << 6) | + (((unsigned int)str[3] & 0x3f) << 0); + } + } + } + + if(p_size != NULL) + *p_size = 1; + return str[0]; + } + + static int + md_decode_utf8_before__(MD_CTX* ctx, OFF off) + { + if(!IS_UTF8_LEAD1(CH(off-1))) { + if(off > 1 && IS_UTF8_LEAD2(CH(off-2)) && IS_UTF8_TAIL(CH(off-1))) + return (((unsigned int)CH(off-2) & 0x1f) << 6) | + (((unsigned int)CH(off-1) & 0x3f) << 0); + + if(off > 2 && IS_UTF8_LEAD3(CH(off-3)) && IS_UTF8_TAIL(CH(off-2)) && IS_UTF8_TAIL(CH(off-1))) + return (((unsigned int)CH(off-3) & 0x0f) << 12) | + (((unsigned int)CH(off-2) & 0x3f) << 6) | + (((unsigned int)CH(off-1) & 0x3f) << 0); + + if(off > 3 && IS_UTF8_LEAD4(CH(off-4)) && IS_UTF8_TAIL(CH(off-3)) && IS_UTF8_TAIL(CH(off-2)) && IS_UTF8_TAIL(CH(off-1))) + return (((unsigned int)CH(off-4) & 0x07) << 18) | + (((unsigned int)CH(off-3) & 0x3f) << 12) | + (((unsigned int)CH(off-2) & 0x3f) << 6) | + (((unsigned int)CH(off-1) & 0x3f) << 0); + } + + return CH(off-1); + } + + #define ISUNICODEWHITESPACE_(codepoint) md_is_unicode_whitespace__(codepoint) + #define ISUNICODEWHITESPACE(off) md_is_unicode_whitespace__(md_decode_utf8__(STR(off), ctx->size - (off), NULL)) + #define ISUNICODEWHITESPACEBEFORE(off) md_is_unicode_whitespace__(md_decode_utf8_before__(ctx, off)) + + #define ISUNICODEPUNCT(off) md_is_unicode_punct__(md_decode_utf8__(STR(off), ctx->size - (off), NULL)) + #define ISUNICODEPUNCTBEFORE(off) md_is_unicode_punct__(md_decode_utf8_before__(ctx, off)) + + static inline int + md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_char_size) + { + return md_decode_utf8__(str+off, str_size-off, p_char_size); + } +#else + #define ISUNICODEWHITESPACE_(codepoint) ISWHITESPACE_(codepoint) + #define ISUNICODEWHITESPACE(off) ISWHITESPACE(off) + #define ISUNICODEWHITESPACEBEFORE(off) ISWHITESPACE((off)-1) + + #define ISUNICODEPUNCT(off) ISPUNCT(off) + #define ISUNICODEPUNCTBEFORE(off) ISPUNCT((off)-1) + + static inline void + md_get_unicode_fold_info(int codepoint, MD_UNICODE_FOLD_INFO* info) + { + info->codepoints[0] = codepoint; + if(ISUPPER_(codepoint)) + info->codepoints[0] += 'a' - 'A'; + info->n_codepoints = 1; + } + + static inline int + md_decode_unicode(const CHAR* str, OFF off, SZ str_size, SZ* p_size) + { + *p_size = 1; + return str[off]; + } +#endif + + +/************************************* + *** Helper string manipulations *** + *************************************/ + +/* Fill buffer with copy of the string between 'beg' and 'end' but replace any + * line breaks with given replacement character. + * + * NOTE: Caller is responsible to make sure the buffer is large enough. + * (Given the output is always shorter then input, (end - beg) is good idea + * what the caller should allocate.) + */ +static void +md_merge_lines(MD_CTX* ctx, OFF beg, OFF end, const MD_LINE* lines, int n_lines, + CHAR line_break_replacement_char, CHAR* buffer, SZ* p_size) +{ + CHAR* ptr = buffer; + int line_index = 0; + OFF off = beg; + + while(1) { + const MD_LINE* line = &lines[line_index]; + OFF line_end = line->end; + if(end < line_end) + line_end = end; + + while(off < line_end) { + *ptr = CH(off); + ptr++; + off++; + } + + if(off >= end) { + *p_size = ptr - buffer; + return; + } + + *ptr = line_break_replacement_char; + ptr++; + + line_index++; + off = lines[line_index].beg; + } +} + +/* Wrapper of md_merge_lines() which allocates new buffer for the output string. + */ +static int +md_merge_lines_alloc(MD_CTX* ctx, OFF beg, OFF end, const MD_LINE* lines, int n_lines, + CHAR line_break_replacement_char, CHAR** p_str, SZ* p_size) +{ + CHAR* buffer; + + buffer = (CHAR*) malloc(sizeof(CHAR) * (end - beg)); + if(buffer == NULL) { + MD_LOG("malloc() failed."); + return -1; + } + + md_merge_lines(ctx, beg, end, lines, n_lines, + line_break_replacement_char, buffer, p_size); + + *p_str = buffer; + return 0; +} + +static OFF +md_skip_unicode_whitespace(const CHAR* label, OFF off, SZ size) +{ + SZ char_size; + int codepoint; + + while(off < size) { + codepoint = md_decode_unicode(label, off, size, &char_size); + if(!ISUNICODEWHITESPACE_(codepoint) && !ISNEWLINE_(label[off])) + break; + off += char_size; + } + + return off; +} + + +/****************************** + *** Recognizing raw HTML *** + ******************************/ + +/* md_is_html_tag() may be called when processing inlines (inline raw HTML) + * or when breaking document to blocks (checking for start of HTML block type 7). + * + * When breaking document to blocks, we do not yet know line boundaries, but + * in that case the whole tag has to live on a single line. We distinguish this + * by n_lines == 0. + */ +static int +md_is_html_tag(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + int attr_state; + OFF off = beg; + OFF line_end = (n_lines > 0) ? lines[0].end : ctx->size; + int i = 0; + + MD_ASSERT(CH(beg) == _T('<')); + + if(off + 1 >= line_end) + return FALSE; + off++; + + /* For parsing attributes, we need a little state automaton below. + * State -1: no attributes are allowed. + * State 0: attribute could follow after some whitespace. + * State 1: after a whitespace (attribute name may follow). + * State 2: after attribute name ('=' MAY follow). + * State 3: after '=' (value specification MUST follow). + * State 41: in middle of unquoted attribute value. + * State 42: in middle of single-quoted attribute value. + * State 43: in middle of double-quoted attribute value. + */ + attr_state = 0; + + if(CH(off) == _T('/')) { + /* Closer tag "". No attributes may be present. */ + attr_state = -1; + off++; + } + + /* Tag name */ + if(off >= line_end || !ISALPHA(off)) + return FALSE; + off++; + while(off < line_end && (ISALNUM(off) || CH(off) == _T('-'))) + off++; + + /* (Optional) attributes (if not closer), (optional) '/' (if not closer) + * and final '>'. */ + while(1) { + while(off < line_end && !ISNEWLINE(off)) { + if(attr_state > 40) { + if(attr_state == 41 && (ISBLANK(off) || ISANYOF(off, _T("\"'=<>`")))) { + attr_state = 0; + off--; /* Put the char back for re-inspection in the new state. */ + } else if(attr_state == 42 && CH(off) == _T('\'')) { + attr_state = 0; + } else if(attr_state == 43 && CH(off) == _T('"')) { + attr_state = 0; + } + off++; + } else if(ISWHITESPACE(off)) { + if(attr_state == 0) + attr_state = 1; + off++; + } else if(attr_state <= 2 && CH(off) == _T('>')) { + /* End. */ + goto done; + } else if(attr_state <= 2 && CH(off) == _T('/') && off+1 < line_end && CH(off+1) == _T('>')) { + /* End with digraph '/>' */ + off++; + goto done; + } else if((attr_state == 1 || attr_state == 2) && (ISALPHA(off) || CH(off) == _T('_') || CH(off) == _T(':'))) { + off++; + /* Attribute name */ + while(off < line_end && (ISALNUM(off) || ISANYOF(off, _T("_.:-")))) + off++; + attr_state = 2; + } else if(attr_state == 2 && CH(off) == _T('=')) { + /* Attribute assignment sign */ + off++; + attr_state = 3; + } else if(attr_state == 3) { + /* Expecting start of attribute value. */ + if(CH(off) == _T('"')) + attr_state = 43; + else if(CH(off) == _T('\'')) + attr_state = 42; + else if(!ISANYOF(off, _T("\"'=<>`")) && !ISNEWLINE(off)) + attr_state = 41; + else + return FALSE; + off++; + } else { + /* Anything unexpected. */ + return FALSE; + } + } + + /* We have to be on a single line. See definition of start condition + * of HTML block, type 7. */ + if(n_lines == 0) + return FALSE; + + i++; + if(i >= n_lines) + return FALSE; + + off = lines[i].beg; + line_end = lines[i].end; + + if(attr_state == 0 || attr_state == 41) + attr_state = 1; + + if(off >= max_end) + return FALSE; + } + +done: + if(off >= max_end) + return FALSE; + + *p_end = off+1; + return TRUE; +} + +static int +md_is_html_comment(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + int i = 0; + + MD_ASSERT(CH(beg) == _T('<')); + + if(off + 4 >= lines[0].end) + return FALSE; + if(CH(off+1) != _T('!') || CH(off+2) != _T('-') || CH(off+3) != _T('-')) + return FALSE; + off += 4; + + /* ">" and "->" must follow the opening. */ + if(off < lines[0].end && CH(off) == _T('>')) + return FALSE; + if(off+1 < lines[0].end && CH(off) == _T('-') && CH(off+1) == _T('>')) + return FALSE; + + while(1) { + while(off + 2 < lines[i].end) { + if(CH(off) == _T('-') && CH(off+1) == _T('-')) { + if(CH(off+2) == _T('>')) { + /* Success. */ + off += 2; + goto done; + } else { + /* "--" is prohibited inside the comment. */ + return FALSE; + } + } + + off++; + } + + i++; + if(i >= n_lines) + return FALSE; + + off = lines[i].beg; + + if(off >= max_end) + return FALSE; + } + +done: + if(off >= max_end) + return FALSE; + + *p_end = off+1; + return TRUE; +} + +static int +md_is_html_processing_instruction(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + int i = 0; + + MD_ASSERT(CH(beg) == _T('<')); + + if(off + 2 >= lines[0].end) + return FALSE; + if(CH(off+1) != _T('?')) + return FALSE; + off += 2; + + while(1) { + while(off + 1 < lines[i].end) { + if(CH(off) == _T('?') && CH(off+1) == _T('>')) { + /* Success. */ + off++; + goto done; + } + + off++; + } + + i++; + if(i >= n_lines) + return FALSE; + + off = lines[i].beg; + if(off >= max_end) + return FALSE; + } + +done: + if(off >= max_end) + return FALSE; + + *p_end = off+1; + return TRUE; +} + +static int +md_is_html_declaration(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + int i = 0; + + MD_ASSERT(CH(beg) == _T('<')); + + if(off + 2 >= lines[0].end) + return FALSE; + if(CH(off+1) != _T('!')) + return FALSE; + off += 2; + + /* Declaration name. */ + if(off >= lines[0].end || !ISALPHA(off)) + return FALSE; + off++; + while(off < lines[0].end && ISALPHA(off)) + off++; + if(off < lines[0].end && !ISWHITESPACE(off)) + return FALSE; + + while(1) { + while(off < lines[i].end) { + if(CH(off) == _T('>')) { + /* Success. */ + goto done; + } + + off++; + } + + i++; + if(i >= n_lines) + return FALSE; + + off = lines[i].beg; + if(off >= max_end) + return FALSE; + } + +done: + if(off >= max_end) + return FALSE; + + *p_end = off+1; + return TRUE; +} + +static int +md_is_html_cdata(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + static const CHAR open_str[] = _T("= lines[0].end) + return FALSE; + if(memcmp(STR(off), open_str, open_size) != 0) + return FALSE; + off += open_size; + + while(1) { + while(off + 2 < lines[i].end) { + if(CH(off) == _T(']') && CH(off+1) == _T(']') && CH(off+2) == _T('>')) { + /* Success. */ + off += 2; + goto done; + } + + off++; + } + + i++; + if(i >= n_lines) + return FALSE; + + off = lines[i].beg; + if(off >= max_end) + return FALSE; + } + +done: + if(off >= max_end) + return FALSE; + + *p_end = off+1; + return TRUE; +} + +static int +md_is_html_any(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_end, OFF* p_end) +{ + if(md_is_html_tag(ctx, lines, n_lines, beg, max_end, p_end) == TRUE) + return TRUE; + if(md_is_html_comment(ctx, lines, n_lines, beg, max_end, p_end) == TRUE) + return TRUE; + if(md_is_html_processing_instruction(ctx, lines, n_lines, beg, max_end, p_end) == TRUE) + return TRUE; + if(md_is_html_declaration(ctx, lines, n_lines, beg, max_end, p_end) == TRUE) + return TRUE; + if(md_is_html_cdata(ctx, lines, n_lines, beg, max_end, p_end) == TRUE) + return TRUE; + + return FALSE; +} + + +/**************************** + *** Recognizing Entity *** + ****************************/ + +static int +md_is_hex_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + + while(off < max_end && ISXDIGIT_(text[off]) && off - beg <= 8) + off++; + + if(1 <= off - beg && off - beg <= 8) { + *p_end = off; + return TRUE; + } else { + return FALSE; + } +} + +static int +md_is_dec_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + + while(off < max_end && ISDIGIT_(text[off]) && off - beg <= 8) + off++; + + if(1 <= off - beg && off - beg <= 8) { + *p_end = off; + return TRUE; + } else { + return FALSE; + } +} + +static int +md_is_named_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + OFF off = beg; + + if(off < max_end && ISALPHA_(text[off])) + off++; + else + return FALSE; + + while(off < max_end && ISALNUM_(text[off]) && off - beg <= 48) + off++; + + if(2 <= off - beg && off - beg <= 48) { + *p_end = off; + return TRUE; + } else { + return FALSE; + } +} + +static int +md_is_entity_str(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) +{ + int is_contents; + OFF off = beg; + + MD_ASSERT(text[off] == _T('&')); + off++; + + if(off+2 < max_end && text[off] == _T('#') && (text[off+1] == _T('x') || text[off+1] == _T('X'))) + is_contents = md_is_hex_entity_contents(ctx, text, off+2, max_end, &off); + else if(off+1 < max_end && text[off] == _T('#')) + is_contents = md_is_dec_entity_contents(ctx, text, off+1, max_end, &off); + else + is_contents = md_is_named_entity_contents(ctx, text, off, max_end, &off); + + if(is_contents && off < max_end && text[off] == _T(';')) { + *p_end = off+1; + return TRUE; + } else { + return FALSE; + } +} + +static inline int +md_is_entity(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end) +{ + return md_is_entity_str(ctx, ctx->text, beg, max_end, p_end); +} + + +/****************************** + *** Attribute Management *** + ******************************/ + +typedef struct MD_ATTRIBUTE_BUILD_tag MD_ATTRIBUTE_BUILD; +struct MD_ATTRIBUTE_BUILD_tag { + CHAR* text; + MD_TEXTTYPE* substr_types; + OFF* substr_offsets; + int substr_count; + int substr_alloc; + MD_TEXTTYPE trivial_types[1]; + OFF trivial_offsets[2]; +}; + + +#define MD_BUILD_ATTR_NO_ESCAPES 0x0001 + +static int +md_build_attr_append_substr(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build, + MD_TEXTTYPE type, OFF off) +{ + if(build->substr_count >= build->substr_alloc) { + MD_TEXTTYPE* new_substr_types; + OFF* new_substr_offsets; + + build->substr_alloc = (build->substr_alloc == 0 ? 8 : build->substr_alloc * 2); + + new_substr_types = (MD_TEXTTYPE*) realloc(build->substr_types, + build->substr_alloc * sizeof(MD_TEXTTYPE)); + if(new_substr_types == NULL) { + MD_LOG("realloc() failed."); + return -1; + } + /* Note +1 to reserve space for final offset (== raw_size). */ + new_substr_offsets = (OFF*) realloc(build->substr_offsets, + (build->substr_alloc+1) * sizeof(OFF)); + if(new_substr_offsets == NULL) { + MD_LOG("realloc() failed."); + free(new_substr_types); + return -1; + } + + build->substr_types = new_substr_types; + build->substr_offsets = new_substr_offsets; + } + + build->substr_types[build->substr_count] = type; + build->substr_offsets[build->substr_count] = off; + build->substr_count++; + return 0; +} + +static void +md_free_attribute(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build) +{ + if(build->substr_alloc > 0) { + free(build->text); + free(build->substr_types); + free(build->substr_offsets); + } +} + +static int +md_build_attribute(MD_CTX* ctx, const CHAR* raw_text, SZ raw_size, + unsigned flags, MD_ATTRIBUTE* attr, MD_ATTRIBUTE_BUILD* build) +{ + OFF raw_off, off; + int is_trivial; + int ret = 0; + + memset(build, 0, sizeof(MD_ATTRIBUTE_BUILD)); + + /* If there is no backslash and no ampersand, build trivial attribute + * without any malloc(). */ + is_trivial = TRUE; + for(raw_off = 0; raw_off < raw_size; raw_off++) { + if(ISANYOF3_(raw_text[raw_off], _T('\\'), _T('&'), _T('\0'))) { + is_trivial = FALSE; + break; + } + } + + if(is_trivial) { + build->text = (CHAR*) (raw_size ? raw_text : NULL); + build->substr_types = build->trivial_types; + build->substr_offsets = build->trivial_offsets; + build->substr_count = 1; + build->substr_alloc = 0; + build->trivial_types[0] = MD_TEXT_NORMAL; + build->trivial_offsets[0] = 0; + build->trivial_offsets[1] = raw_size; + off = raw_size; + } else { + build->text = (CHAR*) malloc(raw_size * sizeof(CHAR)); + if(build->text == NULL) { + MD_LOG("malloc() failed."); + goto abort; + } + + raw_off = 0; + off = 0; + + while(raw_off < raw_size) { + if(raw_text[raw_off] == _T('\0')) { + MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_NULLCHAR, off)); + memcpy(build->text + off, raw_text + raw_off, 1); + off++; + raw_off++; + continue; + } + + if(raw_text[raw_off] == _T('&')) { + OFF ent_end; + + if(md_is_entity_str(ctx, raw_text, raw_off, raw_size, &ent_end)) { + MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_ENTITY, off)); + memcpy(build->text + off, raw_text + raw_off, ent_end - raw_off); + off += ent_end - raw_off; + raw_off = ent_end; + continue; + } + } + + if(build->substr_count == 0 || build->substr_types[build->substr_count-1] != MD_TEXT_NORMAL) + MD_CHECK(md_build_attr_append_substr(ctx, build, MD_TEXT_NORMAL, off)); + + if(!(flags & MD_BUILD_ATTR_NO_ESCAPES) && + raw_text[raw_off] == _T('\\') && raw_off+1 < raw_size && + (ISPUNCT_(raw_text[raw_off+1]) || ISNEWLINE_(raw_text[raw_off+1]))) + raw_off++; + + build->text[off++] = raw_text[raw_off++]; + } + build->substr_offsets[build->substr_count] = off; + } + + attr->text = build->text; + attr->size = off; + attr->substr_offsets = build->substr_offsets; + attr->substr_types = build->substr_types; + return 0; + +abort: + md_free_attribute(ctx, build); + return -1; +} + + +/********************************************* + *** Dictionary of Reference Definitions *** + *********************************************/ + +#define MD_FNV1A_BASE 2166136261 +#define MD_FNV1A_PRIME 16777619 + +static inline unsigned +md_fnv1a(unsigned base, const void* data, size_t n) +{ + const unsigned char* buf = (const unsigned char*) data; + unsigned hash = base; + size_t i; + + for(i = 0; i < n; i++) { + hash ^= buf[i]; + hash *= MD_FNV1A_PRIME; + } + + return hash; +} + + +struct MD_REF_DEF_tag { + CHAR* label; + CHAR* title; + unsigned hash; + SZ label_size : 24; + unsigned label_needs_free : 1; + unsigned title_needs_free : 1; + SZ title_size; + OFF dest_beg; + OFF dest_end; +}; + +/* Label equivalence is quite complicated with regards to whitespace and case + * folding. This complicates computing a hash of it as well as direct comparison + * of two labels. */ + +static unsigned +md_link_label_hash(const CHAR* label, SZ size) +{ + unsigned hash = MD_FNV1A_BASE; + OFF off; + int codepoint; + int is_whitespace = FALSE; + + off = md_skip_unicode_whitespace(label, 0, size); + while(off < size) { + SZ char_size; + + codepoint = md_decode_unicode(label, off, size, &char_size); + is_whitespace = ISUNICODEWHITESPACE_(codepoint) || ISNEWLINE_(label[off]); + + if(is_whitespace) { + codepoint = ' '; + hash = md_fnv1a(hash, &codepoint, 1 * sizeof(int)); + + off = md_skip_unicode_whitespace(label, off, size); + } else { + MD_UNICODE_FOLD_INFO fold_info; + + md_get_unicode_fold_info(codepoint, &fold_info); + hash = md_fnv1a(hash, fold_info.codepoints, fold_info.n_codepoints * sizeof(int)); + + off += char_size; + } + } + + if(!is_whitespace) { + codepoint = ' '; + hash = md_fnv1a(hash, &codepoint, 1 * sizeof(int)); + } + + return hash; +} + +static int +md_link_label_cmp(const CHAR* a_label, SZ a_size, const CHAR* b_label, SZ b_size) +{ + OFF a_off; + OFF b_off; + + /* The slow path, with Unicode case folding and Unicode whitespace collapsing. */ + a_off = md_skip_unicode_whitespace(a_label, 0, a_size); + b_off = md_skip_unicode_whitespace(b_label, 0, b_size); + while(a_off < a_size || b_off < b_size) { + int a_codepoint, b_codepoint; + SZ a_char_size, b_char_size; + int a_is_whitespace, b_is_whitespace; + + if(a_off < a_size) { + a_codepoint = md_decode_unicode(a_label, a_off, a_size, &a_char_size); + a_is_whitespace = ISUNICODEWHITESPACE_(a_codepoint) || ISNEWLINE_(a_label[a_off]); + } else { + /* Treat end of label as a whitespace. */ + a_codepoint = -1; + a_is_whitespace = TRUE; + } + + if(b_off < b_size) { + b_codepoint = md_decode_unicode(b_label, b_off, b_size, &b_char_size); + b_is_whitespace = ISUNICODEWHITESPACE_(b_codepoint) || ISNEWLINE_(b_label[b_off]); + } else { + /* Treat end of label as a whitespace. */ + b_codepoint = -1; + b_is_whitespace = TRUE; + } + + if(a_is_whitespace || b_is_whitespace) { + if(!a_is_whitespace || !b_is_whitespace) + return (a_is_whitespace ? -1 : +1); + + a_off = md_skip_unicode_whitespace(a_label, a_off, a_size); + b_off = md_skip_unicode_whitespace(b_label, b_off, b_size); + } else { + MD_UNICODE_FOLD_INFO a_fold_info, b_fold_info; + int cmp; + + md_get_unicode_fold_info(a_codepoint, &a_fold_info); + md_get_unicode_fold_info(b_codepoint, &b_fold_info); + + if(a_fold_info.n_codepoints != b_fold_info.n_codepoints) + return (a_fold_info.n_codepoints - b_fold_info.n_codepoints); + cmp = memcmp(a_fold_info.codepoints, b_fold_info.codepoints, a_fold_info.n_codepoints * sizeof(int)); + if(cmp != 0) + return cmp; + + a_off += a_char_size; + b_off += b_char_size; + } + } + + return 0; +} + +typedef struct MD_REF_DEF_LIST_tag MD_REF_DEF_LIST; +struct MD_REF_DEF_LIST_tag { + int n_ref_defs; + int alloc_ref_defs; + MD_REF_DEF* ref_defs[]; /* Valid items always point into ctx->ref_defs[] */ +}; + +static int +md_ref_def_cmp(const void* a, const void* b) +{ + const MD_REF_DEF* a_ref = *(const MD_REF_DEF**)a; + const MD_REF_DEF* b_ref = *(const MD_REF_DEF**)b; + + if(a_ref->hash < b_ref->hash) + return -1; + else if(a_ref->hash > b_ref->hash) + return +1; + else + return md_link_label_cmp(a_ref->label, a_ref->label_size, b_ref->label, b_ref->label_size); +} + +static int +md_ref_def_cmp_stable(const void* a, const void* b) +{ + int cmp; + + cmp = md_ref_def_cmp(a, b); + + /* Ensure stability of the sorting. */ + if(cmp == 0) { + const MD_REF_DEF* a_ref = *(const MD_REF_DEF**)a; + const MD_REF_DEF* b_ref = *(const MD_REF_DEF**)b; + + if(a_ref < b_ref) + cmp = -1; + else if(a_ref > b_ref) + cmp = +1; + else + cmp = 0; + } + + return cmp; +} + +static int +md_build_ref_def_hashtable(MD_CTX* ctx) +{ + int i, j; + + if(ctx->n_ref_defs == 0) + return 0; + + ctx->ref_def_hashtable_size = (ctx->n_ref_defs * 5) / 4; + ctx->ref_def_hashtable = malloc(ctx->ref_def_hashtable_size * sizeof(void*)); + if(ctx->ref_def_hashtable == NULL) { + MD_LOG("malloc() failed."); + goto abort; + } + memset(ctx->ref_def_hashtable, 0, ctx->ref_def_hashtable_size * sizeof(void*)); + + /* Each member of ctx->ref_def_hashtable[] can be: + * -- NULL, + * -- pointer to the MD_REF_DEF in ctx->ref_defs[], or + * -- pointer to a MD_REF_DEF_LIST, which holds multiple pointers to + * such MD_REF_DEFs. + */ + for(i = 0; i < ctx->n_ref_defs; i++) { + MD_REF_DEF* def = &ctx->ref_defs[i]; + void* bucket; + MD_REF_DEF_LIST* list; + + def->hash = md_link_label_hash(def->label, def->label_size); + bucket = ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size]; + + if(bucket == NULL) { + ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = def; + continue; + } + + if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs) { + /* The bucket already contains one ref. def. Lets see whether it + * is the same label (ref. def. duplicate) or different one + * (hash conflict). */ + MD_REF_DEF* old_def = (MD_REF_DEF*) bucket; + + if(md_link_label_cmp(def->label, def->label_size, old_def->label, old_def->label_size) == 0) { + /* Ignore this ref. def. */ + continue; + } + + /* Make the bucket capable of holding more ref. defs. */ + list = (MD_REF_DEF_LIST*) malloc(sizeof(MD_REF_DEF_LIST) + 4 * sizeof(MD_REF_DEF)); + if(list == NULL) { + MD_LOG("malloc() failed."); + goto abort; + } + list->ref_defs[0] = old_def; + list->ref_defs[1] = def; + list->n_ref_defs = 2; + list->alloc_ref_defs = 4; + ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = list; + continue; + } + + /* Append the def to the bucket list. */ + list = (MD_REF_DEF_LIST*) bucket; + if(list->n_ref_defs >= list->alloc_ref_defs) { + MD_REF_DEF_LIST* list_tmp = (MD_REF_DEF_LIST*) realloc(list, + sizeof(MD_REF_DEF_LIST) + 2 * list->alloc_ref_defs * sizeof(MD_REF_DEF)); + if(list_tmp == NULL) { + MD_LOG("realloc() failed."); + goto abort; + } + list = list_tmp; + list->alloc_ref_defs *= 2; + ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = list; + } + + list->ref_defs[list->n_ref_defs] = def; + list->n_ref_defs++; + } + + /* Sort the complex buckets so we can use bsearch() with them. */ + for(i = 0; i < ctx->ref_def_hashtable_size; i++) { + void* bucket = ctx->ref_def_hashtable[i]; + MD_REF_DEF_LIST* list; + + if(bucket == NULL) + continue; + if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs) + continue; + + list = (MD_REF_DEF_LIST*) bucket; + qsort(list->ref_defs, list->n_ref_defs, sizeof(MD_REF_DEF*), md_ref_def_cmp_stable); + + /* Disable duplicates. */ + for(j = 1; j < list->n_ref_defs; j++) { + if(md_ref_def_cmp(&list->ref_defs[j-1], &list->ref_defs[j]) == 0) + list->ref_defs[j] = list->ref_defs[j-1]; + } + } + + return 0; + +abort: + return -1; +} + +static void +md_free_ref_def_hashtable(MD_CTX* ctx) +{ + if(ctx->ref_def_hashtable != NULL) { + int i; + + for(i = 0; i < ctx->ref_def_hashtable_size; i++) { + void* bucket = ctx->ref_def_hashtable[i]; + if(bucket == NULL) + continue; + if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs) + continue; + free(bucket); + } + + free(ctx->ref_def_hashtable); + } +} + +static const MD_REF_DEF* +md_lookup_ref_def(MD_CTX* ctx, const CHAR* label, SZ label_size) +{ + unsigned hash; + void* bucket; + + if(ctx->ref_def_hashtable_size == 0) + return NULL; + + hash = md_link_label_hash(label, label_size); + bucket = ctx->ref_def_hashtable[hash % ctx->ref_def_hashtable_size]; + + if(bucket == NULL) { + return NULL; + } else if(ctx->ref_defs <= (MD_REF_DEF*) bucket && (MD_REF_DEF*) bucket < ctx->ref_defs + ctx->n_ref_defs) { + const MD_REF_DEF* def = (MD_REF_DEF*) bucket; + + if(md_link_label_cmp(def->label, def->label_size, label, label_size) == 0) + return def; + else + return NULL; + } else { + MD_REF_DEF_LIST* list = (MD_REF_DEF_LIST*) bucket; + MD_REF_DEF key_buf; + const MD_REF_DEF* key = &key_buf; + const MD_REF_DEF** ret; + + key_buf.label = (CHAR*) label; + key_buf.label_size = label_size; + key_buf.hash = md_link_label_hash(key_buf.label, key_buf.label_size); + + ret = (const MD_REF_DEF**) bsearch(&key, list->ref_defs, + list->n_ref_defs, sizeof(MD_REF_DEF*), md_ref_def_cmp); + if(ret != NULL) + return *ret; + else + return NULL; + } +} + + +/*************************** + *** Recognizing Links *** + ***************************/ + +/* Note this code is partially shared between processing inlines and blocks + * as reference definitions and links share some helper parser functions. + */ + +typedef struct MD_LINK_ATTR_tag MD_LINK_ATTR; +struct MD_LINK_ATTR_tag { + OFF dest_beg; + OFF dest_end; + + CHAR* title; + SZ title_size; + int title_needs_free; +}; + + +static int +md_is_link_label(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, + OFF* p_end, int* p_beg_line_index, int* p_end_line_index, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + OFF contents_beg = 0; + OFF contents_end = 0; + int line_index = 0; + int len = 0; + + if(CH(off) != _T('[')) + return FALSE; + off++; + + while(1) { + OFF line_end = lines[line_index].end; + + while(off < line_end) { + if(CH(off) == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) { + if(contents_end == 0) { + contents_beg = off; + *p_beg_line_index = line_index; + } + contents_end = off + 2; + off += 2; + } else if(CH(off) == _T('[')) { + return FALSE; + } else if(CH(off) == _T(']')) { + if(contents_beg < contents_end) { + /* Success. */ + *p_contents_beg = contents_beg; + *p_contents_end = contents_end; + *p_end = off+1; + *p_end_line_index = line_index; + return TRUE; + } else { + /* Link label must have some non-whitespace contents. */ + return FALSE; + } + } else { + int codepoint; + SZ char_size; + + codepoint = md_decode_unicode(ctx->text, off, ctx->size, &char_size); + if(!ISUNICODEWHITESPACE_(codepoint)) { + if(contents_end == 0) { + contents_beg = off; + *p_beg_line_index = line_index; + } + contents_end = off + char_size; + } + + off += char_size; + } + + len++; + if(len > 999) + return FALSE; + } + + line_index++; + len++; + if(line_index < n_lines) + off = lines[line_index].beg; + else + break; + } + + return FALSE; +} + +static int +md_is_link_destination_A(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + + if(off >= max_end || CH(off) != _T('<')) + return FALSE; + off++; + + while(off < max_end) { + if(CH(off) == _T('\\') && off+1 < max_end && ISPUNCT(off+1)) { + off += 2; + continue; + } + + if(ISWHITESPACE(off) || CH(off) == _T('<')) + return FALSE; + + if(CH(off) == _T('>')) { + /* Success. */ + *p_contents_beg = beg+1; + *p_contents_end = off; + *p_end = off+1; + return TRUE; + } + + off++; + } + + return FALSE; +} + +static int +md_is_link_destination_B(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + int parenthesis_level = 0; + + while(off < max_end) { + if(CH(off) == _T('\\') && off+1 < max_end && ISPUNCT(off+1)) { + off += 2; + continue; + } + + if(ISWHITESPACE(off) || ISCNTRL(off)) + break; + + /* Link destination may include balanced pairs of unescaped '(' ')'. + * Note we limit the maximal nesting level by 32 to protect us from + * https://github.com/jgm/cmark/issues/214 */ + if(CH(off) == _T('(')) { + parenthesis_level++; + if(parenthesis_level > 32) + return FALSE; + } else if(CH(off) == _T(')')) { + if(parenthesis_level == 0) + break; + parenthesis_level--; + } + + off++; + } + + if(parenthesis_level != 0 || off == beg) + return FALSE; + + /* Success. */ + *p_contents_beg = beg; + *p_contents_end = off; + *p_end = off; + return TRUE; +} + +static int +md_is_link_title(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, + OFF* p_end, int* p_beg_line_index, int* p_end_line_index, + OFF* p_contents_beg, OFF* p_contents_end) +{ + OFF off = beg; + CHAR closer_char; + int line_index = 0; + + /* Optional white space with up to one line break. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end) { + line_index++; + if(line_index >= n_lines) + return FALSE; + off = lines[line_index].beg; + } + + *p_beg_line_index = line_index; + + /* First char determines how to detect end of it. */ + switch(CH(off)) { + case _T('"'): closer_char = _T('"'); break; + case _T('\''): closer_char = _T('\''); break; + case _T('('): closer_char = _T(')'); break; + default: return FALSE; + } + off++; + + *p_contents_beg = off; + + while(line_index < n_lines) { + OFF line_end = lines[line_index].end; + + while(off < line_end) { + if(CH(off) == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) { + off++; + } else if(CH(off) == closer_char) { + /* Success. */ + *p_contents_end = off; + *p_end = off+1; + *p_end_line_index = line_index; + return TRUE; + } + + off++; + } + + line_index++; + } + + return FALSE; +} + +/* Returns 0 if it is not a reference definition. + * + * Returns N > 0 if it is a reference definition. N then corresponds to the + * number of lines forming it). In this case the definition is stored for + * resolving any links referring to it. + * + * Returns -1 in case of an error (out of memory). + */ +static int +md_is_link_reference_definition_helper( + MD_CTX* ctx, const MD_LINE* lines, int n_lines, + int (*is_link_dest_fn)(MD_CTX*, OFF, OFF, OFF*, OFF*, OFF*)) +{ + OFF label_contents_beg; + OFF label_contents_end; + int label_contents_line_index = -1; + int label_is_multiline; + CHAR* label; + SZ label_size; + int label_needs_free = FALSE; + OFF dest_contents_beg; + OFF dest_contents_end; + OFF title_contents_beg; + OFF title_contents_end; + int title_contents_line_index; + int title_is_multiline; + OFF off; + int line_index = 0; + int tmp_line_index; + MD_REF_DEF* def; + int ret; + + /* Link label. */ + if(!md_is_link_label(ctx, lines, n_lines, lines[0].beg, + &off, &label_contents_line_index, &line_index, + &label_contents_beg, &label_contents_end)) + return FALSE; + label_is_multiline = (label_contents_line_index != line_index); + + /* Colon. */ + if(off >= lines[line_index].end || CH(off) != _T(':')) + return FALSE; + off++; + + /* Optional white space with up to one line break. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end) { + line_index++; + if(line_index >= n_lines) + return FALSE; + off = lines[line_index].beg; + } + + /* Link destination. */ + if(!is_link_dest_fn(ctx, off, lines[line_index].end, + &off, &dest_contents_beg, &dest_contents_end)) + return FALSE; + + /* (Optional) title. Note we interpret it as an title only if nothing + * more follows on its last line. */ + if(md_is_link_title(ctx, lines + line_index, n_lines - line_index, off, + &off, &title_contents_line_index, &tmp_line_index, + &title_contents_beg, &title_contents_end) + && off >= lines[line_index + tmp_line_index].end) + { + title_is_multiline = (tmp_line_index != title_contents_line_index); + title_contents_line_index += line_index; + line_index += tmp_line_index; + } else { + /* Not a title. */ + title_is_multiline = FALSE; + title_contents_beg = off; + title_contents_end = off; + title_contents_line_index = 0; + } + + /* Nothing more can follow on the last line. */ + if(off < lines[line_index].end) + return FALSE; + + /* Construct label. */ + if(!label_is_multiline) { + label = (CHAR*) STR(label_contents_beg); + label_size = label_contents_end - label_contents_beg; + label_needs_free = FALSE; + } else { + MD_CHECK(md_merge_lines_alloc(ctx, label_contents_beg, label_contents_end, + lines + label_contents_line_index, n_lines - label_contents_line_index, + _T(' '), &label, &label_size)); + label_needs_free = TRUE; + } + + /* Store the reference definition. */ + if(ctx->n_ref_defs >= ctx->alloc_ref_defs) { + MD_REF_DEF* new_defs; + + ctx->alloc_ref_defs = (ctx->alloc_ref_defs > 0 ? ctx->alloc_ref_defs * 2 : 16); + new_defs = (MD_REF_DEF*) realloc(ctx->ref_defs, ctx->alloc_ref_defs * sizeof(MD_REF_DEF)); + if(new_defs == NULL) { + MD_LOG("realloc() failed."); + ret = -1; + goto abort; + } + + ctx->ref_defs = new_defs; + } + + def = &ctx->ref_defs[ctx->n_ref_defs]; + memset(def, 0, sizeof(MD_REF_DEF)); + + def->label = label; + def->label_size = label_size; + def->label_needs_free = label_needs_free; + + def->dest_beg = dest_contents_beg; + def->dest_end = dest_contents_end; + + if(title_contents_beg >= title_contents_end) { + def->title = NULL; + def->title_size = 0; + } else if(!title_is_multiline) { + def->title = (CHAR*) STR(title_contents_beg); + def->title_size = title_contents_end - title_contents_beg; + } else { + MD_CHECK(md_merge_lines_alloc(ctx, title_contents_beg, title_contents_end, + lines + title_contents_line_index, n_lines - title_contents_line_index, + _T('\n'), &def->title, &def->title_size)); + def->title_needs_free = TRUE; + } + + /* Success. */ + ctx->n_ref_defs++; + return line_index + 1; + +abort: + /* Failure. */ + if(label_needs_free) + free(label); + return -1; +} + +static inline int +md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, int n_lines) +{ + int ret; + ret = md_is_link_reference_definition_helper(ctx, lines, n_lines, md_is_link_destination_A); + if(ret == 0) + ret = md_is_link_reference_definition_helper(ctx, lines, n_lines, md_is_link_destination_B); + return ret; +} + +static int +md_is_link_reference(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + OFF beg, OFF end, MD_LINK_ATTR* attr) +{ + const MD_REF_DEF* def; + const MD_LINE* beg_line; + const MD_LINE* end_line; + CHAR* label; + SZ label_size; + int ret; + + MD_ASSERT(CH(beg) == _T('[') || CH(beg) == _T('!')); + MD_ASSERT(CH(end-1) == _T(']')); + + beg += (CH(beg) == _T('!') ? 2 : 1); + end--; + + /* Find lines corresponding to the beg and end positions. */ + MD_ASSERT(lines[0].beg <= beg); + beg_line = lines; + while(beg >= beg_line->end) + beg_line++; + + MD_ASSERT(end <= lines[n_lines-1].end); + end_line = beg_line; + while(end >= end_line->end) + end_line++; + + if(beg_line != end_line) { + MD_CHECK(md_merge_lines_alloc(ctx, beg, end, beg_line, + n_lines - (beg_line - lines), _T(' '), &label, &label_size)); + } else { + label = (CHAR*) STR(beg); + label_size = end - beg; + } + + def = md_lookup_ref_def(ctx, label, label_size); + if(def != NULL) { + attr->dest_beg = def->dest_beg; + attr->dest_end = def->dest_end; + attr->title = def->title; + attr->title_size = def->title_size; + attr->title_needs_free = FALSE; + } + + if(beg_line != end_line) + free(label); + + ret = (def != NULL); + +abort: + return ret; +} + +static int +md_is_inline_link_spec_helper(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + OFF beg, OFF* p_end, MD_LINK_ATTR* attr, + int (*is_link_dest_fn)(MD_CTX*, OFF, OFF, OFF*, OFF*, OFF*)) +{ + int line_index = 0; + int tmp_line_index; + OFF title_contents_beg; + OFF title_contents_end; + int title_contents_line_index; + int title_is_multiline; + OFF off = beg; + int ret = FALSE; + + while(off >= lines[line_index].end) + line_index++; + + MD_ASSERT(CH(off) == _T('(')); + off++; + + /* Optional white space with up to one line break. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end && ISNEWLINE(off)) { + line_index++; + if(line_index >= n_lines) + return FALSE; + off = lines[line_index].beg; + } + + /* Link destination may be omitted, but only when not also having a title. */ + if(off < ctx->size && CH(off) == _T(')')) { + attr->dest_beg = off; + attr->dest_end = off; + attr->title = NULL; + attr->title_size = 0; + attr->title_needs_free = FALSE; + off++; + *p_end = off; + return TRUE; + } + + /* Link destination. */ + if(!is_link_dest_fn(ctx, off, lines[line_index].end, + &off, &attr->dest_beg, &attr->dest_end)) + return FALSE; + + /* (Optional) title. */ + if(md_is_link_title(ctx, lines + line_index, n_lines - line_index, off, + &off, &title_contents_line_index, &tmp_line_index, + &title_contents_beg, &title_contents_end)) + { + title_is_multiline = (tmp_line_index != title_contents_line_index); + title_contents_line_index += line_index; + line_index += tmp_line_index; + } else { + /* Not a title. */ + title_is_multiline = FALSE; + title_contents_beg = off; + title_contents_end = off; + title_contents_line_index = 0; + } + + /* Optional whitespace followed with final ')'. */ + while(off < lines[line_index].end && ISWHITESPACE(off)) + off++; + if(off >= lines[line_index].end && ISNEWLINE(off)) { + line_index++; + if(line_index >= n_lines) + return FALSE; + off = lines[line_index].beg; + } + if(CH(off) != _T(')')) + goto abort; + off++; + + if(title_contents_beg >= title_contents_end) { + attr->title = NULL; + attr->title_size = 0; + attr->title_needs_free = FALSE; + } else if(!title_is_multiline) { + attr->title = (CHAR*) STR(title_contents_beg); + attr->title_size = title_contents_end - title_contents_beg; + attr->title_needs_free = FALSE; + } else { + MD_CHECK(md_merge_lines_alloc(ctx, title_contents_beg, title_contents_end, + lines + title_contents_line_index, n_lines - title_contents_line_index, + _T('\n'), &attr->title, &attr->title_size)); + attr->title_needs_free = TRUE; + } + + *p_end = off; + ret = TRUE; + +abort: + return ret; +} + +static inline int +md_is_inline_link_spec(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + OFF beg, OFF* p_end, MD_LINK_ATTR* attr) +{ + return md_is_inline_link_spec_helper(ctx, lines, n_lines, beg, p_end, attr, md_is_link_destination_A) || + md_is_inline_link_spec_helper(ctx, lines, n_lines, beg, p_end, attr, md_is_link_destination_B); +} + +static void +md_free_ref_defs(MD_CTX* ctx) +{ + int i; + + for(i = 0; i < ctx->n_ref_defs; i++) { + MD_REF_DEF* def = &ctx->ref_defs[i]; + + if(def->label_needs_free) + free(def->label); + if(def->title_needs_free) + free(def->title); + } + + free(ctx->ref_defs); +} + + +/****************************************** + *** Processing Inlines (a.k.a Spans) *** + ******************************************/ + +/* We process inlines in few phases: + * + * (1) We go through the block text and collect all significant characters + * which may start/end a span or some other significant position into + * ctx->marks[]. Core of this is what md_collect_marks() does. + * + * We also do some very brief preliminary context-less analysis, whether + * it might be opener or closer (e.g. of an emphasis span). + * + * This speeds the other steps as we do not need to re-iterate over all + * characters anymore. + * + * (2) We analyze each potential mark types, in order by their precedence. + * + * In each md_analyze_XXX() function, we re-iterate list of the marks, + * skipping already resolved regions (in preceding precedences) and try to + * resolve them. + * + * (2.1) For trivial marks, which are single (e.g. HTML entity), we just mark + * them as resolved. + * + * (2.2) For range-type marks, we analyze whether the mark could be closer + * and, if yes, whether there is some preceding opener it could satisfy. + * + * If not we check whether it could be really an opener and if yes, we + * remember it so subsequent closers may resolve it. + * + * (3) Finally, when all marks were analyzed, we render the block contents + * by calling MD_RENDERER::text() callback, interrupting by ::enter_span() + * or ::close_span() whenever we reach a resolved mark. + */ + + +/* The mark structure. + * + * '\\': Maybe escape sequence. + * '\0': NULL char. + * '*': Maybe (strong) emphasis start/end. + * '_': Maybe (strong) emphasis start/end. + * '~': Maybe strikethrough start/end (needs MD_FLAG_STRIKETHROUGH). + * '`': Maybe code span start/end. + * '&': Maybe start of entity. + * ';': Maybe end of entity. + * '<': Maybe start of raw HTML or autolink. + * '>': Maybe end of raw HTML or autolink. + * '[': Maybe start of link label or link text. + * '!': Equivalent of '[' for image. + * ']': Maybe end of link label or link text. + * '@': Maybe permissive e-mail auto-link (needs MD_FLAG_PERMISSIVEEMAILAUTOLINKS). + * ':': Maybe permissive URL auto-link (needs MD_FLAG_PERMISSIVEURLAUTOLINKS). + * '.': Maybe permissive WWW auto-link (needs MD_FLAG_PERMISSIVEWWWAUTOLINKS). + * 'D': Dummy mark, it reserves a space for splitting a previous mark + * (e.g. emphasis) or to make more space for storing some special data + * related to the preceding mark (e.g. link). + * + * Note that not all instances of these chars in the text imply creation of the + * structure. Only those which have (or may have, after we see more context) + * the special meaning. + * + * (Keep this struct as small as possible to fit as much of them into CPU + * cache line.) + */ +struct MD_MARK_tag { + OFF beg; + OFF end; + + /* For unresolved openers, 'prev' and 'next' form the chain of open openers + * of given type 'ch'. + * + * During resolving, we disconnect from the chain and point to the + * corresponding counterpart so opener points to its closer and vice versa. + */ + int prev; + int next; + CHAR ch; + unsigned char flags; +}; + +/* Mark flags (these apply to ALL mark types). */ +#define MD_MARK_POTENTIAL_OPENER 0x01 /* Maybe opener. */ +#define MD_MARK_POTENTIAL_CLOSER 0x02 /* Maybe closer. */ +#define MD_MARK_OPENER 0x04 /* Definitely opener. */ +#define MD_MARK_CLOSER 0x08 /* Definitely closer. */ +#define MD_MARK_RESOLVED 0x10 /* Resolved in any definite way. */ + +/* Mark flags specific for various mark types (so they can share bits). */ +#define MD_MARK_EMPH_INTRAWORD 0x20 /* Helper for the "rule of 3". */ +#define MD_MARK_EMPH_MODULO3_0 0x40 +#define MD_MARK_EMPH_MODULO3_1 0x80 +#define MD_MARK_EMPH_MODULO3_2 (0x40 | 0x80) +#define MD_MARK_EMPH_MODULO3_MASK (0x40 | 0x80) +#define MD_MARK_AUTOLINK 0x20 /* Distinguisher for '<', '>'. */ +#define MD_MARK_VALIDPERMISSIVEAUTOLINK 0x20 /* For permissive autolinks. */ + + +static MD_MARK* +md_push_mark(MD_CTX* ctx) +{ + if(ctx->n_marks >= ctx->alloc_marks) { + MD_MARK* new_marks; + + ctx->alloc_marks = (ctx->alloc_marks > 0 ? ctx->alloc_marks * 2 : 64); + new_marks = realloc(ctx->marks, ctx->alloc_marks * sizeof(MD_MARK)); + if(new_marks == NULL) { + MD_LOG("realloc() failed."); + return NULL; + } + + ctx->marks = new_marks; + } + + return &ctx->marks[ctx->n_marks++]; +} + +#define PUSH_MARK_() \ + do { \ + mark = md_push_mark(ctx); \ + if(mark == NULL) { \ + ret = -1; \ + goto abort; \ + } \ + } while(0) + +#define PUSH_MARK(ch_, beg_, end_, flags_) \ + do { \ + PUSH_MARK_(); \ + mark->beg = (beg_); \ + mark->end = (end_); \ + mark->prev = -1; \ + mark->next = -1; \ + mark->ch = (char)(ch_); \ + mark->flags = (flags_); \ + } while(0) + + +static void +md_mark_chain_append(MD_CTX* ctx, MD_MARKCHAIN* chain, int mark_index) +{ + if(chain->tail >= 0) + ctx->marks[chain->tail].next = mark_index; + else + chain->head = mark_index; + + ctx->marks[mark_index].prev = chain->tail; + chain->tail = mark_index; +} + +/* Sometimes, we need to store a pointer into the mark. It is quite rare + * so we do not bother to make MD_MARK use union, and it can only happen + * for dummy marks. */ +static inline void +md_mark_store_ptr(MD_CTX* ctx, int mark_index, void* ptr) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + MD_ASSERT(mark->ch == 'D'); + + /* Check only members beg and end are misused for this. */ + MD_ASSERT(sizeof(void*) <= 2 * sizeof(OFF)); + memcpy(mark, &ptr, sizeof(void*)); +} + +static inline void* +md_mark_get_ptr(MD_CTX* ctx, int mark_index) +{ + void* ptr; + MD_MARK* mark = &ctx->marks[mark_index]; + MD_ASSERT(mark->ch == 'D'); + memcpy(&ptr, mark, sizeof(void*)); + return ptr; +} + +static void +md_resolve_range(MD_CTX* ctx, MD_MARKCHAIN* chain, int opener_index, int closer_index) +{ + MD_MARK* opener = &ctx->marks[opener_index]; + MD_MARK* closer = &ctx->marks[closer_index]; + + /* Remove opener from the list of openers. */ + if(chain != NULL) { + if(opener->prev >= 0) + ctx->marks[opener->prev].next = opener->next; + else + chain->head = opener->next; + + if(opener->next >= 0) + ctx->marks[opener->next].prev = opener->prev; + else + chain->tail = opener->prev; + } + + /* Interconnect opener and closer and mark both as resolved. */ + opener->next = closer_index; + opener->flags |= MD_MARK_OPENER | MD_MARK_RESOLVED; + closer->prev = opener_index; + closer->flags |= MD_MARK_CLOSER | MD_MARK_RESOLVED; +} + + +#define MD_ROLLBACK_ALL 0 +#define MD_ROLLBACK_CROSSING 1 + +/* In the range ctx->marks[opener_index] ... [closer_index], undo some or all + * resolvings accordingly to these rules: + * + * (1) All openers BEFORE the range corresponding to any closer inside the + * range are un-resolved and they are re-added to their respective chains + * of unresolved openers. This ensures we can reuse the opener for closers + * AFTER the range. + * + * (2) If 'how' is MD_ROLLBACK_ALL, then ALL resolved marks inside the range + * are discarded. + * + * (3) If 'how' is MD_ROLLBACK_CROSSING, only closers with openers handled + * in (1) are discarded. I.e. pairs of openers and closers which are both + * inside the range are retained as well as any unpaired marks. + */ +static void +md_rollback(MD_CTX* ctx, int opener_index, int closer_index, int how) +{ + int i; + int mark_index; + + /* Cut all unresolved openers at the mark index. */ + for(i = OPENERS_CHAIN_FIRST; i < OPENERS_CHAIN_LAST+1; i++) { + MD_MARKCHAIN* chain = &ctx->mark_chains[i]; + + while(chain->tail >= opener_index) + chain->tail = ctx->marks[chain->tail].prev; + + if(chain->tail >= 0) + ctx->marks[chain->tail].next = -1; + else + chain->head = -1; + } + + /* Go backwards so that un-resolved openers are re-added into their + * respective chains, in the right order. */ + mark_index = closer_index - 1; + while(mark_index > opener_index) { + MD_MARK* mark = &ctx->marks[mark_index]; + int mark_flags = mark->flags; + int discard_flag = (how == MD_ROLLBACK_ALL); + + if(mark->flags & MD_MARK_CLOSER) { + int mark_opener_index = mark->prev; + + /* Undo opener BEFORE the range. */ + if(mark_opener_index < opener_index) { + MD_MARK* mark_opener = &ctx->marks[mark_opener_index]; + MD_MARKCHAIN* chain; + + mark_opener->flags &= ~(MD_MARK_OPENER | MD_MARK_CLOSER | MD_MARK_RESOLVED); + + switch(mark_opener->ch) { + case '*': chain = &ASTERISK_OPENERS; break; + case '_': chain = &UNDERSCORE_OPENERS; break; + case '`': chain = &BACKTICK_OPENERS; break; + case '<': chain = &LOWERTHEN_OPENERS; break; + case '~': chain = &TILDE_OPENERS; break; + default: MD_UNREACHABLE(); break; + } + md_mark_chain_append(ctx, chain, mark_opener_index); + + discard_flag = 1; + } + } + + /* And reset our flags. */ + if(discard_flag) + mark->flags &= ~(MD_MARK_OPENER | MD_MARK_CLOSER | MD_MARK_RESOLVED); + + /* Jump as far as we can over unresolved or non-interesting marks. */ + switch(how) { + case MD_ROLLBACK_CROSSING: + if((mark_flags & MD_MARK_CLOSER) && mark->prev > opener_index) { + /* If we are closer with opener INSIDE the range, there may + * not be any other crosser inside the subrange. */ + mark_index = mark->prev; + break; + } + /* Pass through. */ + default: + mark_index--; + break; + } + } +} + +static void +md_build_mark_char_map(MD_CTX* ctx) +{ + memset(ctx->mark_char_map, 0, sizeof(ctx->mark_char_map)); + + ctx->mark_char_map['\\'] = 1; + ctx->mark_char_map['*'] = 1; + ctx->mark_char_map['_'] = 1; + ctx->mark_char_map['`'] = 1; + ctx->mark_char_map['&'] = 1; + ctx->mark_char_map[';'] = 1; + ctx->mark_char_map['<'] = 1; + ctx->mark_char_map['>'] = 1; + ctx->mark_char_map['['] = 1; + ctx->mark_char_map['!'] = 1; + ctx->mark_char_map[']'] = 1; + ctx->mark_char_map['\0'] = 1; + + if(ctx->parser.flags & MD_FLAG_STRIKETHROUGH) + ctx->mark_char_map['~'] = 1; + + if(ctx->parser.flags & MD_FLAG_PERMISSIVEEMAILAUTOLINKS) + ctx->mark_char_map['@'] = 1; + + if(ctx->parser.flags & MD_FLAG_PERMISSIVEURLAUTOLINKS) + ctx->mark_char_map[':'] = 1; + + if(ctx->parser.flags & MD_FLAG_PERMISSIVEWWWAUTOLINKS) + ctx->mark_char_map['.'] = 1; + + if(ctx->parser.flags & MD_FLAG_TABLES) + ctx->mark_char_map['|'] = 1; + + if(ctx->parser.flags & MD_FLAG_COLLAPSEWHITESPACE) { + int i; + + for(i = 0; i < sizeof(ctx->mark_char_map); i++) { + if(ISWHITESPACE_(i)) + ctx->mark_char_map[i] = 1; + } + } +} + +static int +md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode) +{ + int i; + int ret = 0; + MD_MARK* mark; + + for(i = 0; i < n_lines; i++) { + const MD_LINE* line = &lines[i]; + OFF off = line->beg; + OFF line_end = line->end; + + while(TRUE) { + CHAR ch; + +#ifdef MD4C_USE_UTF16 + /* For UTF-16, mark_char_map[] covers only ASCII. */ + #define IS_MARK_CHAR(off) ((CH(off) < SIZEOF_ARRAY(ctx->mark_char_map)) && \ + (ctx->mark_char_map[(unsigned char) CH(off)])) +#else + /* For 8-bit encodings, mark_char_map[] covers all 256 elements. */ + #define IS_MARK_CHAR(off) (ctx->mark_char_map[(unsigned char) CH(off)]) +#endif + + /* Optimization: Fast path (with some loop unrolling). */ + while(off + 4 < line_end && !IS_MARK_CHAR(off+0) && !IS_MARK_CHAR(off+1) + && !IS_MARK_CHAR(off+2) && !IS_MARK_CHAR(off+3)) + off += 4; + while(off < line_end && !IS_MARK_CHAR(off+0)) + off++; + + if(off >= line_end) + break; + + ch = CH(off); + + /* A backslash escape. + * It can go beyond line->end as it may involve escaped new + * line to form a hard break. */ + if(ch == _T('\\') && off+1 < ctx->size && (ISPUNCT(off+1) || ISNEWLINE(off+1))) { + /* Hard-break cannot be on the last line of the block. */ + if(!ISNEWLINE(off+1) || i+1 < n_lines) + PUSH_MARK(ch, off, off+2, MD_MARK_RESOLVED); + + /* If '`' or '>' follows, we need both marks as the backslash + * may be inside a code span or an autolink where escaping is + * disabled. */ + if(CH(off+1) == _T('`') || CH(off+1) == _T('>')) + off++; + else + off += 2; + continue; + } + + /* A potential (string) emphasis start/end. */ + if(ch == _T('*') || ch == _T('_')) { + OFF tmp = off+1; + int left_level; /* What precedes: 0 = whitespace; 1 = punctuation; 2 = other char. */ + int right_level; /* What follows: 0 = whitespace; 1 = punctuation; 2 = other char. */ + + while(tmp < line_end && CH(tmp) == ch) + tmp++; + + if(off == line->beg || ISUNICODEWHITESPACEBEFORE(off)) + left_level = 0; + else if(ISUNICODEPUNCTBEFORE(off)) + left_level = 1; + else + left_level = 2; + + if(tmp == line_end || ISUNICODEWHITESPACE(tmp)) + right_level = 0; + else if(ISUNICODEPUNCT(tmp)) + right_level = 1; + else + right_level = 2; + + /* Intra-word underscore doesn't have special meaning. */ + if(ch == _T('_') && left_level == 2 && right_level == 2) { + left_level = 0; + right_level = 0; + } + + if(left_level != 0 || right_level != 0) { + unsigned flags = 0; + + if(left_level > 0 && left_level >= right_level) + flags |= MD_MARK_POTENTIAL_CLOSER; + if(right_level > 0 && right_level >= left_level) + flags |= MD_MARK_POTENTIAL_OPENER; + if(left_level == 2 && right_level == 2) + flags |= MD_MARK_EMPH_INTRAWORD; + + /* For "the rule of three" we need to remember the original + * size of the mark (modulo three), before we potentially + * split the mark when being later resolved partially by some + * shorter closer. */ + switch((tmp - off) % 3) { + case 0: flags |= MD_MARK_EMPH_MODULO3_0; break; + case 1: flags |= MD_MARK_EMPH_MODULO3_1; break; + case 2: flags |= MD_MARK_EMPH_MODULO3_2; break; + } + + PUSH_MARK(ch, off, tmp, flags); + + /* During resolving, multiple asterisks may have to be + * split into independent span start/ends. Consider e.g. + * "**foo* bar*". Therefore we push also some empty dummy + * marks to have enough space for that. */ + off++; + while(off < tmp) { + PUSH_MARK('D', off, off, 0); + off++; + } + continue; + } + + off = tmp; + continue; + } + + /* A potential code span start/end. */ + if(ch == _T('`')) { + OFF tmp = off+1; + + while(tmp < line_end && CH(tmp) == _T('`')) + tmp++; + + /* We limit code span marks to lower then 256 backticks. This + * solves a pathologic case of too many openers, each of + * different length: Their resolving is then O(n^2). */ + if(tmp - off < 256) + PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER); + + off = tmp; + continue; + } + + /* A potential entity start. */ + if(ch == _T('&')) { + PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_OPENER); + off++; + continue; + } + + /* A potential entity end. */ + if(ch == _T(';')) { + /* We surely cannot be entity unless the previous mark is '&'. */ + if(ctx->n_marks > 0 && ctx->marks[ctx->n_marks-1].ch == _T('&')) + PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_CLOSER); + + off++; + continue; + } + + /* A potential autolink or raw HTML start/end. */ + if(ch == _T('<') || ch == _T('>')) { + if(!(ctx->parser.flags & MD_FLAG_NOHTMLSPANS)) + PUSH_MARK(ch, off, off+1, (ch == _T('<') ? MD_MARK_POTENTIAL_OPENER : MD_MARK_POTENTIAL_CLOSER)); + + off++; + continue; + } + + /* A potential link or its part. */ + if(ch == _T('[') || (ch == _T('!') && off+1 < line_end && CH(off+1) == _T('['))) { + OFF tmp = (ch == _T('[') ? off+1 : off+2); + PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER); + off = tmp; + /* Two dummies to make enough place for data we need if it is + * a link. */ + PUSH_MARK('D', off, off, 0); + PUSH_MARK('D', off, off, 0); + continue; + } + if(ch == _T(']')) { + PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_CLOSER); + off++; + continue; + } + + /* A potential permissive e-mail autolink. */ + if(ch == _T('@')) { + if(line->beg + 1 <= off && ISALNUM(off-1) && + off + 3 < line->end && ISALNUM(off+1)) + { + PUSH_MARK(ch, off, off+1, MD_MARK_POTENTIAL_OPENER); + /* Push a dummy as a reserve for a closer. */ + PUSH_MARK('D', off, off, 0); + } + + off++; + continue; + } + + /* A potential permissive URL autolink. */ + if(ch == _T(':')) { + static struct { + const CHAR* scheme; + SZ scheme_size; + const CHAR* suffix; + SZ suffix_size; + } scheme_map[] = { + /* In the order from the most frequently used, arguably. */ + { _T("http"), 4, _T("//"), 2 }, + { _T("https"), 5, _T("//"), 2 }, + { _T("ftp"), 3, _T("//"), 2 } + }; + int scheme_index; + + for(scheme_index = 0; scheme_index < SIZEOF_ARRAY(scheme_map); scheme_index++) { + const CHAR* scheme = scheme_map[scheme_index].scheme; + const SZ scheme_size = scheme_map[scheme_index].scheme_size; + const CHAR* suffix = scheme_map[scheme_index].suffix; + const SZ suffix_size = scheme_map[scheme_index].suffix_size; + + if(line->beg + scheme_size <= off && md_ascii_eq(STR(off-scheme_size), scheme, scheme_size) && + (line->beg + scheme_size == off || ISWHITESPACE(off-scheme_size-1) || ISANYOF(off-scheme_size-1, _T("*_~(["))) && + off + 1 + suffix_size < line->end && md_ascii_eq(STR(off+1), suffix, suffix_size)) + { + PUSH_MARK(ch, off-scheme_size, off+1+suffix_size, MD_MARK_POTENTIAL_OPENER); + /* Push a dummy as a reserve for a closer. */ + PUSH_MARK('D', off, off, 0); + off += 1 + suffix_size; + continue; + } + } + + off++; + continue; + } + + /* A potential permissive WWW autolink. */ + if(ch == _T('.')) { + if(line->beg + 3 <= off && md_ascii_eq(STR(off-3), _T("www"), 3) && + (line->beg + 3 == off || ISWHITESPACE(off-4) || ISANYOF(off-4, _T("*_~(["))) && + off + 1 < line_end) + { + PUSH_MARK(ch, off-3, off+1, MD_MARK_POTENTIAL_OPENER); + /* Push a dummy as a reserve for a closer. */ + PUSH_MARK('D', off, off, 0); + off++; + continue; + } + + off++; + continue; + } + + /* A potential table cell boundary. */ + if(table_mode && ch == _T('|')) { + PUSH_MARK(ch, off, off+1, 0); + off++; + continue; + } + + /* A potential strikethrough start/end. */ + if(ch == _T('~')) { + OFF tmp = off+1; + + while(tmp < line_end && CH(tmp) == _T('~')) + tmp++; + + PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER); + off = tmp; + } + + /* Turn non-trivial whitespace into single space. */ + if(ISWHITESPACE_(ch)) { + OFF tmp = off+1; + + while(tmp < line_end && ISWHITESPACE(tmp)) + tmp++; + + if(tmp - off > 1 || ch != _T(' ')) + PUSH_MARK(ch, off, tmp, MD_MARK_RESOLVED); + + off = tmp; + continue; + } + + /* NULL character. */ + if(ch == _T('\0')) { + PUSH_MARK(ch, off, off+1, MD_MARK_RESOLVED); + off++; + continue; + } + + off++; + } + } + + /* Add a dummy mark at the end of the mark vector to simplify + * process_inlines(). */ + PUSH_MARK(127, ctx->size, ctx->size, MD_MARK_RESOLVED); + +abort: + return ret; +} + + +/* Analyze whether the back-tick is really start/end mark of a code span. + * If yes, reset all marks inside of it and setup flags of both marks. */ +static void +md_analyze_backtick(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + int opener_index = BACKTICK_OPENERS.tail; + + /* Try to find unresolved opener of the same length. If we find it, + * we form a code span. */ + while(opener_index >= 0) { + MD_MARK* opener = &ctx->marks[opener_index]; + + if(opener->end - opener->beg == mark->end - mark->beg) { + /* Rollback anything found inside it. + * (e.g. the code span contains some back-ticks or other special + * chars we misinterpreted.) */ + md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_ALL); + + /* Resolve the span. */ + md_resolve_range(ctx, &BACKTICK_OPENERS, opener_index, mark_index); + + /* Append any space or new line inside the span into the mark + * itself to swallow it. */ + while(CH(opener->end) == _T(' ') || ISNEWLINE(opener->end)) + opener->end++; + if(mark->beg > opener->end) { + while(CH(mark->beg-1) == _T(' ') || ISNEWLINE(mark->beg-1)) + mark->beg--; + } + + /* Done. */ + return; + } + + opener_index = ctx->marks[opener_index].prev; + } + + /* We didn't find any matching opener, so we ourselves may be the opener + * of some upcoming closer. We also have to handle specially if there is + * a backslash mark before it as that can cancel the first backtick. */ + if(mark_index > 0 && (mark-1)->beg == mark->beg - 1 && (mark-1)->ch == '\\') { + if(mark->end - mark->beg == 1) { + /* Single escaped backtick. */ + return; + } + + /* Remove the escaped backtick from the opener. */ + mark->beg++; + } + + if(mark->flags & MD_MARK_POTENTIAL_OPENER) + md_mark_chain_append(ctx, &BACKTICK_OPENERS, mark_index); +} + +static int +md_is_autolink_uri(MD_CTX* ctx, OFF beg, OFF end) +{ + OFF off = beg; + + /* Check for scheme. */ + if(off >= end || !ISASCII(off)) + return FALSE; + off++; + while(1) { + if(off >= end) + return FALSE; + if(off - beg > 32) + return FALSE; + if(CH(off) == _T(':') && off - beg >= 2) + break; + if(!ISALNUM(off) && CH(off) != _T('+') && CH(off) != _T('-') && CH(off) != _T('.')) + return FALSE; + off++; + } + + /* Check the path after the scheme. */ + while(off < end) { + if(ISWHITESPACE(off) || ISCNTRL(off) || CH(off) == _T('<') || CH(off) == _T('>')) + return FALSE; + off++; + } + + return TRUE; +} + +static int +md_is_autolink_email(MD_CTX* ctx, OFF beg, OFF end) +{ + OFF off = beg; + int label_len; + + /* The code should correspond to this regexp: + /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+ + @[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])? + (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ + */ + + /* Username (before '@'). */ + while(off < end && (ISALNUM(off) || ISANYOF(off, _T(".!#$%&'*+/=?^_`{|}~-")))) + off++; + if(off <= beg) + return FALSE; + + /* '@' */ + if(off >= end || CH(off) != _T('@')) + return FALSE; + off++; + + /* Labels delimited with '.'; each label is sequence of 1 - 62 alnum + * characters or '-', but '-' is not allowed as first or last char. */ + label_len = 0; + while(off < end) { + if(ISALNUM(off)) + label_len++; + else if(CH(off) == _T('-') && label_len > 0) + label_len++; + else if(CH(off) == _T('.') && label_len > 0 && CH(off-1) != _T('-')) + label_len = 0; + else + return FALSE; + + if(label_len > 63) + return FALSE; + + off++; + } + + if(label_len <= 0 || CH(off-1) == _T('-')) + return FALSE; + + return TRUE; +} + +static int +md_is_autolink(MD_CTX* ctx, OFF beg, OFF end, int* p_missing_mailto) +{ + MD_ASSERT(CH(beg) == _T('<')); + MD_ASSERT(CH(end-1) == _T('>')); + + beg++; + end--; + + if(md_is_autolink_uri(ctx, beg, end)) + return TRUE; + + if(md_is_autolink_email(ctx, beg, end)) { + *p_missing_mailto = 1; + return TRUE; + } + + return FALSE; +} + +static void +md_analyze_lt_gt(MD_CTX* ctx, int mark_index, const MD_LINE* lines, int n_lines) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + int opener_index; + + /* If it is an opener ('<'), remember it. */ + if(mark->flags & MD_MARK_POTENTIAL_OPENER) { + md_mark_chain_append(ctx, &LOWERTHEN_OPENERS, mark_index); + return; + } + + /* Otherwise we are potential closer and we try to resolve with since all + * the chained unresolved openers. */ + opener_index = LOWERTHEN_OPENERS.head; + while(opener_index >= 0) { + MD_MARK* opener = &ctx->marks[opener_index]; + OFF detected_end; + int is_autolink = 0; + int is_missing_mailto = 0; + int is_raw_html = 0; + + is_autolink = (md_is_autolink(ctx, opener->beg, mark->end, &is_missing_mailto)); + + if(is_autolink) { + if(is_missing_mailto) + opener->ch = _T('@'); + } else { + /* Identify the line where the opening mark lives. */ + int line_index = 0; + while(1) { + if(opener->beg < lines[line_index].end) + break; + line_index++; + } + + is_raw_html = (md_is_html_any(ctx, lines + line_index, + n_lines - line_index, opener->beg, mark->end, &detected_end)); + } + + /* Check whether the range forms a valid raw HTML. */ + if(is_autolink || is_raw_html) { + md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_ALL); + md_resolve_range(ctx, &LOWERTHEN_OPENERS, opener_index, mark_index); + + if(is_raw_html) { + /* If this fails, it means we have missed some earlier opportunity + * to resolve the opener of raw HTML. */ + MD_ASSERT(detected_end == mark->end); + + /* Make these marks zero width so the '<' and '>' are part of its + * contents. */ + opener->end = opener->beg; + mark->beg = mark->end; + + opener->flags &= ~MD_MARK_AUTOLINK; + mark->flags &= ~MD_MARK_AUTOLINK; + } else { + opener->flags |= MD_MARK_AUTOLINK; + mark->flags |= MD_MARK_AUTOLINK; + } + + /* And we are done. */ + return; + } + + opener_index = opener->next; + } +} + +static void +md_analyze_bracket(MD_CTX* ctx, int mark_index) +{ + /* We cannot really resolve links here as for that we would need + * more context. E.g. a following pair of brackets (reference link), + * or enclosing pair of brackets (if the inner is the link, the outer + * one cannot be.) + * + * Therefore we here only construct a list of resolved '[' ']' pairs + * ordered by position of the closer. This allows ur to analyze what is + * or is not link in the right order, from inside to outside in case + * of nested brackets. + * + * The resolving itself is deferred into md_resolve_links(). + */ + + MD_MARK* mark = &ctx->marks[mark_index]; + + if(mark->flags & MD_MARK_POTENTIAL_OPENER) { + md_mark_chain_append(ctx, &BRACKET_OPENERS, mark_index); + return; + } + + if(BRACKET_OPENERS.tail >= 0) { + /* Pop the opener from the chain. */ + int opener_index = BRACKET_OPENERS.tail; + MD_MARK* opener = &ctx->marks[opener_index]; + if(opener->prev >= 0) + ctx->marks[opener->prev].next = -1; + else + BRACKET_OPENERS.head = -1; + BRACKET_OPENERS.tail = opener->prev; + + /* Interconnect the opener and closer. */ + opener->next = mark_index; + mark->prev = opener_index; + + /* Add the pair into chain of potential links for md_resolve_links(). + * Note we misuse opener->prev for this as opener->next points to its + * closer. */ + if(ctx->unresolved_link_tail >= 0) + ctx->marks[ctx->unresolved_link_tail].prev = opener_index; + else + ctx->unresolved_link_head = opener_index; + ctx->unresolved_link_tail = opener_index; + opener->prev = -1; + } +} + +/* Forward declaration. */ +static void md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + int mark_beg, int mark_end); + +static int +md_resolve_links(MD_CTX* ctx, const MD_LINE* lines, int n_lines) +{ + int opener_index = ctx->unresolved_link_head; + OFF last_link_beg = 0; + OFF last_link_end = 0; + OFF last_img_beg = 0; + OFF last_img_end = 0; + + while(opener_index >= 0) { + MD_MARK* opener = &ctx->marks[opener_index]; + int closer_index = opener->next; + MD_MARK* closer = &ctx->marks[closer_index]; + int next_index = opener->prev; + MD_MARK* next_opener; + MD_MARK* next_closer; + MD_LINK_ATTR attr; + int is_link = FALSE; + + if(next_index >= 0) { + next_opener = &ctx->marks[next_index]; + next_closer = &ctx->marks[next_opener->next]; + } else { + next_opener = NULL; + next_closer = NULL; + } + + /* If nested ("[ [ ] ]"), we need to make sure that: + * - The outer does not end inside of (...) belonging to the inner. + * - The outer cannot be link if the inner is link (i.e. not image). + * + * (Note we here analyze from inner to outer as the marks are ordered + * by closer->beg.) + */ + if((opener->beg < last_link_beg && closer->end < last_link_end) || + (opener->beg < last_img_beg && closer->end < last_img_end) || + (opener->beg < last_link_end && opener->ch == '[')) + { + opener_index = next_index; + continue; + } + + if(next_opener != NULL && next_opener->beg == closer->end) { + if(next_closer->beg > closer->end + 1) { + /* Might be full reference link. */ + is_link = md_is_link_reference(ctx, lines, n_lines, next_opener->beg, next_closer->end, &attr); + } else { + /* Might be shortcut reference link. */ + is_link = md_is_link_reference(ctx, lines, n_lines, opener->beg, closer->end, &attr); + } + + if(is_link < 0) + return -1; + + if(is_link) { + /* Eat the 2nd "[...]". */ + closer->end = next_closer->end; + } + } else { + if(closer->end < ctx->size && CH(closer->end) == _T('(')) { + /* Might be inline link. */ + OFF inline_link_end = -1; + + is_link = md_is_inline_link_spec(ctx, lines, n_lines, closer->end, &inline_link_end, &attr); + if(is_link < 0) + return -1; + + /* Check the closing ')' is not inside an already resolved range + * (i.e. a range with a higher priority), e.g. a code span. */ + if(is_link) { + int i = closer_index + 1; + + while(i < ctx->n_marks) { + MD_MARK* mark = &ctx->marks[i]; + + if(mark->beg >= inline_link_end) + break; + if((mark->flags & (MD_MARK_OPENER | MD_MARK_RESOLVED)) == (MD_MARK_OPENER | MD_MARK_RESOLVED)) { + if(ctx->marks[mark->next].beg >= inline_link_end) { + /* Cancel the link status. */ + if(attr.title_needs_free) + free(attr.title); + is_link = FALSE; + break; + } + + i = mark->next + 1; + } else { + i++; + } + } + } + + if(is_link) { + /* Eat the "(...)" */ + closer->end = inline_link_end; + } + } + + if(!is_link) { + /* Might be collapsed reference link. */ + is_link = md_is_link_reference(ctx, lines, n_lines, opener->beg, closer->end, &attr); + if(is_link < 0) + return -1; + } + } + + if(is_link) { + /* Resolve the brackets as a link. */ + opener->flags |= MD_MARK_OPENER | MD_MARK_RESOLVED; + closer->flags |= MD_MARK_CLOSER | MD_MARK_RESOLVED; + + /* If it is a link, we store the destination and title in the two + * dummy marks after the opener. */ + MD_ASSERT(ctx->marks[opener_index+1].ch == 'D'); + ctx->marks[opener_index+1].beg = attr.dest_beg; + ctx->marks[opener_index+1].end = attr.dest_end; + + MD_ASSERT(ctx->marks[opener_index+2].ch == 'D'); + md_mark_store_ptr(ctx, opener_index+2, attr.title); + if(attr.title_needs_free) + md_mark_chain_append(ctx, &PTR_CHAIN, opener_index+2); + ctx->marks[opener_index+2].prev = attr.title_size; + + if(opener->ch == '[') { + last_link_beg = opener->beg; + last_link_end = closer->end; + } else { + last_img_beg = opener->beg; + last_img_end = closer->end; + } + + md_analyze_link_contents(ctx, lines, n_lines, opener_index+1, closer_index); + } + + opener_index = next_index; + } + + return 0; +} + +/* Analyze whether the mark '&' starts a HTML entity. + * If so, update its flags as well as flags of corresponding closer ';'. */ +static void +md_analyze_entity(MD_CTX* ctx, int mark_index) +{ + MD_MARK* opener = &ctx->marks[mark_index]; + MD_MARK* closer; + OFF off; + + /* Cannot be entity if there is no closer as the next mark. + * (Any other mark between would mean strange character which cannot be + * part of the entity. + * + * So we can do all the work on '&' and do not call this later for the + * closing mark ';'. + */ + if(mark_index + 1 >= ctx->n_marks) + return; + closer = &ctx->marks[mark_index+1]; + if(closer->ch != ';') + return; + + if(md_is_entity(ctx, opener->beg, closer->end, &off)) { + MD_ASSERT(off == closer->end); + + md_resolve_range(ctx, NULL, mark_index, mark_index+1); + opener->end = closer->end; + } +} + +static void +md_analyze_table_cell_boundary(MD_CTX* ctx, int mark_index) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + mark->flags |= MD_MARK_RESOLVED; + + md_mark_chain_append(ctx, &TABLECELLBOUNDARIES, mark_index); + ctx->n_table_cell_boundaries++; +} + +/* Split a longer mark into two. The new mark takes the given count of + * characters. May only be called if an adequate number of dummy 'D' marks + * follows. + */ +static int +md_split_simple_pairing_mark(MD_CTX* ctx, int mark_index, SZ n) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + int new_mark_index = mark_index + (mark->end - mark->beg - n); + MD_MARK* dummy = &ctx->marks[new_mark_index]; + + MD_ASSERT(mark->end - mark->beg > n); + MD_ASSERT(dummy->ch == 'D'); + + memcpy(dummy, mark, sizeof(MD_MARK)); + mark->end -= n; + dummy->beg = mark->end; + + return new_mark_index; +} + +static void +md_analyze_simple_pairing_mark(MD_CTX* ctx, MD_MARKCHAIN* chain, int mark_index, + int apply_rule_of_three) +{ + MD_MARK* mark = &ctx->marks[mark_index]; + + /* If we can be a closer, try to resolve with the preceding opener. */ + if((mark->flags & MD_MARK_POTENTIAL_CLOSER) && chain->tail >= 0) { + int opener_index = chain->tail; + MD_MARK* opener = &ctx->marks[opener_index]; + SZ opener_size = opener->end - opener->beg; + SZ closer_size = mark->end - mark->beg; + + /* Apply the "rule of three". */ + if(apply_rule_of_three) { + while((mark->flags & MD_MARK_EMPH_INTRAWORD) || (opener->flags & MD_MARK_EMPH_INTRAWORD)) { + SZ opener_orig_size_modulo3; + + switch(opener->flags & MD_MARK_EMPH_MODULO3_MASK) { + case MD_MARK_EMPH_MODULO3_0: opener_orig_size_modulo3 = 0; break; + case MD_MARK_EMPH_MODULO3_1: opener_orig_size_modulo3 = 1; break; + case MD_MARK_EMPH_MODULO3_2: opener_orig_size_modulo3 = 2; break; + default: MD_UNREACHABLE(); break; + } + + if((opener_orig_size_modulo3 + closer_size) % 3 != 0) { + /* This opener is suitable. */ + break; + } + + if(opener->prev >= 0) { + /* Try previous opener. */ + opener_index = opener->prev; + opener = &ctx->marks[opener_index]; + opener_size = opener->end - opener->beg; + closer_size = mark->end - mark->beg; + } else { + /* No suitable opener found. */ + goto cannot_resolve; + } + } + } + + if(opener_size > closer_size) { + opener_index = md_split_simple_pairing_mark(ctx, opener_index, closer_size); + md_mark_chain_append(ctx, chain, opener_index); + } else if(opener_size < closer_size) { + md_split_simple_pairing_mark(ctx, mark_index, closer_size - opener_size); + } + + md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_CROSSING); + md_resolve_range(ctx, chain, opener_index, mark_index); + return; + } + +cannot_resolve: + /* If not resolved, and we can be an opener, remember the mark for + * the future. */ + if(mark->flags & MD_MARK_POTENTIAL_OPENER) + md_mark_chain_append(ctx, chain, mark_index); +} + +static inline void +md_analyze_asterisk(MD_CTX* ctx, int mark_index) +{ + md_analyze_simple_pairing_mark(ctx, &ASTERISK_OPENERS, mark_index, 1); +} + +static inline void +md_analyze_underscore(MD_CTX* ctx, int mark_index) +{ + md_analyze_simple_pairing_mark(ctx, &UNDERSCORE_OPENERS, mark_index, 1); +} + +static void +md_analyze_tilde(MD_CTX* ctx, int mark_index) +{ + /* We attempt to be Github Flavored Markdown compatible here. GFM says + * that length of the tilde sequence is not important at all. Note that + * implies the TILDE_OPENERS chain can have at most one item. */ + + if(TILDE_OPENERS.head >= 0) { + /* The chain already contains an opener, so we may resolve the span. */ + int opener_index = TILDE_OPENERS.head; + + md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_CROSSING); + md_resolve_range(ctx, &TILDE_OPENERS, opener_index, mark_index); + } else { + /* We can only be opener. */ + md_mark_chain_append(ctx, &TILDE_OPENERS, mark_index); + } +} + +static void +md_analyze_permissive_url_autolink(MD_CTX* ctx, int mark_index) +{ + MD_MARK* opener = &ctx->marks[mark_index]; + int closer_index = mark_index + 1; + MD_MARK* closer = &ctx->marks[closer_index]; + MD_MARK* next_resolved_mark; + OFF off = opener->end; + int seen_dot = FALSE; + int seen_underscore_or_hyphen[2] = { FALSE, FALSE }; + + /* Check for domain. */ + while(off < ctx->size) { + if(ISALNUM(off)) { + off++; + } else if(CH(off) == _T('.')) { + seen_dot = TRUE; + seen_underscore_or_hyphen[0] = seen_underscore_or_hyphen[1]; + seen_underscore_or_hyphen[1] = FALSE; + off++; + } else if(ISANYOF2(off, _T('-'), _T('_'))) { + seen_underscore_or_hyphen[1] = TRUE; + off++; + } else { + break; + } + } + + if(off <= opener->end || !seen_dot || seen_underscore_or_hyphen[0] || seen_underscore_or_hyphen[1]) + return; + + /* Check for path. */ + next_resolved_mark = closer + 1; + while(next_resolved_mark->ch == 'D' || !(next_resolved_mark->flags & MD_MARK_RESOLVED)) + next_resolved_mark++; + while(off < next_resolved_mark->beg && CH(off) != _T('<') && !ISWHITESPACE(off) && !ISNEWLINE(off)) + off++; + + /* Path validation. */ + if(ISANYOF(off-1, _T("?!.,:*_~)"))) { + if(CH(off-1) != _T(')')) { + off--; + } else { + int parenthesis_balance = 0; + OFF tmp; + + for(tmp = opener->end; tmp < off; tmp++) { + if(CH(tmp) == _T('(')) + parenthesis_balance++; + else if(CH(tmp) == _T(')')) + parenthesis_balance--; + } + + if(parenthesis_balance < 0) + off--; + } + } + + /* Ok. Lets call it auto-link. Adapt opener and create closer to zero + * length so all the contents becomes the link text. */ + MD_ASSERT(closer->ch == 'D'); + opener->end = opener->beg; + closer->ch = opener->ch; + closer->beg = off; + closer->end = off; + md_resolve_range(ctx, NULL, mark_index, closer_index); +} + +/* The permissive autolinks do not have to be enclosed in '<' '>' but we + * instead impose stricter rules what is understood as an e-mail address + * here. Actually any non-alphanumeric characters with exception of '.' + * are prohibited both in username and after '@'. */ +static void +md_analyze_permissive_email_autolink(MD_CTX* ctx, int mark_index) +{ + MD_MARK* opener = &ctx->marks[mark_index]; + int closer_index; + MD_MARK* closer; + OFF beg = opener->beg; + OFF end = opener->end; + int dot_count = 0; + + MD_ASSERT(CH(beg) == _T('@')); + + /* Scan for name before '@'. */ + while(beg > 0 && (ISALNUM(beg-1) || ISANYOF(beg-1, _T(".-_+")))) + beg--; + + /* Scan for domain after '@'. */ + while(end < ctx->size && (ISALNUM(end) || ISANYOF(end, _T(".-_")))) { + if(CH(end) == _T('.')) + dot_count++; + end++; + } + if(CH(end-1) == _T('.')) { /* Final '.' not part of it. */ + dot_count--; + end--; + } + else if(ISANYOF2(end-1, _T('-'), _T('_'))) /* These are forbidden at the end. */ + return; + if(CH(end-1) == _T('@') || dot_count == 0) + return; + + /* Ok. Lets call it auto-link. Adapt opener and create closer to zero + * length so all the contents becomes the link text. */ + closer_index = mark_index + 1; + closer = &ctx->marks[closer_index]; + MD_ASSERT(closer->ch == 'D'); + + opener->beg = beg; + opener->end = beg; + closer->ch = opener->ch; + closer->beg = end; + closer->end = end; + md_resolve_range(ctx, NULL, mark_index, closer_index); +} + +static inline void +md_analyze_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + int mark_beg, int mark_end, const CHAR* mark_chars) +{ + int i = mark_beg; + + while(i < mark_end) { + MD_MARK* mark = &ctx->marks[i]; + + /* Skip resolved spans. */ + if(mark->flags & MD_MARK_RESOLVED) { + if(mark->flags & MD_MARK_OPENER) { + MD_ASSERT(i < mark->next); + i = mark->next + 1; + } else { + i++; + } + continue; + } + + /* Skip marks we do not want to deal with. */ + if(!ISANYOF_(mark->ch, mark_chars)) { + i++; + continue; + } + + /* Analyze the mark. */ + switch(mark->ch) { + case '`': md_analyze_backtick(ctx, i); break; + case '<': /* Pass through. */ + case '>': md_analyze_lt_gt(ctx, i, lines, n_lines); break; + case '[': /* Pass through. */ + case '!': /* Pass through. */ + case ']': md_analyze_bracket(ctx, i); break; + case '&': md_analyze_entity(ctx, i); break; + case '|': md_analyze_table_cell_boundary(ctx, i); break; + case '*': md_analyze_asterisk(ctx, i); break; + case '_': md_analyze_underscore(ctx, i); break; + case '~': md_analyze_tilde(ctx, i); break; + case '.': /* Pass through. */ + case ':': md_analyze_permissive_url_autolink(ctx, i); break; + case '@': md_analyze_permissive_email_autolink(ctx, i); break; + } + + i++; + } +} + +/* Analyze marks (build ctx->marks). */ +static int +md_analyze_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode) +{ + int ret; + + /* Reset the previously collected stack of marks. */ + ctx->n_marks = 0; + + /* Collect all marks. */ + MD_CHECK(md_collect_marks(ctx, lines, n_lines, table_mode)); + + /* We analyze marks in few groups to handle their precedence. */ + /* (1) Entities; code spans; autolinks; raw HTML. */ + md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("&`<>")); + BACKTICK_OPENERS.head = -1; + BACKTICK_OPENERS.tail = -1; + LOWERTHEN_OPENERS.head = -1; + LOWERTHEN_OPENERS.tail = -1; + + if(table_mode) { + /* (2) Analyze table cell boundaries. + * Note we reset TABLECELLBOUNDARIES chain prior to the call md_analyze_marks(), + * not after, because caller may need it. */ + MD_ASSERT(n_lines == 1); + TABLECELLBOUNDARIES.head = -1; + TABLECELLBOUNDARIES.tail = -1; + ctx->n_table_cell_boundaries = 0; + md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("|")); + return ret; + } + + /* (3) Links. */ + md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("[]!")); + MD_CHECK(md_resolve_links(ctx, lines, n_lines)); + BRACKET_OPENERS.head = -1; + BRACKET_OPENERS.tail = -1; + ctx->unresolved_link_head = -1; + ctx->unresolved_link_tail = -1; + + /* (4) Emphasis and strong emphasis; permissive autolinks. */ + md_analyze_link_contents(ctx, lines, n_lines, 0, ctx->n_marks); + +abort: + return ret; +} + +static void +md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines, + int mark_beg, int mark_end) +{ + md_analyze_marks(ctx, lines, n_lines, mark_beg, mark_end, _T("*_~@:.")); + ASTERISK_OPENERS.head = -1; + ASTERISK_OPENERS.tail = -1; + UNDERSCORE_OPENERS.head = -1; + UNDERSCORE_OPENERS.tail = -1; + TILDE_OPENERS.head = -1; + TILDE_OPENERS.tail = -1; +} + +static int +md_enter_leave_span_a(MD_CTX* ctx, int enter, MD_SPANTYPE type, + const CHAR* dest, SZ dest_size, int prohibit_escapes_in_dest, + const CHAR* title, SZ title_size) +{ + MD_ATTRIBUTE_BUILD href_build = { 0 }; + MD_ATTRIBUTE_BUILD title_build = { 0 }; + MD_SPAN_A_DETAIL det; + int ret = 0; + + /* Note we here rely on fact that MD_SPAN_A_DETAIL and + * MD_SPAN_IMG_DETAIL are binary-compatible. */ + memset(&det, 0, sizeof(MD_SPAN_A_DETAIL)); + MD_CHECK(md_build_attribute(ctx, dest, dest_size, + (prohibit_escapes_in_dest ? MD_BUILD_ATTR_NO_ESCAPES : 0), + &det.href, &href_build)); + MD_CHECK(md_build_attribute(ctx, title, title_size, 0, &det.title, &title_build)); + + if(enter) + MD_ENTER_SPAN(type, &det); + else + MD_LEAVE_SPAN(type, &det); + +abort: + md_free_attribute(ctx, &href_build); + md_free_attribute(ctx, &title_build); + return ret; +} + +/* Render the output, accordingly to the analyzed ctx->marks. */ +static int +md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines) +{ + MD_TEXTTYPE text_type; + const MD_LINE* line = lines; + MD_MARK* prev_mark = NULL; + MD_MARK* mark; + OFF off = lines[0].beg; + OFF end = lines[n_lines-1].end; + int enforce_hardbreak = 0; + int ret = 0; + + /* Find first resolved mark. Note there is always at least one resolved + * mark, the dummy last one after the end of the latest line we actually + * never really reach. This saves us of a lot of special checks and cases + * in this function. */ + mark = ctx->marks; + while(!(mark->flags & MD_MARK_RESOLVED)) + mark++; + + text_type = MD_TEXT_NORMAL; + + while(1) { + /* Process the text up to the next mark or end-of-line. */ + OFF tmp = (line->end < mark->beg ? line->end : mark->beg); + if(tmp > off) { + MD_TEXT(text_type, STR(off), tmp - off); + off = tmp; + } + + /* If reached the mark, process it and move to next one. */ + if(off >= mark->beg) { + switch(mark->ch) { + case '\\': /* Backslash escape. */ + if(ISNEWLINE(mark->beg+1)) + enforce_hardbreak = 1; + else + MD_TEXT(text_type, STR(mark->beg+1), 1); + break; + + case ' ': /* Non-trivial space. */ + MD_TEXT(text_type, _T(" "), 1); + break; + + case '`': /* Code span. */ + if(mark->flags & MD_MARK_OPENER) { + MD_ENTER_SPAN(MD_SPAN_CODE, NULL); + text_type = MD_TEXT_CODE; + } else { + MD_LEAVE_SPAN(MD_SPAN_CODE, NULL); + text_type = MD_TEXT_NORMAL; + } + break; + + case '_': + case '*': /* Emphasis, strong emphasis. */ + if(mark->flags & MD_MARK_OPENER) { + if((mark->end - off) % 2) { + MD_ENTER_SPAN(MD_SPAN_EM, NULL); + off++; + } + while(off + 1 < mark->end) { + MD_ENTER_SPAN(MD_SPAN_STRONG, NULL); + off += 2; + } + } else { + while(off + 1 < mark->end) { + MD_LEAVE_SPAN(MD_SPAN_STRONG, NULL); + off += 2; + } + if((mark->end - off) % 2) { + MD_LEAVE_SPAN(MD_SPAN_EM, NULL); + off++; + } + } + break; + + case '~': + if(mark->flags & MD_MARK_OPENER) + MD_ENTER_SPAN(MD_SPAN_DEL, NULL); + else + MD_LEAVE_SPAN(MD_SPAN_DEL, NULL); + break; + + case '[': /* Link, image. */ + case '!': + case ']': + { + const MD_MARK* opener = (mark->ch != ']' ? mark : &ctx->marks[mark->prev]); + const MD_MARK* dest_mark = opener+1; + const MD_MARK* title_mark = opener+2; + + MD_ASSERT(dest_mark->ch == 'D'); + MD_ASSERT(title_mark->ch == 'D'); + + MD_CHECK(md_enter_leave_span_a(ctx, (mark->ch != ']'), + (opener->ch == '!' ? MD_SPAN_IMG : MD_SPAN_A), + STR(dest_mark->beg), dest_mark->end - dest_mark->beg, FALSE, + md_mark_get_ptr(ctx, title_mark - ctx->marks), title_mark->prev)); + + /* link/image closer may span multiple lines. */ + if(mark->ch == ']') { + while(mark->end > line->end) + line++; + } + + break; + } + + case '<': + case '>': /* Autolink or raw HTML. */ + if(!(mark->flags & MD_MARK_AUTOLINK)) { + /* Raw HTML. */ + if(mark->flags & MD_MARK_OPENER) + text_type = MD_TEXT_HTML; + else + text_type = MD_TEXT_NORMAL; + break; + } + /* Pass through, if auto-link. */ + + case '@': /* Permissive e-mail autolink. */ + case ':': /* Permissive URL autolink. */ + case '.': /* Permissive WWW autolink. */ + { + MD_MARK* opener = ((mark->flags & MD_MARK_OPENER) ? mark : &ctx->marks[mark->prev]); + MD_MARK* closer = &ctx->marks[opener->next]; + const CHAR* dest = STR(opener->end); + SZ dest_size = closer->beg - opener->end; + + /* For permissive auto-links we do not know closer mark + * position at the time of md_collect_marks(), therefore + * it can be out-of-order in ctx->marks[]. + * + * With this flag, we make sure that we output the closer + * only if we processed the opener. */ + if(mark->flags & MD_MARK_OPENER) + closer->flags |= MD_MARK_VALIDPERMISSIVEAUTOLINK; + + if(opener->ch == '@' || opener->ch == '.') { + dest_size += 7; + MD_TEMP_BUFFER(dest_size * sizeof(CHAR)); + memcpy(ctx->buffer, + (opener->ch == '@' ? _T("mailto:") : _T("http://")), + 7 * sizeof(CHAR)); + memcpy(ctx->buffer + 7, dest, (dest_size-7) * sizeof(CHAR)); + dest = ctx->buffer; + } + + if(closer->flags & MD_MARK_VALIDPERMISSIVEAUTOLINK) + MD_CHECK(md_enter_leave_span_a(ctx, (mark->flags & MD_MARK_OPENER), + MD_SPAN_A, dest, dest_size, TRUE, NULL, 0)); + break; + } + + case '&': /* Entity. */ + MD_TEXT(MD_TEXT_ENTITY, STR(mark->beg), mark->end - mark->beg); + break; + + case '\0': + MD_TEXT(MD_TEXT_NULLCHAR, _T(""), 1); + break; + + case 127: + goto abort; + } + + off = mark->end; + + /* Move to next resolved mark. */ + prev_mark = mark; + mark++; + while(!(mark->flags & MD_MARK_RESOLVED) || mark->beg < off) + mark++; + } + + /* If reached end of line, move to next one. */ + if(off >= line->end) { + /* If it is the last line, we are done. */ + if(off >= end) + break; + + if(text_type == MD_TEXT_CODE) { + /* Inside code spans, new lines are transformed into single + * spaces. */ + MD_ASSERT(prev_mark != NULL); + MD_ASSERT(prev_mark->ch == '`' && (prev_mark->flags & MD_MARK_OPENER)); + MD_ASSERT(mark->ch == '`' && (mark->flags & MD_MARK_CLOSER)); + + if(prev_mark->end < off && off < mark->beg) + MD_TEXT(MD_TEXT_CODE, _T(" "), 1); + } else if(text_type == MD_TEXT_HTML) { + /* Inside raw HTML, we output the new line verbatim, including + * any trailing spaces. */ + OFF tmp = off; + + while(tmp < end && ISBLANK(tmp)) + tmp++; + if(tmp > off) + MD_TEXT(MD_TEXT_HTML, STR(off), tmp - off); + MD_TEXT(MD_TEXT_HTML, _T("\n"), 1); + } else { + /* Output soft or hard line break. */ + MD_TEXTTYPE break_type = MD_TEXT_SOFTBR; + + if(text_type == MD_TEXT_NORMAL) { + if(enforce_hardbreak) + break_type = MD_TEXT_BR; + else if((CH(line->end) == _T(' ') && CH(line->end+1) == _T(' '))) + break_type = MD_TEXT_BR; + } + + MD_TEXT(break_type, _T("\n"), 1); + } + + /* Move to the next line. */ + line++; + off = line->beg; + + enforce_hardbreak = 0; + } + } + +abort: + return ret; +} + + +/*************************** + *** Processing Tables *** + ***************************/ + +static void +md_analyze_table_alignment(MD_CTX* ctx, OFF beg, OFF end, MD_ALIGN* align, int n_align) +{ + static const MD_ALIGN align_map[] = { MD_ALIGN_DEFAULT, MD_ALIGN_LEFT, MD_ALIGN_RIGHT, MD_ALIGN_CENTER }; + OFF off = beg; + + while(n_align > 0) { + int index = 0; /* index into align_map[] */ + + while(CH(off) != _T('-')) + off++; + if(off > beg && CH(off-1) == _T(':')) + index |= 1; + while(off < end && CH(off) == _T('-')) + off++; + if(off < end && CH(off) == _T(':')) + index |= 2; + + *align = align_map[index]; + align++; + n_align--; + } + +} + +/* Forward declaration. */ +static int md_process_normal_block_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines); + +static int +md_process_table_cell(MD_CTX* ctx, MD_BLOCKTYPE cell_type, MD_ALIGN align, OFF beg, OFF end) +{ + MD_LINE line; + MD_BLOCK_TD_DETAIL det; + int ret = 0; + + while(beg < end && ISWHITESPACE(beg)) + beg++; + while(end > beg && ISWHITESPACE(end-1)) + end--; + + det.align = align; + line.beg = beg; + line.end = end; + + MD_ENTER_BLOCK(cell_type, &det); + MD_CHECK(md_process_normal_block_contents(ctx, &line, 1)); + MD_LEAVE_BLOCK(cell_type, &det); + +abort: + return ret; +} + +static int +md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end, + const MD_ALIGN* align, int col_count) +{ + MD_LINE line = { beg, end }; + OFF* pipe_offs = NULL; + int i, j, n; + int ret = 0; + + /* Break the line into table cells by identifying pipe characters who + * form the cell boundary. */ + MD_CHECK(md_analyze_inlines(ctx, &line, 1, TRUE)); + + /* We have to remember the cell boundaries in local buffer because + * ctx->marks[] shall be reused during cell contents processing. */ + n = ctx->n_table_cell_boundaries; + pipe_offs = (OFF*) malloc(n * sizeof(OFF)); + if(pipe_offs == NULL) { + MD_LOG("malloc() failed."); + ret = -1; + goto abort; + } + for(i = TABLECELLBOUNDARIES.head, j = 0; i >= 0; i = ctx->marks[i].next) { + MD_MARK* mark = &ctx->marks[i]; + pipe_offs[j++] = mark->beg; + } + + /* Process cells. */ + MD_ENTER_BLOCK(MD_BLOCK_TR, NULL); + j = 0; + if(beg < pipe_offs[0] && j < col_count) + MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], beg, pipe_offs[0])); + for(i = 0; i < n-1 && j < col_count; i++) + MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], pipe_offs[i]+1, pipe_offs[i+1])); + if(pipe_offs[n-1] < end-1 && j < col_count) + MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], pipe_offs[n-1]+1, end)); + /* Make sure we call enough table cells even if the current table contains + * too few of them. */ + while(j < col_count) + MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], 0, 0)); + + MD_LEAVE_BLOCK(MD_BLOCK_TR, NULL); + +abort: + free(pipe_offs); + + /* Free any temporary memory blocks stored within some dummy marks. */ + for(i = PTR_CHAIN.head; i >= 0; i = ctx->marks[i].next) + free(md_mark_get_ptr(ctx, i)); + PTR_CHAIN.head = -1; + PTR_CHAIN.tail = -1; + + return ret; +} + +static int +md_process_table_block_contents(MD_CTX* ctx, int col_count, const MD_LINE* lines, int n_lines) +{ + MD_ALIGN* align; + int i; + int ret = 0; + + /* At least two lines have to be present: The column headers and the line + * with the underlines. */ + MD_ASSERT(n_lines >= 2); + + align = malloc(col_count * sizeof(MD_ALIGN)); + if(align == NULL) { + MD_LOG("malloc() failed."); + ret = -1; + goto abort; + } + + md_analyze_table_alignment(ctx, lines[1].beg, lines[1].end, align, col_count); + + MD_ENTER_BLOCK(MD_BLOCK_THEAD, NULL); + MD_CHECK(md_process_table_row(ctx, MD_BLOCK_TH, + lines[0].beg, lines[0].end, align, col_count)); + MD_LEAVE_BLOCK(MD_BLOCK_THEAD, NULL); + + MD_ENTER_BLOCK(MD_BLOCK_TBODY, NULL); + for(i = 2; i < n_lines; i++) { + MD_CHECK(md_process_table_row(ctx, MD_BLOCK_TD, + lines[i].beg, lines[i].end, align, col_count)); + } + MD_LEAVE_BLOCK(MD_BLOCK_TBODY, NULL); + +abort: + free(align); + return ret; +} + +static int +md_is_table_row(MD_CTX* ctx, OFF beg, OFF* p_end) +{ + MD_LINE line = { beg, beg }; + int i; + int ret = FALSE; + + /* Find end of line. */ + while(line.end < ctx->size && !ISNEWLINE(line.end)) + line.end++; + + MD_CHECK(md_analyze_inlines(ctx, &line, 1, TRUE)); + + if(TABLECELLBOUNDARIES.head >= 0) { + if(p_end != NULL) + *p_end = line.end; + ret = TRUE; + } + +abort: + /* Free any temporary memory blocks stored within some dummy marks. */ + for(i = PTR_CHAIN.head; i >= 0; i = ctx->marks[i].next) + free(md_mark_get_ptr(ctx, i)); + PTR_CHAIN.head = -1; + PTR_CHAIN.tail = -1; + + return ret; +} + + +/************************** + *** Processing Block *** + **************************/ + +#define MD_BLOCK_CONTAINER_OPENER 0x01 +#define MD_BLOCK_CONTAINER_CLOSER 0x02 +#define MD_BLOCK_CONTAINER (MD_BLOCK_CONTAINER_OPENER | MD_BLOCK_CONTAINER_CLOSER) +#define MD_BLOCK_LOOSE_LIST 0x04 + +struct MD_BLOCK_tag { + MD_BLOCKTYPE type : 8; + unsigned flags : 8; + + /* MD_BLOCK_H: Header level (1 - 6) + * MD_BLOCK_CODE: Non-zero if fenced, zero if indented. + * MD_BLOCK_LI: Task mark character (0 if not task list item, 'x', 'X' or ' '). + * MD_BLOCK_TABLE: Column count (as determined by the table underline). + */ + unsigned data : 16; + + /* Leaf blocks: Count of lines (MD_LINE or MD_VERBATIMLINE) on the block. + * MD_BLOCK_LI: Task mark offset in the input doc. + * MD_BLOCK_OL: Start item number. + */ + unsigned n_lines; +}; + +struct MD_CONTAINER_tag { + CHAR ch; + unsigned is_loose : 8; + unsigned is_task : 8; + unsigned start; + unsigned mark_indent; + unsigned contents_indent; + OFF block_byte_off; + OFF task_mark_off; +}; + + +static int +md_process_normal_block_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines) +{ + int i; + int ret; + + MD_CHECK(md_analyze_inlines(ctx, lines, n_lines, FALSE)); + MD_CHECK(md_process_inlines(ctx, lines, n_lines)); + +abort: + /* Free any temporary memory blocks stored within some dummy marks. */ + for(i = PTR_CHAIN.head; i >= 0; i = ctx->marks[i].next) + free(md_mark_get_ptr(ctx, i)); + PTR_CHAIN.head = -1; + PTR_CHAIN.tail = -1; + + return ret; +} + +static int +md_process_verbatim_block_contents(MD_CTX* ctx, MD_TEXTTYPE text_type, const MD_VERBATIMLINE* lines, int n_lines) +{ + static const CHAR indent_chunk_str[] = _T(" "); + static const SZ indent_chunk_size = SIZEOF_ARRAY(indent_chunk_str) - 1; + + int i; + int ret = 0; + + for(i = 0; i < n_lines; i++) { + const MD_VERBATIMLINE* line = &lines[i]; + int indent = line->indent; + + MD_ASSERT(indent >= 0); + + /* Output code indentation. */ + while(indent > SIZEOF_ARRAY(indent_chunk_str)) { + MD_TEXT(text_type, indent_chunk_str, indent_chunk_size); + indent -= SIZEOF_ARRAY(indent_chunk_str); + } + if(indent > 0) + MD_TEXT(text_type, indent_chunk_str, indent); + + /* Output the code line itself. */ + MD_TEXT_INSECURE(text_type, STR(line->beg), line->end - line->beg); + + /* Enforce end-of-line. */ + MD_TEXT(text_type, _T("\n"), 1); + } + +abort: + return ret; +} + +static int +md_process_code_block_contents(MD_CTX* ctx, int is_fenced, const MD_VERBATIMLINE* lines, int n_lines) +{ + if(is_fenced) { + /* Skip the first line in case of fenced code: It is the fence. + * (Only the starting fence is present due to logic in md_analyze_line().) */ + lines++; + n_lines--; + } else { + /* Ignore blank lines at start/end of indented code block. */ + while(n_lines > 0 && lines[0].beg == lines[0].end) { + lines++; + n_lines--; + } + while(n_lines > 0 && lines[n_lines-1].beg == lines[n_lines-1].end) { + n_lines--; + } + } + + if(n_lines == 0) + return 0; + + return md_process_verbatim_block_contents(ctx, MD_TEXT_CODE, lines, n_lines); +} + +static int +md_setup_fenced_code_detail(MD_CTX* ctx, const MD_BLOCK* block, MD_BLOCK_CODE_DETAIL* det, + MD_ATTRIBUTE_BUILD* info_build, MD_ATTRIBUTE_BUILD* lang_build) +{ + const MD_VERBATIMLINE* fence_line = (const MD_VERBATIMLINE*)(block + 1); + OFF beg = fence_line->beg; + OFF end = fence_line->end; + OFF lang_end; + CHAR fence_ch = CH(fence_line->beg); + int ret = 0; + + /* Skip the fence itself. */ + while(beg < ctx->size && CH(beg) == fence_ch) + beg++; + /* Trim initial spaces. */ + while(beg < ctx->size && CH(beg) == _T(' ')) + beg++; + + /* Trim trailing spaces. */ + while(end > beg && CH(end-1) == _T(' ')) + end--; + + /* Build info string attribute. */ + MD_CHECK(md_build_attribute(ctx, STR(beg), end - beg, 0, &det->info, info_build)); + + /* Build info string attribute. */ + lang_end = beg; + while(lang_end < end && !ISWHITESPACE(lang_end)) + lang_end++; + MD_CHECK(md_build_attribute(ctx, STR(beg), lang_end - beg, 0, &det->lang, lang_build)); + +abort: + return ret; +} + +static int +md_process_leaf_block(MD_CTX* ctx, const MD_BLOCK* block) +{ + union { + MD_BLOCK_H_DETAIL header; + MD_BLOCK_CODE_DETAIL code; + } det; + MD_ATTRIBUTE_BUILD info_build; + MD_ATTRIBUTE_BUILD lang_build; + int is_in_tight_list; + int clean_fence_code_detail = FALSE; + int ret = 0; + + memset(&det, 0, sizeof(det)); + + if(ctx->n_containers == 0) + is_in_tight_list = FALSE; + else + is_in_tight_list = !ctx->containers[ctx->n_containers-1].is_loose; + + switch(block->type) { + case MD_BLOCK_H: + det.header.level = block->data; + break; + + case MD_BLOCK_CODE: + /* For fenced code block, we may need to set the info string. */ + if(block->data != 0) { + memset(&det.code, 0, sizeof(MD_BLOCK_CODE_DETAIL)); + clean_fence_code_detail = TRUE; + MD_CHECK(md_setup_fenced_code_detail(ctx, block, &det.code, &info_build, &lang_build)); + } + break; + + default: + /* Noop. */ + break; + } + + if(!is_in_tight_list || block->type != MD_BLOCK_P) + MD_ENTER_BLOCK(block->type, (void*) &det); + + /* Process the block contents accordingly to is type. */ + switch(block->type) { + case MD_BLOCK_HR: + /* noop */ + break; + + case MD_BLOCK_CODE: + MD_CHECK(md_process_code_block_contents(ctx, (block->data != 0), + (const MD_VERBATIMLINE*)(block + 1), block->n_lines)); + break; + + case MD_BLOCK_HTML: + MD_CHECK(md_process_verbatim_block_contents(ctx, MD_TEXT_HTML, + (const MD_VERBATIMLINE*)(block + 1), block->n_lines)); + break; + + case MD_BLOCK_TABLE: + MD_CHECK(md_process_table_block_contents(ctx, block->data, + (const MD_LINE*)(block + 1), block->n_lines)); + break; + + default: + MD_CHECK(md_process_normal_block_contents(ctx, + (const MD_LINE*)(block + 1), block->n_lines)); + break; + } + + if(!is_in_tight_list || block->type != MD_BLOCK_P) + MD_LEAVE_BLOCK(block->type, (void*) &det); + +abort: + if(clean_fence_code_detail) { + md_free_attribute(ctx, &info_build); + md_free_attribute(ctx, &lang_build); + } + return ret; +} + +static int +md_process_all_blocks(MD_CTX* ctx) +{ + int byte_off = 0; + int ret = 0; + + /* ctx->containers now is not needed for detection of lists and list items + * so we reuse it for tracking what lists are loose or tight. We rely + * on the fact the vector is large enough to hold the deepest nesting + * level of lists. */ + ctx->n_containers = 0; + + while(byte_off < ctx->n_block_bytes) { + MD_BLOCK* block = (MD_BLOCK*)((char*)ctx->block_bytes + byte_off); + union { + MD_BLOCK_UL_DETAIL ul; + MD_BLOCK_OL_DETAIL ol; + MD_BLOCK_LI_DETAIL li; + } det; + + switch(block->type) { + case MD_BLOCK_UL: + det.ul.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? FALSE : TRUE; + det.ul.mark = (CHAR) block->data; + break; + + case MD_BLOCK_OL: + det.ol.start = block->n_lines; + det.ol.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? FALSE : TRUE; + det.ol.mark_delimiter = (CHAR) block->data; + break; + + case MD_BLOCK_LI: + det.li.is_task = (block->data != 0); + det.li.task_mark = (CHAR) block->data; + det.li.task_mark_offset = (OFF) block->n_lines; + break; + + default: + /* noop */ + break; + } + + if(block->flags & MD_BLOCK_CONTAINER) { + if(block->flags & MD_BLOCK_CONTAINER_CLOSER) { + MD_LEAVE_BLOCK(block->type, &det); + + if(block->type == MD_BLOCK_UL || block->type == MD_BLOCK_OL || block->type == MD_BLOCK_QUOTE) + ctx->n_containers--; + } + + if(block->flags & MD_BLOCK_CONTAINER_OPENER) { + MD_ENTER_BLOCK(block->type, &det); + + if(block->type == MD_BLOCK_UL || block->type == MD_BLOCK_OL) { + ctx->containers[ctx->n_containers].is_loose = (block->flags & MD_BLOCK_LOOSE_LIST); + ctx->n_containers++; + } else if(block->type == MD_BLOCK_QUOTE) { + /* This causes that any text in a block quote, even if + * nested inside a tight list item, is wrapped with + *

...

. */ + ctx->containers[ctx->n_containers].is_loose = TRUE; + ctx->n_containers++; + } + } + } else { + MD_CHECK(md_process_leaf_block(ctx, block)); + + if(block->type == MD_BLOCK_CODE || block->type == MD_BLOCK_HTML) + byte_off += block->n_lines * sizeof(MD_VERBATIMLINE); + else + byte_off += block->n_lines * sizeof(MD_LINE); + } + + byte_off += sizeof(MD_BLOCK); + } + + ctx->n_block_bytes = 0; + +abort: + return ret; +} + + +/************************************ + *** Grouping Lines into Blocks *** + ************************************/ + +static void* +md_push_block_bytes(MD_CTX* ctx, int n_bytes) +{ + void* ptr; + + if(ctx->n_block_bytes + n_bytes > ctx->alloc_block_bytes) { + void* new_block_bytes; + + ctx->alloc_block_bytes = (ctx->alloc_block_bytes > 0 ? ctx->alloc_block_bytes * 2 : 512); + new_block_bytes = realloc(ctx->block_bytes, ctx->alloc_block_bytes); + if(new_block_bytes == NULL) { + MD_LOG("realloc() failed."); + return NULL; + } + + /* Fix the ->current_block after the reallocation. */ + if(ctx->current_block != NULL) { + OFF off_current_block = (char*) ctx->current_block - (char*) ctx->block_bytes; + ctx->current_block = (MD_BLOCK*) ((char*) new_block_bytes + off_current_block); + } + + ctx->block_bytes = new_block_bytes; + } + + ptr = (char*)ctx->block_bytes + ctx->n_block_bytes; + ctx->n_block_bytes += n_bytes; + return ptr; +} + +static int +md_start_new_block(MD_CTX* ctx, const MD_LINE_ANALYSIS* line) +{ + MD_BLOCK* block; + + MD_ASSERT(ctx->current_block == NULL); + + block = (MD_BLOCK*) md_push_block_bytes(ctx, sizeof(MD_BLOCK)); + if(block == NULL) + return -1; + + switch(line->type) { + case MD_LINE_HR: + block->type = MD_BLOCK_HR; + break; + + case MD_LINE_ATXHEADER: + case MD_LINE_SETEXTHEADER: + block->type = MD_BLOCK_H; + break; + + case MD_LINE_FENCEDCODE: + case MD_LINE_INDENTEDCODE: + block->type = MD_BLOCK_CODE; + break; + + case MD_LINE_TEXT: + block->type = MD_BLOCK_P; + break; + + case MD_LINE_HTML: + block->type = MD_BLOCK_HTML; + break; + + case MD_LINE_BLANK: + case MD_LINE_SETEXTUNDERLINE: + case MD_LINE_TABLEUNDERLINE: + default: + MD_UNREACHABLE(); + break; + } + + block->flags = 0; + block->data = line->data; + block->n_lines = 0; + + ctx->current_block = block; + return 0; +} + +/* Eat from start of current (textual) block any reference definitions and + * remember them so we can resolve any links referring to them. + * + * (Reference definitions can only be at start of it as they cannot break + * a paragraph.) + */ +static int +md_consume_link_reference_definitions(MD_CTX* ctx) +{ + MD_LINE* lines = (MD_LINE*) (ctx->current_block + 1); + int n_lines = ctx->current_block->n_lines; + int n = 0; + + /* Compute how many lines at the start of the block form one or more + * reference definitions. */ + while(n < n_lines) { + int n_link_ref_lines; + + n_link_ref_lines = md_is_link_reference_definition(ctx, + lines + n, n_lines - n); + /* Not a reference definition? */ + if(n_link_ref_lines == 0) + break; + + /* We fail if it is the ref. def. but it could not be stored due + * a memory allocation error. */ + if(n_link_ref_lines < 0) + return -1; + + n += n_link_ref_lines; + } + + /* If there was at least one reference definition, we need to remove + * its lines from the block, or perhaps even the whole block. */ + if(n > 0) { + if(n == n_lines) { + /* Remove complete block. */ + ctx->n_block_bytes -= n * sizeof(MD_LINE); + ctx->n_block_bytes -= sizeof(MD_BLOCK); + } else { + /* Remove just some initial lines from the block. */ + memmove(lines, lines + n, (n_lines - n) * sizeof(MD_LINE)); + ctx->current_block->n_lines -= n; + ctx->n_block_bytes -= n * sizeof(MD_LINE); + } + } + + return 0; +} + +static int +md_end_current_block(MD_CTX* ctx) +{ + int ret = 0; + + if(ctx->current_block == NULL) + return ret; + + /* Check whether there is a reference definition. (We do this here instead + * of in md_analyze_line() because reference definition can take multiple + * lines.) */ + if(ctx->current_block->type == MD_BLOCK_P) { + MD_LINE* lines = (MD_LINE*) (ctx->current_block + 1); + if(CH(lines[0].beg) == _T('[')) + MD_CHECK(md_consume_link_reference_definitions(ctx)); + } + + /* Mark we are not building any block anymore. */ + ctx->current_block = NULL; + +abort: + return ret; +} + +static int +md_add_line_into_current_block(MD_CTX* ctx, const MD_LINE_ANALYSIS* analysis) +{ + MD_ASSERT(ctx->current_block != NULL); + + if(ctx->current_block->type == MD_BLOCK_CODE || ctx->current_block->type == MD_BLOCK_HTML) { + MD_VERBATIMLINE* line; + + line = (MD_VERBATIMLINE*) md_push_block_bytes(ctx, sizeof(MD_VERBATIMLINE)); + if(line == NULL) + return -1; + + line->indent = analysis->indent; + line->beg = analysis->beg; + line->end = analysis->end; + } else { + MD_LINE* line; + + line = (MD_LINE*) md_push_block_bytes(ctx, sizeof(MD_LINE)); + if(line == NULL) + return -1; + + line->beg = analysis->beg; + line->end = analysis->end; + } + ctx->current_block->n_lines++; + + return 0; +} + +static int +md_push_container_bytes(MD_CTX* ctx, MD_BLOCKTYPE type, unsigned start, + unsigned data, unsigned flags) +{ + MD_BLOCK* block; + int ret = 0; + + MD_CHECK(md_end_current_block(ctx)); + + block = (MD_BLOCK*) md_push_block_bytes(ctx, sizeof(MD_BLOCK)); + if(block == NULL) + return -1; + + block->type = type; + block->flags = flags; + block->data = data; + block->n_lines = start; + +abort: + return ret; +} + + + +/*********************** + *** Line Analysis *** + ***********************/ + +static int +md_is_hr_line(MD_CTX* ctx, OFF beg, OFF* p_end) +{ + OFF off = beg + 1; + int n = 1; + + while(off < ctx->size && (CH(off) == CH(beg) || CH(off) == _T(' ') || CH(off) == _T('\t'))) { + if(CH(off) == CH(beg)) + n++; + off++; + } + + if(n < 3) + return FALSE; + + /* Nothing else can be present on the line. */ + if(off < ctx->size && !ISNEWLINE(off)) + return FALSE; + + *p_end = off; + return TRUE; +} + +static int +md_is_atxheader_line(MD_CTX* ctx, OFF beg, OFF* p_beg, OFF* p_end, unsigned* p_level) +{ + int n; + OFF off = beg + 1; + + while(off < ctx->size && CH(off) == _T('#') && off - beg < 7) + off++; + n = off - beg; + + if(n > 6) + return FALSE; + *p_level = n; + + if(!(ctx->parser.flags & MD_FLAG_PERMISSIVEATXHEADERS) && off < ctx->size && + CH(off) != _T(' ') && CH(off) != _T('\t') && !ISNEWLINE(off)) + return FALSE; + + while(off < ctx->size && CH(off) == _T(' ')) + off++; + *p_beg = off; + *p_end = off; + return TRUE; +} + +static int +md_is_setext_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_level) +{ + OFF off = beg + 1; + + while(off < ctx->size && CH(off) == CH(beg)) + off++; + + while(off < ctx->size && CH(off) == _T(' ')) + off++; + + /* Optionally, space(s) can follow. */ + while(off < ctx->size && CH(off) == _T(' ')) + off++; + + /* But nothing more is allowed on the line. */ + if(off < ctx->size && !ISNEWLINE(off)) + return FALSE; + + *p_level = (CH(beg) == _T('=') ? 1 : 2); + *p_end = off; + return TRUE; +} + +static int +md_is_table_underline(MD_CTX* ctx, OFF beg, OFF* p_end, unsigned* p_col_count) +{ + OFF off = beg; + int found_pipe = FALSE; + unsigned col_count = 0; + + if(off < ctx->size && CH(off) == _T('|')) { + found_pipe = TRUE; + off++; + while(off < ctx->size && ISWHITESPACE(off)) + off++; + } + + while(1) { + OFF cell_beg; + int delimited = FALSE; + + /* Cell underline ("-----", ":----", "----:" or ":----:") */ + cell_beg = off; + if(off < ctx->size && CH(off) == _T(':')) + off++; + while(off < ctx->size && CH(off) == _T('-')) + off++; + if(off < ctx->size && CH(off) == _T(':')) + off++; + if(off - cell_beg < 3) + return FALSE; + + col_count++; + + /* Pipe delimiter (optional at the end of line). */ + while(off < ctx->size && ISWHITESPACE(off)) + off++; + if(off < ctx->size && CH(off) == _T('|')) { + delimited = TRUE; + found_pipe = TRUE; + off++; + while(off < ctx->size && ISWHITESPACE(off)) + off++; + } + + /* Success, if we reach end of line. */ + if(off >= ctx->size || ISNEWLINE(off)) + break; + + if(!delimited) + return FALSE; + } + + if(!found_pipe) + return FALSE; + + *p_end = off; + *p_col_count = col_count; + return TRUE; +} + +static int +md_is_opening_code_fence(MD_CTX* ctx, OFF beg, OFF* p_end) +{ + OFF off = beg; + + while(off < ctx->size && CH(off) == CH(beg)) + off++; + + /* Fence must have at least three characters. */ + if(off - beg < 3) + return FALSE; + + ctx->code_fence_length = off - beg; + + /* Optionally, space(s) can follow. */ + while(off < ctx->size && CH(off) == _T(' ')) + off++; + + /* Optionally, an info string can follow. It must not contain '`'. */ + while(off < ctx->size && CH(off) != _T('`') && !ISNEWLINE(off)) + off++; + if(off < ctx->size && !ISNEWLINE(off)) + return FALSE; + + *p_end = off; + return TRUE; +} + +static int +md_is_closing_code_fence(MD_CTX* ctx, CHAR ch, OFF beg, OFF* p_end) +{ + OFF off = beg; + int ret = FALSE; + + /* Closing fence must have at least the same length and use same char as + * opening one. */ + while(off < ctx->size && CH(off) == ch) + off++; + if(off - beg < ctx->code_fence_length) + goto out; + + /* Optionally, space(s) can follow */ + while(off < ctx->size && CH(off) == _T(' ')) + off++; + + /* But nothing more is allowed on the line. */ + if(off < ctx->size && !ISNEWLINE(off)) + goto out; + + ret = TRUE; + +out: + /* Note we set *p_end even on failure: If we are not closing fence, caller + * would eat the line anyway without any parsing. */ + *p_end = off; + return ret; +} + +/* Returns type of the raw HTML block, or FALSE if it is not HTML block. + * (Refer to CommonMark specification for details about the types.) + */ +static int +md_is_html_block_start_condition(MD_CTX* ctx, OFF beg) +{ + typedef struct TAG_tag TAG; + struct TAG_tag { + const CHAR* name; + unsigned len : 8; + }; + + /* Type 6 is started by a long list of allowed tags. We use two-level + * tree to speed-up the search. */ +#ifdef X + #undef X +#endif +#define X(name) { _T(name), sizeof(name)-1 } +#define Xend { NULL, 0 } + static const TAG t1[] = { X("script"), X("pre"), X("style"), Xend }; + + static const TAG a6[] = { X("address"), X("article"), X("aside"), Xend }; + static const TAG b6[] = { X("base"), X("basefont"), X("blockquote"), X("body"), Xend }; + static const TAG c6[] = { X("caption"), X("center"), X("col"), X("colgroup"), Xend }; + static const TAG d6[] = { X("dd"), X("details"), X("dialog"), X("dir"), + X("div"), X("dl"), X("dt"), Xend }; + static const TAG f6[] = { X("fieldset"), X("figcaption"), X("figure"), X("footer"), + X("form"), X("frame"), X("frameset"), Xend }; + static const TAG h6[] = { X("h1"), X("head"), X("header"), X("hr"), X("html"), Xend }; + static const TAG i6[] = { X("iframe"), Xend }; + static const TAG l6[] = { X("legend"), X("li"), X("link"), Xend }; + static const TAG m6[] = { X("main"), X("menu"), X("menuitem"), X("meta"), Xend }; + static const TAG n6[] = { X("nav"), X("noframes"), Xend }; + static const TAG o6[] = { X("ol"), X("optgroup"), X("option"), Xend }; + static const TAG p6[] = { X("p"), X("param"), Xend }; + static const TAG s6[] = { X("section"), X("source"), X("summary"), Xend }; + static const TAG t6[] = { X("table"), X("tbody"), X("td"), X("tfoot"), X("th"), + X("thead"), X("title"), X("tr"), X("track"), Xend }; + static const TAG u6[] = { X("ul"), Xend }; + static const TAG xx[] = { Xend }; +#undef X + + static const TAG* map6[26] = { + a6, b6, c6, d6, xx, f6, xx, h6, i6, xx, xx, l6, m6, + n6, o6, p6, xx, xx, s6, t6, u6, xx, xx, xx, xx, xx + }; + OFF off = beg + 1; + int i; + + /* Check for type 1: size) { + if(md_ascii_case_eq(STR(off), t1[i].name, t1[i].len)) + return 1; + } + } + + /* Check for type 2: "), 3, p_end) ? 2 : FALSE); + + case 3: + return (md_line_contains(ctx, beg, _T("?>"), 2, p_end) ? 3 : FALSE); + + case 4: + return (md_line_contains(ctx, beg, _T(">"), 1, p_end) ? 4 : FALSE); + + case 5: + return (md_line_contains(ctx, beg, _T("]]>"), 3, p_end) ? 5 : FALSE); + + case 6: /* Pass through */ + case 7: + *p_end = beg; + return (ISNEWLINE(beg) ? ctx->html_block_type : FALSE); + + default: + MD_UNREACHABLE(); + } +} + + +static int +md_is_container_compatible(const MD_CONTAINER* pivot, const MD_CONTAINER* container) +{ + /* Block quote has no "items" like lists. */ + if(container->ch == _T('>')) + return FALSE; + + if(container->ch != pivot->ch) + return FALSE; + if(container->mark_indent > pivot->contents_indent) + return FALSE; + + return TRUE; +} + +static int +md_push_container(MD_CTX* ctx, const MD_CONTAINER* container) +{ + if(ctx->n_containers >= ctx->alloc_containers) { + MD_CONTAINER* new_containers; + + ctx->alloc_containers = (ctx->alloc_containers > 0 ? ctx->alloc_containers * 2 : 16); + new_containers = realloc(ctx->containers, ctx->alloc_containers * sizeof(MD_CONTAINER)); + if(new_containers == NULL) { + MD_LOG("realloc() failed."); + return -1; + } + + ctx->containers = new_containers; + } + + memcpy(&ctx->containers[ctx->n_containers++], container, sizeof(MD_CONTAINER)); + return 0; +} + +static int +md_enter_child_containers(MD_CTX* ctx, int n_children, unsigned data) +{ + int i; + int ret = 0; + + for(i = ctx->n_containers - n_children; i < ctx->n_containers; i++) { + MD_CONTAINER* c = &ctx->containers[i]; + int is_ordered_list = FALSE; + + switch(c->ch) { + case _T(')'): + case _T('.'): + is_ordered_list = TRUE; + /* Pass through */ + + case _T('-'): + case _T('+'): + case _T('*'): + /* Remember offset in ctx->block_bytes so we can revisit the + * block if we detect it is a loose list. */ + md_end_current_block(ctx); + c->block_byte_off = ctx->n_block_bytes; + + MD_CHECK(md_push_container_bytes(ctx, + (is_ordered_list ? MD_BLOCK_OL : MD_BLOCK_UL), + c->start, data, MD_BLOCK_CONTAINER_OPENER)); + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + c->task_mark_off, + (c->is_task ? CH(c->task_mark_off) : 0), + MD_BLOCK_CONTAINER_OPENER)); + break; + + case _T('>'): + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, 0, 0, MD_BLOCK_CONTAINER_OPENER)); + break; + + default: + MD_UNREACHABLE(); + break; + } + } + +abort: + return ret; +} + +static int +md_leave_child_containers(MD_CTX* ctx, int n_keep) +{ + int ret = 0; + + while(ctx->n_containers > n_keep) { + MD_CONTAINER* c = &ctx->containers[ctx->n_containers-1]; + int is_ordered_list = FALSE; + + switch(c->ch) { + case _T(')'): + case _T('.'): + is_ordered_list = TRUE; + /* Pass through */ + + case _T('-'): + case _T('+'): + case _T('*'): + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + c->task_mark_off, (c->is_task ? CH(c->task_mark_off) : 0), + MD_BLOCK_CONTAINER_CLOSER)); + MD_CHECK(md_push_container_bytes(ctx, + (is_ordered_list ? MD_BLOCK_OL : MD_BLOCK_UL), 0, + c->ch, MD_BLOCK_CONTAINER_CLOSER)); + break; + + case _T('>'): + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, 0, + 0, MD_BLOCK_CONTAINER_CLOSER)); + break; + + default: + MD_UNREACHABLE(); + break; + } + + ctx->n_containers--; + } + +abort: + return ret; +} + +static int +md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTAINER* p_container) +{ + OFF off = beg; + OFF max_end; + + /* Check for block quote mark. */ + if(off < ctx->size && CH(off) == _T('>')) { + off++; + p_container->ch = _T('>'); + p_container->is_loose = FALSE; + p_container->is_task = FALSE; + p_container->mark_indent = indent; + p_container->contents_indent = indent + 1; + *p_end = off; + return TRUE; + } + + /* Check for list item bullet mark. */ + if(off+1 < ctx->size && ISANYOF(off, _T("-+*")) && (ISBLANK(off+1) || ISNEWLINE(off+1))) { + p_container->ch = CH(off); + p_container->is_loose = FALSE; + p_container->is_task = FALSE; + p_container->mark_indent = indent; + p_container->contents_indent = indent + 1; + *p_end = off + 1; + return TRUE; + } + + /* Check for ordered list item marks. */ + max_end = off + 9; + if(max_end > ctx->size) + max_end = ctx->size; + p_container->start = 0; + while(off < max_end && ISDIGIT(off)) { + p_container->start = p_container->start * 10 + CH(off) - _T('0'); + off++; + } + if(off+1 < ctx->size && (CH(off) == _T('.') || CH(off) == _T(')')) && (ISBLANK(off+1) || ISNEWLINE(off+1))) { + p_container->ch = CH(off); + p_container->is_loose = FALSE; + p_container->is_task = FALSE; + p_container->mark_indent = indent; + p_container->contents_indent = indent + off - beg + 1; + *p_end = off + 1; + return TRUE; + } + + return FALSE; +} + +static unsigned +md_line_indentation(MD_CTX* ctx, unsigned total_indent, OFF beg, OFF* p_end) +{ + OFF off = beg; + unsigned indent = total_indent; + + while(off < ctx->size && ISBLANK(off)) { + if(CH(off) == _T('\t')) + indent = (indent + 4) & ~3; + else + indent++; + off++; + } + + *p_end = off; + return indent - total_indent; +} + +static const MD_LINE_ANALYSIS md_dummy_blank_line = { MD_LINE_BLANK, 0 }; + +/* Analyze type of the line and find some its properties. This serves as a + * main input for determining type and boundaries of a block. */ +static int +md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, + const MD_LINE_ANALYSIS* pivot_line, MD_LINE_ANALYSIS* line) +{ + unsigned total_indent = 0; + int n_parents = 0; + int n_brothers = 0; + int n_children = 0; + MD_CONTAINER container = { 0 }; + int prev_line_has_list_loosening_effect = ctx->last_line_has_list_loosening_effect; + OFF off = beg; + int ret = 0; + + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + line->beg = off; + + /* Given the indentation and block quote marks '>', determine how many of + * the current containers are our parents. */ + while(n_parents < ctx->n_containers) { + MD_CONTAINER* c = &ctx->containers[n_parents]; + + if(c->ch == _T('>') && line->indent < ctx->code_indent_offset && + off < ctx->size && CH(off) == _T('>')) + { + /* Block quote mark. */ + off++; + total_indent++; + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + + /* The optional 1st space after '>' is part of the block quote mark. */ + if(line->indent > 0) + line->indent--; + + line->beg = off; + } else if(c->ch != _T('>') && line->indent >= c->contents_indent) { + /* List. */ + line->indent -= c->contents_indent; + } else { + break; + } + + n_parents++; + } + +redo: + /* Check whether we are fenced code continuation. */ + if(pivot_line->type == MD_LINE_FENCEDCODE) { + line->beg = off; + + /* We are another MD_LINE_FENCEDCODE unless we are closing fence + * which we transform into MD_LINE_BLANK. */ + if(line->indent < ctx->code_indent_offset) { + if(md_is_closing_code_fence(ctx, CH(pivot_line->beg), off, &off)) { + line->type = MD_LINE_BLANK; + ctx->last_line_has_list_loosening_effect = FALSE; + goto done; + } + } + + if(off >= ctx->size || ISNEWLINE(off)) { + /* Blank line does not need any real indentation to be nested inside + * a list. */ + if(n_brothers + n_children == 0) { + while(n_parents < ctx->n_containers && ctx->containers[n_parents].ch != _T('>')) + n_parents++; + } + } + + /* Change indentation accordingly to the initial code fence. */ + if(n_parents == ctx->n_containers) { + if(line->indent > pivot_line->indent) + line->indent -= pivot_line->indent; + else + line->indent = 0; + + line->type = MD_LINE_FENCEDCODE; + goto done; + } + } + + /* Check whether we are HTML block continuation. */ + if(pivot_line->type == MD_LINE_HTML && ctx->html_block_type > 0) { + int html_block_type; + + html_block_type = md_is_html_block_end_condition(ctx, off, &off); + if(html_block_type > 0) { + MD_ASSERT(html_block_type == ctx->html_block_type); + + /* Make sure this is the last line of the block. */ + ctx->html_block_type = 0; + + /* Some end conditions serve as blank lines at the same time. */ + if(html_block_type == 6 || html_block_type == 7) { + line->type = MD_LINE_BLANK; + line->indent = 0; + goto done; + } + } + + if(n_parents == ctx->n_containers) { + line->type = MD_LINE_HTML; + goto done; + } + } + + /* Check for blank line. */ + if(off >= ctx->size || ISNEWLINE(off)) { + /* Blank line does not need any real indentation to be nested inside + * a list. */ + if(n_brothers + n_children == 0) { + while(n_parents < ctx->n_containers && ctx->containers[n_parents].ch != _T('>')) + n_parents++; + } + + if(pivot_line->type == MD_LINE_INDENTEDCODE && n_parents == ctx->n_containers) { + line->type = MD_LINE_INDENTEDCODE; + if(line->indent > ctx->code_indent_offset) + line->indent -= ctx->code_indent_offset; + else + line->indent = 0; + ctx->last_line_has_list_loosening_effect = FALSE; + } else { + line->type = MD_LINE_BLANK; + ctx->last_line_has_list_loosening_effect = (n_parents > 0 && + n_brothers + n_children == 0 && + ctx->containers[n_parents-1].ch != _T('>')); + +#if 1 + /* See https://github.com/mity/md4c/issues/6 + * + * This ugly checking tests we are in (yet empty) list item but not + * its very first line (with the list item mark). + * + * If we are such blank line, then any following non-blank line + * which would be part of this list item actually ends the list + * because "a list item can begin with at most one blank line." + */ + if(n_parents > 0 && ctx->containers[n_parents-1].ch != _T('>') && + n_brothers + n_children == 0 && ctx->current_block == NULL && + ctx->n_block_bytes > sizeof(MD_BLOCK)) + { + MD_BLOCK* top_block = (MD_BLOCK*) ((char*)ctx->block_bytes + ctx->n_block_bytes - sizeof(MD_BLOCK)); + if(top_block->type == MD_BLOCK_LI) + ctx->last_list_item_starts_with_two_blank_lines = TRUE; + } +#endif + } + goto done_on_eol; + } else { +#if 1 + /* This is 2nd half of the hack. If the flag is set (that is there + * were 2nd blank line at the start of the list item) and we would also + * belonging to such list item, then interrupt the list. */ + ctx->last_line_has_list_loosening_effect = FALSE; + if(ctx->last_list_item_starts_with_two_blank_lines) { + if(n_parents > 0 && ctx->containers[n_parents-1].ch != _T('>') && + n_brothers + n_children == 0 && ctx->current_block == NULL && + ctx->n_block_bytes > sizeof(MD_BLOCK)) + { + MD_BLOCK* top_block = (MD_BLOCK*) ((char*)ctx->block_bytes + ctx->n_block_bytes - sizeof(MD_BLOCK)); + if(top_block->type == MD_BLOCK_LI) + n_parents--; + } + + ctx->last_list_item_starts_with_two_blank_lines = FALSE; + } +#endif + } + + /* Check whether we are Setext underline. */ + if(line->indent < ctx->code_indent_offset && pivot_line->type == MD_LINE_TEXT + && (CH(off) == _T('=') || CH(off) == _T('-')) + && (n_parents == ctx->n_containers)) + { + unsigned level; + + if(md_is_setext_underline(ctx, off, &off, &level)) { + line->type = MD_LINE_SETEXTUNDERLINE; + line->data = level; + goto done; + } + } + + /* Check for thematic break line. */ + if(line->indent < ctx->code_indent_offset && ISANYOF(off, _T("-_*"))) { + if(md_is_hr_line(ctx, off, &off)) { + line->type = MD_LINE_HR; + goto done; + } + } + + /* Check for "brother" container. I.e. whether we are another list item + * in already started list. */ + if(n_parents < ctx->n_containers && n_brothers + n_children == 0) { + OFF tmp; + + if(md_is_container_mark(ctx, line->indent, off, &tmp, &container) && + md_is_container_compatible(&ctx->containers[n_parents], &container)) + { + pivot_line = &md_dummy_blank_line; + + off = tmp; + + total_indent += container.contents_indent - container.mark_indent; + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + line->beg = off; + + /* Some of the following whitespace actually still belongs to the mark. */ + if(off >= ctx->size || ISNEWLINE(off)) { + container.contents_indent++; + } else if(line->indent <= ctx->code_indent_offset) { + container.contents_indent += line->indent; + line->indent = 0; + } else { + container.contents_indent += 1; + line->indent--; + } + + ctx->containers[n_parents].mark_indent = container.mark_indent; + ctx->containers[n_parents].contents_indent = container.contents_indent; + + n_brothers++; + goto redo; + } + } + + /* Check for indented code. + * Note indented code block cannot interrupt a paragraph. */ + if(line->indent >= ctx->code_indent_offset && + (pivot_line->type == MD_LINE_BLANK || pivot_line->type == MD_LINE_INDENTEDCODE)) + { + line->type = MD_LINE_INDENTEDCODE; + MD_ASSERT(line->indent >= ctx->code_indent_offset); + line->indent -= ctx->code_indent_offset; + line->data = 0; + goto done; + } + + /* Check for start of a new container block. */ + if(line->indent < ctx->code_indent_offset && + md_is_container_mark(ctx, line->indent, off, &off, &container)) + { + if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers && + (off >= ctx->size || ISNEWLINE(off))) + { + /* Noop. List mark followed by a blank line cannot interrupt a paragraph. */ + } else if(pivot_line->type == MD_LINE_TEXT && n_parents == ctx->n_containers && + (container.ch == _T('.') || container.ch == _T(')')) && container.start != 1) + { + /* Noop. Ordered list cannot interrupt a paragraph unless the start index is 1. */ + } else { + total_indent += container.contents_indent - container.mark_indent; + line->indent = md_line_indentation(ctx, total_indent, off, &off); + total_indent += line->indent; + + line->beg = off; + line->data = container.ch; + + /* Some of the following whitespace actually still belongs to the mark. */ + if(off >= ctx->size || ISNEWLINE(off)) { + container.contents_indent++; + } else if(line->indent <= ctx->code_indent_offset) { + container.contents_indent += line->indent; + line->indent = 0; + } else { + container.contents_indent += 1; + line->indent--; + } + + if(n_brothers + n_children == 0) + pivot_line = &md_dummy_blank_line; + + if(n_children == 0) + MD_CHECK(md_leave_child_containers(ctx, n_parents + n_brothers)); + + n_children++; + MD_CHECK(md_push_container(ctx, &container)); + goto redo; + } + } + + /* Check whether we are table continuation. */ + if(pivot_line->type == MD_LINE_TABLE && md_is_table_row(ctx, off, &off) && + n_parents == ctx->n_containers) + { + line->type = MD_LINE_TABLE; + goto done; + } + + /* Check for ATX header. */ + if(line->indent < ctx->code_indent_offset && CH(off) == _T('#')) { + unsigned level; + + if(md_is_atxheader_line(ctx, off, &line->beg, &off, &level)) { + line->type = MD_LINE_ATXHEADER; + line->data = level; + goto done; + } + } + + /* Check whether we are starting code fence. */ + if(CH(off) == _T('`') || CH(off) == _T('~')) { + if(md_is_opening_code_fence(ctx, off, &off)) { + line->type = MD_LINE_FENCEDCODE; + line->data = 1; + goto done; + } + } + + /* Check for start of raw HTML block. */ + if(CH(off) == _T('<') && !(ctx->parser.flags & MD_FLAG_NOHTMLBLOCKS)) + { + ctx->html_block_type = md_is_html_block_start_condition(ctx, off); + + /* HTML block type 7 cannot interrupt paragraph. */ + if(ctx->html_block_type == 7 && pivot_line->type == MD_LINE_TEXT) + ctx->html_block_type = 0; + + if(ctx->html_block_type > 0) { + /* The line itself also may immediately close the block. */ + if(md_is_html_block_end_condition(ctx, off, &off) == ctx->html_block_type) { + /* Make sure this is the last line of the block. */ + ctx->html_block_type = 0; + } + + line->type = MD_LINE_HTML; + goto done; + } + } + + /* Check for table underline. */ + if((ctx->parser.flags & MD_FLAG_TABLES) && pivot_line->type == MD_LINE_TEXT && + (CH(off) == _T('|') || CH(off) == _T('-') || CH(off) == _T(':')) && + n_parents == ctx->n_containers) + { + unsigned col_count; + + if(ctx->current_block != NULL && ctx->current_block->n_lines == 1 && + md_is_table_underline(ctx, off, &off, &col_count) && + md_is_table_row(ctx, pivot_line->beg, NULL)) + { + line->data = col_count; + line->type = MD_LINE_TABLEUNDERLINE; + goto done; + } + } + + /* By default, we are normal text line. */ + line->type = MD_LINE_TEXT; + if(pivot_line->type == MD_LINE_TEXT && n_brothers + n_children == 0) { + /* Lazy continuation. */ + n_parents = ctx->n_containers; + } + + /* Check for task mark. */ + if((ctx->parser.flags & MD_FLAG_TASKLISTS) && n_brothers + n_children > 0 && + ISANYOF_(ctx->containers[ctx->n_containers-1].ch, _T("-+*.)"))) + { + OFF tmp = off; + + while(tmp < ctx->size && tmp < off + 3 && ISBLANK(tmp)) + tmp++; + if(tmp + 2 < ctx->size && CH(tmp) == _T('[') && + ISANYOF(tmp+1, _T("xX ")) && CH(tmp+2) == _T(']') && + (tmp + 3 == ctx->size || ISBLANK(tmp+3) || ISNEWLINE(tmp+3))) + { + MD_CONTAINER* task_container = (n_children > 0 ? &ctx->containers[ctx->n_containers-1] : &container); + task_container->is_task = TRUE; + task_container->task_mark_off = tmp + 1; + off = tmp + 3; + while(ISWHITESPACE(off)) + off++; + line->beg = off; + } + } + +done: + /* Scan for end of the line. + * + * Note this is bottleneck of this function as we itereate over (almost) + * all line contents after some initial line indentation. To optimize, we + * try to eat multiple chars in every loop iteration. + * + * (Measured ~6% performance boost of md2html with this optimization for + * normal kind of input.) + */ + while(off + 4 < ctx->size && !ISNEWLINE(off+0) && !ISNEWLINE(off+1) + && !ISNEWLINE(off+2) && !ISNEWLINE(off+3)) + off += 4; + while(off < ctx->size && !ISNEWLINE(off)) + off++; + +done_on_eol: + /* Set end of the line. */ + line->end = off; + + /* But for ATX header, we should exclude the optional trailing mark. */ + if(line->type == MD_LINE_ATXHEADER) { + OFF tmp = line->end; + while(tmp > line->beg && CH(tmp-1) == _T(' ')) + tmp--; + while(tmp > line->beg && CH(tmp-1) == _T('#')) + tmp--; + if(tmp == line->beg || CH(tmp-1) == _T(' ') || (ctx->parser.flags & MD_FLAG_PERMISSIVEATXHEADERS)) + line->end = tmp; + } + + /* Trim trailing spaces. */ + if(line->type != MD_LINE_INDENTEDCODE && line->type != MD_LINE_FENCEDCODE) { + while(line->end > line->beg && CH(line->end-1) == _T(' ')) + line->end--; + } + + /* Eat also the new line. */ + if(off < ctx->size && CH(off) == _T('\r')) + off++; + if(off < ctx->size && CH(off) == _T('\n')) + off++; + + *p_end = off; + + /* If we belong to a list after seeing a blank line, the list is loose. */ + if(prev_line_has_list_loosening_effect && line->type != MD_LINE_BLANK && n_parents + n_brothers > 0) { + MD_CONTAINER* c = &ctx->containers[n_parents + n_brothers - 1]; + if(c->ch != _T('>')) { + MD_BLOCK* block = (MD_BLOCK*) (((char*)ctx->block_bytes) + c->block_byte_off); + block->flags |= MD_BLOCK_LOOSE_LIST; + } + } + + /* Leave any containers we are not part of anymore. */ + if(n_children == 0 && n_parents + n_brothers < ctx->n_containers) + MD_CHECK(md_leave_child_containers(ctx, n_parents + n_brothers)); + + /* Enter any container we found a mark for. */ + if(n_brothers > 0) { + MD_ASSERT(n_brothers == 1); + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + ctx->containers[n_parents].task_mark_off, + (ctx->containers[n_parents].is_task ? CH(ctx->containers[n_parents].task_mark_off) : 0), + MD_BLOCK_CONTAINER_CLOSER)); + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, + container.task_mark_off, + (container.is_task ? CH(container.task_mark_off) : 0), + MD_BLOCK_CONTAINER_OPENER)); + ctx->containers[n_parents].is_task = container.is_task; + ctx->containers[n_parents].task_mark_off = container.task_mark_off; + } + + if(n_children > 0) + MD_CHECK(md_enter_child_containers(ctx, n_children, line->data)); + +abort: + return ret; +} + +static int +md_process_line(MD_CTX* ctx, const MD_LINE_ANALYSIS** p_pivot_line, const MD_LINE_ANALYSIS* line) +{ + const MD_LINE_ANALYSIS* pivot_line = *p_pivot_line; + int ret = 0; + + /* Blank line ends current leaf block. */ + if(line->type == MD_LINE_BLANK) { + MD_CHECK(md_end_current_block(ctx)); + *p_pivot_line = &md_dummy_blank_line; + return 0; + } + + /* Some line types form block on their own. */ + if(line->type == MD_LINE_HR || line->type == MD_LINE_ATXHEADER) { + MD_CHECK(md_end_current_block(ctx)); + + /* Add our single-line block. */ + MD_CHECK(md_start_new_block(ctx, line)); + MD_CHECK(md_add_line_into_current_block(ctx, line)); + MD_CHECK(md_end_current_block(ctx)); + *p_pivot_line = &md_dummy_blank_line; + return 0; + } + + /* MD_LINE_SETEXTUNDERLINE changes meaning of the current block and ends it. */ + if(line->type == MD_LINE_SETEXTUNDERLINE) { + MD_ASSERT(ctx->current_block != NULL); + ctx->current_block->type = MD_BLOCK_H; + ctx->current_block->data = line->data; + MD_CHECK(md_end_current_block(ctx)); + *p_pivot_line = &md_dummy_blank_line; + return 0; + } + + /* MD_LINE_TABLEUNDERLINE changes meaning of the current block. */ + if(line->type == MD_LINE_TABLEUNDERLINE) { + MD_ASSERT(ctx->current_block != NULL); + MD_ASSERT(ctx->current_block->n_lines == 1); + ctx->current_block->type = MD_BLOCK_TABLE; + ctx->current_block->data = line->data; + MD_ASSERT(pivot_line != &md_dummy_blank_line); + ((MD_LINE_ANALYSIS*)pivot_line)->type = MD_LINE_TABLE; + MD_CHECK(md_add_line_into_current_block(ctx, line)); + return 0; + } + + /* The current block also ends if the line has different type. */ + if(line->type != pivot_line->type) + MD_CHECK(md_end_current_block(ctx)); + + /* The current line may start a new block. */ + if(ctx->current_block == NULL) { + MD_CHECK(md_start_new_block(ctx, line)); + *p_pivot_line = line; + } + + /* In all other cases the line is just a continuation of the current block. */ + MD_CHECK(md_add_line_into_current_block(ctx, line)); + +abort: + return ret; +} + +static int +md_process_doc(MD_CTX *ctx) +{ + const MD_LINE_ANALYSIS* pivot_line = &md_dummy_blank_line; + MD_LINE_ANALYSIS line_buf[2]; + MD_LINE_ANALYSIS* line = &line_buf[0]; + OFF off = 0; + int ret = 0; + + MD_ENTER_BLOCK(MD_BLOCK_DOC, NULL); + + while(off < ctx->size) { + if(line == pivot_line) + line = (line == &line_buf[0] ? &line_buf[1] : &line_buf[0]); + + MD_CHECK(md_analyze_line(ctx, off, &off, pivot_line, line)); + MD_CHECK(md_process_line(ctx, &pivot_line, line)); + } + + md_end_current_block(ctx); + + MD_CHECK(md_build_ref_def_hashtable(ctx)); + + /* Process all blocks. */ + MD_CHECK(md_leave_child_containers(ctx, 0)); + MD_CHECK(md_process_all_blocks(ctx)); + + MD_LEAVE_BLOCK(MD_BLOCK_DOC, NULL); + +abort: + +#if 0 + /* Output some memory consumption statistics. */ + { + char buffer[256]; + sprintf(buffer, "Alloced %u bytes for block buffer.", + (unsigned)(ctx->alloc_block_bytes)); + MD_LOG(buffer); + + sprintf(buffer, "Alloced %u bytes for containers buffer.", + (unsigned)(ctx->alloc_containers * sizeof(MD_CONTAINER))); + MD_LOG(buffer); + + sprintf(buffer, "Alloced %u bytes for marks buffer.", + (unsigned)(ctx->alloc_marks * sizeof(MD_MARK))); + MD_LOG(buffer); + + sprintf(buffer, "Alloced %u bytes for aux. buffer.", + (unsigned)(ctx->alloc_buffer * sizeof(MD_CHAR))); + MD_LOG(buffer); + } +#endif + + return ret; +} + + +/******************** + *** Public API *** + ********************/ + +int +md_parse(const MD_CHAR* text, MD_SIZE size, const MD_PARSER* parser, void* userdata) +{ + MD_CTX ctx; + int i; + int ret; + + if(parser->abi_version != 0) { + if(parser->debug_log != NULL) + parser->debug_log("Unsupported abi_version.", userdata); + return -1; + } + + /* Setup context structure. */ + memset(&ctx, 0, sizeof(MD_CTX)); + ctx.text = text; + ctx.size = size; + memcpy(&ctx.parser, parser, sizeof(MD_PARSER)); + ctx.userdata = userdata; + ctx.code_indent_offset = (ctx.parser.flags & MD_FLAG_NOINDENTEDCODEBLOCKS) ? (OFF)(-1) : 4; + md_build_mark_char_map(&ctx); + + /* Reset all unresolved opener mark chains. */ + for(i = 0; i < SIZEOF_ARRAY(ctx.mark_chains); i++) { + ctx.mark_chains[i].head = -1; + ctx.mark_chains[i].tail = -1; + } + ctx.unresolved_link_head = -1; + ctx.unresolved_link_tail = -1; + + /* All the work. */ + ret = md_process_doc(&ctx); + + /* Clean-up. */ + md_free_ref_defs(&ctx); + md_free_ref_def_hashtable(&ctx); + free(ctx.buffer); + free(ctx.marks); + free(ctx.block_bytes); + free(ctx.containers); + + return ret; +} diff --git a/src/3rdparty/md4c/md4c.h b/src/3rdparty/md4c/md4c.h new file mode 100644 index 0000000000..10cba67e95 --- /dev/null +++ b/src/3rdparty/md4c/md4c.h @@ -0,0 +1,359 @@ +/* + * MD4C: Markdown parser for C + * (http://github.com/mity/md4c) + * + * Copyright (c) 2016-2019 Martin Mitas + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef MD4C_MARKDOWN_H +#define MD4C_MARKDOWN_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Magic to support UTF-16. */ +#if defined MD4C_USE_UTF16 + #ifdef _WIN32 + #include + typedef WCHAR MD_CHAR; + #else + #error MD4C_USE_UTF16 is only supported on Windows. + #endif +#else + typedef char MD_CHAR; +#endif + +typedef unsigned MD_SIZE; +typedef unsigned MD_OFFSET; + + +/* Block represents a part of document hierarchy structure like a paragraph + * or list item. + */ +typedef enum MD_BLOCKTYPE { + /* ... */ + MD_BLOCK_DOC = 0, + + /*
...
*/ + MD_BLOCK_QUOTE, + + /*
    ...
+ * Detail: Structure MD_BLOCK_UL_DETAIL. */ + MD_BLOCK_UL, + + /*
    ...
+ * Detail: Structure MD_BLOCK_OL_DETAIL. */ + MD_BLOCK_OL, + + /*
  • ...
  • + * Detail: Structure MD_BLOCK_LI_DETAIL. */ + MD_BLOCK_LI, + + /*
    */ + MD_BLOCK_HR, + + /*

    ...

    (for levels up to 6) + * Detail: Structure MD_BLOCK_H_DETAIL. */ + MD_BLOCK_H, + + /*
    ...
    + * Note the text lines within code blocks are terminated with '\n' + * instead of explicit MD_TEXT_BR. */ + MD_BLOCK_CODE, + + /* Raw HTML block. This itself does not correspond to any particular HTML + * tag. The contents of it _is_ raw HTML source intended to be put + * in verbatim form to the HTML output. */ + MD_BLOCK_HTML, + + /*

    ...

    */ + MD_BLOCK_P, + + /* ...
    and its contents. + * Detail: Structure MD_BLOCK_TD_DETAIL (used with MD_BLOCK_TH and MD_BLOCK_TD) + * Note all of these are used only if extension MD_FLAG_TABLES is enabled. */ + MD_BLOCK_TABLE, + MD_BLOCK_THEAD, + MD_BLOCK_TBODY, + MD_BLOCK_TR, + MD_BLOCK_TH, + MD_BLOCK_TD +} MD_BLOCKTYPE; + +/* Span represents an in-line piece of a document which should be rendered with + * the same font, color and other attributes. A sequence of spans forms a block + * like paragraph or list item. */ +typedef enum MD_SPANTYPE { + /* ... */ + MD_SPAN_EM, + + /* ... */ + MD_SPAN_STRONG, + + /* ... + * Detail: Structure MD_SPAN_A_DETAIL. */ + MD_SPAN_A, + + /* ... + * Detail: Structure MD_SPAN_IMG_DETAIL. + * Note: Image text can contain nested spans and even nested images. + * If rendered into ALT attribute of HTML tag, it's responsibility + * of the renderer to deal with it. + */ + MD_SPAN_IMG, + + /* ... */ + MD_SPAN_CODE, + + /* ... + * Note: Recognized only when MD_FLAG_STRIKETHROUGH is enabled. + */ + MD_SPAN_DEL +} MD_SPANTYPE; + +/* Text is the actual textual contents of span. */ +typedef enum MD_TEXTTYPE { + /* Normal text. */ + MD_TEXT_NORMAL = 0, + + /* NULL character. CommonMark requires replacing NULL character with + * the replacement char U+FFFD, so this allows caller to do that easily. */ + MD_TEXT_NULLCHAR, + + /* Line breaks. + * Note these are not sent from blocks with verbatim output (MD_BLOCK_CODE + * or MD_BLOCK_HTML). In such cases, '\n' is part of the text itself. */ + MD_TEXT_BR, /*
    (hard break) */ + MD_TEXT_SOFTBR, /* '\n' in source text where it is not semantically meaningful (soft break) */ + + /* Entity. + * (a) Named entity, e.g.   + * (Note MD4C does not have a list of known entities. + * Anything matching the regexp /&[A-Za-z][A-Za-z0-9]{1,47};/ is + * treated as a named entity.) + * (b) Numerical entity, e.g. Ӓ + * (c) Hexadecimal entity, e.g. ካ + * + * As MD4C is mostly encoding agnostic, application gets the verbatim + * entity text into the MD_RENDERER::text_callback(). */ + MD_TEXT_ENTITY, + + /* Text in a code block (inside MD_BLOCK_CODE) or inlined code (`code`). + * If it is inside MD_BLOCK_CODE, it includes spaces for indentation and + * '\n' for new lines. MD_TEXT_BR and MD_TEXT_SOFTBR are not sent for this + * kind of text. */ + MD_TEXT_CODE, + + /* Text is a raw HTML. If it is contents of a raw HTML block (i.e. not + * an inline raw HTML), then MD_TEXT_BR and MD_TEXT_SOFTBR are not used. + * The text contains verbatim '\n' for the new lines. */ + MD_TEXT_HTML +} MD_TEXTTYPE; + + +/* Alignment enumeration. */ +typedef enum MD_ALIGN { + MD_ALIGN_DEFAULT = 0, /* When unspecified. */ + MD_ALIGN_LEFT, + MD_ALIGN_CENTER, + MD_ALIGN_RIGHT +} MD_ALIGN; + + +/* String attribute. + * + * This wraps strings which are outside of a normal text flow and which are + * propagated within various detailed structures, but which still may contain + * string portions of different types like e.g. entities. + * + * So, for example, lets consider an image has a title attribute string + * set to "foo " bar". (Note the string size is 14.) + * + * Then the attribute MD_SPAN_IMG_DETAIL::title shall provide the following: + * -- [0]: "foo " (substr_types[0] == MD_TEXT_NORMAL; substr_offsets[0] == 0) + * -- [1]: """ (substr_types[1] == MD_TEXT_ENTITY; substr_offsets[1] == 4) + * -- [2]: " bar" (substr_types[2] == MD_TEXT_NORMAL; substr_offsets[2] == 10) + * -- [3]: (n/a) (n/a ; substr_offsets[3] == 14) + * + * Note that these conditions are guaranteed: + * -- substr_offsets[0] == 0 + * -- substr_offsets[LAST+1] == size + * -- Only MD_TEXT_NORMAL, MD_TEXT_ENTITY, MD_TEXT_NULLCHAR substrings can appear. + */ +typedef struct MD_ATTRIBUTE { + const MD_CHAR* text; + MD_SIZE size; + const MD_TEXTTYPE* substr_types; + const MD_OFFSET* substr_offsets; +} MD_ATTRIBUTE; + + +/* Detailed info for MD_BLOCK_UL. */ +typedef struct MD_BLOCK_UL_DETAIL { + int is_tight; /* Non-zero if tight list, zero if loose. */ + MD_CHAR mark; /* Item bullet character in MarkDown source of the list, e.g. '-', '+', '*'. */ +} MD_BLOCK_UL_DETAIL; + +/* Detailed info for MD_BLOCK_OL. */ +typedef struct MD_BLOCK_OL_DETAIL { + unsigned start; /* Start index of the ordered list. */ + int is_tight; /* Non-zero if tight list, zero if loose. */ + MD_CHAR mark_delimiter; /* Character delimiting the item marks in MarkDown source, e.g. '.' or ')' */ +} MD_BLOCK_OL_DETAIL; + +/* Detailed info for MD_BLOCK_LI. */ +typedef struct MD_BLOCK_LI_DETAIL { + int is_task; /* Can be non-zero only with MD_FLAG_TASKLISTS */ + MD_CHAR task_mark; /* If is_task, then one of 'x', 'X' or ' '. Undefined otherwise. */ + MD_OFFSET task_mark_offset; /* If is_task, then offset in the input of the char between '[' and ']'. */ +} MD_BLOCK_LI_DETAIL; + +/* Detailed info for MD_BLOCK_H. */ +typedef struct MD_BLOCK_H_DETAIL { + unsigned level; /* Header level (1 - 6) */ +} MD_BLOCK_H_DETAIL; + +/* Detailed info for MD_BLOCK_CODE. */ +typedef struct MD_BLOCK_CODE_DETAIL { + MD_ATTRIBUTE info; + MD_ATTRIBUTE lang; +} MD_BLOCK_CODE_DETAIL; + +/* Detailed info for MD_BLOCK_TH and MD_BLOCK_TD. */ +typedef struct MD_BLOCK_TD_DETAIL { + MD_ALIGN align; +} MD_BLOCK_TD_DETAIL; + +/* Detailed info for MD_SPAN_A. */ +typedef struct MD_SPAN_A_DETAIL { + MD_ATTRIBUTE href; + MD_ATTRIBUTE title; +} MD_SPAN_A_DETAIL; + +/* Detailed info for MD_SPAN_IMG. */ +typedef struct MD_SPAN_IMG_DETAIL { + MD_ATTRIBUTE src; + MD_ATTRIBUTE title; +} MD_SPAN_IMG_DETAIL; + + +/* Flags specifying extensions/deviations from CommonMark specification. + * + * By default (when MD_RENDERER::flags == 0), we follow CommonMark specification. + * The following flags may allow some extensions or deviations from it. + */ +#define MD_FLAG_COLLAPSEWHITESPACE 0x0001 /* In MD_TEXT_NORMAL, collapse non-trivial whitespace into single ' ' */ +#define MD_FLAG_PERMISSIVEATXHEADERS 0x0002 /* Do not require space in ATX headers ( ###header ) */ +#define MD_FLAG_PERMISSIVEURLAUTOLINKS 0x0004 /* Recognize URLs as autolinks even without '<', '>' */ +#define MD_FLAG_PERMISSIVEEMAILAUTOLINKS 0x0008 /* Recognize e-mails as autolinks even without '<', '>' and 'mailto:' */ +#define MD_FLAG_NOINDENTEDCODEBLOCKS 0x0010 /* Disable indented code blocks. (Only fenced code works.) */ +#define MD_FLAG_NOHTMLBLOCKS 0x0020 /* Disable raw HTML blocks. */ +#define MD_FLAG_NOHTMLSPANS 0x0040 /* Disable raw HTML (inline). */ +#define MD_FLAG_TABLES 0x0100 /* Enable tables extension. */ +#define MD_FLAG_STRIKETHROUGH 0x0200 /* Enable strikethrough extension. */ +#define MD_FLAG_PERMISSIVEWWWAUTOLINKS 0x0400 /* Enable WWW autolinks (even without any scheme prefix, if they begin with 'www.') */ +#define MD_FLAG_TASKLISTS 0x0800 /* Enable task list extension. */ + +#define MD_FLAG_PERMISSIVEAUTOLINKS (MD_FLAG_PERMISSIVEEMAILAUTOLINKS | MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_PERMISSIVEWWWAUTOLINKS) +#define MD_FLAG_NOHTML (MD_FLAG_NOHTMLBLOCKS | MD_FLAG_NOHTMLSPANS) + +/* Convenient sets of flags corresponding to well-known Markdown dialects. + * + * Note we may only support subset of features of the referred dialect. + * The constant just enables those extensions which bring us as close as + * possible given what features we implement. + * + * ABI compatibility note: Meaning of these can change in time as new + * extensions, bringing the dialect closer to the original, are implemented. + */ +#define MD_DIALECT_COMMONMARK 0 +#define MD_DIALECT_GITHUB (MD_FLAG_PERMISSIVEAUTOLINKS | MD_FLAG_TABLES | MD_FLAG_STRIKETHROUGH | MD_FLAG_TASKLISTS) + +/* Renderer structure. + */ +typedef struct MD_PARSER { + /* Reserved. Set to zero. + */ + unsigned abi_version; + + /* Dialect options. Bitmask of MD_FLAG_xxxx values. + */ + unsigned flags; + + /* Caller-provided rendering callbacks. + * + * For some block/span types, more detailed information is provided in a + * type-specific structure pointed by the argument 'detail'. + * + * The last argument of all callbacks, 'userdata', is just propagated from + * md_parse() and is available for any use by the application. + * + * Note any strings provided to the callbacks as their arguments or as + * members of any detail structure are generally not zero-terminated. + * Application has take the respective size information into account. + * + * Callbacks may abort further parsing of the document by returning non-zero. + */ + int (*enter_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + int (*leave_block)(MD_BLOCKTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + + int (*enter_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + int (*leave_span)(MD_SPANTYPE /*type*/, void* /*detail*/, void* /*userdata*/); + + int (*text)(MD_TEXTTYPE /*type*/, const MD_CHAR* /*text*/, MD_SIZE /*size*/, void* /*userdata*/); + + /* Debug callback. Optional (may be NULL). + * + * If provided and something goes wrong, this function gets called. + * This is intended for debugging and problem diagnosis for developers; + * it is not intended to provide any errors suitable for displaying to an + * end user. + */ + void (*debug_log)(const char* /*msg*/, void* /*userdata*/); + + /* Reserved. Set to NULL. + */ + void (*syntax)(void); +} MD_PARSER; + + +/* For backward compatibility. Do not use in new code. */ +typedef MD_PARSER MD_RENDERER; + + +/* Parse the Markdown document stored in the string 'text' of size 'size'. + * The renderer provides callbacks to be called during the parsing so the + * caller can render the document on the screen or convert the Markdown + * to another format. + * + * Zero is returned on success. If a runtime error occurs (e.g. a memory + * fails), -1 is returned. If the processing is aborted due any callback + * returning non-zero, md_parse() the return value of the callback is returned. + */ +int md_parse(const MD_CHAR* text, MD_SIZE size, const MD_PARSER* parser, void* userdata); + + +#ifdef __cplusplus + } /* extern "C" { */ +#endif + +#endif /* MD4C_MARKDOWN_H */ diff --git a/src/3rdparty/md4c/qt_attribution.json b/src/3rdparty/md4c/qt_attribution.json new file mode 100644 index 0000000000..9180ed69b5 --- /dev/null +++ b/src/3rdparty/md4c/qt_attribution.json @@ -0,0 +1,15 @@ +{ + "Id": "md4c", + "Name": "MD4C", + "QDocModule": "qtgui", + "QtUsage": "Optionally used in QTextDocument if configured with textmarkdownreader.", + + "Description": "A CommonMark-compliant Markdown parser.", + "Homepage": "https://github.com/mity/md4c", + "License": "MIT License", + "LicenseId": "MIT", + "LicenseFile": "LICENSE.md", + "Version": "0.3.0", + "DownloadLocation": "https://github.com/mity/md4c/releases/tag/release-0.3.0-rc", + "Copyright": "Copyright © 2016-2019 Martin Mitáš" +} From 860bf13dbd2e9ad0a87b75defcab2cc3c9c771f3 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 17 Apr 2019 14:29:57 +0200 Subject: [PATCH 003/122] Fix compilation errors and warnings on INTEGRITY in md4c 3rdparty Change-Id: Ic27801f790b533f0a16099501fbe8a3ffe941d02 Reviewed-by: Shawn Rutledge --- src/3rdparty/md4c/md4c.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/3rdparty/md4c/md4c.c b/src/3rdparty/md4c/md4c.c index 4c0ad5c0fc..13c7bd3433 100644 --- a/src/3rdparty/md4c/md4c.c +++ b/src/3rdparty/md4c/md4c.c @@ -25,6 +25,7 @@ #include "md4c.h" +#include #include #include #include @@ -3375,7 +3376,7 @@ md_resolve_links(MD_CTX* ctx, const MD_LINE* lines, int n_lines) } else { if(closer->end < ctx->size && CH(closer->end) == _T('(')) { /* Might be inline link. */ - OFF inline_link_end = -1; + OFF inline_link_end = UINT_MAX; is_link = md_is_inline_link_spec(ctx, lines, n_lines, closer->end, &inline_link_end, &attr); if(is_link < 0) @@ -4152,11 +4153,14 @@ static int md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end, const MD_ALIGN* align, int col_count) { - MD_LINE line = { beg, end }; + MD_LINE line; OFF* pipe_offs = NULL; int i, j, n; int ret = 0; + line.beg = beg; + line.end = end; + /* Break the line into table cells by identifying pipe characters who * form the cell boundary. */ MD_CHECK(md_analyze_inlines(ctx, &line, 1, TRUE)); @@ -4243,10 +4247,13 @@ abort: static int md_is_table_row(MD_CTX* ctx, OFF beg, OFF* p_end) { - MD_LINE line = { beg, beg }; + MD_LINE line; int i; int ret = FALSE; + line.beg = beg; + line.end = beg; + /* Find end of line. */ while(line.end < ctx->size && !ISNEWLINE(line.end)) line.end++; @@ -5186,6 +5193,7 @@ md_is_html_block_end_condition(MD_CTX* ctx, OFF beg, OFF* p_end) default: MD_UNREACHABLE(); } + return FALSE; } From 65314b6ce88cdbb28a22be0cab9856ec9bc9604b Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 18 Dec 2017 08:55:18 +0100 Subject: [PATCH 004/122] Add QTextMarkdownImporter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This provides the ability to read from a Markdown string or file into a QTextDocument, such that the formatting will be recognized and can be rendered. - Add QTextDocument::setMarkdown(QString) - Add QTextEdit::setMarkdown(QString) - Add TextFormat::MarkdownText - QWidgetTextControl::setContent() calls QTextDocument::setMarkdown() if that's the format Fixes: QTBUG-72349 Change-Id: Ief2ad71bf840666c64145d58e9ca71d05fad5659 Reviewed-by: Lisandro Damián Nicanor Pérez Meyer Reviewed-by: Gatis Paeglis --- src/corelib/global/qnamespace.h | 3 +- src/gui/configure.json | 34 ++ src/gui/text/qtextdocument.cpp | 30 +- src/gui/text/qtextdocument.h | 15 +- src/gui/text/qtextformat.h | 12 + src/gui/text/qtextmarkdownimporter.cpp | 435 +++++++++++++++++++ src/gui/text/qtextmarkdownimporter_p.h | 127 ++++++ src/gui/text/text.pri | 12 + src/widgets/widgets/qtextedit.cpp | 9 +- src/widgets/widgets/qtextedit.h | 5 +- src/widgets/widgets/qwidgettextcontrol.cpp | 15 +- src/widgets/widgets/qwidgettextcontrol_p.h | 5 +- src/widgets/widgets/qwidgettextcontrol_p_p.h | 2 +- 13 files changed, 696 insertions(+), 8 deletions(-) create mode 100644 src/gui/text/qtextmarkdownimporter.cpp create mode 100644 src/gui/text/qtextmarkdownimporter_p.h diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 90dd36113f..06aef81afc 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1198,7 +1198,8 @@ public: enum TextFormat { PlainText, RichText, - AutoText + AutoText, + MarkdownText }; enum AspectRatioMode { diff --git a/src/gui/configure.json b/src/gui/configure.json index 7a1796041e..a4ea4375d1 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -28,6 +28,7 @@ "lgmon": "boolean", "libinput": "boolean", "libjpeg": { "type": "enum", "values": [ "no", "qt", "system" ] }, + "libmd4c": { "type": "enum", "values": [ "no", "qt", "system" ] }, "libpng": { "type": "enum", "values": [ "no", "qt", "system" ] }, "linuxfb": "boolean", "mtdev": "boolean", @@ -376,6 +377,17 @@ "-ljpeg" ] }, + "libmd4c": { + "label": "libmd4c", + "test": { + "main": "md_parse(\"hello\", 5, nullptr, nullptr);" + }, + "headers": "md4c.h", + "sources": [ + { "type": "pkgConfig", "args": "md4c" }, + { "libs": "-lmd4c" } + ] + }, "libpng": { "label": "libpng", "test": { @@ -1583,6 +1595,22 @@ "section": "Kernel", "output": [ "publicFeature", "feature" ] }, + "textmarkdownreader": { + "label": "MarkdownReader", + "disable": "input.libmd4c == 'no'", + "enable": "input.libmd4c == 'system' || input.libmd4c == 'qt' || input.libmd4c == 'yes'", + "purpose": "Provides a Markdown (CommonMark and GitHub) reader", + "section": "Kernel", + "output": [ "publicFeature" ] + }, + "system-textmarkdownreader": { + "label": " Using system libmd4c", + "disable": "input.libmd4c == 'qt'", + "enable": "input.libmd4c == 'system'", + "section": "Kernel", + "condition": "libs.libmd4c", + "output": [ "publicFeature" ] + }, "textodfwriter": { "label": "OdfWriter", "purpose": "Provides an ODF writer.", @@ -1861,6 +1889,12 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla "gif", "ico", "jpeg", "system-jpeg", "png", "system-png" ] }, + { + "section": "Text formats", + "entries": [ + "texthtmlparser", "cssparser", "textodfwriter", "textmarkdownreader", "system-textmarkdownreader" + ] + }, "egl", "openvg", { diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index fd3473b32e..87c8f1ba8a 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -70,6 +70,9 @@ #include #include "qpagedpaintdevice.h" #include "private/qpagedpaintdevice_p.h" +#if QT_CONFIG(textmarkdownreader) +#include +#endif #include @@ -3285,6 +3288,31 @@ QString QTextDocument::toHtml(const QByteArray &encoding) const } #endif // QT_NO_TEXTHTMLPARSER +/*! + Replaces the entire contents of the document with the given + Markdown-formatted text in the \a markdown string, with the given + \a features supported. By default, all supported GitHub-style + Markdown features are included; pass \c MarkdownDialectCommonMark + for a more basic parse. + + The Markdown formatting is respected as much as possible; for example, + "*bold* text" will produce text where the first word has a font weight that + gives it an emphasized appearance. + + Parsing of HTML included in the \a markdown string is handled in the same + way as in \l setHtml; however, Markdown formatting inside HTML blocks is + not supported. The \c MarkdownNoHTML feature flag can be set to disable + HTML parsing. + + The undo/redo history is reset when this function is called. +*/ +#if QT_CONFIG(textmarkdownreader) +void QTextDocument::setMarkdown(const QString &markdown, QTextDocument::MarkdownFeatures features) +{ + QTextMarkdownImporter(static_cast(int(features))).import(this, markdown); +} +#endif + /*! Returns a vector of text formats for all the formats used in the document. */ diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index c9b22e053b..ade67999ad 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -151,6 +151,19 @@ public: void setHtml(const QString &html); #endif +#if QT_CONFIG(textmarkdownreader) + // Must be in sync with QTextMarkdownImporter::Features, should be in sync with #define MD_FLAG_* in md4c + enum MarkdownFeature { + MarkdownNoHTML = 0x0020 | 0x0040, + MarkdownDialectCommonMark = 0, + MarkdownDialectGitHub = 0x0004 | 0x0008 | 0x0400 | 0x0100 | 0x0200 | 0x0800 + }; + Q_DECLARE_FLAGS(MarkdownFeatures, MarkdownFeature) + Q_FLAG(MarkdownFeatures) + + void setMarkdown(const QString &markdown, MarkdownFeatures features = MarkdownDialectGitHub); +#endif + QString toRawText() const; QString toPlainText() const; void setPlainText(const QString &text); diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h index 80d8e82694..1eb52a379c 100644 --- a/src/gui/text/qtextformat.h +++ b/src/gui/text/qtextformat.h @@ -176,6 +176,7 @@ public: BlockNonBreakableLines = 0x1050, BlockTrailingHorizontalRulerWidth = 0x1060, HeadingLevel = 0x1070, + BlockMarker = 0x1080, // character properties FirstFontProperty = 0x1FE0, @@ -605,6 +606,12 @@ public: LineDistanceHeight = 4 }; + enum MarkerType { + NoMarker = 0, + Unchecked = 1, + Checked = 2 + }; + QTextBlockFormat(); bool isValid() const { return isBlockFormat(); } @@ -668,6 +675,11 @@ public: void setTabPositions(const QList &tabs); QList tabPositions() const; + inline void setMarker(MarkerType marker) + { setProperty(BlockMarker, int(marker)); } + inline MarkerType marker() const + { return MarkerType(intProperty(BlockMarker)); } + protected: explicit QTextBlockFormat(const QTextFormat &fmt); friend class QTextFormat; diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp new file mode 100644 index 0000000000..6c053ac81a --- /dev/null +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -0,0 +1,435 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui 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 "qtextmarkdownimporter_p.h" +#include "qtextdocumentfragment_p.h" +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcMD, "qt.text.markdown") + +// -------------------------------------------------------- +// MD4C callback function wrappers + +static int CbEnterBlock(MD_BLOCKTYPE type, void *detail, void *userdata) +{ + QTextMarkdownImporter *mdi = static_cast(userdata); + return mdi->cbEnterBlock(type, detail); +} + +static int CbLeaveBlock(MD_BLOCKTYPE type, void *detail, void *userdata) +{ + QTextMarkdownImporter *mdi = static_cast(userdata); + return mdi->cbLeaveBlock(type, detail); +} + +static int CbEnterSpan(MD_SPANTYPE type, void *detail, void *userdata) +{ + QTextMarkdownImporter *mdi = static_cast(userdata); + return mdi->cbEnterSpan(type, detail); +} + +static int CbLeaveSpan(MD_SPANTYPE type, void *detail, void *userdata) +{ + QTextMarkdownImporter *mdi = static_cast(userdata); + return mdi->cbLeaveSpan(type, detail); +} + +static int CbText(MD_TEXTTYPE type, const MD_CHAR *text, MD_SIZE size, void *userdata) +{ + QTextMarkdownImporter *mdi = static_cast(userdata); + return mdi->cbText(type, text, size); +} + +static void CbDebugLog(const char *msg, void *userdata) +{ + Q_UNUSED(userdata) + qCDebug(lcMD) << msg; +} + +// MD4C callback function wrappers +// -------------------------------------------------------- + +static Qt::Alignment MdAlignment(MD_ALIGN a, Qt::Alignment defaultAlignment = Qt::AlignLeft | Qt::AlignVCenter) +{ + switch (a) { + case MD_ALIGN_LEFT: + return Qt::AlignLeft | Qt::AlignVCenter; + case MD_ALIGN_CENTER: + return Qt::AlignHCenter | Qt::AlignVCenter; + case MD_ALIGN_RIGHT: + return Qt::AlignRight | Qt::AlignVCenter; + default: // including MD_ALIGN_DEFAULT + return defaultAlignment; + } +} + +QTextMarkdownImporter::QTextMarkdownImporter(QTextMarkdownImporter::Features features) + : m_monoFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)) + , m_features(features) +{ +} + +void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown) +{ + MD_PARSER callbacks = { + 0, // abi_version + m_features, + &CbEnterBlock, + &CbLeaveBlock, + &CbEnterSpan, + &CbLeaveSpan, + &CbText, + &CbDebugLog, + nullptr // syntax + }; + m_doc = doc; + m_cursor = new QTextCursor(doc); + doc->clear(); + qCDebug(lcMD) << "default font" << doc->defaultFont() << "mono font" << m_monoFont; + QByteArray md = markdown.toUtf8(); + md_parse(md.constData(), md.size(), &callbacks, this); + delete m_cursor; + m_cursor = nullptr; +} + +int QTextMarkdownImporter::cbEnterBlock(MD_BLOCKTYPE type, void *det) +{ + m_blockType = type; + switch (type) { + case MD_BLOCK_P: { + QTextBlockFormat blockFmt; + int margin = m_doc->defaultFont().pointSize() / 2; + blockFmt.setTopMargin(margin); + blockFmt.setBottomMargin(margin); + m_cursor->insertBlock(blockFmt, QTextCharFormat()); + } break; + case MD_BLOCK_CODE: { + QTextBlockFormat blockFmt; + QTextCharFormat charFmt; + charFmt.setFont(m_monoFont); + m_cursor->insertBlock(blockFmt, charFmt); + } break; + case MD_BLOCK_H: { + MD_BLOCK_H_DETAIL *detail = static_cast(det); + QTextBlockFormat blockFmt; + QTextCharFormat charFmt; + int sizeAdjustment = 4 - detail->level; // H1 to H6: +3 to -2 + charFmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment); + charFmt.setFontWeight(QFont::Bold); + blockFmt.setHeadingLevel(detail->level); + m_cursor->insertBlock(blockFmt, charFmt); + } break; + case MD_BLOCK_LI: { + MD_BLOCK_LI_DETAIL *detail = static_cast(det); + QTextBlockFormat bfmt = m_cursor->blockFormat(); + bfmt.setMarker(detail->is_task ? + (detail->task_mark == ' ' ? QTextBlockFormat::Unchecked : QTextBlockFormat::Checked) : + QTextBlockFormat::NoMarker); + if (!m_emptyList) { + m_cursor->insertBlock(bfmt, QTextCharFormat()); + m_listStack.top()->add(m_cursor->block()); + } + m_cursor->setBlockFormat(bfmt); + m_emptyList = false; // Avoid insertBlock for the first item (because insertList already did that) + } break; + case MD_BLOCK_UL: { + MD_BLOCK_UL_DETAIL *detail = static_cast(det); + QTextListFormat fmt; + fmt.setIndent(m_listStack.count() + 1); + switch (detail->mark) { + case '*': + fmt.setStyle(QTextListFormat::ListCircle); + break; + case '+': + fmt.setStyle(QTextListFormat::ListSquare); + break; + default: // including '-' + fmt.setStyle(QTextListFormat::ListDisc); + break; + } + m_listStack.push(m_cursor->insertList(fmt)); + m_emptyList = true; + } break; + case MD_BLOCK_OL: { + MD_BLOCK_OL_DETAIL *detail = static_cast(det); + QTextListFormat fmt; + fmt.setIndent(m_listStack.count() + 1); + fmt.setNumberSuffix(QChar::fromLatin1(detail->mark_delimiter)); + fmt.setStyle(QTextListFormat::ListDecimal); + m_listStack.push(m_cursor->insertList(fmt)); + m_emptyList = true; + } break; + case MD_BLOCK_TD: { + MD_BLOCK_TD_DETAIL *detail = static_cast(det); + ++m_tableCol; + // absolute movement (and storage of m_tableCol) shouldn't be necessary, but + // movePosition(QTextCursor::NextCell) doesn't work + QTextTableCell cell = m_currentTable->cellAt(m_tableRowCount - 1, m_tableCol); + if (!cell.isValid()) { + qWarning("malformed table in Markdown input"); + return 1; + } + *m_cursor = cell.firstCursorPosition(); + QTextBlockFormat blockFmt = m_cursor->blockFormat(); + blockFmt.setAlignment(MdAlignment(detail->align)); + m_cursor->setBlockFormat(blockFmt); + qCDebug(lcMD) << "TD; align" << detail->align << MdAlignment(detail->align) << "col" << m_tableCol; + } break; + case MD_BLOCK_TH: { + ++m_tableColumnCount; + ++m_tableCol; + if (m_currentTable->columns() < m_tableColumnCount) + m_currentTable->appendColumns(1); + auto cell = m_currentTable->cellAt(m_tableRowCount - 1, m_tableCol); + if (!cell.isValid()) { + qWarning("malformed table in Markdown input"); + return 1; + } + auto fmt = cell.format(); + fmt.setFontWeight(QFont::Bold); + cell.setFormat(fmt); + } break; + case MD_BLOCK_TR: { + ++m_tableRowCount; + m_nonEmptyTableCells.clear(); + if (m_currentTable->rows() < m_tableRowCount) + m_currentTable->appendRows(1); + m_tableCol = -1; + qCDebug(lcMD) << "TR" << m_currentTable->rows(); + } break; + case MD_BLOCK_TABLE: + m_tableColumnCount = 0; + m_tableRowCount = 0; + m_currentTable = m_cursor->insertTable(1, 1); // we don't know the dimensions yet + break; + case MD_BLOCK_HR: { + QTextBlockFormat blockFmt = m_cursor->blockFormat(); + blockFmt.setProperty(QTextFormat::BlockTrailingHorizontalRulerWidth, 1); + m_cursor->insertBlock(blockFmt, QTextCharFormat()); + } break; + default: + break; // nothing to do for now + } + return 0; // no error +} + +int QTextMarkdownImporter::cbLeaveBlock(MD_BLOCKTYPE type, void *detail) +{ + Q_UNUSED(detail) + switch (type) { + case MD_BLOCK_UL: + case MD_BLOCK_OL: + m_listStack.pop(); + break; + case MD_BLOCK_TR: { + // https://github.com/mity/md4c/issues/29 + // MD4C doesn't tell us explicitly which cells are merged, so merge empty cells + // with previous non-empty ones + int mergeEnd = -1; + int mergeBegin = -1; + for (int col = m_tableCol; col >= 0; --col) { + if (m_nonEmptyTableCells.contains(col)) { + if (mergeEnd >= 0 && mergeBegin >= 0) { + qCDebug(lcMD) << "merging cells" << mergeBegin << "to" << mergeEnd << "inclusive, on row" << m_currentTable->rows() - 1; + m_currentTable->mergeCells(m_currentTable->rows() - 1, mergeBegin - 1, 1, mergeEnd - mergeBegin + 2); + } + mergeEnd = -1; + mergeBegin = -1; + } else { + if (mergeEnd < 0) + mergeEnd = col; + else + mergeBegin = col; + } + } + } break; + case MD_BLOCK_QUOTE: { + QTextBlockFormat blockFmt = m_cursor->blockFormat(); + blockFmt.setIndent(1); + m_cursor->setBlockFormat(blockFmt); + } break; + case MD_BLOCK_TABLE: + qCDebug(lcMD) << "table ended with" << m_currentTable->columns() << "cols and" << m_currentTable->rows() << "rows"; + m_currentTable = nullptr; + m_cursor->movePosition(QTextCursor::End); + break; + default: + break; + } + return 0; // no error +} + +int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) +{ + QTextCharFormat charFmt; + switch (type) { + case MD_SPAN_EM: + charFmt.setFontItalic(true); + break; + case MD_SPAN_STRONG: + charFmt.setFontWeight(QFont::Bold); + break; + case MD_SPAN_A: { + MD_SPAN_A_DETAIL *detail = static_cast(det); + QString url = QString::fromLatin1(detail->href.text, detail->href.size); + QString title = QString::fromLatin1(detail->title.text, detail->title.size); + charFmt.setAnchorHref(url); + charFmt.setAnchorName(title); + charFmt.setForeground(m_palette.link()); + qCDebug(lcMD) << "anchor" << url << title; + } break; + case MD_SPAN_IMG: { + m_imageSpan = true; + MD_SPAN_IMG_DETAIL *detail = static_cast(det); + QString src = QString::fromUtf8(detail->src.text, detail->src.size); + QString title = QString::fromUtf8(detail->title.text, detail->title.size); + QTextImageFormat img; + img.setName(src); + qCDebug(lcMD) << "image" << src << "title" << title << "relative to" << m_doc->baseUrl(); + m_cursor->insertImage(img); + break; + } + case MD_SPAN_CODE: + charFmt.setFont(m_monoFont); + break; + case MD_SPAN_DEL: + charFmt.setFontStrikeOut(true); + break; + } + m_spanFormatStack.push(charFmt); + m_cursor->setCharFormat(charFmt); + return 0; // no error +} + +int QTextMarkdownImporter::cbLeaveSpan(MD_SPANTYPE type, void *detail) +{ + Q_UNUSED(detail) + QTextCharFormat charFmt; + if (!m_spanFormatStack.isEmpty()) { + m_spanFormatStack.pop(); + if (!m_spanFormatStack.isEmpty()) + charFmt = m_spanFormatStack.top(); + } + m_cursor->setCharFormat(charFmt); + if (type == MD_SPAN_IMG) + m_imageSpan = false; + return 0; // no error +} + +int QTextMarkdownImporter::cbText(MD_TEXTTYPE type, const MD_CHAR *text, MD_SIZE size) +{ + if (m_imageSpan) + return 0; // it's the alt-text + static const QRegularExpression openingBracket(QStringLiteral("<[a-zA-Z]")); + static const QRegularExpression closingBracket(QStringLiteral("(/>|insertHtml(s); + s = QString(); + break; + case MD_TEXT_HTML: + // count how many tags are opened and how many are closed + { + int startIdx = 0; + while ((startIdx = s.indexOf(openingBracket, startIdx)) >= 0) { + ++m_htmlTagDepth; + startIdx += 2; + } + startIdx = 0; + while ((startIdx = s.indexOf(closingBracket, startIdx)) >= 0) { + --m_htmlTagDepth; + startIdx += 2; + } + } + m_htmlAccumulator += s; + s = QString(); + if (!m_htmlTagDepth) { // all open tags are now closed + qCDebug(lcMD) << "HTML" << m_htmlAccumulator; + m_cursor->insertHtml(m_htmlAccumulator); + if (m_spanFormatStack.isEmpty()) + m_cursor->setCharFormat(QTextCharFormat()); + else + m_cursor->setCharFormat(m_spanFormatStack.top()); + m_htmlAccumulator = QString(); + } + break; + } + + switch (m_blockType) { + case MD_BLOCK_TD: + m_nonEmptyTableCells.append(m_tableCol); + break; + default: + break; + } + + if (!s.isEmpty()) + m_cursor->insertText(s); + return 0; // no error +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h new file mode 100644 index 0000000000..b73e744434 --- /dev/null +++ b/src/gui/text/qtextmarkdownimporter_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui 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 QTEXTMARKDOWNIMPORTER_H +#define QTEXTMARKDOWNIMPORTER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include + +#include "../../3rdparty/md4c/md4c.h" + +QT_BEGIN_NAMESPACE + +class QTextCursor; +class QTextDocument; +class QTextTable; + +class Q_GUI_EXPORT QTextMarkdownImporter +{ +public: + enum Feature { + FeatureCollapseWhitespace = MD_FLAG_COLLAPSEWHITESPACE, + FeaturePermissiveATXHeaders = MD_FLAG_PERMISSIVEATXHEADERS, + FeaturePermissiveURLAutoLinks = MD_FLAG_PERMISSIVEURLAUTOLINKS, + FeaturePermissiveMailAutoLinks = MD_FLAG_PERMISSIVEEMAILAUTOLINKS, + FeatureNoIndentedCodeBlocks = MD_FLAG_NOINDENTEDCODEBLOCKS, + FeatureNoHTMLBlocks = MD_FLAG_NOHTMLBLOCKS, + FeatureNoHTMLSpans = MD_FLAG_NOHTMLSPANS, + FeatureTables = MD_FLAG_TABLES, + FeatureStrikeThrough = MD_FLAG_STRIKETHROUGH, + FeaturePermissiveWWWAutoLinks = MD_FLAG_PERMISSIVEWWWAUTOLINKS, + FeatureTasklists = MD_FLAG_TASKLISTS, + // composite flags + FeaturePermissiveAutoLinks = MD_FLAG_PERMISSIVEAUTOLINKS, + FeatureNoHTML = MD_FLAG_NOHTML, + DialectCommonMark = MD_DIALECT_COMMONMARK, + DialectGitHub = MD_DIALECT_GITHUB + }; + Q_DECLARE_FLAGS(Features, Feature) + + QTextMarkdownImporter(Features features); + + void import(QTextDocument *doc, const QString &markdown); + +public: + // MD4C callbacks + int cbEnterBlock(MD_BLOCKTYPE type, void* detail); + int cbLeaveBlock(MD_BLOCKTYPE type, void* detail); + int cbEnterSpan(MD_SPANTYPE type, void* detail); + int cbLeaveSpan(MD_SPANTYPE type, void* detail); + int cbText(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size); + +private: + QTextDocument *m_doc = nullptr; + QTextCursor *m_cursor = nullptr; + QTextTable *m_currentTable = nullptr; // because m_cursor->currentTable() doesn't work + QString m_htmlAccumulator; + QVector m_nonEmptyTableCells; // in the current row + QStack m_listStack; + QStack m_spanFormatStack; + QFont m_monoFont; + QPalette m_palette; + int m_htmlTagDepth = 0; + int m_tableColumnCount = 0; + int m_tableRowCount = 0; + int m_tableCol = -1; // because relative cell movements (e.g. m_cursor->movePosition(QTextCursor::NextCell)) don't work + Features m_features; + MD_BLOCKTYPE m_blockType = MD_BLOCK_DOC; + bool m_emptyList = false; // true when the last thing we did was insertList + bool m_imageSpan = false; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QTextMarkdownImporter::Features) + +QT_END_NAMESPACE + +#endif // QTEXTMARKDOWNIMPORTER_H diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index abe20abe02..b35a231747 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -97,6 +97,18 @@ qtConfig(textodfwriter) { text/qzip.cpp } +qtConfig(textmarkdownreader) { + qtConfig(system-textmarkdownreader) { + QMAKE_USE += libmd4c + } else { + include($$PWD/../../3rdparty/md4c.pri) + } + HEADERS += \ + text/qtextmarkdownimporter_p.h + SOURCES += \ + text/qtextmarkdownimporter.cpp +} + qtConfig(cssparser) { HEADERS += \ text/qcssparser_p.h diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 920133d493..4a06f58b4a 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -1202,6 +1202,13 @@ QString QTextEdit::toHtml() const } #endif +#if QT_CONFIG(textmarkdownreader) +void QTextEdit::setMarkdown(const QString &text) +{ + Q_D(const QTextEdit); + d->control->setMarkdown(text); +} +#endif /*! \reimp */ diff --git a/src/widgets/widgets/qtextedit.h b/src/widgets/widgets/qtextedit.h index 3aa23aaace..f20bd936c4 100644 --- a/src/widgets/widgets/qtextedit.h +++ b/src/widgets/widgets/qtextedit.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -237,6 +237,9 @@ public Q_SLOTS: void setPlainText(const QString &text); #ifndef QT_NO_TEXTHTMLPARSER void setHtml(const QString &text); +#endif +#if QT_CONFIG(textmarkdownreader) + void setMarkdown(const QString &text); #endif void setText(const QString &text); diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 711c4bfd2a..5744d43cbf 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -491,6 +491,11 @@ void QWidgetTextControlPrivate::setContent(Qt::TextFormat format, const QString formatCursor.select(QTextCursor::Document); formatCursor.setCharFormat(charFormatForInsertion); formatCursor.endEditBlock(); +#if QT_CONFIG(textmarkdownreader) + } else if (format == Qt::MarkdownText) { + doc->setMarkdown(text); + doc->setUndoRedoEnabled(false); +#endif } else { #ifndef QT_NO_TEXTHTMLPARSER doc->setHtml(text); @@ -1194,6 +1199,14 @@ void QWidgetTextControl::setPlainText(const QString &text) d->setContent(Qt::PlainText, text); } +#if QT_CONFIG(textmarkdownreader) +void QWidgetTextControl::setMarkdown(const QString &text) +{ + Q_D(QWidgetTextControl); + d->setContent(Qt::MarkdownText, text); +} +#endif + void QWidgetTextControl::setHtml(const QString &text) { Q_D(QWidgetTextControl); diff --git a/src/widgets/widgets/qwidgettextcontrol_p.h b/src/widgets/widgets/qwidgettextcontrol_p.h index 9c80d53728..4c9e47dfc9 100644 --- a/src/widgets/widgets/qwidgettextcontrol_p.h +++ b/src/widgets/widgets/qwidgettextcontrol_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -194,6 +194,9 @@ public: public Q_SLOTS: void setPlainText(const QString &text); +#if QT_CONFIG(textmarkdownreader) + void setMarkdown(const QString &text); +#endif void setHtml(const QString &text); #ifndef QT_NO_CLIPBOARD diff --git a/src/widgets/widgets/qwidgettextcontrol_p_p.h b/src/widgets/widgets/qwidgettextcontrol_p_p.h index 6a1ee564cd..6ccdfafe2b 100644 --- a/src/widgets/widgets/qwidgettextcontrol_p_p.h +++ b/src/widgets/widgets/qwidgettextcontrol_p_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. From 642ef0c7311e18b9b4414af6ec3a2d8210bb6880 Mon Sep 17 00:00:00 2001 From: Konstantin Shegunov Date: Wed, 3 Apr 2019 13:00:01 +0300 Subject: [PATCH 005/122] Clear SSL key data as soon as possible when move-assigning Move-assign uses qSwap to exchange the private pointer and thus can extend the lifetime of sensitive data. The move assignment operator is changed so it releases the private data as soon as possible. [ChangeLog][QtNetwork][QSslKey] Key data is cleared as soon as possible when move-assigning. Change-Id: Iebd029bf657acfe000417ce648e3b3829948c0e5 Reviewed-by: Samuel Gaist --- src/network/ssl/qsslkey.h | 5 ++--- src/network/ssl/qsslkey_p.cpp | 18 ++++++++++++++++++ src/network/ssl/qsslkey_qt.cpp | 5 ++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/network/ssl/qsslkey.h b/src/network/ssl/qsslkey.h index a865f20a51..74be406539 100644 --- a/src/network/ssl/qsslkey.h +++ b/src/network/ssl/qsslkey.h @@ -71,9 +71,8 @@ public: const QByteArray &passPhrase = QByteArray()); explicit QSslKey(Qt::HANDLE handle, QSsl::KeyType type = QSsl::PrivateKey); QSslKey(const QSslKey &other); -#ifdef Q_COMPILER_RVALUE_REFS - QSslKey &operator=(QSslKey &&other) noexcept { swap(other); return *this; } -#endif + QSslKey(QSslKey &&other) noexcept; + QSslKey &operator=(QSslKey &&other) noexcept; QSslKey &operator=(const QSslKey &other); ~QSslKey(); diff --git a/src/network/ssl/qsslkey_p.cpp b/src/network/ssl/qsslkey_p.cpp index b29b38beab..7d14aacebf 100644 --- a/src/network/ssl/qsslkey_p.cpp +++ b/src/network/ssl/qsslkey_p.cpp @@ -385,6 +385,24 @@ QSslKey::QSslKey(const QSslKey &other) : d(other.d) { } +QSslKey::QSslKey(QSslKey &&other) noexcept + : d(nullptr) +{ + qSwap(d, other.d); +} + +QSslKey &QSslKey::operator=(QSslKey &&other) noexcept +{ + if (this == &other) + return *this; + + // If no one else is referencing the key data we want to make sure + // before we swap the d-ptr that it is not left in memory. + d.reset(); + qSwap(d, other.d); + return *this; +} + /*! Destroys the QSslKey object. */ diff --git a/src/network/ssl/qsslkey_qt.cpp b/src/network/ssl/qsslkey_qt.cpp index 2662418a05..43969c3d28 100644 --- a/src/network/ssl/qsslkey_qt.cpp +++ b/src/network/ssl/qsslkey_qt.cpp @@ -48,6 +48,8 @@ #include +#include + QT_USE_NAMESPACE static const quint8 bits_table[256] = { @@ -186,8 +188,9 @@ static QByteArray deriveKey(QSslKeyPrivate::Cipher cipher, const QByteArray &pas void QSslKeyPrivate::clear(bool deep) { - Q_UNUSED(deep); isNull = true; + if (deep) + std::memset(derData.data(), 0, derData.size()); derData.clear(); keyLength = -1; } From e2906ea5c4b97ca9bb4ebf9710207097c44cc8ce Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 27 Sep 2018 00:19:49 +0200 Subject: [PATCH 006/122] QRegExp include cleanup QRegExp includes can be found in several files where there's not even a use of the class. This patch aims to avoid needless includes as well as follow the "include only what you use" moto. This patch removes a QRegExp include from the QStringList header which means that there is likely going to be code breaking since QStringList is used in many places and would get QRegExp in. [ChangeLog][Potentially Source-Incompatible Changes] qstringlist.h no longer includes qregexp.h. Change-Id: I32847532f16e419d4cb735ddc11a26551127e923 Reviewed-by: Thiago Macieira --- qmake/generators/metamakefile.cpp | 1 - qmake/generators/unix/unixmake.cpp | 1 - qmake/generators/win32/msbuild_objectmodel.cpp | 1 + qmake/generators/win32/msvc_objectmodel.cpp | 1 + qmake/library/ioutils.cpp | 1 + qmake/library/qmakeevaluator_p.h | 2 -- qmake/library/qmakeglobals.cpp | 1 - src/corelib/io/qdiriterator.cpp | 1 + src/corelib/itemmodels/qabstractitemmodel.cpp | 1 + src/corelib/kernel/qmetatype.cpp | 1 + src/corelib/kernel/qvariant.cpp | 1 + src/corelib/tools/qdatetimeparser.cpp | 1 - src/corelib/tools/qstringlist.cpp | 1 + src/gui/image/qpicture.cpp | 1 + src/gui/image/qxbmhandler.cpp | 1 + src/gui/image/qxpmhandler.cpp | 1 + src/gui/kernel/qkeysequence.cpp | 3 --- src/gui/kernel/qsimpledrag.cpp | 1 - src/network/access/qnetworkcookie.cpp | 1 + .../fontdatabases/windows/qwindowsfontdatabase_ft.cpp | 4 ++++ src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 1 - src/plugins/platforms/cocoa/qcocoamenuitem.mm | 1 + src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp | 1 - src/sql/kernel/qsqlresult.cpp | 1 - src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp | 1 - src/tools/rcc/rcc.cpp | 1 + src/tools/tracegen/etw.cpp | 1 - src/tools/tracegen/lttng.cpp | 1 - src/widgets/dialogs/qcolordialog.cpp | 5 +++++ tests/auto/other/lancelot/paintcommands.h | 1 + tests/baselineserver/shared/baselineprotocol.cpp | 1 + 31 files changed, 25 insertions(+), 16 deletions(-) diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp index 8ebd0c61ce..f9159ccd75 100644 --- a/qmake/generators/metamakefile.cpp +++ b/qmake/generators/metamakefile.cpp @@ -27,7 +27,6 @@ ****************************************************************************/ #include "metamakefile.h" -#include "qregexp.h" #include "qdir.h" #include "qdebug.h" #include "makefile.h" diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 7f42fbe09e..836737e77d 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -28,7 +28,6 @@ #include "unixmake.h" #include "option.h" -#include #include #include #include diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index 0e95766f8e..89428bd454 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -34,6 +34,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index cf0b96ec9f..eb46e0cf69 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -34,6 +34,7 @@ #include #include +#include using namespace QMakeInternal; diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index 3e49a99cd5..d2171274d8 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -30,6 +30,7 @@ #include #include +#include #ifdef Q_OS_WIN # include diff --git a/qmake/library/qmakeevaluator_p.h b/qmake/library/qmakeevaluator_p.h index f888bc5765..da83ff0de2 100644 --- a/qmake/library/qmakeevaluator_p.h +++ b/qmake/library/qmakeevaluator_p.h @@ -31,8 +31,6 @@ #include "proitems.h" -#include - #define debugMsg if (!m_debugLevel) {} else debugMsgInternal #define traceMsg if (!m_debugLevel) {} else traceMsgInternal #ifdef PROEVALUATOR_DEBUG diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp index daf4707779..1d76cecc45 100644 --- a/qmake/library/qmakeglobals.cpp +++ b/qmake/library/qmakeglobals.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp index 648593b020..69d61bf5a8 100644 --- a/src/corelib/io/qdiriterator.cpp +++ b/src/corelib/io/qdiriterator.cpp @@ -93,6 +93,7 @@ #include "qdir_p.h" #include "qabstractfileengine_p.h" +#include #include #include #include diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index 18f0f6f55f..664e16540b 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 19bda7e8d6..855d36794d 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -51,6 +51,7 @@ #include "quuid.h" #include "qvariant.h" #include "qdatastream.h" +#include "qregexp.h" #include "qmetatypeswitcher_p.h" #if QT_CONFIG(regularexpression) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index cd4e233af0..4af2073365 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -55,6 +55,7 @@ #include "qstringlist.h" #include "qurl.h" #include "qlocale.h" +#include "qregexp.h" #include "quuid.h" #if QT_CONFIG(itemmodel) #include "qabstractitemmodel.h" diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index e8470f6cde..5d1704daeb 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -47,7 +47,6 @@ #if QT_CONFIG(timezone) #include "qtimezone.h" #endif -#include "qregexp.h" #include "qdebug.h" //#define QDATETIMEPARSER_DEBUG diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index 49247d66b8..f6da7b1428 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include +#include #include #if QT_CONFIG(regularexpression) # include diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index 56b82abcfa..350fda19ac 100644 --- a/src/gui/image/qpicture.cpp +++ b/src/gui/image/qpicture.cpp @@ -54,6 +54,7 @@ #include "qpainter.h" #include "qpainterpath.h" #include "qpixmap.h" +#include "qregexp.h" #include "qregion.h" #include "qdebug.h" diff --git a/src/gui/image/qxbmhandler.cpp b/src/gui/image/qxbmhandler.cpp index 65a5b63bc7..3cd15b3e4d 100644 --- a/src/gui/image/qxbmhandler.cpp +++ b/src/gui/image/qxbmhandler.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index a32dfda96d..7349a400a6 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 0fa3dcfbdb..8688bb8403 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -46,9 +46,6 @@ #include "qdebug.h" #include -#ifndef QT_NO_REGEXP -# include "qregexp.h" -#endif #ifndef QT_NO_DATASTREAM # include "qdatastream.h" #endif diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp index 9aab332ef5..bba2a863a9 100644 --- a/src/gui/kernel/qsimpledrag.cpp +++ b/src/gui/kernel/qsimpledrag.cpp @@ -48,7 +48,6 @@ #include "qpoint.h" #include "qbuffer.h" #include "qimage.h" -#include "qregexp.h" #include "qdir.h" #include "qimagereader.h" #include "qimagewriter.h" diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp index b7cf989477..903de322ff 100644 --- a/src/network/access/qnetworkcookie.cpp +++ b/src/network/access/qnetworkcookie.cpp @@ -46,6 +46,7 @@ #include "QtCore/qdebug.h" #include "QtCore/qlist.h" #include "QtCore/qlocale.h" +#include #include "QtCore/qstring.h" #include "QtCore/qstringlist.h" #include "QtCore/qurl.h" diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp index db2186644b..40d5749cf3 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp @@ -48,7 +48,11 @@ #include #include #include +#if QT_CONFIG(regularexpression) #include +#else +#include +#endif #include #include diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index d1695ea860..5f32400af0 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -51,7 +51,6 @@ #include "qt_mac_p.h" #include "qcocoahelpers.h" #include "qcocoaeventdispatcher.h" -#include #include #include #include diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index e54b6284e5..32fc3ab660 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -53,6 +53,7 @@ #include #include +#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp index 390f05c7aa..b7bcd044ab 100644 --- a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp +++ b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp index 589088238b..cc91c6d0ed 100644 --- a/src/sql/kernel/qsqlresult.cpp +++ b/src/sql/kernel/qsqlresult.cpp @@ -41,7 +41,6 @@ #include "qvariant.h" #include "qhash.h" -#include "qregexp.h" #include "qsqlerror.h" #include "qsqlfield.h" #include "qsqlrecord.h" diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp index 7c6f0bdeef..522c55593f 100644 --- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp +++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp index bb4e6e3615..08fb6fca5f 100644 --- a/src/tools/rcc/rcc.cpp +++ b/src/tools/rcc/rcc.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include diff --git a/src/tools/tracegen/etw.cpp b/src/tools/tracegen/etw.cpp index e839137915..acd81bd5c1 100644 --- a/src/tools/tracegen/etw.cpp +++ b/src/tools/tracegen/etw.cpp @@ -45,7 +45,6 @@ #include #include #include -#include #include static inline QString providerVar(const QString &providerName) diff --git a/src/tools/tracegen/lttng.cpp b/src/tools/tracegen/lttng.cpp index f0fbca9e16..1aef1b3d17 100644 --- a/src/tools/tracegen/lttng.cpp +++ b/src/tools/tracegen/lttng.cpp @@ -46,7 +46,6 @@ #include #include #include -#include #include static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field) diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index c0bacd553d..a6b6df4045 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -57,6 +57,11 @@ #include "qpainter.h" #include "qpixmap.h" #include "qpushbutton.h" +#if QT_CONFIG(regularexpression) +#include +#else +#include +#endif #if QT_CONFIG(settings) #include "qsettings.h" #endif diff --git a/tests/auto/other/lancelot/paintcommands.h b/tests/auto/other/lancelot/paintcommands.h index 79bdab634a..2923502e68 100644 --- a/tests/auto/other/lancelot/paintcommands.h +++ b/tests/auto/other/lancelot/paintcommands.h @@ -37,6 +37,7 @@ #include #include #include +#include QT_FORWARD_DECLARE_CLASS(QPainter) #ifndef QT_NO_OPENGL diff --git a/tests/baselineserver/shared/baselineprotocol.cpp b/tests/baselineserver/shared/baselineprotocol.cpp index c9f9cd9bd2..6357024341 100644 --- a/tests/baselineserver/shared/baselineprotocol.cpp +++ b/tests/baselineserver/shared/baselineprotocol.cpp @@ -38,6 +38,7 @@ #include #include #include +#include const QString PI_Project(QLS("Project")); const QString PI_TestCase(QLS("TestCase")); From 7d646508c8219408f90103ed13613db8d01a4065 Mon Sep 17 00:00:00 2001 From: Alexander Kanavin Date: Mon, 25 Feb 2019 16:05:13 +0100 Subject: [PATCH 007/122] libinput: add support for LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE This is required to get Qt EGLFS in qemu working, as qemu mouse device issues only absolute mouse events. Fixes: QTBUG-69172 Change-Id: Ia9985dc01d7871fdcd856c14160d54d3ce684396 Reviewed-by: Johan Helsing --- .../input/libinput/qlibinputhandler.cpp | 3 +++ .../input/libinput/qlibinputpointer.cpp | 18 ++++++++++++++++++ .../input/libinput/qlibinputpointer_p.h | 1 + 3 files changed, 22 insertions(+) diff --git a/src/platformsupport/input/libinput/qlibinputhandler.cpp b/src/platformsupport/input/libinput/qlibinputhandler.cpp index 52eaa18f4b..bb81890a67 100644 --- a/src/platformsupport/input/libinput/qlibinputhandler.cpp +++ b/src/platformsupport/input/libinput/qlibinputhandler.cpp @@ -205,6 +205,9 @@ void QLibInputHandler::processEvent(libinput_event *ev) case LIBINPUT_EVENT_POINTER_MOTION: m_pointer->processMotion(libinput_event_get_pointer_event(ev)); break; + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + m_pointer->processAbsMotion(libinput_event_get_pointer_event(ev)); + break; case LIBINPUT_EVENT_POINTER_AXIS: m_pointer->processAxis(libinput_event_get_pointer_event(ev)); break; diff --git a/src/platformsupport/input/libinput/qlibinputpointer.cpp b/src/platformsupport/input/libinput/qlibinputpointer.cpp index c54b61fc66..db9e81b5df 100644 --- a/src/platformsupport/input/libinput/qlibinputpointer.cpp +++ b/src/platformsupport/input/libinput/qlibinputpointer.cpp @@ -103,6 +103,24 @@ void QLibInputPointer::processMotion(libinput_event_pointer *e) Qt::NoButton, QEvent::MouseMove, mods); } +void QLibInputPointer::processAbsMotion(libinput_event_pointer *e) +{ + QScreen * const primaryScreen = QGuiApplication::primaryScreen(); + const QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen); + + const double x = libinput_event_pointer_get_absolute_x_transformed(e, g.width()); + const double y = libinput_event_pointer_get_absolute_y_transformed(e, g.height()); + + m_pos.setX(qBound(g.left(), qRound(g.left() + x), g.right())); + m_pos.setY(qBound(g.top(), qRound(g.top() + y), g.bottom())); + + Qt::KeyboardModifiers mods = QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers(); + + QWindowSystemInterface::handleMouseEvent(nullptr, m_pos, m_pos, m_buttons, + Qt::NoButton, QEvent::MouseMove, mods); + +} + void QLibInputPointer::processAxis(libinput_event_pointer *e) { double value; // default axis value is 15 degrees per wheel click diff --git a/src/platformsupport/input/libinput/qlibinputpointer_p.h b/src/platformsupport/input/libinput/qlibinputpointer_p.h index a7a66337f1..55d4a5f919 100644 --- a/src/platformsupport/input/libinput/qlibinputpointer_p.h +++ b/src/platformsupport/input/libinput/qlibinputpointer_p.h @@ -64,6 +64,7 @@ public: void processButton(libinput_event_pointer *e); void processMotion(libinput_event_pointer *e); + void processAbsMotion(libinput_event_pointer *e); void processAxis(libinput_event_pointer *e); void setPos(const QPoint &pos); From c17d6d4e4657416051847d2c78ef944ea8f362f8 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Tue, 23 Apr 2019 16:13:12 +0200 Subject: [PATCH 008/122] Fix compiling with QHOSTINFO_DEBUG enabled Since we require getaddrinfo and freeaddrinfo, those symbols are not resolved dynamically, and will never be null, which causes compile errors. Correctly appending a string literal shuts up compiler warnings. Change-Id: I0096dca6a77ad86e0c89890444b8d7bbb38a40f2 Reviewed-by: Thiago Macieira --- src/network/kernel/qhostinfo_win.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index c51e9968f8..ef7cff46f1 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -79,9 +79,8 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QHostInfo results; #if defined(QHOSTINFO_DEBUG) - qDebug("QHostInfoAgent::fromName(): looking up \"%s\" (IPv6 support is %s)", - hostName.toLatin1().constData(), - (getaddrinfo && freeaddrinfo) ? "enabled" : "disabled"); + qDebug("QHostInfoAgent::fromName(%s) looking up...", + hostName.toLatin1().constData()); #endif QHostAddress address; @@ -129,6 +128,12 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) if (err == 0) { QList addresses; for (addrinfo *p = res; p != 0; p = p->ai_next) { +#ifdef QHOSTINFO_DEBUG + qDebug() << "getaddrinfo node: flags:" << p->ai_flags << "family:" << p->ai_family + << "ai_socktype:" << p->ai_socktype << "ai_protocol:" << p->ai_protocol + << "ai_addrlen:" << p->ai_addrlen; +#endif + switch (p->ai_family) { case AF_INET: { QHostAddress addr; @@ -163,7 +168,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QString tmp; QList addresses = results.addresses(); for (int i = 0; i < addresses.count(); ++i) { - if (i != 0) tmp += ", "; + if (i != 0) tmp += QLatin1String(", "); tmp += addresses.at(i).toString(); } qDebug("QHostInfoAgent::run(): found %i entries: {%s}", From b21b07877a96c175ee51e83e1b41425c2e67beb3 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Tue, 16 Apr 2019 09:58:23 +0200 Subject: [PATCH 009/122] Add a QVkConvenience class with vkFormatFromGlFormat Converts from OpenGL formats to Vulkan formats. There are commented out lines for the formats in QOpenGLTexture::TextureFormat for which it was hard to find an unambiguous mapping to vkFormat. Task-number: QTBUG-75108 Change-Id: I06a7fd8df7d98cef314410ffd79ca9cff6599357 Reviewed-by: Laszlo Agocs --- .../vkconvenience/qvkconvenience.cpp | 215 ++++++++++++++++++ .../vkconvenience/qvkconvenience_p.h | 67 ++++++ .../vkconvenience/vkconvenience.pro | 2 + 3 files changed, 284 insertions(+) create mode 100644 src/platformsupport/vkconvenience/qvkconvenience.cpp create mode 100644 src/platformsupport/vkconvenience/qvkconvenience_p.h diff --git a/src/platformsupport/vkconvenience/qvkconvenience.cpp b/src/platformsupport/vkconvenience/qvkconvenience.cpp new file mode 100644 index 0000000000..462cdc9e0d --- /dev/null +++ b/src/platformsupport/vkconvenience/qvkconvenience.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 "qvkconvenience_p.h" + +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QVkConvenience + \brief A collection of static helper functions for Vulkan support + \since 5.14 + \internal + \ingroup qpa + */ + +VkFormat QVkConvenience::vkFormatFromGlFormat(uint glFormat) +{ + using GlFormat = QOpenGLTexture::TextureFormat; + switch (glFormat) { + case GlFormat::NoFormat: return VK_FORMAT_UNDEFINED; // GL_NONE + + // Unsigned normalized formats + case GlFormat::R8_UNorm: return VK_FORMAT_R8_UNORM; // GL_R8 + case GlFormat::RG8_UNorm: return VK_FORMAT_R8G8_UNORM; // GL_RG8 + case GlFormat::RGB8_UNorm: return VK_FORMAT_R8G8B8_UNORM; // GL_RGB8 + case GlFormat::RGBA8_UNorm: return VK_FORMAT_R8G8B8A8_UNORM; // GL_RGBA8 + + case GlFormat::R16_UNorm: return VK_FORMAT_R16_UNORM; // GL_R16 + case GlFormat::RG16_UNorm: return VK_FORMAT_R16G16_UNORM; // GL_RG16 + case GlFormat::RGB16_UNorm: return VK_FORMAT_R16G16B16_UNORM; // GL_RGB16 + case GlFormat::RGBA16_UNorm: return VK_FORMAT_R16G16B16A16_UNORM; // GL_RGBA16 + + // Signed normalized formats + case GlFormat::R8_SNorm: return VK_FORMAT_R8_SNORM; // GL_R8_SNORM + case GlFormat::RG8_SNorm: return VK_FORMAT_R8G8_SNORM; // GL_RG8_SNORM + case GlFormat::RGB8_SNorm: return VK_FORMAT_R8G8B8_SNORM; // GL_RGB8_SNORM + case GlFormat::RGBA8_SNorm: return VK_FORMAT_R8G8B8A8_SNORM; // GL_RGBA8_SNORM + + case GlFormat::R16_SNorm: return VK_FORMAT_R16_SNORM; // GL_R16_SNORM + case GlFormat::RG16_SNorm: return VK_FORMAT_R16G16_SNORM; // GL_RG16_SNORM + case GlFormat::RGB16_SNorm: return VK_FORMAT_R16G16B16_SNORM; // GL_RGB16_SNORM + case GlFormat::RGBA16_SNorm: return VK_FORMAT_R16G16B16A16_SNORM; // GL_RGBA16_SNORM + + // Unsigned integer formats + case GlFormat::R8U: return VK_FORMAT_R8_UINT; // GL_R8UI + case GlFormat::RG8U: return VK_FORMAT_R8G8_UINT; // GL_RG8UI + case GlFormat::RGB8U: return VK_FORMAT_R8G8B8_UINT; // GL_RGB8UI + case GlFormat::RGBA8U: return VK_FORMAT_R8G8B8A8_UINT; // GL_RGBA8UI + + case GlFormat::R16U: return VK_FORMAT_R16_UINT; // GL_R16UI + case GlFormat::RG16U: return VK_FORMAT_R16G16_UINT; // GL_RG16UI + case GlFormat::RGB16U: return VK_FORMAT_R16G16B16_UINT; // GL_RGB16UI + case GlFormat::RGBA16U: return VK_FORMAT_R16G16B16A16_UINT; // GL_RGBA16UI + + case GlFormat::R32U: return VK_FORMAT_R32_UINT; // GL_R32UI + case GlFormat::RG32U: return VK_FORMAT_R32G32_UINT; // GL_RG32UI + case GlFormat::RGB32U: return VK_FORMAT_R32G32B32_UINT; // GL_RGB32UI + case GlFormat::RGBA32U: return VK_FORMAT_R32G32B32A32_UINT; // GL_RGBA32UI + + // Signed integer formats + case GlFormat::R8I: return VK_FORMAT_R8_SINT; // GL_R8I + case GlFormat::RG8I: return VK_FORMAT_R8G8_SINT; // GL_RG8I + case GlFormat::RGB8I: return VK_FORMAT_R8G8B8_SINT; // GL_RGB8I + case GlFormat::RGBA8I: return VK_FORMAT_R8G8B8A8_SINT; // GL_RGBA8I + + case GlFormat::R16I: return VK_FORMAT_R16_SINT; // GL_R16I + case GlFormat::RG16I: return VK_FORMAT_R16G16_SINT; // GL_RG16I + case GlFormat::RGB16I: return VK_FORMAT_R16G16B16_SINT; // GL_RGB16I + case GlFormat::RGBA16I: return VK_FORMAT_R16G16B16A16_SINT; // GL_RGBA16I + + case GlFormat::R32I: return VK_FORMAT_R32_SINT; // GL_R32I + case GlFormat::RG32I: return VK_FORMAT_R32G32_SINT; // GL_RG32I + case GlFormat::RGB32I: return VK_FORMAT_R32G32B32_SINT; // GL_RGB32I + case GlFormat::RGBA32I: return VK_FORMAT_R32G32B32A32_SINT; // GL_RGBA32I + + // Floating point formats + case GlFormat::R16F: return VK_FORMAT_R16_SFLOAT; // GL_R16F + case GlFormat::RG16F: return VK_FORMAT_R16G16_SFLOAT; // GL_RG16F + case GlFormat::RGB16F: return VK_FORMAT_R16G16B16_SFLOAT; // GL_RGB16F + case GlFormat::RGBA16F: return VK_FORMAT_R16G16B16A16_SFLOAT; // GL_RGBA16F + + case GlFormat::R32F: return VK_FORMAT_R32_SFLOAT; // GL_R32F + case GlFormat::RG32F: return VK_FORMAT_R32G32_SFLOAT; // GL_RG32F + case GlFormat::RGB32F: return VK_FORMAT_R32G32B32_SFLOAT; // GL_RGB32F + case GlFormat::RGBA32F: return VK_FORMAT_R32G32B32A32_SFLOAT; // GL_RGBA32F + + // Packed formats + case GlFormat::RGB9E5: return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; // GL_RGB9_E5 + case GlFormat::RG11B10F: return VK_FORMAT_B10G11R11_UFLOAT_PACK32; // GL_R11F_G11F_B10F +// case GlFormat::RG3B2: return VK_FORMAT_R3_G3_B2; // GL_R3_G3_B2 + case GlFormat::R5G6B5: return VK_FORMAT_R5G6B5_UNORM_PACK16; // GL_RGB565 + case GlFormat::RGB5A1: return VK_FORMAT_R5G5B5A1_UNORM_PACK16; // GL_RGB5_A1 + case GlFormat::RGBA4: return VK_FORMAT_R4G4B4A4_UNORM_PACK16; // GL_RGBA4 + case GlFormat::RGB10A2: return VK_FORMAT_A2R10G10B10_UINT_PACK32; // GL_RGB10_A2UI + + // Depth formats +// case Format::D16: return VK_FORMAT_DEPTH_COMPONENT16; // GL_DEPTH_COMPONENT16 +// case Format::D24: return VK_FORMAT_DEPTH_COMPONENT24; // GL_DEPTH_COMPONENT24 +// case Format::D24S8: return VK_FORMAT_DEPTH24_STENCIL8; // GL_DEPTH24_STENCIL8 +// case Format::D32: return VK_FORMAT_DEPTH_COMPONENT32; // GL_DEPTH_COMPONENT32 +// case Format::D32F: return VK_FORMAT_DEPTH_COMPONENT32F; // GL_DEPTH_COMPONENT32F +// case Format::D32FS8X24: return VK_FORMAT_DEPTH32F_STENCIL8; // GL_DEPTH32F_STENCIL8 +// case Format::S8: return VK_FORMAT_STENCIL_INDEX8; // GL_STENCIL_INDEX8 + + // Compressed formats + case GlFormat::RGB_DXT1: return VK_FORMAT_BC1_RGB_UNORM_BLOCK; // GL_COMPRESSED_RGB_S3TC_DXT1_EXT + case GlFormat::RGBA_DXT1: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK; // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + case GlFormat::RGBA_DXT3: return VK_FORMAT_BC2_UNORM_BLOCK; // GL_COMPRESSED_RGBA_S3TC_DXT3_EXT + case GlFormat::RGBA_DXT5: return VK_FORMAT_BC3_UNORM_BLOCK; // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT + case GlFormat::R_ATI1N_UNorm: return VK_FORMAT_BC4_UNORM_BLOCK; // GL_COMPRESSED_RED_RGTC1 + case GlFormat::R_ATI1N_SNorm: return VK_FORMAT_BC4_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_RED_RGTC1 + case GlFormat::RG_ATI2N_UNorm: return VK_FORMAT_BC5_UNORM_BLOCK; // GL_COMPRESSED_RG_RGTC2 + case GlFormat::RG_ATI2N_SNorm: return VK_FORMAT_BC5_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_RG_RGTC2 + case GlFormat::RGB_BP_UNSIGNED_FLOAT: return VK_FORMAT_BC6H_UFLOAT_BLOCK; // GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB + case GlFormat::RGB_BP_SIGNED_FLOAT: return VK_FORMAT_BC6H_SFLOAT_BLOCK; // GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB + case GlFormat::RGB_BP_UNorm: return VK_FORMAT_BC7_UNORM_BLOCK; // GL_COMPRESSED_RGBA_BPTC_UNORM_ARB + case GlFormat::R11_EAC_UNorm: return VK_FORMAT_EAC_R11_UNORM_BLOCK; // GL_COMPRESSED_R11_EAC + case GlFormat::R11_EAC_SNorm: return VK_FORMAT_EAC_R11_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_R11_EAC + case GlFormat::RG11_EAC_UNorm: return VK_FORMAT_EAC_R11G11_UNORM_BLOCK; // GL_COMPRESSED_RG11_EAC + case GlFormat::RG11_EAC_SNorm: return VK_FORMAT_EAC_R11G11_SNORM_BLOCK; // GL_COMPRESSED_SIGNED_RG11_EAC + case GlFormat::RGB8_ETC2: return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; // GL_COMPRESSED_RGB8_ETC2 + case GlFormat::SRGB8_ETC2: return VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ETC2 + case GlFormat::RGB8_PunchThrough_Alpha1_ETC2: return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 + case GlFormat::SRGB8_PunchThrough_Alpha1_ETC2: return VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 + case GlFormat::RGBA8_ETC2_EAC: return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; // GL_COMPRESSED_RGBA8_ETC2_EAC + case GlFormat::SRGB8_Alpha8_ETC2_EAC: return VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC +// case GlFormat::RGB8_ETC1: return VK_FORMAT_ETC1_RGB8_OES; // GL_ETC1_RGB8_OES + case GlFormat::RGBA_ASTC_4x4: return VK_FORMAT_ASTC_4x4_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_4x4_KHR + case GlFormat::RGBA_ASTC_5x4: return VK_FORMAT_ASTC_5x4_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_5x4_KHR + case GlFormat::RGBA_ASTC_5x5: return VK_FORMAT_ASTC_5x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_5x5_KHR + case GlFormat::RGBA_ASTC_6x5: return VK_FORMAT_ASTC_6x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_6x5_KHR + case GlFormat::RGBA_ASTC_6x6: return VK_FORMAT_ASTC_6x6_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_6x6_KHR + case GlFormat::RGBA_ASTC_8x5: return VK_FORMAT_ASTC_8x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_8x5_KHR + case GlFormat::RGBA_ASTC_8x6: return VK_FORMAT_ASTC_8x6_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_8x6_KHR + case GlFormat::RGBA_ASTC_8x8: return VK_FORMAT_ASTC_8x8_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_8x8_KHR + case GlFormat::RGBA_ASTC_10x5: return VK_FORMAT_ASTC_10x5_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x5_KHR + case GlFormat::RGBA_ASTC_10x6: return VK_FORMAT_ASTC_10x6_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x6_KHR + case GlFormat::RGBA_ASTC_10x8: return VK_FORMAT_ASTC_10x8_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x8_KHR + case GlFormat::RGBA_ASTC_10x10: return VK_FORMAT_ASTC_10x10_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_10x10_KHR + case GlFormat::RGBA_ASTC_12x10: return VK_FORMAT_ASTC_12x10_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_12x10_KHR + case GlFormat::RGBA_ASTC_12x12: return VK_FORMAT_ASTC_12x12_UNORM_BLOCK; // GL_COMPRESSED_RGBA_ASTC_12x12_KHR + case GlFormat::SRGB8_Alpha8_ASTC_4x4: return VK_FORMAT_ASTC_4x4_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR + case GlFormat::SRGB8_Alpha8_ASTC_5x4: return VK_FORMAT_ASTC_5x4_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR + case GlFormat::SRGB8_Alpha8_ASTC_5x5: return VK_FORMAT_ASTC_5x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR + case GlFormat::SRGB8_Alpha8_ASTC_6x5: return VK_FORMAT_ASTC_6x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR + case GlFormat::SRGB8_Alpha8_ASTC_6x6: return VK_FORMAT_ASTC_6x6_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR + case GlFormat::SRGB8_Alpha8_ASTC_8x5: return VK_FORMAT_ASTC_8x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR + case GlFormat::SRGB8_Alpha8_ASTC_8x6: return VK_FORMAT_ASTC_8x6_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR + case GlFormat::SRGB8_Alpha8_ASTC_8x8: return VK_FORMAT_ASTC_8x8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR + case GlFormat::SRGB8_Alpha8_ASTC_10x5: return VK_FORMAT_ASTC_10x5_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR + case GlFormat::SRGB8_Alpha8_ASTC_10x6: return VK_FORMAT_ASTC_10x6_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR + case GlFormat::SRGB8_Alpha8_ASTC_10x8: return VK_FORMAT_ASTC_10x8_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR + case GlFormat::SRGB8_Alpha8_ASTC_10x10: return VK_FORMAT_ASTC_10x10_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR + case GlFormat::SRGB8_Alpha8_ASTC_12x10: return VK_FORMAT_ASTC_12x10_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR + case GlFormat::SRGB8_Alpha8_ASTC_12x12: return VK_FORMAT_ASTC_12x12_SRGB_BLOCK; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR + + // sRGB formats + case GlFormat::SRGB8: return VK_FORMAT_R8G8B8_SRGB; // GL_SRGB8 + case GlFormat::SRGB8_Alpha8: return VK_FORMAT_R8G8B8A8_SRGB; // GL_SRGB8_ALPHA8 + case GlFormat::SRGB_DXT1: return VK_FORMAT_BC1_RGB_SRGB_BLOCK; // GL_COMPRESSED_SRGB_S3TC_DXT1_EXT + case GlFormat::SRGB_Alpha_DXT1: return VK_FORMAT_BC1_RGBA_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT + case GlFormat::SRGB_Alpha_DXT3: return VK_FORMAT_BC2_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT + case GlFormat::SRGB_Alpha_DXT5: return VK_FORMAT_BC3_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT + case GlFormat::SRGB_BP_UNorm: return VK_FORMAT_BC7_SRGB_BLOCK; // GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB + + // ES 2 formats +// case GlFormat::DepthFormat: return VK_FORMAT_DEPTH_COMPONENT; // GL_DEPTH_COMPONENT +// case GlFormat::AlphaFormat: return VK_FORMAT_ALPHA; // GL_ALPHA +// case GlFormat::RGBFormat: return VK_FORMAT_RGB; // GL_RGB +// case GlFormat::RGBAFormat: return VK_FORMAT_RGBA; // GL_RGBA +// case GlFormat::LuminanceFormat: return VK_FORMAT_LUMINANCE; // GL_LUMINANCE +// case GlFormat::LuminanceAlphaFormat: return VK_FORMAT; + default: return VK_FORMAT_UNDEFINED; + } +} + +QT_END_NAMESPACE diff --git a/src/platformsupport/vkconvenience/qvkconvenience_p.h b/src/platformsupport/vkconvenience/qvkconvenience_p.h new file mode 100644 index 0000000000..1dd1dfc4a7 --- /dev/null +++ b/src/platformsupport/vkconvenience/qvkconvenience_p.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 QVKCONVENIENCE_P_H +#define QVKCONVENIENCE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QVkConvenience +{ +public: + static VkFormat vkFormatFromGlFormat(uint glFormat); +}; + +QT_END_NAMESPACE + +#endif // QVKCONVENIENCE_P_H diff --git a/src/platformsupport/vkconvenience/vkconvenience.pro b/src/platformsupport/vkconvenience/vkconvenience.pro index 7a4cdb041d..ee540024cf 100644 --- a/src/platformsupport/vkconvenience/vkconvenience.pro +++ b/src/platformsupport/vkconvenience/vkconvenience.pro @@ -8,9 +8,11 @@ DEFINES += QT_NO_CAST_FROM_ASCII PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h SOURCES += \ + qvkconvenience.cpp \ qbasicvulkanplatforminstance.cpp HEADERS += \ + qvkconvenience_p.h \ qbasicvulkanplatforminstance_p.h load(qt_module) From 2eb849ed516afc8e602dbec3da0ac12db2cdf8ec Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 21 Feb 2019 20:54:03 +0100 Subject: [PATCH 010/122] Implement std::numeric_limits This shall make it more nearly a first-class numeric type; in particular, I need some of these for testlib's comparing and formatting of float16 to handle NaNs and infinities sensibly. Change-Id: Ic894dd0eb3e05653cd7645ab496463e7a884dff8 Reviewed-by: Qt CI Bot Reviewed-by: Thiago Macieira --- src/corelib/global/qfloat16.h | 71 +++++++++ src/corelib/serialization/qcborvalue.cpp | 4 +- .../corelib/global/qfloat16/tst_qfloat16.cpp | 142 ++++++++++++++++++ 3 files changed, 215 insertions(+), 2 deletions(-) diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 243aea98be..4c3f9ca063 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 by Southwest Research Institute (R) ** Contact: http://www.qt-project.org/legal ** @@ -66,6 +67,13 @@ QT_BEGIN_NAMESPACE class qfloat16 { + struct Wrap + { + // To let our private constructor work, without other code seeing + // ambiguity when constructing from int, double &c. + quint16 b16; + constexpr inline explicit Wrap(int value) : b16(value) {} + }; public: constexpr inline qfloat16() noexcept : b16(0) {} inline qfloat16(float f) noexcept; @@ -75,8 +83,20 @@ public: bool isInf() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7c; } bool isNaN() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7e; } bool isFinite() const noexcept { return ((b16 >> 8) & 0x7c) != 0x7c; } + // Support for std::numeric_limits + static constexpr qfloat16 _limit_epsilon() noexcept { return qfloat16(Wrap(0x1400)); } + static constexpr qfloat16 _limit_min() noexcept { return qfloat16(Wrap(0x400)); } + static constexpr qfloat16 _limit_denorm_min() noexcept { return qfloat16(Wrap(1)); } + static constexpr qfloat16 _limit_max() noexcept { return qfloat16(Wrap(0x7bff)); } + static constexpr qfloat16 _limit_lowest() noexcept { return qfloat16(Wrap(0xfbff)); } + static constexpr qfloat16 _limit_infinity() noexcept { return qfloat16(Wrap(0x7c00)); } + static constexpr qfloat16 _limit_quiet_NaN() noexcept { return qfloat16(Wrap(0x7e00)); } + // Signalling NaN is 0x7f00 + inline constexpr bool isNormal() const noexcept + { return b16 == 0 || ((b16 & 0x7c00) && (b16 & 0x7c00) != 0x7c00); } private: quint16 b16; + constexpr inline explicit qfloat16(Wrap nibble) noexcept : b16(nibble.b16) {} Q_CORE_EXPORT static const quint32 mantissatable[]; Q_CORE_EXPORT static const quint32 exponenttable[]; @@ -263,4 +283,55 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(qfloat16) +namespace std { +template<> +class numeric_limits : public numeric_limits +{ +public: + /* + Treat quint16 b16 as if it were: + uint S: 1; // b16 >> 15 (sign) + uint E: 5; // (b16 >> 10) & 0x1f (offset exponent) + uint M: 10; // b16 & 0x3ff (adjusted mantissa) + + for E == 0: magnitude is M / 2.^{24} + for 0 < E < 31: magnitude is (1. + M / 2.^{10}) * 2.^{E - 15) + for E == 31: not finite + */ + static constexpr int digits = 11; + static constexpr int min_exponent = -13; + static constexpr int max_exponent = 16; + + static constexpr int digits10 = 3; + static constexpr int max_digits10 = 5; + static constexpr int min_exponent10 = -4; + static constexpr int max_exponent10 = 4; + + static constexpr QT_PREPEND_NAMESPACE(qfloat16) epsilon() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_epsilon(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) (min)() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_min(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) denorm_min() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_denorm_min(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) (max)() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_max(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) lowest() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_lowest(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) infinity() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_infinity(); } + static constexpr QT_PREPEND_NAMESPACE(qfloat16) quiet_NaN() + { return QT_PREPEND_NAMESPACE(qfloat16)::_limit_quiet_NaN(); } +}; + +template<> class numeric_limits + : public numeric_limits {}; +template<> class numeric_limits + : public numeric_limits {}; +template<> class numeric_limits + : public numeric_limits {}; + +// Adding overloads to std isn't allowed, so we can't extend this to support +// for fpclassify(), isnormal() &c. (which, furthermore, are macros on MinGW). +} // namespace std + #endif // QFLOAT16_H diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 288446878c..d469735ae9 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -766,8 +766,8 @@ static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::E if (qt_is_nan(d)) { if (opt & QCborValue::UseFloat16) { if ((opt & QCborValue::UseFloat16) == QCborValue::UseFloat16) - return writer.append(qfloat16(qt_qnan())); - return writer.append(float(qt_qnan())); + return writer.append(std::numeric_limits::quiet_NaN()); + return writer.append(std::numeric_limits::quiet_NaN()); } return writer.append(qt_qnan()); } diff --git a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp index 241dccb90e..b5a77a1de6 100644 --- a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp +++ b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 by Southwest Research Institute (R) ** Contact: https://www.qt.io/licensing/ ** @@ -48,6 +49,7 @@ private slots: void arithOps(); void floatToFloat16(); void floatFromFloat16(); + void limits(); }; void tst_qfloat16::fuzzyCompare_data() @@ -345,5 +347,145 @@ void tst_qfloat16::floatFromFloat16() QCOMPARE(out[i], expected[i]); } +static qfloat16 powf16(qfloat16 base, int raise) +{ + const qfloat16 one(1.f); + if (raise < 0) { + raise = -raise; + base = one / base; + } + qfloat16 answer = (raise & 1) ? base : one; + while (raise > 0) { + raise >>= 1; + base *= base; + if (raise & 1) + answer *= base; + } + return answer; +} + +void tst_qfloat16::limits() +{ + // *NOT* using QCOMPARE() on finite qfloat16 values, since that uses fuzzy + // comparison, and we need exact here. + using Bounds = std::numeric_limits; + QVERIFY(Bounds::is_specialized); + QVERIFY(Bounds::is_signed); + QVERIFY(!Bounds::is_integer); + QVERIFY(!Bounds::is_exact); + QVERIFY(Bounds::is_iec559); + QVERIFY(Bounds::is_bounded); + QVERIFY(!Bounds::is_modulo); + QVERIFY(!Bounds::traps); + QVERIFY(Bounds::has_infinity); + QVERIFY(Bounds::has_quiet_NaN); + QVERIFY(Bounds::has_signaling_NaN); + QCOMPARE(Bounds::has_denorm, std::denorm_present); + QCOMPARE(Bounds::round_style, std::round_to_nearest); + QCOMPARE(Bounds::radix, 2); + // Untested: has_denorm_loss + + // A few common values: + const qfloat16 zero(0), one(1), ten(10); + QVERIFY(qIsFinite(zero)); + QVERIFY(!qIsInf(zero)); + QVERIFY(!qIsNaN(zero)); + QVERIFY(qIsFinite(one)); + QVERIFY(!qIsInf(one)); + QVERIFY(!qIsNaN(one)); + QVERIFY(qIsFinite(ten)); + QVERIFY(!qIsInf(ten)); + QVERIFY(!qIsNaN(ten)); + + // digits in the mantissa, including the implicit 1 before the binary dot at its left: + QVERIFY(qfloat16(1 << (Bounds::digits - 1)) + one > qfloat16(1 << (Bounds::digits - 1))); + QVERIFY(qfloat16(1 << Bounds::digits) + one == qfloat16(1 << Bounds::digits)); + + // There is a wilful of-by-one in how m(ax|in)_exponent are defined; they're + // the lowest and highest n for which radix^{n-1} are normal and finite. + const qfloat16 two(Bounds::radix); + qfloat16 bit = powf16(two, Bounds::max_exponent - 1); + QVERIFY(qIsFinite(bit)); + QVERIFY(qIsInf(bit * two)); + bit = powf16(two, Bounds::min_exponent - 1); + QVERIFY(bit.isNormal()); + QVERIFY(!(bit / two).isNormal()); + QVERIFY(bit / two > zero); + + // Base ten (with no matching off-by-one idiocy): + // the lowest negative number n such that 10^n is a valid normalized value + qfloat16 low10(powf16(ten, Bounds::min_exponent10)); + QVERIFY(low10 > zero); + QVERIFY(low10.isNormal()); + low10 /= ten; + QVERIFY(low10 == zero || !low10.isNormal()); + // the largest positive number n such that 10^n is a representable finite value + qfloat16 high10(powf16(ten, Bounds::max_exponent10)); + QVERIFY(high10 > zero); + QVERIFY(qIsFinite(high10)); + QVERIFY(!qIsFinite(high10 * ten)); + + // How many digits are significant ? (Casts avoid linker errors ...) + QCOMPARE(int(Bounds::digits10), 3); // 9.79e-4 has enough sigificant digits: + qfloat16 below(9.785e-4f), above(9.794e-4f); +#if 0 // Sadly, the QEMU x-compile for arm64 "optimises" comparisons: + const bool overOptimised = false; +#else + const bool overOptimised = (below != above); + if (overOptimised) + QEXPECT_FAIL("", "Over-optimised on QEMU", Continue); +#endif // (but it did, so should, pass everywhere else, confirming digits10 is indeed 3). + QVERIFY(below == above); + QCOMPARE(int(Bounds::max_digits10), 5); // we need 5 to distinguish these two: + QVERIFY(qfloat16(1000.5f) != qfloat16(1001.4f)); + + // Actual limiting values of the type: + const qfloat16 rose(one + Bounds::epsilon()); + QVERIFY(rose > one); + if (overOptimised) + QEXPECT_FAIL("", "Over-optimised on QEMU", Continue); + QVERIFY(one + Bounds::epsilon() / rose == one); + QVERIFY(qIsInf(Bounds::infinity())); + QVERIFY(!qIsNaN(Bounds::infinity())); + QVERIFY(!qIsFinite(Bounds::infinity())); + // QCOMPARE(Bounds::infinity(), Bounds::infinity()); + QVERIFY(Bounds::infinity() > -Bounds::infinity()); + QVERIFY(Bounds::infinity() > zero); + QVERIFY(qIsInf(-Bounds::infinity())); + QVERIFY(!qIsNaN(-Bounds::infinity())); + QVERIFY(!qIsFinite(-Bounds::infinity())); + // QCOMPARE(-Bounds::infinity(), -Bounds::infinity()); + QVERIFY(-Bounds::infinity() < zero); + QVERIFY(qIsNaN(Bounds::quiet_NaN())); + QVERIFY(!qIsInf(Bounds::quiet_NaN())); + QVERIFY(!qIsFinite(Bounds::quiet_NaN())); + QVERIFY(!(Bounds::quiet_NaN() == Bounds::quiet_NaN())); + // QCOMPARE(Bounds::quiet_NaN(), Bounds::quiet_NaN()); + QVERIFY(Bounds::max() > zero); + QVERIFY(qIsFinite(Bounds::max())); + QVERIFY(!qIsInf(Bounds::max())); + QVERIFY(!qIsNaN(Bounds::max())); + QVERIFY(qIsInf(Bounds::max() * rose)); + QVERIFY(Bounds::lowest() < zero); + QVERIFY(qIsFinite(Bounds::lowest())); + QVERIFY(!qIsInf(Bounds::lowest())); + QVERIFY(!qIsNaN(Bounds::lowest())); + QVERIFY(qIsInf(Bounds::lowest() * rose)); + QVERIFY(Bounds::min() > zero); + QVERIFY(Bounds::min().isNormal()); + QVERIFY(!(Bounds::min() / rose).isNormal()); + QVERIFY(qIsFinite(Bounds::min())); + QVERIFY(!qIsInf(Bounds::min())); + QVERIFY(!qIsNaN(Bounds::min())); + QVERIFY(Bounds::denorm_min() > zero); + QVERIFY(!Bounds::denorm_min().isNormal()); + QVERIFY(qIsFinite(Bounds::denorm_min())); + QVERIFY(!qIsInf(Bounds::denorm_min())); + QVERIFY(!qIsNaN(Bounds::denorm_min())); + if (overOptimised) + QEXPECT_FAIL("", "Over-optimised on QEMU", Continue); + QCOMPARE(Bounds::denorm_min() / rose, zero); +} + QTEST_APPLESS_MAIN(tst_qfloat16) #include "tst_qfloat16.moc" From 934000c11afe8b03c81a8f52f3a51be6615087c6 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 22 Mar 2019 16:03:59 +0100 Subject: [PATCH 011/122] Implement qFpClassify(qfloat16) This extends support for qfloat16 sufficiently for the things testlib needs in order to treat it as a first-class citizen. Extended tests for qfloat to check qFpClassify() on it. Change-Id: I906292afaf51cd9c94ba384ff5aaa855edd56da1 Reviewed-by: Thiago Macieira --- src/corelib/global/qfloat16.cpp | 13 +++++++++++++ src/corelib/global/qfloat16.h | 2 ++ .../corelib/global/qfloat16/tst_qfloat16.cpp | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp index 680268c59b..2bf6ff00c2 100644 --- a/src/corelib/global/qfloat16.cpp +++ b/src/corelib/global/qfloat16.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 by Southwest Research Institute (R) ** Contact: http://www.qt-project.org/legal ** @@ -39,6 +40,7 @@ #include "qfloat16.h" #include "private/qsimd_p.h" +#include // for fpclassify()'s return values QT_BEGIN_NAMESPACE @@ -91,6 +93,17 @@ QT_BEGIN_NAMESPACE \sa qIsFinite */ +/*! + \internal + Implements qFpClassify() for qfloat16. + */ + +int qfloat16::fpClassify() const noexcept +{ + return isInf() ? FP_INFINITE : isNaN() ? FP_NAN + : !b16 ? FP_ZERO : isNormal() ? FP_NORMAL : FP_SUBNORMAL; +} + /*! \fn int qRound(qfloat16 value) \relates diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 4c3f9ca063..6f798f8b8f 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -83,6 +83,7 @@ public: bool isInf() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7c; } bool isNaN() const noexcept { return ((b16 >> 8) & 0x7e) == 0x7e; } bool isFinite() const noexcept { return ((b16 >> 8) & 0x7c) != 0x7c; } + Q_CORE_EXPORT int fpClassify() const noexcept; // Support for std::numeric_limits static constexpr qfloat16 _limit_epsilon() noexcept { return qfloat16(Wrap(0x1400)); } static constexpr qfloat16 _limit_min() noexcept { return qfloat16(Wrap(0x400)); } @@ -117,6 +118,7 @@ Q_CORE_EXPORT void qFloatFromFloat16(float *, const qfloat16 *, qsizetype length Q_REQUIRED_RESULT inline bool qIsInf(qfloat16 f) noexcept { return f.isInf(); } Q_REQUIRED_RESULT inline bool qIsNaN(qfloat16 f) noexcept { return f.isNaN(); } Q_REQUIRED_RESULT inline bool qIsFinite(qfloat16 f) noexcept { return f.isFinite(); } +Q_REQUIRED_RESULT inline int qFpClassify(qfloat16 f) noexcept { return f.fpClassify(); } // Q_REQUIRED_RESULT quint32 qFloatDistance(qfloat16 a, qfloat16 b); // The remainder of these utility functions complement qglobal.h diff --git a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp index b5a77a1de6..b82751cfb5 100644 --- a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp +++ b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp @@ -390,12 +390,15 @@ void tst_qfloat16::limits() QVERIFY(qIsFinite(zero)); QVERIFY(!qIsInf(zero)); QVERIFY(!qIsNaN(zero)); + QCOMPARE(qFpClassify(zero), FP_ZERO); QVERIFY(qIsFinite(one)); QVERIFY(!qIsInf(one)); + QCOMPARE(qFpClassify(one), FP_NORMAL); QVERIFY(!qIsNaN(one)); QVERIFY(qIsFinite(ten)); QVERIFY(!qIsInf(ten)); QVERIFY(!qIsNaN(ten)); + QCOMPARE(qFpClassify(ten), FP_NORMAL); // digits in the mantissa, including the implicit 1 before the binary dot at its left: QVERIFY(qfloat16(1 << (Bounds::digits - 1)) + one > qfloat16(1 << (Bounds::digits - 1))); @@ -409,7 +412,9 @@ void tst_qfloat16::limits() QVERIFY(qIsInf(bit * two)); bit = powf16(two, Bounds::min_exponent - 1); QVERIFY(bit.isNormal()); + QCOMPARE(qFpClassify(bit), FP_NORMAL); QVERIFY(!(bit / two).isNormal()); + QCOMPARE(qFpClassify(bit / two), FP_SUBNORMAL); QVERIFY(bit / two > zero); // Base ten (with no matching off-by-one idiocy): @@ -424,6 +429,7 @@ void tst_qfloat16::limits() QVERIFY(high10 > zero); QVERIFY(qIsFinite(high10)); QVERIFY(!qIsFinite(high10 * ten)); + QCOMPARE(qFpClassify(high10), FP_NORMAL); // How many digits are significant ? (Casts avoid linker errors ...) QCOMPARE(int(Bounds::digits10), 3); // 9.79e-4 has enough sigificant digits: @@ -449,34 +455,46 @@ void tst_qfloat16::limits() QVERIFY(!qIsNaN(Bounds::infinity())); QVERIFY(!qIsFinite(Bounds::infinity())); // QCOMPARE(Bounds::infinity(), Bounds::infinity()); + QCOMPARE(qFpClassify(Bounds::infinity()), FP_INFINITE); + QVERIFY(Bounds::infinity() > -Bounds::infinity()); QVERIFY(Bounds::infinity() > zero); QVERIFY(qIsInf(-Bounds::infinity())); QVERIFY(!qIsNaN(-Bounds::infinity())); QVERIFY(!qIsFinite(-Bounds::infinity())); // QCOMPARE(-Bounds::infinity(), -Bounds::infinity()); + QCOMPARE(qFpClassify(-Bounds::infinity()), FP_INFINITE); + QVERIFY(-Bounds::infinity() < zero); QVERIFY(qIsNaN(Bounds::quiet_NaN())); QVERIFY(!qIsInf(Bounds::quiet_NaN())); QVERIFY(!qIsFinite(Bounds::quiet_NaN())); QVERIFY(!(Bounds::quiet_NaN() == Bounds::quiet_NaN())); // QCOMPARE(Bounds::quiet_NaN(), Bounds::quiet_NaN()); + QCOMPARE(qFpClassify(Bounds::quiet_NaN()), FP_NAN); + QVERIFY(Bounds::max() > zero); QVERIFY(qIsFinite(Bounds::max())); QVERIFY(!qIsInf(Bounds::max())); QVERIFY(!qIsNaN(Bounds::max())); QVERIFY(qIsInf(Bounds::max() * rose)); + QCOMPARE(qFpClassify(Bounds::max()), FP_NORMAL); + QVERIFY(Bounds::lowest() < zero); QVERIFY(qIsFinite(Bounds::lowest())); QVERIFY(!qIsInf(Bounds::lowest())); QVERIFY(!qIsNaN(Bounds::lowest())); QVERIFY(qIsInf(Bounds::lowest() * rose)); + QCOMPARE(qFpClassify(Bounds::lowest()), FP_NORMAL); + QVERIFY(Bounds::min() > zero); QVERIFY(Bounds::min().isNormal()); QVERIFY(!(Bounds::min() / rose).isNormal()); QVERIFY(qIsFinite(Bounds::min())); QVERIFY(!qIsInf(Bounds::min())); QVERIFY(!qIsNaN(Bounds::min())); + QCOMPARE(qFpClassify(Bounds::min()), FP_NORMAL); + QVERIFY(Bounds::denorm_min() > zero); QVERIFY(!Bounds::denorm_min().isNormal()); QVERIFY(qIsFinite(Bounds::denorm_min())); @@ -485,6 +503,7 @@ void tst_qfloat16::limits() if (overOptimised) QEXPECT_FAIL("", "Over-optimised on QEMU", Continue); QCOMPARE(Bounds::denorm_min() / rose, zero); + QCOMPARE(qFpClassify(Bounds::denorm_min()), FP_SUBNORMAL); } QTEST_APPLESS_MAIN(tst_qfloat16) From 3abfa4dfff08d9d2ab9aeb474656b36076a48b3b Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 21 Nov 2018 14:36:08 +0100 Subject: [PATCH 012/122] QtTestLib: handle float16 the same as double and float In QCOMPARE, handle NaNs and infinities the way tests want them handled, rather than by strict IEEE rules. In particular, if a test expects NaN, this lets it treat that just like any other expected value, despite NaN != NaN as float16 values. Likewise, format infinities and NaNs specially in toString() so that they're reported consistently. Enable the qfloat16 tests that depend on this QCOMPARE() behavior. Refise the testlib selftest's float test to test qfloat16 the same way it tests float and double (and format the test the same way). This is a follow-up to 37f617c405a. Change-Id: I433256a09b1657e6725d68d07c5f80d805bf586a Reviewed-by: Thiago Macieira --- src/testlib/qtestcase.cpp | 11 +- .../corelib/global/qfloat16/tst_qfloat16.cpp | 6 +- .../testlib/selftests/expected_float.lightxml | 191 ++++++++- .../auto/testlib/selftests/expected_float.tap | 377 +++++++++++++++++- .../testlib/selftests/expected_float.teamcity | 102 ++++- .../auto/testlib/selftests/expected_float.txt | 123 +++++- .../auto/testlib/selftests/expected_float.xml | 191 ++++++++- .../testlib/selftests/expected_float.xunitxml | 86 +++- .../testlib/selftests/float/tst_float.cpp | 30 +- 9 files changed, 1054 insertions(+), 63 deletions(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index db44b3860a..cad29b5326 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -2539,7 +2539,8 @@ static bool floatingCompare(const T &t1, const T &t2) bool QTest::qCompare(qfloat16 const &t1, qfloat16 const &t2, const char *actual, const char *expected, const char *file, int line) { - return compare_helper(qFuzzyCompare(t1, t2), "Compared qfloat16s are not the same (fuzzy compare)", + return compare_helper(floatingCompare(t1, t2), + "Compared qfloat16s are not the same (fuzzy compare)", toString(t1), toString(t2), actual, expected, file, line); } @@ -2646,16 +2647,10 @@ template <> Q_TESTLIB_EXPORT char *QTest::toString(const TYPE &t) \ return msg; \ } +TO_STRING_FLOAT(qfloat16, %.3g) TO_STRING_FLOAT(float, %g) TO_STRING_FLOAT(double, %.12g) -template <> Q_TESTLIB_EXPORT char *QTest::toString(const qfloat16 &t) -{ - char *msg = new char[16]; - qsnprintf(msg, 16, "%.3g", static_cast(t)); - return msg; -} - template <> Q_TESTLIB_EXPORT char *QTest::toString(const char &t) { unsigned char c = static_cast(t); diff --git a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp index b82751cfb5..6894fd4cc3 100644 --- a/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp +++ b/tests/auto/corelib/global/qfloat16/tst_qfloat16.cpp @@ -454,7 +454,7 @@ void tst_qfloat16::limits() QVERIFY(qIsInf(Bounds::infinity())); QVERIFY(!qIsNaN(Bounds::infinity())); QVERIFY(!qIsFinite(Bounds::infinity())); - // QCOMPARE(Bounds::infinity(), Bounds::infinity()); + QCOMPARE(Bounds::infinity(), Bounds::infinity()); QCOMPARE(qFpClassify(Bounds::infinity()), FP_INFINITE); QVERIFY(Bounds::infinity() > -Bounds::infinity()); @@ -462,7 +462,7 @@ void tst_qfloat16::limits() QVERIFY(qIsInf(-Bounds::infinity())); QVERIFY(!qIsNaN(-Bounds::infinity())); QVERIFY(!qIsFinite(-Bounds::infinity())); - // QCOMPARE(-Bounds::infinity(), -Bounds::infinity()); + QCOMPARE(-Bounds::infinity(), -Bounds::infinity()); QCOMPARE(qFpClassify(-Bounds::infinity()), FP_INFINITE); QVERIFY(-Bounds::infinity() < zero); @@ -470,7 +470,7 @@ void tst_qfloat16::limits() QVERIFY(!qIsInf(Bounds::quiet_NaN())); QVERIFY(!qIsFinite(Bounds::quiet_NaN())); QVERIFY(!(Bounds::quiet_NaN() == Bounds::quiet_NaN())); - // QCOMPARE(Bounds::quiet_NaN(), Bounds::quiet_NaN()); + QCOMPARE(Bounds::quiet_NaN(), Bounds::quiet_NaN()); QCOMPARE(qFpClassify(Bounds::quiet_NaN()), FP_NAN); QVERIFY(Bounds::max() > zero); diff --git a/tests/auto/testlib/selftests/expected_float.lightxml b/tests/auto/testlib/selftests/expected_float.lightxml index 54d6eabdbd..5f5114bb2e 100644 --- a/tests/auto/testlib/selftests/expected_float.lightxml +++ b/tests/auto/testlib/selftests/expected_float.lightxml @@ -428,21 +428,24 @@ - - - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/testlib/selftests/expected_float.tap b/tests/auto/testlib/selftests/expected_float.tap index 4a3b3906c2..9da51b93b3 100644 --- a/tests/auto/testlib/selftests/expected_float.tap +++ b/tests/auto/testlib/selftests/expected_float.tap @@ -759,8 +759,7 @@ not ok 77 - floatComparisons(should FAIL: -max != -inf) file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp line: 137 ... -ok 78 - float16Comparisons(should SUCCEED 1) -not ok 79 - float16Comparisons(should FAIL 1) +not ok 78 - float16Comparisons(should FAIL 1) --- type: QCOMPARE message: Compared qfloat16s are not the same (fuzzy compare) @@ -772,6 +771,7 @@ not ok 79 - float16Comparisons(should FAIL 1) file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp line: 171 ... +ok 79 - float16Comparisons(should PASS 1) not ok 80 - float16Comparisons(should FAIL 2) --- type: QCOMPARE @@ -784,7 +784,8 @@ not ok 80 - float16Comparisons(should FAIL 2) file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp line: 171 ... -not ok 81 - float16Comparisons(should FAIL 3) +ok 81 - float16Comparisons(should PASS 2) +not ok 82 - float16Comparisons(should FAIL 3) --- type: QCOMPARE message: Compared qfloat16s are not the same (fuzzy compare) @@ -796,8 +797,348 @@ not ok 81 - float16Comparisons(should FAIL 3) file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp line: 171 ... -ok 82 - float16Comparisons(should SUCCEED 2) -not ok 83 - compareFloatTests(1e0) +ok 83 - float16Comparisons(should PASS 3) +not ok 84 - float16Comparisons(should FAIL 4) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: 5.87e-05 (operandRight) + found: 5.93e-05 (operandLeft) + expected: 5.87e-05 (operandRight) + actual: 5.93e-05 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +ok 85 - float16Comparisons(should PASS 4) +not ok 86 - float16Comparisons(should FAIL 5) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: 5.88e+04 (operandRight) + found: 5.94e+04 (operandLeft) + expected: 5.88e+04 (operandRight) + actual: 5.94e+04 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +ok 87 - float16Comparisons(should PASS: NaN == NaN) +not ok 88 - float16Comparisons(should FAIL: NaN != 0) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: 0 (operandRight) + found: nan (operandLeft) + expected: 0 (operandRight) + actual: nan (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 89 - float16Comparisons(should FAIL: 0 != NaN) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: nan (operandRight) + found: 0 (operandLeft) + expected: nan (operandRight) + actual: 0 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 90 - float16Comparisons(should FAIL: NaN != 1) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: 1 (operandRight) + found: nan (operandLeft) + expected: 1 (operandRight) + actual: nan (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 91 - float16Comparisons(should FAIL: 1 != NaN) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: nan (operandRight) + found: 1 (operandLeft) + expected: nan (operandRight) + actual: 1 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +ok 92 - float16Comparisons(should PASS: inf == inf) +ok 93 - float16Comparisons(should PASS: -inf == -inf) +not ok 94 - float16Comparisons(should FAIL: inf != -inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: -inf (operandRight) + found: inf (operandLeft) + expected: -inf (operandRight) + actual: inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 95 - float16Comparisons(should FAIL: -inf != inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: inf (operandRight) + found: -inf (operandLeft) + expected: inf (operandRight) + actual: -inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 96 - float16Comparisons(should FAIL: inf != nan) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: nan (operandRight) + found: inf (operandLeft) + expected: nan (operandRight) + actual: inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 97 - float16Comparisons(should FAIL: nan != inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: inf (operandRight) + found: nan (operandLeft) + expected: inf (operandRight) + actual: nan (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 98 - float16Comparisons(should FAIL: -inf != nan) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: nan (operandRight) + found: -inf (operandLeft) + expected: nan (operandRight) + actual: -inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 99 - float16Comparisons(should FAIL: nan != -inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: -inf (operandRight) + found: nan (operandLeft) + expected: -inf (operandRight) + actual: nan (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 100 - float16Comparisons(should FAIL: inf != 0) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: 0 (operandRight) + found: inf (operandLeft) + expected: 0 (operandRight) + actual: inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 101 - float16Comparisons(should FAIL: 0 != inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: inf (operandRight) + found: 0 (operandLeft) + expected: inf (operandRight) + actual: 0 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 102 - float16Comparisons(should FAIL: -inf != 0) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: 0 (operandRight) + found: -inf (operandLeft) + expected: 0 (operandRight) + actual: -inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 103 - float16Comparisons(should FAIL: 0 != -inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: -inf (operandRight) + found: 0 (operandLeft) + expected: -inf (operandRight) + actual: 0 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 104 - float16Comparisons(should FAIL: inf != 1) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: 1 (operandRight) + found: inf (operandLeft) + expected: 1 (operandRight) + actual: inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 105 - float16Comparisons(should FAIL: 1 != inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: inf (operandRight) + found: 1 (operandLeft) + expected: inf (operandRight) + actual: 1 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 106 - float16Comparisons(should FAIL: -inf != 1) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: 1 (operandRight) + found: -inf (operandLeft) + expected: 1 (operandRight) + actual: -inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 107 - float16Comparisons(should FAIL: 1 != -inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: -inf (operandRight) + found: 1 (operandLeft) + expected: -inf (operandRight) + actual: 1 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 108 - float16Comparisons(should FAIL: inf != max) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: 6.55e+04 (operandRight) + found: inf (operandLeft) + expected: 6.55e+04 (operandRight) + actual: inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 109 - float16Comparisons(should FAIL: inf != -max) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: -6.55e+04 (operandRight) + found: inf (operandLeft) + expected: -6.55e+04 (operandRight) + actual: inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 110 - float16Comparisons(should FAIL: max != inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: inf (operandRight) + found: 6.55e+04 (operandLeft) + expected: inf (operandRight) + actual: 6.55e+04 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 111 - float16Comparisons(should FAIL: -max != inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: inf (operandRight) + found: -6.55e+04 (operandLeft) + expected: inf (operandRight) + actual: -6.55e+04 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 112 - float16Comparisons(should FAIL: -inf != max) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: 6.55e+04 (operandRight) + found: -inf (operandLeft) + expected: 6.55e+04 (operandRight) + actual: -inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 113 - float16Comparisons(should FAIL: -inf != -max) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: -6.55e+04 (operandRight) + found: -inf (operandLeft) + expected: -6.55e+04 (operandRight) + actual: -inf (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 114 - float16Comparisons(should FAIL: max != -inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: -inf (operandRight) + found: 6.55e+04 (operandLeft) + expected: -inf (operandRight) + actual: 6.55e+04 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 115 - float16Comparisons(should FAIL: -max != -inf) + --- + type: QCOMPARE + message: Compared qfloat16s are not the same (fuzzy compare) + wanted: -inf (operandRight) + found: -6.55e+04 (operandLeft) + expected: -inf (operandRight) + actual: -6.55e+04 (operandLeft) + at: tst_float::float16Comparisons() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:171) + file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp + line: 171 + ... +not ok 116 - compareFloatTests(1e0) --- type: QCOMPARE message: Compared floats are not the same (fuzzy compare) @@ -805,11 +1146,11 @@ not ok 83 - compareFloatTests(1e0) found: 1 (t1) expected: 3 (t3) actual: 1 (t1) - at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:216) + at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:210) file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp - line: 216 + line: 210 ... -not ok 84 - compareFloatTests(1e-7) +not ok 117 - compareFloatTests(1e-7) --- type: QCOMPARE message: Compared floats are not the same (fuzzy compare) @@ -817,11 +1158,11 @@ not ok 84 - compareFloatTests(1e-7) found: 1e-07 (t1) expected: 3e-07 (t3) actual: 1e-07 (t1) - at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:216) + at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:210) file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp - line: 216 + line: 210 ... -not ok 85 - compareFloatTests(1e+7) +not ok 118 - compareFloatTests(1e+7) --- type: QCOMPARE message: Compared floats are not the same (fuzzy compare) @@ -829,12 +1170,12 @@ not ok 85 - compareFloatTests(1e+7) found: 1e+07 (t1) expected: 3e+07 (t3) actual: 1e+07 (t1) - at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:216) + at: tst_float::compareFloatTests() (qtbase/tests/auto/testlib/selftests/float/tst_float.cpp:210) file: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp - line: 216 + line: 210 ... -ok 86 - cleanupTestCase() -1..86 -# tests 86 -# pass 18 -# fail 68 +ok 119 - cleanupTestCase() +1..119 +# tests 119 +# pass 23 +# fail 96 diff --git a/tests/auto/testlib/selftests/expected_float.teamcity b/tests/auto/testlib/selftests/expected_float.teamcity index eb99d3f6ea..af81296c42 100644 --- a/tests/auto/testlib/selftests/expected_float.teamcity +++ b/tests/auto/testlib/selftests/expected_float.teamcity @@ -215,19 +215,113 @@ ##teamcity[testStarted name='floatComparisons(should FAIL: -max != -inf)' flowId='tst_float'] ##teamcity[testFailed name='floatComparisons(should FAIL: -max != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared floats are not the same (fuzzy compare)|n Actual (operandLeft) : -3.40282e+38|n Expected (operandRight): -inf' flowId='tst_float'] ##teamcity[testFinished name='floatComparisons(should FAIL: -max != -inf)' flowId='tst_float'] -##teamcity[testStarted name='float16Comparisons(should SUCCEED 1)' flowId='tst_float'] -##teamcity[testFinished name='float16Comparisons(should SUCCEED 1)' flowId='tst_float'] ##teamcity[testStarted name='float16Comparisons(should FAIL 1)' flowId='tst_float'] ##teamcity[testFailed name='float16Comparisons(should FAIL 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): 3' flowId='tst_float'] ##teamcity[testFinished name='float16Comparisons(should FAIL 1)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should PASS 1)' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should PASS 1)' flowId='tst_float'] ##teamcity[testStarted name='float16Comparisons(should FAIL 2)' flowId='tst_float'] ##teamcity[testFailed name='float16Comparisons(should FAIL 2)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0.0001|n Expected (operandRight): 0.0003' flowId='tst_float'] ##teamcity[testFinished name='float16Comparisons(should FAIL 2)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should PASS 2)' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should PASS 2)' flowId='tst_float'] ##teamcity[testStarted name='float16Comparisons(should FAIL 3)' flowId='tst_float'] ##teamcity[testFailed name='float16Comparisons(should FAIL 3)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 98|n Expected (operandRight): 99' flowId='tst_float'] ##teamcity[testFinished name='float16Comparisons(should FAIL 3)' flowId='tst_float'] -##teamcity[testStarted name='float16Comparisons(should SUCCEED 2)' flowId='tst_float'] -##teamcity[testFinished name='float16Comparisons(should SUCCEED 2)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should PASS 3)' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should PASS 3)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL 4)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL 4)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 5.93e-05|n Expected (operandRight): 5.87e-05' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL 4)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should PASS 4)' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should PASS 4)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL 5)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL 5)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 5.94e+04|n Expected (operandRight): 5.88e+04' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL 5)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should PASS: NaN == NaN)' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should PASS: NaN == NaN)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: NaN != 0)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: NaN != 0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): 0' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: NaN != 0)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: 0 != NaN)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: 0 != NaN)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0|n Expected (operandRight): nan' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: 0 != NaN)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: NaN != 1)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: NaN != 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): 1' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: NaN != 1)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: 1 != NaN)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: 1 != NaN)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): nan' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: 1 != NaN)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should PASS: inf == inf)' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should PASS: inf == inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should PASS: -inf == -inf)' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should PASS: -inf == -inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: inf != -inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: inf != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): -inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: inf != -inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: inf != nan)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: inf != nan)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): nan' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: inf != nan)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: nan != inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: nan != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: nan != inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != nan)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != nan)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): nan' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != nan)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: nan != -inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: nan != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : nan|n Expected (operandRight): -inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: nan != -inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: inf != 0)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: inf != 0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): 0' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: inf != 0)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: 0 != inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: 0 != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0|n Expected (operandRight): inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: 0 != inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != 0)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != 0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): 0' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != 0)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: 0 != -inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: 0 != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 0|n Expected (operandRight): -inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: 0 != -inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: inf != 1)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: inf != 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): 1' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: inf != 1)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: 1 != inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: 1 != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: 1 != inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != 1)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != 1)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): 1' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != 1)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: 1 != -inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: 1 != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 1|n Expected (operandRight): -inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: 1 != -inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: inf != max)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: inf != max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): 6.55e+04' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: inf != max)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: inf != -max)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: inf != -max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : inf|n Expected (operandRight): -6.55e+04' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: inf != -max)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: max != inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: max != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 6.55e+04|n Expected (operandRight): inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: max != inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: -max != inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: -max != inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -6.55e+04|n Expected (operandRight): inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: -max != inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != max)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): 6.55e+04' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != max)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: -inf != -max)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: -inf != -max)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -inf|n Expected (operandRight): -6.55e+04' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: -inf != -max)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: max != -inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: max != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : 6.55e+04|n Expected (operandRight): -inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: max != -inf)' flowId='tst_float'] +##teamcity[testStarted name='float16Comparisons(should FAIL: -max != -inf)' flowId='tst_float'] +##teamcity[testFailed name='float16Comparisons(should FAIL: -max != -inf)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared qfloat16s are not the same (fuzzy compare)|n Actual (operandLeft) : -6.55e+04|n Expected (operandRight): -inf' flowId='tst_float'] +##teamcity[testFinished name='float16Comparisons(should FAIL: -max != -inf)' flowId='tst_float'] ##teamcity[testStarted name='compareFloatTests(1e0)' flowId='tst_float'] ##teamcity[testFailed name='compareFloatTests(1e0)' message='Failure! |[Loc: qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)|]' details='Compared floats are not the same (fuzzy compare)|n Actual (t1): 1|n Expected (t3): 3' flowId='tst_float'] ##teamcity[testFinished name='compareFloatTests(1e0)' flowId='tst_float'] diff --git a/tests/auto/testlib/selftests/expected_float.txt b/tests/auto/testlib/selftests/expected_float.txt index 18a5bab628..d22a52a63d 100644 --- a/tests/auto/testlib/selftests/expected_float.txt +++ b/tests/auto/testlib/selftests/expected_float.txt @@ -263,20 +263,137 @@ FAIL! : tst_float::floatComparisons(should FAIL: -max != -inf) Compared floats Actual (operandLeft) : -3.40282e+38 Expected (operandRight): -inf Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] -PASS : tst_float::float16Comparisons(should SUCCEED 1) FAIL! : tst_float::float16Comparisons(should FAIL 1) Compared qfloat16s are not the same (fuzzy compare) Actual (operandLeft) : 1 Expected (operandRight): 3 Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +PASS : tst_float::float16Comparisons(should PASS 1) FAIL! : tst_float::float16Comparisons(should FAIL 2) Compared qfloat16s are not the same (fuzzy compare) Actual (operandLeft) : 0.0001 Expected (operandRight): 0.0003 Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +PASS : tst_float::float16Comparisons(should PASS 2) FAIL! : tst_float::float16Comparisons(should FAIL 3) Compared qfloat16s are not the same (fuzzy compare) Actual (operandLeft) : 98 Expected (operandRight): 99 Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] -PASS : tst_float::float16Comparisons(should SUCCEED 2) +PASS : tst_float::float16Comparisons(should PASS 3) +FAIL! : tst_float::float16Comparisons(should FAIL 4) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : 5.93e-05 + Expected (operandRight): 5.87e-05 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +PASS : tst_float::float16Comparisons(should PASS 4) +FAIL! : tst_float::float16Comparisons(should FAIL 5) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : 5.94e+04 + Expected (operandRight): 5.88e+04 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +PASS : tst_float::float16Comparisons(should PASS: NaN == NaN) +FAIL! : tst_float::float16Comparisons(should FAIL: NaN != 0) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : nan + Expected (operandRight): 0 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: 0 != NaN) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : 0 + Expected (operandRight): nan + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: NaN != 1) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : nan + Expected (operandRight): 1 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: 1 != NaN) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : 1 + Expected (operandRight): nan + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +PASS : tst_float::float16Comparisons(should PASS: inf == inf) +PASS : tst_float::float16Comparisons(should PASS: -inf == -inf) +FAIL! : tst_float::float16Comparisons(should FAIL: inf != -inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : inf + Expected (operandRight): -inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: -inf != inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : -inf + Expected (operandRight): inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: inf != nan) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : inf + Expected (operandRight): nan + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: nan != inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : nan + Expected (operandRight): inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: -inf != nan) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : -inf + Expected (operandRight): nan + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: nan != -inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : nan + Expected (operandRight): -inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: inf != 0) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : inf + Expected (operandRight): 0 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: 0 != inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : 0 + Expected (operandRight): inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: -inf != 0) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : -inf + Expected (operandRight): 0 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: 0 != -inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : 0 + Expected (operandRight): -inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: inf != 1) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : inf + Expected (operandRight): 1 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: 1 != inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : 1 + Expected (operandRight): inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: -inf != 1) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : -inf + Expected (operandRight): 1 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: 1 != -inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : 1 + Expected (operandRight): -inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: inf != max) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : inf + Expected (operandRight): 6.55e+04 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: inf != -max) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : inf + Expected (operandRight): -6.55e+04 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: max != inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : 6.55e+04 + Expected (operandRight): inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: -max != inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : -6.55e+04 + Expected (operandRight): inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: -inf != max) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : -inf + Expected (operandRight): 6.55e+04 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: -inf != -max) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : -inf + Expected (operandRight): -6.55e+04 + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: max != -inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : 6.55e+04 + Expected (operandRight): -inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] +FAIL! : tst_float::float16Comparisons(should FAIL: -max != -inf) Compared qfloat16s are not the same (fuzzy compare) + Actual (operandLeft) : -6.55e+04 + Expected (operandRight): -inf + Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] FAIL! : tst_float::compareFloatTests(1e0) Compared floats are not the same (fuzzy compare) Actual (t1): 1 Expected (t3): 3 @@ -290,5 +407,5 @@ FAIL! : tst_float::compareFloatTests(1e+7) Compared floats are not the same (fu Expected (t3): 3e+07 Loc: [qtbase/tests/auto/testlib/selftests/float/tst_float.cpp(0)] PASS : tst_float::cleanupTestCase() -Totals: 18 passed, 68 failed, 0 skipped, 0 blacklisted, 0ms +Totals: 23 passed, 96 failed, 0 skipped, 0 blacklisted, 0ms ********* Finished testing of tst_float ********* diff --git a/tests/auto/testlib/selftests/expected_float.xml b/tests/auto/testlib/selftests/expected_float.xml index b8e1a23616..247bce9577 100644 --- a/tests/auto/testlib/selftests/expected_float.xml +++ b/tests/auto/testlib/selftests/expected_float.xml @@ -430,21 +430,24 @@ - - - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/testlib/selftests/expected_float.xunitxml b/tests/auto/testlib/selftests/expected_float.xunitxml index 9b2af9b616..602f9252a4 100644 --- a/tests/auto/testlib/selftests/expected_float.xunitxml +++ b/tests/auto/testlib/selftests/expected_float.xunitxml @@ -1,5 +1,5 @@ - + @@ -206,6 +206,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + ("operandRight"); + qfloat16 zero(0), one(1); - QTest::newRow("should SUCCEED 1") - << qfloat16(0) - << qfloat16(0); - - QTest::newRow("should FAIL 1") - << qfloat16(1.000) - << qfloat16(3.000); - - QTest::newRow("should FAIL 2") - << qfloat16(1.000e-4f) - << qfloat16(3.000e-4f); + QTest::newRow("should FAIL 1") << one << qfloat16(3); + QTest::newRow("should PASS 1") << zero << zero; + QTest::newRow("should FAIL 2") << qfloat16(1e-4f) << qfloat16(3e-4f); // QCOMPARE for qfloat16s uses qFuzzyCompare() + QTest::newRow("should PASS 2") << qfloat16(1001) << qfloat16(1002); + QTest::newRow("should FAIL 3") << qfloat16(98) << qfloat16(99); + // ... which gets a bit unreliable near to the type's bounds + QTest::newRow("should PASS 3") << qfloat16(6e-5f) + qfloat16(6e-7f) << qfloat16(6e-5f) + qfloat16(11e-7f); + QTest::newRow("should FAIL 4") << qfloat16(6e-5f) - qfloat16(7e-7f) << qfloat16(6e-5f) - qfloat16(13e-7f); + QTest::newRow("should PASS 4") << qfloat16(6e4) + qfloat16(700) << qfloat16(6e4) + qfloat16(1200); + QTest::newRow("should FAIL 5") << qfloat16(6e4) - qfloat16(600) << qfloat16(6e4) - qfloat16(1200); - QTest::newRow("should FAIL 3") - << qfloat16(98) - << qfloat16(99); - - QTest::newRow("should SUCCEED 2") - << qfloat16(1001) - << qfloat16(1002); + nonFinite_data(zero, one); } void tst_float::compareFloatTests() const From 80853afd732aba126caa138ac421b036d2005f8d Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 23 Aug 2018 18:04:07 +0200 Subject: [PATCH 013/122] Add startOfDay() and endOfDay() methods to QDate These methods give the first and last QDateTime values in the given day, for a given time-zone or time-spec. These are usually the relevant midnight, or the millisecond before, except when time-zone transitions (typically DST changes) skip it, when care is needed to select the right moment. Adapted some code to make use of the new API, eliminating some old cruft from qdatetimeparser_p.h in the process. [ChangeLog][QtCore][QDate] Added startOfDay() and endOfDay() methods to provide a QDateTime at the start and end of a given date, taking account of any time skipped by transitions, e.g. a DST spring-forward, which can lead to a day starting at 01:00 or ending just before 23:00. Task-number: QTBUG-64485 Change-Id: I3dd7a34bedfbec8f8af00c43d13f50f99346ecd0 Reviewed-by: Thiago Macieira --- .../code/src_corelib_tools_qdatetime.cpp | 2 +- src/corelib/tools/qdatetime.cpp | 271 +++++++++++++++++- src/corelib/tools/qdatetime.h | 10 +- src/corelib/tools/qdatetimeparser.cpp | 10 +- src/corelib/tools/qdatetimeparser_p.h | 7 +- src/widgets/widgets/qabstractspinbox.cpp | 2 +- src/widgets/widgets/qdatetimeedit.cpp | 19 +- tests/auto/corelib/tools/qdate/qdate.pro | 2 +- tests/auto/corelib/tools/qdate/tst_qdate.cpp | 168 ++++++++++- 9 files changed, 462 insertions(+), 29 deletions(-) diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp index 3ecb67a48f..a477e91548 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qdatetime.cpp @@ -128,7 +128,7 @@ qDebug("Time elapsed: %d ms", t.elapsed()); //! [11] QDateTime now = QDateTime::currentDateTime(); -QDateTime xmas(QDate(now.date().year(), 12, 25), QTime(0, 0)); +QDateTime xmas(QDate(now.date().year(), 12, 25).startOfDay()); qDebug("There are %d seconds to Christmas", now.secsTo(xmas)); //! [11] diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 6fa735dab7..cc98f80feb 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -617,6 +617,268 @@ int QDate::weekNumber(int *yearNumber) const return week; } +static bool inDateTimeRange(qint64 jd, bool start) +{ + using Bounds = std::numeric_limits; + if (jd < Bounds::min() + JULIAN_DAY_FOR_EPOCH) + return false; + jd -= JULIAN_DAY_FOR_EPOCH; + const qint64 maxDay = Bounds::max() / MSECS_PER_DAY; + const qint64 minDay = Bounds::min() / MSECS_PER_DAY - 1; + // (Divisions rounded towards zero, as MSECS_PER_DAY has factors other than two.) + // Range includes start of last day and end of first: + if (start) + return jd > minDay && jd <= maxDay; + return jd >= minDay && jd < maxDay; +} + +static QDateTime toEarliest(const QDate &day, const QDateTime &form) +{ + const Qt::TimeSpec spec = form.timeSpec(); + const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0; +#if QT_CONFIG(timezone) + QTimeZone zone; + if (spec == Qt::TimeZone) + zone = form.timeZone(); +#endif + auto moment = [=](QTime time) { + switch (spec) { + case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset); +#if QT_CONFIG(timezone) + case Qt::TimeZone: return QDateTime(day, time, zone); +#endif + default: return QDateTime(day, time, spec); + } + }; + // Longest routine time-zone transition is 2 hours: + QDateTime when = moment(QTime(2, 0)); + if (!when.isValid()) { + // Noon should be safe ... + when = moment(QTime(12, 0)); + if (!when.isValid()) { + // ... unless it's a 24-hour jump (moving the date-line) + when = moment(QTime(23, 59, 59, 999)); + if (!when.isValid()) + return QDateTime(); + } + } + int high = when.time().msecsSinceStartOfDay() / 60000; + int low = 0; + // Binary chop to the right minute + while (high > low + 1) { + int mid = (high + low) / 2; + QDateTime probe = moment(QTime(mid / 60, mid % 60)); + if (probe.isValid() && probe.date() == day) { + high = mid; + when = probe; + } else { + low = mid; + } + } + return when; +} + +/*! + \since 5.14 + \fn QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const + \fn QDateTime QDate::startOfDay(const QTimeZone &zone) const + + Returns the start-moment of the day. Usually, this shall be midnight at the + start of the day: however, if a time-zone transition causes the given date + to skip over that midnight (e.g. a DST spring-forward skipping from the end + of the previous day to 01:00 of the new day), the actual earliest time in + the day is returned. This can only arise when the start-moment is specified + in terms of a time-zone (by passing its QTimeZone as \a zone) or in terms of + local time (by passing Qt::LocalTime as \a spec; this is its default). + + The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it + gives the implied zone's offset from UTC. As UTC and such zones have no + transitions, the start of the day is QTime(0, 0) in these cases. + + In the rare case of a date that was entirely skipped (this happens when a + zone east of the international date-line switches to being west of it), the + return shall be invalid. Passing Qt::TimeZone as \a spec (instead of + passing a QTimeZone) or passing an invalid time-zone as \a zone will also + produce an invalid result, as shall dates that start outside the range + representable by QDateTime. + + \sa endOfDay() +*/ +QDateTime QDate::startOfDay(Qt::TimeSpec spec, int offsetSeconds) const +{ + if (!inDateTimeRange(jd, true)) + return QDateTime(); + + switch (spec) { + case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone + qWarning() << "Called QDate::startOfDay(Qt::TimeZone) on" << *this; + return QDateTime(); + case Qt::OffsetFromUTC: + case Qt::UTC: + return QDateTime(*this, QTime(0, 0), spec, offsetSeconds); + + case Qt::LocalTime: + if (offsetSeconds) + qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds); + break; + } + QDateTime when(*this, QTime(0, 0), spec); + if (!when.isValid()) + when = toEarliest(*this, when); + + return when.isValid() ? when : QDateTime(); +} + +#if QT_CONFIG(timezone) +/*! + \overload + \since 5.14 +*/ +QDateTime QDate::startOfDay(const QTimeZone &zone) const +{ + if (!inDateTimeRange(jd, true) || !zone.isValid()) + return QDateTime(); + + QDateTime when(*this, QTime(0, 0), zone); + if (when.isValid()) + return when; + + // The start of the day must have fallen in a spring-forward's gap; find the spring-forward: + if (zone.hasTransitions()) { + QTimeZone::OffsetData tran = zone.previousTransition(QDateTime(*this, QTime(23, 59, 59, 999), zone)); + const QDateTime &at = tran.atUtc.toTimeZone(zone); + if (at.isValid() && at.date() == *this) + return at; + } + + when = toEarliest(*this, when); + return when.isValid() ? when : QDateTime(); +} +#endif // timezone + +static QDateTime toLatest(const QDate &day, const QDateTime &form) +{ + const Qt::TimeSpec spec = form.timeSpec(); + const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0; +#if QT_CONFIG(timezone) + QTimeZone zone; + if (spec == Qt::TimeZone) + zone = form.timeZone(); +#endif + auto moment = [=](QTime time) { + switch (spec) { + case Qt::OffsetFromUTC: return QDateTime(day, time, spec, offset); +#if QT_CONFIG(timezone) + case Qt::TimeZone: return QDateTime(day, time, zone); +#endif + default: return QDateTime(day, time, spec); + } + }; + // Longest routine time-zone transition is 2 hours: + QDateTime when = moment(QTime(21, 59, 59, 999)); + if (!when.isValid()) { + // Noon should be safe ... + when = moment(QTime(12, 0)); + if (!when.isValid()) { + // ... unless it's a 24-hour jump (moving the date-line) + when = moment(QTime(0, 0)); + if (!when.isValid()) + return QDateTime(); + } + } + int high = 24 * 60; + int low = when.time().msecsSinceStartOfDay() / 60000; + // Binary chop to the right minute + while (high > low + 1) { + int mid = (high + low) / 2; + QDateTime probe = moment(QTime(mid / 60, mid % 60, 59, 999)); + if (probe.isValid() && probe.date() == day) { + low = mid; + when = probe; + } else { + high = mid; + } + } + return when; +} + +/*! + \since 5.14 + \fn QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const + \fn QDateTime QDate::endOfDay(const QTimeZone &zone) const + + Returns the end-moment of the day. Usually, this is one millisecond before + the midnight at the end of the day: however, if a time-zone transition + causes the given date to skip over that midnight (e.g. a DST spring-forward + skipping from just before 23:00 to the start of the next day), the actual + latest time in the day is returned. This can only arise when the + start-moment is specified in terms of a time-zone (by passing its QTimeZone + as \a zone) or in terms of local time (by passing Qt::LocalTime as \a spec; + this is its default). + + The \a offsetSeconds is ignored unless \a spec is Qt::OffsetFromUTC, when it + gives the implied zone's offset from UTC. As UTC and such zones have no + transitions, the end of the day is QTime(23, 59, 59, 999) in these cases. + + In the rare case of a date that was entirely skipped (this happens when a + zone east of the international date-line switches to being west of it), the + return shall be invalid. Passing Qt::TimeZone as \a spec (instead of + passing a QTimeZone) will also produce an invalid result, as shall dates + that end outside the range representable by QDateTime. + + \sa startOfDay() +*/ +QDateTime QDate::endOfDay(Qt::TimeSpec spec, int offsetSeconds) const +{ + if (!inDateTimeRange(jd, false)) + return QDateTime(); + + switch (spec) { + case Qt::TimeZone: // should pass a QTimeZone instead of Qt::TimeZone + qWarning() << "Called QDate::endOfDay(Qt::TimeZone) on" << *this; + return QDateTime(); + case Qt::UTC: + case Qt::OffsetFromUTC: + return QDateTime(*this, QTime(23, 59, 59, 999), spec, offsetSeconds); + + case Qt::LocalTime: + if (offsetSeconds) + qWarning("Ignoring offset (%d seconds) passed with Qt::LocalTime", offsetSeconds); + break; + } + QDateTime when(*this, QTime(23, 59, 59, 999), spec); + if (!when.isValid()) + when = toLatest(*this, when); + return when.isValid() ? when : QDateTime(); +} + +#if QT_CONFIG(timezone) +/*! + \overload + \since 5.14 +*/ +QDateTime QDate::endOfDay(const QTimeZone &zone) const +{ + if (!inDateTimeRange(jd, false) || !zone.isValid()) + return QDateTime(); + + QDateTime when(*this, QTime(23, 59, 59, 999), zone); + if (when.isValid()) + return when; + + // The end of the day must have fallen in a spring-forward's gap; find the spring-forward: + if (zone.hasTransitions()) { + QTimeZone::OffsetData tran = zone.nextTransition(QDateTime(*this, QTime(0, 0), zone)); + const QDateTime &at = tran.atUtc.toTimeZone(zone); + if (at.isValid() && at.date() == *this) + return at; + } + + when = toLatest(*this, when); + return when.isValid() ? when : QDateTime(); +} +#endif // timezone + #if QT_DEPRECATED_SINCE(5, 11) && QT_CONFIG(textdate) /*! \since 4.5 @@ -1468,7 +1730,8 @@ bool QDate::isLeapYear(int y) \fn QTime::QTime() Constructs a null time object. For a null time, isNull() returns \c true and - isValid() returns \c false. If you need a zero time, use QTime(0, 0). + isValid() returns \c false. If you need a zero time, use QTime(0, 0). For + the start of a day, see QDate::startOfDay(). \sa isNull(), isValid() */ @@ -2392,8 +2655,8 @@ static void msecsToTime(qint64 msecs, QDate *date, QTime *time) qint64 jd = JULIAN_DAY_FOR_EPOCH; qint64 ds = 0; - if (qAbs(msecs) >= MSECS_PER_DAY) { - jd += (msecs / MSECS_PER_DAY); + if (msecs >= MSECS_PER_DAY || msecs <= -MSECS_PER_DAY) { + jd += msecs / MSECS_PER_DAY; msecs %= MSECS_PER_DAY; } diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index 51d5dd9759..8873651f17 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -55,6 +55,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(NSDate); QT_BEGIN_NAMESPACE class QTimeZone; +class QDateTime; class Q_CORE_EXPORT QDate { @@ -81,6 +82,13 @@ public: int daysInYear() const; int weekNumber(int *yearNum = nullptr) const; + QDateTime startOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const; + QDateTime endOfDay(Qt::TimeSpec spec = Qt::LocalTime, int offsetSeconds = 0) const; +#if QT_CONFIG(timezone) + QDateTime startOfDay(const QTimeZone &zone) const; + QDateTime endOfDay(const QTimeZone &zone) const; +#endif + #if QT_DEPRECATED_SINCE(5, 10) && QT_CONFIG(textdate) QT_DEPRECATED_X("Use QLocale::monthName or QLocale::standaloneMonthName") static QString shortMonthName(int month, MonthNameType type = DateFormat); diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index 5d1704daeb..e1dc596d2d 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -1982,7 +1982,7 @@ QString QDateTimeParser::stateName(State s) const #if QT_CONFIG(datestring) bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const { - QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN); + QDateTime val(QDate(1900, 1, 1).startOfDay()); const StateNode tmp = parse(t, -1, val, false); if (tmp.state != Acceptable || tmp.conflicts) { return false; @@ -2010,20 +2010,20 @@ QDateTime QDateTimeParser::getMinimum() const { // Cache the most common case if (spec == Qt::LocalTime) { - static const QDateTime localTimeMin(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, Qt::LocalTime); + static const QDateTime localTimeMin(QDATETIMEEDIT_DATE_MIN.startOfDay(Qt::LocalTime)); return localTimeMin; } - return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec); + return QDateTime(QDATETIMEEDIT_DATE_MIN.startOfDay(spec)); } QDateTime QDateTimeParser::getMaximum() const { // Cache the most common case if (spec == Qt::LocalTime) { - static const QDateTime localTimeMax(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, Qt::LocalTime); + static const QDateTime localTimeMax(QDATETIMEEDIT_DATE_MAX.endOfDay(Qt::LocalTime)); return localTimeMax; } - return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec); + return QDateTime(QDATETIMEEDIT_DATE_MAX.endOfDay(spec)); } QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h index e244fed09a..d9e39f0795 100644 --- a/src/corelib/tools/qdatetimeparser_p.h +++ b/src/corelib/tools/qdatetimeparser_p.h @@ -65,14 +65,11 @@ QT_REQUIRE_CONFIG(datetimeparser); -#define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0) -#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999) +#define QDATETIMEEDIT_TIME_MIN QTime(0, 0) // Prefer QDate::startOfDay() +#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999) // Prefer QDate::endOfDay() #define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1) #define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14) #define QDATETIMEEDIT_DATE_MAX QDate(9999, 12, 31) -#define QDATETIMEEDIT_DATETIME_MIN QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN) -#define QDATETIMEEDIT_COMPAT_DATETIME_MIN QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN) -#define QDATETIMEEDIT_DATETIME_MAX QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX) #define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1) QT_BEGIN_NAMESPACE diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index c617525c45..56697c5e8f 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -2097,7 +2097,7 @@ QVariant operator*(const QVariant &arg1, double multiplier) days -= daysInt; qint64 msecs = qint64(arg1.toDateTime().time().msecsSinceStartOfDay() * multiplier + days * (24 * 3600 * 1000)); - ret = QDateTime(QDATETIMEEDIT_DATE_MIN.addDays(daysInt), QTime::fromMSecsSinceStartOfDay(msecs)); + ret = QDATETIMEEDIT_DATE_MIN.addDays(daysInt).startOfDay().addMSecs(msecs); break; } #endif // datetimeparser diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp index b874e4e3a9..3f41fdeb59 100644 --- a/src/widgets/widgets/qdatetimeedit.cpp +++ b/src/widgets/widgets/qdatetimeedit.cpp @@ -153,7 +153,7 @@ QDateTimeEdit::QDateTimeEdit(QWidget *parent) : QAbstractSpinBox(*new QDateTimeEditPrivate, parent) { Q_D(QDateTimeEdit); - d->init(QDateTime(QDATETIMEEDIT_DATE_INITIAL, QDATETIMEEDIT_TIME_MIN)); + d->init(QDATETIMEEDIT_DATE_INITIAL.startOfDay()); } /*! @@ -165,8 +165,7 @@ QDateTimeEdit::QDateTimeEdit(const QDateTime &datetime, QWidget *parent) : QAbstractSpinBox(*new QDateTimeEditPrivate, parent) { Q_D(QDateTimeEdit); - d->init(datetime.isValid() ? datetime : QDateTime(QDATETIMEEDIT_DATE_INITIAL, - QDATETIMEEDIT_TIME_MIN)); + d->init(datetime.isValid() ? datetime : QDATETIMEEDIT_DATE_INITIAL.startOfDay()); } /*! @@ -342,7 +341,7 @@ QDateTime QDateTimeEdit::minimumDateTime() const void QDateTimeEdit::clearMinimumDateTime() { - setMinimumDateTime(QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN)); + setMinimumDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN.startOfDay()); } void QDateTimeEdit::setMinimumDateTime(const QDateTime &dt) @@ -385,7 +384,7 @@ QDateTime QDateTimeEdit::maximumDateTime() const void QDateTimeEdit::clearMaximumDateTime() { - setMaximumDateTime(QDATETIMEEDIT_DATETIME_MAX); + setMaximumDateTime(QDATETIMEEDIT_DATE_MAX.endOfDay()); } void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt) @@ -1658,8 +1657,8 @@ QDateTimeEditPrivate::QDateTimeEditPrivate() first.pos = 0; sections = 0; calendarPopup = false; - minimum = QDATETIMEEDIT_COMPAT_DATETIME_MIN; - maximum = QDATETIMEEDIT_DATETIME_MAX; + minimum = QDATETIMEEDIT_COMPAT_DATE_MIN.startOfDay(); + maximum = QDATETIMEEDIT_DATE_MAX.endOfDay(); arrowState = QStyle::State_None; monthCalendar = 0; readLocaleSettings(); @@ -1683,8 +1682,8 @@ void QDateTimeEditPrivate::updateTimeSpec() const bool dateShown = (sections & QDateTimeEdit::DateSections_Mask); if (!dateShown) { if (minimum.toTime() >= maximum.toTime()){ - minimum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MIN, spec); - maximum = QDateTime(value.toDate(), QDATETIMEEDIT_TIME_MAX, spec); + minimum = value.toDate().startOfDay(spec); + maximum = value.toDate().endOfDay(spec); } } } @@ -2382,7 +2381,7 @@ void QDateTimeEditPrivate::init(const QVariant &var) Q_Q(QDateTimeEdit); switch (var.type()) { case QVariant::Date: - value = QDateTime(var.toDate(), QDATETIMEEDIT_TIME_MIN); + value = var.toDate().startOfDay(); updateTimeSpec(); q->setDisplayFormat(defaultDateFormat); if (sectionNodes.isEmpty()) // ### safeguard for broken locale diff --git a/tests/auto/corelib/tools/qdate/qdate.pro b/tests/auto/corelib/tools/qdate/qdate.pro index dd7c6cb888..925c3b4c78 100644 --- a/tests/auto/corelib/tools/qdate/qdate.pro +++ b/tests/auto/corelib/tools/qdate/qdate.pro @@ -1,4 +1,4 @@ CONFIG += testcase TARGET = tst_qdate -QT = core testlib +QT = core-private testlib SOURCES = tst_qdate.cpp diff --git a/tests/auto/corelib/tools/qdate/tst_qdate.cpp b/tests/auto/corelib/tools/qdate/tst_qdate.cpp index c17af8741b..0ef494b229 100644 --- a/tests/auto/corelib/tools/qdate/tst_qdate.cpp +++ b/tests/auto/corelib/tools/qdate/tst_qdate.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -27,6 +27,7 @@ ** ****************************************************************************/ +#include // for the icu feature test #include #include #include @@ -54,6 +55,13 @@ private slots: void weekNumber_invalid(); void weekNumber_data(); void weekNumber(); +#if QT_CONFIG(timezone) + void startOfDay_endOfDay_data(); + void startOfDay_endOfDay(); +#endif + void startOfDay_endOfDay_fixed_data(); + void startOfDay_endOfDay_fixed(); + void startOfDay_endOfDay_bounds(); void julianDaysLimits(); void addDays_data(); void addDays(); @@ -458,6 +466,164 @@ void tst_QDate::weekNumber_invalid() QCOMPARE( dt.weekNumber( &yearNumber ), 0 ); } +#if QT_CONFIG(timezone) +void tst_QDate::startOfDay_endOfDay_data() +{ + QTest::addColumn("date"); // Typically a spring-forward. + // A zone in which that date's start and end are worth checking: + QTest::addColumn("zoneName"); + // The start and end times in that zone: + QTest::addColumn("start"); + QTest::addColumn("end"); + + const QTime initial(0, 0), final(23, 59, 59, 999), invalid(QDateTime().time()); + + QTest::newRow("epoch") + << QDate(1970, 1, 1) << QByteArray("UTC") + << initial << final; + QTest::newRow("Brazil") + << QDate(2008, 10, 19) << QByteArray("America/Sao_Paulo") + << QTime(1, 0) << final; +#if QT_CONFIG(icu) || !defined(Q_OS_WIN) // MS's TZ APIs lack data + QTest::newRow("Sofia") + << QDate(1994, 3, 27) << QByteArray("Europe/Sofia") + << QTime(1, 0) << final; +#endif + QTest::newRow("Kiritimati") + << QDate(1994, 12, 31) << QByteArray("Pacific/Kiritimati") + << invalid << invalid; + QTest::newRow("Samoa") + << QDate(2011, 12, 30) << QByteArray("Pacific/Apia") + << invalid << invalid; + // TODO: find other zones with transitions at/crossing midnight. +} + +void tst_QDate::startOfDay_endOfDay() +{ + QFETCH(QDate, date); + QFETCH(QByteArray, zoneName); + QFETCH(QTime, start); + QFETCH(QTime, end); + const QTimeZone zone(zoneName); + const bool isSystem = QTimeZone::systemTimeZone() == zone; + QDateTime front(date.startOfDay(zone)), back(date.endOfDay(zone)); + if (end.isValid()) + QCOMPARE(date.addDays(1).startOfDay(zone).addMSecs(-1), back); + if (start.isValid()) + QCOMPARE(date.addDays(-1).endOfDay(zone).addMSecs(1), front); + do { // Avoids duplicating these tests for local-time when it *is* zone: + if (start.isValid()) { + QCOMPARE(front.date(), date); + QCOMPARE(front.time(), start); + } + if (end.isValid()) { + QCOMPARE(back.date(), date); + QCOMPARE(back.time(), end); + } + if (front.timeSpec() == Qt::LocalTime) + break; + front = date.startOfDay(Qt::LocalTime); + back = date.endOfDay(Qt::LocalTime); + } while (isSystem); + if (end.isValid()) + QCOMPARE(date.addDays(1).startOfDay(Qt::LocalTime).addMSecs(-1), back); + if (start.isValid()) + QCOMPARE(date.addDays(-1).endOfDay(Qt::LocalTime).addMSecs(1), front); + if (!isSystem) { + // These might fail if system zone coincides with zone; but only if it + // did something similarly unusual on the date picked for this test. + if (start.isValid()) { + QCOMPARE(front.date(), date); + QCOMPARE(front.time(), QTime(0, 0)); + } + if (end.isValid()) { + QCOMPARE(back.date(), date); + QCOMPARE(back.time(), QTime(23, 59, 59, 999)); + } + } +} +#endif // timezone + +void tst_QDate::startOfDay_endOfDay_fixed_data() +{ + const qint64 kilo(1000); + using Bounds = std::numeric_limits; + const QDateTime + first(QDateTime::fromMSecsSinceEpoch(Bounds::min() + 1, Qt::UTC)), + start32sign(QDateTime::fromMSecsSinceEpoch(-0x80000000L * kilo, Qt::UTC)), + end32sign(QDateTime::fromMSecsSinceEpoch(0x80000000L * kilo, Qt::UTC)), + end32unsign(QDateTime::fromMSecsSinceEpoch(0x100000000L * kilo, Qt::UTC)), + last(QDateTime::fromMSecsSinceEpoch(Bounds::max(), Qt::UTC)); + + const struct { + const char *name; + QDate date; + } data[] = { + { "epoch", QDate(1970, 1, 1) }, + { "y2k-leap-day", QDate(2000, 2, 29) }, + // Just outside the start and end of 32-bit time_t: + { "pre-sign32", QDate(start32sign.date().year(), 1, 1) }, + { "post-sign32", QDate(end32sign.date().year(), 12, 31) }, + { "post-uint32", QDate(end32unsign.date().year(), 12, 31) }, + // Just inside the start and end of QDateTime's range: + { "first-full", first.date().addDays(1) }, + { "last-full", last.date().addDays(-1) } + }; + + QTest::addColumn("date"); + for (const auto &r : data) + QTest::newRow(r.name) << r.date; +} + +void tst_QDate::startOfDay_endOfDay_fixed() +{ + const QTime early(0, 0), late(23, 59, 59, 999); + QFETCH(QDate, date); + + QDateTime start(date.startOfDay(Qt::UTC)); + QDateTime end(date.endOfDay(Qt::UTC)); + QCOMPARE(start.date(), date); + QCOMPARE(end.date(), date); + QCOMPARE(start.time(), early); + QCOMPARE(end.time(), late); + QCOMPARE(date.addDays(1).startOfDay(Qt::UTC).addMSecs(-1), end); + QCOMPARE(date.addDays(-1).endOfDay(Qt::UTC).addMSecs(1), start); + for (int offset = -60 * 16; offset <= 60 * 16; offset += 65) { + start = date.startOfDay(Qt::OffsetFromUTC, offset); + end = date.endOfDay(Qt::OffsetFromUTC, offset); + QCOMPARE(start.date(), date); + QCOMPARE(end.date(), date); + QCOMPARE(start.time(), early); + QCOMPARE(end.time(), late); + QCOMPARE(date.addDays(1).startOfDay(Qt::OffsetFromUTC, offset).addMSecs(-1), end); + QCOMPARE(date.addDays(-1).endOfDay(Qt::OffsetFromUTC, offset).addMSecs(1), start); + } +} + +void tst_QDate::startOfDay_endOfDay_bounds() +{ + // Check the days in which QDateTime's range starts and ends: + using Bounds = std::numeric_limits; + const QDateTime + first(QDateTime::fromMSecsSinceEpoch(Bounds::min(), Qt::UTC)), + last(QDateTime::fromMSecsSinceEpoch(Bounds::max(), Qt::UTC)), + epoch(QDateTime::fromMSecsSinceEpoch(0, Qt::UTC)); + // First, check these *are* the start and end of QDateTime's range: + QVERIFY(first.isValid()); + QVERIFY(last.isValid()); + QVERIFY(first < epoch); + QVERIFY(last > epoch); + // QDateTime's addMSecs doesn't check against {und,ov}erflow ... + QVERIFY(!first.addMSecs(-1).isValid() || first.addMSecs(-1) > first); + QVERIFY(!last.addMSecs(1).isValid() || last.addMSecs(1) < last); + + // Now test start/end methods with them: + QCOMPARE(first.date().endOfDay(Qt::UTC).time(), QTime(23, 59, 59, 999)); + QCOMPARE(last.date().startOfDay(Qt::UTC).time(), QTime(0, 0)); + QVERIFY(!first.date().startOfDay(Qt::UTC).isValid()); + QVERIFY(!last.date().endOfDay(Qt::UTC).isValid()); +} + void tst_QDate::julianDaysLimits() { qint64 min = std::numeric_limits::min(); From ae38dd485bab4a0591745b78afa28547ce6ae6fc Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 24 Apr 2019 15:41:48 +0200 Subject: [PATCH 014/122] uic: Fix missing Python import for QFontComboBox It requires QFontDatabase from QtGui. Add more classes from QtGui. Fixes: PYSIDE-994 Change-Id: Ib84c86e2305fad60560a3f12997eb1e46deb67cb Reviewed-by: Cristian Maureira-Fredes --- src/tools/uic/python/pythonwriteimports.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/uic/python/pythonwriteimports.cpp b/src/tools/uic/python/pythonwriteimports.cpp index 8e11981f37..303615f77b 100644 --- a/src/tools/uic/python/pythonwriteimports.cpp +++ b/src/tools/uic/python/pythonwriteimports.cpp @@ -40,7 +40,9 @@ QT_BEGIN_NAMESPACE static const char *standardImports = R"I(from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint, QRect, QSize, QUrl, Qt) -from PySide2.QtGui import (QColor, QFont, QIcon, QPixmap) +from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QFont, + QFontDatabase, QIcon, QLinearGradient, QPalette, QPainter, QPixmap, + QRadialGradient) from PySide2.QtWidgets import * )I"; From f10d37c9c10c323c37d5ec617588348458e7286f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Wed, 24 Apr 2019 15:57:55 +0200 Subject: [PATCH 015/122] Fix -Wc++11-narrowing error in qtextmarkdownimporter error: non-constant-expression cannot be narrowed from type 'qt::QFlags::Int' (aka 'int') to 'unsigned int' in initializer list [-Wc++11-narrowing] Change-Id: Ic634a98d29a108741d41955da1fbf2c986e4a943 Reviewed-by: Shawn Rutledge --- src/gui/text/qtextmarkdownimporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index 6c053ac81a..6bff337ff4 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -117,7 +117,7 @@ void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown) { MD_PARSER callbacks = { 0, // abi_version - m_features, + unsigned(m_features), &CbEnterBlock, &CbLeaveBlock, &CbEnterSpan, From e6d9617c79ea029cf60c5555a3d7a32bac1cdbf6 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 3 Mar 2016 20:20:42 +0100 Subject: [PATCH 016/122] QHash/QMultiHash: add range constructors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QMap and QMultiMap will go in a separate commit, due to QMap's insertion behavior that "reverses" the inserted elements. [ChangeLog][QtCore][QHash] Added range constructor. [ChangeLog][QtCore][QMultiHash] Added range constructor. Change-Id: Icfd0d0afde27792e8439ed6df3e8774696b134d3 Reviewed-by: Edward Welbourne Reviewed-by: Sérgio Martins Reviewed-by: Thiago Macieira --- src/corelib/tools/qcontainertools_impl.h | 43 ++++++ src/corelib/tools/qhash.cpp | 22 +++ src/corelib/tools/qhash.h | 43 ++++++ .../tst_containerapisymmetry.cpp | 140 ++++++++++++++++++ 4 files changed, 248 insertions(+) diff --git a/src/corelib/tools/qcontainertools_impl.h b/src/corelib/tools/qcontainertools_impl.h index c2de50b145..86a16eb32b 100644 --- a/src/corelib/tools/qcontainertools_impl.h +++ b/src/corelib/tools/qcontainertools_impl.h @@ -84,6 +84,49 @@ void reserveIfForwardIterator(Container *c, ForwardIterator f, ForwardIterator l { c->reserve(static_cast(std::distance(f, l))); } + +// for detecting expression validity +template +using void_t = void; + +template > +struct AssociativeIteratorHasKeyAndValue : std::false_type +{ +}; + +template +struct AssociativeIteratorHasKeyAndValue< + Iterator, + void_t().key()), + decltype(std::declval().value())> + > + : std::true_type +{ +}; + +template , typename = void_t<>> +struct AssociativeIteratorHasFirstAndSecond : std::false_type +{ +}; + +template +struct AssociativeIteratorHasFirstAndSecond< + Iterator, + void_t()->first), + decltype(std::declval()->second)> + > + : std::true_type +{ +}; + +template +using IfAssociativeIteratorHasKeyAndValue = + typename std::enable_if::value, bool>::type; + +template +using IfAssociativeIteratorHasFirstAndSecond = + typename std::enable_if::value, bool>::type; + } // namespace QtPrivate QT_END_NAMESPACE diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index dd22a38be1..5c7e535c30 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -1251,6 +1251,17 @@ uint qHash(long double key, uint seed) noexcept compiled in C++11 mode. */ +/*! \fn template template QHash::QHash(InputIterator begin, InputIterator end) + \since 5.14 + + Constructs a hash with a copy of each of the elements in the iterator range + [\a begin, \a end). Either the elements iterated by the range must be + objects with \c{first} and \c{second} data members (like \c{QPair}, + \c{std::pair}, etc.) convertible to \c Key and to \c T respectively; or the + iterators must have \c{key()} and \c{value()} member functions, returning a + key convertible to \c Key and a value convertible to \c T respectively. +*/ + /*! \fn template QHash::QHash(const QHash &other) Constructs a copy of \a other. @@ -2586,6 +2597,17 @@ uint qHash(long double key, uint seed) noexcept \sa operator=() */ +/*! \fn template template QMultiHash::QMultiHash(InputIterator begin, InputIterator end) + \since 5.14 + + Constructs a multi-hash with a copy of each of the elements in the iterator range + [\a begin, \a end). Either the elements iterated by the range must be + objects with \c{first} and \c{second} data members (like \c{QPair}, + \c{std::pair}, etc.) convertible to \c Key and to \c T respectively; or the + iterators must have \c{key()} and \c{value()} member functions, returning a + key convertible to \c Key and a value convertible to \c T respectively. +*/ + /*! \fn template QMultiHash::iterator QMultiHash::replace(const Key &key, const T &value) Inserts a new item with the \a key and a value of \a value. diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 120ee9cc85..a757e85386 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -46,6 +46,7 @@ #include #include #include +#include #ifdef Q_COMPILER_INITIALIZER_LISTS #include @@ -258,6 +259,28 @@ public: QHash(QHash &&other) noexcept : d(other.d) { other.d = const_cast(&QHashData::shared_null); } QHash &operator=(QHash &&other) noexcept { QHash moved(std::move(other)); swap(moved); return *this; } +#endif +#ifdef Q_QDOC + template + QHash(InputIterator f, InputIterator l); +#else + template = true> + QHash(InputIterator f, InputIterator l) + : QHash() + { + QtPrivate::reserveIfForwardIterator(this, f, l); + for (; f != l; ++f) + insert(f.key(), f.value()); + } + + template = true> + QHash(InputIterator f, InputIterator l) + : QHash() + { + QtPrivate::reserveIfForwardIterator(this, f, l); + for (; f != l; ++f) + insert(f->first, f->second); + } #endif void swap(QHash &other) noexcept { qSwap(d, other.d); } @@ -1028,6 +1051,26 @@ public: for (typename std::initializer_list >::const_iterator it = list.begin(); it != list.end(); ++it) insert(it->first, it->second); } +#endif +#ifdef Q_QDOC + template + QMultiHash(InputIterator f, InputIterator l); +#else + template = true> + QMultiHash(InputIterator f, InputIterator l) + { + QtPrivate::reserveIfForwardIterator(this, f, l); + for (; f != l; ++f) + insert(f.key(), f.value()); + } + + template = true> + QMultiHash(InputIterator f, InputIterator l) + { + QtPrivate::reserveIfForwardIterator(this, f, l); + for (; f != l; ++f) + insert(f->first, f->second); + } #endif // compiler-generated copy/move ctors/assignment operators are fine! // compiler-generated destructor is fine! diff --git a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp index 196276c52f..7df220acf9 100644 --- a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp +++ b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp @@ -34,6 +34,7 @@ #include "qstring.h" #include "qvarlengtharray.h" #include "qvector.h" +#include "qhash.h" #include "qdebug.h" #include @@ -41,6 +42,7 @@ #include // for reference #include #include +#include // MSVC has these containers from the Standard Library, but it lacks // a __has_include mechanism (that we need to use for other stdlibs). @@ -58,6 +60,9 @@ #if COMPILER_HAS_STDLIB_INCLUDE() #include #endif +#if COMPILER_HAS_STDLIB_INCLUDE() +#include +#endif struct Movable { @@ -255,6 +260,9 @@ private: template class Container> void non_associative_container_duplicates_strategy() const; + template + void ranged_ctor_associative_impl() const; + private Q_SLOTS: // non associative void ranged_ctor_std_vector_int() { ranged_ctor_non_associative_impl>(); } @@ -403,6 +411,71 @@ private Q_SLOTS: void ranged_ctor_QSet_Complex() { ranged_ctor_non_associative_impl>(); } void ranged_ctor_QSet_duplicates_strategy() { non_associative_container_duplicates_strategy(); } + // associative + void ranged_ctor_std_map_int() { ranged_ctor_associative_impl>(); } + void ranged_ctor_std_map_Movable() { ranged_ctor_associative_impl>(); } + void ranged_ctor_std_map_Complex() { ranged_ctor_associative_impl>(); } + + void ranged_ctor_std_multimap_int() { ranged_ctor_associative_impl>(); } + void ranged_ctor_std_multimap_Movable() { ranged_ctor_associative_impl>(); } + void ranged_ctor_std_multimap_Complex() { ranged_ctor_associative_impl>(); } + + void ranged_ctor_unordered_map_int() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_unordered_map_Movable() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_unordered_map_Complex() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_QHash_int() { ranged_ctor_associative_impl>(); } + void ranged_ctor_QHash_Movable() { ranged_ctor_associative_impl>(); } + void ranged_ctor_QHash_Complex() { ranged_ctor_associative_impl>(); } + + void ranged_ctor_unordered_multimap_int() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_unordered_multimap_Movable() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_unordered_multimap_Complex() { +#if COMPILER_HAS_STDLIB_INCLUDE() + ranged_ctor_associative_impl>(); +#else + QSKIP(" is needed for this test"); +#endif + } + + void ranged_ctor_QMultiHash_int() { ranged_ctor_associative_impl>(); } + void ranged_ctor_QMultiHash_Movable() { ranged_ctor_associative_impl>(); } + void ranged_ctor_QMultiHash_Complex() { ranged_ctor_associative_impl>(); } + private: template void front_back_impl() const; @@ -651,6 +724,73 @@ void tst_ContainerApiSymmetry::non_associative_container_duplicates_strategy() c } #endif // Q_COMPILER_INITIALIZER_LISTS +template +void tst_ContainerApiSymmetry::ranged_ctor_associative_impl() const +{ + using K = typename Container::key_type; + using V = typename Container::mapped_type; + + // The double K(0) is deliberate. The order of the elements matters: + // * for unique-key STL containers, the first one should be the one inserted (cf. LWG 2844) + // * for unique-key Qt containers, the last one should be the one inserted + // * for multi-key sorted containers, the order of insertion of identical keys is also the + // iteration order (which establishes the equality of the containers) + // (although nothing of this is being tested here, that deserves its own testing) + const Container reference{ + { K(0), V(1000) }, + { K(1), V(1001) }, + { K(2), V(1002) }, + { K(0), V(1003) } + }; + + // Note that using anything not convertible to std::pair doesn't work for + // std containers. Their ranged construction is defined in terms of + // insert(value_type), which for std associative containers is + // std::pair. + + // plain array + const std::pair values1[] = { + std::make_pair(K(0), V(1000)), + std::make_pair(K(1), V(1001)), + std::make_pair(K(2), V(1002)), + std::make_pair(K(0), V(1003)) + }; + + const Container c1(values1, values1 + sizeof(values1)/sizeof(values1[0])); + + // from QList + QList> l2; + l2 << std::make_pair(K(0), V(1000)) + << std::make_pair(K(1), V(1001)) + << std::make_pair(K(2), V(1002)) + << std::make_pair(K(0), V(1003)); + + const Container c2a(l2.begin(), l2.end()); + const Container c2b(l2.cbegin(), l2.cend()); + + // from std::list + std::list> l3; + l3.push_back(std::make_pair(K(0), V(1000))); + l3.push_back(std::make_pair(K(1), V(1001))); + l3.push_back(std::make_pair(K(2), V(1002))); + l3.push_back(std::make_pair(K(0), V(1003))); + const Container c3a(l3.begin(), l3.end()); + + // from const std::list + const std::list> l3c = l3; + const Container c3b(l3c.begin(), l3c.end()); + + // from itself + const Container c4(reference.begin(), reference.end()); + + QCOMPARE(c1, reference); + QCOMPARE(c2a, reference); + QCOMPARE(c2b, reference); + QCOMPARE(c3a, reference); + QCOMPARE(c3b, reference); + QCOMPARE(c4, reference); +} + template Container make(int size) { From 0c404fd6f34c7ca75400324e95e44842152bdd87 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 6 Feb 2019 13:12:35 +0100 Subject: [PATCH 017/122] Add image layer on windows The docker-compose files were trying to use volume sharing, which is not supported on Windows in conjunction with docker-machine. Hence create a separate layer on Windows, which copies the configuration files to the target. Change-Id: Ifeacc56198ffc8fb2eb31c14ab91334e22e916f5 Reviewed-by: Maurice Kalinowski Reviewed-by: Edward Welbourne --- tests/testserver/Dockerfile | 11 +++++ .../testserver/docker-compose-for-windows.yml | 45 ++++++++++--------- 2 files changed, 36 insertions(+), 20 deletions(-) create mode 100644 tests/testserver/Dockerfile diff --git a/tests/testserver/Dockerfile b/tests/testserver/Dockerfile new file mode 100644 index 0000000000..a4db873a5d --- /dev/null +++ b/tests/testserver/Dockerfile @@ -0,0 +1,11 @@ +# This Dockerfile is used on windows as volume sharing / mounting does not work in conjunction +# docker-machine. Windows Update 1809 might solve some of those issues when using docker0 +# network switch, but nothing has been reported in regards to the combination with docker-machine. + +ARG provisioningImage +FROM $provisioningImage + +# Common is used for all test images so far, no need for a variable +COPY ./common /common +ARG servicedir +COPY $servicedir /service diff --git a/tests/testserver/docker-compose-for-windows.yml b/tests/testserver/docker-compose-for-windows.yml index aa610dfb88..4867413361 100644 --- a/tests/testserver/docker-compose-for-windows.yml +++ b/tests/testserver/docker-compose-for-windows.yml @@ -12,12 +12,13 @@ version: '3.4' services: apache2: - image: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13 container_name: qt-test-server-apache2 domainname: ${TEST_DOMAIN} - volumes: - - ./common:/common:ro - - ./apache2:/service:ro + build: + context: . + args: + provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13 + servicedir: ./apache2 entrypoint: common/startup.sh command: [common/ssl.sh, service/apache2.sh] network_mode: "host" @@ -28,14 +29,15 @@ services: - test_cert="qt-test-server-host-network-cacert.pem" squid: - image: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c container_name: qt-test-server-squid domainname: ${TEST_DOMAIN} depends_on: - apache2 - volumes: - - ./common:/common:ro - - ./squid:/service:ro + build: + context: . + args: + provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c + servicedir: ./squid entrypoint: common/startup.sh command: service/squid.sh network_mode: "host" @@ -45,12 +47,13 @@ services: - test_domain=${TEST_DOMAIN} vsftpd: - image: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e container_name: qt-test-server-vsftpd domainname: ${TEST_DOMAIN} - volumes: - - ./common:/common:ro - - ./vsftpd:/service:ro + build: + context: . + args: + provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e + servicedir: ./vsftpd entrypoint: common/startup.sh command: service/vsftpd.sh network_mode: "host" @@ -60,14 +63,15 @@ services: - test_domain=${TEST_DOMAIN} ftp-proxy: - image: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae container_name: qt-test-server-ftp-proxy domainname: ${TEST_DOMAIN} depends_on: - vsftpd - volumes: - - ./common:/common:ro - - ./ftp-proxy:/service:ro + build: + context: . + args: + provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae + servicedir: ./ftp-proxy entrypoint: common/startup.sh command: service/ftp-proxy.sh network_mode: "host" @@ -77,16 +81,17 @@ services: - test_domain=${TEST_DOMAIN} danted: - image: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5 container_name: qt-test-server-danted domainname: ${TEST_DOMAIN} depends_on: - apache2 - vsftpd - ftp-proxy - volumes: - - ./common:/common:ro - - ./danted:/service:ro + build: + context: . + args: + provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5 + servicedir: ./danted entrypoint: common/startup.sh command: service/danted.sh network_mode: "host" From 713f77176e5de34503bd265e00f665b7f6ef05b4 Mon Sep 17 00:00:00 2001 From: Ryan Chu Date: Fri, 22 Mar 2019 16:20:52 +0100 Subject: [PATCH 018/122] Support multi-stage builds to provision the configurations and test data In order to reuse the test server to the external modules, it is much easier to share the common configurations (scripts) and test data via Dockerfile. In addition, the external module can create more layers depending on their needs. Therefore, supporting multi-stage builds is needed. The disadvantage is that the docker-compose needs to re-build the images every time. However, it is just a one-time effort. If the Dockerfile doesn't get changed, the extra build time can be ignored. Because of multi-stage builds, the test server will keep a Dockerfile at least. Therefore, the volume sharing is no more needed. The test data of a service can be added into the images by using COPY/ADD commands. NOTE: This patch relies on docker-compose v1.21.0 (docker-compose build now supports the use of Dockerfile from outside the build context). Change-Id: Ib3f6a5fcf6979732ae8a40a494a1360fca4ac7bf Reviewed-by: Maurice Kalinowski Reviewed-by: Edward Welbourne --- tests/auto/Dockerfile | 27 ++++ tests/auto/testserver.pri | 5 +- tests/testserver/Dockerfile | 11 -- tests/testserver/common/startup.sh | 17 +-- tests/testserver/docker-compose-for-macOS.yml | 81 +++++++----- .../testserver/docker-compose-for-windows.yml | 46 ++++--- tests/testserver/docker-compose.yml | 124 +++++++++++------- 7 files changed, 185 insertions(+), 126 deletions(-) create mode 100644 tests/auto/Dockerfile delete mode 100644 tests/testserver/Dockerfile diff --git a/tests/auto/Dockerfile b/tests/auto/Dockerfile new file mode 100644 index 0000000000..8fb664a1d2 --- /dev/null +++ b/tests/auto/Dockerfile @@ -0,0 +1,27 @@ +# This Dockerfile is used to provision the shared scripts (e.g. startup.sh) and configurations. It +# relies on the arguments passed by docker-compose file to build additional images for each service. +# To lean more how it works, please check the topic "Use multi-stage builds". +# https://docs.docker.com/develop/develop-images/multistage-build/ + +ARG provisioningImage +FROM $provisioningImage as testserver_tier2 + +# Add and merge the testdata into service folder +ARG serviceDir +ARG shareDir=$serviceDir +COPY $serviceDir $shareDir service/ + +# create the shared script of testserver +RUN echo "#!/usr/bin/env bash\n" \ + "set -ex\n" \ + "for RUN_CMD; do \$RUN_CMD; done\n" \ + "service dbus restart\n" \ + "service avahi-daemon restart\n" \ + "sleep infinity\n" > startup.sh +RUN chmod +x startup.sh + +# rewrite the default configurations of avahi-daemon +ARG test_domain +RUN sed -i -e "s,#domain-name=local,domain-name=${test_domain:-test-net.qt.local}," \ + -e "s,#publish-aaaa-on-ipv4=yes,publish-aaaa-on-ipv4=no," \ + /etc/avahi/avahi-daemon.conf diff --git a/tests/auto/testserver.pri b/tests/auto/testserver.pri index 455f88fa5d..1b7ccf5757 100644 --- a/tests/auto/testserver.pri +++ b/tests/auto/testserver.pri @@ -102,6 +102,7 @@ isEmpty(TESTSERVER_VERSION) { # The environment variables passed to the docker-compose file TEST_ENV = 'MACHINE_IP=$(shell docker-machine ip qt-test-server)' TEST_ENV += 'TEST_DOMAIN=$$DNSDOMAIN' + TEST_ENV += 'SHARED_DATA=$$PWD' TEST_CMD = env } else:equals(QMAKE_HOST.os, Windows) { # There is no docker bridge on Windows. It is impossible to ping a container. @@ -115,6 +116,7 @@ isEmpty(TESTSERVER_VERSION) { # The environment variables passed to the docker-compose file TEST_ENV = '\$\$env:MACHINE_IP = docker-machine ip qt-test-server;' TEST_ENV += '\$\$env:TEST_DOMAIN = $$shell_quote(\"$$DNSDOMAIN\");' + TEST_ENV += '\$\$env:SHARED_DATA = $$shell_quote(\"$$PWD\");' # Docker-compose CLI environment variables: # Enable path conversion from Windows-style to Unix-style in volume definitions. @@ -127,6 +129,7 @@ isEmpty(TESTSERVER_VERSION) { $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml # The environment variables passed to the docker-compose file TEST_ENV = 'TEST_DOMAIN=$$DNSDOMAIN' + TEST_ENV += 'SHARED_DATA=$$PWD' TEST_CMD = env } !exists($$TESTSERVER_COMPOSE_FILE): error("Invalid TESTSERVER_COMPOSE_FILE specified") @@ -200,7 +203,7 @@ isEmpty(TESTSERVER_VERSION) { # Bring up test servers and make sure the services are ready. !isEmpty(TEST_CMD): testserver_test.commands = $$TEST_CMD $$TEST_ENV testserver_test.commands += docker-compose $$MACHINE_CONFIG -f $$TESTSERVER_COMPOSE_FILE up \ - --detach --force-recreate --timeout 1 $${QT_TEST_SERVER_LIST} && + --build -d --force-recreate --timeout 1 $${QT_TEST_SERVER_LIST} && # Check test cases with docker-based test servers. testserver_test.commands += $(MAKE) -f $(MAKEFILE) check_network && diff --git a/tests/testserver/Dockerfile b/tests/testserver/Dockerfile deleted file mode 100644 index a4db873a5d..0000000000 --- a/tests/testserver/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -# This Dockerfile is used on windows as volume sharing / mounting does not work in conjunction -# docker-machine. Windows Update 1809 might solve some of those issues when using docker0 -# network switch, but nothing has been reported in regards to the combination with docker-machine. - -ARG provisioningImage -FROM $provisioningImage - -# Common is used for all test images so far, no need for a variable -COPY ./common /common -ARG servicedir -COPY $servicedir /service diff --git a/tests/testserver/common/startup.sh b/tests/testserver/common/startup.sh index 74990a47f6..1386314e38 100755 --- a/tests/testserver/common/startup.sh +++ b/tests/testserver/common/startup.sh @@ -34,7 +34,7 @@ set -ex # export variables export USER=qt-test-server export PASS=password -export CONFIG=common/testdata +export CONFIG=service/testdata export TESTDATA=service/testdata # add users @@ -43,17 +43,4 @@ useradd -m -s /bin/bash $USER; echo "$USER:$PASS" | chpasswd # install configurations and test data su $USER -c "cp $CONFIG/system/passwords ~/" -# modules initialization (apache2.sh, ftp-proxy.sh ...) -for RUN_CMD -do $RUN_CMD -done - -# start multicast DNS service discovery (mDNS) -sed -i -e "s,#domain-name=local,domain-name=${test_domain:-test-net.qt.local}," \ - -e "s,#publish-aaaa-on-ipv4=yes,publish-aaaa-on-ipv4=no," \ - /etc/avahi/avahi-daemon.conf -service dbus restart -service avahi-daemon restart - -# keep-alive in docker detach mode -sleep infinity +./startup.sh "$@" diff --git a/tests/testserver/docker-compose-for-macOS.yml b/tests/testserver/docker-compose-for-macOS.yml index aa610dfb88..c5348e27b6 100644 --- a/tests/testserver/docker-compose-for-macOS.yml +++ b/tests/testserver/docker-compose-for-macOS.yml @@ -12,82 +12,95 @@ version: '3.4' services: apache2: - image: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13 container_name: qt-test-server-apache2 domainname: ${TEST_DOMAIN} - volumes: - - ./common:/common:ro - - ./apache2:/service:ro - entrypoint: common/startup.sh - command: [common/ssl.sh, service/apache2.sh] + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13 + shareDir: ./common + serviceDir: ./apache2 + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh + command: [service/ssl.sh, service/apache2.sh] network_mode: "host" extra_hosts: - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}" environment: - - test_domain=${TEST_DOMAIN} - test_cert="qt-test-server-host-network-cacert.pem" squid: - image: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c container_name: qt-test-server-squid domainname: ${TEST_DOMAIN} depends_on: - apache2 - volumes: - - ./common:/common:ro - - ./squid:/service:ro - entrypoint: common/startup.sh + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c + shareDir: ./common + serviceDir: ./squid + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/squid.sh network_mode: "host" extra_hosts: - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}" - environment: - - test_domain=${TEST_DOMAIN} vsftpd: - image: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e container_name: qt-test-server-vsftpd domainname: ${TEST_DOMAIN} - volumes: - - ./common:/common:ro - - ./vsftpd:/service:ro - entrypoint: common/startup.sh + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e + shareDir: ./common + serviceDir: ./vsftpd + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/vsftpd.sh network_mode: "host" extra_hosts: - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}" - environment: - - test_domain=${TEST_DOMAIN} ftp-proxy: - image: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae container_name: qt-test-server-ftp-proxy domainname: ${TEST_DOMAIN} depends_on: - vsftpd - volumes: - - ./common:/common:ro - - ./ftp-proxy:/service:ro - entrypoint: common/startup.sh + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae + shareDir: ./common + serviceDir: ./ftp-proxy + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/ftp-proxy.sh network_mode: "host" extra_hosts: - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}" - environment: - - test_domain=${TEST_DOMAIN} danted: - image: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5 container_name: qt-test-server-danted domainname: ${TEST_DOMAIN} depends_on: - apache2 - vsftpd - ftp-proxy - volumes: - - ./common:/common:ro - - ./danted:/service:ro - entrypoint: common/startup.sh + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5 + shareDir: ./common + serviceDir: ./danted + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/danted.sh network_mode: "host" extra_hosts: @@ -97,4 +110,4 @@ services: - danted_external=${MACHINE_IP} - danted_auth_internal=${MACHINE_IP} - danted_auth_external=${MACHINE_IP} - - test_domain=${TEST_DOMAIN} + diff --git a/tests/testserver/docker-compose-for-windows.yml b/tests/testserver/docker-compose-for-windows.yml index 4867413361..c5348e27b6 100644 --- a/tests/testserver/docker-compose-for-windows.yml +++ b/tests/testserver/docker-compose-for-windows.yml @@ -16,16 +16,18 @@ services: domainname: ${TEST_DOMAIN} build: context: . + dockerfile: ${SHARED_DATA}/Dockerfile args: provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13 - servicedir: ./apache2 - entrypoint: common/startup.sh - command: [common/ssl.sh, service/apache2.sh] + shareDir: ./common + serviceDir: ./apache2 + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh + command: [service/ssl.sh, service/apache2.sh] network_mode: "host" extra_hosts: - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}" environment: - - test_domain=${TEST_DOMAIN} - test_cert="qt-test-server-host-network-cacert.pem" squid: @@ -35,32 +37,34 @@ services: - apache2 build: context: . + dockerfile: ${SHARED_DATA}/Dockerfile args: provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c - servicedir: ./squid - entrypoint: common/startup.sh + shareDir: ./common + serviceDir: ./squid + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/squid.sh network_mode: "host" extra_hosts: - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}" - environment: - - test_domain=${TEST_DOMAIN} vsftpd: container_name: qt-test-server-vsftpd domainname: ${TEST_DOMAIN} build: context: . + dockerfile: ${SHARED_DATA}/Dockerfile args: provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e - servicedir: ./vsftpd - entrypoint: common/startup.sh + shareDir: ./common + serviceDir: ./vsftpd + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/vsftpd.sh network_mode: "host" extra_hosts: - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}" - environment: - - test_domain=${TEST_DOMAIN} ftp-proxy: container_name: qt-test-server-ftp-proxy @@ -69,16 +73,17 @@ services: - vsftpd build: context: . + dockerfile: ${SHARED_DATA}/Dockerfile args: provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae - servicedir: ./ftp-proxy - entrypoint: common/startup.sh + shareDir: ./common + serviceDir: ./ftp-proxy + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/ftp-proxy.sh network_mode: "host" extra_hosts: - "qt-test-server.${TEST_DOMAIN}:${MACHINE_IP}" - environment: - - test_domain=${TEST_DOMAIN} danted: container_name: qt-test-server-danted @@ -89,10 +94,13 @@ services: - ftp-proxy build: context: . + dockerfile: ${SHARED_DATA}/Dockerfile args: provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5 - servicedir: ./danted - entrypoint: common/startup.sh + shareDir: ./common + serviceDir: ./danted + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/danted.sh network_mode: "host" extra_hosts: @@ -102,4 +110,4 @@ services: - danted_external=${MACHINE_IP} - danted_auth_internal=${MACHINE_IP} - danted_auth_external=${MACHINE_IP} - - test_domain=${TEST_DOMAIN} + diff --git a/tests/testserver/docker-compose.yml b/tests/testserver/docker-compose.yml index 962daad3c9..75e8a0fea2 100644 --- a/tests/testserver/docker-compose.yml +++ b/tests/testserver/docker-compose.yml @@ -12,18 +12,21 @@ version: '3.4' services: apache2: - image: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13 container_name: qt-test-server-apache2 domainname: ${TEST_DOMAIN} hostname: apache2 - volumes: - - ./common:/common:ro - - ./apache2:/service:ro - entrypoint: common/startup.sh - command: [common/ssl.sh, service/apache2.sh] + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13 + shareDir: ./common + serviceDir: ./apache2 + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh + command: [service/ssl.sh, service/apache2.sh] squid: - image: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c container_name: qt-test-server-squid domainname: ${TEST_DOMAIN} hostname: squid @@ -35,25 +38,33 @@ services: - iptables:iptables.${TEST_DOMAIN} - vsftpd:vsftpd.${TEST_DOMAIN} - echo:echo.${TEST_DOMAIN} - volumes: - - ./common:/common:ro - - ./squid:/service:ro - entrypoint: common/startup.sh + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c + shareDir: ./common + serviceDir: ./squid + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/squid.sh vsftpd: - image: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e container_name: qt-test-server-vsftpd domainname: ${TEST_DOMAIN} hostname: vsftpd - volumes: - - ./common:/common:ro - - ./vsftpd:/service:ro - entrypoint: common/startup.sh + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e + shareDir: ./common + serviceDir: ./vsftpd + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/vsftpd.sh ftp-proxy: - image: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae container_name: qt-test-server-ftp-proxy domainname: ${TEST_DOMAIN} hostname: ftp-proxy @@ -61,14 +72,18 @@ services: - vsftpd external_links: - vsftpd:vsftpd.${TEST_DOMAIN} - volumes: - - ./common:/common:ro - - ./ftp-proxy:/service:ro - entrypoint: common/startup.sh + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae + shareDir: ./common + serviceDir: ./ftp-proxy + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/ftp-proxy.sh danted: - image: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5 container_name: qt-test-server-danted domainname: ${TEST_DOMAIN} hostname: danted @@ -82,44 +97,61 @@ services: - ftp-proxy:ftp-proxy.${TEST_DOMAIN} - cyrus:cyrus.${TEST_DOMAIN} - echo:echo.${TEST_DOMAIN} - volumes: - - ./common:/common:ro - - ./danted:/service:ro - entrypoint: common/startup.sh + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5 + shareDir: ./common + serviceDir: ./danted + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/danted.sh cyrus: - image: qt-test-server-cyrus:c8d72754abc0e501afd624ce838e4df35505abc9 container_name: qt-test-server-cyrus domainname: ${TEST_DOMAIN} hostname: cyrus - volumes: - - ./common:/common:ro - - ./cyrus:/service:ro - entrypoint: common/startup.sh - command: [common/ssl.sh, service/cyrus.sh] + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-cyrus:c8d72754abc0e501afd624ce838e4df35505abc9 + shareDir: ./common + serviceDir: ./cyrus + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh + command: [service/ssl.sh, service/cyrus.sh] iptables: - image: qt-test-server-iptables:cb7a8bd6d28602085a88c8ced7d67e28e75781e2 container_name: qt-test-server-iptables domainname: ${TEST_DOMAIN} hostname: iptables - volumes: - - ./common:/common:ro - - ./iptables:/service:ro - entrypoint: common/startup.sh + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-iptables:cb7a8bd6d28602085a88c8ced7d67e28e75781e2 + shareDir: ./common + serviceDir: ./iptables + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh command: service/iptables.sh cap_add: - NET_ADMIN - NET_RAW echo: - image: qt-test-server-echo:b29ad409e746a834c1055fd0f7a55fd5056da6ea - container_name: qt-test-server-echo - domainname: ${TEST_DOMAIN} - hostname: echo - volumes: - - ./common:/common:ro - - ./echo:/service:ro - entrypoint: common/startup.sh - command: service/echo.sh + container_name: qt-test-server-echo + domainname: ${TEST_DOMAIN} + hostname: echo + build: + context: . + dockerfile: ${SHARED_DATA}/Dockerfile + args: + provisioningImage: qt-test-server-echo:b29ad409e746a834c1055fd0f7a55fd5056da6ea + shareDir: ./common + serviceDir: ./echo + test_domain: ${TEST_DOMAIN} + entrypoint: service/startup.sh + command: service/echo.sh From 658f12d7354e82ae552703fa928e1c94315c3a6a Mon Sep 17 00:00:00 2001 From: Ryan Chu Date: Mon, 25 Mar 2019 18:04:26 +0100 Subject: [PATCH 019/122] Expose docker test server as an internal config to all modules Before testserver becomes a stable feature, let's keep testserver.prf in "mkspecs/features/unsupported". The test server's shared files will be stored in "mkspecs/features/data/testserver". Because the path of testserver has been changed, all the tests relying on the docker servers should be updated as well. Change-Id: Id2494d2b58ee2a9522d99ae61c6236021506b876 Reviewed-by: Maurice Kalinowski Reviewed-by: Edward Welbourne --- {tests/auto => mkspecs/features/data/testserver}/Dockerfile | 0 .../features/unsupported/testserver.prf | 6 +++--- .../access/qabstractnetworkcache/qabstractnetworkcache.pro | 2 +- .../qhttpnetworkconnection/qhttpnetworkconnection.pro | 3 +-- tests/auto/network/access/qnetworkreply/test/test.pro | 2 +- .../network/socket/qhttpsocketengine/qhttpsocketengine.pro | 2 +- .../socket/qsocks5socketengine/qsocks5socketengine.pro | 2 +- tests/auto/network/socket/qtcpserver/test/test.pro | 2 +- tests/auto/network/socket/qtcpsocket/test/test.pro | 2 +- tests/auto/network/socket/qudpsocket/test/test.pro | 2 +- tests/auto/network/ssl/qsslsocket/qsslsocket.pro | 2 +- .../qsslsocket_onDemandCertificates_member.pro | 2 +- .../qsslsocket_onDemandCertificates_static.pro | 2 +- 13 files changed, 14 insertions(+), 15 deletions(-) rename {tests/auto => mkspecs/features/data/testserver}/Dockerfile (100%) rename tests/auto/testserver.pri => mkspecs/features/unsupported/testserver.prf (98%) diff --git a/tests/auto/Dockerfile b/mkspecs/features/data/testserver/Dockerfile similarity index 100% rename from tests/auto/Dockerfile rename to mkspecs/features/data/testserver/Dockerfile diff --git a/tests/auto/testserver.pri b/mkspecs/features/unsupported/testserver.prf similarity index 98% rename from tests/auto/testserver.pri rename to mkspecs/features/unsupported/testserver.prf index 1b7ccf5757..6507a360c5 100644 --- a/tests/auto/testserver.pri +++ b/mkspecs/features/unsupported/testserver.prf @@ -102,7 +102,7 @@ isEmpty(TESTSERVER_VERSION) { # The environment variables passed to the docker-compose file TEST_ENV = 'MACHINE_IP=$(shell docker-machine ip qt-test-server)' TEST_ENV += 'TEST_DOMAIN=$$DNSDOMAIN' - TEST_ENV += 'SHARED_DATA=$$PWD' + TEST_ENV += 'SHARED_DATA=$$PWD/../data/testserver' TEST_CMD = env } else:equals(QMAKE_HOST.os, Windows) { # There is no docker bridge on Windows. It is impossible to ping a container. @@ -116,7 +116,7 @@ isEmpty(TESTSERVER_VERSION) { # The environment variables passed to the docker-compose file TEST_ENV = '\$\$env:MACHINE_IP = docker-machine ip qt-test-server;' TEST_ENV += '\$\$env:TEST_DOMAIN = $$shell_quote(\"$$DNSDOMAIN\");' - TEST_ENV += '\$\$env:SHARED_DATA = $$shell_quote(\"$$PWD\");' + TEST_ENV += '\$\$env:SHARED_DATA = $$shell_quote(\"$$PWD/../data/testserver\");' # Docker-compose CLI environment variables: # Enable path conversion from Windows-style to Unix-style in volume definitions. @@ -129,7 +129,7 @@ isEmpty(TESTSERVER_VERSION) { $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compose.yml # The environment variables passed to the docker-compose file TEST_ENV = 'TEST_DOMAIN=$$DNSDOMAIN' - TEST_ENV += 'SHARED_DATA=$$PWD' + TEST_ENV += 'SHARED_DATA=$$PWD/../data/testserver' TEST_CMD = env } !exists($$TESTSERVER_COMPOSE_FILE): error("Invalid TESTSERVER_COMPOSE_FILE specified") diff --git a/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro b/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro index bdd9d4eb7e..c722100ead 100644 --- a/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro +++ b/tests/auto/network/access/qabstractnetworkcache/qabstractnetworkcache.pro @@ -5,5 +5,5 @@ SOURCES += tst_qabstractnetworkcache.cpp TESTDATA += tests/* +CONFIG += unsupported/testserver QT_TEST_SERVER_LIST = apache2 -include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri) diff --git a/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro index 69a4a50144..84e6f857a1 100644 --- a/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro +++ b/tests/auto/network/access/qhttpnetworkconnection/qhttpnetworkconnection.pro @@ -5,6 +5,5 @@ requires(qtConfig(private_tests)) QT = core-private network-private testlib +CONFIG += unsupported/testserver QT_TEST_SERVER_LIST = apache2 -include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri) - diff --git a/tests/auto/network/access/qnetworkreply/test/test.pro b/tests/auto/network/access/qnetworkreply/test/test.pro index 9d36352abc..4cc1f6431e 100644 --- a/tests/auto/network/access/qnetworkreply/test/test.pro +++ b/tests/auto/network/access/qnetworkreply/test/test.pro @@ -15,5 +15,5 @@ TESTDATA += ../empty ../rfc3252.txt ../resource ../bigfile ../*.jpg ../certs \ !android:!winrt: TEST_HELPER_INSTALLS = ../echo/echo +CONFIG += unsupported/testserver QT_TEST_SERVER_LIST = vsftpd apache2 ftp-proxy danted squid -include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri) diff --git a/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro b/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro index 492bb6aa8d..63f41f4eb7 100644 --- a/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro +++ b/tests/auto/network/socket/qhttpsocketengine/qhttpsocketengine.pro @@ -12,6 +12,6 @@ QT = core-private network-private testlib # TODO: For now linux-only, because cyrus is linux-only atm ... linux { + CONFIG += unsupported/testserver QT_TEST_SERVER_LIST = squid danted cyrus apache2 - include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri) } diff --git a/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro b/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro index ca9e44873c..243eab9480 100644 --- a/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro +++ b/tests/auto/network/socket/qsocks5socketengine/qsocks5socketengine.pro @@ -14,6 +14,6 @@ requires(qtConfig(private_tests)) # Only on Linux until cyrus has been added to docker-compose-for-{windows,macOS}.yml and tested linux { + CONFIG += unsupported/testserver QT_TEST_SERVER_LIST = danted apache2 cyrus - include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri) } diff --git a/tests/auto/network/socket/qtcpserver/test/test.pro b/tests/auto/network/socket/qtcpserver/test/test.pro index ac4ed9a989..de02fb032d 100644 --- a/tests/auto/network/socket/qtcpserver/test/test.pro +++ b/tests/auto/network/socket/qtcpserver/test/test.pro @@ -19,6 +19,6 @@ MOC_DIR=tmp # Only on Linux until cyrus has been added to docker-compose-for-{windows,macOS}.yml and tested linux { + CONFIG += unsupported/testserver QT_TEST_SERVER_LIST = danted cyrus squid ftp-proxy - include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri) } diff --git a/tests/auto/network/socket/qtcpsocket/test/test.pro b/tests/auto/network/socket/qtcpsocket/test/test.pro index 29d9414b03..05699bbe4e 100644 --- a/tests/auto/network/socket/qtcpsocket/test/test.pro +++ b/tests/auto/network/socket/qtcpsocket/test/test.pro @@ -18,6 +18,6 @@ win32 { # Only on Linux until cyrus has been added to docker-compose-for-{windows,macOS}.yml and tested linux { + CONFIG += unsupported/testserver QT_TEST_SERVER_LIST = danted squid apache2 ftp-proxy vsftpd iptables cyrus - include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri) } diff --git a/tests/auto/network/socket/qudpsocket/test/test.pro b/tests/auto/network/socket/qudpsocket/test/test.pro index 0fdb97ba27..969e4d72cf 100644 --- a/tests/auto/network/socket/qudpsocket/test/test.pro +++ b/tests/auto/network/socket/qudpsocket/test/test.pro @@ -20,6 +20,6 @@ TARGET = tst_qudpsocket # Only on Linux until 'echo' has been added to docker-compose-for-{windows,macOS}.yml and tested linux { + CONFIG += unsupported/testserver QT_TEST_SERVER_LIST = danted echo - include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri) } diff --git a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro index 03fbe89002..51fcff9a8d 100644 --- a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro +++ b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro @@ -22,6 +22,6 @@ requires(qtConfig(private_tests)) # DOCKERTODO: it's 'linux' because it requires cyrus, which # is linux-only for now ... linux { + CONFIG += unsupported/testserver QT_TEST_SERVER_LIST = squid danted cyrus apache2 echo - include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri) } diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro index 3e3ebeb358..8585a3c861 100644 --- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro +++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_member/qsslsocket_onDemandCertificates_member.pro @@ -20,6 +20,6 @@ requires(qtConfig(private_tests)) # DOCKERTODO: linux, docker is disabled on macOS/Windows. linux { + CONFIG += unsupported/testserver QT_TEST_SERVER_LIST = squid danted - include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri) } diff --git a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro index 1ad42b309e..158ecbee37 100644 --- a/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro +++ b/tests/auto/network/ssl/qsslsocket_onDemandCertificates_static/qsslsocket_onDemandCertificates_static.pro @@ -19,6 +19,6 @@ requires(qtConfig(private_tests)) #DOCKERTODO Linux, docker is disabled on macOS and Windows. linux { + CONFIG += unsupported/testserver QT_TEST_SERVER_LIST = squid danted - include($$dirname(_QMAKE_CONF_)/tests/auto/testserver.pri) } From 220028d37c38835987b817193ecaf0e2a1ad066b Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Tue, 5 Mar 2019 22:39:27 +0100 Subject: [PATCH 020/122] QtBase: introduce QT_DEPRECATED_VERSION/QT_DEPRECATED_VERSION_X QT_DEPRECATED_VERSION(major, minor) and QT_DEPRECATED_VERSION_X(major, minor, text) outputs a deprecation warning if QT_DEPRECATED_WARNINGS_SINCE is equal or greater than the version specified as major, minor. This allows the user to hide deprecation warnings which can't yet be fixed for their codebase because the minimum required Qt version does not provide the replacement function. If QT_DEPRECATED_WARNINGS_SINCE is not set by the user, it's set to QT_DISABLE_DEPRECATED_BEFORE if available, otherwise to QT_VERSION. [ChangeLog][QtCore][QtGlobal] Add new macros QT_DEPRECATED_VERSION and QT_DEPRECATED_VERSION_X to conditionally display deprecation warnings Change-Id: I61b1a7624c9b870695c9e3274313de636f804b5d Reviewed-by: Konstantin Shegunov Reviewed-by: Edward Welbourne Reviewed-by: hjk --- mkspecs/features/qt_module.prf | 1 + src/corelib/global/qglobal.h | 53 +++++++++++++++++++++++++++++++++ src/widgets/widgets/qcombobox.h | 6 ++-- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index 51b5bde67a..8bd2d92421 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -317,5 +317,6 @@ win32 { # On other platforms, Qt's own compilation goes needs to compile the Qt 5.0 API DEFINES *= QT_DISABLE_DEPRECATED_BEFORE=0x050000 } +DEFINES *= QT_DEPRECATED_WARNINGS_SINCE=0x060000 TARGET = $$qt5LibraryTarget($$TARGET$$QT_LIBINFIX) # Do this towards the end diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index a0207b483d..3c17bbb2d4 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -307,6 +307,14 @@ typedef double qreal; # define QT_DEPRECATED_CONSTRUCTOR #endif +#ifndef QT_DEPRECATED_WARNINGS_SINCE +# ifdef QT_DISABLE_DEPRECATED_BEFORE +# define QT_DEPRECATED_WARNINGS_SINCE QT_DISABLE_DEPRECATED_BEFORE +# else +# define QT_DEPRECATED_WARNINGS_SINCE QT_VERSION +# endif +#endif + #ifndef QT_DISABLE_DEPRECATED_BEFORE #define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(5, 0, 0) #endif @@ -329,6 +337,51 @@ typedef double qreal; #define QT_DEPRECATED_SINCE(major, minor) 0 #endif +/* + QT_DEPRECATED_VERSION(major, minor) and QT_DEPRECATED_VERSION_X(major, minor, text) + outputs a deprecation warning if QT_DEPRECATED_WARNINGS_SINCE is equal or greater + than the version specified as major, minor. This makes it possible to deprecate a + function without annoying a user who needs to stick at a specified minimum version + and therefore can't use the new function. +*/ +#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 12, 0) +# define QT_DEPRECATED_VERSION_X_5_12(text) QT_DEPRECATED_X(text) +# define QT_DEPRECATED_VERSION_5_12 QT_DEPRECATED +#else +# define QT_DEPRECATED_VERSION_X_5_12(text) +# define QT_DEPRECATED_VERSION_5_12 +#endif + +#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 13, 0) +# define QT_DEPRECATED_VERSION_X_5_13(text) QT_DEPRECATED_X(text) +# define QT_DEPRECATED_VERSION_5_13 QT_DEPRECATED +#else +# define QT_DEPRECATED_VERSION_X_5_13(text) +# define QT_DEPRECATED_VERSION_5_13 +#endif + +#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 14, 0) +# define QT_DEPRECATED_VERSION_X_5_14(text) QT_DEPRECATED_X(text) +# define QT_DEPRECATED_VERSION_5_14 QT_DEPRECATED +#else +# define QT_DEPRECATED_VERSION_X_5_14(text) +# define QT_DEPRECATED_VERSION_5_14 +#endif + +#if QT_DEPRECATED_WARNINGS_SINCE >= QT_VERSION_CHECK(5, 15, 0) +# define QT_DEPRECATED_VERSION_X_5_15(text) QT_DEPRECATED_X(text) +# define QT_DEPRECATED_VERSION_5_15 QT_DEPRECATED +#else +# define QT_DEPRECATED_VERSION_X_5_15(text) +# define QT_DEPRECATED_VERSION_5_15 +#endif + +#define QT_DEPRECATED_VERSION_X_5(minor, text) QT_DEPRECATED_VERSION_X_5_##minor(text) +#define QT_DEPRECATED_VERSION_X(major, minor, text) QT_DEPRECATED_VERSION_X_##major(minor, text) + +#define QT_DEPRECATED_VERSION_5(minor) QT_DEPRECATED_VERSION_5_##minor() +#define QT_DEPRECATED_VERSION(major, minor) QT_DEPRECATED_VERSION_##major(minor) + /* The Qt modules' export macros. The options are: diff --git a/src/widgets/widgets/qcombobox.h b/src/widgets/widgets/qcombobox.h index 6a87a675a4..37b155774d 100644 --- a/src/widgets/widgets/qcombobox.h +++ b/src/widgets/widgets/qcombobox.h @@ -226,13 +226,13 @@ Q_SIGNALS: void currentIndexChanged(int index); void currentTextChanged(const QString &); #if QT_DEPRECATED_SINCE(5, 13) - QT_DEPRECATED_X("Use currentTextChanged() instead") + QT_DEPRECATED_VERSION_X(5, 13, "Use currentTextChanged() instead") void currentIndexChanged(const QString &); #endif #if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_X("Use textActivated() instead") + QT_DEPRECATED_VERSION_X(5, 15, "Use textActivated() instead") void activated(const QString &); - QT_DEPRECATED_X("Use textHighlighted() instead") + QT_DEPRECATED_VERSION_X(5, 15, "Use textHighlighted() instead") void highlighted(const QString &); #endif From c530ca1c170798159c3d84029841a1224d1cdc65 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 3 Mar 2019 12:14:43 +0100 Subject: [PATCH 021/122] QLineF: add intersects() as a replacement for intersect() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QLineF::intersect() does not follow the naming rules for functions. Therefore add a replacement function intersects() instead and also rename the return type from IntersectType to IntersectionType [ChangeLog][QtCore][QLineF] added QLineF::intersects() as a replacement for QLineF::intersect() Change-Id: I744b960ea339cb817facb12f296f78cca3e7d938 Reviewed-by: Jędrzej Nowacki Reviewed-by: Konstantin Shegunov --- .../graphicsview/diagramscene/arrow.cpp | 12 ++++----- src/corelib/tools/qline.cpp | 26 ++++++++++++++++++- src/corelib/tools/qline.h | 6 +++-- src/gui/painting/qstroker.cpp | 2 +- tests/auto/corelib/tools/qline/tst_qline.cpp | 2 +- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/examples/widgets/graphicsview/diagramscene/arrow.cpp b/examples/widgets/graphicsview/diagramscene/arrow.cpp index 88160d9399..525e0b3fbb 100644 --- a/examples/widgets/graphicsview/diagramscene/arrow.cpp +++ b/examples/widgets/graphicsview/diagramscene/arrow.cpp @@ -113,15 +113,13 @@ void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QLineF centerLine(myStartItem->pos(), myEndItem->pos()); QPolygonF endPolygon = myEndItem->polygon(); QPointF p1 = endPolygon.first() + myEndItem->pos(); - QPointF p2; QPointF intersectPoint; - QLineF polyLine; for (int i = 1; i < endPolygon.count(); ++i) { - p2 = endPolygon.at(i) + myEndItem->pos(); - polyLine = QLineF(p1, p2); - QLineF::IntersectType intersectType = - polyLine.intersect(centerLine, &intersectPoint); - if (intersectType == QLineF::BoundedIntersection) + QPointF p2 = endPolygon.at(i) + myEndItem->pos(); + QLineF polyLine = QLineF(p1, p2); + QLineF::IntersectionType intersectionType = + polyLine.intersects(centerLine, &intersectPoint); + if (intersectionType == QLineF::BoundedIntersection) break; p1 = p2; } diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp index 6f3c22a6ec..3afd23d76b 100644 --- a/src/corelib/tools/qline.cpp +++ b/src/corelib/tools/qline.cpp @@ -347,7 +347,7 @@ QDataStream &operator>>(QDataStream &stream, QLine &line) function to determine whether the QLineF represents a valid line or a null line. - The intersect() function determines the IntersectType for this + The intersects() function determines the IntersectionType for this line and a given line, while the angleTo() function returns the angle between the lines. In addition, the unitVector() function returns a line that has the same starting point as this line, but @@ -370,6 +370,11 @@ QDataStream &operator>>(QDataStream &stream, QLine &line) /*! \enum QLineF::IntersectType + \obsolete Use QLineF::IntersectionType instead +*/ + +/*! + \enum QLineF::IntersectionType Describes the intersection between two lines. @@ -657,8 +662,10 @@ QLineF QLineF::unitVector() const return f; } +#if QT_DEPRECATED_SINCE(5, 14) /*! \fn QLineF::IntersectType QLineF::intersect(const QLineF &line, QPointF *intersectionPoint) const + \obsolete Use intersects() instead Returns a value indicating whether or not \e this line intersects with the given \a line. @@ -669,6 +676,23 @@ QLineF QLineF::unitVector() const */ QLineF::IntersectType QLineF::intersect(const QLineF &l, QPointF *intersectionPoint) const +{ + return intersects(l, intersectionPoint); +} +#endif + +/*! + \fn QLineF::IntersectionType QLineF::intersects(const QLineF &line, QPointF *intersectionPoint) const + \since 5.14 + + Returns a value indicating whether or not \e this line intersects + with the given \a line. + + The actual intersection point is extracted to \a intersectionPoint + (if the pointer is valid). If the lines are parallel, the + intersection point is undefined. +*/ +QLineF::IntersectionType QLineF::intersects(const QLineF &l, QPointF *intersectionPoint) const { // ipmlementation is based on Graphics Gems III's "Faster Line Segment Intersection" const QPointF a = pt2 - pt1; diff --git a/src/corelib/tools/qline.h b/src/corelib/tools/qline.h index 14980b60a0..c96d624afd 100644 --- a/src/corelib/tools/qline.h +++ b/src/corelib/tools/qline.h @@ -215,6 +215,7 @@ class Q_CORE_EXPORT QLineF { public: enum IntersectType { NoIntersection, BoundedIntersection, UnboundedIntersection }; + using IntersectionType = IntersectType; Q_DECL_CONSTEXPR inline QLineF(); Q_DECL_CONSTEXPR inline QLineF(const QPointF &pt1, const QPointF &pt2); @@ -248,10 +249,11 @@ public: Q_REQUIRED_RESULT QLineF unitVector() const; Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QLineF normalVector() const; - // ### Qt 6: rename intersects() or intersection() and rename IntersectType IntersectionType - IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const; + IntersectionType intersects(const QLineF &l, QPointF *intersectionPoint) const; #if QT_DEPRECATED_SINCE(5, 14) + QT_DEPRECATED_VERSION_X(5, 14, "Use intersects() instead") + IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const; QT_DEPRECATED_X("Use angleTo() instead, take care that the return value is between 0 and 360 degree.") qreal angle(const QLineF &l) const; #endif diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp index f8f8d72d14..f158222f82 100644 --- a/src/gui/painting/qstroker.cpp +++ b/src/gui/painting/qstroker.cpp @@ -456,7 +456,7 @@ void QStroker::joinPoints(qfixed focal_x, qfixed focal_y, const QLineF &nextLine QLineF prevLine(qt_fixed_to_real(m_back2X), qt_fixed_to_real(m_back2Y), qt_fixed_to_real(m_back1X), qt_fixed_to_real(m_back1Y)); QPointF isect; - QLineF::IntersectType type = prevLine.intersect(nextLine, &isect); + QLineF::IntersectionType type = prevLine.intersects(nextLine, &isect); if (join == FlatJoin) { QLineF shortCut(prevLine.p2(), nextLine.p1()); diff --git a/tests/auto/corelib/tools/qline/tst_qline.cpp b/tests/auto/corelib/tools/qline/tst_qline.cpp index ae65d8f697..915a24a1f6 100644 --- a/tests/auto/corelib/tools/qline/tst_qline.cpp +++ b/tests/auto/corelib/tools/qline/tst_qline.cpp @@ -205,7 +205,7 @@ void tst_QLine::testIntersection() QPointF ip; - QLineF::IntersectType itype = a.intersect(b, &ip); + QLineF::IntersectionType itype = a.intersect(b, &ip); QCOMPARE(int(itype), type); if (type != QLineF::NoIntersection) { From e092b32922ef650d49167aaf48f9d33190191f9f Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 23 Apr 2019 07:48:50 +0200 Subject: [PATCH 022/122] QTextMarkdownImporter: insert list items into the correct list There was a bug when handling situations like 1. first 1) subfirst 2. second It was always inserting items into the list where the cursor already was, but it needs to insert the "second" list item into the list which is currently the top of m_listStack. Change-Id: Id0899032efafb2e2b9e7c45a6fb9f2c5221fc4df Reviewed-by: Gatis Paeglis --- src/gui/text/qtextmarkdownimporter.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index 6bff337ff4..2477e0bc74 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -165,13 +165,14 @@ int QTextMarkdownImporter::cbEnterBlock(MD_BLOCKTYPE type, void *det) } break; case MD_BLOCK_LI: { MD_BLOCK_LI_DETAIL *detail = static_cast(det); - QTextBlockFormat bfmt = m_cursor->blockFormat(); + QTextList *list = m_listStack.top(); + QTextBlockFormat bfmt = list->item(list->count() - 1).blockFormat(); bfmt.setMarker(detail->is_task ? (detail->task_mark == ' ' ? QTextBlockFormat::Unchecked : QTextBlockFormat::Checked) : QTextBlockFormat::NoMarker); if (!m_emptyList) { m_cursor->insertBlock(bfmt, QTextCharFormat()); - m_listStack.top()->add(m_cursor->block()); + list->add(m_cursor->block()); } m_cursor->setBlockFormat(bfmt); m_emptyList = false; // Avoid insertBlock for the first item (because insertList already did that) From 8059762565d1ed6b7aaee2729d3a637efcd671d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Thu, 25 Apr 2019 17:30:36 +0200 Subject: [PATCH 023/122] Set 'originalRequest' in QNetworkReplyImpl It's what's returned when calling request() on a QNetworkReply, but for QNetworkReplyImpl (the implementation used for e.g. FTP) it was not set, so it returned a default object. Change-Id: Id82f7920e4268c1a7743e681fc503bcd28889b6e Reviewed-by: Thiago Macieira Reviewed-by: Markus Goetz (Woboq GmbH) Reviewed-by: Edward Welbourne --- src/network/access/qnetworkreplyimpl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index a794b492e7..f5bb4d5887 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -368,6 +368,7 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const outgoingData = data; request = req; + originalRequest = req; url = request.url(); operation = op; From 9a6a84731131b205f74b10f866ae212e0895bd4a Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Tue, 18 Dec 2018 16:41:39 +0100 Subject: [PATCH 024/122] Add RISC-V detection Change-Id: I0203c88e0944064841c9f6fe9f8a7888d6c421d1 Reviewed-by: Giuseppe D'Angelo Reviewed-by: Thiago Macieira --- src/corelib/global/archdetect.cpp | 4 +++ src/corelib/global/qglobal.cpp | 36 ++++++++++++++++++++++++ src/corelib/global/qprocessordetection.h | 14 +++++++++ 3 files changed, 54 insertions(+) diff --git a/src/corelib/global/archdetect.cpp b/src/corelib/global/archdetect.cpp index 66a5e074f6..1d00b7f5a5 100644 --- a/src/corelib/global/archdetect.cpp +++ b/src/corelib/global/archdetect.cpp @@ -67,6 +67,10 @@ # define ARCH_PROCESSOR "power" #elif defined(Q_PROCESSOR_POWER_64) # define ARCH_PROCESSOR "power64" +#elif defined(Q_PROCESSOR_RISCV_32) +# define ARCH_PROCESSOR "riscv32" +#elif defined(Q_PROCESSOR_RISCV_64) +# define ARCH_PROCESSOR "riscv64" #elif defined(Q_PROCESSOR_S390_X) # define ARCH_PROCESSOR "s390x" #elif defined(Q_PROCESSOR_S390) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index d95064af27..16d8d8b8ac 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1883,6 +1883,42 @@ bool qSharedBuild() noexcept \sa QSysInfo::buildCpuArchitecture() */ +/*! + \macro Q_PROCESSOR_RISCV + \relates + \since 5.13 + + Defined if the application is compiled for RISC-V processors. Qt currently + supports two RISC-V variants: \l Q_PROCESSOR_RISCV_32 and \l + Q_PROCESSOR_RISCV_64. + + \sa QSysInfo::buildCpuArchitecture() +*/ + +/*! + \macro Q_PROCESSOR_RISCV_32 + \relates + \since 5.13 + + Defined if the application is compiled for 32-bit RISC-V processors. The \l + Q_PROCESSOR_RISCV macro is also defined when Q_PROCESSOR_RISCV_32 is + defined. + + \sa QSysInfo::buildCpuArchitecture() +*/ + +/*! + \macro Q_PROCESSOR_RISCV_64 + \relates + \since 5.13 + + Defined if the application is compiled for 64-bit RISC-V processors. The \l + Q_PROCESSOR_RISCV macro is also defined when Q_PROCESSOR_RISCV_64 is + defined. + + \sa QSysInfo::buildCpuArchitecture() +*/ + /*! \macro Q_PROCESSOR_S390 \relates diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h index 1f327c352e..8d65720850 100644 --- a/src/corelib/global/qprocessordetection.h +++ b/src/corelib/global/qprocessordetection.h @@ -281,6 +281,20 @@ # endif // Q_BYTE_ORDER not defined, use endianness auto-detection +/* + RISC-V family, known variants: 32- and 64-bit + + RISC-V is little-endian. +*/ +#elif defined(__riscv) +# define Q_PROCESSOR_RISCV +# if __riscv_xlen == 64 +# define Q_PROCESSOR_RISCV_64 +# else +# define Q_PROCESSOR_RISCV_32 +# endif +# define Q_BYTE_ORDER Q_LITTLE_ENDIAN + /* S390 family, known variant: S390X (64-bit) From 8e82e536cdbf2b6c36a7eabd6fba1a85613973f8 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Tue, 19 Mar 2019 11:41:53 +0100 Subject: [PATCH 025/122] FTP: Workaround for servers without HELP command support Ignores errors produced by the HELP command. It will continue executing the commands sent to QFtp when a server does not have a HELP command implemented. Commands SIZE, MDTM, and PWD are not going to be used if the HELP command failed. [ChangeLog][QtNetwork][QNetworkAccessManager] Don't fail when FTP does not implement the HELP command. Task-number: QTBUG-69477 Change-Id: I0ebd51b134535730c6bef83de1abf1a427b8d2ce Reviewed-by: Thiago Macieira Reviewed-by: Edward Welbourne --- src/network/access/qftp.cpp | 11 +++++++++++ src/network/access/qftp_p.h | 3 +++ src/network/access/qnetworkaccessftpbackend.cpp | 7 ++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp index 4e399f018f..b6b721030b 100644 --- a/src/network/access/qftp.cpp +++ b/src/network/access/qftp.cpp @@ -2122,6 +2122,17 @@ void QFtp::abort() d_func()->pi.abort(); } +/*! + \internal + Clears the last error. + + \sa currentCommand() +*/ +void QFtp::clearError() +{ + d_func()->error = NoError; +} + /*! \internal Returns the identifier of the FTP command that is being executed diff --git a/src/network/access/qftp_p.h b/src/network/access/qftp_p.h index 91d78d1351..a55429933b 100644 --- a/src/network/access/qftp_p.h +++ b/src/network/access/qftp_p.h @@ -157,6 +157,9 @@ Q_SIGNALS: void commandFinished(int, bool); void done(bool); +protected: + void clearError(); + private: Q_DISABLE_COPY_MOVE(QFtp) Q_DECLARE_PRIVATE(QFtp) diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index 5ad820eba0..51ed2f5a55 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -99,6 +99,8 @@ public: connect(this, SIGNAL(done(bool)), this, SLOT(deleteLater())); close(); } + + using QFtp::clearError; }; QNetworkAccessFtpBackend::QNetworkAccessFtpBackend() @@ -282,7 +284,10 @@ void QNetworkAccessFtpBackend::ftpDone() } // check for errors: - if (ftp->error() != QFtp::NoError) { + if (state == CheckingFeatures && ftp->error() == QFtp::UnknownError) { + qWarning("QNetworkAccessFtpBackend: HELP command failed, ignoring it"); + ftp->clearError(); + } else if (ftp->error() != QFtp::NoError) { QString msg; if (operation() == QNetworkAccessManager::GetOperation) msg = tr("Error while downloading %1: %2"); From 8e2895557471538afc4610c4340701a39d59a851 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Tue, 2 Oct 2018 11:44:49 +0200 Subject: [PATCH 026/122] Plug and paint example: Fix -Wweak-tables Fixes warning: 'BrushInterface' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit Change-Id: I2e693ac60e9eba1976665546e1c9c4a92e6ff63b Reviewed-by: Paul Wicking Reviewed-by: Richard Moe Gustavsen --- examples/widgets/tools/plugandpaint/app/interfaces.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/widgets/tools/plugandpaint/app/interfaces.h b/examples/widgets/tools/plugandpaint/app/interfaces.h index a1e91e13ff..705e578809 100644 --- a/examples/widgets/tools/plugandpaint/app/interfaces.h +++ b/examples/widgets/tools/plugandpaint/app/interfaces.h @@ -68,7 +68,7 @@ QT_END_NAMESPACE class BrushInterface { public: - virtual ~BrushInterface() {} + virtual ~BrushInterface() = default; virtual QStringList brushes() const = 0; virtual QRect mousePress(const QString &brush, QPainter &painter, @@ -84,7 +84,7 @@ public: class ShapeInterface { public: - virtual ~ShapeInterface() {} + virtual ~ShapeInterface() = default; virtual QStringList shapes() const = 0; virtual QPainterPath generateShape(const QString &shape, @@ -96,7 +96,7 @@ public: class FilterInterface { public: - virtual ~FilterInterface() {} + virtual ~FilterInterface() = default; virtual QStringList filters() const = 0; virtual QImage filterImage(const QString &filter, const QImage &image, From d647cf85fa3813a65921266a9998cd2e54e5f2f9 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Fri, 5 Oct 2018 14:53:18 +0200 Subject: [PATCH 027/122] Tests: Simplify MyCookieJar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't reimplement the protected functions in the base class just override the access with the using keyword. Change-Id: I323487d9ddb1d458d5faca020c3eb4d931a9b226 Reviewed-by: Mårten Nordheim Reviewed-by: Edward Welbourne --- .../access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp index 45abb6aa05..1ef2c118b9 100644 --- a/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp +++ b/tests/auto/network/access/qnetworkcookiejar/tst_qnetworkcookiejar.cpp @@ -61,10 +61,8 @@ class MyCookieJar: public QNetworkCookieJar { public: ~MyCookieJar() override; - inline QList allCookies() const - { return QNetworkCookieJar::allCookies(); } - inline void setAllCookies(const QList &cookieList) - { QNetworkCookieJar::setAllCookies(cookieList); } + using QNetworkCookieJar::allCookies; + using QNetworkCookieJar::setAllCookies; }; MyCookieJar::~MyCookieJar() = default; From dc3e5c48380ff564df9a232b13e2cf1fab65f66d Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Wed, 24 Apr 2019 17:06:15 +0200 Subject: [PATCH 028/122] Consolidate Unix and Windows implementations of QHostInfo::fromName The implementations were practically identical, so we can just move the code into qhostinfo.cpp, cleaning up things along the way. Since QHostInfoAgent is an internal class, add the shared code as additional static helper functions. And since half the code already used QCoreApplication::translate anyway, we can remove the QObject inheritance which was only added for getting a tr(). Change-Id: I58eafbdc3e7d06d2e898486a1add63cd63d98c96 Reviewed-by: Thiago Macieira --- src/network/kernel/qhostinfo.cpp | 168 ++++++++++++++++++++++++++ src/network/kernel/qhostinfo_p.h | 7 +- src/network/kernel/qhostinfo_unix.cpp | 139 +-------------------- src/network/kernel/qhostinfo_win.cpp | 111 +---------------- 4 files changed, 178 insertions(+), 247 deletions(-) diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index d3fe85f5d5..9374728244 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -37,8 +37,11 @@ ** ****************************************************************************/ +//#define QHOSTINFO_DEBUG + #include "qhostinfo.h" #include "qhostinfo_p.h" +#include #include "QtCore/qscopedpointer.h" #include @@ -53,6 +56,15 @@ #ifdef Q_OS_UNIX # include +# include +# include +# if defined(AI_ADDRCONFIG) +# define Q_ADDRCONFIG AI_ADDRCONFIG +# endif +#elif defined Q_OS_WIN +# include + +# define QT_SOCKLEN_T int #endif QT_BEGIN_NAMESPACE @@ -412,6 +424,162 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer(&sa4); + saSize = sizeof(sa4); + memset(&sa4, 0, sizeof(sa4)); + sa4.sin_family = AF_INET; + sa4.sin_addr.s_addr = htonl(address.toIPv4Address()); + } else { + sa = reinterpret_cast(&sa6); + saSize = sizeof(sa6); + memset(&sa6, 0, sizeof(sa6)); + sa6.sin6_family = AF_INET6; + memcpy(&sa6.sin6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr)); + } + + char hbuf[NI_MAXHOST]; + if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), nullptr, 0, 0) == 0) + results.setHostName(QString::fromLatin1(hbuf)); + + if (results.hostName().isEmpty()) + results.setHostName(address.toString()); + results.setAddresses(QList() << address); + + return results; +} + +/* + Call getaddrinfo, and returns the results as QHostInfo::addresses +*/ +QHostInfo QHostInfoAgent::lookup(const QString &hostName) +{ + QHostInfo results; + + // IDN support + QByteArray aceHostname = QUrl::toAce(hostName); + results.setHostName(hostName); + if (aceHostname.isEmpty()) { + results.setError(QHostInfo::HostNotFound); + results.setErrorString(hostName.isEmpty() ? + QCoreApplication::translate("QHostInfoAgent", "No host name given") : + QCoreApplication::translate("QHostInfoAgent", "Invalid hostname")); + return results; + } + + addrinfo *res = 0; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef Q_ADDRCONFIG + hints.ai_flags = Q_ADDRCONFIG; +#endif + + int result = getaddrinfo(aceHostname.constData(), nullptr, &hints, &res); +# ifdef Q_ADDRCONFIG + if (result == EAI_BADFLAGS) { + // if the lookup failed with AI_ADDRCONFIG set, try again without it + hints.ai_flags = 0; + result = getaddrinfo(aceHostname.constData(), nullptr, &hints, &res); + } +# endif + + if (result == 0) { + addrinfo *node = res; + QList addresses; + while (node) { +#ifdef QHOSTINFO_DEBUG + qDebug() << "getaddrinfo node: flags:" << node->ai_flags << "family:" << node->ai_family + << "ai_socktype:" << node->ai_socktype << "ai_protocol:" << node->ai_protocol + << "ai_addrlen:" << node->ai_addrlen; +#endif + switch (node->ai_family) { + case AF_INET: { + QHostAddress addr; + addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr)); + if (!addresses.contains(addr)) + addresses.append(addr); + break; + } + case AF_INET6: { + QHostAddress addr; + sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr; + addr.setAddress(sa6->sin6_addr.s6_addr); + if (sa6->sin6_scope_id) + addr.setScopeId(QString::number(sa6->sin6_scope_id)); + if (!addresses.contains(addr)) + addresses.append(addr); + break; + } + default: + results.setError(QHostInfo::UnknownError); + results.setErrorString(QCoreApplication::translate("QHostInfoAgent", "Unknown address type")); + } + node = node->ai_next; + } + if (addresses.isEmpty()) { + // Reached the end of the list, but no addresses were found; this + // means the list contains one or more unknown address types. + results.setError(QHostInfo::UnknownError); + results.setErrorString(QCoreApplication::translate("QHostInfoAgent", "Unknown address type")); + } + + results.setAddresses(addresses); + freeaddrinfo(res); + } else { + switch (result) { +#ifdef Q_OS_WIN + case WSAHOST_NOT_FOUND: //authoritative not found + case WSATRY_AGAIN: //non authoritative not found + case WSANO_DATA: //valid name, no associated address +#else + case EAI_NONAME: + case EAI_FAIL: +# ifdef EAI_NODATA // EAI_NODATA is deprecated in RFC 3493 + case EAI_NODATA: +# endif +#endif + results.setError(QHostInfo::HostNotFound); + results.setErrorString(QCoreApplication::translate("QHostInfoAgent", "Host not found")); + break; + default: + results.setError(QHostInfo::UnknownError); +#ifdef Q_OS_WIN + results.setErrorString(QString::fromWCharArray(gai_strerror(result))); +#else + results.setErrorString(QString::fromLocal8Bit(gai_strerror(result))); +#endif + break; + } + } + +#if defined(QHOSTINFO_DEBUG) + if (results.error() != QHostInfo::NoError) { + qDebug("QHostInfoAgent::fromName(): error #%d %s", + h_errno, results.errorString().toLatin1().constData()); + } else { + QString tmp; + QList addresses = results.addresses(); + for (int i = 0; i < addresses.count(); ++i) { + if (i != 0) tmp += QLatin1String(", "); + tmp += addresses.at(i).toString(); + } + qDebug("QHostInfoAgent::fromName(): found %i entries for \"%s\": {%s}", + addresses.count(), aceHostname.constData(), + tmp.toLatin1().constData()); + } +#endif + + return results; +} /*! \enum QHostInfo::HostInfoError diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index da02163ddf..3c0ee2a0d8 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -127,15 +127,16 @@ Q_SIGNALS: void resultsReady(const QHostInfo &info); }; -// needs to be QObject because fromName calls tr() -class QHostInfoAgent : public QObject +class QHostInfoAgent { - Q_OBJECT public: static QHostInfo fromName(const QString &hostName); #ifndef QT_NO_BEARERMANAGEMENT static QHostInfo fromName(const QString &hostName, QSharedPointer networkSession); #endif +private: + static QHostInfo lookup(const QString &hostName); + static QHostInfo reverseLookup(const QHostAddress &address); }; class QHostInfoPrivate diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index e4810d68ee..78a05f8407 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -72,17 +72,6 @@ QT_BEGIN_NAMESPACE -// Almost always the same. If not, specify in qplatformdefs.h. -#if !defined(QT_SOCKOPTLEN_T) -# define QT_SOCKOPTLEN_T QT_SOCKLEN_T -#endif - -// HP-UXi has a bug in getaddrinfo(3) that makes it thread-unsafe -// with this flag. So disable it in that platform. -#if defined(AI_ADDRCONFIG) && !defined(Q_OS_HPUX) -# define Q_ADDRCONFIG AI_ADDRCONFIG -#endif - enum LibResolvFeature { NeedResInit, NeedResNInit @@ -197,132 +186,10 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) local_res_init(); QHostAddress address; - if (address.setAddress(hostName)) { - // Reverse lookup - sockaddr_in sa4; - sockaddr_in6 sa6; - sockaddr *sa = 0; - QT_SOCKLEN_T saSize = 0; - if (address.protocol() == QAbstractSocket::IPv4Protocol) { - sa = (sockaddr *)&sa4; - saSize = sizeof(sa4); - memset(&sa4, 0, sizeof(sa4)); - sa4.sin_family = AF_INET; - sa4.sin_addr.s_addr = htonl(address.toIPv4Address()); - } - else { - sa = (sockaddr *)&sa6; - saSize = sizeof(sa6); - memset(&sa6, 0, sizeof(sa6)); - sa6.sin6_family = AF_INET6; - memcpy(sa6.sin6_addr.s6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr.s6_addr)); - } + if (address.setAddress(hostName)) + return reverseLookup(address); - char hbuf[NI_MAXHOST]; - if (sa && getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0) - results.setHostName(QString::fromLatin1(hbuf)); - - if (results.hostName().isEmpty()) - results.setHostName(address.toString()); - results.setAddresses(QList() << address); - return results; - } - - // IDN support - QByteArray aceHostname = QUrl::toAce(hostName); - results.setHostName(hostName); - if (aceHostname.isEmpty()) { - results.setError(QHostInfo::HostNotFound); - results.setErrorString(hostName.isEmpty() ? - QCoreApplication::translate("QHostInfoAgent", "No host name given") : - QCoreApplication::translate("QHostInfoAgent", "Invalid hostname")); - return results; - } - - // Call getaddrinfo, and place all IPv4 addresses at the start and - // the IPv6 addresses at the end of the address list in results. - addrinfo *res = 0; - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; -#ifdef Q_ADDRCONFIG - hints.ai_flags = Q_ADDRCONFIG; -#endif - - int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); -# ifdef Q_ADDRCONFIG - if (result == EAI_BADFLAGS) { - // if the lookup failed with AI_ADDRCONFIG set, try again without it - hints.ai_flags = 0; - result = getaddrinfo(aceHostname.constData(), 0, &hints, &res); - } -# endif - - if (result == 0) { - addrinfo *node = res; - QList addresses; - while (node) { -#ifdef QHOSTINFO_DEBUG - qDebug() << "getaddrinfo node: flags:" << node->ai_flags << "family:" << node->ai_family << "ai_socktype:" << node->ai_socktype << "ai_protocol:" << node->ai_protocol << "ai_addrlen:" << node->ai_addrlen; -#endif - if (node->ai_family == AF_INET) { - QHostAddress addr; - addr.setAddress(ntohl(((sockaddr_in *) node->ai_addr)->sin_addr.s_addr)); - if (!addresses.contains(addr)) - addresses.append(addr); - } - else if (node->ai_family == AF_INET6) { - QHostAddress addr; - sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr; - addr.setAddress(sa6->sin6_addr.s6_addr); - if (sa6->sin6_scope_id) - addr.setScopeId(QString::number(sa6->sin6_scope_id)); - if (!addresses.contains(addr)) - addresses.append(addr); - } - node = node->ai_next; - } - if (addresses.isEmpty() && node == 0) { - // Reached the end of the list, but no addresses were found; this - // means the list contains one or more unknown address types. - results.setError(QHostInfo::UnknownError); - results.setErrorString(tr("Unknown address type")); - } - - results.setAddresses(addresses); - freeaddrinfo(res); - } else if (result == EAI_NONAME - || result == EAI_FAIL -#ifdef EAI_NODATA - // EAI_NODATA is deprecated in RFC 3493 - || result == EAI_NODATA -#endif - ) { - results.setError(QHostInfo::HostNotFound); - results.setErrorString(tr("Host not found")); - } else { - results.setError(QHostInfo::UnknownError); - results.setErrorString(QString::fromLocal8Bit(gai_strerror(result))); - } - - -#if defined(QHOSTINFO_DEBUG) - if (results.error() != QHostInfo::NoError) { - qDebug("QHostInfoAgent::fromName(): error #%d %s", - h_errno, results.errorString().toLatin1().constData()); - } else { - QString tmp; - QList addresses = results.addresses(); - for (int i = 0; i < addresses.count(); ++i) { - if (i != 0) tmp += ", "; - tmp += addresses.at(i).toString(); - } - qDebug("QHostInfoAgent::fromName(): found %i entries for \"%s\": {%s}", - addresses.count(), hostName.toLatin1().constData(), - tmp.toLatin1().constData()); - } -#endif - return results; + return lookup(hostName); } QString QHostInfo::localDomainName() diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp index ef7cff46f1..0b5cc98970 100644 --- a/src/network/kernel/qhostinfo_win.cpp +++ b/src/network/kernel/qhostinfo_win.cpp @@ -51,27 +51,10 @@ QT_BEGIN_NAMESPACE //#define QHOSTINFO_DEBUG //### -#define QT_SOCKLEN_T int #ifndef NI_MAXHOST // already defined to 1025 in ws2tcpip.h? #define NI_MAXHOST 1024 #endif -static void translateWSAError(int error, QHostInfo *results) -{ - switch (error) { - case WSAHOST_NOT_FOUND: //authoritative not found - case WSATRY_AGAIN: //non authoritative not found - case WSANO_DATA: //valid name, no associated address - results->setError(QHostInfo::HostNotFound); - results->setErrorString(QHostInfoAgent::tr("Host not found")); - return; - default: - results->setError(QHostInfo::UnknownError); - results->setErrorString(QHostInfoAgent::tr("Unknown error (%1)").arg(error)); - return; - } -} - QHostInfo QHostInfoAgent::fromName(const QString &hostName) { QSysInfo::machineHostName(); // this initializes ws2_32.dll @@ -84,98 +67,10 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) #endif QHostAddress address; - if (address.setAddress(hostName)) { - // Reverse lookup - sockaddr_in sa4; - sockaddr_in6 sa6; - sockaddr *sa; - QT_SOCKLEN_T saSize; - if (address.protocol() == QAbstractSocket::IPv4Protocol) { - sa = reinterpret_cast(&sa4); - saSize = sizeof(sa4); - memset(&sa4, 0, sizeof(sa4)); - sa4.sin_family = AF_INET; - sa4.sin_addr.s_addr = htonl(address.toIPv4Address()); - } else { - sa = reinterpret_cast(&sa6); - saSize = sizeof(sa6); - memset(&sa6, 0, sizeof(sa6)); - sa6.sin6_family = AF_INET6; - memcpy(&sa6.sin6_addr, address.toIPv6Address().c, sizeof(sa6.sin6_addr)); - } + if (address.setAddress(hostName)) + return reverseLookup(address); - char hbuf[NI_MAXHOST]; - if (getnameinfo(sa, saSize, hbuf, sizeof(hbuf), 0, 0, 0) == 0) - results.setHostName(QString::fromLatin1(hbuf)); - - if (results.hostName().isEmpty()) - results.setHostName(address.toString()); - results.setAddresses(QList() << address); - return results; - } - - // IDN support - QByteArray aceHostname = QUrl::toAce(hostName); - results.setHostName(hostName); - if (aceHostname.isEmpty()) { - results.setError(QHostInfo::HostNotFound); - results.setErrorString(hostName.isEmpty() ? tr("No host name given") : tr("Invalid hostname")); - return results; - } - - addrinfo *res; - int err = getaddrinfo(aceHostname.constData(), 0, 0, &res); - if (err == 0) { - QList addresses; - for (addrinfo *p = res; p != 0; p = p->ai_next) { -#ifdef QHOSTINFO_DEBUG - qDebug() << "getaddrinfo node: flags:" << p->ai_flags << "family:" << p->ai_family - << "ai_socktype:" << p->ai_socktype << "ai_protocol:" << p->ai_protocol - << "ai_addrlen:" << p->ai_addrlen; -#endif - - switch (p->ai_family) { - case AF_INET: { - QHostAddress addr; - addr.setAddress(ntohl(reinterpret_cast(p->ai_addr)->sin_addr.s_addr)); - if (!addresses.contains(addr)) - addresses.append(addr); - } - break; - case AF_INET6: { - QHostAddress addr; - addr.setAddress(reinterpret_cast(p->ai_addr)->sin6_addr.s6_addr); - if (!addresses.contains(addr)) - addresses.append(addr); - } - break; - default: - results.setError(QHostInfo::UnknownError); - results.setErrorString(tr("Unknown address type")); - } - } - results.setAddresses(addresses); - freeaddrinfo(res); - } else { - translateWSAError(WSAGetLastError(), &results); - } - -#if defined(QHOSTINFO_DEBUG) - if (results.error() != QHostInfo::NoError) { - qDebug("QHostInfoAgent::run(): error (%s)", - results.errorString().toLatin1().constData()); - } else { - QString tmp; - QList addresses = results.addresses(); - for (int i = 0; i < addresses.count(); ++i) { - if (i != 0) tmp += QLatin1String(", "); - tmp += addresses.at(i).toString(); - } - qDebug("QHostInfoAgent::run(): found %i entries: {%s}", - addresses.count(), tmp.toLatin1().constData()); - } -#endif - return results; + return lookup(hostName); } // QString QHostInfo::localDomainName() defined in qnetworkinterface_win.cpp From abd2cf3b0a8c862d09f8163278424ca54297f854 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 26 Apr 2019 11:47:00 +0200 Subject: [PATCH 029/122] Remove extraneous sodipodi/inkskape cruft from Qt SVG Change-Id: Ib2d77331b33cac97e819e8273362703fcd80886c Reviewed-by: Allan Sandfeld Jensen --- src/plugins/platforms/wasm/qtlogo.svg | 29 +-------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/src/plugins/platforms/wasm/qtlogo.svg b/src/plugins/platforms/wasm/qtlogo.svg index cb8989bb79..ad7c7776bf 100644 --- a/src/plugins/platforms/wasm/qtlogo.svg +++ b/src/plugins/platforms/wasm/qtlogo.svg @@ -5,15 +5,10 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="462pt" height="339pt" viewBox="0 0 462 339" - version="1.1" - id="svg2" - inkscape:version="0.91 r13725" - sodipodi:docname="TheQtCompany_logo_2.svg"> + version="1.1"> @@ -26,28 +21,6 @@ - - Date: Tue, 30 Apr 2019 09:44:18 +0200 Subject: [PATCH 030/122] QList: do not call std::swap directly; use ADL Change-Id: Iaf6b965dd123f39436ba134ea1065d8dc4278c1e Reviewed-by: Thiago Macieira --- src/corelib/tools/qlist.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index dfb8a8a4ab..48a71b0ecf 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -709,7 +709,8 @@ inline void QList::swapItemsAt(int i, int j) Q_ASSERT_X(i >= 0 && i < p.size() && j >= 0 && j < p.size(), "QList::swap", "index out of range"); detach(); - std::swap(d->array[d->begin + i], d->array[d->begin + j]); + using std::swap; + swap(d->array[d->begin + i], d->array[d->begin + j]); } template From 9ec564b0bfc94c2d33f02b24ca081b64ff9ebb9b Mon Sep 17 00:00:00 2001 From: James McDonnell Date: Fri, 4 May 2018 14:23:51 -0400 Subject: [PATCH 031/122] Basic foreign window support for QNX Requires a screen with working context permission parsing. Currently, all context permission requests fail because the parsing is incorrect. A context permission is added temporarily to prevent CLOSE/CREATE events when Qt reparents foreign windows. Qt does this temporarily when a foreign window is wrapped in a widget. Change-Id: I84c18e70d43239286fcd53715332d7015cf1a826 Reviewed-by: Rafael Roquetto --- .../widgets/qnx/foreignwindows/collector.cpp | 176 ++++++++++++++++++ .../widgets/qnx/foreignwindows/collector.h | 75 ++++++++ .../qnx/foreignwindows/foreignwindows.pro | 11 ++ examples/widgets/qnx/foreignwindows/main.cpp | 53 ++++++ src/plugins/platforms/qnx/qnx.pro | 2 + .../platforms/qnx/qqnxforeignwindow.cpp | 65 +++++++ src/plugins/platforms/qnx/qqnxforeignwindow.h | 61 ++++++ src/plugins/platforms/qnx/qqnxintegration.cpp | 27 ++- src/plugins/platforms/qnx/qqnxintegration.h | 7 +- .../platforms/qnx/qqnxscreeneventhandler.cpp | 49 +++++ src/plugins/platforms/qnx/qqnxscreentraits.h | 127 +++++++++++++ src/plugins/platforms/qnx/qqnxwindow.cpp | 96 +++++++++- src/plugins/platforms/qnx/qqnxwindow.h | 8 +- 13 files changed, 747 insertions(+), 10 deletions(-) create mode 100644 examples/widgets/qnx/foreignwindows/collector.cpp create mode 100644 examples/widgets/qnx/foreignwindows/collector.h create mode 100644 examples/widgets/qnx/foreignwindows/foreignwindows.pro create mode 100644 examples/widgets/qnx/foreignwindows/main.cpp create mode 100644 src/plugins/platforms/qnx/qqnxforeignwindow.cpp create mode 100644 src/plugins/platforms/qnx/qqnxforeignwindow.h create mode 100644 src/plugins/platforms/qnx/qqnxscreentraits.h diff --git a/examples/widgets/qnx/foreignwindows/collector.cpp b/examples/widgets/qnx/foreignwindows/collector.cpp new file mode 100644 index 0000000000..4b9e774945 --- /dev/null +++ b/examples/widgets/qnx/foreignwindows/collector.cpp @@ -0,0 +1,176 @@ +/*************************************************************************** +** +** Copyright (C) 2018 QNX Software Systems. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 +#include +#include +#include + +#include +#include + +#include "collector.h" + +constexpr int MANAGER_EVENT_NAME_SUGGESTION = 9999; + +Collector::Collector(QWidget *parent) + : QWidget(parent) +{ + QApplication::instance()->installNativeEventFilter(this); + + QLayout *layout = new QHBoxLayout(this); + setLayout(layout); +} + +Collector::~Collector() +{ + QApplication::instance()->removeNativeEventFilter(this); +} + +bool Collector::nativeEventFilter(const QByteArray &eventType, void *message, long *result) +{ + Q_UNUSED(result); + + if (eventType == QByteArrayLiteral("screen_event_t")) + return filterQnxScreenEvent(static_cast(message)); + + return false; +} + +bool Collector::filterQnxScreenEvent(screen_event_t event) +{ + int objectType = SCREEN_OBJECT_TYPE_CONTEXT; + screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType); + + if (objectType == SCREEN_OBJECT_TYPE_WINDOW) + return filterQnxScreenWindowEvent(event); + + return false; +} + +bool Collector::filterQnxScreenWindowEvent(screen_event_t event) +{ + int eventType = SCREEN_EVENT_NONE; + screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &eventType); + screen_window_t window = nullptr; + screen_get_event_property_pv(event, + SCREEN_PROPERTY_WINDOW, + reinterpret_cast(&window)); + + if (eventType == SCREEN_EVENT_CREATE) + return filterQnxScreenWindowCreateEvent(window, event); + else if (eventType == SCREEN_EVENT_CLOSE) + return filterQnxScreenWindowCloseEvent(window, event); + else if (eventType == SCREEN_EVENT_MANAGER) + return filterQnxScreenWindowManagerEvent(window, event); + + return false; +} + +bool Collector::filterQnxScreenWindowCreateEvent(screen_window_t window, screen_event_t event) +{ + Q_UNUSED(event); + WId winId = reinterpret_cast(window); + + QByteArray parentGroup(256, 0); + screen_get_window_property_cv(window, + SCREEN_PROPERTY_PARENT, + parentGroup.length(), + parentGroup.data()); + parentGroup.resize(strlen(parentGroup.constData())); + + QByteArray group(256, 0); + screen_get_window_property_cv(reinterpret_cast(windowHandle()->winId()), + SCREEN_PROPERTY_GROUP, + group.length(), + group.data()); + group.resize(strlen(group.constData())); + + if (parentGroup != group) + return false; + + Collectible collectible; + collectible.window = QWindow::fromWinId(winId); + collectible.widget = QWidget::createWindowContainer(collectible.window, this); + layout()->addWidget(collectible.widget); + m_collectibles.append(collectible); + + return false; +} + +bool Collector::filterQnxScreenWindowCloseEvent(screen_window_t window, screen_event_t event) +{ + Q_UNUSED(event); + WId winId = reinterpret_cast(window); + auto it = std::find_if(m_collectibles.begin(), m_collectibles.end(), + [winId] (const Collectible &collectible) { + return collectible.window->winId() == winId; + }); + if (it != m_collectibles.end()) { + delete it->widget; + // it->window is deleted by it->widget. + m_collectibles.erase(it); + } + + return false; +} + +bool Collector::filterQnxScreenWindowManagerEvent(screen_window_t window, screen_event_t event) +{ + int managerEventType = 0; + screen_get_event_property_iv(event, SCREEN_PROPERTY_SUBTYPE, &managerEventType); + + if (managerEventType == MANAGER_EVENT_NAME_SUGGESTION) + return filterQnxScreenWindowManagerNameEvent(window, event); + + return false; +} + +bool Collector::filterQnxScreenWindowManagerNameEvent(screen_window_t window, screen_event_t event) +{ + Q_UNUSED(window); + int dataSize = 0; + screen_get_event_property_iv(event, SCREEN_PROPERTY_SIZE, &dataSize); + if (dataSize > 0) { + QByteArray data(dataSize, 0); + screen_get_event_property_cv(event, SCREEN_PROPERTY_USER_DATA, data.size(), data.data()); + } + + return false; +} diff --git a/examples/widgets/qnx/foreignwindows/collector.h b/examples/widgets/qnx/foreignwindows/collector.h new file mode 100644 index 0000000000..2b1ed499ff --- /dev/null +++ b/examples/widgets/qnx/foreignwindows/collector.h @@ -0,0 +1,75 @@ +/*************************************************************************** +** +** Copyright (C) 2018 QNX Software Systems. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 COLLECTOR_H_ +#define COLLECTOR_H_ + +#include +#include +#include + +#include + +class Collector : public QWidget, public QAbstractNativeEventFilter +{ +public: + explicit Collector(QWidget *parent = nullptr); + ~Collector() override; + + bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override; + +private: + struct Collectible + { + QWindow *window; + QWidget *widget; + }; + QVector m_collectibles; + + bool filterQnxScreenEvent(screen_event_t event); + bool filterQnxScreenWindowEvent(screen_event_t event); + bool filterQnxScreenWindowCreateEvent(screen_window_t window, screen_event_t event); + bool filterQnxScreenWindowCloseEvent(screen_window_t window, screen_event_t event); + bool filterQnxScreenWindowManagerEvent(screen_window_t window, screen_event_t event); + bool filterQnxScreenWindowManagerNameEvent(screen_window_t window, + screen_event_t event); +}; + + +#endif /* COLLECTOR_H_ */ diff --git a/examples/widgets/qnx/foreignwindows/foreignwindows.pro b/examples/widgets/qnx/foreignwindows/foreignwindows.pro new file mode 100644 index 0000000000..09ff8633eb --- /dev/null +++ b/examples/widgets/qnx/foreignwindows/foreignwindows.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +HEADERS += collector.h +SOURCES += main.cpp collector.cpp +LIBS += -lscreen + +QT += widgets + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/qnx/foreignwindows +INSTALLS += target diff --git a/examples/widgets/qnx/foreignwindows/main.cpp b/examples/widgets/qnx/foreignwindows/main.cpp new file mode 100644 index 0000000000..128e93cf88 --- /dev/null +++ b/examples/widgets/qnx/foreignwindows/main.cpp @@ -0,0 +1,53 @@ +/*************************************************************************** +** +** Copyright (C) 2018 QNX Software Systems. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 + +#include "collector.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + Collector collector; + collector.resize(640, 480); + collector.show(); + + return app.exec(); +} diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro index 96bfa1dd19..bfd56e8d13 100644 --- a/src/plugins/platforms/qnx/qnx.pro +++ b/src/plugins/platforms/qnx/qnx.pro @@ -33,6 +33,7 @@ QT += \ SOURCES = main.cpp \ qqnxbuffer.cpp \ + qqnxforeignwindow.cpp \ qqnxintegration.cpp \ qqnxscreen.cpp \ qqnxwindow.cpp \ @@ -50,6 +51,7 @@ SOURCES = main.cpp \ HEADERS = main.h \ qqnxbuffer.h \ + qqnxforeignwindow.h \ qqnxkeytranslator.h \ qqnxintegration.h \ qqnxscreen.h \ diff --git a/src/plugins/platforms/qnx/qqnxforeignwindow.cpp b/src/plugins/platforms/qnx/qqnxforeignwindow.cpp new file mode 100644 index 0000000000..94608215dc --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxforeignwindow.cpp @@ -0,0 +1,65 @@ +/*************************************************************************** +** +** Copyright (C) 2018 QNX Software Systems. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 "qqnxforeignwindow.h" +#include "qqnxintegration.h" + +QT_BEGIN_NAMESPACE + +QQnxForeignWindow::QQnxForeignWindow(QWindow *window, + screen_context_t context, + screen_window_t screenWindow) + : QQnxWindow(window, context, screenWindow) +{ + initWindow(); +} + +bool QQnxForeignWindow::isForeignWindow() const +{ + return true; +} + +int QQnxForeignWindow::pixelFormat() const +{ + int result = SCREEN_FORMAT_RGBA8888; + screen_get_window_property_iv(nativeHandle(), SCREEN_PROPERTY_FORMAT, &result); + return result; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxforeignwindow.h b/src/plugins/platforms/qnx/qqnxforeignwindow.h new file mode 100644 index 0000000000..22dde643e4 --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxforeignwindow.h @@ -0,0 +1,61 @@ +/*************************************************************************** +** +** Copyright (C) 2018 QNX Software Systems. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 QQNXFOREIGNWINDOW_H +#define QQNXFOREIGNWINDOW_H + +#include "qqnxwindow.h" + +QT_BEGIN_NAMESPACE + +class QQnxForeignWindow : public QQnxWindow +{ +public: + QQnxForeignWindow(QWindow *window, + screen_context_t context, + screen_window_t screenWindow); + + bool isForeignWindow() const override; + int pixelFormat() const override; + void resetBuffers() override {} +}; + +QT_END_NAMESPACE + +#endif // QQNXFOREIGNWINDOW_H diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index a45dcabeb7..d9120256b3 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -51,6 +51,7 @@ #include "qqnxabstractvirtualkeyboard.h" #include "qqnxservices.h" +#include "qqnxforeignwindow.h" #include "qqnxrasterwindow.h" #if !defined(QT_NO_OPENGL) #include "qqnxeglwindow.h" @@ -147,6 +148,7 @@ static inline int getContextCapabilities(const QStringList ¶mList) QQnxIntegration::QQnxIntegration(const QStringList ¶mList) : QPlatformIntegration() + , m_screenContextId(256, 0) , m_screenEventThread(0) , m_navigatorEventHandler(new QQnxNavigatorEventHandler()) , m_virtualKeyboard(0) @@ -178,6 +180,11 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) qFatal("%s - Screen: Failed to create screen context - Error: %s (%i)", Q_FUNC_INFO, strerror(errno), errno); } + screen_get_context_property_cv(m_screenContext, + SCREEN_PROPERTY_ID, + m_screenContextId.size(), + m_screenContextId.data()); + m_screenContextId.resize(strlen(m_screenContextId.constData())); #if QT_CONFIG(qqnx_pps) // Create/start navigator event notifier @@ -310,6 +317,7 @@ bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const qIntegrationDebug(); switch (cap) { case MultipleWindows: + case ForeignWindows: case ThreadedPixmaps: return true; #if !defined(QT_NO_OPENGL) @@ -323,6 +331,18 @@ bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const } } +QPlatformWindow *QQnxIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const +{ + screen_window_t screenWindow = reinterpret_cast(nativeHandle); + if (this->window(screenWindow)) { + qWarning() << "QWindow already created for foreign window" + << screenWindow; + return nullptr; + } + + return new QQnxForeignWindow(window, m_screenContext, screenWindow); +} + QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const { qIntegrationDebug(); @@ -478,7 +498,7 @@ QPlatformServices * QQnxIntegration::services() const return m_services; } -QWindow *QQnxIntegration::window(screen_window_t qnxWindow) +QWindow *QQnxIntegration::window(screen_window_t qnxWindow) const { qIntegrationDebug(); QMutexLocker locker(&m_windowMapperMutex); @@ -706,6 +726,11 @@ screen_context_t QQnxIntegration::screenContext() return m_screenContext; } +QByteArray QQnxIntegration::screenContextId() +{ + return m_screenContextId; +} + QQnxNavigatorEventHandler *QQnxIntegration::navigatorEventHandler() { return m_navigatorEventHandler; diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h index 366556dc4b..0bf37880d1 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.h +++ b/src/plugins/platforms/qnx/qqnxintegration.h @@ -92,6 +92,7 @@ public: bool hasCapability(QPlatformIntegration::Capability cap) const override; + QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override; QPlatformWindow *createPlatformWindow(QWindow *window) const override; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override; @@ -123,7 +124,7 @@ public: QPlatformServices *services() const override; - QWindow *window(screen_window_t qnxWindow); + QWindow *window(screen_window_t qnxWindow) const; QQnxScreen *screenForNative(screen_display_t qnxScreen) const; @@ -132,6 +133,7 @@ public: QQnxScreen *primaryDisplay() const; Options options() const; screen_context_t screenContext(); + QByteArray screenContextId(); QQnxNavigatorEventHandler *navigatorEventHandler(); @@ -145,6 +147,7 @@ private: int displayCount); screen_context_t m_screenContext; + QByteArray m_screenContextId; QQnxScreenEventThread *m_screenEventThread; QQnxNavigatorEventHandler *m_navigatorEventHandler; QQnxAbstractVirtualKeyboard *m_virtualKeyboard; @@ -168,7 +171,7 @@ private: QSimpleDrag *m_drag; #endif QQnxWindowMapper m_windowMapper; - QMutex m_windowMapperMutex; + mutable QMutex m_windowMapperMutex; Options m_options; diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index c2471751f5..56131dcc48 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -45,6 +45,7 @@ #include "qqnxkeytranslator.h" #include "qqnxscreen.h" #include "qqnxscreeneventfilter.h" +#include "qqnxscreentraits.h" #include #include @@ -89,6 +90,51 @@ static QString capKeyString(int cap, int modifiers, int key) return QString(); } +template +static void finishCloseEvent(screen_event_t event) +{ + T t; + screen_get_event_property_pv(event, + screen_traits::propertyName, + reinterpret_cast(&t)); + screen_traits::destroy(t); +} + +static void finishCloseEvent(screen_event_t event) +{ + // Let libscreen know that we're finished with anything that may have been acquired. + int objectType = SCREEN_OBJECT_TYPE_CONTEXT; + screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType); + switch (objectType) { + case SCREEN_OBJECT_TYPE_CONTEXT: + finishCloseEvent(event); + break; + case SCREEN_OBJECT_TYPE_DEVICE: + finishCloseEvent(event); + break; + case SCREEN_OBJECT_TYPE_DISPLAY: + // no screen_destroy_display + break; + case SCREEN_OBJECT_TYPE_GROUP: + finishCloseEvent(event); + break; + case SCREEN_OBJECT_TYPE_PIXMAP: + finishCloseEvent(event); + break; + case SCREEN_OBJECT_TYPE_SESSION: + finishCloseEvent(event); + break; +#if _SCREEN_VERSION >= _SCREEN_MAKE_VERSION(2, 0, 0) + case SCREEN_OBJECT_TYPE_STREAM: + finishCloseEvent(event); + break; +#endif + case SCREEN_OBJECT_TYPE_WINDOW: + finishCloseEvent(event); + break; + } +} + QT_BEGIN_NAMESPACE QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration) @@ -251,6 +297,9 @@ void QQnxScreenEventHandler::processEvents() bool handled = dispatcher && dispatcher->filterNativeEvent(QByteArrayLiteral("screen_event_t"), event, &result); if (!handled) handleEvent(event); + + if (type == SCREEN_EVENT_CLOSE) + finishCloseEvent(event); } m_eventThread->armEventsPending(count); diff --git a/src/plugins/platforms/qnx/qqnxscreentraits.h b/src/plugins/platforms/qnx/qqnxscreentraits.h new file mode 100644 index 0000000000..ebd74141f2 --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxscreentraits.h @@ -0,0 +1,127 @@ +/*************************************************************************** +** +** Copyright (C) 2018 QNX Software Systems. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins 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 QQNXSCREENTRAITS_H +#define QQNXSCREENTRAITS_H + +#include + +QT_BEGIN_NAMESPACE + +template +class screen_traits +{ +}; + +template <> +class screen_traits +{ +public: + typedef screen_context_t screen_type; + static const int propertyName = SCREEN_PROPERTY_CONTEXT; + static int destroy(screen_context_t context) { return screen_destroy_context(context); } +}; + +template <> +class screen_traits +{ +public: + typedef screen_device_t screen_type; + static const int propertyName = SCREEN_PROPERTY_DEVICE; + static int destroy(screen_device_t device) { return screen_destroy_device(device); } +}; + +template <> +class screen_traits +{ +public: + typedef screen_display_t screen_type; + static const int propertyName = SCREEN_PROPERTY_DISPLAY; +}; + +template <> +class screen_traits +{ +public: + typedef screen_group_t screen_type; + static const int propertyName = SCREEN_PROPERTY_GROUP; + static int destroy(screen_group_t group) { return screen_destroy_group(group); } +}; + +template <> +class screen_traits +{ +public: + typedef screen_pixmap_t screen_type; + static const int propertyName = SCREEN_PROPERTY_PIXMAP; + static int destroy(screen_pixmap_t pixmap) { return screen_destroy_pixmap(pixmap); } +}; + +template <> +class screen_traits +{ +public: + typedef screen_session_t screen_type; + static const int propertyName = SCREEN_PROPERTY_SESSION; + static int destroy(screen_session_t session) { return screen_destroy_session(session); } +}; + +#if _SCREEN_VERSION >= _SCREEN_MAKE_VERSION(2, 0, 0) +template <> +class screen_traits +{ +public: + typedef screen_stream_t screen_type; + static const int propertyName = SCREEN_PROPERTY_STREAM; + static int destroy(screen_stream_t stream) { return screen_destroy_stream(stream); } +}; +#endif + +template <> +class screen_traits +{ +public: + typedef screen_window_t screen_type; + static const int propertyName = SCREEN_PROPERTY_WINDOW; + static int destroy(screen_window_t window) { return screen_destroy_window(window); } +}; + +QT_END_NAMESPACE + +#endif // QQNXSCREENTRAITS_H diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 7644e28b44..1d3d609017 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -155,6 +155,7 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW m_parentWindow(0), m_visible(false), m_exposed(true), + m_foreign(false), m_windowState(Qt::WindowNoState), m_mmRendererWindow(0), m_firstActivateHandled(false) @@ -254,6 +255,39 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW } } +QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, screen_window_t screenWindow) + : QPlatformWindow(window) + , m_screenContext(context) + , m_window(screenWindow) + , m_screen(0) + , m_parentWindow(0) + , m_visible(false) + , m_exposed(true) + , m_foreign(true) + , m_windowState(Qt::WindowNoState) + , m_mmRendererWindow(0) + , m_parentGroupName(256, 0) + , m_isTopLevel(false) +{ + qWindowDebug() << "window =" << window << ", size =" << window->size(); + + collectWindowGroup(); + + screen_get_window_property_cv(m_window, + SCREEN_PROPERTY_PARENT, + m_parentGroupName.size(), + m_parentGroupName.data()); + m_parentGroupName.resize(strlen(m_parentGroupName.constData())); + + // If a window group has been provided join it now. If it's an empty string that's OK too, + // it'll cause us not to join a group (the app will presumably join at some future time). + QVariant parentGroup = window->property("qnxInitialWindowGroup"); + if (!parentGroup.isValid()) + parentGroup = window->property("_q_platform_qnxParentGroup"); + if (parentGroup.isValid() && parentGroup.canConvert()) + joinWindowGroup(parentGroup.toByteArray()); +} + QQnxWindow::~QQnxWindow() { qWindowDebug() << "window =" << window(); @@ -270,7 +304,11 @@ QQnxWindow::~QQnxWindow() m_screen->updateHierarchy(); // Cleanup QNX window and its buffers - screen_destroy_window(m_window); + // Foreign windows are cleaned up externally after the CLOSE event has been handled. + if (m_foreign) + removeContextPermission(); + else + screen_destroy_window(m_window); } void QQnxWindow::setGeometry(const QRect &rect) @@ -793,14 +831,24 @@ void QQnxWindow::initWindow() setGeometryHelper(shouldMakeFullScreen() ? screen()->geometry() : window()->geometry()); } +void QQnxWindow::collectWindowGroup() +{ + QByteArray groupName(256, 0); + Q_SCREEN_CHECKERROR(screen_get_window_property_cv(m_window, + SCREEN_PROPERTY_GROUP, + groupName.size(), + groupName.data()), + "Failed to retrieve window group"); + groupName.resize(strlen(groupName.constData())); + m_windowGroupName = groupName; +} + void QQnxWindow::createWindowGroup() { - // Generate a random window group name - m_windowGroupName = QUuid::createUuid().toByteArray(); - - // Create window group so child windows can be parented by container window - Q_SCREEN_CHECKERROR(screen_create_window_group(m_window, m_windowGroupName.constData()), + Q_SCREEN_CHECKERROR(screen_create_window_group(m_window, nullptr), "Failed to create window group"); + + collectWindowGroup(); } void QQnxWindow::joinWindowGroup(const QByteArray &groupName) @@ -809,6 +857,17 @@ void QQnxWindow::joinWindowGroup(const QByteArray &groupName) qWindowDebug() << "group:" << groupName; + // screen has this annoying habit of generating a CLOSE/CREATE when the owner context of + // the parent group moves a foreign window to another group that it also owns. The + // CLOSE/CREATE changes the identity of the foreign window. Usually, this is undesirable. + // To prevent this CLOSE/CREATE when changing the parent group, we temporarily add a + // context permission for the Qt context. screen won't send a CLOSE/CREATE when the + // context has some permission other than the PARENT permission. If there isn't a new + // group (the window has no parent), this context permission is left in place. + + if (m_foreign && !m_parentGroupName.isEmpty())\ + addContextPermission(); + if (!groupName.isEmpty()) { if (groupName != m_parentGroupName) { screen_join_window_group(m_window, groupName); @@ -827,6 +886,9 @@ void QQnxWindow::joinWindowGroup(const QByteArray &groupName) m_parentGroupName = ""; } + if (m_foreign && !groupName.isEmpty()) + removeContextPermission(); + if (changed) screen_flush_context(m_screenContext, 0); } @@ -899,4 +961,26 @@ bool QQnxWindow::focusable() const return (window()->flags() & Qt::WindowDoesNotAcceptFocus) != Qt::WindowDoesNotAcceptFocus; } +void QQnxWindow::addContextPermission() +{ + QByteArray grantString("context:"); + grantString.append(QQnxIntegration::instance()->screenContextId()); + grantString.append(":rw-"); + screen_set_window_property_cv(m_window, + SCREEN_PROPERTY_PERMISSIONS, + grantString.length(), + grantString.data()); +} + +void QQnxWindow::removeContextPermission() +{ + QByteArray revokeString("context:"); + revokeString.append(QQnxIntegration::instance()->screenContextId()); + revokeString.append(":---"); + screen_set_window_property_cv(m_window, + SCREEN_PROPERTY_PERMISSIONS, + revokeString.length(), + revokeString.data()); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index 20c38cb4b7..9040619c41 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -64,7 +64,8 @@ class QQnxWindow : public QPlatformWindow { friend class QQnxScreen; public: - QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow); + explicit QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow); + explicit QQnxWindow(QWindow *window, screen_context_t context, screen_window_t screenWindow); virtual ~QQnxWindow(); void setGeometry(const QRect &rect) override; @@ -124,6 +125,7 @@ protected: screen_context_t m_screenContext; private: + void collectWindowGroup(); void createWindowGroup(); void setGeometryHelper(const QRect &rect); void removeFromParent(); @@ -135,6 +137,9 @@ private: bool showWithoutActivating() const; bool focusable() const; + void addContextPermission(); + void removeContextPermission(); + screen_window_t m_window; QSize m_bufferSize; @@ -144,6 +149,7 @@ private: QScopedPointer m_cover; bool m_visible; bool m_exposed; + bool m_foreign; QRect m_unmaximizedGeometry; Qt::WindowStates m_windowState; QString m_mmRendererWindowName; From 23c2da3cc23a2e04a0b3b3c8ad7fa9cc6126ff23 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 19 Dec 2017 15:25:55 +0100 Subject: [PATCH 032/122] Add QTextMarkdownWriter, QTextEdit::markdown property etc. A QTextDocument can now be written out in Markdown format. - Add the QTextMarkdownWriter as a private class for now - Add QTextDocument::toMarkdown() - QTextDocumentWriter uses QTextMarkdownWriter if setFormat("markdown") is called or if the file suffix is .md or .mkd - Add QTextEdit::toMarkdown() and the markdown property [ChangeLog][QtGui][Text] Markdown (CommonMark or GitHub dialect) is now a supported format for reading into and writing from QTextDocument. Change-Id: I663a77017fac7ae1b3f9a400f5cd357bb40750af Reviewed-by: Gatis Paeglis --- src/gui/configure.json | 8 +- src/gui/text/qtextdocument.cpp | 34 +- src/gui/text/qtextdocument.h | 8 +- src/gui/text/qtextdocumentwriter.cpp | 19 + src/gui/text/qtextmarkdownwriter.cpp | 363 ++++++++++++++++++ src/gui/text/qtextmarkdownwriter_p.h | 78 ++++ src/gui/text/text.pri | 7 + src/widgets/widgets/qtextedit.cpp | 62 ++- src/widgets/widgets/qtextedit.h | 8 +- src/widgets/widgets/qwidgettextcontrol.cpp | 7 + src/widgets/widgets/qwidgettextcontrol_p.h | 3 + .../gui/text/qtextmarkdownwriter/BLACKLIST | 3 + .../text/qtextmarkdownwriter/data/example.md | 95 +++++ .../qtextmarkdownwriter.pro | 7 + .../tst_qtextmarkdownwriter.cpp | 360 +++++++++++++++++ tests/auto/gui/text/text.pro | 3 + tests/manual/markdown/html2md.cpp | 64 +++ tests/manual/markdown/html2md.pro | 6 + 18 files changed, 1124 insertions(+), 11 deletions(-) create mode 100644 src/gui/text/qtextmarkdownwriter.cpp create mode 100644 src/gui/text/qtextmarkdownwriter_p.h create mode 100644 tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST create mode 100644 tests/auto/gui/text/qtextmarkdownwriter/data/example.md create mode 100644 tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro create mode 100644 tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp create mode 100644 tests/manual/markdown/html2md.cpp create mode 100644 tests/manual/markdown/html2md.pro diff --git a/src/gui/configure.json b/src/gui/configure.json index d7c0da4640..9e76fc455e 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -1611,6 +1611,12 @@ "condition": "libs.libmd4c", "output": [ "publicFeature" ] }, + "textmarkdownwriter": { + "label": "MarkdownWriter", + "purpose": "Provides a Markdown (CommonMark) writer", + "section": "Kernel", + "output": [ "publicFeature" ] + }, "textodfwriter": { "label": "OdfWriter", "purpose": "Provides an ODF writer.", @@ -1892,7 +1898,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla { "section": "Text formats", "entries": [ - "texthtmlparser", "cssparser", "textodfwriter", "textmarkdownreader", "system-textmarkdownreader" + "texthtmlparser", "cssparser", "textodfwriter", "textmarkdownreader", "system-textmarkdownreader", "textmarkdownwriter" ] }, "egl", diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 87c8f1ba8a..0a59bfb838 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -73,6 +73,9 @@ #if QT_CONFIG(textmarkdownreader) #include #endif +#if QT_CONFIG(textmarkdownwriter) +#include +#endif #include @@ -3288,6 +3291,22 @@ QString QTextDocument::toHtml(const QByteArray &encoding) const } #endif // QT_NO_TEXTHTMLPARSER +/*! + Returns a string containing a Markdown representation of the document, + or an empty string if writing fails for any reason. +*/ +#if QT_CONFIG(textmarkdownwriter) +QString QTextDocument::toMarkdown(QTextDocument::MarkdownFeatures features) const +{ + QString ret; + QTextStream s(&ret); + QTextMarkdownWriter w(s, features); + if (w.writeAll(*this)) + return ret; + return QString(); +} +#endif + /*! Replaces the entire contents of the document with the given Markdown-formatted text in the \a markdown string, with the given @@ -3301,8 +3320,19 @@ QString QTextDocument::toHtml(const QByteArray &encoding) const Parsing of HTML included in the \a markdown string is handled in the same way as in \l setHtml; however, Markdown formatting inside HTML blocks is - not supported. The \c MarkdownNoHTML feature flag can be set to disable - HTML parsing. + not supported. + + Some features of the parser can be enabled or disabled via the \a features + argument: + + \value MarkdownNoHTML + Any HTML tags in the Markdown text will be discarded + \value MarkdownDialectCommonMark + The parser supports only the features standardized by CommonMark + \value MarkdownDialectGitHub + The parser supports the GitHub dialect + + The default is \c MarkdownDialectGitHub. The undo/redo history is reset when this function is called. */ diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index ade67999ad..31c06976a5 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -151,7 +151,7 @@ public: void setHtml(const QString &html); #endif -#if QT_CONFIG(textmarkdownreader) +#if QT_CONFIG(textmarkdownwriter) || QT_CONFIG(textmarkdownreader) // Must be in sync with QTextMarkdownImporter::Features, should be in sync with #define MD_FLAG_* in md4c enum MarkdownFeature { MarkdownNoHTML = 0x0020 | 0x0040, @@ -160,7 +160,13 @@ public: }; Q_DECLARE_FLAGS(MarkdownFeatures, MarkdownFeature) Q_FLAG(MarkdownFeatures) +#endif +#if QT_CONFIG(textmarkdownwriter) + QString toMarkdown(MarkdownFeatures features = MarkdownDialectGitHub) const; +#endif + +#if QT_CONFIG(textmarkdownreader) void setMarkdown(const QString &markdown, MarkdownFeatures features = MarkdownDialectGitHub); #endif diff --git a/src/gui/text/qtextdocumentwriter.cpp b/src/gui/text/qtextdocumentwriter.cpp index 42e623153a..c82ff873cd 100644 --- a/src/gui/text/qtextdocumentwriter.cpp +++ b/src/gui/text/qtextdocumentwriter.cpp @@ -51,6 +51,9 @@ #include "qtextdocumentfragment_p.h" #include "qtextodfwriter_p.h" +#if QT_CONFIG(textmarkdownwriter) +#include "qtextmarkdownwriter_p.h" +#endif #include @@ -267,6 +270,18 @@ bool QTextDocumentWriter::write(const QTextDocument *document) } #endif // QT_NO_TEXTODFWRITER +#if QT_CONFIG(textmarkdownwriter) + if (format == "md" || format == "mkd" || format == "markdown") { + if (!d->device->isWritable() && !d->device->open(QIODevice::WriteOnly)) { + qWarning("QTextDocumentWriter::write: the device can not be opened for writing"); + return false; + } + QTextStream s(d->device); + QTextMarkdownWriter writer(s, QTextDocument::MarkdownDialectGitHub); + return writer.writeAll(*document); + } +#endif // textmarkdownwriter + #ifndef QT_NO_TEXTHTMLPARSER if (format == "html" || format == "htm") { if (!d->device->isWritable() && ! d->device->open(QIODevice::WriteOnly)) { @@ -348,6 +363,7 @@ QTextCodec *QTextDocumentWriter::codec() const \header \li Format \li Description \row \li plaintext \li Plain text \row \li HTML \li HyperText Markup Language + \row \li markdown \li Markdown (CommonMark or GitHub dialects) \row \li ODF \li OpenDocument Format \endtable @@ -364,6 +380,9 @@ QList QTextDocumentWriter::supportedDocumentFormats() #ifndef QT_NO_TEXTODFWRITER answer << "ODF"; #endif // QT_NO_TEXTODFWRITER +#if QT_CONFIG(textmarkdownwriter) + answer << "markdown"; +#endif std::sort(answer.begin(), answer.end()); return answer; diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp new file mode 100644 index 0000000000..c91248757a --- /dev/null +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -0,0 +1,363 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui 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 "qtextmarkdownwriter_p.h" +#include "qtextdocumentlayout_p.h" +#include "qfontinfo.h" +#include "qfontmetrics.h" +#include "qtextdocument_p.h" +#include "qtextlist.h" +#include "qtexttable.h" +#include "qtextcursor.h" +#include "qtextimagehandler_p.h" + +QT_BEGIN_NAMESPACE + +static const QChar Space = QLatin1Char(' '); +static const QChar Newline = QLatin1Char('\n'); +static const QChar Backtick = QLatin1Char('`'); + +QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features) + : m_stream(stream), m_features(features) +{ +} + +bool QTextMarkdownWriter::writeAll(const QTextDocument &document) +{ + writeFrame(document.rootFrame()); + return true; +} + +void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) +{ + Q_ASSERT(frame); + const QTextTable *table = qobject_cast (frame); + QTextFrame::iterator iterator = frame->begin(); + QTextFrame *child = 0; + int tableRow = -1; + bool lastWasList = false; + QVector tableColumnWidths; + if (table) { + tableColumnWidths.resize(table->columns()); + for (int col = 0; col < table->columns(); ++col) { + for (int row = 0; row < table->rows(); ++ row) { + QTextTableCell cell = table->cellAt(row, col); + int cellTextLen = 0; + auto it = cell.begin(); + while (it != cell.end()) { + QTextBlock block = it.currentBlock(); + if (block.isValid()) + cellTextLen += block.text().length(); + ++it; + } + if (cell.columnSpan() == 1 && tableColumnWidths[col] < cellTextLen) + tableColumnWidths[col] = cellTextLen; + } + } + } + while (!iterator.atEnd()) { + if (iterator.currentFrame() && child != iterator.currentFrame()) + writeFrame(iterator.currentFrame()); + else { // no frame, it's a block + QTextBlock block = iterator.currentBlock(); + if (table) { + QTextTableCell cell = table->cellAt(block.position()); + if (tableRow < cell.row()) { + if (tableRow == 0) { + m_stream << Newline; + for (int col = 0; col < tableColumnWidths.length(); ++col) + m_stream << '|' << QString(tableColumnWidths[col], QLatin1Char('-')); + m_stream << '|'; + } + m_stream << Newline << "|"; + tableRow = cell.row(); + } + } else if (!block.textList()) { + if (lastWasList) + m_stream << Newline; + } + int endingCol = writeBlock(block, !table, table && tableRow == 0); + if (table) { + QTextTableCell cell = table->cellAt(block.position()); + int paddingLen = -endingCol; + int spanEndCol = cell.column() + cell.columnSpan(); + for (int col = cell.column(); col < spanEndCol; ++col) + paddingLen += tableColumnWidths[col]; + if (paddingLen > 0) + m_stream << QString(paddingLen, Space); + for (int col = cell.column(); col < spanEndCol; ++col) + m_stream << "|"; + } else if (block.textList()) { + m_stream << Newline; + } else if (endingCol > 0) { + m_stream << Newline << Newline; + } + lastWasList = block.textList(); + } + child = iterator.currentFrame(); + ++iterator; + } + if (table) + m_stream << Newline << Newline; +} + +static int nearestWordWrapIndex(const QString &s, int before) +{ + before = qMin(before, s.length()); + for (int i = before - 1; i >= 0; --i) { + if (s.at(i).isSpace()) + return i; + } + return -1; +} + +static int adjacentBackticksCount(const QString &s) +{ + int start = -1, len = s.length(); + int ret = 0; + for (int i = 0; i < len; ++i) { + if (s.at(i) == Backtick) { + if (start < 0) + start = i; + } else if (start >= 0) { + ret = qMax(ret, i - start); + start = -1; + } + } + if (s.at(len - 1) == Backtick) + ret = qMax(ret, len - start); + return ret; +} + +static void maybeEscapeFirstChar(QString &s) +{ + QString sTrimmed = s.trimmed(); + if (sTrimmed.isEmpty()) + return; + char firstChar = sTrimmed.at(0).toLatin1(); + if (firstChar == '*' || firstChar == '+' || firstChar == '-') { + int i = s.indexOf(QLatin1Char(firstChar)); + s.insert(i, QLatin1Char('\\')); + } +} + +int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat) +{ + int ColumnLimit = 80; + int wrapIndent = 0; + if (block.textList()) { // it's a list-item + auto fmt = block.textList()->format(); + const int listLevel = fmt.indent(); + const int number = block.textList()->itemNumber(block) + 1; + QByteArray bullet = " "; + bool numeric = false; + switch (fmt.style()) { + case QTextListFormat::ListDisc: bullet = "-"; break; + case QTextListFormat::ListCircle: bullet = "*"; break; + case QTextListFormat::ListSquare: bullet = "+"; break; + case QTextListFormat::ListStyleUndefined: break; + case QTextListFormat::ListDecimal: + case QTextListFormat::ListLowerAlpha: + case QTextListFormat::ListUpperAlpha: + case QTextListFormat::ListLowerRoman: + case QTextListFormat::ListUpperRoman: + numeric = true; + break; + } + switch (block.blockFormat().marker()) { + case QTextBlockFormat::Checked: + bullet += " [x]"; + break; + case QTextBlockFormat::Unchecked: + bullet += " [ ]"; + break; + default: + break; + } + QString prefix((listLevel - 1) * (numeric ? 4 : 2), Space); + if (numeric) + prefix += QString::number(number) + fmt.numberSuffix() + Space; + else + prefix += QLatin1String(bullet) + Space; + m_stream << prefix; + wrapIndent = prefix.length(); + } + + if (block.blockFormat().headingLevel()) + m_stream << QByteArray(block.blockFormat().headingLevel(), '#') << ' '; + + QString wrapIndentString(wrapIndent, Space); + // It would be convenient if QTextStream had a lineCharPos() accessor, + // to keep track of how many characters (not bytes) have been written on the current line, + // but it doesn't. So we have to keep track with this col variable. + int col = wrapIndent; + bool mono = false; + bool startsOrEndsWithBacktick = false; + bool bold = false; + bool italic = false; + bool underline = false; + bool strikeOut = false; + QString backticks(Backtick); + for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) { + QString fragmentText = frag.fragment().text(); + while (fragmentText.endsWith(QLatin1Char('\n'))) + fragmentText.chop(1); + startsOrEndsWithBacktick |= fragmentText.startsWith(Backtick) || fragmentText.endsWith(Backtick); + QTextCharFormat fmt = frag.fragment().charFormat(); + if (fmt.isImageFormat()) { + QTextImageFormat ifmt = fmt.toImageFormat(); + QString s = QLatin1String("![image](") + ifmt.name() + QLatin1Char(')'); + if (wrap && col + s.length() > ColumnLimit) { + m_stream << Newline << wrapIndentString; + col = wrapIndent; + } + m_stream << s; + col += s.length(); + } else if (fmt.hasProperty(QTextFormat::AnchorHref)) { + QString s = QLatin1Char('[') + fragmentText + QLatin1String("](") + + fmt.property(QTextFormat::AnchorHref).toString() + QLatin1Char(')'); + if (wrap && col + s.length() > ColumnLimit) { + m_stream << Newline << wrapIndentString; + col = wrapIndent; + } + m_stream << s; + col += s.length(); + } else { + QFontInfo fontInfo(fmt.font()); + bool monoFrag = fontInfo.fixedPitch(); + QString markers; + if (!ignoreFormat) { + if (monoFrag != mono) { + if (monoFrag) + backticks = QString::fromLatin1(QByteArray(adjacentBackticksCount(fragmentText) + 1, '`')); + markers += backticks; + if (startsOrEndsWithBacktick) + markers += Space; + mono = monoFrag; + } + if (!block.blockFormat().headingLevel() && !mono) { + if (fmt.font().bold() != bold) { + markers += QLatin1String("**"); + bold = fmt.font().bold(); + } + if (fmt.font().italic() != italic) { + markers += QLatin1Char('*'); + italic = fmt.font().italic(); + } + if (fmt.font().strikeOut() != strikeOut) { + markers += QLatin1String("~~"); + strikeOut = fmt.font().strikeOut(); + } + if (fmt.font().underline() != underline) { + // Markdown doesn't support underline, but the parser will treat a single underline + // the same as a single asterisk, and the marked fragment will be rendered in italics. + // That will have to do. + markers += QLatin1Char('_'); + underline = fmt.font().underline(); + } + } + } + if (wrap && col + markers.length() * 2 + fragmentText.length() > ColumnLimit) { + int i = 0; + int fragLen = fragmentText.length(); + bool breakingLine = false; + while (i < fragLen) { + int j = i + ColumnLimit - col; + if (j < fragLen) { + int wi = nearestWordWrapIndex(fragmentText, j); + if (wi < 0) { + j = fragLen; + } else { + j = wi; + breakingLine = true; + } + } else { + j = fragLen; + breakingLine = false; + } + QString subfrag = fragmentText.mid(i, j - i); + if (!i) { + m_stream << markers; + col += markers.length(); + } + if (col == wrapIndent) + maybeEscapeFirstChar(subfrag); + m_stream << subfrag; + if (breakingLine) { + m_stream << Newline << wrapIndentString; + col = wrapIndent; + } else { + col += subfrag.length(); + } + i = j + 1; + } + } else { + m_stream << markers << fragmentText; + col += markers.length() + fragmentText.length(); + } + } + } + if (mono) { + if (startsOrEndsWithBacktick) { + m_stream << Space; + col += 1; + } + m_stream << backticks; + col += backticks.size(); + } + if (bold) { + m_stream << "**"; + col += 2; + } + if (italic) { + m_stream << "*"; + col += 1; + } + if (underline) { + m_stream << "_"; + col += 1; + } + if (strikeOut) { + m_stream << "~~"; + col += 2; + } + return col; +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h new file mode 100644 index 0000000000..9845355259 --- /dev/null +++ b/src/gui/text/qtextmarkdownwriter_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui 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 QTEXTMARKDOWNWRITER_P_H +#define QTEXTMARKDOWNWRITER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +#include "qtextdocument_p.h" +#include "qtextdocumentwriter.h" + +QT_BEGIN_NAMESPACE + +class Q_GUI_EXPORT QTextMarkdownWriter +{ +public: + QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features); + bool writeAll(const QTextDocument &document); + + int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat); + void writeFrame(const QTextFrame *frame); + +private: + QTextStream &m_stream; + QTextDocument::MarkdownFeatures m_features; +}; + +QT_END_NAMESPACE + +#endif // QTEXTMARKDOWNWRITER_P_H diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index b35a231747..5e97b312f1 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -109,6 +109,13 @@ qtConfig(textmarkdownreader) { text/qtextmarkdownimporter.cpp } +qtConfig(textmarkdownwriter) { + HEADERS += \ + text/qtextmarkdownwriter_p.h + SOURCES += \ + text/qtextmarkdownwriter.cpp +} + qtConfig(cssparser) { HEADERS += \ text/qcssparser_p.h diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index 9e134493b5..5f734258b2 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -366,8 +366,8 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) \section1 Introduction and Concepts QTextEdit is an advanced WYSIWYG viewer/editor supporting rich - text formatting using HTML-style tags. It is optimized to handle - large documents and to respond quickly to user input. + text formatting using HTML-style tags, or Markdown format. It is optimized + to handle large documents and to respond quickly to user input. QTextEdit works on paragraphs and characters. A paragraph is a formatted string which is word-wrapped to fit into the width of @@ -381,7 +381,7 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) QTextEdit can display images, lists and tables. If the text is too large to view within the text edit's viewport, scroll bars will appear. The text edit can load both plain text and rich text files. - Rich text is described using a subset of HTML 4 markup, refer to the + Rich text can be described using a subset of HTML 4 markup; refer to the \l {Supported HTML Subset} page for more information. If you just need to display a small piece of rich text use QLabel. @@ -401,12 +401,19 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) QTextEdit can display a large HTML subset, including tables and images. - The text is set or replaced using setHtml() which deletes any + The text can be set or replaced using \l setHtml() which deletes any existing text and replaces it with the text passed in the setHtml() call. If you call setHtml() with legacy HTML, and then call toHtml(), the text that is returned may have different markup, but will render the same. The entire text can be deleted with clear(). + Text can also be set or replaced using \l setMarkdown(), and the same + caveats apply: if you then call \l toMarkdown(), the text that is returned + may be different, but the meaning is preserved as much as possible. + Markdown with some embedded HTML can be parsed, with the same limitations + that \l setHtml() has; but \l toMarkdown() only writes "pure" Markdown, + without any embedded HTML. + Text itself can be inserted using the QTextCursor class or using the convenience functions insertHtml(), insertPlainText(), append() or paste(). QTextCursor is also able to insert complex objects like tables @@ -1213,11 +1220,54 @@ QString QTextEdit::toHtml() const } #endif +#if QT_CONFIG(textmarkdownreader) && QT_CONFIG(textmarkdownwriter) +/*! + \property QTextEdit::markdown + + This property provides a Markdown interface to the text of the text edit. + + \c toMarkdown() returns the text of the text edit as "pure" Markdown, + without any embedded HTML formatting. Some features that QTextDocument + supports (such as the use of specific colors and named fonts) cannot be + expressed in "pure" Markdown, and they will be omitted. + + \c setMarkdown() changes the text of the text edit. Any previous text is + removed and the undo/redo history is cleared. The input text is + interpreted as rich text in Markdown format. + + Parsing of HTML included in the \a markdown string is handled in the same + way as in \l setHtml; however, Markdown formatting inside HTML blocks is + not supported. + + Some features of the parser can be enabled or disabled via the \a features + argument: + + \value MarkdownNoHTML + Any HTML tags in the Markdown text will be discarded + \value MarkdownDialectCommonMark + The parser supports only the features standardized by CommonMark + \value MarkdownDialectGitHub + The parser supports the GitHub dialect + + The default is \c MarkdownDialectGitHub. + + \sa plainText, html, QTextDocument::toMarkdown(), QTextDocument::setMarkdown() +*/ +#endif + #if QT_CONFIG(textmarkdownreader) -void QTextEdit::setMarkdown(const QString &text) +void QTextEdit::setMarkdown(const QString &markdown) { Q_D(const QTextEdit); - d->control->setMarkdown(text); + d->control->setMarkdown(markdown); +} +#endif + +#if QT_CONFIG(textmarkdownwriter) +QString QTextEdit::toMarkdown(QTextDocument::MarkdownFeatures features) const +{ + Q_D(const QTextEdit); + return d->control->toMarkdown(features); } #endif diff --git a/src/widgets/widgets/qtextedit.h b/src/widgets/widgets/qtextedit.h index f20bd936c4..3b7e610786 100644 --- a/src/widgets/widgets/qtextedit.h +++ b/src/widgets/widgets/qtextedit.h @@ -71,6 +71,9 @@ class Q_WIDGETS_EXPORT QTextEdit : public QAbstractScrollArea QDOC_PROPERTY(QTextOption::WrapMode wordWrapMode READ wordWrapMode WRITE setWordWrapMode) Q_PROPERTY(int lineWrapColumnOrWidth READ lineWrapColumnOrWidth WRITE setLineWrapColumnOrWidth) Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly) +#if QT_CONFIG(textmarkdownreader) && QT_CONFIG(textmarkdownwriter) + Q_PROPERTY(QString markdown READ toMarkdown WRITE setMarkdown NOTIFY textChanged) +#endif #ifndef QT_NO_TEXTHTMLPARSER Q_PROPERTY(QString html READ toHtml WRITE setHtml NOTIFY textChanged USER true) #endif @@ -174,6 +177,9 @@ public: #ifndef QT_NO_TEXTHTMLPARSER QString toHtml() const; #endif +#if QT_CONFIG(textmarkdownwriter) + QString toMarkdown(QTextDocument::MarkdownFeatures features = QTextDocument::MarkdownDialectGitHub) const; +#endif void ensureCursorVisible(); @@ -239,7 +245,7 @@ public Q_SLOTS: void setHtml(const QString &text); #endif #if QT_CONFIG(textmarkdownreader) - void setMarkdown(const QString &text); + void setMarkdown(const QString &markdown); #endif void setText(const QString &text); diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 5744d43cbf..209156b901 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -3130,6 +3130,13 @@ QString QWidgetTextControl::toHtml() const } #endif +#ifndef QT_NO_TEXTHTMLPARSER +QString QWidgetTextControl::toMarkdown(QTextDocument::MarkdownFeatures features) const +{ + return document()->toMarkdown(features); +} +#endif + void QWidgetTextControlPrivate::append(const QString &text, Qt::TextFormat format) { QTextCursor tmp(doc); diff --git a/src/widgets/widgets/qwidgettextcontrol_p.h b/src/widgets/widgets/qwidgettextcontrol_p.h index 4c9e47dfc9..e521e7b356 100644 --- a/src/widgets/widgets/qwidgettextcontrol_p.h +++ b/src/widgets/widgets/qwidgettextcontrol_p.h @@ -128,6 +128,9 @@ public: #ifndef QT_NO_TEXTHTMLPARSER QString toHtml() const; #endif +#if QT_CONFIG(textmarkdownwriter) + QString toMarkdown(QTextDocument::MarkdownFeatures features = QTextDocument::MarkdownDialectGitHub) const; +#endif virtual void ensureCursorVisible(); diff --git a/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST b/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST new file mode 100644 index 0000000000..fc9e5a9efe --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST @@ -0,0 +1,3 @@ +[rewriteDocument] +winrt # QTBUG-54623 + diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/example.md b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md new file mode 100644 index 0000000000..3c63f209a2 --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md @@ -0,0 +1,95 @@ +# QTextEdit + +The QTextEdit widget is an advanced editor that supports formatted rich text. +It can be used to display HTML and other rich document formats. Internally, +QTextEdit uses the QTextDocument class to describe both the high-level +structure of each document and the low-level formatting of paragraphs. + +If you are viewing this document in the textedit example, you can edit this +document to explore Qt's rich text editing features. We have included some +comments in each of the following sections to encourage you to experiment. + +## Font and Paragraph Styles + +QTextEdit supports **bold**, *italic*, and ~~strikethrough~~ font styles, and can +display multicolored text. Font families such as Times New Roman and `Courier` +can also be used directly. *If you place the cursor in a region of styled text, +the controls in the tool bars will change to reflect the current style.* + +Paragraphs can be formatted so that the text is left-aligned, right-aligned, +centered, or fully justified. + +*Try changing the alignment of some text and resize the editor to see how the +text layout changes.* + +## Lists + +Different kinds of lists can be included in rich text documents. Standard +bullet lists can be nested, using different symbols for each level of the list: + +* Disc symbols are typically used for top-level list items. + - Circle symbols can be used to distinguish between items in lower-level + lists. + + Square symbols provide a reasonable alternative to discs and circles. + +Ordered lists can be created that can be used for tables of contents. Different +characters can be used to enumerate items, and we can use both Roman and Arabic +numerals in the same list structure: + +1. Introduction +2. Qt Tools + 1) Qt Assistant + 2) Qt Designer + 1. Form Editor + 2. Component Architecture + 3) Qt Linguist + +The list will automatically be renumbered if you add or remove items. *Try +adding new sections to the above list or removing existing item to see the +numbers change.* + +## Images + +Inline images are treated like ordinary ranges of characters in the text +editor, so they flow with the surrounding text. Images can also be selected in +the same way as text, making it easy to cut, copy, and paste them. + +![image](images/logo32.png) *Try to select this image by clicking and dragging +over it with the mouse, or use the text cursor to select it by holding down +Shift and using the arrow keys. You can then cut or copy it, and paste it into +different parts of this document.* + +## Tables + +QTextEdit can arrange and format tables, supporting features such as row and +column spans, text formatting within cells, and size constraints for columns. + + +| |Development Tools |Programming Techniques |Graphical User Interfaces| +|-------------|------------------------------------|---------------------------|-------------------------| +|9:00 - 11:00 |Introduction to Qt ||| +|11:00 - 13:00|Using qmake |Object-oriented Programming|Layouts in Qt | +|13:00 - 15:00|Qt Designer Tutorial |Extreme Programming |Writing Custom Styles | +|15:00 - 17:00|Qt Linguist and Internationalization|  |  | + +*Try adding text to the cells in the table and experiment with the alignment of +the paragraphs.* + +## Hyperlinks + +QTextEdit is designed to support hyperlinks between documents, and this feature +is used extensively in +[Qt Assistant](http://doc.qt.io/qt-5/qtassistant-index.html). Hyperlinks are +automatically created when an HTML file is imported into an editor. Since the +rich text framework supports hyperlinks natively, they can also be created +programatically. + +## Undo and Redo + +Full support for undo and redo operations is built into QTextEdit and the +underlying rich text framework. Operations on a document can be packaged +together to make editing a more comfortable experience for the user. + +*Try making changes to this document and press `Ctrl+Z` to undo them. You can +always recover the original contents of the document.* + diff --git a/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro new file mode 100644 index 0000000000..04cf7ef5dd --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro @@ -0,0 +1,7 @@ +CONFIG += testcase +TARGET = tst_qtextmarkdownwriter +QT += core-private gui-private testlib +SOURCES += tst_qtextmarkdownwriter.cpp +TESTDATA += data/example.md + +DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp new file mode 100644 index 0000000000..bf7c9708de --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp @@ -0,0 +1,360 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// #define DEBUG_WRITE_OUTPUT + +class tst_QTextMarkdownWriter : public QObject +{ + Q_OBJECT +public slots: + void init(); + void cleanup(); + +private slots: + void testWriteParagraph_data(); + void testWriteParagraph(); + void testWriteList(); + void testWriteNestedBulletLists(); + void testWriteNestedNumericLists(); + void testWriteTable(); + void rewriteDocument(); + void fromHtml_data(); + void fromHtml(); + +private: + QString documentToUnixMarkdown(); + +private: + QTextDocument *document; +}; + +void tst_QTextMarkdownWriter::init() +{ + document = new QTextDocument(); +} + +void tst_QTextMarkdownWriter::cleanup() +{ + delete document; +} + +void tst_QTextMarkdownWriter::testWriteParagraph_data() +{ + QTest::addColumn("input"); + QTest::addColumn("output"); + + QTest::newRow("empty") << "" << + ""; + QTest::newRow("spaces") << "foobar word" << + "foobar word\n\n"; + QTest::newRow("starting spaces") << " starting spaces" << + " starting spaces\n\n"; + QTest::newRow("trailing spaces") << "trailing spaces " << + "trailing spaces \n\n"; + QTest::newRow("tab") << "word\ttab x" << + "word\ttab x\n\n"; + QTest::newRow("tab2") << "word\t\ttab\tx" << + "word\t\ttab\tx\n\n"; + QTest::newRow("misc") << "foobar word\ttab x" << + "foobar word\ttab x\n\n"; + QTest::newRow("misc2") << "\t \tFoo" << + "\t \tFoo\n\n"; +} + +void tst_QTextMarkdownWriter::testWriteParagraph() +{ + QFETCH(QString, input); + QFETCH(QString, output); + + QTextCursor cursor(document); + cursor.insertText(input); + + QCOMPARE(documentToUnixMarkdown(), output); +} + +void tst_QTextMarkdownWriter::testWriteList() +{ + QTextCursor cursor(document); + QTextList *list = cursor.createList(QTextListFormat::ListDisc); + cursor.insertText("ListItem 1"); + list->add(cursor.block()); + cursor.insertBlock(); + cursor.insertText("ListItem 2"); + list->add(cursor.block()); + + QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1( + "- ListItem 1\n- ListItem 2\n")); +} + +void tst_QTextMarkdownWriter::testWriteNestedBulletLists() +{ + QTextCursor cursor(document); + + QTextList *list1 = cursor.createList(QTextListFormat::ListDisc); + cursor.insertText("ListItem 1"); + list1->add(cursor.block()); + + QTextListFormat fmt2; + fmt2.setStyle(QTextListFormat::ListCircle); + fmt2.setIndent(2); + QTextList *list2 = cursor.insertList(fmt2); + cursor.insertText("ListItem 2"); + + QTextListFormat fmt3; + fmt3.setStyle(QTextListFormat::ListSquare); + fmt3.setIndent(3); + cursor.insertList(fmt3); + cursor.insertText("ListItem 3"); + + cursor.insertBlock(); + cursor.insertText("ListItem 4"); + list1->add(cursor.block()); + + cursor.insertBlock(); + cursor.insertText("ListItem 5"); + list2->add(cursor.block()); + + QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1( + "- ListItem 1\n * ListItem 2\n + ListItem 3\n- ListItem 4\n * ListItem 5\n")); +} + +void tst_QTextMarkdownWriter::testWriteNestedNumericLists() +{ + QTextCursor cursor(document); + + QTextList *list1 = cursor.createList(QTextListFormat::ListDecimal); + cursor.insertText("ListItem 1"); + list1->add(cursor.block()); + + QTextListFormat fmt2; + fmt2.setStyle(QTextListFormat::ListLowerAlpha); + fmt2.setNumberSuffix(QLatin1String(")")); + fmt2.setIndent(2); + QTextList *list2 = cursor.insertList(fmt2); + cursor.insertText("ListItem 2"); + + QTextListFormat fmt3; + fmt3.setStyle(QTextListFormat::ListDecimal); + fmt3.setIndent(3); + cursor.insertList(fmt3); + cursor.insertText("ListItem 3"); + + cursor.insertBlock(); + cursor.insertText("ListItem 4"); + list1->add(cursor.block()); + + cursor.insertBlock(); + cursor.insertText("ListItem 5"); + list2->add(cursor.block()); + + // There's no QTextList API to set the starting number so we hard-coded all lists to start at 1 (QTBUG-65384) + QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1( + "1 ListItem 1\n 1) ListItem 2\n 1 ListItem 3\n2 ListItem 4\n 2) ListItem 5\n")); +} + +void tst_QTextMarkdownWriter::testWriteTable() +{ + QTextCursor cursor(document); + QTextTable * table = cursor.insertTable(4, 3); + cursor = table->cellAt(0, 0).firstCursorPosition(); + // valid Markdown tables need headers, but QTextTable doesn't make that distinction + // so QTextMarkdownWriter assumes the first row of any table is a header + cursor.insertText("one"); + cursor.movePosition(QTextCursor::NextCell); + cursor.insertText("two"); + cursor.movePosition(QTextCursor::NextCell); + cursor.insertText("three"); + cursor.movePosition(QTextCursor::NextCell); + + cursor.insertText("alice"); + cursor.movePosition(QTextCursor::NextCell); + cursor.insertText("bob"); + cursor.movePosition(QTextCursor::NextCell); + cursor.insertText("carl"); + cursor.movePosition(QTextCursor::NextCell); + + cursor.insertText("dennis"); + cursor.movePosition(QTextCursor::NextCell); + cursor.insertText("eric"); + cursor.movePosition(QTextCursor::NextCell); + cursor.insertText("fiona"); + cursor.movePosition(QTextCursor::NextCell); + + cursor.insertText("gina"); + /* + |one |two |three| + |------|----|-----| + |alice |bob |carl | + |dennis|eric|fiona| + |gina | | | + */ + + QString md = documentToUnixMarkdown(); + +#ifdef DEBUG_WRITE_OUTPUT + { + QFile out("/tmp/table.md"); + out.open(QFile::WriteOnly); + out.write(md.toUtf8()); + out.close(); + } +#endif + + QString expected = QString::fromLatin1( + "\n|one |two |three|\n|------|----|-----|\n|alice |bob |carl |\n|dennis|eric|fiona|\n|gina | | |\n\n"); + QCOMPARE(md, expected); + + // create table with merged cells + document->clear(); + cursor = QTextCursor(document); + table = cursor.insertTable(3, 3); + table->mergeCells(0, 0, 1, 2); + table->mergeCells(1, 1, 1, 2); + cursor = table->cellAt(0, 0).firstCursorPosition(); + cursor.insertText("a"); + cursor.movePosition(QTextCursor::NextCell); + cursor.insertText("b"); + cursor.movePosition(QTextCursor::NextCell); + cursor.insertText("c"); + cursor.movePosition(QTextCursor::NextCell); + cursor.insertText("d"); + cursor.movePosition(QTextCursor::NextCell); + cursor.insertText("e"); + cursor.movePosition(QTextCursor::NextCell); + cursor.insertText("f"); + /* + +---+-+ + |a |b| + +---+-+ + |c| d| + +-+-+-+ + |e|f| | + +-+-+-+ + + generates + + |a ||b| + |-|-|-| + |c|d || + |e|f| | + + */ + + md = documentToUnixMarkdown(); + +#ifdef DEBUG_WRITE_OUTPUT + { + QFile out("/tmp/table-merged-cells.md"); + out.open(QFile::WriteOnly); + out.write(md.toUtf8()); + out.close(); + } +#endif + + QCOMPARE(md, QString::fromLatin1("\n|a ||b|\n|-|-|-|\n|c|d ||\n|e|f| |\n\n")); +} + +void tst_QTextMarkdownWriter::rewriteDocument() +{ + QTextDocument doc; + QFile f(QFINDTESTDATA("data/example.md")); + QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text)); + QString orig = QString::fromUtf8(f.readAll()); + f.close(); + doc.setMarkdown(orig); + QString md = doc.toMarkdown(); + +#ifdef DEBUG_WRITE_OUTPUT + QFile out("/tmp/rewrite.md"); + out.open(QFile::WriteOnly); + out.write(md.toUtf8()); + out.close(); +#endif + + QCOMPARE(md, orig); +} + +void tst_QTextMarkdownWriter::fromHtml_data() +{ + QTest::addColumn("input"); + QTest::addColumn("output"); + + QTest::newRow("long URL") << + "https://www.example.com/dir/subdir/subsubdir/subsubsubdir/subsubsubsubdir/subsubsubsubsubdir/" << + "*https://www.example.com/dir/subdir/subsubdir/subsubsubdir/subsubsubsubdir/subsubsubsubsubdir/*\n\n"; + QTest::newRow("non-emphasis inline asterisk") << "3 * 4" << "3 * 4\n\n"; + QTest::newRow("arithmetic") << "(2 * a * x + b)^2 = b^2 - 4 * a * c" << "(2 * a * x + b)^2 = b^2 - 4 * a * c\n\n"; + QTest::newRow("escaped asterisk after newline") << + "The first sentence of this paragraph holds 80 characters, then there's a star. * This is wrapped, but is not a bullet point." << + "The first sentence of this paragraph holds 80 characters, then there's a star.\n\\* This is wrapped, but is *not* a bullet point.\n\n"; + QTest::newRow("escaped plus after newline") << + "The first sentence of this paragraph holds 80 characters, then there's a plus. + This is wrapped, but is not a bullet point." << + "The first sentence of this paragraph holds 80 characters, then there's a plus.\n\\+ This is wrapped, but is *not* a bullet point.\n\n"; + QTest::newRow("escaped hyphen after newline") << + "The first sentence of this paragraph holds 80 characters, then there's a minus. - This is wrapped, but is not a bullet point." << + "The first sentence of this paragraph holds 80 characters, then there's a minus.\n\\- This is wrapped, but is *not* a bullet point.\n\n"; + // TODO +// QTest::newRow("escaped number and paren after double newline") << +// "

    (The first sentence of this paragraph is a line, the next paragraph has a number

    13) but that's not part of an ordered list" << +// "(The first sentence of this paragraph is a line, the next paragraph has a number\n\n13\\) but that's not part of an ordered list\n\n"; +// QTest::newRow("preformats with embedded backticks") << +// "
    none `one` ``two``
    ```three``` ````four````
    plain" << +// "``` none `one` ``two`` ```\n\n````` ```three``` ````four```` `````\n\nplain\n\n"; +} + +void tst_QTextMarkdownWriter::fromHtml() +{ + QFETCH(QString, input); + QFETCH(QString, output); + + document->setHtml(input); + QCOMPARE(documentToUnixMarkdown(), output); +} + +QString tst_QTextMarkdownWriter::documentToUnixMarkdown() +{ + QString ret; + QTextStream ts(&ret, QIODevice::WriteOnly); + QTextMarkdownWriter writer(ts, QTextDocument::MarkdownDialectGitHub); + writer.writeAll(*document); + return ret; +} + +QTEST_MAIN(tst_QTextMarkdownWriter) +#include "tst_qtextmarkdownwriter.moc" diff --git a/tests/auto/gui/text/text.pro b/tests/auto/gui/text/text.pro index 6b033fb506..a98debe35c 100644 --- a/tests/auto/gui/text/text.pro +++ b/tests/auto/gui/text/text.pro @@ -28,12 +28,15 @@ SUBDIRS=\ win32:SUBDIRS -= qtextpiecetable +qtConfig(textmarkdownwriter): SUBDIRS += qtextmarkdownwriter + !qtConfig(private_tests): SUBDIRS -= \ qfontcache \ qcssparser \ qtextlayout \ qtextpiecetable \ qzip \ + qtextmarkdownwriter \ qtextodfwriter !qtHaveModule(xml): SUBDIRS -= \ diff --git a/tests/manual/markdown/html2md.cpp b/tests/manual/markdown/html2md.cpp new file mode 100644 index 0000000000..19d6ff06af --- /dev/null +++ b/tests/manual/markdown/html2md.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** + ** + ** Copyright (C) 2019 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the test suite of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** 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 General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** 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-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + QGuiApplication::setApplicationVersion(QT_VERSION_STR); + QCommandLineParser parser; + parser.setApplicationDescription("Converts the Qt-supported subset of HTML to Markdown."); + parser.addHelpOption(); + parser.addVersionOption(); + parser.addPositionalArgument(QGuiApplication::translate("main", "input"), + QGuiApplication::translate("main", "input file")); + parser.addPositionalArgument(QGuiApplication::translate("main", "output"), + QGuiApplication::translate("main", "output file")); + parser.process(app); + if (parser.positionalArguments().count() != 2) + parser.showHelp(1); + + QFile inFile(parser.positionalArguments().first()); + if (!inFile.open(QIODevice::ReadOnly)) { + qFatal("failed to open %s for reading", parser.positionalArguments().first().toLocal8Bit().data()); + exit(2); + } + QFile outFile(parser.positionalArguments().at(1)); + if (!outFile.open(QIODevice::WriteOnly)) { + qFatal("failed to open %s for writing", parser.positionalArguments().at(1).toLocal8Bit().data()); + exit(2); + } + QTextDocument doc; + doc.setHtml(QString::fromUtf8(inFile.readAll())); + outFile.write(doc.toMarkdown().toUtf8()); +} diff --git a/tests/manual/markdown/html2md.pro b/tests/manual/markdown/html2md.pro new file mode 100644 index 0000000000..4d6254e5a0 --- /dev/null +++ b/tests/manual/markdown/html2md.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +TARGET = html2md +INCLUDEPATH += . +#QT += gui-private +SOURCES += html2md.cpp + From d4435a37cae43abfbdb247b7d4a3a950aced2751 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 30 Apr 2019 12:39:22 +0200 Subject: [PATCH 033/122] Add qobject_cast operators for std::shared_ptr Mimicking what we currently have for QSharedPointer, but also adding * snake_case version (matching the ones in std) * rvalue-overloaded versions (matching the C++2a overloads). [ChangeLog][QtCore][QSharedPointer] Overloads of qSharedPointerObjectCast have been added to work on std::shared_ptr. Change-Id: I26ddffd82b000bf876e7c141fdce86a7b8c1d75a Reviewed-by: Thiago Macieira --- src/corelib/tools/qsharedpointer.cpp | 51 +++++++++++++++++ src/corelib/tools/qsharedpointer_impl.h | 42 ++++++++++++++ .../qsharedpointer/tst_qsharedpointer.cpp | 55 +++++++++++++++++++ 3 files changed, 148 insertions(+) diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 62b76c5bb7..0aedf4c6d6 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -1299,6 +1299,57 @@ \sa QSharedPointer::objectCast(), qSharedPointerCast(), qSharedPointerConstCast() */ +/*! + \fn template std::shared_ptr qSharedPointerObjectCast(const std::shared_ptr &src) + \relates QSharedPointer + \since 5.14 + + Returns a shared pointer to the pointer held by \a src, using a + \l qobject_cast() to type \tt X to obtain an internal pointer of the + appropriate type. If the \tt qobject_cast fails, the object + returned will be null. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use const_pointer_cast to cast away the constness. +*/ + +/*! + \fn template std::shared_ptr qobject_pointer_cast(const std::shared_ptr &src) + \relates QSharedPointer + \since 5.14 + + Same as qSharedPointerObjectCast(). This function is provided for STL + compatibility. +*/ + +/*! + \fn template std::shared_ptr qSharedPointerObjectCast(std::shared_ptr &&src) + \relates QSharedPointer + \since 5.14 + + Returns a shared pointer to the pointer held by \a src, using a + \l qobject_cast() to type \tt X to obtain an internal pointer of the + appropriate type. + + If the \tt qobject_cast succeeds, the function will return a valid shared + pointer, and \a src is reset to null. If the \tt qobject_cast fails, the + object returned will be null, and \a src will not be modified. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use const_pointer_cast to cast away the constness. +*/ + +/*! + \fn template std::shared_ptr qobject_pointer_cast(std::shared_ptr &&src) + \relates QSharedPointer + \since 5.14 + + Same as qSharedPointerObjectCast(). This function is provided for STL + compatibility. +*/ + /*! \fn template template QSharedPointer qSharedPointerObjectCast(const QWeakPointer &src) \relates QSharedPointer diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 81d8dcd839..0851121ff2 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -67,6 +67,8 @@ QT_END_NAMESPACE #endif #include +#include + QT_BEGIN_NAMESPACE @@ -996,6 +998,46 @@ qSharedPointerFromVariant(const QVariant &variant) return qSharedPointerObjectCast(QtSharedPointer::sharedPointerFromVariant_internal(variant)); } +// std::shared_ptr helpers + +template +std::shared_ptr qobject_pointer_cast(const std::shared_ptr &src) +{ + using element_type = typename std::shared_ptr::element_type; + return std::shared_ptr(src, qobject_cast(src.get())); +} + +template +std::shared_ptr qobject_pointer_cast(std::shared_ptr &&src) +{ + using element_type = typename std::shared_ptr::element_type; + auto castResult = qobject_cast(src.get()); + if (castResult) { + auto result = std::shared_ptr(std::move(src), castResult); +#if __cplusplus <= 201703L + // C++2a's move aliasing constructor will leave src empty. + // Before C++2a we don't really know if the compiler has support for it. + // The move aliasing constructor is the resolution for LWG2996, + // which does not impose a feature-testing macro. So: clear src. + src.reset(); +#endif + return result; + } + return std::shared_ptr(); +} + +template +std::shared_ptr qSharedPointerObjectCast(const std::shared_ptr &src) +{ + return qobject_pointer_cast(src); +} + +template +std::shared_ptr qSharedPointerObjectCast(std::shared_ptr &&src) +{ + return qobject_pointer_cast(std::move(src)); +} + #endif template Q_DECLARE_TYPEINFO_BODY(QWeakPointer, Q_MOVABLE_TYPE); diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index 19b2aa02f3..3e87a506bf 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -78,6 +78,7 @@ private slots: void sharedPointerFromQObjectWithWeak(); void weakQObjectFromSharedPointer(); void objectCast(); + void objectCastStdSharedPtr(); void differentPointers(); void virtualBaseDifferentPointers(); #ifndef QTEST_NO_RTTI @@ -1113,6 +1114,60 @@ void tst_QSharedPointer::objectCast() safetyCheck(); } + +void tst_QSharedPointer::objectCastStdSharedPtr() +{ + { + OtherObject *data = new OtherObject; + std::shared_ptr baseptr = std::shared_ptr(data); + QVERIFY(baseptr.get() == data); + + // perform successful object cast + std::shared_ptr ptr = qobject_pointer_cast(baseptr); + QVERIFY(ptr.get()); + QVERIFY(ptr.get() == data); + + QVERIFY(baseptr.get() == data); + } + + { + OtherObject *data = new OtherObject; + std::shared_ptr baseptr = std::shared_ptr(data); + QVERIFY(baseptr.get() == data); + + // perform successful object cast + std::shared_ptr ptr = qobject_pointer_cast(std::move(baseptr)); + QVERIFY(ptr.get()); + QVERIFY(ptr.get() == data); + + QVERIFY(!baseptr.get()); + } + + { + QObject *data = new QObject; + std::shared_ptr baseptr = std::shared_ptr(data); + QVERIFY(baseptr.get() == data); + + // perform unsuccessful object cast + std::shared_ptr ptr = qobject_pointer_cast(baseptr); + QVERIFY(!ptr.get()); + + QVERIFY(baseptr.get() == data); + } + + { + QObject *data = new QObject; + std::shared_ptr baseptr = std::shared_ptr(data); + QVERIFY(baseptr.get() == data); + + // perform unsuccessful object cast + std::shared_ptr ptr = qobject_pointer_cast(std::move(baseptr)); + QVERIFY(!ptr.get()); + + QVERIFY(baseptr.get() == data); + } +} + void tst_QSharedPointer::differentPointers() { { From 2ded0043ca5115ddec41c15b2b98481f45bf0eba Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 30 Apr 2019 11:16:25 +0200 Subject: [PATCH 034/122] Moc: compile generate_keywords with corelib only It does not depend on QtGui. Change-Id: If7b01d1a6d2ce3945562f4480177ce883abfdbf4 Reviewed-by: Thiago Macieira Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/tools/moc/util/generate_keywords.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/moc/util/generate_keywords.pro b/src/tools/moc/util/generate_keywords.pro index 2bbc3ced61..e29738c18a 100644 --- a/src/tools/moc/util/generate_keywords.pro +++ b/src/tools/moc/util/generate_keywords.pro @@ -1,4 +1,5 @@ CONFIG -= moc CONFIG += cmdline +QT = core SOURCES += generate_keywords.cpp From b32b61f17eb6f816d854d6177e70df9c9e8fb895 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 30 Apr 2019 17:16:17 +0200 Subject: [PATCH 035/122] Remove handling of missing Q_COMPILER_RVALUE_REFS Remove remaining handling of missing support for rvalue refs. Change-Id: I78bab8bccfeeb9c76f464f345874364a37e4840a Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.h | 5 +---- src/corelib/mimetypes/qmimetype_p.h | 19 ------------------- src/corelib/tools/qdatetime.h | 2 -- src/corelib/tools/qeasingcurve.h | 2 -- src/corelib/tools/qhash.h | 4 ---- src/corelib/tools/qlinkedlist.h | 2 -- src/corelib/tools/qlist.h | 2 -- src/corelib/tools/qlocale.h | 2 -- src/corelib/tools/qmap.h | 4 ---- src/corelib/tools/qpair.h | 2 -- src/corelib/tools/qregexp.h | 2 -- src/corelib/tools/qregularexpression.h | 8 -------- src/corelib/tools/qshareddata.h | 4 ---- src/corelib/tools/qsharedpointer_impl.h | 5 ----- src/corelib/tools/qstring.h | 4 ---- src/corelib/tools/qstringlist.h | 4 ---- src/corelib/tools/qtimezone.h | 2 -- src/corelib/tools/qvector.h | 8 -------- src/corelib/tools/qversionnumber.h | 4 ---- src/dbus/qdbusargument.h | 2 -- src/dbus/qdbusconnection.h | 2 -- src/dbus/qdbuserror.h | 2 -- src/dbus/qdbusextratypes.h | 6 ------ src/dbus/qdbusmessage.h | 2 -- src/dbus/qdbuspendingcall.h | 2 -- src/dbus/qdbusunixfiledescriptor.h | 6 +----- src/gui/image/qicon.h | 4 ---- src/gui/image/qimage.h | 4 ---- src/gui/image/qpicture.h | 2 -- src/gui/image/qpixmap.h | 4 ---- src/gui/image/qpixmapcache.h | 2 -- src/gui/kernel/qcursor.h | 2 -- src/gui/kernel/qevent.h | 2 -- src/gui/kernel/qkeysequence.h | 2 -- src/gui/kernel/qpalette.h | 2 -- src/gui/opengl/qopengldebug.h | 2 -- src/gui/opengl/qopenglpixeltransferoptions.h | 2 -- src/gui/painting/qbrush.h | 2 -- src/gui/painting/qcolor.h | 2 -- src/gui/painting/qpagelayout.h | 2 -- src/gui/painting/qpagesize.h | 2 -- src/gui/painting/qpainterpath.h | 2 -- src/gui/painting/qpen.h | 2 -- src/gui/painting/qpolygon.h | 8 -------- src/gui/painting/qregion.h | 2 -- src/gui/text/qfont.h | 2 -- src/gui/text/qfontmetrics.h | 4 ---- src/gui/text/qglyphrun.h | 2 -- src/gui/text/qrawfont.h | 2 -- src/gui/text/qstatictext.h | 2 -- src/gui/text/qtextcursor.h | 2 -- src/network/access/qabstractnetworkcache.h | 2 -- src/network/access/qhttpmultipart.h | 2 -- src/network/access/qnetworkcookie.h | 2 -- src/network/access/qnetworkrequest.h | 2 -- src/network/bearer/qnetworkconfiguration.h | 2 -- src/network/kernel/qdnslookup.h | 10 ---------- src/network/kernel/qhostaddress.h | 3 --- src/network/kernel/qnetworkinterface.h | 4 ---- src/network/kernel/qnetworkproxy.h | 4 ---- src/network/ssl/qsslcertificate.h | 2 -- src/network/ssl/qsslcertificateextension.h | 2 -- src/network/ssl/qsslcipher.h | 2 -- src/network/ssl/qsslconfiguration.h | 2 -- src/network/ssl/qsslerror.h | 2 -- .../ssl/qsslpresharedkeyauthenticator.h | 2 -- src/printsupport/kernel/qprintdevice_p.h | 2 -- .../corelib/global/qglobal/tst_qglobal.cpp | 4 ---- .../qsignalblocker/tst_qsignalblocker.cpp | 5 ----- .../mimetypes/qmimetype/tst_qmimetype.cpp | 4 ---- .../tools/qarraydata/tst_qarraydata.cpp | 4 ---- .../corelib/tools/qcollator/tst_qcollator.cpp | 6 ------ .../tools/qeasingcurve/tst_qeasingcurve.cpp | 6 +----- .../qsharedpointer/tst_qsharedpointer.cpp | 6 ------ .../corelib/tools/qvector/tst_qvector.cpp | 4 ---- .../qversionnumber/tst_qversionnumber.cpp | 5 ----- .../auto/gui/kernel/qpalette/tst_qpalette.cpp | 4 ---- 77 files changed, 3 insertions(+), 261 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 3c17bbb2d4..ceae0583ee 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -509,11 +509,8 @@ namespace QtPrivate { template struct AlignOf : AlignOf_Default { }; template struct AlignOf : AlignOf {}; - template struct AlignOf : AlignOf {}; - -#ifdef Q_COMPILER_RVALUE_REFS template struct AlignOf : AlignOf {}; -#endif + template struct AlignOf : AlignOf {}; #if defined(Q_PROCESSOR_X86_32) && !defined(Q_OS_WIN) template struct AlignOf_WorkaroundForI386Abi { enum { Value = sizeof(T) }; }; diff --git a/src/corelib/mimetypes/qmimetype_p.h b/src/corelib/mimetypes/qmimetype_p.h index 2918309ad7..0d6b4b4b12 100644 --- a/src/corelib/mimetypes/qmimetype_p.h +++ b/src/corelib/mimetypes/qmimetype_p.h @@ -84,25 +84,6 @@ public: QT_END_NAMESPACE -#define QMIMETYPE_BUILDER \ - QT_BEGIN_NAMESPACE \ - static QMimeType buildQMimeType ( \ - const QString &name, \ - const QString &genericIconName, \ - const QString &iconName, \ - const QStringList &globPatterns \ - ) \ - { \ - QMimeTypePrivate qMimeTypeData; \ - qMimeTypeData.name = name; \ - qMimeTypeData.loaded = true; \ - qMimeTypeData.genericIconName = genericIconName; \ - qMimeTypeData.iconName = iconName; \ - qMimeTypeData.globPatterns = globPatterns; \ - return QMimeType(qMimeTypeData); \ - } \ - QT_END_NAMESPACE - #define QMIMETYPE_BUILDER_FROM_RVALUE_REFS \ QT_BEGIN_NAMESPACE \ static QMimeType buildQMimeType ( \ diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index 8873651f17..79fd25d762 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -278,9 +278,7 @@ public: QDateTime(QDateTime &&other) noexcept; ~QDateTime(); -#ifdef Q_COMPILER_RVALUE_REFS QDateTime &operator=(QDateTime &&other) noexcept { swap(other); return *this; } -#endif QDateTime &operator=(const QDateTime &other) noexcept; void swap(QDateTime &other) noexcept { qSwap(d.d, other.d.d); } diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h index 1791f19199..725ddd5dcc 100644 --- a/src/corelib/tools/qeasingcurve.h +++ b/src/corelib/tools/qeasingcurve.h @@ -80,11 +80,9 @@ public: QEasingCurve &operator=(const QEasingCurve &other) { if ( this != &other ) { QEasingCurve copy(other); swap(copy); } return *this; } -#ifdef Q_COMPILER_RVALUE_REFS QEasingCurve(QEasingCurve &&other) noexcept : d_ptr(other.d_ptr) { other.d_ptr = nullptr; } QEasingCurve &operator=(QEasingCurve &&other) noexcept { qSwap(d_ptr, other.d_ptr); return *this; } -#endif void swap(QEasingCurve &other) noexcept { qSwap(d_ptr, other.d_ptr); } diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index a757e85386..0078bbbee9 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -255,11 +255,9 @@ public: ~QHash() { if (!d->ref.deref()) freeData(d); } QHash &operator=(const QHash &other); -#ifdef Q_COMPILER_RVALUE_REFS QHash(QHash &&other) noexcept : d(other.d) { other.d = const_cast(&QHashData::shared_null); } QHash &operator=(QHash &&other) noexcept { QHash moved(std::move(other)); swap(moved); return *this; } -#endif #ifdef Q_QDOC template QHash(InputIterator f, InputIterator l); @@ -1076,9 +1074,7 @@ public: // compiler-generated destructor is fine! QMultiHash(const QHash &other) : QHash(other) {} -#ifdef Q_COMPILER_RVALUE_REFS QMultiHash(QHash &&other) noexcept : QHash(std::move(other)) {} -#endif void swap(QMultiHash &other) noexcept { QHash::swap(other); } // prevent QMultiHash<->QHash swaps inline typename QHash::iterator replace(const Key &key, const T &value) diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 83f70deceb..0c8a99e258 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -95,12 +95,10 @@ public: } ~QLinkedList(); QLinkedList &operator=(const QLinkedList &); -#ifdef Q_COMPILER_RVALUE_REFS QLinkedList(QLinkedList &&other) noexcept : d(other.d) { other.d = const_cast(&QLinkedListData::shared_null); } QLinkedList &operator=(QLinkedList &&other) noexcept { QLinkedList moved(std::move(other)); swap(moved); return *this; } -#endif inline void swap(QLinkedList &other) noexcept { qSwap(d, other.d); } bool operator==(const QLinkedList &l) const; inline bool operator!=(const QLinkedList &l) const { return !(*this == l); } diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 48a71b0ecf..59578b1e61 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -161,12 +161,10 @@ public: QList(const QList &l); ~QList(); QList &operator=(const QList &l); -#ifdef Q_COMPILER_RVALUE_REFS inline QList(QList &&other) noexcept : d(other.d) { other.d = const_cast(&QListData::shared_null); } inline QList &operator=(QList &&other) noexcept { QList moved(std::move(other)); swap(moved); return *this; } -#endif inline void swap(QList &other) noexcept { qSwap(d, other.d); } #ifdef Q_COMPILER_INITIALIZER_LISTS inline QList(std::initializer_list args) diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index 3dc5ee0a01..977c4c6c9c 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -939,9 +939,7 @@ public: QLocale(Language language, Country country = AnyCountry); QLocale(Language language, Script script, Country country); QLocale(const QLocale &other); -#ifdef Q_COMPILER_RVALUE_REFS QLocale &operator=(QLocale &&other) noexcept { swap(other); return *this; } -#endif QLocale &operator=(const QLocale &other); ~QLocale(); diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 103124f4ad..3b8aad9a33 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -339,7 +339,6 @@ public: inline ~QMap() { if (!d->ref.deref()) d->destroy(); } QMap &operator=(const QMap &other); -#ifdef Q_COMPILER_RVALUE_REFS inline QMap(QMap &&other) noexcept : d(other.d) { @@ -349,7 +348,6 @@ public: inline QMap &operator=(QMap &&other) noexcept { QMap moved(std::move(other)); swap(moved); return *this; } -#endif inline void swap(QMap &other) noexcept { qSwap(d, other.d); } explicit QMap(const typename std::map &other); std::map toStdMap() const; @@ -1196,9 +1194,7 @@ public: } #endif QMultiMap(const QMap &other) : QMap(other) {} -#ifdef Q_COMPILER_RVALUE_REFS QMultiMap(QMap &&other) noexcept : QMap(std::move(other)) {} -#endif void swap(QMultiMap &other) noexcept { QMap::swap(other); } inline typename QMap::iterator replace(const Key &key, const T &value) diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h index 6d1e67efb7..9ebf88bc8f 100644 --- a/src/corelib/tools/qpair.h +++ b/src/corelib/tools/qpair.h @@ -71,7 +71,6 @@ struct QPair noexcept((std::is_nothrow_assignable::value && std::is_nothrow_assignable::value)) { first = p.first; second = p.second; return *this; } -#ifdef Q_COMPILER_RVALUE_REFS template Q_DECL_CONSTEXPR QPair(QPair &&p) noexcept((std::is_nothrow_constructible::value && @@ -83,7 +82,6 @@ struct QPair noexcept((std::is_nothrow_assignable::value && std::is_nothrow_assignable::value)) { first = std::move(p.first); second = std::move(p.second); return *this; } -#endif Q_DECL_RELAXED_CONSTEXPR void swap(QPair &other) noexcept(noexcept(qSwap(other.first, other.first)) && noexcept(qSwap(other.second, other.second))) diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h index c043a06496..8f6de24c74 100644 --- a/src/corelib/tools/qregexp.h +++ b/src/corelib/tools/qregexp.h @@ -73,9 +73,7 @@ public: QRegExp(const QRegExp &rx); ~QRegExp(); QRegExp &operator=(const QRegExp &rx); -#ifdef Q_COMPILER_RVALUE_REFS QRegExp &operator=(QRegExp &&other) noexcept { swap(other); return *this; } -#endif void swap(QRegExp &other) noexcept { qSwap(priv, other.priv); } bool operator==(const QRegExp &rx) const; diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index f16b7e91be..f799a38ae4 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -86,11 +86,8 @@ public: QRegularExpression(const QRegularExpression &re); ~QRegularExpression(); QRegularExpression &operator=(const QRegularExpression &re); - -#ifdef Q_COMPILER_RVALUE_REFS QRegularExpression &operator=(QRegularExpression &&re) noexcept { d.swap(re.d); return *this; } -#endif void swap(QRegularExpression &other) noexcept { d.swap(other.d); } @@ -186,11 +183,8 @@ public: ~QRegularExpressionMatch(); QRegularExpressionMatch(const QRegularExpressionMatch &match); QRegularExpressionMatch &operator=(const QRegularExpressionMatch &match); - -#ifdef Q_COMPILER_RVALUE_REFS QRegularExpressionMatch &operator=(QRegularExpressionMatch &&match) noexcept { d.swap(match.d); return *this; } -#endif void swap(QRegularExpressionMatch &other) noexcept { d.swap(other.d); } QRegularExpression regularExpression() const; @@ -257,10 +251,8 @@ public: ~QRegularExpressionMatchIterator(); QRegularExpressionMatchIterator(const QRegularExpressionMatchIterator &iterator); QRegularExpressionMatchIterator &operator=(const QRegularExpressionMatchIterator &iterator); -#ifdef Q_COMPILER_RVALUE_REFS QRegularExpressionMatchIterator &operator=(QRegularExpressionMatchIterator &&iterator) noexcept { d.swap(iterator.d); return *this; } -#endif void swap(QRegularExpressionMatchIterator &other) noexcept { d.swap(other.d); } bool isValid() const; diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index cbaa1aa3c4..04051472d6 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -112,7 +112,6 @@ public: } return *this; } -#ifdef Q_COMPILER_RVALUE_REFS QSharedDataPointer(QSharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; } inline QSharedDataPointer &operator=(QSharedDataPointer &&other) noexcept { @@ -120,7 +119,6 @@ public: swap(moved); return *this; } -#endif inline bool operator!() const { return !d; } @@ -218,7 +216,6 @@ public: } return *this; } -#ifdef Q_COMPILER_RVALUE_REFS inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) noexcept : d(o.d) { o.d = nullptr; } inline QExplicitlySharedDataPointer &operator=(QExplicitlySharedDataPointer &&other) noexcept { @@ -226,7 +223,6 @@ public: swap(moved); return *this; } -#endif inline bool operator!() const { return !d; } diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 0851121ff2..9fb452da6b 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -337,7 +337,6 @@ public: swap(copy); return *this; } -#ifdef Q_COMPILER_RVALUE_REFS QSharedPointer(QSharedPointer &&other) noexcept : value(other.value), d(other.d) { @@ -367,8 +366,6 @@ public: return *this; } -#endif - template QSharedPointer(const QSharedPointer &other) noexcept : value(other.value), d(other.d) { if (d) ref(); } @@ -590,7 +587,6 @@ public: QWeakPointer(const QWeakPointer &other) noexcept : d(other.d), value(other.value) { if (d) d->weakref.ref(); } -#ifdef Q_COMPILER_RVALUE_REFS QWeakPointer(QWeakPointer &&other) noexcept : d(other.d), value(other.value) { @@ -599,7 +595,6 @@ public: } QWeakPointer &operator=(QWeakPointer &&other) noexcept { QWeakPointer moved(std::move(other)); swap(moved); return *this; } -#endif QWeakPointer &operator=(const QWeakPointer &other) noexcept { QWeakPointer copy(other); diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index a526a6537a..e4798eb51b 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -230,11 +230,9 @@ public: QString &operator=(QChar c); QString &operator=(const QString &) noexcept; QString &operator=(QLatin1String latin1); -#ifdef Q_COMPILER_RVALUE_REFS inline QString(QString && other) noexcept : d(other.d) { other.d = Data::sharedNull(); } inline QString &operator=(QString &&other) noexcept { qSwap(d, other.d); return *this; } -#endif inline void swap(QString &other) noexcept { qSwap(d, other.d); } inline int size() const { return d->size; } inline int count() const { return d->size; } @@ -1437,10 +1435,8 @@ public: QStringRef(const QStringRef &other) noexcept :m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {} -#ifdef Q_COMPILER_RVALUE_REFS QStringRef(QStringRef &&other) noexcept : m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {} QStringRef &operator=(QStringRef &&other) noexcept { return *this = other; } -#endif QStringRef &operator=(const QStringRef &other) noexcept { m_string = other.m_string; m_position = other.m_position; diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index 5ad01a0658..73ac737643 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -104,9 +104,7 @@ public: inline QStringList() noexcept { } inline explicit QStringList(const QString &i) { append(i); } inline QStringList(const QList &l) : QList(l) { } -#ifdef Q_COMPILER_RVALUE_REFS inline QStringList(QList &&l) noexcept : QList(std::move(l)) { } -#endif #ifdef Q_COMPILER_INITIALIZER_LISTS inline QStringList(std::initializer_list args) : QList(args) { } #endif @@ -116,10 +114,8 @@ public: QStringList &operator=(const QList &other) { QList::operator=(other); return *this; } -#ifdef Q_COMPILER_RVALUE_REFS QStringList &operator=(QList &&other) noexcept { QList::operator=(std::move(other)); return *this; } -#endif #if QT_STRINGVIEW_LEVEL < 2 inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; diff --git a/src/corelib/tools/qtimezone.h b/src/corelib/tools/qtimezone.h index ca98986ec1..62ecee49bb 100644 --- a/src/corelib/tools/qtimezone.h +++ b/src/corelib/tools/qtimezone.h @@ -99,9 +99,7 @@ public: ~QTimeZone(); QTimeZone &operator=(const QTimeZone &other); - #ifdef Q_COMPILER_RVALUE_REFS QTimeZone &operator=(QTimeZone &&other) noexcept { swap(other); return *this; } -#endif void swap(QTimeZone &other) noexcept { d.swap(other.d); } diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 6cbf794c6c..7e14a0c9b2 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -72,11 +72,9 @@ public: inline QVector(const QVector &v); inline ~QVector() { if (!d->ref.deref()) freeData(d); } QVector &operator=(const QVector &v); -#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC) QVector(QVector &&other) noexcept : d(other.d) { other.d = Data::sharedNull(); } QVector &operator=(QVector &&other) noexcept { QVector moved(std::move(other)); swap(moved); return *this; } -#endif void swap(QVector &other) noexcept { qSwap(d, other.d); } #ifdef Q_COMPILER_INITIALIZER_LISTS inline QVector(std::initializer_list args); @@ -143,9 +141,7 @@ public: T &operator[](int i); const T &operator[](int i) const; void append(const T &t); -#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC) void append(T &&t); -#endif inline void append(const QVector &l) { *this += l; } void prepend(T &&t); void prepend(const T &t); @@ -268,10 +264,8 @@ public: typedef const_iterator ConstIterator; typedef int size_type; inline void push_back(const T &t) { append(t); } -#if defined(Q_COMPILER_RVALUE_REFS) || defined(Q_CLANG_QDOC) void push_back(T &&t) { append(std::move(t)); } void push_front(T &&t) { prepend(std::move(t)); } -#endif inline void push_front(const T &t) { prepend(t); } void pop_back() { removeLast(); } void pop_front() { removeFirst(); } @@ -799,7 +793,6 @@ void QVector::append(const T &t) ++d->size; } -#ifdef Q_COMPILER_RVALUE_REFS template void QVector::append(T &&t) { @@ -813,7 +806,6 @@ void QVector::append(T &&t) ++d->size; } -#endif template void QVector::removeLast() diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h index d51947c091..1488014d38 100644 --- a/src/corelib/tools/qversionnumber.h +++ b/src/corelib/tools/qversionnumber.h @@ -119,7 +119,6 @@ class QVersionNumber return *this; } -#ifdef Q_COMPILER_RVALUE_REFS SegmentStorage(SegmentStorage &&other) noexcept : dummy(other.dummy) { @@ -139,7 +138,6 @@ class QVersionNumber else pointer_segments = new QVector(std::move(seg)); } -#endif #ifdef Q_COMPILER_INITIALIZER_LISTS SegmentStorage(std::initializer_list args) { @@ -227,11 +225,9 @@ public: // compiler-generated copy/move ctor/assignment operators and the destructor are ok -#ifdef Q_COMPILER_RVALUE_REFS explicit QVersionNumber(QVector &&seg) : m_segments(std::move(seg)) {} -#endif #ifdef Q_COMPILER_INITIALIZER_LISTS inline QVersionNumber(std::initializer_list args) diff --git a/src/dbus/qdbusargument.h b/src/dbus/qdbusargument.h index 7f4bd269a9..b7cd4c8989 100644 --- a/src/dbus/qdbusargument.h +++ b/src/dbus/qdbusargument.h @@ -76,10 +76,8 @@ public: QDBusArgument(); QDBusArgument(const QDBusArgument &other); -#ifdef Q_COMPILER_RVALUE_REFS QDBusArgument(QDBusArgument &&other) noexcept : d(other.d) { other.d = nullptr; } QDBusArgument &operator=(QDBusArgument &&other) noexcept { swap(other); return *this; } -#endif QDBusArgument &operator=(const QDBusArgument &other); ~QDBusArgument(); diff --git a/src/dbus/qdbusconnection.h b/src/dbus/qdbusconnection.h index a880a7a939..368f811602 100644 --- a/src/dbus/qdbusconnection.h +++ b/src/dbus/qdbusconnection.h @@ -131,10 +131,8 @@ public: explicit QDBusConnection(const QString &name); QDBusConnection(const QDBusConnection &other); -#ifdef Q_COMPILER_RVALUE_REFS QDBusConnection(QDBusConnection &&other) noexcept : d(other.d) { other.d = nullptr; } QDBusConnection &operator=(QDBusConnection &&other) noexcept { swap(other); return *this; } -#endif QDBusConnection &operator=(const QDBusConnection &other); ~QDBusConnection(); diff --git a/src/dbus/qdbuserror.h b/src/dbus/qdbuserror.h index 5a68a417c4..bcf68dbcdc 100644 --- a/src/dbus/qdbuserror.h +++ b/src/dbus/qdbuserror.h @@ -98,12 +98,10 @@ public: #endif QDBusError(ErrorType error, const QString &message); QDBusError(const QDBusError &other); -#ifdef Q_COMPILER_RVALUE_REFS QDBusError(QDBusError &&other) noexcept : code(other.code), msg(std::move(other.msg)), nm(std::move(other.nm)) {} QDBusError &operator=(QDBusError &&other) noexcept { swap(other); return *this; } -#endif QDBusError &operator=(const QDBusError &other); #ifndef QT_BOOTSTRAPPED QDBusError &operator=(const QDBusMessage &msg); diff --git a/src/dbus/qdbusextratypes.h b/src/dbus/qdbusextratypes.h index e2430ad6f2..fdac917947 100644 --- a/src/dbus/qdbusextratypes.h +++ b/src/dbus/qdbusextratypes.h @@ -66,9 +66,7 @@ public: inline explicit QDBusObjectPath(const char *path); inline explicit QDBusObjectPath(QLatin1String path); inline explicit QDBusObjectPath(const QString &path); -#ifdef Q_COMPILER_RVALUE_REFS explicit QDBusObjectPath(QString &&p) : m_path(std::move(p)) { doCheck(); } -#endif void swap(QDBusObjectPath &other) noexcept { qSwap(m_path, other.m_path); } @@ -121,9 +119,7 @@ public: inline explicit QDBusSignature(const char *signature); inline explicit QDBusSignature(QLatin1String signature); inline explicit QDBusSignature(const QString &signature); -#ifdef Q_COMPILER_RVALUE_REFS explicit QDBusSignature(QString &&sig) : m_signature(std::move(sig)) { doCheck(); } -#endif void swap(QDBusSignature &other) noexcept { qSwap(m_signature, other.m_signature); } @@ -173,9 +169,7 @@ public: // compiler-generated destructor is ok! inline explicit QDBusVariant(const QVariant &variant); -#ifdef Q_COMPILER_RVALUE_REFS explicit QDBusVariant(QVariant &&v) noexcept : m_variant(std::move(v)) {} -#endif void swap(QDBusVariant &other) noexcept { qSwap(m_variant, other.m_variant); } diff --git a/src/dbus/qdbusmessage.h b/src/dbus/qdbusmessage.h index 3e73db70de..41845317c4 100644 --- a/src/dbus/qdbusmessage.h +++ b/src/dbus/qdbusmessage.h @@ -68,9 +68,7 @@ public: QDBusMessage(); QDBusMessage(const QDBusMessage &other); -#ifdef Q_COMPILER_RVALUE_REFS QDBusMessage &operator=(QDBusMessage &&other) noexcept { swap(other); return *this; } -#endif QDBusMessage &operator=(const QDBusMessage &other); ~QDBusMessage(); diff --git a/src/dbus/qdbuspendingcall.h b/src/dbus/qdbuspendingcall.h index c521b7d163..dd99346301 100644 --- a/src/dbus/qdbuspendingcall.h +++ b/src/dbus/qdbuspendingcall.h @@ -60,9 +60,7 @@ class Q_DBUS_EXPORT QDBusPendingCall public: QDBusPendingCall(const QDBusPendingCall &other); ~QDBusPendingCall(); -#ifdef Q_COMPILER_RVALUE_REFS QDBusPendingCall &operator=(QDBusPendingCall &&other) noexcept { swap(other); return *this; } -#endif QDBusPendingCall &operator=(const QDBusPendingCall &other); void swap(QDBusPendingCall &other) noexcept { qSwap(d, other.d); } diff --git a/src/dbus/qdbusunixfiledescriptor.h b/src/dbus/qdbusunixfiledescriptor.h index 6b264a6b86..fcd73b2ec5 100644 --- a/src/dbus/qdbusunixfiledescriptor.h +++ b/src/dbus/qdbusunixfiledescriptor.h @@ -46,9 +46,7 @@ #ifndef QT_NO_DBUS -#ifdef Q_COMPILER_RVALUE_REFS -# include -#endif +#include QT_BEGIN_NAMESPACE @@ -61,9 +59,7 @@ public: QDBusUnixFileDescriptor(); explicit QDBusUnixFileDescriptor(int fileDescriptor); QDBusUnixFileDescriptor(const QDBusUnixFileDescriptor &other); -#if defined(Q_COMPILER_RVALUE_REFS) QDBusUnixFileDescriptor &operator=(QDBusUnixFileDescriptor &&other) noexcept { swap(other); return *this; } -#endif QDBusUnixFileDescriptor &operator=(const QDBusUnixFileDescriptor &other); ~QDBusUnixFileDescriptor(); diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index 0f834fc2cb..735a3e134d 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -61,19 +61,15 @@ public: QIcon() noexcept; QIcon(const QPixmap &pixmap); QIcon(const QIcon &other); -#ifdef Q_COMPILER_RVALUE_REFS QIcon(QIcon &&other) noexcept : d(other.d) { other.d = nullptr; } -#endif explicit QIcon(const QString &fileName); // file or resource name explicit QIcon(QIconEngine *engine); ~QIcon(); QIcon &operator=(const QIcon &other); -#ifdef Q_COMPILER_RVALUE_REFS inline QIcon &operator=(QIcon &&other) noexcept { swap(other); return *this; } -#endif inline void swap(QIcon &other) noexcept { qSwap(d, other.d); } diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 9d177142d9..7c68168be8 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -151,18 +151,14 @@ public: explicit QImage(const QString &fileName, const char *format = nullptr); QImage(const QImage &); -#ifdef Q_COMPILER_RVALUE_REFS inline QImage(QImage &&other) noexcept : QPaintDevice(), d(nullptr) { qSwap(d, other.d); } -#endif ~QImage(); QImage &operator=(const QImage &); -#ifdef Q_COMPILER_RVALUE_REFS inline QImage &operator=(QImage &&other) noexcept { qSwap(d, other.d); return *this; } -#endif inline void swap(QImage &other) noexcept { qSwap(d, other.d); } diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h index cac2ef5dfc..189e57b9a3 100644 --- a/src/gui/image/qpicture.h +++ b/src/gui/image/qpicture.h @@ -78,10 +78,8 @@ public: void setBoundingRect(const QRect &r); QPicture& operator=(const QPicture &p); -#ifdef Q_COMPILER_RVALUE_REFS inline QPicture &operator=(QPicture &&other) noexcept { qSwap(d_ptr, other.d_ptr); return *this; } -#endif inline void swap(QPicture &other) noexcept { d_ptr.swap(other.d_ptr); } void detach(); diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index 2103fcc58c..8c1395857e 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -73,10 +73,8 @@ public: ~QPixmap(); QPixmap &operator=(const QPixmap &); -#ifdef Q_COMPILER_RVALUE_REFS inline QPixmap &operator=(QPixmap &&other) noexcept { qSwap(data, other.data); return *this; } -#endif inline void swap(QPixmap &other) noexcept { qSwap(data, other.data); } @@ -139,12 +137,10 @@ public: QImage toImage() const; static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor); static QPixmap fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags = Qt::AutoColor); -#ifdef Q_COMPILER_RVALUE_REFS static QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags = Qt::AutoColor) { return fromImageInPlace(image, flags); } -#endif bool load(const QString& fileName, const char *format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor); bool loadFromData(const uchar *buf, uint len, const char* format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor); diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h index c5bedb27ab..55af35a5d9 100644 --- a/src/gui/image/qpixmapcache.h +++ b/src/gui/image/qpixmapcache.h @@ -55,10 +55,8 @@ public: public: Key(); Key(const Key &other); -#ifdef Q_COMPILER_RVALUE_REFS Key(Key &&other) noexcept : d(other.d) { other.d = nullptr; } Key &operator =(Key &&other) noexcept { swap(other); return *this; } -#endif ~Key(); bool operator ==(const Key &key) const; inline bool operator !=(const Key &key) const diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h index ced166dc29..7966e35840 100644 --- a/src/gui/kernel/qcursor.h +++ b/src/gui/kernel/qcursor.h @@ -86,11 +86,9 @@ public: QCursor(const QCursor &cursor); ~QCursor(); QCursor &operator=(const QCursor &cursor); -#ifdef Q_COMPILER_RVALUE_REFS QCursor(QCursor &&other) noexcept : d(other.d) { other.d = nullptr; } inline QCursor &operator=(QCursor &&other) noexcept { swap(other); return *this; } -#endif void swap(QCursor &other) noexcept { qSwap(d, other.d); } diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index aeefb53819..eb0a6208a9 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -855,13 +855,11 @@ public: explicit TouchPoint(int id = -1); TouchPoint(const TouchPoint &other); -#ifdef Q_COMPILER_RVALUE_REFS TouchPoint(TouchPoint &&other) noexcept : d(nullptr) { qSwap(d, other.d); } TouchPoint &operator=(TouchPoint &&other) noexcept { qSwap(d, other.d); return *this; } -#endif ~TouchPoint(); TouchPoint &operator=(const TouchPoint &other) diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h index 5630bdda58..3dcbbe5941 100644 --- a/src/gui/kernel/qkeysequence.h +++ b/src/gui/kernel/qkeysequence.h @@ -186,9 +186,7 @@ public: operator QVariant() const; int operator[](uint i) const; QKeySequence &operator=(const QKeySequence &other); -#ifdef Q_COMPILER_RVALUE_REFS QKeySequence &operator=(QKeySequence &&other) noexcept { swap(other); return *this; } -#endif void swap(QKeySequence &other) noexcept { qSwap(d, other.d); } bool operator==(const QKeySequence &other) const; diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h index a463245d4d..d3a840d9ad 100644 --- a/src/gui/kernel/qpalette.h +++ b/src/gui/kernel/qpalette.h @@ -67,7 +67,6 @@ public: QPalette(const QPalette &palette); ~QPalette(); QPalette &operator=(const QPalette &palette); -#ifdef Q_COMPILER_RVALUE_REFS QPalette(QPalette &&other) noexcept : d(other.d), data(other.data) { other.d = nullptr; } @@ -76,7 +75,6 @@ public: for_faster_swapping_dont_use = other.for_faster_swapping_dont_use; qSwap(d, other.d); return *this; } -#endif void swap(QPalette &other) noexcept { diff --git a/src/gui/opengl/qopengldebug.h b/src/gui/opengl/qopengldebug.h index 1ba3ef91ac..7363985d60 100644 --- a/src/gui/opengl/qopengldebug.h +++ b/src/gui/opengl/qopengldebug.h @@ -110,9 +110,7 @@ public: QOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage); QOpenGLDebugMessage &operator=(const QOpenGLDebugMessage &debugMessage); -#ifdef Q_COMPILER_RVALUE_REFS QOpenGLDebugMessage &operator=(QOpenGLDebugMessage &&other) noexcept { swap(other); return *this; } -#endif ~QOpenGLDebugMessage(); void swap(QOpenGLDebugMessage &other) noexcept { qSwap(d, other.d); } diff --git a/src/gui/opengl/qopenglpixeltransferoptions.h b/src/gui/opengl/qopenglpixeltransferoptions.h index be60e66e71..195543ae90 100644 --- a/src/gui/opengl/qopenglpixeltransferoptions.h +++ b/src/gui/opengl/qopenglpixeltransferoptions.h @@ -55,10 +55,8 @@ class Q_GUI_EXPORT QOpenGLPixelTransferOptions public: QOpenGLPixelTransferOptions(); QOpenGLPixelTransferOptions(const QOpenGLPixelTransferOptions &); -#ifdef Q_COMPILER_RVALUE_REFS QOpenGLPixelTransferOptions &operator=(QOpenGLPixelTransferOptions &&other) noexcept { swap(other); return *this; } -#endif QOpenGLPixelTransferOptions &operator=(const QOpenGLPixelTransferOptions &); ~QOpenGLPixelTransferOptions(); diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index 27d710eca6..ef8f7a18de 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -79,10 +79,8 @@ public: ~QBrush(); QBrush &operator=(const QBrush &brush); -#ifdef Q_COMPILER_RVALUE_REFS inline QBrush &operator=(QBrush &&other) noexcept { qSwap(d, other.d); return *this; } -#endif inline void swap(QBrush &other) noexcept { qSwap(d, other.d); } diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h index 77b2d43c40..e3c267f97d 100644 --- a/src/gui/painting/qcolor.h +++ b/src/gui/painting/qcolor.h @@ -82,11 +82,9 @@ public: #if QT_VERSION < QT_VERSION_CHECK(6,0,0) inline QColor(const QColor &color) noexcept; // ### Qt 6: remove all of these, the trivial ones are fine. -# ifdef Q_COMPILER_RVALUE_REFS QColor(QColor &&other) noexcept : cspec(other.cspec), ct(other.ct) {} QColor &operator=(QColor &&other) noexcept { cspec = other.cspec; ct = other.ct; return *this; } -# endif QColor &operator=(const QColor &) noexcept; #endif // Qt < 6 diff --git a/src/gui/painting/qpagelayout.h b/src/gui/painting/qpagelayout.h index faf0827c1a..7ee0ce7a76 100644 --- a/src/gui/painting/qpagelayout.h +++ b/src/gui/painting/qpagelayout.h @@ -82,9 +82,7 @@ public: const QMarginsF &margins, Unit units = Point, const QMarginsF &minMargins = QMarginsF(0, 0, 0, 0)); QPageLayout(const QPageLayout &other); -#ifdef Q_COMPILER_RVALUE_REFS QPageLayout &operator=(QPageLayout &&other) noexcept { swap(other); return *this; } -#endif QPageLayout &operator=(const QPageLayout &other); ~QPageLayout(); diff --git a/src/gui/painting/qpagesize.h b/src/gui/painting/qpagesize.h index a2ea691677..133274760f 100644 --- a/src/gui/painting/qpagesize.h +++ b/src/gui/painting/qpagesize.h @@ -236,9 +236,7 @@ public: const QString &name = QString(), SizeMatchPolicy matchPolicy = FuzzyMatch); QPageSize(const QPageSize &other); -#ifdef Q_COMPILER_RVALUE_REFS QPageSize &operator=(QPageSize &&other) noexcept { swap(other); return *this; } -#endif QPageSize &operator=(const QPageSize &other); ~QPageSize(); diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h index 2785669260..ed5be667b7 100644 --- a/src/gui/painting/qpainterpath.h +++ b/src/gui/painting/qpainterpath.h @@ -92,10 +92,8 @@ public: explicit QPainterPath(const QPointF &startPoint); QPainterPath(const QPainterPath &other); QPainterPath &operator=(const QPainterPath &other); -#ifdef Q_COMPILER_RVALUE_REFS inline QPainterPath &operator=(QPainterPath &&other) noexcept { qSwap(d_ptr, other.d_ptr); return *this; } -#endif ~QPainterPath(); inline void swap(QPainterPath &other) noexcept { d_ptr.swap(other.d_ptr); } diff --git a/src/gui/painting/qpen.h b/src/gui/painting/qpen.h index 884ec8cdfa..10b11d1d85 100644 --- a/src/gui/painting/qpen.h +++ b/src/gui/painting/qpen.h @@ -70,12 +70,10 @@ public: ~QPen(); QPen &operator=(const QPen &pen) noexcept; -#ifdef Q_COMPILER_RVALUE_REFS QPen(QPen &&other) noexcept : d(other.d) { other.d = nullptr; } QPen &operator=(QPen &&other) noexcept { qSwap(d, other.d); return *this; } -#endif void swap(QPen &other) noexcept { qSwap(d, other.d); } Qt::PenStyle style() const; diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h index 118861c0f2..93fab55aa1 100644 --- a/src/gui/painting/qpolygon.h +++ b/src/gui/painting/qpolygon.h @@ -60,16 +60,12 @@ public: inline ~QPolygon() {} inline explicit QPolygon(int size); inline /*implicit*/ QPolygon(const QVector &v) : QVector(v) {} -#ifdef Q_COMPILER_RVALUE_REFS /*implicit*/ QPolygon(QVector &&v) noexcept : QVector(std::move(v)) {} -#endif QPolygon(const QRect &r, bool closed=false); QPolygon(int nPoints, const int *points); QPolygon(const QPolygon &other) : QVector(other) {} -#ifdef Q_COMPILER_RVALUE_REFS QPolygon(QPolygon &&other) noexcept : QVector(std::move(other)) {} QPolygon &operator=(QPolygon &&other) noexcept { swap(other); return *this; } -#endif QPolygon &operator=(const QPolygon &other) { QVector::operator=(other); return *this; } void swap(QPolygon &other) noexcept { QVector::swap(other); } // prevent QVector<->QPolygon swaps @@ -145,16 +141,12 @@ public: inline ~QPolygonF() {} inline explicit QPolygonF(int size); inline /*implicit*/ QPolygonF(const QVector &v) : QVector(v) {} -#ifdef Q_COMPILER_RVALUE_REFS /* implicit */ QPolygonF(QVector &&v) noexcept : QVector(std::move(v)) {} -#endif QPolygonF(const QRectF &r); /*implicit*/ QPolygonF(const QPolygon &a); inline QPolygonF(const QPolygonF &a) : QVector(a) {} -#ifdef Q_COMPILER_RVALUE_REFS QPolygonF(QPolygonF &&other) noexcept : QVector(std::move(other)) {} QPolygonF &operator=(QPolygonF &&other) noexcept { swap(other); return *this; } -#endif QPolygonF &operator=(const QPolygonF &other) { QVector::operator=(other); return *this; } inline void swap(QPolygonF &other) { QVector::swap(other); } // prevent QVector<->QPolygonF swaps diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index 9b6b25d743..54de916198 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -74,10 +74,8 @@ public: QRegion(const QBitmap &bitmap); ~QRegion(); QRegion &operator=(const QRegion &); -#ifdef Q_COMPILER_RVALUE_REFS inline QRegion &operator=(QRegion &&other) noexcept { qSwap(d, other.d); return *this; } -#endif inline void swap(QRegion &other) noexcept { qSwap(d, other.d); } bool isEmpty() const; bool isNull() const; diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index 16685ed9e8..683aa3bf65 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -261,10 +261,8 @@ public: bool operator<(const QFont &) const; operator QVariant() const; bool isCopyOf(const QFont &) const; -#ifdef Q_COMPILER_RVALUE_REFS inline QFont &operator=(QFont &&other) noexcept { qSwap(d, other.d); qSwap(resolve_mask, other.resolve_mask); return *this; } -#endif #if QT_DEPRECATED_SINCE(5, 3) // needed for X11 diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h index 761cadde47..a92ee9ed2f 100644 --- a/src/gui/text/qfontmetrics.h +++ b/src/gui/text/qfontmetrics.h @@ -76,10 +76,8 @@ public: ~QFontMetrics(); QFontMetrics &operator=(const QFontMetrics &); -#ifdef Q_COMPILER_RVALUE_REFS inline QFontMetrics &operator=(QFontMetrics &&other) noexcept { qSwap(d, other.d); return *this; } -#endif void swap(QFontMetrics &other) noexcept { qSwap(d, other.d); } @@ -172,10 +170,8 @@ public: QFontMetricsF &operator=(const QFontMetricsF &); QFontMetricsF &operator=(const QFontMetrics &); -#ifdef Q_COMPILER_RVALUE_REFS inline QFontMetricsF &operator=(QFontMetricsF &&other) { qSwap(d, other.d); return *this; } -#endif void swap(QFontMetricsF &other) { qSwap(d, other.d); } diff --git a/src/gui/text/qglyphrun.h b/src/gui/text/qglyphrun.h index 9bb1d3c820..15e315bea2 100644 --- a/src/gui/text/qglyphrun.h +++ b/src/gui/text/qglyphrun.h @@ -66,9 +66,7 @@ public: QGlyphRun(); QGlyphRun(const QGlyphRun &other); -#ifdef Q_COMPILER_RVALUE_REFS QGlyphRun &operator=(QGlyphRun &&other) noexcept { swap(other); return *this; } -#endif QGlyphRun &operator=(const QGlyphRun &other); ~QGlyphRun(); diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h index 3b84f642d3..c6289d6c93 100644 --- a/src/gui/text/qrawfont.h +++ b/src/gui/text/qrawfont.h @@ -79,9 +79,7 @@ public: qreal pixelSize, QFont::HintingPreference hintingPreference = QFont::PreferDefaultHinting); QRawFont(const QRawFont &other); -#ifdef Q_COMPILER_RVALUE_REFS QRawFont &operator=(QRawFont &&other) noexcept { swap(other); return *this; } -#endif QRawFont &operator=(const QRawFont &other); ~QRawFont(); diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h index c6a0d158c1..e8c94a6add 100644 --- a/src/gui/text/qstatictext.h +++ b/src/gui/text/qstatictext.h @@ -64,9 +64,7 @@ public: QStaticText(); explicit QStaticText(const QString &text); QStaticText(const QStaticText &other); -#ifdef Q_COMPILER_RVALUE_REFS QStaticText &operator=(QStaticText &&other) noexcept { swap(other); return *this; } -#endif QStaticText &operator=(const QStaticText &); ~QStaticText(); diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h index 4a9c614887..7cad3cc5e8 100644 --- a/src/gui/text/qtextcursor.h +++ b/src/gui/text/qtextcursor.h @@ -73,9 +73,7 @@ public: explicit QTextCursor(QTextFrame *frame); explicit QTextCursor(const QTextBlock &block); QTextCursor(const QTextCursor &cursor); -#ifdef Q_COMPILER_RVALUE_REFS QTextCursor &operator=(QTextCursor &&other) noexcept { swap(other); return *this; } -#endif QTextCursor &operator=(const QTextCursor &other); ~QTextCursor(); diff --git a/src/network/access/qabstractnetworkcache.h b/src/network/access/qabstractnetworkcache.h index b604323c41..e357dfe58f 100644 --- a/src/network/access/qabstractnetworkcache.h +++ b/src/network/access/qabstractnetworkcache.h @@ -67,9 +67,7 @@ public: QNetworkCacheMetaData(const QNetworkCacheMetaData &other); ~QNetworkCacheMetaData(); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkCacheMetaData &operator=(QNetworkCacheMetaData &&other) noexcept { swap(other); return *this; } -#endif QNetworkCacheMetaData &operator=(const QNetworkCacheMetaData &other); void swap(QNetworkCacheMetaData &other) noexcept diff --git a/src/network/access/qhttpmultipart.h b/src/network/access/qhttpmultipart.h index f718d51d0c..56db83779a 100644 --- a/src/network/access/qhttpmultipart.h +++ b/src/network/access/qhttpmultipart.h @@ -60,9 +60,7 @@ public: QHttpPart(); QHttpPart(const QHttpPart &other); ~QHttpPart(); -#ifdef Q_COMPILER_RVALUE_REFS QHttpPart &operator=(QHttpPart &&other) noexcept { swap(other); return *this; } -#endif QHttpPart &operator=(const QHttpPart &other); void swap(QHttpPart &other) noexcept { qSwap(d, other.d); } diff --git a/src/network/access/qnetworkcookie.h b/src/network/access/qnetworkcookie.h index 58c504f9ae..b712b63849 100644 --- a/src/network/access/qnetworkcookie.h +++ b/src/network/access/qnetworkcookie.h @@ -66,9 +66,7 @@ public: explicit QNetworkCookie(const QByteArray &name = QByteArray(), const QByteArray &value = QByteArray()); QNetworkCookie(const QNetworkCookie &other); ~QNetworkCookie(); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkCookie &operator=(QNetworkCookie &&other) noexcept { swap(other); return *this; } -#endif QNetworkCookie &operator=(const QNetworkCookie &other); void swap(QNetworkCookie &other) noexcept { qSwap(d, other.d); } diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index 2515ff6ead..de27b9fede 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -130,9 +130,7 @@ public: explicit QNetworkRequest(const QUrl &url = QUrl()); QNetworkRequest(const QNetworkRequest &other); ~QNetworkRequest(); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkRequest &operator=(QNetworkRequest &&other) noexcept { swap(other); return *this; } -#endif QNetworkRequest &operator=(const QNetworkRequest &other); void swap(QNetworkRequest &other) noexcept { qSwap(d, other.d); } diff --git a/src/network/bearer/qnetworkconfiguration.h b/src/network/bearer/qnetworkconfiguration.h index 41b6e6f020..048abc2fc8 100644 --- a/src/network/bearer/qnetworkconfiguration.h +++ b/src/network/bearer/qnetworkconfiguration.h @@ -55,9 +55,7 @@ class Q_NETWORK_EXPORT QNetworkConfiguration public: QNetworkConfiguration(); QNetworkConfiguration(const QNetworkConfiguration& other); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkConfiguration &operator=(QNetworkConfiguration &&other) noexcept { swap(other); return *this; } -#endif QNetworkConfiguration &operator=(const QNetworkConfiguration &other); ~QNetworkConfiguration(); diff --git a/src/network/kernel/qdnslookup.h b/src/network/kernel/qdnslookup.h index 79a476b98f..110a74da44 100644 --- a/src/network/kernel/qdnslookup.h +++ b/src/network/kernel/qdnslookup.h @@ -64,9 +64,7 @@ class Q_NETWORK_EXPORT QDnsDomainNameRecord public: QDnsDomainNameRecord(); QDnsDomainNameRecord(const QDnsDomainNameRecord &other); -#ifdef Q_COMPILER_RVALUE_REFS QDnsDomainNameRecord &operator=(QDnsDomainNameRecord &&other) noexcept { swap(other); return *this; } -#endif QDnsDomainNameRecord &operator=(const QDnsDomainNameRecord &other); ~QDnsDomainNameRecord(); @@ -88,9 +86,7 @@ class Q_NETWORK_EXPORT QDnsHostAddressRecord public: QDnsHostAddressRecord(); QDnsHostAddressRecord(const QDnsHostAddressRecord &other); -#ifdef Q_COMPILER_RVALUE_REFS QDnsHostAddressRecord &operator=(QDnsHostAddressRecord &&other) noexcept { swap(other); return *this; } -#endif QDnsHostAddressRecord &operator=(const QDnsHostAddressRecord &other); ~QDnsHostAddressRecord(); @@ -112,9 +108,7 @@ class Q_NETWORK_EXPORT QDnsMailExchangeRecord public: QDnsMailExchangeRecord(); QDnsMailExchangeRecord(const QDnsMailExchangeRecord &other); -#ifdef Q_COMPILER_RVALUE_REFS QDnsMailExchangeRecord &operator=(QDnsMailExchangeRecord &&other) noexcept { swap(other); return *this; } -#endif QDnsMailExchangeRecord &operator=(const QDnsMailExchangeRecord &other); ~QDnsMailExchangeRecord(); @@ -137,9 +131,7 @@ class Q_NETWORK_EXPORT QDnsServiceRecord public: QDnsServiceRecord(); QDnsServiceRecord(const QDnsServiceRecord &other); -#ifdef Q_COMPILER_RVALUE_REFS QDnsServiceRecord &operator=(QDnsServiceRecord &&other) noexcept { swap(other); return *this; } -#endif QDnsServiceRecord &operator=(const QDnsServiceRecord &other); ~QDnsServiceRecord(); @@ -164,9 +156,7 @@ class Q_NETWORK_EXPORT QDnsTextRecord public: QDnsTextRecord(); QDnsTextRecord(const QDnsTextRecord &other); -#ifdef Q_COMPILER_RVALUE_REFS QDnsTextRecord &operator=(QDnsTextRecord &&other) noexcept { swap(other); return *this; } -#endif QDnsTextRecord &operator=(const QDnsTextRecord &other); ~QDnsTextRecord(); diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h index f20da3304f..799247695e 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -102,11 +102,8 @@ public: QHostAddress(SpecialAddress address); ~QHostAddress(); -#ifdef Q_COMPILER_RVALUE_REFS QHostAddress &operator=(QHostAddress &&other) noexcept { swap(other); return *this; } -#endif - QHostAddress &operator=(const QHostAddress &other); #if QT_DEPRECATED_SINCE(5, 8) QT_DEPRECATED_X("use = QHostAddress(string) instead") diff --git a/src/network/kernel/qnetworkinterface.h b/src/network/kernel/qnetworkinterface.h index 1d3286118e..4caedaa38f 100644 --- a/src/network/kernel/qnetworkinterface.h +++ b/src/network/kernel/qnetworkinterface.h @@ -64,9 +64,7 @@ public: QNetworkAddressEntry(); QNetworkAddressEntry(const QNetworkAddressEntry &other); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkAddressEntry &operator=(QNetworkAddressEntry &&other) noexcept { swap(other); return *this; } -#endif QNetworkAddressEntry &operator=(const QNetworkAddressEntry &other); ~QNetworkAddressEntry(); @@ -142,9 +140,7 @@ public: QNetworkInterface(); QNetworkInterface(const QNetworkInterface &other); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkInterface &operator=(QNetworkInterface &&other) noexcept { swap(other); return *this; } -#endif QNetworkInterface &operator=(const QNetworkInterface &other); ~QNetworkInterface(); diff --git a/src/network/kernel/qnetworkproxy.h b/src/network/kernel/qnetworkproxy.h index 0b1bc02695..302a2ce6ca 100644 --- a/src/network/kernel/qnetworkproxy.h +++ b/src/network/kernel/qnetworkproxy.h @@ -89,9 +89,7 @@ public: QueryType queryType = TcpServer); #endif QNetworkProxyQuery(const QNetworkProxyQuery &other); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkProxyQuery &operator=(QNetworkProxyQuery &&other) noexcept { swap(other); return *this; } -#endif QNetworkProxyQuery &operator=(const QNetworkProxyQuery &other); ~QNetworkProxyQuery(); @@ -161,9 +159,7 @@ public: QNetworkProxy(ProxyType type, const QString &hostName = QString(), quint16 port = 0, const QString &user = QString(), const QString &password = QString()); QNetworkProxy(const QNetworkProxy &other); -#ifdef Q_COMPILER_RVALUE_REFS QNetworkProxy &operator=(QNetworkProxy &&other) noexcept { swap(other); return *this; } -#endif QNetworkProxy &operator=(const QNetworkProxy &other); ~QNetworkProxy(); diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index a6acfa2cc3..69901b526c 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -88,9 +88,7 @@ public: explicit QSslCertificate(const QByteArray &data = QByteArray(), QSsl::EncodingFormat format = QSsl::Pem); QSslCertificate(const QSslCertificate &other); ~QSslCertificate(); -#ifdef Q_COMPILER_RVALUE_REFS QSslCertificate &operator=(QSslCertificate &&other) noexcept { swap(other); return *this; } -#endif QSslCertificate &operator=(const QSslCertificate &other); void swap(QSslCertificate &other) noexcept diff --git a/src/network/ssl/qsslcertificateextension.h b/src/network/ssl/qsslcertificateextension.h index f862015312..7cc8a888be 100644 --- a/src/network/ssl/qsslcertificateextension.h +++ b/src/network/ssl/qsslcertificateextension.h @@ -55,9 +55,7 @@ class Q_NETWORK_EXPORT QSslCertificateExtension public: QSslCertificateExtension(); QSslCertificateExtension(const QSslCertificateExtension &other); -#ifdef Q_COMPILER_RVALUE_REFS QSslCertificateExtension &operator=(QSslCertificateExtension &&other) noexcept { swap(other); return *this; } -#endif QSslCertificateExtension &operator=(const QSslCertificateExtension &other); ~QSslCertificateExtension(); diff --git a/src/network/ssl/qsslcipher.h b/src/network/ssl/qsslcipher.h index 430fe9aa7c..6994f590ae 100644 --- a/src/network/ssl/qsslcipher.h +++ b/src/network/ssl/qsslcipher.h @@ -59,9 +59,7 @@ public: explicit QSslCipher(const QString &name); QSslCipher(const QString &name, QSsl::SslProtocol protocol); QSslCipher(const QSslCipher &other); -#ifdef Q_COMPILER_RVALUE_REFS QSslCipher &operator=(QSslCipher &&other) noexcept { swap(other); return *this; } -#endif QSslCipher &operator=(const QSslCipher &other); ~QSslCipher(); diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h index 16704ba17b..c25c2686de 100644 --- a/src/network/ssl/qsslconfiguration.h +++ b/src/network/ssl/qsslconfiguration.h @@ -85,9 +85,7 @@ public: QSslConfiguration(); QSslConfiguration(const QSslConfiguration &other); ~QSslConfiguration(); -#ifdef Q_COMPILER_RVALUE_REFS QSslConfiguration &operator=(QSslConfiguration &&other) noexcept { swap(other); return *this; } -#endif QSslConfiguration &operator=(const QSslConfiguration &other); void swap(QSslConfiguration &other) noexcept diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h index a9c46c8571..c4a0d52193 100644 --- a/src/network/ssl/qsslerror.h +++ b/src/network/ssl/qsslerror.h @@ -107,9 +107,7 @@ public: { qSwap(d, other.d); } ~QSslError(); -#ifdef Q_COMPILER_RVALUE_REFS QSslError &operator=(QSslError &&other) noexcept { swap(other); return *this; } -#endif QSslError &operator=(const QSslError &other); bool operator==(const QSslError &other) const; inline bool operator!=(const QSslError &other) const diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.h b/src/network/ssl/qsslpresharedkeyauthenticator.h index 29d647b121..5d714dc34e 100644 --- a/src/network/ssl/qsslpresharedkeyauthenticator.h +++ b/src/network/ssl/qsslpresharedkeyauthenticator.h @@ -59,9 +59,7 @@ public: Q_NETWORK_EXPORT QSslPreSharedKeyAuthenticator(const QSslPreSharedKeyAuthenticator &authenticator); Q_NETWORK_EXPORT QSslPreSharedKeyAuthenticator &operator=(const QSslPreSharedKeyAuthenticator &authenticator); -#ifdef Q_COMPILER_RVALUE_REFS QSslPreSharedKeyAuthenticator &operator=(QSslPreSharedKeyAuthenticator &&other) noexcept { swap(other); return *this; } -#endif void swap(QSslPreSharedKeyAuthenticator &other) noexcept { qSwap(d, other.d); } diff --git a/src/printsupport/kernel/qprintdevice_p.h b/src/printsupport/kernel/qprintdevice_p.h index a2b18f08cf..9e76c37617 100644 --- a/src/printsupport/kernel/qprintdevice_p.h +++ b/src/printsupport/kernel/qprintdevice_p.h @@ -76,9 +76,7 @@ public: ~QPrintDevice(); QPrintDevice &operator=(const QPrintDevice &other); - #ifdef Q_COMPILER_RVALUE_REFS QPrintDevice &operator=(QPrintDevice &&other) { swap(other); return *this; } -#endif void swap(QPrintDevice &other) { d.swap(other.d); } diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index 56da047147..5e5492de59 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -456,12 +456,8 @@ typedef int (Empty::*memFun) (); } while (false) \ /**/ -#ifdef Q_COMPILER_RVALUE_REFS #define TEST_AlignOf_RValueRef(type, alignment) \ TEST_AlignOf_impl(type, alignment) -#else -#define TEST_AlignOf_RValueRef(type, alignment) do {} while (false) -#endif #define TEST_AlignOf_impl(type, alignment) \ do { \ diff --git a/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp b/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp index fd18f00cd0..39b03ade61 100644 --- a/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp +++ b/tests/auto/corelib/kernel/qsignalblocker/tst_qsignalblocker.cpp @@ -66,7 +66,6 @@ void tst_QSignalBlocker::signalBlocking() void tst_QSignalBlocker::moveAssignment() { -#ifdef Q_COMPILER_RVALUE_REFS QObject o1, o2; // move-assignment: both block other objects @@ -157,10 +156,6 @@ void tst_QSignalBlocker::moveAssignment() QVERIFY(!o1.signalsBlocked()); QVERIFY(!o2.signalsBlocked()); - -#else - QSKIP("This compiler is not in C++11 mode or doesn't support move semantics"); -#endif // Q_COMPILER_RVALUE_REFS } QTEST_MAIN(tst_QSignalBlocker) diff --git a/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp b/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp index c74bce3b5b..e1357245f3 100644 --- a/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp +++ b/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp @@ -91,11 +91,7 @@ static QStringList qMimeTypeGlobPatterns() // ------------------------------------------------------------------------------------------------ -#ifndef Q_COMPILER_RVALUE_REFS -QMIMETYPE_BUILDER -#else QMIMETYPE_BUILDER_FROM_RVALUE_REFS -#endif // ------------------------------------------------------------------------------------------------ diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp index 2d1ae07b35..6ae2aab5b9 100644 --- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp +++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp @@ -79,9 +79,7 @@ private slots: void fromRawData(); void literals(); void variadicLiterals(); -#ifdef Q_COMPILER_RVALUE_REFS void rValueReferences(); -#endif void grow(); }; @@ -1678,7 +1676,6 @@ void tst_QArrayData::variadicLiterals() } } -#ifdef Q_COMPILER_RVALUE_REFS // std::remove_reference is in C++11, but requires library support template struct RemoveReference { typedef T Type; }; template struct RemoveReference { typedef T Type; }; @@ -1761,7 +1758,6 @@ void tst_QArrayData::rValueReferences() QCOMPARE(v3.size(), size_t(1)); QCOMPARE(v3.front(), 42); } -#endif void tst_QArrayData::grow() { diff --git a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp index 72f88a235d..2ae9c6e159 100644 --- a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp +++ b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp @@ -47,7 +47,6 @@ private Q_SLOTS: void state(); }; -#ifdef Q_COMPILER_RVALUE_REFS static bool dpointer_is_null(QCollator &c) { char mem[sizeof c]; @@ -58,11 +57,9 @@ static bool dpointer_is_null(QCollator &c) return false; return true; } -#endif void tst_QCollator::moveSemantics() { -#ifdef Q_COMPILER_RVALUE_REFS const QLocale de_AT(QLocale::German, QLocale::Austria); QCollator c1(de_AT); @@ -78,9 +75,6 @@ void tst_QCollator::moveSemantics() c1 = std::move(c2); QCOMPARE(c1.locale(), de_AT); QVERIFY(dpointer_is_null(c2)); -#else - QSKIP("The compiler is not in C++11 mode or does not support move semantics."); -#endif } diff --git a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp index c21d0afacb..3af6132695 100644 --- a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp +++ b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp @@ -30,9 +30,7 @@ #include -#ifdef Q_COMPILER_RVALUE_REFS // cpp11() slot -# include // for std::move() -#endif +#include // for std::move() class tst_QEasingCurve : public QObject { @@ -794,7 +792,6 @@ void tst_QEasingCurve::testCbrtFloat() void tst_QEasingCurve::cpp11() { -#ifdef Q_COMPILER_RVALUE_REFS { QEasingCurve ec( QEasingCurve::InOutBack ); QEasingCurve copy = std::move(ec); // move ctor @@ -809,7 +806,6 @@ void tst_QEasingCurve::cpp11() QCOMPARE( copy.type(), QEasingCurve::InOutBack ); QCOMPARE( ec.type(), type ); } -#endif } void tst_QEasingCurve::quadraticEquation() { diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index 3e87a506bf..42792b5310 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -225,13 +225,11 @@ struct NoDefaultConstructorConstRef2 NoDefaultConstructorConstRef2(const QByteArray &ba, int i = 42) : str(QString::fromLatin1(ba)), i(i) {} }; -#ifdef Q_COMPILER_RVALUE_REFS struct NoDefaultConstructorRRef1 { int &i; NoDefaultConstructorRRef1(int &&i) : i(i) {} }; -#endif void tst_QSharedPointer::basics_data() { @@ -500,7 +498,6 @@ void tst_QSharedPointer::swap() void tst_QSharedPointer::moveSemantics() { -#ifdef Q_COMPILER_RVALUE_REFS QSharedPointer p1, p2(new int(42)), control = p2; QVERIFY(p1 != control); QVERIFY(p1.isNull()); @@ -553,9 +550,6 @@ void tst_QSharedPointer::moveSemantics() QVERIFY(w1.isNull()); QVERIFY(w2.isNull()); QVERIFY(w3.isNull()); -#else - QSKIP("This test requires C++11 rvalue/move semantics support in the compiler."); -#endif } void tst_QSharedPointer::useOfForwardDeclared() diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index 2278e0ba13..f7e7c3e3ae 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -709,7 +709,6 @@ void tst_QVector::appendCustom() const void tst_QVector::appendRvalue() const { -#ifdef Q_COMPILER_RVALUE_REFS QVector v; v.append("hello"); QString world = "world"; @@ -717,9 +716,6 @@ void tst_QVector::appendRvalue() const QVERIFY(world.isEmpty()); QCOMPARE(v.front(), QString("hello")); QCOMPARE(v.back(), QString("world")); -#else - QSKIP("This test requires that C++11 move semantics support is enabled in the compiler"); -#endif } void tst_QVector::at() const diff --git a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp index aaf40a9c2e..9bc8c84ee4 100644 --- a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp +++ b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp @@ -586,7 +586,6 @@ void tst_QVersionNumber::serialize() void tst_QVersionNumber::moveSemantics() { -#ifdef Q_COMPILER_RVALUE_REFS // QVersionNumber(QVersionNumber &&) { QVersionNumber v1(1, 2, 3); @@ -609,7 +608,6 @@ void tst_QVersionNumber::moveSemantics() QVERIFY(!v2.isNull()); QCOMPARE(v1, v2); } -#endif #ifdef Q_COMPILER_REF_QUALIFIERS // normalized() { @@ -636,9 +634,6 @@ void tst_QVersionNumber::moveSemantics() QVERIFY(!segments.empty()); } #endif -#if !defined(Q_COMPILER_RVALUE_REFS) && !defined(Q_COMPILER_REF_QUALIFIERS) - QSKIP("This test requires C++11 move semantics support in the compiler."); -#endif } void tst_QVersionNumber::qtVersion() diff --git a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp index 234793a7cf..6ce6422f48 100644 --- a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp +++ b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp @@ -141,7 +141,6 @@ void tst_QPalette::copySemantics() void tst_QPalette::moveSemantics() { -#ifdef Q_COMPILER_RVALUE_REFS QPalette src(Qt::red), dst; const QPalette control = src; QVERIFY(src != dst); @@ -163,9 +162,6 @@ void tst_QPalette::moveSemantics() QVERIFY(dst2.isCopyOf(dst)); QVERIFY(dst2.isCopyOf(control)); // check moved-from 'src' can still be destroyed (doesn't crash) -#else - QSKIP("Compiler doesn't support C++11 move semantics"); -#endif } void tst_QPalette::setBrush() From deae75ae093d11714dd2f05a40dcfcdb6bb8e10e Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 18 Dec 2017 11:28:33 +0100 Subject: [PATCH 036/122] TextEdit example: add Markdown as a supported format Also use QT_CONFIG to disable features gracefully if Qt is configured without them. Change-Id: I38e92bf5fd70f77fc4d5158769d590619be8905f Reviewed-by: Gatis Paeglis --- examples/widgets/richtext/textedit/example.md | 96 +++++++++++++++++++ .../widgets/richtext/textedit/textedit.cpp | 33 ++++++- 2 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 examples/widgets/richtext/textedit/example.md diff --git a/examples/widgets/richtext/textedit/example.md b/examples/widgets/richtext/textedit/example.md new file mode 100644 index 0000000000..70aeaf7649 --- /dev/null +++ b/examples/widgets/richtext/textedit/example.md @@ -0,0 +1,96 @@ +# QTextEdit + +The QTextEdit widget is an advanced editor that supports formatted rich text. +It can be used to display HTML and other rich document formats. Internally, +QTextEdit uses the QTextDocument class to describe both the high-level +structure of each document and the low-level formatting of paragraphs. + +If you are viewing this document in the textedit example, you can edit this +document to explore Qt's rich text editing features. We have included some +comments in each of the following sections to encourage you to experiment. + +## Font and Paragraph Styles + +QTextEdit supports **bold**, *italic*, & ~~strikethrough~~ font styles, and +can display multicolored text. Font families such as Times New Roman and `Courier` +can also be used directly. *If you place the cursor in a region of styled text, +the controls in the tool bars will change to reflect the current style.* + +Paragraphs can be formatted so that the text is left-aligned, right-aligned, +centered, or fully justified. + +*Try changing the alignment of some text and resize the editor to see how the +text layout changes.* + +## Lists + +Different kinds of lists can be included in rich text documents. Standard +bullet lists can be nested, using different symbols for each level of the list: + +- Disc symbols are typically used for top-level list items. + * Circle symbols can be used to distinguish between items in lower-level + lists. + + Square symbols provide a reasonable alternative to discs and circles. + +Ordered lists can be created that can be used for tables of contents. Different +characters can be used to enumerate items, and we can use both Roman and Arabic +numerals in the same list structure: + +1. Introduction +2. Qt Tools + 1) Qt Assistant + 2) Qt Designer + 1. Form Editor + 2. Component Architecture + 3) Qt Linguist + +The list will automatically be renumbered if you add or remove items. *Try +adding new sections to the above list or removing existing item to see the +numbers change.* + +## Images + +Inline images are treated like ordinary ranges of characters in the text +editor, so they flow with the surrounding text. Images can also be selected in +the same way as text, making it easy to cut, copy, and paste them. + +![logo](images/logo32.png "logo") *Try to select this image by clicking and +dragging over it with the mouse, or use the text cursor to select it by holding +down Shift and using the arrow keys. You can then cut or copy it, and paste it +into different parts of this document.* + +## Tables + +QTextEdit can arrange and format tables, supporting features such as row and +column spans, text formatting within cells, and size constraints for columns. + +| | Development Tools | Programming Techniques | Graphical User Interfaces | +| ------------: | ----------------- | ---------------------- | ------------------------- | +| 9:00 - 11:00 | Introduction to Qt ||| +| 11:00 - 13:00 | Using qmake | Object-oriented Programming | Layouts in Qt | +| 13:00 - 15:00 | Qt Designer Tutorial | Extreme Programming | Writing Custom Styles | +| 15:00 - 17:00 | Qt Linguist and Internationalization |   |   | + +*Try adding text to the cells in the table and experiment with the alignment of +the paragraphs.* + +## Hyperlinks + +QTextEdit is designed to support hyperlinks between documents, and this feature +is used extensively in +[Qt Assistant](http://doc.qt.io/qt-5/qtassistant-index.html). Hyperlinks are +automatically created when an HTML file is imported into an editor. Since the +rich text framework supports hyperlinks natively, they can also be created +programatically. + +## Undo and Redo + +Full support for undo and redo operations is built into QTextEdit and the +underlying rich text framework. Operations on a document can be packaged +together to make editing a more comfortable experience for the user. + +*Try making changes to this document and press `Ctrl+Z` to undo them. You can +always recover the original contents of the document.* + diff --git a/examples/widgets/richtext/textedit/textedit.cpp b/examples/widgets/richtext/textedit/textedit.cpp index 3ad9f48b67..7b8c242cfc 100644 --- a/examples/widgets/richtext/textedit/textedit.cpp +++ b/examples/widgets/richtext/textedit/textedit.cpp @@ -71,6 +71,7 @@ #include #include #include +#include #if defined(QT_PRINTSUPPORT_LIB) #include #if QT_CONFIG(printer) @@ -395,11 +396,18 @@ bool TextEdit::load(const QString &f) QByteArray data = file.readAll(); QTextCodec *codec = Qt::codecForHtml(data); QString str = codec->toUnicode(data); + QUrl baseUrl = (f.front() == QLatin1Char(':') ? QUrl(f) : QUrl::fromLocalFile(f)).adjusted(QUrl::RemoveFilename); + textEdit->document()->setBaseUrl(baseUrl); if (Qt::mightBeRichText(str)) { textEdit->setHtml(str); } else { - str = QString::fromLocal8Bit(data); - textEdit->setPlainText(str); +#if QT_CONFIG(textmarkdownreader) + QMimeDatabase db; + if (db.mimeTypeForFileNameAndData(f, data).name() == QLatin1String("text/markdown")) + textEdit->setMarkdown(str); + else +#endif + textEdit->setPlainText(QString::fromLocal8Bit(data)); } setCurrentFileName(f); @@ -451,7 +459,15 @@ void TextEdit::fileOpen() QFileDialog fileDialog(this, tr("Open File...")); fileDialog.setAcceptMode(QFileDialog::AcceptOpen); fileDialog.setFileMode(QFileDialog::ExistingFile); - fileDialog.setMimeTypeFilters(QStringList() << "text/html" << "text/plain"); + fileDialog.setMimeTypeFilters(QStringList() +#if QT_CONFIG(texthtmlparser) + << "text/html" +#endif +#if QT_CONFIG(textmarkdownreader) + + << "text/markdown" +#endif + << "text/plain"); if (fileDialog.exec() != QDialog::Accepted) return; const QString fn = fileDialog.selectedFiles().first(); @@ -485,9 +501,18 @@ bool TextEdit::fileSaveAs() QFileDialog fileDialog(this, tr("Save as...")); fileDialog.setAcceptMode(QFileDialog::AcceptSave); QStringList mimeTypes; - mimeTypes << "application/vnd.oasis.opendocument.text" << "text/html" << "text/plain"; + mimeTypes << "text/plain" +#if QT_CONFIG(textodfwriter) + << "application/vnd.oasis.opendocument.text" +#endif +#if QT_CONFIG(textmarkdownwriter) + << "text/markdown" +#endif + << "text/html"; fileDialog.setMimeTypeFilters(mimeTypes); +#if QT_CONFIG(textodfwriter) fileDialog.setDefaultSuffix("odt"); +#endif if (fileDialog.exec() != QDialog::Accepted) return false; const QString fn = fileDialog.selectedFiles().first(); From 75256d62d2462103180b368aa79b933acf71f444 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 6 Feb 2019 17:10:42 +0100 Subject: [PATCH 037/122] Render markdown task lists (checkboxes instead of bullets) in QTextEdit Checkboxes are right-aligned with any bullets that are in the same QTextList so that there is enough space to make them larger than bullets. But hopefully mixing bullets and checkboxes will be a rarely-used feature. Change-Id: I28e274d1f7883aa093df29eb4988e99641e87a71 Reviewed-by: Gatis Paeglis --- examples/widgets/richtext/textedit/example.md | 6 ++++ src/gui/text/qtextdocumentlayout.cpp | 32 +++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/examples/widgets/richtext/textedit/example.md b/examples/widgets/richtext/textedit/example.md index 70aeaf7649..a16a9197b4 100644 --- a/examples/widgets/richtext/textedit/example.md +++ b/examples/widgets/richtext/textedit/example.md @@ -50,6 +50,12 @@ The list will automatically be renumbered if you add or remove items. *Try adding new sections to the above list or removing existing item to see the numbers change.* +Task lists can be used to track progress on projects: + +- [ ] This is not yet done +- This is just a bullet point +- [x] This is done + ## Images Inline images are treated like ordinary ranges of characters in the text diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index bed0a2c450..7873faf2cb 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -1436,6 +1436,21 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p QBrush brush = context.palette.brush(QPalette::Text); + bool marker = bl.blockFormat().marker() != QTextBlockFormat::NoMarker; + if (marker) { + int adj = fontMetrics.lineSpacing() / 6; + r.adjust(-adj, 0, -adj, 0); + if (bl.blockFormat().marker() == QTextBlockFormat::Checked) { + // ### Qt6: render with QStyle / PE_IndicatorCheckBox. We don't currently + // have access to that here, because it would be a widget dependency. + painter->setPen(QPen(painter->pen().color(), 2)); + painter->drawLine(r.topLeft(), r.bottomRight()); + painter->drawLine(r.topRight(), r.bottomLeft()); + painter->setPen(QPen(painter->pen().color(), 0)); + } + painter->drawRect(r.adjusted(-adj, -adj, adj, adj)); + } + switch (style) { case QTextListFormat::ListDecimal: case QTextListFormat::ListLowerAlpha: @@ -1456,16 +1471,21 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p break; } case QTextListFormat::ListSquare: - painter->fillRect(r, brush); + if (!marker) + painter->fillRect(r, brush); break; case QTextListFormat::ListCircle: - painter->setPen(QPen(brush, 0)); - painter->drawEllipse(r.translated(0.5, 0.5)); // pixel align for sharper rendering + if (!marker) { + painter->setPen(QPen(brush, 0)); + painter->drawEllipse(r.translated(0.5, 0.5)); // pixel align for sharper rendering + } break; case QTextListFormat::ListDisc: - painter->setBrush(brush); - painter->setPen(Qt::NoPen); - painter->drawEllipse(r); + if (!marker) { + painter->setBrush(brush); + painter->setPen(Qt::NoPen); + painter->drawEllipse(r); + } break; case QTextListFormat::ListStyleUndefined: break; From 0df30ff22e50aa301791fc72f106ab15ce385a6a Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 18 Feb 2019 15:40:04 +0100 Subject: [PATCH 038/122] Add task list checkbox manipulation features to the TextEdit example Change-Id: I5f0b8cb94d1af609ec531f9765d58be65b1129a3 Reviewed-by: Gatis Paeglis --- .../textedit/images/mac/checkbox-checked.png | Bin 0 -> 1167 bytes .../richtext/textedit/images/mac/checkbox.png | Bin 0 -> 779 bytes .../textedit/images/win/checkbox-checked.png | Bin 0 -> 1167 bytes .../richtext/textedit/images/win/checkbox.png | Bin 0 -> 779 bytes .../widgets/richtext/textedit/textedit.cpp | 70 +++++++++++++++--- examples/widgets/richtext/textedit/textedit.h | 2 + .../widgets/richtext/textedit/textedit.qrc | 4 + 7 files changed, 64 insertions(+), 12 deletions(-) create mode 100644 examples/widgets/richtext/textedit/images/mac/checkbox-checked.png create mode 100644 examples/widgets/richtext/textedit/images/mac/checkbox.png create mode 100644 examples/widgets/richtext/textedit/images/win/checkbox-checked.png create mode 100644 examples/widgets/richtext/textedit/images/win/checkbox.png diff --git a/examples/widgets/richtext/textedit/images/mac/checkbox-checked.png b/examples/widgets/richtext/textedit/images/mac/checkbox-checked.png new file mode 100644 index 0000000000000000000000000000000000000000..a072d7fb5cf6f50faee3024265d421423eebd2fd GIT binary patch literal 1167 zcmZvbe=ys37{|X^qB2^SolQ;MX1(ol({W{5HtJX7N2tssL)BCfq)3oNqC`TpMV+&C zSgSibv!nESw41hwpV1%$(I6@s5+Z0435obI`=XR0ZR5q&5S+;P(B@;LBvNglAfis)1uag79NX zKr{tQN~X}RW#a)Fjpj@srjZk`W#XMl*(tRuFFUa4Q&SO+KuN~~K}1pp-T|ANkw8i( zBs!oINkj)+Dn0{W(ePyp06_Y~FW~~fmjBhrn=O!YCS*O6a@pq2;X8pup)>xsK0UAa z2u4I+0TUPucI3gPn)|=m*xG(zZM~&8fcA9g)n6miPlrW+k4%I1Y;^X#myf4kKx#Jq z#rRy8P~zzycmajx2qn+^c^u&aCMvdXTIzK%*e5V_U}nh=jqwk`fXTi3#`ZDspjaLr z6OW5aq86}U&dCSF@=?*;utdR|S9DJ;G=1}oHQR~AoTN-TfmQ&LZs9^wCXJB8NTajTa|^}G8wnZI)EowpQGA_N z077DZaW<4w$zt5hVwF(Xcc{hX3+r0dwvkd)26~=Ul}gPAr}1T* zV{+}-vTjkWU*6owV%{bfmQadHUrb0kg>N{brJm`fzS)(5*GlfZa!C4iSh_K?q#luN z@?{#nTstaLkIJ>*D&go4bdnx3{lfSR|pkp|Pi@x3{lZMMyu0pZEbCvq&LZ6FzlFQG#Yo0w70i^aPW^w+;7i!g72yfjq<~J z@TpVFSNr1;<{B(Ao`>T4_7MXH`?)Gr;9##xrN@;Y&ZJnir_|1OUg%LvQaUpL#C_L& z-Jg%9#P!iq$E@+2acfRB5V$y($J>m=Q!!nqt9N{#Sng2@e)_%X>|w7>*SUVcdo7>5 zaU)kyQQhpe7j2p1v0BSu^IiKYq>Ovbc2Uw(o~Pf+Z`r$0J~zO7REFL- zrVN^QW0?=#M4l|f!M`!1w>8wPxFO7{LRmqY-1nH(fzS!T-BgjYo)7V1uSEe9&e_Jt zl@~jXx03B=C-R_715zA)3)Y%ApN}-eZ5=`kI&@A5bkRuggIxFdW#~gz60;rwaF{W4 z)>kLZ%)Q$@6Ml{*4o=m@mb2}hS}()WWe990Qb`-9H-)=PKXY3mBe2htE1CK^We8Q{ z((WfT*Qf6PQRQRRVx=BDW9|FV()Ur=yJN{MZ83Z&o6t7#gSwz*Bkbxf6!>))N%B!s nnfC5{Ui7nqhmY>CbF7tzW`fdv2D{GV-7iN6U{H_!j-)B8 z0003gP)t-s00000000000LtI=0002J(Br?+26BG3I_w@Gnv&hu6%GR^V)wRmjwaV7F%-Cphc)8Eoywcsh(%rbi$Gy_t zPFGyP*5Jd};=|YCnWCq*&Dq7-s_+~=yj$ivv<)#&o5yvIaMQs?jUvd7Z8&e`bj^|Hs(zS7>=K_;G)SbAgC-f{D4%-MiA? zzt-Z&;O)ua?8@Tr%H#3N`R%w=`r@z0zz`?@A$;-{o&d<@*)z;S6*x1_I-QC{f z=jiF_>gww2>+tgP^Yrxe_4W4o`uh6&{Qdp@{{H^{2kVo$0002aNklG&tA*5LgfR=B*eUQbm&`F*xHh()`#G?bZ%2;GXi%w0Pgn^UVt+$d{W;Mp2ZL zcswS{awHTAN|GdHU-?-y1IE-yblzdn2>=GqX=9+T|8(g!1Ah+JTb+9Ru~z^9002ov JPDHLkV1k{Ct#JSV literal 0 HcmV?d00001 diff --git a/examples/widgets/richtext/textedit/images/win/checkbox-checked.png b/examples/widgets/richtext/textedit/images/win/checkbox-checked.png new file mode 100644 index 0000000000000000000000000000000000000000..a072d7fb5cf6f50faee3024265d421423eebd2fd GIT binary patch literal 1167 zcmZvbe=ys37{|X^qB2^SolQ;MX1(ol({W{5HtJX7N2tssL)BCfq)3oNqC`TpMV+&C zSgSibv!nESw41hwpV1%$(I6@s5+Z0435obI`=XR0ZR5q&5S+;P(B@;LBvNglAfis)1uag79NX zKr{tQN~X}RW#a)Fjpj@srjZk`W#XMl*(tRuFFUa4Q&SO+KuN~~K}1pp-T|ANkw8i( zBs!oINkj)+Dn0{W(ePyp06_Y~FW~~fmjBhrn=O!YCS*O6a@pq2;X8pup)>xsK0UAa z2u4I+0TUPucI3gPn)|=m*xG(zZM~&8fcA9g)n6miPlrW+k4%I1Y;^X#myf4kKx#Jq z#rRy8P~zzycmajx2qn+^c^u&aCMvdXTIzK%*e5V_U}nh=jqwk`fXTi3#`ZDspjaLr z6OW5aq86}U&dCSF@=?*;utdR|S9DJ;G=1}oHQR~AoTN-TfmQ&LZs9^wCXJB8NTajTa|^}G8wnZI)EowpQGA_N z077DZaW<4w$zt5hVwF(Xcc{hX3+r0dwvkd)26~=Ul}gPAr}1T* zV{+}-vTjkWU*6owV%{bfmQadHUrb0kg>N{brJm`fzS)(5*GlfZa!C4iSh_K?q#luN z@?{#nTstaLkIJ>*D&go4bdnx3{lfSR|pkp|Pi@x3{lZMMyu0pZEbCvq&LZ6FzlFQG#Yo0w70i^aPW^w+;7i!g72yfjq<~J z@TpVFSNr1;<{B(Ao`>T4_7MXH`?)Gr;9##xrN@;Y&ZJnir_|1OUg%LvQaUpL#C_L& z-Jg%9#P!iq$E@+2acfRB5V$y($J>m=Q!!nqt9N{#Sng2@e)_%X>|w7>*SUVcdo7>5 zaU)kyQQhpe7j2p1v0BSu^IiKYq>Ovbc2Uw(o~Pf+Z`r$0J~zO7REFL- zrVN^QW0?=#M4l|f!M`!1w>8wPxFO7{LRmqY-1nH(fzS!T-BgjYo)7V1uSEe9&e_Jt zl@~jXx03B=C-R_715zA)3)Y%ApN}-eZ5=`kI&@A5bkRuggIxFdW#~gz60;rwaF{W4 z)>kLZ%)Q$@6Ml{*4o=m@mb2}hS}()WWe990Qb`-9H-)=PKXY3mBe2htE1CK^We8Q{ z((WfT*Qf6PQRQRRVx=BDW9|FV()Ur=yJN{MZ83Z&o6t7#gSwz*Bkbxf6!>))N%B!s nnfC5{Ui7nqhmY>CbF7tzW`fdv2D{GV-7iN6U{H_!j-)B8 z0003gP)t-s00000000000LtI=0002J(Br?+26BG3I_w@Gnv&hu6%GR^V)wRmjwaV7F%-Cphc)8Eoywcsh(%rbi$Gy_t zPFGyP*5Jd};=|YCnWCq*&Dq7-s_+~=yj$ivv<)#&o5yvIaMQs?jUvd7Z8&e`bj^|Hs(zS7>=K_;G)SbAgC-f{D4%-MiA? zzt-Z&;O)ua?8@Tr%H#3N`R%w=`r@z0zz`?@A$;-{o&d<@*)z;S6*x1_I-QC{f z=jiF_>gww2>+tgP^Yrxe_4W4o`uh6&{Qdp@{{H^{2kVo$0002aNklG&tA*5LgfR=B*eUQbm&`F*xHh()`#G?bZ%2;GXi%w0Pgn^UVt+$d{W;Mp2ZL zcswS{awHTAN|GdHU-?-y1IE-yblzdn2>=GqX=9+T|8(g!1Ah+JTb+9Ru~z^9002ov JPDHLkV1k{Ct#JSV literal 0 HcmV?d00001 diff --git a/examples/widgets/richtext/textedit/textedit.cpp b/examples/widgets/richtext/textedit/textedit.cpp index 7b8c242cfc..683e441fce 100644 --- a/examples/widgets/richtext/textedit/textedit.cpp +++ b/examples/widgets/richtext/textedit/textedit.cpp @@ -343,6 +343,15 @@ void TextEdit::setupTextActions() actionTextColor = menu->addAction(pix, tr("&Color..."), this, &TextEdit::textColor); tb->addAction(actionTextColor); + menu->addSeparator(); + + const QIcon checkboxIcon = QIcon::fromTheme("status-checkbox-checked", QIcon(rsrcPath + "/checkbox-checked.png")); + actionToggleCheckState = menu->addAction(checkboxIcon, tr("Chec&ked"), this, &TextEdit::setChecked); + actionToggleCheckState->setShortcut(Qt::CTRL + Qt::Key_K); + actionToggleCheckState->setCheckable(true); + actionToggleCheckState->setPriority(QAction::LowPriority); + tb->addAction(actionToggleCheckState); + tb = addToolBar(tr("Format Actions")); tb->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); addToolBarBreak(Qt::TopToolBarArea); @@ -354,6 +363,8 @@ void TextEdit::setupTextActions() comboStyle->addItem("Bullet List (Disc)"); comboStyle->addItem("Bullet List (Circle)"); comboStyle->addItem("Bullet List (Square)"); + comboStyle->addItem("Task List (Unchecked)"); + comboStyle->addItem("Task List (Checked)"); comboStyle->addItem("Ordered List (Decimal)"); comboStyle->addItem("Ordered List (Alpha lower)"); comboStyle->addItem("Ordered List (Alpha upper)"); @@ -617,6 +628,7 @@ void TextEdit::textStyle(int styleIndex) { QTextCursor cursor = textEdit->textCursor(); QTextListFormat::Style style = QTextListFormat::ListStyleUndefined; + QTextBlockFormat::MarkerType marker = QTextBlockFormat::NoMarker; switch (styleIndex) { case 1: @@ -629,18 +641,32 @@ void TextEdit::textStyle(int styleIndex) style = QTextListFormat::ListSquare; break; case 4: - style = QTextListFormat::ListDecimal; + if (cursor.currentList()) + style = cursor.currentList()->format().style(); + else + style = QTextListFormat::ListDisc; + marker = QTextBlockFormat::Unchecked; break; case 5: - style = QTextListFormat::ListLowerAlpha; + if (cursor.currentList()) + style = cursor.currentList()->format().style(); + else + style = QTextListFormat::ListDisc; + marker = QTextBlockFormat::Checked; break; case 6: - style = QTextListFormat::ListUpperAlpha; + style = QTextListFormat::ListDecimal; break; case 7: - style = QTextListFormat::ListLowerRoman; + style = QTextListFormat::ListLowerAlpha; break; case 8: + style = QTextListFormat::ListUpperAlpha; + break; + case 9: + style = QTextListFormat::ListLowerRoman; + break; + case 10: style = QTextListFormat::ListUpperRoman; break; default: @@ -665,6 +691,8 @@ void TextEdit::textStyle(int styleIndex) cursor.mergeCharFormat(fmt); textEdit->mergeCurrentCharFormat(fmt); } else { + blockFmt.setMarker(marker); + cursor.setBlockFormat(blockFmt); QTextListFormat listFmt; if (cursor.currentList()) { listFmt = cursor.currentList()->format(); @@ -703,6 +731,11 @@ void TextEdit::textAlign(QAction *a) textEdit->setAlignment(Qt::AlignJustify); } +void TextEdit::setChecked(bool checked) +{ + textStyle(checked ? 5 : 4); +} + void TextEdit::currentCharFormatChanged(const QTextCharFormat &format) { fontChanged(format.font()); @@ -725,24 +758,37 @@ void TextEdit::cursorPositionChanged() comboStyle->setCurrentIndex(3); break; case QTextListFormat::ListDecimal: - comboStyle->setCurrentIndex(4); - break; - case QTextListFormat::ListLowerAlpha: - comboStyle->setCurrentIndex(5); - break; - case QTextListFormat::ListUpperAlpha: comboStyle->setCurrentIndex(6); break; - case QTextListFormat::ListLowerRoman: + case QTextListFormat::ListLowerAlpha: comboStyle->setCurrentIndex(7); break; - case QTextListFormat::ListUpperRoman: + case QTextListFormat::ListUpperAlpha: comboStyle->setCurrentIndex(8); break; + case QTextListFormat::ListLowerRoman: + comboStyle->setCurrentIndex(9); + break; + case QTextListFormat::ListUpperRoman: + comboStyle->setCurrentIndex(10); + break; default: comboStyle->setCurrentIndex(-1); break; } + switch (textEdit->textCursor().block().blockFormat().marker()) { + case QTextBlockFormat::NoMarker: + actionToggleCheckState->setChecked(false); + break; + case QTextBlockFormat::Unchecked: + comboStyle->setCurrentIndex(4); + actionToggleCheckState->setChecked(false); + break; + case QTextBlockFormat::Checked: + comboStyle->setCurrentIndex(5); + actionToggleCheckState->setChecked(true); + break; + } } else { int headingLevel = textEdit->textCursor().blockFormat().headingLevel(); comboStyle->setCurrentIndex(headingLevel ? headingLevel + 8 : 0); diff --git a/examples/widgets/richtext/textedit/textedit.h b/examples/widgets/richtext/textedit/textedit.h index ae0b13a4cc..c253548a4f 100644 --- a/examples/widgets/richtext/textedit/textedit.h +++ b/examples/widgets/richtext/textedit/textedit.h @@ -96,6 +96,7 @@ private slots: void textStyle(int styleIndex); void textColor(); void textAlign(QAction *a); + void setChecked(bool checked); void currentCharFormatChanged(const QTextCharFormat &format); void cursorPositionChanged(); @@ -125,6 +126,7 @@ private: QAction *actionAlignCenter; QAction *actionAlignRight; QAction *actionAlignJustify; + QAction *actionToggleCheckState; QAction *actionUndo; QAction *actionRedo; #ifndef QT_NO_CLIPBOARD diff --git a/examples/widgets/richtext/textedit/textedit.qrc b/examples/widgets/richtext/textedit/textedit.qrc index 7d6efd7d67..8016a07ca0 100644 --- a/examples/widgets/richtext/textedit/textedit.qrc +++ b/examples/widgets/richtext/textedit/textedit.qrc @@ -1,6 +1,8 @@ images/logo32.png + images/mac/checkbox.png + images/mac/checkbox-checked.png images/mac/editcopy.png images/mac/editcut.png images/mac/editpaste.png @@ -20,6 +22,8 @@ images/mac/textunder.png images/mac/zoomin.png images/mac/zoomout.png + images/win/checkbox.png + images/win/checkbox-checked.png images/win/editcopy.png images/win/editcut.png images/win/editpaste.png From 355ecfb11c838b4c9facc9a631e04a52531a2127 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 18 Dec 2018 00:56:37 +0100 Subject: [PATCH 039/122] Add QTextMarkdownWriter::writeTable(QAbstractTableModel) This provides the ability to write live data from a table to Markdown, which can be useful to load it into a text document or a wiki. But so far QTextMarkdownWriter is still a private class, intended to be used experimentally from QtQuick and perhaps later exposed in other ways. Change-Id: I0de4673987e4172178604e49b5a024a05d4486ba Reviewed-by: Richard Moe Gustavsen --- src/gui/text/qtextmarkdownwriter.cpp | 31 ++++++++++++++++ src/gui/text/qtextmarkdownwriter_p.h | 2 ++ .../itemviews/qtableview/tst_qtableview.cpp | 35 +++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index c91248757a..fed4a7b766 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -64,6 +64,37 @@ bool QTextMarkdownWriter::writeAll(const QTextDocument &document) return true; } +void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) +{ + QVector tableColumnWidths(table.columnCount()); + for (int col = 0; col < table.columnCount(); ++col) { + tableColumnWidths[col] = table.headerData(col, Qt::Horizontal).toString().length(); + for (int row = 0; row < table.rowCount(); ++row) { + tableColumnWidths[col] = qMax(tableColumnWidths[col], + table.data(table.index(row, col)).toString().length()); + } + } + + // write the header and separator + for (int col = 0; col < table.columnCount(); ++col) { + QString s = table.headerData(col, Qt::Horizontal).toString(); + m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); + } + m_stream << "|" << endl; + for (int col = 0; col < tableColumnWidths.length(); ++col) + m_stream << '|' << QString(tableColumnWidths[col], QLatin1Char('-')); + m_stream << '|'<< endl; + + // write the body + for (int row = 0; row < table.rowCount(); ++row) { + for (int col = 0; col < table.columnCount(); ++col) { + QString s = table.data(table.index(row, col)).toString(); + m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); + } + m_stream << '|'<< endl; + } +} + void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) { Q_ASSERT(frame); diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h index 9845355259..2a9388ca2d 100644 --- a/src/gui/text/qtextmarkdownwriter_p.h +++ b/src/gui/text/qtextmarkdownwriter_p.h @@ -56,6 +56,7 @@ #include "qtextdocument_p.h" #include "qtextdocumentwriter.h" +#include "QAbstractTableModel" QT_BEGIN_NAMESPACE @@ -64,6 +65,7 @@ class Q_GUI_EXPORT QTextMarkdownWriter public: QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features); bool writeAll(const QTextDocument &document); + void writeTable(const QAbstractTableModel &table); int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat); void writeFrame(const QTextFrame *frame); diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp index b1ddc6e7a2..e7822ef7de 100644 --- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp @@ -32,6 +32,9 @@ #include #include #include "private/qapplication_p.h" +#if QT_CONFIG(textmarkdownwriter) +#include "private/qtextmarkdownwriter_p.h" +#endif #include @@ -196,6 +199,10 @@ private slots: void viewOptions(); void taskQTBUG_7232_AllowUserToControlSingleStep(); + +#if QT_CONFIG(textmarkdownwriter) + void markdownWriter(); +#endif }; // Testing get/set functions @@ -4560,5 +4567,33 @@ void tst_QTableView::taskQTBUG_50171_selectRowAfterSwapColumns() } } +// This has nothing to do with QTableView, but it's convenient to reuse the QtTestTableModel +#if QT_CONFIG(textmarkdownwriter) + +// #define DEBUG_WRITE_OUTPUT + +void tst_QTableView::markdownWriter() +{ + QtTestTableModel model(2, 3); + QString md; + { + QTextStream stream(&md); + QTextMarkdownWriter writer(stream, QTextDocument::MarkdownDialectGitHub); + writer.writeTable(model); + } + +#ifdef DEBUG_WRITE_OUTPUT + { + QFile out("/tmp/table.md"); + out.open(QFile::WriteOnly); + out.write(md.toUtf8()); + out.close(); + } +#endif + + QCOMPARE(md, QString::fromLatin1("|1 |2 |3 |\n|-------|-------|-------|\n|[0,0,0]|[0,1,0]|[0,2,0]|\n|[1,0,0]|[1,1,0]|[1,2,0]|\n")); +} +#endif + QTEST_MAIN(tst_QTableView) #include "tst_qtableview.moc" From 402cb62d5db7516e4d8d77d972e55e90cb855679 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Fri, 15 Mar 2019 12:05:38 +0100 Subject: [PATCH 040/122] Introduce QNetworkConnection/Status/Monitor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Private classes to replace broken or even not working at all 'session management' and 'bearer manager' (on at least two major platforms we support). This implementation is macOS/iOS-specific and uses SystemConfiguration framework, or more precisely SCNetworkReachability's part of it. Task-number: QTBUG-40332 Change-Id: Iac5f44c4063c4092b93b8cf2bde3fb2c524855b3 Reviewed-by: Mårten Nordheim --- src/network/access/qhttpnetworkconnection.cpp | 38 +- src/network/access/qhttpnetworkconnection_p.h | 13 + .../access/qhttpnetworkconnectionchannel.cpp | 12 + src/network/access/qnetworkaccessmanager.cpp | 153 ++++-- src/network/access/qnetworkaccessmanager.h | 2 +- src/network/access/qnetworkaccessmanager_p.h | 8 +- src/network/access/qnetworkreplyhttpimpl.cpp | 15 +- src/network/access/qnetworkreplyimpl.cpp | 2 - src/network/access/qnetworkreplyimpl_p.h | 2 - src/network/kernel/kernel.pri | 12 +- src/network/kernel/qnetconmonitor_darwin.mm | 434 ++++++++++++++++++ src/network/kernel/qnetconmonitor_p.h | 126 +++++ src/network/kernel/qnetconmonitor_stub.cpp | 141 ++++++ 13 files changed, 903 insertions(+), 55 deletions(-) create mode 100644 src/network/kernel/qnetconmonitor_darwin.mm create mode 100644 src/network/kernel/qnetconmonitor_p.h create mode 100644 src/network/kernel/qnetconmonitor_stub.cpp diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 0a37122fc6..cb4c722eb5 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -1320,6 +1320,10 @@ QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 Q_D(QHttpNetworkConnection); d->networkSession = std::move(networkSession); d->init(); + if (QNetworkStatusMonitor::isEnabled()) { + connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged, + this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection); + } } QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, @@ -1332,6 +1336,10 @@ QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QS Q_D(QHttpNetworkConnection); d->networkSession = std::move(networkSession); d->init(); + if (QNetworkStatusMonitor::isEnabled()) { + connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged, + this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection); + } } #else QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, @@ -1340,6 +1348,10 @@ QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 { Q_D(QHttpNetworkConnection); d->init(); + if (QNetworkStatusMonitor::isEnabled()) { + connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged, + this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection); + } } QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QString &hostName, @@ -1350,8 +1362,12 @@ QHttpNetworkConnection::QHttpNetworkConnection(quint16 connectionCount, const QS { Q_D(QHttpNetworkConnection); d->init(); + if (QNetworkStatusMonitor::isEnabled()) { + connect(&d->connectionMonitor, &QNetworkConnectionMonitor::reachabilityChanged, + this, &QHttpNetworkConnection::onlineStateChanged, Qt::QueuedConnection); + } } -#endif +#endif // QT_NO_BEARERMANAGEMENT QHttpNetworkConnection::~QHttpNetworkConnection() { @@ -1531,6 +1547,26 @@ void QHttpNetworkConnection::setPeerVerifyName(const QString &peerName) d->peerVerifyName = peerName; } +void QHttpNetworkConnection::onlineStateChanged(bool isOnline) +{ + Q_D(QHttpNetworkConnection); + + if (isOnline) { + // If we did not have any 'isOffline' previously - well, good + // to know, we are 'online' apparently. + return; + } + + for (int i = 0; i < d->activeChannelCount; i++) { + auto &channel = d->channels[i]; + channel.emitFinishedWithError(QNetworkReply::TemporaryNetworkFailureError, "Temporary network failure."); + channel.close(); + } + + // We don't care, this connection is broken from our POV. + d->connectionMonitor.stopMonitoring(); +} + #ifndef QT_NO_NETWORKPROXY // only called from QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired, not // from QHttpNetworkConnectionChannel::handleAuthenticationChallenge diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 2f3c334248..85d89f20c2 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -67,6 +67,7 @@ #include #include #include +#include #include #include @@ -156,6 +157,10 @@ public: QString peerVerifyName() const; void setPeerVerifyName(const QString &peerName); + +public slots: + void onlineStateChanged(bool isOnline); + private: Q_DECLARE_PRIVATE(QHttpNetworkConnection) Q_DISABLE_COPY_MOVE(QHttpNetworkConnection) @@ -292,6 +297,14 @@ public: Http2::ProtocolParameters http2Parameters; QString peerVerifyName; + // If network status monitoring is enabled, we activate connectionMonitor + // as soons as one of channels managed to connect to host (and we + // have a pair of addresses (us,peer). + // NETMONTODO: consider activating a monitor on a change from + // HostLookUp state to ConnectingState (means we have both + // local/remote addresses known and can start monitoring this + // early). + QNetworkConnectionMonitor connectionMonitor; friend class QHttpNetworkConnectionChannel; }; diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index f79a4d1dc6..9309d718e4 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -59,6 +59,8 @@ #include "private/qnetworksession_p.h" #endif +#include "private/qnetconmonitor_p.h" + QT_BEGIN_NAMESPACE namespace @@ -896,6 +898,16 @@ void QHttpNetworkConnectionChannel::_q_connected() pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningSupportUnknown; + if (QNetworkStatusMonitor::isEnabled()) { + auto connectionPrivate = connection->d_func(); + if (!connectionPrivate->connectionMonitor.isMonitoring()) { + // Now that we have a pair of addresses, we can start monitoring the + // connection status to handle its loss properly. + if (connectionPrivate->connectionMonitor.setTargets(socket->localAddress(), socket->peerAddress())) + connectionPrivate->connectionMonitor.startMonitoring(); + } + } + // ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again! //channels[i].reconnectAttempts = 2; if (ssl || pendingEncrypt) { // FIXME: Didn't work properly with pendingEncrypt only, we should refactor this into an EncrypingState diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 50b9488594..8bd630ad9d 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -90,6 +90,8 @@ #include "qnetworkreplywasmimpl_p.h" #endif +#include "qnetconmonitor_p.h" + QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QNetworkAccessFileBackendFactory, fileBackend) @@ -486,18 +488,25 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) qRegisterMetaType(); qRegisterMetaType >(); -#ifndef QT_NO_BEARERMANAGEMENT Q_D(QNetworkAccessManager); - // if a session is required, we track online state through - // the QNetworkSession's signals if a request is already made. - // we need to track current accessibility state by default - // - connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), - SLOT(_q_onlineStateChanged(bool))); - connect(&d->networkConfigurationManager, SIGNAL(configurationChanged(QNetworkConfiguration)), - SLOT(_q_configurationChanged(QNetworkConfiguration))); - -#endif + if (QNetworkStatusMonitor::isEnabled()) { + connect(&d->statusMonitor, SIGNAL(onlineStateChanged(bool)), + SLOT(_q_onlineStateChanged(bool))); +#ifdef QT_NO_BEARERMANAGEMENT + d->networkAccessible = d->statusMonitor.isNetworkAccesible(); +#else + d->networkAccessible = d->statusMonitor.isNetworkAccesible() ? Accessible : NotAccessible; + } else { + // if a session is required, we track online state through + // the QNetworkSession's signals if a request is already made. + // we need to track current accessibility state by default + // + connect(&d->networkConfigurationManager, SIGNAL(onlineStateChanged(bool)), + SLOT(_q_onlineStateChanged(bool))); + connect(&d->networkConfigurationManager, SIGNAL(configurationChanged(QNetworkConfiguration)), + SLOT(_q_configurationChanged(QNetworkConfiguration))); +#endif // QT_NO_BEARERMANAGEMENT + } } /*! @@ -1030,9 +1039,13 @@ QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &requ void QNetworkAccessManager::setConfiguration(const QNetworkConfiguration &config) { Q_D(QNetworkAccessManager); - d->networkConfiguration = config; - d->customNetworkConfiguration = true; - d->createSession(config); + if (!d->statusMonitor.isEnabled()) { + d->networkConfiguration = config; + d->customNetworkConfiguration = true; + d->createSession(config); + } else { + qWarning(lcNetMon, "No network configuration can be set with network status monitor enabled"); + } } /*! @@ -1048,7 +1061,7 @@ QNetworkConfiguration QNetworkAccessManager::configuration() const Q_D(const QNetworkAccessManager); QSharedPointer session(d->getNetworkSession()); - if (session) { + if (session && !d->statusMonitor.isEnabled()) { return session->configuration(); } else { return d->networkConfigurationManager.defaultConfiguration(); @@ -1075,7 +1088,7 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const Q_D(const QNetworkAccessManager); QSharedPointer networkSession(d->getNetworkSession()); - if (networkSession) { + if (networkSession && !d->statusMonitor.isEnabled()) { return d->networkConfigurationManager.configurationFromIdentifier( networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString()); } else { @@ -1094,6 +1107,11 @@ void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkA { Q_D(QNetworkAccessManager); + if (d->statusMonitor.isEnabled()) { + qWarning(lcNetMon, "Can not manually set network accessibility with the network status monitor enabled"); + return; + } + d->defaultAccessControl = accessible == NotAccessible ? false : true; if (d->networkAccessible != accessible) { @@ -1114,6 +1132,12 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess { Q_D(const QNetworkAccessManager); + if (d->statusMonitor.isEnabled()) { + if (!d->statusMonitor.isMonitoring()) + d->statusMonitor.start(); + return d->networkAccessible; + } + if (d->customNetworkConfiguration && d->networkConfiguration.state().testFlag(QNetworkConfiguration::Undefined)) return UnknownAccessibility; @@ -1434,35 +1458,57 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera } } + if (d->statusMonitor.isEnabled()) { + // See the code in ctor - QNetworkStatusMonitor allows us to + // immediately set 'networkAccessible' even before we start + // the monitor. +#ifdef QT_NO_BEARERMANAGEMENT + if (d->networkAccessible +#else + if (d->networkAccessible == NotAccessible +#endif // QT_NO_BEARERMANAGEMENT + && !isLocalFile) { + QHostAddress dest; + QString host = req.url().host().toLower(); + if (!(dest.setAddress(host) && dest.isLoopback()) + && host != QLatin1String("localhost") + && host != QHostInfo::localHostName().toLower()) { + return new QDisabledNetworkReply(this, req, op); + } + } + + if (!d->statusMonitor.isMonitoring() && !d->statusMonitor.start()) + qWarning(lcNetMon, "failed to start network status monitoring"); + } else { #ifndef QT_NO_BEARERMANAGEMENT - - // Return a disabled network reply if network access is disabled. - // Except if the scheme is empty or file:// or if the host resolves to a loopback address. - if (d->networkAccessible == NotAccessible && !isLocalFile) { - QHostAddress dest; - QString host = req.url().host().toLower(); - if (!(dest.setAddress(host) && dest.isLoopback()) && host != QLatin1String("localhost") + // Return a disabled network reply if network access is disabled. + // Except if the scheme is empty or file:// or if the host resolves to a loopback address. + if (d->networkAccessible == NotAccessible && !isLocalFile) { + QHostAddress dest; + QString host = req.url().host().toLower(); + if (!(dest.setAddress(host) && dest.isLoopback()) && host != QLatin1String("localhost") && host != QHostInfo::localHostName().toLower()) { - return new QDisabledNetworkReply(this, req, op); + return new QDisabledNetworkReply(this, req, op); + } } - } - if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) { - if (!d->networkConfiguration.identifier().isEmpty()) { - if ((d->networkConfiguration.state() & QNetworkConfiguration::Defined) - && d->networkConfiguration != d->networkConfigurationManager.defaultConfiguration()) - d->createSession(d->networkConfigurationManager.defaultConfiguration()); - else - d->createSession(d->networkConfiguration); + if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) { + if (!d->networkConfiguration.identifier().isEmpty()) { + if ((d->networkConfiguration.state() & QNetworkConfiguration::Defined) + && d->networkConfiguration != d->networkConfigurationManager.defaultConfiguration()) + d->createSession(d->networkConfigurationManager.defaultConfiguration()); + else + d->createSession(d->networkConfiguration); - } else { - if (d->networkSessionRequired) - d->createSession(d->networkConfigurationManager.defaultConfiguration()); - else - d->initializeSession = false; + } else { + if (d->networkSessionRequired) + d->createSession(d->networkConfigurationManager.defaultConfiguration()); + else + d->initializeSession = false; + } } - } #endif + } QNetworkRequest request = req; if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() && @@ -1509,8 +1555,10 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera #endif QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData); #ifndef QT_NO_BEARERMANAGEMENT - connect(this, SIGNAL(networkSessionConnected()), - reply, SLOT(_q_networkSessionConnected())); + if (!d->statusMonitor.isEnabled()) { + connect(this, SIGNAL(networkSessionConnected()), + reply, SLOT(_q_networkSessionConnected())); + } #endif return reply; } @@ -1519,7 +1567,9 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera // first step: create the reply QNetworkReplyImpl *reply = new QNetworkReplyImpl(this); #ifndef QT_NO_BEARERMANAGEMENT - if (!isLocalFile) { + // NETMONTODO: network reply impl must be augmented to use the same monitoring + // capabilities as http network reply impl does. + if (!isLocalFile && !d->statusMonitor.isEnabled()) { connect(this, SIGNAL(networkSessionConnected()), reply, SLOT(_q_networkSessionConnected())); } @@ -1988,7 +2038,13 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) { - Q_Q(QNetworkAccessManager); + Q_Q(QNetworkAccessManager); + + if (statusMonitor.isEnabled()) { + networkAccessible = isOnline ? QNetworkAccessManager::Accessible : QNetworkAccessManager::NotAccessible; + return; + } + // if the user set a config, we only care whether this one is active. // Otherwise, this QNAM is online if there is an online config. @@ -2018,6 +2074,9 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfiguration &configuration) { + if (statusMonitor.isEnabled()) + return; + const QString id = configuration.identifier(); if (configuration.state().testFlag(QNetworkConfiguration::Active)) { if (!onlineConfigurations.contains(id)) { @@ -2050,6 +2109,9 @@ void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfigu void QNetworkAccessManagerPrivate::_q_networkSessionFailed(QNetworkSession::SessionError) { + if (statusMonitor.isEnabled()) + return; + const auto cfgs = networkConfigurationManager.allConfigurations(); for (const QNetworkConfiguration &cfg : cfgs) { if (cfg.state().testFlag(QNetworkConfiguration::Active)) { @@ -2061,6 +2123,13 @@ void QNetworkAccessManagerPrivate::_q_networkSessionFailed(QNetworkSession::Sess } } +#else + +void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline) +{ + networkAccessible = isOnline; +} + #endif // QT_NO_BEARERMANAGEMENT #if QT_CONFIG(http) diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 7e2f7683d0..fa23537c68 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -209,10 +209,10 @@ private: #ifndef QT_NO_BEARERMANAGEMENT Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) - Q_PRIVATE_SLOT(d_func(), void _q_onlineStateChanged(bool)) Q_PRIVATE_SLOT(d_func(), void _q_configurationChanged(const QNetworkConfiguration &)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed(QNetworkSession::SessionError)) #endif + Q_PRIVATE_SLOT(d_func(), void _q_onlineStateChanged(bool)) }; QT_END_NAMESPACE diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index 5cab4928e4..d3a3936533 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -55,6 +55,7 @@ #include "qnetworkaccessmanager.h" #include "qnetworkaccesscache_p.h" #include "qnetworkaccessbackend_p.h" +#include "qnetconmonitor_p.h" #include "qnetworkrequest.h" #include "qhsts_p.h" #include "private/qobject_p.h" @@ -151,6 +152,7 @@ public: QNetworkAccessBackend *findBackend(QNetworkAccessManager::Operation op, const QNetworkRequest &request); QStringList backendSupportedSchemes() const; + void _q_onlineStateChanged(bool isOnline); #ifndef QT_NO_BEARERMANAGEMENT void createSession(const QNetworkConfiguration &config); QSharedPointer getNetworkSession() const; @@ -160,12 +162,11 @@ public: void _q_networkSessionPreferredConfigurationChanged(const QNetworkConfiguration &config, bool isSeamless); void _q_networkSessionStateChanged(QNetworkSession::State state); - void _q_onlineStateChanged(bool isOnline); + void _q_configurationChanged(const QNetworkConfiguration &configuration); void _q_networkSessionFailed(QNetworkSession::SessionError error); QSet onlineConfigurations; - #endif #if QT_CONFIG(http) @@ -199,6 +200,8 @@ public: int activeReplyCount; bool online; bool initializeSession; +#else + bool networkAccessible = true; #endif bool cookieJarCreated; @@ -222,6 +225,7 @@ public: QScopedPointer stsStore; #endif // QT_CONFIG(settings) bool stsEnabled = false; + mutable QNetworkStatusMonitor statusMonitor; #ifndef QT_NO_BEARERMANAGEMENT Q_AUTOTEST_EXPORT static const QWeakPointer getNetworkSession(const QNetworkAccessManager *manager); diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index f801ef0c88..b9651b35d2 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -59,6 +59,7 @@ #include #include "qnetworkcookiejar.h" +#include "qnetconmonitor_p.h" #include // for strchr @@ -166,6 +167,11 @@ static QHash parseHttpOptionHeader(const QByteArray &hea #if QT_CONFIG(bearermanagement) static bool isSessionNeeded(const QUrl &url) { + if (QNetworkStatusMonitor::isEnabled()) { + // In case QNetworkStatus/QNetConManager are in business, + // no session, no bearer manager are involved. + return false; + } // Connections to the local machine does not require a session QString host = url.host().toLower(); return !QHostAddress(host).isLoopback() && host != QLatin1String("localhost") @@ -796,7 +802,8 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq if (blob.isValid() && blob.canConvert()) delegate->http2Parameters = blob.value(); #ifndef QT_NO_BEARERMANAGEMENT - delegate->networkSession = managerPrivate->getNetworkSession(); + if (!QNetworkStatusMonitor::isEnabled()) + delegate->networkSession = managerPrivate->getNetworkSession(); #endif // For the synchronous HTTP, this is the normal way the delegate gets deleted @@ -1807,7 +1814,7 @@ bool QNetworkReplyHttpImplPrivate::start(const QNetworkRequest &newHttpRequest) { #ifndef QT_NO_BEARERMANAGEMENT QSharedPointer networkSession(managerPrivate->getNetworkSession()); - if (!networkSession) { + if (!networkSession || QNetworkStatusMonitor::isEnabled()) { #endif postRequest(newHttpRequest); return true; @@ -1895,7 +1902,7 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() // state changes. if (!startWaitForSession(session)) return; - } else if (session) { + } else if (session && !QNetworkStatusMonitor::isEnabled()) { QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)), q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); @@ -2184,7 +2191,7 @@ void QNetworkReplyHttpImplPrivate::finished() #ifndef QT_NO_BEARERMANAGEMENT Q_ASSERT(managerPrivate); QSharedPointer session = managerPrivate->getNetworkSession(); - if (session && session->state() == QNetworkSession::Roaming && + if (!QNetworkStatusMonitor::isEnabled() && session && session->state() == QNetworkSession::Roaming && state == Working && errorCode != QNetworkReply::OperationCanceledError) { // only content with a known size will fail with a temporary network failure error if (!totalSize.isNull()) { diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index f5bb4d5887..1a02938de9 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -1117,7 +1117,6 @@ bool QNetworkReplyImplPrivate::migrateBackend() return true; } -#ifndef QT_NO_BEARERMANAGEMENT QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent, const QNetworkRequest &req, QNetworkAccessManager::Operation op) @@ -1142,7 +1141,6 @@ QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent, QDisabledNetworkReply::~QDisabledNetworkReply() { } -#endif QT_END_NAMESPACE diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 4881e84e9c..85f5b862a8 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -209,7 +209,6 @@ public: }; Q_DECLARE_TYPEINFO(QNetworkReplyImplPrivate::InternalNotifications, Q_PRIMITIVE_TYPE); -#ifndef QT_NO_BEARERMANAGEMENT class QDisabledNetworkReply : public QNetworkReply { Q_OBJECT @@ -223,7 +222,6 @@ public: protected: qint64 readData(char *, qint64) override { return -1; } }; -#endif QT_END_NAMESPACE diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index b86119b200..0e4cef5e74 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -16,7 +16,8 @@ HEADERS += kernel/qtnetworkglobal.h \ kernel/qnetworkinterface.h \ kernel/qnetworkinterface_p.h \ kernel/qnetworkinterface_unix_p.h \ - kernel/qnetworkproxy.h + kernel/qnetworkproxy.h \ + kernel/qnetconmonitor_p.h SOURCES += kernel/qauthenticator.cpp \ kernel/qhostaddress.cpp \ @@ -71,6 +72,15 @@ mac { !uikit: LIBS_PRIVATE += -framework CoreServices -framework SystemConfiguration } +macos | ios { + OBJECTIVE_SOURCES += \ + kernel/qnetconmonitor_darwin.mm + + LIBS_PRIVATE += -framework SystemConfiguration +} else { + SOURCES += kernel/qnetconmonitor_stub.cpp +} + qtConfig(gssapi): LIBS_PRIVATE += -lgssapi_krb5 uikit:HEADERS += kernel/qnetworkinterface_uikit_p.h diff --git a/src/network/kernel/qnetconmonitor_darwin.mm b/src/network/kernel/qnetconmonitor_darwin.mm new file mode 100644 index 0000000000..322c87cb4b --- /dev/null +++ b/src/network/kernel/qnetconmonitor_darwin.mm @@ -0,0 +1,434 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 "private/qnativesocketengine_p.h" +#include "private/qnetconmonitor_p.h" + +#include "private/qobject_p.h" + +#include +#include + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcNetMon, "qt.network.monitor"); + +namespace { + +class ReachabilityDispatchQueue +{ +public: + ReachabilityDispatchQueue() + { + queue = dispatch_queue_create("qt-network-reachability-queue", nullptr); + if (!queue) + qCWarning(lcNetMon, "Failed to create a dispatch queue for reachability probes"); + } + + ~ReachabilityDispatchQueue() + { + if (queue) + dispatch_release(queue); + } + + dispatch_queue_t data() const + { + return queue; + } + +private: + dispatch_queue_t queue = nullptr; + + Q_DISABLE_COPY_MOVE(ReachabilityDispatchQueue) +}; + +dispatch_queue_t qt_reachability_queue() +{ + static const ReachabilityDispatchQueue reachabilityQueue; + return reachabilityQueue.data(); +} + +qt_sockaddr qt_hostaddress_to_sockaddr(const QHostAddress &src) +{ + if (src.isNull()) + return {}; + + qt_sockaddr dst; + if (src.protocol() == QAbstractSocket::IPv4Protocol) { + dst.a4 = sockaddr_in{}; + dst.a4.sin_family = AF_INET; + dst.a4.sin_addr.s_addr = htonl(src.toIPv4Address()); + dst.a4.sin_len = sizeof(sockaddr_in); + } else if (src.protocol() == QAbstractSocket::IPv6Protocol) { + dst.a6 = sockaddr_in6{}; + dst.a6.sin6_family = AF_INET6; + dst.a6.sin6_len = sizeof(sockaddr_in6); + const Q_IPV6ADDR ipv6 = src.toIPv6Address(); + std::memcpy(&dst.a6.sin6_addr, &ipv6, sizeof ipv6); + } else { + Q_UNREACHABLE(); + } + + return dst; +} + +} // unnamed namespace + +class QNetworkConnectionMonitorPrivate : public QObjectPrivate +{ +public: + SCNetworkReachabilityRef probe = nullptr; + SCNetworkReachabilityFlags state = kSCNetworkReachabilityFlagsIsLocalAddress; + bool scheduled = false; + + void updateState(SCNetworkReachabilityFlags newState); + void reset(); + bool isReachable() const; + + static void probeCallback(SCNetworkReachabilityRef probe, SCNetworkReachabilityFlags flags, void *info); + + Q_DECLARE_PUBLIC(QNetworkConnectionMonitor) +}; + +void QNetworkConnectionMonitorPrivate::updateState(SCNetworkReachabilityFlags newState) +{ + // To be executed only on the reachability queue. + Q_Q(QNetworkConnectionMonitor); + + // NETMONTODO: for now, 'online' for us means kSCNetworkReachabilityFlagsReachable + // is set. There are more possible flags that require more tests/some special + // setup. So in future this part and related can change/be extended. + const bool wasReachable = isReachable(); + state = newState; + if (wasReachable != isReachable()) + emit q->reachabilityChanged(isReachable()); +} + +void QNetworkConnectionMonitorPrivate::reset() +{ + if (probe) { + CFRelease(probe); + probe = nullptr; + } + + state = kSCNetworkReachabilityFlagsIsLocalAddress; + scheduled = false; +} + +bool QNetworkConnectionMonitorPrivate::isReachable() const +{ + return !!(state & kSCNetworkReachabilityFlagsReachable); +} + +void QNetworkConnectionMonitorPrivate::probeCallback(SCNetworkReachabilityRef probe, SCNetworkReachabilityFlags flags, void *info) +{ + // To be executed only on the reachability queue. + Q_UNUSED(probe); + + auto monitorPrivate = static_cast(info); + Q_ASSERT(monitorPrivate); + monitorPrivate->updateState(flags); +} + +QNetworkConnectionMonitor::QNetworkConnectionMonitor() + : QObject(*new QNetworkConnectionMonitorPrivate) +{ +} + +QNetworkConnectionMonitor::QNetworkConnectionMonitor(const QHostAddress &local, const QHostAddress &remote) + : QObject(*new QNetworkConnectionMonitorPrivate) +{ + setTargets(local, remote); +} + +QNetworkConnectionMonitor::~QNetworkConnectionMonitor() +{ + Q_D(QNetworkConnectionMonitor); + + stopMonitoring(); + d->reset(); +} + +bool QNetworkConnectionMonitor::setTargets(const QHostAddress &local, const QHostAddress &remote) +{ + Q_D(QNetworkConnectionMonitor); + + if (isMonitoring()) { + qCWarning(lcNetMon, "Monitor is already active, call stopMonitoring() first"); + return false; + } + + if (local.isNull()) { + qCWarning(lcNetMon, "Invalid (null) local address, cannot create a reachability target"); + return false; + } + + // Clear the old target if needed: + d->reset(); + + qt_sockaddr client = qt_hostaddress_to_sockaddr(local); + if (remote.isNull()) { + // That's a special case our QNetworkStatusMonitor is using (AnyIpv4/6 address to check an overall status). + d->probe = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, reinterpret_cast(&client)); + } else { + qt_sockaddr target = qt_hostaddress_to_sockaddr(remote); + d->probe = SCNetworkReachabilityCreateWithAddressPair(kCFAllocatorDefault, + reinterpret_cast(&client), + reinterpret_cast(&target)); + } + + if (d->probe) { + // Let's read the initial state so that callback coming later can + // see a difference. Ignore errors though. + SCNetworkReachabilityGetFlags(d->probe, &d->state); + }else { + qCWarning(lcNetMon, "Failed to create network reachability probe"); + return false; + } + + return true; +} + +bool QNetworkConnectionMonitor::startMonitoring() +{ + Q_D(QNetworkConnectionMonitor); + + if (isMonitoring()) { + qCWarning(lcNetMon, "Monitor is already active, call stopMonitoring() first"); + return false; + } + + if (!d->probe) { + qCWarning(lcNetMon, "Can not start monitoring, set targets first"); + return false; + } + + auto queue = qt_reachability_queue(); + if (!queue) { + qWarning(lcNetMon, "Failed to create a dispatch queue to schedule a probe on"); + return false; + } + + SCNetworkReachabilityContext context = {}; + context.info = d; + if (!SCNetworkReachabilitySetCallback(d->probe, QNetworkConnectionMonitorPrivate::probeCallback, &context)) { + qWarning(lcNetMon, "Failed to set a reachability callback"); + return false; + } + + + if (!SCNetworkReachabilitySetDispatchQueue(d->probe, queue)) { + qWarning(lcNetMon, "Failed to schedule a reachability callback on a queue"); + return false; + } + + return d->scheduled = true; +} + +bool QNetworkConnectionMonitor::isMonitoring() const +{ + Q_D(const QNetworkConnectionMonitor); + + return d->scheduled; +} + +void QNetworkConnectionMonitor::stopMonitoring() +{ + Q_D(QNetworkConnectionMonitor); + + if (d->scheduled) { + Q_ASSERT(d->probe); + SCNetworkReachabilitySetDispatchQueue(d->probe, nullptr); + SCNetworkReachabilitySetCallback(d->probe, nullptr, nullptr); + d->scheduled = false; + } +} + +bool QNetworkConnectionMonitor::isReachable() +{ + Q_D(QNetworkConnectionMonitor); + + if (isMonitoring()) { + qCWarning(lcNetMon, "Calling isReachable() is unsafe after the monitoring started"); + return false; + } + + if (!d->probe) { + qCWarning(lcNetMon, "Reachability is unknown, set the target first"); + return false; + } + + return d->isReachable(); +} + +class QNetworkStatusMonitorPrivate : public QObjectPrivate +{ +public: + QNetworkConnectionMonitor ipv4Probe; + bool isOnlineIpv4 = false; + QNetworkConnectionMonitor ipv6Probe; + bool isOnlineIpv6 = false; + + static bool enabled; + static void readEnv(); +}; + +bool QNetworkStatusMonitorPrivate::enabled = false; + +void QNetworkStatusMonitorPrivate::readEnv() +{ + bool envOk = false; + const int env = qEnvironmentVariableIntValue("QT_USE_NETWORK_MONITOR", &envOk); + enabled = envOk && env > 0; +} + +QNetworkStatusMonitor::QNetworkStatusMonitor() + : QObject(*new QNetworkStatusMonitorPrivate) +{ + Q_D(QNetworkStatusMonitor); + + if (d->ipv4Probe.setTargets(QHostAddress::AnyIPv4, {})) { + // We manage to create SCNetworkReachabilityRef for IPv4, let's + // read the last known state then! + d->isOnlineIpv4 = d->ipv4Probe.isReachable(); + } + + if (d->ipv6Probe.setTargets(QHostAddress::AnyIPv6, {})) { + // We manage to create SCNetworkReachability ref for IPv6, let's + // read the last known state then! + d->isOnlineIpv6 = d->ipv6Probe.isReachable(); + } + + + connect(&d->ipv4Probe, &QNetworkConnectionMonitor::reachabilityChanged, this, + &QNetworkStatusMonitor::reachabilityChanged, Qt::QueuedConnection); + connect(&d->ipv6Probe, &QNetworkConnectionMonitor::reachabilityChanged, this, + &QNetworkStatusMonitor::reachabilityChanged, Qt::QueuedConnection); +} + +QNetworkStatusMonitor::~QNetworkStatusMonitor() +{ + Q_D(QNetworkStatusMonitor); + + d->ipv4Probe.disconnect(); + d->ipv4Probe.stopMonitoring(); + d->ipv6Probe.disconnect(); + d->ipv6Probe.stopMonitoring(); +} + +bool QNetworkStatusMonitor::start() +{ + Q_D(QNetworkStatusMonitor); + + if (isMonitoring()) { + qCWarning(lcNetMon, "Network status monitor is already active"); + return true; + } + + d->ipv4Probe.startMonitoring(); + d->ipv6Probe.startMonitoring(); + + return isMonitoring(); +} + +void QNetworkStatusMonitor::stop() +{ + Q_D(QNetworkStatusMonitor); + + if (d->ipv4Probe.isMonitoring()) + d->ipv4Probe.stopMonitoring(); + if (d->ipv6Probe.isMonitoring()) + d->ipv6Probe.stopMonitoring(); +} + +bool QNetworkStatusMonitor::isMonitoring() const +{ + Q_D(const QNetworkStatusMonitor); + + return d->ipv4Probe.isMonitoring() || d->ipv6Probe.isMonitoring(); +} + +bool QNetworkStatusMonitor::isNetworkAccesible() +{ + // This function is to be executed on the thread that created + // and uses 'this'. + Q_D(QNetworkStatusMonitor); + + return d->isOnlineIpv4 || d->isOnlineIpv6; +} + +bool QNetworkStatusMonitor::isEnabled() +{ + static std::once_flag envRead = {}; + std::call_once(envRead, QNetworkStatusMonitorPrivate::readEnv); + return QNetworkStatusMonitorPrivate::enabled; +} + +void QNetworkStatusMonitor::reachabilityChanged(bool online) +{ + // This function is executed on the thread that created/uses 'this', + // not on the reachability queue. + Q_D(QNetworkStatusMonitor); + + auto probe = qobject_cast(sender()); + if (!probe) + return; + + const bool isIpv4 = probe == &d->ipv4Probe; + bool &probeOnline = isIpv4 ? d->isOnlineIpv4 : d->isOnlineIpv6; + bool otherOnline = isIpv4 ? d->isOnlineIpv6 : d->isOnlineIpv4; + + if (probeOnline == online) { + // We knew this already? + return; + } + + probeOnline = online; + if (!otherOnline) { + // We either just lost or got a network access. + emit onlineStateChanged(probeOnline); + } +} + +QT_END_NAMESPACE diff --git a/src/network/kernel/qnetconmonitor_p.h b/src/network/kernel/qnetconmonitor_p.h new file mode 100644 index 0000000000..74ee56d422 --- /dev/null +++ b/src/network/kernel/qnetconmonitor_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 QNETCONMONITOR_P_H +#define QNETCONMONITOR_P_H + +#include + +#include +#include +#include +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class QNetworkConnectionMonitorPrivate; +class QNetworkConnectionMonitor : public QObject +{ + Q_OBJECT + +public: + QNetworkConnectionMonitor(); + QNetworkConnectionMonitor(const QHostAddress &local, const QHostAddress &remote = {}); + ~QNetworkConnectionMonitor(); + + bool setTargets(const QHostAddress &local, const QHostAddress &remote); + bool isReachable(); + + // Important: on Darwin you should not call isReachable() after + // startMonitoring(), you have to listen to reachabilityChanged() + // signal instead. + bool startMonitoring(); + bool isMonitoring() const; + void stopMonitoring(); + +Q_SIGNALS: + // Important: connect to this using QueuedConnection. On Darwin + // callback is coming on a special dispatch queue. + void reachabilityChanged(bool isOnline); + +private: + Q_DECLARE_PRIVATE(QNetworkConnectionMonitor) + Q_DISABLE_COPY_MOVE(QNetworkConnectionMonitor) +}; + +class QNetworkStatusMonitorPrivate; +class QNetworkStatusMonitor : public QObject +{ + Q_OBJECT + +public: + QNetworkStatusMonitor(); + ~QNetworkStatusMonitor(); + + bool isNetworkAccesible(); + + bool start(); + void stop(); + bool isMonitoring() const; + + static bool isEnabled(); + +Q_SIGNALS: + // Unlike QNetworkConnectionMonitor, this can be connected to directly. + void onlineStateChanged(bool isOnline); + +private slots: + void reachabilityChanged(bool isOnline); + +private: + Q_DECLARE_PRIVATE(QNetworkStatusMonitor) + Q_DISABLE_COPY_MOVE(QNetworkStatusMonitor) +}; + +Q_DECLARE_LOGGING_CATEGORY(lcNetMon) + +QT_END_NAMESPACE + +#endif // QNETCONMONITOR_P_H diff --git a/src/network/kernel/qnetconmonitor_stub.cpp b/src/network/kernel/qnetconmonitor_stub.cpp new file mode 100644 index 0000000000..7f3a0c44c6 --- /dev/null +++ b/src/network/kernel/qnetconmonitor_stub.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 "qnetconmonitor_p.h" + +#include "private/qobject_p.h" + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcNetMon, "qt.network.monitor"); + +// Note: this 'stub' version is never enabled (see QNetworkStatusMonitor::isEnabled below) +// and thus should never affect QNAM in any unusuall way. Having this 'stub' version is similar +// to building Qt with bearer management configured out. + +class QNetworkConnectionMonitorPrivate : public QObjectPrivate +{ +}; + +QNetworkConnectionMonitor::QNetworkConnectionMonitor() + : QObject(*new QNetworkConnectionMonitorPrivate) +{ +} + +QNetworkConnectionMonitor::QNetworkConnectionMonitor(const QHostAddress &local, const QHostAddress &remote) + : QObject(*new QNetworkConnectionMonitorPrivate) +{ + Q_UNUSED(local) + Q_UNUSED(remote) +} + +QNetworkConnectionMonitor::~QNetworkConnectionMonitor() +{ +} + +bool QNetworkConnectionMonitor::setTargets(const QHostAddress &local, const QHostAddress &remote) +{ + Q_UNUSED(local) + Q_UNUSED(remote) + + return false; +} + +bool QNetworkConnectionMonitor::startMonitoring() +{ + return false; +} + +bool QNetworkConnectionMonitor::isMonitoring() const +{ + return false; +} + +void QNetworkConnectionMonitor::stopMonitoring() +{ +} + +bool QNetworkConnectionMonitor::isReachable() +{ + return false; +} + +class QNetworkStatusMonitorPrivate : public QObjectPrivate +{ +}; + +QNetworkStatusMonitor::QNetworkStatusMonitor() + : QObject(*new QNetworkStatusMonitorPrivate) +{ +} + +QNetworkStatusMonitor::~QNetworkStatusMonitor() +{ +} + +bool QNetworkStatusMonitor::start() +{ + return false; +} + +void QNetworkStatusMonitor::stop() +{ +} + +bool QNetworkStatusMonitor::isMonitoring() const +{ + return false; +} + +bool QNetworkStatusMonitor::isNetworkAccesible() +{ + return false; +} + +bool QNetworkStatusMonitor::isEnabled() +{ + return false; +} + +void QNetworkStatusMonitor::reachabilityChanged(bool online) +{ + Q_UNUSED(online) +} + +QT_END_NAMESPACE From c940ca50ce0db76e12b06eb9cefd13c0876c0938 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 30 Apr 2019 11:55:55 +0200 Subject: [PATCH 041/122] Remove spurious class-name prefixes in its own methods Change-Id: I13093e02b251a084e468a50471cf1b9256555e40 Reviewed-by: Jesus Fernandez Reviewed-by: Thiago Macieira --- src/corelib/tools/qlocale_p.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index 16ded7650c..15398ded32 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -359,9 +359,9 @@ public: QByteArray bcp47Name(char separator = '-') const; - inline QLatin1String languageCode() const { return QLocalePrivate::languageToCode(QLocale::Language(m_data->m_language_id)); } - inline QLatin1String scriptCode() const { return QLocalePrivate::scriptToCode(QLocale::Script(m_data->m_script_id)); } - inline QLatin1String countryCode() const { return QLocalePrivate::countryToCode(QLocale::Country(m_data->m_country_id)); } + inline QLatin1String languageCode() const { return languageToCode(QLocale::Language(m_data->m_language_id)); } + inline QLatin1String scriptCode() const { return scriptToCode(QLocale::Script(m_data->m_script_id)); } + inline QLatin1String countryCode() const { return countryToCode(QLocale::Country(m_data->m_country_id)); } static QLatin1String languageToCode(QLocale::Language language); static QLatin1String scriptToCode(QLocale::Script script); From 7a0d4b39daa1beed7070ceb43414eb55934f1266 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 30 Apr 2019 16:58:38 +0200 Subject: [PATCH 042/122] Doc-fix: mention FP_ZERO as a possible return of qFpClassify() This follows up on commit 84aea6c091d020a37c2b452a6f56ca27b3b2c7cb, in which I forgot to mention this possible return value. Change-Id: I109bed66bc0fd63d7ee289bfaea65b3d05c6560c Reviewed-by: Giuseppe D'Angelo Reviewed-by: Thiago Macieira --- src/corelib/global/qnumeric.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/corelib/global/qnumeric.cpp b/src/corelib/global/qnumeric.cpp index e6ba62f530..11440f40a4 100644 --- a/src/corelib/global/qnumeric.cpp +++ b/src/corelib/global/qnumeric.cpp @@ -110,6 +110,7 @@ Q_CORE_EXPORT double qInf() { return qt_inf(); } \list \li FP_NAN not a number \li FP_INFINITE infinities (positive or negative) + \li FP_ZERO zero (positive or negative) \li FP_NORMAL finite with a full mantissa \li FP_SUBNORMAL finite with a reduced mantissa \endlist From a2b38f64e6def1538b9d153ec4c6589fa9b6d3c0 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 30 Apr 2019 17:53:53 +0200 Subject: [PATCH 043/122] Remove handling of missing =delete and =default support Change-Id: I006dfd0b7cfa3bda5e5ab01bcefa851f031dfe0e Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.h | 6 +++--- src/corelib/kernel/qmetaobject.h | 2 +- src/corelib/kernel/qmetatype.h | 2 +- src/corelib/kernel/qvariant.h | 14 +++++++------- src/corelib/thread/qatomic_cxx11.h | 2 +- src/corelib/thread/qbasicatomic.h | 2 +- src/corelib/thread/qthread.h | 2 -- src/corelib/tools/qmap.h | 2 +- src/corelib/tools/qsharedpointer_impl.h | 12 ++++-------- src/corelib/tools/qstringbuilder.h | 4 ++-- src/gui/image/qiconengine.h | 2 +- src/widgets/kernel/qtooltip.h | 2 +- src/widgets/kernel/qwhatsthis.h | 2 +- src/xml/sax/qxml.h | 2 -- 14 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index ceae0583ee..4817acb48f 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -422,8 +422,8 @@ typedef double qreal; operator to disable copying (the compiler gives an error message). */ #define Q_DISABLE_COPY(Class) \ - Class(const Class &) Q_DECL_EQ_DELETE;\ - Class &operator=(const Class &) Q_DECL_EQ_DELETE; + Class(const Class &) = delete;\ + Class &operator=(const Class &) = delete; #define Q_DISABLE_MOVE(Class) \ Class(Class &&) = delete; \ @@ -1021,7 +1021,7 @@ template Q_DECL_CONSTEXPR typename std::add_const::type &qAsConst(T &t) noexcept { return t; } // prevent rvalue arguments: template -void qAsConst(const T &&) Q_DECL_EQ_DELETE; +void qAsConst(const T &&) = delete; #ifndef QT_NO_FOREACH diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 6c5f78d208..10b14a7e03 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -183,7 +183,7 @@ private: // signature() has been renamed to methodSignature() in Qt 5. // Warning, that function returns a QByteArray; check the life time if // you convert to char*. - char *signature(struct renamedInQt5_warning_checkTheLifeTime * = nullptr) Q_DECL_EQ_DELETE; + char *signature(struct renamedInQt5_warning_checkTheLifeTime * = nullptr) = delete; #endif static QMetaMethod fromSignalImpl(const QMetaObject *, void **); diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index a47fbfe28d..79ee5eec11 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -849,7 +849,7 @@ struct VariantData const uint flags; private: // copy constructor allowed to be implicit to silence level 4 warning from MSVC - VariantData &operator=(const VariantData &) Q_DECL_EQ_DELETE; + VariantData &operator=(const VariantData &) = delete; }; template diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 2247c7adc8..924cfa1e1a 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -483,27 +483,27 @@ public: private: // force compile error, prevent QVariant(bool) to be called - inline QVariant(void *) Q_DECL_EQ_DELETE; + inline QVariant(void *) = delete; // QVariant::Type is marked as \obsolete, but we don't want to // provide a constructor from its intended replacement, // QMetaType::Type, instead, because the idea behind these // constructors is flawed in the first place. But we also don't // want QVariant(QMetaType::String) to compile and falsely be an // int variant, so delete this constructor: - QVariant(QMetaType::Type) Q_DECL_EQ_DELETE; + QVariant(QMetaType::Type) = delete; // These constructors don't create QVariants of the type associcated // with the enum, as expected, but they would create a QVariant of // type int with the value of the enum value. // Use QVariant v = QColor(Qt::red) instead of QVariant v = Qt::red for // example. - QVariant(Qt::GlobalColor) Q_DECL_EQ_DELETE; - QVariant(Qt::BrushStyle) Q_DECL_EQ_DELETE; - QVariant(Qt::PenStyle) Q_DECL_EQ_DELETE; - QVariant(Qt::CursorShape) Q_DECL_EQ_DELETE; + QVariant(Qt::GlobalColor) = delete; + QVariant(Qt::BrushStyle) = delete; + QVariant(Qt::PenStyle) = delete; + QVariant(Qt::CursorShape) = delete; #ifdef QT_NO_CAST_FROM_ASCII // force compile error when implicit conversion is not wanted - inline QVariant(const char *) Q_DECL_EQ_DELETE; + inline QVariant(const char *) = delete; #endif public: typedef Private DataPtr; diff --git a/src/corelib/thread/qatomic_cxx11.h b/src/corelib/thread/qatomic_cxx11.h index 32d27734fc..2851bae73e 100644 --- a/src/corelib/thread/qatomic_cxx11.h +++ b/src/corelib/thread/qatomic_cxx11.h @@ -462,7 +462,7 @@ template struct QAtomicOps } }; -#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS) +#if defined(Q_COMPILER_CONSTEXPR) # define Q_BASIC_ATOMIC_INITIALIZER(a) { a } #else # define Q_BASIC_ATOMIC_INITIALIZER(a) { ATOMIC_VAR_INIT(a) } diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index 4c3c1fc01f..7d2e06a499 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -75,7 +75,7 @@ QT_END_NAMESPACE // New atomics -#if defined(Q_COMPILER_CONSTEXPR) && defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS) +#if defined(Q_COMPILER_CONSTEXPR) # if defined(Q_CC_CLANG) && Q_CC_CLANG < 303 /* Do not define QT_BASIC_ATOMIC_HAS_CONSTRUCTORS for Clang before version 3.3. diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index 8e92d75401..c7a6dc8f1a 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -209,7 +209,6 @@ struct Callable { } -#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS) // Apply the same semantics of a lambda closure type w.r.t. the special // member functions, if possible: delete the copy assignment operator, // bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure]) @@ -218,7 +217,6 @@ struct Callable Callable(Callable &&) = default; Callable &operator=(const Callable &) = delete; Callable &operator=(Callable &&) = default; -#endif void operator()() { diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 3b8aad9a33..2d01a75a42 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -142,7 +142,7 @@ private: rightNode()->destroySubTree(); } - QMapNode() Q_DECL_EQ_DELETE; + QMapNode() = delete; Q_DISABLE_COPY(QMapNode) }; diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 9fb452da6b..c219d310dc 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -235,8 +235,8 @@ namespace QtSharedPointer { } private: // prevent construction - ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE; - ~ExternalRefCountWithCustomDeleter() Q_DECL_EQ_DELETE; + ExternalRefCountWithCustomDeleter() = delete; + ~ExternalRefCountWithCustomDeleter() = delete; Q_DISABLE_COPY(ExternalRefCountWithCustomDeleter) }; @@ -280,8 +280,8 @@ namespace QtSharedPointer { private: // prevent construction - ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE; - ~ExternalRefCountWithContiguousData() Q_DECL_EQ_DELETE; + ExternalRefCountWithContiguousData() = delete; + ~ExternalRefCountWithContiguousData() = delete; Q_DISABLE_COPY(ExternalRefCountWithContiguousData) }; @@ -705,11 +705,7 @@ template class QEnableSharedFromThis { protected: -#ifdef Q_COMPILER_DEFAULT_MEMBERS QEnableSharedFromThis() = default; -#else - Q_DECL_CONSTEXPR QEnableSharedFromThis() {} -#endif QEnableSharedFromThis(const QEnableSharedFromThis &) {} QEnableSharedFromThis &operator=(const QEnableSharedFromThis &) { return *this; } diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 79ed10c7a8..b3cf2f695e 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -150,7 +150,7 @@ class QStringBuilder : public QStringBuilderBase @@ -167,7 +167,7 @@ class QStringBuilder : public QStringBuilderBase Date: Wed, 24 Apr 2019 18:03:59 +0200 Subject: [PATCH 044/122] Increase entityCharacterLimit to 4096 The previous fix to decrease the limit to 1024 breaks the parsing for some files. The limit is arbitrary, so increasing it to 4096, which is what some linux distros have been working with. Change-Id: I131f15278aa99c3f91db2e1ec2d14156ceed4775 Fixes: QTBUG-35459 Reviewed-by: Mitch Curtis Reviewed-by: David Faure --- src/xml/sax/qxml_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xml/sax/qxml_p.h b/src/xml/sax/qxml_p.h index 98dc2aea0c..eb6135db04 100644 --- a/src/xml/sax/qxml_p.h +++ b/src/xml/sax/qxml_p.h @@ -229,7 +229,7 @@ private: // for the DTD currently being parsed. static const int dtdRecursionLimit = 2; // The maximum amount of characters an entity value may contain, after expansion. - static const int entityCharacterLimit = 1024; + static const int entityCharacterLimit = 4096; const QString &string(); void stringClear(); From 343528841e72adf36a37d9afd7260e260a9342eb Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 12:51:36 +0200 Subject: [PATCH 045/122] Prefix textstream operators with Qt:: As the non prefixed variants are deprecated Change-Id: I2ba09d71b9cea5203b54297a3f2332e6d44fedcf Reviewed-by: Allan Sandfeld Jensen --- .../serialization/convert/cborconverter.cpp | 2 +- .../serialization/convert/textconverter.cpp | 6 +- examples/xml/htmlinfo/main.cpp | 18 +- qmake/generators/mac/pbuilder_pbx.cpp | 28 +- qmake/generators/makefile.cpp | 156 ++++----- qmake/generators/projectgenerator.cpp | 14 +- qmake/generators/unix/unixmake2.cpp | 160 ++++----- qmake/generators/win32/mingw_make.cpp | 24 +- qmake/generators/win32/msvc_nmake.cpp | 12 +- qmake/generators/win32/msvc_objectmodel.h | 2 +- qmake/generators/win32/winmakefile.cpp | 108 +++--- qmake/generators/xmloutput.cpp | 6 +- src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp | 2 +- src/3rdparty/harfbuzz/tests/shaping/main.cpp | 4 +- .../doc/snippets/code/doc_src_qset.cpp | 4 +- .../code/src_corelib_io_qtextstream.cpp | 4 +- .../code/src_corelib_thread_qfuture.cpp | 2 +- .../code/src_corelib_tools_qbytearray.cpp | 6 +- .../snippets/code/src_corelib_tools_qhash.cpp | 28 +- .../code/src_corelib_tools_qlinkedlist.cpp | 8 +- .../code/src_corelib_tools_qlistdata.cpp | 8 +- .../snippets/code/src_corelib_tools_qmap.cpp | 30 +- .../code/src_corelib_tools_qqueue.cpp | 2 +- .../src_corelib_tools_qstringiterator.cpp | 6 +- .../code/src_corelib_tools_qvector.cpp | 4 +- src/corelib/doc/snippets/qstack/main.cpp | 2 +- src/corelib/doc/snippets/qstringlist/main.cpp | 6 +- src/corelib/io/qdebug.cpp | 6 +- src/corelib/io/qdebug.h | 2 +- src/corelib/io/qfilesystemwatcher_inotify.cpp | 2 +- src/corelib/io/qfilesystemwatcher_win.cpp | 4 +- src/corelib/kernel/qeventdispatcher_cf.mm | 2 +- src/corelib/kernel/qtimerinfo_unix.cpp | 8 +- src/corelib/plugin/qfactoryloader.cpp | 2 +- src/corelib/serialization/qcborvalue.cpp | 2 +- src/corelib/serialization/qjsonparser.cpp | 2 +- src/corelib/serialization/qtextstream.cpp | 4 +- src/corelib/tools/qstring.cpp | 6 +- src/gui/accessible/qaccessible.cpp | 4 +- .../doc/snippets/textdocumentendsnippet.cpp | 2 +- src/gui/image/qicon.cpp | 2 +- src/gui/image/qpixmap.cpp | 2 +- src/gui/image/qxpmhandler.cpp | 10 +- src/gui/kernel/qevent.cpp | 10 +- src/gui/kernel/qpalette.cpp | 4 +- src/gui/kernel/qscreen.cpp | 2 +- src/gui/kernel/qwindow.cpp | 4 +- src/gui/math3d/qgenericmatrix.h | 4 +- src/gui/math3d/qmatrix4x4.cpp | 10 +- src/gui/opengl/qopengl.cpp | 2 +- src/gui/painting/qblendfunctions_p.h | 16 +- src/gui/painting/qpaintengine_raster.cpp | 4 +- src/gui/painting/qpaintengineex.cpp | 2 +- src/gui/painting/qpainterpath.cpp | 4 +- src/gui/text/qfontengine.cpp | 2 +- src/gui/text/qfontengine_qpf2.cpp | 6 +- src/gui/text/qtextengine.cpp | 8 +- .../freetype/qfreetypefontdatabase.cpp | 2 +- src/plugins/bearer/nla/qnlaengine.cpp | 30 +- .../platforms/android/androidjnimain.cpp | 2 +- .../platforms/cocoa/qcocoaaccessibility.mm | 2 +- .../platforms/cocoa/qnsview_gestures.mm | 10 +- src/plugins/platforms/cocoa/qnsview_touch.mm | 8 +- .../eglfs_kms/qeglfskmsgbmscreen.cpp | 2 +- .../platforms/windows/qwindowscontext.cpp | 4 +- .../windows/qwindowsdialoghelpers.cpp | 6 +- .../platforms/windows/qwindowsdrag.cpp | 8 +- .../platforms/windows/qwindowsglcontext.cpp | 8 +- .../windows/qwindowsinputcontext.cpp | 4 +- .../platforms/windows/qwindowsintegration.cpp | 6 +- .../platforms/windows/qwindowskeymapper.cpp | 6 +- .../platforms/windows/qwindowsmenu.cpp | 6 +- .../windows/qwindowsmousehandler.cpp | 4 +- src/plugins/platforms/windows/qwindowsole.cpp | 6 +- .../windows/qwindowsopengltester.cpp | 8 +- .../windows/qwindowspointerhandler.cpp | 20 +- .../windows/qwindowstabletsupport.cpp | 12 +- .../platforms/windows/qwindowswindow.cpp | 6 +- .../platforms/xcb/qxcbnativeinterface.cpp | 8 +- src/plugins/platforms/xcb/qxcbscreen.cpp | 6 +- .../doc/snippets/sqldatabase/sqldatabase.cpp | 4 +- src/sql/kernel/qsqlrecord.cpp | 2 +- src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp | 328 +++++++++--------- src/tools/qlalr/cppgenerator.cpp | 188 +++++----- src/tools/qlalr/dotgraph.cpp | 22 +- src/tools/qlalr/lalr.cpp | 20 +- src/tools/qlalr/lalr.g | 12 +- src/tools/qlalr/main.cpp | 24 +- src/tools/qlalr/parsetable.cpp | 26 +- src/tools/qlalr/recognizer.cpp | 12 +- src/tools/uic/cpp/cppwriteinitialization.cpp | 10 +- src/widgets/itemviews/qtableview.cpp | 8 +- src/widgets/kernel/qwidget.cpp | 4 +- src/widgets/widgets/qsplitter.cpp | 2 +- .../doc/snippets/code/src_xml_dom_qdom.cpp | 8 +- src/xml/dom/qdom.cpp | 18 +- 96 files changed, 826 insertions(+), 826 deletions(-) diff --git a/examples/corelib/serialization/convert/cborconverter.cpp b/examples/corelib/serialization/convert/cborconverter.cpp index ad69983eb1..f907bb0af6 100644 --- a/examples/corelib/serialization/convert/cborconverter.cpp +++ b/examples/corelib/serialization/convert/cborconverter.cpp @@ -226,7 +226,7 @@ void CborDiagnosticDumper::saveFile(QIODevice *f, const QVariant &contents, cons QTextStream out(f); out << convertFromVariant(contents, Double).toDiagnosticNotation(opts) - << endl; + << Qt::endl; } CborConverter::CborConverter() diff --git a/examples/corelib/serialization/convert/textconverter.cpp b/examples/corelib/serialization/convert/textconverter.cpp index e80e69a0b5..7aed08f96c 100644 --- a/examples/corelib/serialization/convert/textconverter.cpp +++ b/examples/corelib/serialization/convert/textconverter.cpp @@ -66,7 +66,7 @@ static void dumpVariant(QTextStream &out, const QVariant &v) case QVariant::String: { const QStringList list = v.toStringList(); for (const QString &s : list) - out << s << endl; + out << s << Qt::endl; break; } @@ -80,11 +80,11 @@ static void dumpVariant(QTextStream &out, const QVariant &v) } case QMetaType::Nullptr: - out << "(null)" << endl; + out << "(null)" << Qt::endl; break; default: - out << v.toString() << endl; + out << v.toString() << Qt::endl; break; } } diff --git a/examples/xml/htmlinfo/main.cpp b/examples/xml/htmlinfo/main.cpp index 22bf36f33c..bc19ae4a82 100644 --- a/examples/xml/htmlinfo/main.cpp +++ b/examples/xml/htmlinfo/main.cpp @@ -54,10 +54,10 @@ void parseHtmlFile(QTextStream &out, const QString &fileName) { QFile file(fileName); - out << "Analysis of HTML file: " << fileName << endl; + out << "Analysis of HTML file: " << fileName << Qt::endl; if (!file.open(QIODevice::ReadOnly)) { - out << " Couldn't open the file." << endl << endl << endl; + out << " Couldn't open the file." << Qt::endl << Qt::endl << Qt::endl; return; } @@ -85,22 +85,22 @@ void parseHtmlFile(QTextStream &out, const QString &fileName) //! [2] if (reader.hasError()) { out << " The HTML file isn't well-formed: " << reader.errorString() - << endl << endl << endl; + << Qt::endl << Qt::endl << Qt::endl; return; } //! [2] - out << " Title: \"" << title << '"' << endl - << " Number of paragraphs: " << paragraphCount << endl - << " Number of links: " << links.size() << endl - << " Showing first few links:" << endl; + out << " Title: \"" << title << '"' << Qt::endl + << " Number of paragraphs: " << paragraphCount << Qt::endl + << " Number of links: " << links.size() << Qt::endl + << " Showing first few links:" << Qt::endl; while (links.size() > 5) links.removeLast(); for (const QString &link : qAsConst(links)) - out << " " << link << endl; - out << endl << endl; + out << " " << link << Qt::endl; + out << Qt::endl << Qt::endl; } int main(int argc, char **argv) diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 07832041a7..3bed28afdf 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -541,7 +541,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData()); QTextStream mkt(&mkf); writeHeader(mkt); - mkt << "QMAKE = " << var("QMAKE_QMAKE") << endl; + mkt << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl; project->values("QMAKE_MAKE_QMAKE_EXTRA_COMMANDS") << "@echo 'warning: Xcode project has been regenerated, custom settings have been lost. " \ "Use CONFIG+=no_autoqmake to prevent this behavior in the future, " \ @@ -740,15 +740,15 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData()); QTextStream mkt(&mkf); writeHeader(mkt); - mkt << "MOC = " << var("QMAKE_MOC") << endl; - mkt << "UIC = " << var("QMAKE_UIC") << endl; - mkt << "LEX = " << var("QMAKE_LEX") << endl; - mkt << "LEXFLAGS = " << var("QMAKE_LEXFLAGS") << endl; - mkt << "YACC = " << var("QMAKE_YACC") << endl; - mkt << "YACCFLAGS = " << var("QMAKE_YACCFLAGS") << endl; + mkt << "MOC = " << var("QMAKE_MOC") << Qt::endl; + mkt << "UIC = " << var("QMAKE_UIC") << Qt::endl; + mkt << "LEX = " << var("QMAKE_LEX") << Qt::endl; + mkt << "LEXFLAGS = " << var("QMAKE_LEXFLAGS") << Qt::endl; + mkt << "YACC = " << var("QMAKE_YACC") << Qt::endl; + mkt << "YACCFLAGS = " << var("QMAKE_YACCFLAGS") << Qt::endl; mkt << "DEFINES = " << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ") - << varGlue("DEFINES","-D"," -D","") << endl; + << varGlue("DEFINES","-D"," -D","") << Qt::endl; mkt << "INCPATH ="; { const ProStringList &incs = project->values("INCLUDEPATH"); @@ -757,9 +757,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) } if(!project->isEmpty("QMAKE_FRAMEWORKPATH_FLAGS")) mkt << " " << var("QMAKE_FRAMEWORKPATH_FLAGS"); - mkt << endl; - mkt << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; - mkt << "MOVE = " << var("QMAKE_MOVE") << endl << endl; + mkt << Qt::endl; + mkt << "DEL_FILE = " << var("QMAKE_DEL_FILE") << Qt::endl; + mkt << "MOVE = " << var("QMAKE_MOVE") << Qt::endl << Qt::endl; mkt << "preprocess: compilers\n"; mkt << "clean preprocess_clean: compiler_clean\n\n"; writeExtraTargets(mkt); @@ -789,7 +789,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) } } } - mkt << endl; + mkt << Qt::endl; writeExtraCompilerTargets(mkt); writingUnixMakefileGenerator = false; } @@ -994,12 +994,12 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) tmp = project->values("SUBLIBS"); for(int i = 0; i < tmp.count(); i++) t << escapeFilePath("tmp/lib" + tmp[i] + ".a") << ' '; - t << endl << endl; + t << Qt::endl << Qt::endl; mkt << "sublibs: $(SUBLIBS)\n\n"; tmp = project->values("SUBLIBS"); for(int i = 0; i < tmp.count(); i++) t << escapeFilePath("tmp/lib" + tmp[i] + ".a") + ":\n\t" - << var(ProKey("MAKELIB" + tmp[i])) << endl << endl; + << var(ProKey("MAKELIB" + tmp[i])) << Qt::endl << Qt::endl; mkt.flush(); mkf.close(); writingUnixMakefileGenerator = false; diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index b634ec622b..aae5a44e21 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -994,25 +994,25 @@ MakefileGenerator::writePrlFile(QTextStream &t) QString bdir = Option::output_dir; if(bdir.isEmpty()) bdir = qmake_getpwd(); - t << "QMAKE_PRL_BUILD_DIR =" << qv(bdir) << endl; + t << "QMAKE_PRL_BUILD_DIR =" << qv(bdir) << Qt::endl; - t << "QMAKE_PRO_INPUT =" << qv(project->projectFile().section('/', -1)) << endl; + t << "QMAKE_PRO_INPUT =" << qv(project->projectFile().section('/', -1)) << Qt::endl; if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) - t << "QMAKE_PRL_SOURCE_DIR =" << qv(project->first("QMAKE_ABSOLUTE_SOURCE_PATH")) << endl; - t << "QMAKE_PRL_TARGET =" << qv(project->first("LIB_TARGET")) << endl; + t << "QMAKE_PRL_SOURCE_DIR =" << qv(project->first("QMAKE_ABSOLUTE_SOURCE_PATH")) << Qt::endl; + t << "QMAKE_PRL_TARGET =" << qv(project->first("LIB_TARGET")) << Qt::endl; if(!project->isEmpty("PRL_EXPORT_DEFINES")) - t << "QMAKE_PRL_DEFINES =" << qv(project->values("PRL_EXPORT_DEFINES")) << endl; + t << "QMAKE_PRL_DEFINES =" << qv(project->values("PRL_EXPORT_DEFINES")) << Qt::endl; if(!project->isEmpty("PRL_EXPORT_CFLAGS")) - t << "QMAKE_PRL_CFLAGS =" << qv(project->values("PRL_EXPORT_CFLAGS")) << endl; + t << "QMAKE_PRL_CFLAGS =" << qv(project->values("PRL_EXPORT_CFLAGS")) << Qt::endl; if(!project->isEmpty("PRL_EXPORT_CXXFLAGS")) - t << "QMAKE_PRL_CXXFLAGS =" << qv(project->values("PRL_EXPORT_CXXFLAGS")) << endl; + t << "QMAKE_PRL_CXXFLAGS =" << qv(project->values("PRL_EXPORT_CXXFLAGS")) << Qt::endl; if(!project->isEmpty("CONFIG")) - t << "QMAKE_PRL_CONFIG =" << qv(project->values("CONFIG")) << endl; + t << "QMAKE_PRL_CONFIG =" << qv(project->values("CONFIG")) << Qt::endl; if(!project->isEmpty("TARGET_VERSION_EXT")) - t << "QMAKE_PRL_VERSION = " << project->first("TARGET_VERSION_EXT") << endl; + t << "QMAKE_PRL_VERSION = " << project->first("TARGET_VERSION_EXT") << Qt::endl; else if(!project->isEmpty("VERSION")) - t << "QMAKE_PRL_VERSION = " << project->first("VERSION") << endl; + t << "QMAKE_PRL_VERSION = " << project->first("VERSION") << Qt::endl; if(project->isActiveConfig("staticlib") || project->isActiveConfig("explicitlib")) { ProStringList libs; if (!project->isActiveConfig("staticlib")) @@ -1022,7 +1022,7 @@ MakefileGenerator::writePrlFile(QTextStream &t) t << "QMAKE_PRL_LIBS ="; for (ProStringList::Iterator it = libs.begin(); it != libs.end(); ++it) t << qv(project->values((*it).toKey())); - t << endl; + t << Qt::endl; } } @@ -1055,15 +1055,15 @@ MakefileGenerator::writeProjectMakefile() t << "install: "; for(it = targets.begin(); it != targets.end(); ++it) t << (*it)->target << "-install "; - t << endl; + t << Qt::endl; //uninstall t << "uninstall: "; for(it = targets.begin(); it != targets.end(); ++it) t << (*it)->target << "-uninstall "; - t << endl; + t << Qt::endl; } else { - t << "first: " << targets.first()->target << endl + t << "first: " << targets.first()->target << Qt::endl << "install: " << targets.first()->target << "-install\n" << "uninstall: " << targets.first()->target << "-uninstall\n"; } @@ -1072,7 +1072,7 @@ MakefileGenerator::writeProjectMakefile() if(!project->isActiveConfig("no_autoqmake")) { QString mkf = escapeDependencyPath(fileFixify(Option::output.fileName())); for(QList::Iterator it = targets.begin(); it != targets.end(); ++it) - t << escapeDependencyPath((*it)->makefile) << ": " << mkf << endl; + t << escapeDependencyPath((*it)->makefile) << ": " << mkf << Qt::endl; } qDeleteAll(targets); return true; @@ -1186,7 +1186,7 @@ MakefileGenerator::writeObj(QTextStream &t, const char *src) p.replace(stringObj, escapeFilePath(dstf)); t << "\n\t" << p; } - t << endl << endl; + t << Qt::endl << Qt::endl; } } @@ -1380,14 +1380,14 @@ MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild) QString tmp_dst = fileFixify((*pit).toQString(), FileFixifyAbsolute, false); t << mkdir_p_asstring(filePrefixRoot(root, tmp_dst)) << "\n\t"; } - t << target << endl << endl; + t << target << Qt::endl << Qt::endl; if(!uninst.isEmpty()) { t << "uninstall_" << (*it) << ": FORCE"; for (int i = uninst.size(); --i >= 0; ) t << "\n\t" << uninst.at(i); t << "\n\t-$(DEL_DIR) " << escapeFilePath(filePrefixRoot(root, dst)) << " \n\n"; } - t << endl; + t << Qt::endl; if (installConfigValues.indexOf("no_default_install") == -1) { all_installs += QString("install_") + (*it) + " "; @@ -1824,7 +1824,7 @@ MakefileGenerator::writeExtraTargets(QTextStream &t) t << escapeDependencyPath(targ) << ":" << deps; if(!cmd.isEmpty()) t << "\n\t" << cmd; - t << endl << endl; + t << Qt::endl << Qt::endl; } } @@ -1916,7 +1916,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) FileFixifyFromOutdir)); } } - t << endl; + t << Qt::endl; if (config.indexOf("no_clean") == -1) { QStringList raw_clean = project->values(ProKey(*it + ".clean")).toQStringList(); @@ -1981,7 +1981,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) } } } - t << endl; + t << Qt::endl; } QStringList tmp_dep = project->values(ProKey(*it + ".depends")).toQStringList(); if (config.indexOf("combine") != -1) { @@ -2065,7 +2065,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) } else { t << " " << valList(escapeDependencyPaths(inputs)) << " " << valList(finalizeDependencyPaths(deps)); } - t << "\n\t" << cmd << endl << endl; + t << "\n\t" << cmd << Qt::endl << Qt::endl; continue; } for (ProStringList::ConstIterator input = tmp_inputs.cbegin(); input != tmp_inputs.cend(); ++input) { @@ -2177,10 +2177,10 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t) ++i; } t << escapeDependencyPath(out) << ": " << valList(finalizeDependencyPaths(deps)) << "\n\t" - << cmd << endl << endl; + << cmd << Qt::endl << Qt::endl; } } - t << "compiler_clean: " << clean_targets << endl << endl; + t << "compiler_clean: " << clean_targets << Qt::endl << Qt::endl; } void @@ -2196,17 +2196,17 @@ MakefileGenerator::writeExtraCompilerVariables(QTextStream &t) first = false; } t << "QMAKE_COMP_" << (*varit) << " = " - << valList(project->values((*varit).toKey())) << endl; + << valList(project->values((*varit).toKey())) << Qt::endl; } } if(!first) - t << endl; + t << Qt::endl; } void MakefileGenerator::writeExtraVariables(QTextStream &t) { - t << endl; + t << Qt::endl; ProStringList outlist; const ProValueMap &vars = project->variables(); @@ -2220,7 +2220,7 @@ MakefileGenerator::writeExtraVariables(QTextStream &t) } if (!outlist.isEmpty()) { t << "####### Custom Variables\n"; - t << outlist.join('\n') << endl << endl; + t << outlist.join('\n') << Qt::endl << Qt::endl; } } @@ -2236,11 +2236,11 @@ MakefileGenerator::writeExportedVariables(QTextStream &t) const ProString &name = project->first(ProKey(exp + ".name")); const ProString &value = project->first(ProKey(exp + ".value")); if (!value.isEmpty()) - t << name << " = " << value << endl; + t << name << " = " << value << Qt::endl; else t << name << " =\n"; } - t << endl; + t << Qt::endl; } bool @@ -2248,7 +2248,7 @@ MakefileGenerator::writeDummyMakefile(QTextStream &t) { if (project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()) return false; - t << "QMAKE = " << var("QMAKE_QMAKE") << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl; const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) t << *it << " "; @@ -2264,7 +2264,7 @@ MakefileGenerator::writeDummyMakefile(QTextStream &t) bool MakefileGenerator::writeStubMakefile(QTextStream &t) { - t << "QMAKE = " << var("QMAKE_QMAKE") << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl; const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) t << *it << " "; @@ -2293,22 +2293,22 @@ MakefileGenerator::writeMakefile(QTextStream &t) void MakefileGenerator::writeDefaultVariables(QTextStream &t) { - t << "QMAKE = " << var("QMAKE_QMAKE") << endl; - t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; - t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << endl; - t << "MKDIR = " << var("QMAKE_MKDIR") << endl; - t << "COPY = " << var("QMAKE_COPY") << endl; - t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << endl; - t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl; - t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << endl; - t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << endl; - t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl; - t << "QINSTALL = " << var("QMAKE_QMAKE") << " -install qinstall" << endl; - t << "QINSTALL_PROGRAM = " << var("QMAKE_QMAKE") << " -install qinstall -exe" << endl; - t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; - t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << endl; - t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; - t << "MOVE = " << var("QMAKE_MOVE") << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl; + t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << Qt::endl; + t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << Qt::endl; + t << "MKDIR = " << var("QMAKE_MKDIR") << Qt::endl; + t << "COPY = " << var("QMAKE_COPY") << Qt::endl; + t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << Qt::endl; + t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << Qt::endl; + t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << Qt::endl; + t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << Qt::endl; + t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << Qt::endl; + t << "QINSTALL = " << var("QMAKE_QMAKE") << " -install qinstall" << Qt::endl; + t << "QINSTALL_PROGRAM = " << var("QMAKE_QMAKE") << " -install qinstall -exe" << Qt::endl; + t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << Qt::endl; + t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << Qt::endl; + t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << Qt::endl; + t << "MOVE = " << var("QMAKE_MOVE") << Qt::endl; } QString MakefileGenerator::buildArgs(bool withExtra) @@ -2349,18 +2349,18 @@ void MakefileGenerator::writeHeader(QTextStream &t) { t << "#############################################################################\n"; - t << "# Makefile for building: " << escapeFilePath(var("TARGET")) << endl; + t << "# Makefile for building: " << escapeFilePath(var("TARGET")) << Qt::endl; t << "# Generated by qmake (" QMAKE_VERSION_STR ") (Qt " QT_VERSION_STR ")\n"; - t << "# Project: " << fileFixify(project->projectFile()) << endl; - t << "# Template: " << var("TEMPLATE") << endl; + t << "# Project: " << fileFixify(project->projectFile()) << Qt::endl; + t << "# Template: " << var("TEMPLATE") << Qt::endl; if(!project->isActiveConfig("build_pass")) - t << "# Command: " << build_args().replace(QLatin1String("$(QMAKE)"), var("QMAKE_QMAKE")) << endl; + t << "# Command: " << build_args().replace(QLatin1String("$(QMAKE)"), var("QMAKE_QMAKE")) << Qt::endl; t << "#############################################################################\n"; - t << endl; + t << Qt::endl; QString ofile = Option::fixPathToTargetOS(Option::output.fileName()); if (ofile.lastIndexOf(Option::dir_sep) != -1) ofile.remove(0, ofile.lastIndexOf(Option::dir_sep) +1); - t << "MAKEFILE = " << escapeFilePath(ofile) << endl << endl; + t << "MAKEFILE = " << escapeFilePath(ofile) << Qt::endl << Qt::endl; t << "EQ = =\n\n"; } @@ -2492,7 +2492,7 @@ MakefileGenerator::writeSubDirs(QTextStream &t) void MakefileGenerator::writeSubMakeCall(QTextStream &t, const QString &callPrefix, const QString &makeArguments) { - t << callPrefix << "$(MAKE)" << makeArguments << endl; + t << callPrefix << "$(MAKE)" << makeArguments << Qt::endl; } void @@ -2517,14 +2517,14 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QListvalues("QMAKE_EXTRA_INCLUDES"); for (ProStringList::ConstIterator qeui_it = qeui.begin(); qeui_it != qeui.end(); ++qeui_it) - t << "include " << (*qeui_it) << endl; + t << "include " << (*qeui_it) << Qt::endl; if (!(flags & SubTargetSkipDefaultVariables)) { writeDefaultVariables(t); t << "SUBTARGETS = "; // subtargets are sub-directory for(int target = 0; target < targets.size(); ++target) t << " \\\n\t\t" << targets.at(target)->target; - t << endl << endl; + t << Qt::endl << Qt::endl; } writeExtraVariables(t); @@ -2580,7 +2580,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QListvalues(ProKey(*qut_it + ".depends")); for (ProStringList::ConstIterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) { @@ -2758,7 +2758,7 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QListisEmpty("QMAKE_FAILED_REQUIREMENTS") && !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) { QStringList files = escapeFilePaths(fileFixify(Option::mkfile::project_files)); t << escapeDependencyPath(project->first("QMAKE_INTERNAL_PRL_FILE").toQString()) << ": \n\t" - << "@$(QMAKE) -prl " << files.join(' ') << ' ' << buildArgs(true) << endl; + << "@$(QMAKE) -prl " << files.join(' ') << ' ' << buildArgs(true) << Qt::endl; } QString qmake = build_args(); @@ -2795,10 +2795,10 @@ MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll) } const ProStringList &included = escapeDependencyPaths(project->values("QMAKE_INTERNAL_INCLUDED_FILES")); t << included.join(QString(" \\\n\t\t")) << "\n\t" - << qmake << endl; + << qmake << Qt::endl; const ProStringList &extraCommands = project->values("QMAKE_MAKE_QMAKE_EXTRA_COMMANDS"); if (!extraCommands.isEmpty()) - t << "\t" << extraCommands.join(QString("\n\t")) << endl; + t << "\t" << extraCommands.join(QString("\n\t")) << Qt::endl; for(int include = 0; include < included.size(); ++include) { const ProString &i = included.at(include); if(!i.isEmpty()) @@ -2806,7 +2806,7 @@ MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll) } } if(project->first("QMAKE_ORIG_TARGET") != "qmake") { - t << "qmake: FORCE\n\t@" << qmake << endl << endl; + t << "qmake: FORCE\n\t@" << qmake << Qt::endl << Qt::endl; if (!noDummyQmakeAll) t << "qmake_all: FORCE\n\n"; } @@ -3298,11 +3298,11 @@ MakefileGenerator::writePkgConfigFile() if(includeDir.isEmpty()) includeDir = prefix + "/include"; - t << "prefix=" << prefix << endl; + t << "prefix=" << prefix << Qt::endl; t << "exec_prefix=${prefix}\n" << "libdir=" << pkgConfigFixPath(libDir) << "\n" - << "includedir=" << pkgConfigFixPath(includeDir) << endl; - t << endl; + << "includedir=" << pkgConfigFixPath(includeDir) << Qt::endl; + t << Qt::endl; //extra PKGCONFIG variables const ProStringList &pkgconfig_vars = project->values("QMAKE_PKGCONFIG_VARIABLES"); @@ -3323,17 +3323,17 @@ MakefileGenerator::writePkgConfigFile() } } if (!val.isEmpty()) - t << var << "=" << val << endl; + t << var << "=" << val << Qt::endl; } - t << endl; + t << Qt::endl; QString name = project->first("QMAKE_PKGCONFIG_NAME").toQString(); if(name.isEmpty()) { name = project->first("QMAKE_ORIG_TARGET").toQString().toLower(); name.replace(0, 1, name[0].toUpper()); } - t << "Name: " << name << endl; + t << "Name: " << name << Qt::endl; QString desc = project->values("QMAKE_PKGCONFIG_DESCRIPTION").join(' '); if(desc.isEmpty()) { if(name.isEmpty()) { @@ -3351,12 +3351,12 @@ MakefileGenerator::writePkgConfigFile() desc += " Application"; } } - t << "Description: " << desc << endl; + t << "Description: " << desc << Qt::endl; ProString version = project->first("QMAKE_PKGCONFIG_VERSION"); if (version.isEmpty()) version = project->first("VERSION"); if (!version.isEmpty()) - t << "Version: " << version << endl; + t << "Version: " << version << Qt::endl; // libs t << "Libs: "; @@ -3393,7 +3393,7 @@ MakefileGenerator::writePkgConfigFile() t << "Libs.private:"; for (ProStringList::ConstIterator it = libs.cbegin(); it != libs.cend(); ++it) t << ' ' << fixLibFlags((*it).toKey()).join(' '); - t << endl; + t << Qt::endl; } // flags @@ -3411,15 +3411,15 @@ MakefileGenerator::writePkgConfigFile() && libDir != QLatin1String("/Library/Frameworks")) { t << " -F${libdir}"; } - t << endl; + t << Qt::endl; // requires const QString requires = project->values("QMAKE_PKGCONFIG_REQUIRES").join(' '); if (!requires.isEmpty()) { - t << "Requires: " << requires << endl; + t << "Requires: " << requires << Qt::endl; } - t << endl; + t << Qt::endl; } static QString windowsifyPath(const QString &str) diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp index ef34955eb1..f729ec89ef 100644 --- a/qmake/generators/projectgenerator.cpp +++ b/qmake/generators/projectgenerator.cpp @@ -324,14 +324,14 @@ ProjectGenerator::init() bool ProjectGenerator::writeMakefile(QTextStream &t) { - t << "######################################################################" << endl; - t << "# Automatically generated by qmake (" QMAKE_VERSION_STR ") " << QDateTime::currentDateTime().toString() << endl; - t << "######################################################################" << endl << endl; + t << "######################################################################" << Qt::endl; + t << "# Automatically generated by qmake (" QMAKE_VERSION_STR ") " << QDateTime::currentDateTime().toString() << Qt::endl; + t << "######################################################################" << Qt::endl << Qt::endl; if (!Option::globals->extra_cmds[QMakeEvalBefore].isEmpty()) - t << Option::globals->extra_cmds[QMakeEvalBefore] << endl; + t << Option::globals->extra_cmds[QMakeEvalBefore] << Qt::endl; t << getWritableVar("TEMPLATE_ASSIGN", false); if(project->first("TEMPLATE_ASSIGN") == "subdirs") { - t << endl << "# Directories" << "\n" + t << Qt::endl << "# Directories" << "\n" << getWritableVar("SUBDIRS"); } else { //figure out target @@ -343,7 +343,7 @@ ProjectGenerator::writeMakefile(QTextStream &t) t << getWritableVar("TARGET_ASSIGN") << getWritableVar("CONFIG", false) << getWritableVar("CONFIG_REMOVE", false) - << getWritableVar("INCLUDEPATH") << endl; + << getWritableVar("INCLUDEPATH") << Qt::endl; t << "# You can make your code fail to compile if you use deprecated APIs.\n" "# In order to do so, uncomment the following line.\n" @@ -362,7 +362,7 @@ ProjectGenerator::writeMakefile(QTextStream &t) << getWritableVar("TRANSLATIONS"); } if (!Option::globals->extra_cmds[QMakeEvalAfter].isEmpty()) - t << Option::globals->extra_cmds[QMakeEvalAfter] << endl; + t << Option::globals->extra_cmds[QMakeEvalAfter] << Qt::endl; return true; } diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 7d8c70ec3b..a384439aac 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -83,8 +83,8 @@ void UnixMakefileGenerator::writeDefaultVariables(QTextStream &t) { MakefileGenerator::writeDefaultVariables(t); - t << "TAR = " << var("QMAKE_TAR") << endl; - t << "COMPRESS = " << var("QMAKE_GZIP") << endl; + t << "TAR = " << var("QMAKE_TAR") << Qt::endl; + t << "COMPRESS = " << var("QMAKE_GZIP") << Qt::endl; if (project->isEmpty("QMAKE_DISTNAME")) { ProString distname = project->first("QMAKE_ORIG_TARGET"); @@ -92,13 +92,13 @@ UnixMakefileGenerator::writeDefaultVariables(QTextStream &t) distname += project->first("VERSION"); project->values("QMAKE_DISTNAME") = distname; } - t << "DISTNAME = " << fileVar("QMAKE_DISTNAME") << endl; + t << "DISTNAME = " << fileVar("QMAKE_DISTNAME") << Qt::endl; if (project->isEmpty("QMAKE_DISTDIR")) project->values("QMAKE_DISTDIR") = project->first("QMAKE_DISTNAME"); t << "DISTDIR = " << escapeFilePath(fileFixify( (project->isEmpty("OBJECTS_DIR") ? ProString(".tmp/") : project->first("OBJECTS_DIR")) + project->first("QMAKE_DISTDIR"), - FileFixifyFromOutdir | FileFixifyAbsolute)) << endl; + FileFixifyFromOutdir | FileFixifyAbsolute)) << Qt::endl; } void @@ -106,10 +106,10 @@ UnixMakefileGenerator::writeSubTargets(QTextStream &t, QListfirst("QMAKE_ABSOLUTE_SOURCE_PATH").toQString(); for (int target = 0; target < targets.size(); ++target) { @@ -151,7 +151,7 @@ UnixMakefileGenerator::writeSubTargets(QTextStream &t, QListtarget << "-distdir: FORCE"; writeSubTargetCall(t, in_directory, in, out_directory, escapeFilePath(out), out_directory_cdin, makefilein); - t << endl; + t << Qt::endl; } } @@ -183,11 +183,11 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) writeExportedVariables(t); t << "####### Compiler, tools and options\n\n"; - t << "CC = " << var("QMAKE_CC") << endl; - t << "CXX = " << var("QMAKE_CXX") << endl; + t << "CC = " << var("QMAKE_CC") << Qt::endl; + t << "CXX = " << var("QMAKE_CXX") << Qt::endl; t << "DEFINES = " << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ") - << varGlue("DEFINES","-D"," -D","") << endl; + << varGlue("DEFINES","-D"," -D","") << Qt::endl; t << "CFLAGS = " << var("QMAKE_CFLAGS") << " $(DEFINES)\n"; t << "CXXFLAGS = " << var("QMAKE_CXXFLAGS") << " $(DEFINES)\n"; t << "INCPATH ="; @@ -208,38 +208,38 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) } if(!project->isEmpty("QMAKE_FRAMEWORKPATH_FLAGS")) t << " " << var("QMAKE_FRAMEWORKPATH_FLAGS"); - t << endl; + t << Qt::endl; writeDefaultVariables(t); if(!project->isActiveConfig("staticlib")) { - t << "LINK = " << var("QMAKE_LINK") << endl; - t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl; + t << "LINK = " << var("QMAKE_LINK") << Qt::endl; + t << "LFLAGS = " << var("QMAKE_LFLAGS") << Qt::endl; t << "LIBS = $(SUBLIBS) " << fixLibFlags("LIBS").join(' ') << ' ' << fixLibFlags("LIBS_PRIVATE").join(' ') << ' ' << fixLibFlags("QMAKE_LIBS").join(' ') << ' ' - << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl; + << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << Qt::endl; } - t << "AR = " << var("QMAKE_AR") << endl; - t << "RANLIB = " << var("QMAKE_RANLIB") << endl; - t << "SED = " << var("QMAKE_STREAM_EDITOR") << endl; - t << "STRIP = " << var("QMAKE_STRIP") << endl; + t << "AR = " << var("QMAKE_AR") << Qt::endl; + t << "RANLIB = " << var("QMAKE_RANLIB") << Qt::endl; + t << "SED = " << var("QMAKE_STREAM_EDITOR") << Qt::endl; + t << "STRIP = " << var("QMAKE_STRIP") << Qt::endl; - t << endl; + t << Qt::endl; t << "####### Output directory\n\n"; // This is used in commands by some .prf files. if (! project->values("OBJECTS_DIR").isEmpty()) - t << "OBJECTS_DIR = " << fileVar("OBJECTS_DIR") << endl; + t << "OBJECTS_DIR = " << fileVar("OBJECTS_DIR") << Qt::endl; else t << "OBJECTS_DIR = ./\n"; - t << endl; + t << Qt::endl; /* files */ t << "####### Files\n\n"; // This is used by the dist target. - t << "SOURCES = " << fileVarList("SOURCES") << ' ' << fileVarList("GENERATED_SOURCES") << endl; + t << "SOURCES = " << fileVarList("SOURCES") << ' ' << fileVarList("GENERATED_SOURCES") << Qt::endl; if(do_incremental) { const ProStringList &objs = project->values("OBJECTS"); const ProStringList &incrs = project->values("QMAKE_INCREMENTAL"); @@ -259,59 +259,59 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "\\\n\t\t" << (*objit); } if(incrs_out.count() == objs.count()) { //we just switched places, no real incrementals to be done! - t << escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << endl; + t << escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << Qt::endl; } else if(!incrs_out.count()) { - t << endl; + t << Qt::endl; } else { src_incremental = true; - t << endl; + t << Qt::endl; t << "INCREMENTAL_OBJECTS = " - << escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << endl; + << escapeFilePaths(incrs_out).join(QString(" \\\n\t\t")) << Qt::endl; } } else { // Used all over the place in both deps and commands. - t << "OBJECTS = " << valList(escapeDependencyPaths(project->values("OBJECTS"))) << endl; + t << "OBJECTS = " << valList(escapeDependencyPaths(project->values("OBJECTS"))) << Qt::endl; } if(do_incremental && !src_incremental) do_incremental = false; t << "DIST = " << valList(fileFixify(project->values("DISTFILES").toQStringList())) << " " - << fileVarList("HEADERS") << ' ' << fileVarList("SOURCES") << endl; - t << "QMAKE_TARGET = " << fileVar("QMAKE_ORIG_TARGET") << endl; + << fileVarList("HEADERS") << ' ' << fileVarList("SOURCES") << Qt::endl; + t << "QMAKE_TARGET = " << fileVar("QMAKE_ORIG_TARGET") << Qt::endl; QString destd = fileVar("DESTDIR"); // When building on non-MSys MinGW, the path ends with a backslash, which // GNU make will interpret that as a line continuation. Doubling the backslash // avoids the problem, at the cost of the variable containing *both* backslashes. if (destd.endsWith('\\')) destd += '\\'; - t << "DESTDIR = " << destd << endl; - t << "TARGET = " << fileVar("TARGET") << endl; + t << "DESTDIR = " << destd << Qt::endl; + t << "TARGET = " << fileVar("TARGET") << Qt::endl; if(project->isActiveConfig("plugin")) { - t << "TARGETD = " << fileVar("TARGET") << endl; + t << "TARGETD = " << fileVar("TARGET") << Qt::endl; } else if(!project->isActiveConfig("staticlib") && project->values("QMAKE_APP_FLAG").isEmpty()) { - t << "TARGETA = " << fileVar("TARGETA") << endl; + t << "TARGETA = " << fileVar("TARGETA") << Qt::endl; if(!project->isEmpty("QMAKE_BUNDLE")) { - t << "TARGETD = " << fileVar("TARGET_x.y") << endl; - t << "TARGET0 = " << fileVar("TARGET_") << endl; + t << "TARGETD = " << fileVar("TARGET_x.y") << Qt::endl; + t << "TARGET0 = " << fileVar("TARGET_") << Qt::endl; } else if (!project->isActiveConfig("unversioned_libname")) { - t << "TARGET0 = " << fileVar("TARGET_") << endl; + t << "TARGET0 = " << fileVar("TARGET_") << Qt::endl; if (project->isEmpty("QMAKE_HPUX_SHLIB")) { - t << "TARGETD = " << fileVar("TARGET_x.y.z") << endl; - t << "TARGET1 = " << fileVar("TARGET_x") << endl; - t << "TARGET2 = " << fileVar("TARGET_x.y") << endl; + t << "TARGETD = " << fileVar("TARGET_x.y.z") << Qt::endl; + t << "TARGET1 = " << fileVar("TARGET_x") << Qt::endl; + t << "TARGET2 = " << fileVar("TARGET_x.y") << Qt::endl; } else { - t << "TARGETD = " << fileVar("TARGET_x") << endl; + t << "TARGETD = " << fileVar("TARGET_x") << Qt::endl; } } } writeExtraCompilerVariables(t); writeExtraVariables(t); - t << endl; + t << Qt::endl; // blasted includes const ProStringList &qeui = project->values("QMAKE_EXTRA_INCLUDES"); ProStringList::ConstIterator it; for(it = qeui.begin(); it != qeui.end(); ++it) - t << "include " << escapeDependencyPath(*it) << endl; + t << "include " << escapeDependencyPath(*it) << Qt::endl; /* rules */ t << "first:" << (!project->isActiveConfig("no_default_goal_deps") ? " all" : "") << "\n"; @@ -321,7 +321,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) ProStringList objects = project->values("OBJECTS"); for (ProStringList::Iterator it = objects.begin(); it != objects.end(); ++it) { QString d_file = (*it).toQString().replace(QRegExp(Option::obj_ext + "$"), ".d"); - t << "-include " << escapeDependencyPath(d_file) << endl; + t << "-include " << escapeDependencyPath(d_file) << Qt::endl; project->values("QMAKE_DISTCLEAN") << d_file; } } else { @@ -379,8 +379,8 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) QStringList deps = findDependencies((*it).toQString()).filter(QRegExp( "((^|/)" + Option::h_moc_mod + "|" + Option::cpp_moc_ext + "$)")); if(!deps.isEmpty()) - t << d_file_d << ": " << finalizeDependencyPaths(deps).join(' ') << endl; - t << "-include " << d_file_d << endl; + t << d_file_d << ": " << finalizeDependencyPaths(deps).join(' ') << Qt::endl; + t << "-include " << d_file_d << Qt::endl; project->values("QMAKE_DISTCLEAN") += d_file; } } @@ -399,7 +399,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) for (ProStringList::ConstIterator it = l.begin(); it != l.end(); ++it) t << escapeFilePath(libdir + project->first("QMAKE_PREFIX_STATICLIB") + (*it) + '.' + project->first("QMAKE_EXTENSION_STATICLIB")) << ' '; - t << endl << endl; + t << Qt::endl << Qt::endl; } QString target_deps; if ((project->isActiveConfig("depend_prl") || project->isActiveConfig("fast_depend_prl")) @@ -504,7 +504,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "$(LINK) $(LFLAGS) " << var("QMAKE_LINK_O_FLAG") << "$(TARGET) " << incr_deps << " " << incr_objs << " $(OBJCOMP) $(LIBS)"; if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); - t << endl << endl; + t << Qt::endl << Qt::endl; } else { t << depVar("TARGET") << ": " << depVar("PRE_TARGETDEPS") << " $(OBJECTS) " << target_deps << ' ' << depVar("POST_TARGETDEPS") << "\n\t"; @@ -517,7 +517,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if (!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); } - t << endl << endl; + t << Qt::endl << Qt::endl; } allDeps = ' ' + depVar("TARGET"); } else if(!project->isActiveConfig("staticlib")) { @@ -548,7 +548,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) //actual target const QString link_deps = "$(OBJECTS) "; t << incr_target_dir_d << ": " << link_deps << "\n\t" - << "ld -r -o " << incr_target_dir_f << ' ' << link_deps << endl; + << "ld -r -o " << incr_target_dir_f << ' ' << link_deps << Qt::endl; //communicated below ProStringList &cmd = project->values("QMAKE_LINK_SHLIB_CMD"); cmd[0] = cmd.at(0).toQString().replace(QLatin1String("$(OBJECTS) "), QLatin1String("$(INCREMENTAL_OBJECTS)")); //ick @@ -606,7 +606,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << "-$(MOVE) $(TARGET) " << destdir << "$(TARGET)"; if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); - t << endl << endl; + t << Qt::endl << Qt::endl; } else if(!project->isEmpty("QMAKE_BUNDLE")) { bundledFiles << destdir_r + var("TARGET"); t << "\n\t" @@ -620,7 +620,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) " Versions/Current/$(TARGET) $(DESTDIR)$(TARGET0)") << "\n\t"; if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); - t << endl << endl; + t << Qt::endl << Qt::endl; } else if(project->isEmpty("QMAKE_HPUX_SHLIB")) { t << "\n\t"; @@ -654,7 +654,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) } if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); - t << endl << endl; + t << Qt::endl << Qt::endl; } else { t << "\n\t" << "-$(DEL_FILE) $(TARGET) $(TARGET0)\n\t" @@ -668,9 +668,9 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << "-$(MOVE) $(TARGET0) " << destdir << "$(TARGET0)\n\t"; if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); - t << endl << endl; + t << Qt::endl << Qt::endl; } - t << endl << endl; + t << Qt::endl << Qt::endl; if (! project->isActiveConfig("plugin")) { t << "staticlib: " << depVar("TARGETA") << "\n\n"; @@ -688,7 +688,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "\n\t" << var("QMAKE_POST_LINK"); if(!project->isEmpty("QMAKE_RANLIB")) t << "\n\t$(RANLIB) $(TARGETA)"; - t << endl << endl; + t << Qt::endl << Qt::endl; } } else { QString destdir_r = project->first("DESTDIR").toQString(); @@ -708,7 +708,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "\t" << var("QMAKE_POST_LINK") << "\n"; if (!project->isEmpty("QMAKE_RANLIB")) t << "\t$(RANLIB) " << destdir << "$(TARGET)\n"; - t << endl << endl; + t << Qt::endl << Qt::endl; } writeMakeQmake(t); @@ -722,7 +722,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) } if(!meta_files.isEmpty()) t << escapeDependencyPaths(meta_files).join(" ") << ": \n\t" - << "@$(QMAKE) -prl " << escapeFilePath(project->projectFile()) << ' ' << buildArgs(true) << endl; + << "@$(QMAKE) -prl " << escapeFilePath(project->projectFile()) << ' ' << buildArgs(true) << Qt::endl; } if (!project->isEmpty("QMAKE_BUNDLE")) { @@ -743,7 +743,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << "@echo \"APPL" << (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) - << "\" > " << pkginfo_f << endl; + << "\" > " << pkginfo_f << Qt::endl; } if (!project->first("QMAKE_BUNDLE_RESOURCE_FILE").isEmpty()) { ProString resources = project->first("QMAKE_BUNDLE_RESOURCE_FILE"); @@ -852,7 +852,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << "-e \"s,\\$${EXECUTABLE_NAME}," << (app_bundle_name.isEmpty() ? app_bundle_name : plugin_bundle_name) << ",g\" " << "-e \"s,@TYPEINFO@,"<< typeInfo << ",g\" " << "-e \"s,\\$${QMAKE_PKGINFO_TYPEINFO},"<< typeInfo << ",g\" " - << "" << info_plist << " >" << info_plist_out << endl; + << "" << info_plist << " >" << info_plist_out << Qt::endl; //copy the icon if (!project->isEmpty("ICON")) { QString dir = bundle_dir + "Contents/Resources/"; @@ -863,7 +863,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << escapeDependencyPath(icon_path) << ": " << escapeDependencyPath(icon) << "\n\t" << mkdir_p_asstring(dir) << "\n\t" << "@$(DEL_FILE) " << icon_path_f << "\n\t" - << "@$(COPY_FILE) " << escapeFilePath(icon) << ' ' << icon_path_f << endl; + << "@$(COPY_FILE) " << escapeFilePath(icon) << ' ' << icon_path_f << Qt::endl; } } else { ProString lib_bundle_name = var("QMAKE_FRAMEWORK_BUNDLE_NAME"); @@ -880,7 +880,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << "-e \"s,\\$${EXECUTABLE_NAME}," << lib_bundle_name << ",g\" " << "-e \"s,@TYPEINFO@," << typeInfo << ",g\" " << "-e \"s,\\$${QMAKE_PKGINFO_TYPEINFO}," << typeInfo << ",g\" " - << "" << info_plist << " >" << info_plist_out << endl; + << "" << info_plist << " >" << info_plist_out << Qt::endl; } break; } // project->isActiveConfig("no_plist") @@ -924,10 +924,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) QFileInfo fi(fileInfo(fn)); if(fi.isDir()) t << "@$(DEL_FILE) -r " << dst << "\n\t" - << "@$(COPY_DIR) " << src << " " << dst << endl; + << "@$(COPY_DIR) " << src << " " << dst << Qt::endl; else t << "@$(DEL_FILE) " << dst << "\n\t" - << "@$(COPY_FILE) " << src << " " << dst << endl; + << "@$(COPY_FILE) " << src << " " << dst << Qt::endl; } } } @@ -940,7 +940,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) alldeps << symIt.key(); t << escapeDependencyPath(symIt.key()) << ":\n\t" << mkdir_p_asstring(bundle_dir) << "\n\t" - << "@$(SYMLINK) " << escapeFilePath(symIt.value()) << ' ' << bundle_dir_f << endl; + << "@$(SYMLINK) " << escapeFilePath(symIt.value()) << ' ' << bundle_dir_f << Qt::endl; } if (!project->isActiveConfig("shallow_bundle")) { @@ -952,24 +952,24 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << mkdir_p_asstring(bundle_dir + "Versions") << "\n\t" << "@-$(DEL_FILE) " << currentLink_f << "\n\t" << "@$(SYMLINK) " << project->first("QMAKE_FRAMEWORK_VERSION") - << ' ' << currentLink_f << endl; + << ' ' << currentLink_f << Qt::endl; } } } - t << endl << "all: " << deps + t << Qt::endl << "all: " << deps << valGlue(escapeDependencyPaths(project->values("ALL_DEPS")), " \\\n\t\t", " \\\n\t\t", "") - << allDeps << endl << endl; + << allDeps << Qt::endl << Qt::endl; t << "dist: distdir FORCE\n\t"; t << "(cd `dirname $(DISTDIR)` && $(TAR) $(DISTNAME).tar $(DISTNAME) && $(COMPRESS) $(DISTNAME).tar)" " && $(MOVE) `dirname $(DISTDIR)`" << Option::dir_sep << "$(DISTNAME).tar.gz ." " && $(DEL_FILE) -r $(DISTDIR)"; - t << endl << endl; + t << Qt::endl << Qt::endl; t << "distdir: FORCE\n\t" << mkdir_p_asstring("$(DISTDIR)", false) << "\n\t" - << "$(COPY_FILE) --parents $(DIST) $(DISTDIR)" << Option::dir_sep << endl; + << "$(COPY_FILE) --parents $(DIST) $(DISTDIR)" << Option::dir_sep << Qt::endl; if(!project->isEmpty("QMAKE_EXTRA_COMPILERS")) { const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS"); for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) { @@ -979,20 +979,20 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) if(val.isEmpty()) continue; t << "\t$(COPY_FILE) --parents " << escapeFilePaths(val).join(' ') - << " $(DISTDIR)" << Option::dir_sep << endl; + << " $(DISTDIR)" << Option::dir_sep << Qt::endl; } } } if(!project->isEmpty("TRANSLATIONS")) - t << "\t$(COPY_FILE) --parents " << fileVar("TRANSLATIONS") << " $(DISTDIR)" << Option::dir_sep << endl; - t << endl << endl; + t << "\t$(COPY_FILE) --parents " << fileVar("TRANSLATIONS") << " $(DISTDIR)" << Option::dir_sep << Qt::endl; + t << Qt::endl << Qt::endl; QString clean_targets = " compiler_clean " + depVar("CLEAN_DEPS"); if(do_incremental) { t << "incrclean:\n"; if(src_incremental) t << "\t-$(DEL_FILE) $(INCREMENTAL_OBJECTS)\n"; - t << endl; + t << Qt::endl; } t << "clean:" << clean_targets << "\n\t"; @@ -1060,7 +1060,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "-$(DEL_FILE) $(INCREMENTAL_OBJECTS)\n\t"; t << fileVarGlue("QMAKE_CLEAN","-$(DEL_FILE) "," ","\n\t") << "-$(DEL_FILE) *~ core *.core\n" - << fileVarGlue("CLEAN_FILES","\t-$(DEL_FILE) "," ","") << endl << endl; + << fileVarGlue("CLEAN_FILES","\t-$(DEL_FILE) "," ","") << Qt::endl << Qt::endl; ProString destdir = project->first("DESTDIR"); if (!destdir.isEmpty() && !destdir.endsWith(Option::dir_sep)) @@ -1068,7 +1068,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) t << "distclean: clean " << depVar("DISTCLEAN_DEPS") << '\n'; if(!project->isEmpty("QMAKE_BUNDLE")) { QString bundlePath = escapeFilePath(destdir + project->first("QMAKE_BUNDLE")); - t << "\t-$(DEL_FILE) -r " << bundlePath << endl; + t << "\t-$(DEL_FILE) -r " << bundlePath << Qt::endl; } else if (project->isActiveConfig("staticlib") || project->isActiveConfig("plugin")) { t << "\t-$(DEL_FILE) " << escapeFilePath(destdir) << "$(TARGET) \n"; } else if (project->values("QMAKE_APP_FLAG").isEmpty()) { @@ -1087,9 +1087,9 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) { QString ofile = fileFixify(Option::output.fileName()); if(!ofile.isEmpty()) - t << "\t-$(DEL_FILE) " << escapeFilePath(ofile) << endl; + t << "\t-$(DEL_FILE) " << escapeFilePath(ofile) << Qt::endl; } - t << endl << endl; + t << Qt::endl << Qt::endl; t << "####### Sub-libraries\n\n"; if (!project->values("SUBLIBS").isEmpty()) { @@ -1100,7 +1100,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) for (it = l.begin(); it != l.end(); ++it) t << escapeDependencyPath(libdir + project->first("QMAKE_PREFIX_STATICLIB") + (*it) + '.' + project->first("QMAKE_EXTENSION_STATICLIB")) << ":\n\t" - << var(ProKey("MAKELIB" + *it)) << endl << endl; + << var(ProKey("MAKELIB" + *it)) << Qt::endl << Qt::endl; } if(doPrecompiledHeaders() && !project->isEmpty("PRECOMPILED_HEADER")) { @@ -1184,7 +1184,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) compilerExecutable = "$(CXX)"; // compile command - t << "\n\t" << compilerExecutable << cflags << " $(INCPATH) " << pchArchFlags << endl << endl; + t << "\n\t" << compilerExecutable << cflags << " $(INCPATH) " << pchArchFlags << Qt::endl << Qt::endl; } } } diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index de7363e51b..eb771a695a 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -99,7 +99,7 @@ bool MingwMakefileGenerator::writeMakefile(QTextStream &t) writePkgConfigFile(); if(Option::mkfile::do_stub_makefile) { - t << "QMAKE = " << var("QMAKE_QMAKE") << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl; const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS"); for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) t << escapeDependencyPath(*it) << ' '; @@ -148,7 +148,7 @@ void createLdResponseFile(const QString &fileName, const ProStringList &objList) .replace(QLatin1Char('\t'), QLatin1String("\\\t")) .replace(QLatin1Char('"'), QLatin1String("\\\"")) .replace(QLatin1Char('\''), QLatin1String("\\'")); - t << path << endl; + t << path << Qt::endl; } t.flush(); file.close(); @@ -162,9 +162,9 @@ void createArObjectScriptFile(const QString &fileName, const QString &target, co if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream t(&file); // ### quoting? - t << "CREATE " << target << endl; + t << "CREATE " << target << Qt::endl; for (ProStringList::ConstIterator it = objList.constBegin(); it != objList.constEnd(); ++it) { - t << "ADDMOD " << *it << endl; + t << "ADDMOD " << *it << Qt::endl; } t << "SAVE\n"; t.flush(); @@ -183,13 +183,13 @@ void MingwMakefileGenerator::writeMingwParts(QTextStream &t) << finalizeDependencyPaths(findDependencies(header)).join(" \\\n\t\t") << "\n\t" << mkdir_p_asstring(preCompHeaderOut) << "\n\t$(CC) -x c-header -c $(CFLAGS) $(INCPATH) -o " << escapeFilePath(cHeader) - << ' ' << escapeFilePath(header) << endl << endl; + << ' ' << escapeFilePath(header) << Qt::endl << Qt::endl; QString cppHeader = preCompHeaderOut + Option::dir_sep + "c++"; t << escapeDependencyPath(cppHeader) << ": " << escapeDependencyPath(header) << " " << finalizeDependencyPaths(findDependencies(header)).join(" \\\n\t\t") << "\n\t" << mkdir_p_asstring(preCompHeaderOut) << "\n\t$(CXX) -x c++-header -c $(CXXFLAGS) $(INCPATH) -o " << escapeFilePath(cppHeader) - << ' ' << escapeFilePath(header) << endl << endl; + << ' ' << escapeFilePath(header) << Qt::endl << Qt::endl; } } @@ -274,21 +274,21 @@ void MingwMakefileGenerator::writeIncPart(QTextStream &t) t << "-I"; t << escapeFilePath(inc) << ' '; } - t << endl; + t << Qt::endl; } void MingwMakefileGenerator::writeLibsPart(QTextStream &t) { if(project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") { - t << "LIB = " << var("QMAKE_LIB") << endl; + t << "LIB = " << var("QMAKE_LIB") << Qt::endl; } else { - t << "LINKER = " << var("QMAKE_LINK") << endl; - t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl; + t << "LINKER = " << var("QMAKE_LINK") << Qt::endl; + t << "LFLAGS = " << var("QMAKE_LFLAGS") << Qt::endl; t << "LIBS = " << fixLibFlags("LIBS").join(' ') << ' ' << fixLibFlags("LIBS_PRIVATE").join(' ') << ' ' << fixLibFlags("QMAKE_LIBS").join(' ') << ' ' - << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl; + << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << Qt::endl; } } @@ -350,7 +350,7 @@ void MingwMakefileGenerator::writeBuildRulesPart(QTextStream &t) } if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" <isActiveConfig("no_batch"); QSet source_directories; @@ -393,9 +393,9 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t) } } else { for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) - t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl; + t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << Qt::endl << Qt::endl; for(QStringList::Iterator cit = Option::c_ext.begin(); cit != Option::c_ext.end(); ++cit) - t << (*cit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl; + t << (*cit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << Qt::endl << Qt::endl; } } @@ -498,7 +498,7 @@ void NmakeMakefileGenerator::writeBuildRulesPart(QTextStream &t) if(!project->isEmpty("QMAKE_POST_LINK")) { t << "\n\t" << var("QMAKE_POST_LINK"); } - t << endl; + t << Qt::endl; } void NmakeMakefileGenerator::writeLinkCommand(QTextStream &t, const QString &extraFlags, const QString &extraInlineFileContent) diff --git a/qmake/generators/win32/msvc_objectmodel.h b/qmake/generators/win32/msvc_objectmodel.h index b356f1bb73..33eff0d914 100644 --- a/qmake/generators/win32/msvc_objectmodel.h +++ b/qmake/generators/win32/msvc_objectmodel.h @@ -923,7 +923,7 @@ struct VCFilterFile inline QDebug operator<<(QDebug dbg, const VCFilterFile &p) { dbg.nospace() << "VCFilterFile(file(" << p.file - << ") excludeFromBuild(" << p.excludeFromBuild << "))" << endl; + << ") excludeFromBuild(" << p.excludeFromBuild << "))" << Qt::endl; return dbg.space(); } #endif diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index 16f9361d13..8ee86ac395 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -320,11 +320,11 @@ void Win32MakefileGenerator::processRcFileVar() int rcCodePage = project->intValue("RC_CODEPAGE", 1200); // default: Unicode ts << "#include \n"; - ts << endl; + ts << Qt::endl; if (!rcIcons.isEmpty()) { for (int i = 0; i < rcIcons.size(); ++i) - ts << QString("IDI_ICON%1\tICON\tDISCARDABLE\t%2").arg(i + 1).arg(cQuoted(rcIcons[i])) << endl; - ts << endl; + ts << QString("IDI_ICON%1\tICON\tDISCARDABLE\t%2").arg(i + 1).arg(cQuoted(rcIcons[i])) << Qt::endl; + ts << Qt::endl; } if (!manifestFile.isEmpty()) { QString manifestResourceId; @@ -335,8 +335,8 @@ void Win32MakefileGenerator::processRcFileVar() ts << manifestResourceId << " RT_MANIFEST \"" << manifestFile << "\"\n"; } ts << "VS_VERSION_INFO VERSIONINFO\n"; - ts << "\tFILEVERSION " << QString(versionString).replace(".", ",") << endl; - ts << "\tPRODUCTVERSION " << QString(versionString).replace(".", ",") << endl; + ts << "\tFILEVERSION " << QString(versionString).replace(".", ",") << Qt::endl; + ts << "\tPRODUCTVERSION " << QString(versionString).replace(".", ",") << Qt::endl; ts << "\tFILEFLAGSMASK 0x3fL\n"; ts << "#ifdef _DEBUG\n"; ts << "\tFILEFLAGS VS_FF_DEBUG\n"; @@ -369,11 +369,11 @@ void Win32MakefileGenerator::processRcFileVar() ts << "\t\tBEGIN\n"; ts << "\t\t\tVALUE \"Translation\", " << QString("0x%1").arg(rcLang, 4, 16, QLatin1Char('0')) - << ", " << QString("%1").arg(rcCodePage, 4) << endl; + << ", " << QString("%1").arg(rcCodePage, 4) << Qt::endl; ts << "\t\tEND\n"; ts << "\tEND\n"; ts << "/* End of Version info */\n"; - ts << endl; + ts << Qt::endl; ts.flush(); @@ -470,7 +470,7 @@ void Win32MakefileGenerator::writeCleanParts(QTextStream &t) } } } - t << endl << endl; + t << Qt::endl << Qt::endl; t << "distclean: clean " << depVar("DISTCLEAN_DEPS"); { @@ -503,9 +503,9 @@ void Win32MakefileGenerator::writeCleanParts(QTextStream &t) { QString ofile = fileFixify(Option::output.fileName()); if(!ofile.isEmpty()) - t << "\t-$(DEL_FILE) " << escapeFilePath(ofile) << endl; + t << "\t-$(DEL_FILE) " << escapeFilePath(ofile) << Qt::endl; } - t << endl; + t << Qt::endl; } void Win32MakefileGenerator::writeIncPart(QTextStream &t) @@ -519,7 +519,7 @@ void Win32MakefileGenerator::writeIncPart(QTextStream &t) if(!inc.isEmpty()) t << "-I" << escapeFilePath(inc) << ' '; } - t << endl; + t << Qt::endl; } void Win32MakefileGenerator::writeStandardParts(QTextStream &t) @@ -527,51 +527,51 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) writeExportedVariables(t); t << "####### Compiler, tools and options\n\n"; - t << "CC = " << var("QMAKE_CC") << endl; - t << "CXX = " << var("QMAKE_CXX") << endl; + t << "CC = " << var("QMAKE_CC") << Qt::endl; + t << "CXX = " << var("QMAKE_CXX") << Qt::endl; t << "DEFINES = " << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ") - << varGlue("DEFINES","-D"," -D","") << endl; + << varGlue("DEFINES","-D"," -D","") << Qt::endl; t << "CFLAGS = " << var("QMAKE_CFLAGS") << " $(DEFINES)\n"; t << "CXXFLAGS = " << var("QMAKE_CXXFLAGS") << " $(DEFINES)\n"; writeIncPart(t); writeLibsPart(t); - t << "QMAKE = " << var("QMAKE_QMAKE") << endl; + t << "QMAKE = " << var("QMAKE_QMAKE") << Qt::endl; t << "IDC = " << (project->isEmpty("QMAKE_IDC") ? QString("idc") : var("QMAKE_IDC")) - << endl; + << Qt::endl; t << "IDL = " << (project->isEmpty("QMAKE_IDL") ? QString("midl") : var("QMAKE_IDL")) - << endl; - t << "ZIP = " << var("QMAKE_ZIP") << endl; - t << "DEF_FILE = " << fileVar("DEF_FILE") << endl; - t << "RES_FILE = " << fileVar("RES_FILE") << endl; // Not on mingw, can't see why not though... - t << "COPY = " << var("QMAKE_COPY") << endl; - t << "SED = " << var("QMAKE_STREAM_EDITOR") << endl; - t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << endl; - t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl; - t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; - t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; - t << "MOVE = " << var("QMAKE_MOVE") << endl; - t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << endl; - t << "MKDIR = " << var("QMAKE_MKDIR") << endl; - t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << endl; - t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << endl; - t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl; - t << "QINSTALL = " << var("QMAKE_QMAKE") << " -install qinstall" << endl; - t << "QINSTALL_PROGRAM = " << var("QMAKE_QMAKE") << " -install qinstall -exe" << endl; - t << endl; + << Qt::endl; + t << "ZIP = " << var("QMAKE_ZIP") << Qt::endl; + t << "DEF_FILE = " << fileVar("DEF_FILE") << Qt::endl; + t << "RES_FILE = " << fileVar("RES_FILE") << Qt::endl; // Not on mingw, can't see why not though... + t << "COPY = " << var("QMAKE_COPY") << Qt::endl; + t << "SED = " << var("QMAKE_STREAM_EDITOR") << Qt::endl; + t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << Qt::endl; + t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << Qt::endl; + t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << Qt::endl; + t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << Qt::endl; + t << "MOVE = " << var("QMAKE_MOVE") << Qt::endl; + t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << Qt::endl; + t << "MKDIR = " << var("QMAKE_MKDIR") << Qt::endl; + t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << Qt::endl; + t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << Qt::endl; + t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << Qt::endl; + t << "QINSTALL = " << var("QMAKE_QMAKE") << " -install qinstall" << Qt::endl; + t << "QINSTALL_PROGRAM = " << var("QMAKE_QMAKE") << " -install qinstall -exe" << Qt::endl; + t << Qt::endl; t << "####### Output directory\n\n"; if(!project->values("OBJECTS_DIR").isEmpty()) - t << "OBJECTS_DIR = " << escapeFilePath(var("OBJECTS_DIR").remove(QRegExp("\\\\$"))) << endl; + t << "OBJECTS_DIR = " << escapeFilePath(var("OBJECTS_DIR").remove(QRegExp("\\\\$"))) << Qt::endl; else t << "OBJECTS_DIR = . \n"; - t << endl; + t << Qt::endl; t << "####### Files\n\n"; t << "SOURCES = " << valList(escapeFilePaths(project->values("SOURCES"))) - << " " << valList(escapeFilePaths(project->values("GENERATED_SOURCES"))) << endl; + << " " << valList(escapeFilePaths(project->values("GENERATED_SOURCES"))) << Qt::endl; // do this here so we can set DEST_TARGET to be the complete path to the final target if it is needed. QString orgDestDir = var("DESTDIR"); @@ -587,14 +587,14 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) writeExtraVariables(t); t << "DIST = " << fileVarList("DISTFILES") << ' ' - << fileVarList("HEADERS") << ' ' << fileVarList("SOURCES") << endl; - t << "QMAKE_TARGET = " << fileVar("QMAKE_ORIG_TARGET") << endl; // unused + << fileVarList("HEADERS") << ' ' << fileVarList("SOURCES") << Qt::endl; + t << "QMAKE_TARGET = " << fileVar("QMAKE_ORIG_TARGET") << Qt::endl; // unused // The comment is important to maintain variable compatibility with Unix // Makefiles, while not interpreting a trailing-slash as a linebreak t << "DESTDIR = " << escapeFilePath(destDir) << " #avoid trailing-slash linebreak\n"; - t << "TARGET = " << escapeFilePath(target) << endl; - t << "DESTDIR_TARGET = " << fileVar("DEST_TARGET") << endl; - t << endl; + t << "TARGET = " << escapeFilePath(target) << Qt::endl; + t << "DESTDIR_TARGET = " << fileVar("DEST_TARGET") << Qt::endl; + t << Qt::endl; writeImplicitRulesPart(t); @@ -606,10 +606,10 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) const ProStringList &dlldirs = project->values("DLLDESTDIR"); for (ProStringList::ConstIterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir) { t << "\t-$(COPY_FILE) $(DESTDIR_TARGET) " - << escapeFilePath(Option::fixPathToTargetOS((*dlldir).toQString(), false)) << endl; + << escapeFilePath(Option::fixPathToTargetOS((*dlldir).toQString(), false)) << Qt::endl; } } - t << endl; + t << Qt::endl; writeRcFilePart(t); } @@ -642,33 +642,33 @@ void Win32MakefileGenerator::writeStandardParts(QTextStream &t) } } } - t << endl << endl; + t << Qt::endl << Qt::endl; writeCleanParts(t); writeExtraTargets(t); writeExtraCompilerTargets(t); - t << endl << endl; + t << Qt::endl << Qt::endl; } void Win32MakefileGenerator::writeLibsPart(QTextStream &t) { if(project->isActiveConfig("staticlib") && project->first("TEMPLATE") == "lib") { - t << "LIBAPP = " << var("QMAKE_LIB") << endl; - t << "LIBFLAGS = " << var("QMAKE_LIBFLAGS") << endl; + t << "LIBAPP = " << var("QMAKE_LIB") << Qt::endl; + t << "LIBFLAGS = " << var("QMAKE_LIBFLAGS") << Qt::endl; } else { - t << "LINKER = " << var("QMAKE_LINK") << endl; - t << "LFLAGS = " << var("QMAKE_LFLAGS") << endl; + t << "LINKER = " << var("QMAKE_LINK") << Qt::endl; + t << "LFLAGS = " << var("QMAKE_LFLAGS") << Qt::endl; t << "LIBS = " << fixLibFlags("LIBS").join(' ') << ' ' << fixLibFlags("LIBS_PRIVATE").join(' ') << ' ' << fixLibFlags("QMAKE_LIBS").join(' ') << ' ' - << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << endl; + << fixLibFlags("QMAKE_LIBS_PRIVATE").join(' ') << Qt::endl; } } void Win32MakefileGenerator::writeObjectsPart(QTextStream &t) { // Used in both deps and commands. - t << "OBJECTS = " << valList(escapeDependencyPaths(project->values("OBJECTS"))) << endl; + t << "OBJECTS = " << valList(escapeDependencyPaths(project->values("OBJECTS"))) << Qt::endl; } void Win32MakefileGenerator::writeImplicitRulesPart(QTextStream &t) @@ -710,7 +710,7 @@ void Win32MakefileGenerator::writeRcFilePart(QTextStream &t) << var("QMAKE_RC") << (project->isActiveConfig("debug") ? " -D_DEBUG" : "") << defines << incPathStr << " -fo " << escapeFilePath(res_file) << ' ' << escapeFilePath(rc_file); - t << endl << endl; + t << Qt::endl << Qt::endl; } } diff --git a/qmake/generators/xmloutput.cpp b/qmake/generators/xmloutput.cpp index e92749a126..2f48763550 100644 --- a/qmake/generators/xmloutput.cpp +++ b/qmake/generators/xmloutput.cpp @@ -237,7 +237,7 @@ void XmlOutput::newTagOpen(const QString &tag) closeOpen(); if (format == NewLine) - xmlFile << endl << currentIndent; + xmlFile << Qt::endl << currentIndent; xmlFile << '<' << doConversion(tag); currentState = Attribute; tagStack.append(tag); @@ -271,7 +271,7 @@ void XmlOutput::closeTag() case Tag: decreaseIndent(); // <--- Pre-decrease indent if (format == NewLine) - xmlFile << endl << currentIndent; + xmlFile << Qt::endl << currentIndent; xmlFile << "'; tagStack.pop_back(); break; @@ -343,7 +343,7 @@ void XmlOutput::addAttribute(const QString &attribute, const QString &value) break; } if (format == NewLine) - xmlFile << endl; + xmlFile << Qt::endl; xmlFile << currentIndent << doConversion(attribute) << "=\"" << doConversion(value) << "\""; } diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp index 704ea9774a..de3bcb2bbf 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp +++ b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp @@ -1471,7 +1471,7 @@ static bool indic_shape_syllable(HB_Bool openType, HB_ShaperItem *item, bool inv while (finalOrder[toMove].form && fixed < len-1) { IDEBUG(" fixed = %d, toMove=%d, moving form %d with pos %d", fixed, toMove, finalOrder[toMove].form, finalOrder[toMove].position); for (i = fixed; i < len; i++) { -// IDEBUG() << " i=" << i << "uc=" << hex << uc[i] << "form=" << form(uc[i]) +// IDEBUG() << " i=" << i << "uc=" << Qt::hex << uc[i] << "form=" << form(uc[i]) // << "position=" << position[i]; if (form(uc[i]) == finalOrder[toMove].form && position[i] == finalOrder[toMove].position) { diff --git a/src/3rdparty/harfbuzz/tests/shaping/main.cpp b/src/3rdparty/harfbuzz/tests/shaping/main.cpp index 10818c565c..16f469029b 100644 --- a/src/3rdparty/harfbuzz/tests/shaping/main.cpp +++ b/src/3rdparty/harfbuzz/tests/shaping/main.cpp @@ -370,7 +370,7 @@ void tst_QScriptEngine::greek() QString str; str.append(uc); if (str.normalized(QString::NormalizationForm_D).normalized(QString::NormalizationForm_C) != str) { - //qDebug() << "skipping" << hex << uc; + //qDebug() << "skipping" << Qt::hex << uc; continue; } if (uc == 0x1fc1 || uc == 0x1fed) @@ -389,7 +389,7 @@ void tst_QScriptEngine::greek() QString str; str.append(uc); if (str.normalized(QString::NormalizationForm_D).normalized(QString::NormalizationForm_C) != str) { - //qDebug() << "skipping" << hex << uc; + //qDebug() << "skipping" << Qt::hex << uc; continue; } if (uc == 0x1fc1 || uc == 0x1fed) diff --git a/src/corelib/doc/snippets/code/doc_src_qset.cpp b/src/corelib/doc/snippets/code/doc_src_qset.cpp index 4cd84d7330..7f7cec8b45 100644 --- a/src/corelib/doc/snippets/code/doc_src_qset.cpp +++ b/src/corelib/doc/snippets/code/doc_src_qset.cpp @@ -133,7 +133,7 @@ QSet set; ... QSet::iterator it = qFind(set.begin(), set.end(), "Jeanette"); if (it != set.end()) - cout << "Found Jeanette" << endl; + cout << "Found Jeanette" << Qt::endl; //! [10] @@ -152,7 +152,7 @@ QSet set; ... QSet::iterator it = qFind(set.begin(), set.end(), "Jeanette"); if (it != set.constEnd()) - cout << "Found Jeanette" << endl; + cout << "Found Jeanette" << Qt::endl; //! [12] diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp index 625c1cf9bc..c30f13df5a 100644 --- a/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_io_qtextstream.cpp @@ -124,12 +124,12 @@ in >> ch1 >> ch2 >> ch3; //! [8] QTextStream out(stdout); -out << "Qt rocks!" << endl; +out << "Qt rocks!" << Qt::endl; //! [8] //! [9] -stream << '\n' << flush; +stream << '\n' << Qt::flush; //! [9] diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp index 382b08fdb7..dfa9b670e7 100644 --- a/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_thread_qfuture.cpp @@ -53,7 +53,7 @@ QFuture future = ...; QFuture::const_iterator i; for (i = future.constBegin(); i != future.constEnd(); ++i) - cout << *i << endl; + cout << *i << Qt::endl; //! [0] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp index 32fccbefbf..ec63e64fe9 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp @@ -71,7 +71,7 @@ ba[4] = 0xca; //! [2] for (int i = 0; i < ba.size(); ++i) { if (ba.at(i) >= 'a' && ba.at(i) <= 'f') - cout << "Found character in range [a-f]" << endl; + cout << "Found character in range [a-f]" << Qt::endl; } //! [2] @@ -88,7 +88,7 @@ x.replace(5, 3, "&"); // x == "rock & roll" QByteArray ba("We must be bold, very bold"); int j = 0; while ((j = ba.indexOf("", j)) != -1) { - cout << "Found tag at index position " << j << endl; + cout << "Found tag at index position " << j << Qt::endl; ++j; } //! [4] @@ -126,7 +126,7 @@ QByteArray("abc").isEmpty(); // returns false QByteArray ba("Hello world"); char *data = ba.data(); while (*data) { - cout << "[" << *data << "]" << endl; + cout << "[" << *data << "]" << Qt::endl; ++data; } //! [8] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp index a3d2dd7f9e..9813cc98d5 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp @@ -89,7 +89,7 @@ QHash hash; ... for (int i = 0; i < 1000; ++i) { if (hash[i] == okButton) - cout << "Found button at index " << i << endl; + cout << "Found button at index " << i << Qt::endl; } //! [6] @@ -98,7 +98,7 @@ for (int i = 0; i < 1000; ++i) { QHashIterator i(hash); while (i.hasNext()) { i.next(); - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; } //! [7] @@ -106,7 +106,7 @@ while (i.hasNext()) { //! [8] QHash::const_iterator i = hash.constBegin(); while (i != hash.constEnd()) { - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; ++i; } //! [8] @@ -122,14 +122,14 @@ hash.insert("plenty", 2000); //! [10] QList values = hash.values("plenty"); for (int i = 0; i < values.size(); ++i) - cout << values.at(i) << endl; + cout << values.at(i) << Qt::endl; //! [10] //! [11] QHash::iterator i = hash.find("plenty"); while (i != hash.end() && i.key() == "plenty") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [11] @@ -139,7 +139,7 @@ while (i != hash.end() && i.key() == "plenty") { QHash hash; ... foreach (int value, hash) - cout << value << endl; + cout << value << Qt::endl; //! [12] @@ -201,7 +201,7 @@ QHash hash; ... QHash::const_iterator i = hash.find("HDR"); while (i != hash.end() && i.key() == "HDR") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [16] @@ -216,7 +216,7 @@ hash.insert("December", 12); QHash::iterator i; for (i = hash.begin(); i != hash.end(); ++i) - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; //! [17] @@ -274,7 +274,7 @@ hash.insert("December", 12); QHash::const_iterator i; for (i = hash.constBegin(); i != hash.constEnd(); ++i) - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; //! [23] @@ -296,23 +296,23 @@ hash3 = hash1 + hash2; //! [25] QList values = hash.values("plenty"); for (int i = 0; i < values.size(); ++i) - cout << values.at(i) << endl; + cout << values.at(i) << Qt::endl; //! [25] //! [26] QMultiHash::iterator i = hash.find("plenty"); while (i != hash.end() && i.key() == "plenty") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [26] //! [27] for (QHash::const_iterator it = hash.cbegin(), end = hash.cend(); it != end; ++it) { - cout << "The key: " << it.key() << endl - cout << "The value: " << it.value() << endl; - cout << "Also the value: " << (*it) << endl; + cout << "The key: " << it.key() << Qt::endl + cout << "The value: " << it.value() << Qt::endl; + cout << "Also the value: " << (*it) << Qt::endl; } //! [27] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp index 7f743bbd25..e0d3c71dc5 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qlinkedlist.cpp @@ -112,7 +112,7 @@ list.append("December"); QLinkedList::iterator i; for (i = list.begin(); i != list.end(); ++i) - cout << *i << endl; + cout << *i << Qt::endl; //! [7] @@ -122,7 +122,7 @@ QLinkedList list; QLinkedList::iterator it = qFind(list.begin(), list.end(), "Joel"); if (it != list.end()) - cout << "Found Joel" << endl; + cout << "Found Joel" << Qt::endl; //! [8] @@ -182,7 +182,7 @@ list.append("December"); QLinkedList::const_iterator i; for (i = list.constBegin(); i != list.constEnd(); ++i) - cout << *i << endl; + cout << *i << Qt::endl; //! [14] @@ -192,7 +192,7 @@ QLinkedList list; QLinkedList::iterator it = qFind(list.constBegin(), list.constEnd(), "Joel"); if (it != list.constEnd()) - cout << "Found Joel" << endl; + cout << "Found Joel" << Qt::endl; //! [15] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp index 0e746cd6e6..a24e599f2f 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qlistdata.cpp @@ -73,7 +73,7 @@ if (list[0] == "Bob") //! [3] for (int i = 0; i < list.size(); ++i) { if (list.at(i) == "Jane") - cout << "Found Jane at position " << i << endl; + cout << "Found Jane at position " << i << Qt::endl; } //! [3] @@ -89,7 +89,7 @@ while (!list.isEmpty()) //! [5] int i = list.indexOf("Jane"); if (i != -1) - cout << "First occurrence of Jane is at position " << i << endl; + cout << "First occurrence of Jane is at position " << i << Qt::endl; //! [5] @@ -180,7 +180,7 @@ list.append("December"); QList::iterator i; for (i = list.begin(); i != list.end(); ++i) - cout << *i << endl; + cout << *i << Qt::endl; //! [15] @@ -213,7 +213,7 @@ list.append("December"); QList::const_iterator i; for (i = list.constBegin(); i != list.constEnd(); ++i) - cout << *i << endl; + cout << *i << Qt::endl; //! [19] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp index bd59758f71..506022f082 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp @@ -89,7 +89,7 @@ QMap map; ... for (int i = 0; i < 1000; ++i) { if (map[i] == okButton) - cout << "Found button at index " << i << endl; + cout << "Found button at index " << i << Qt::endl; } //! [6] @@ -98,7 +98,7 @@ for (int i = 0; i < 1000; ++i) { QMapIterator i(map); while (i.hasNext()) { i.next(); - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; } //! [7] @@ -106,7 +106,7 @@ while (i.hasNext()) { //! [8] QMap::const_iterator i = map.constBegin(); while (i != map.constEnd()) { - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; ++i; } //! [8] @@ -122,14 +122,14 @@ map.insert("plenty", 2000); //! [10] QList values = map.values("plenty"); for (int i = 0; i < values.size(); ++i) - cout << values.at(i) << endl; + cout << values.at(i) << Qt::endl; //! [10] //! [11] QMap::iterator i = map.find("plenty"); while (i != map.end() && i.key() == "plenty") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [11] @@ -139,7 +139,7 @@ while (i != map.end() && i.key() == "plenty") { QMap map; ... foreach (int value, map) - cout << value << endl; + cout << value << Qt::endl; //! [12] @@ -175,7 +175,7 @@ QMap map; ... QMap::const_iterator i = map.find("HDR"); while (i != map.end() && i.key() == "HDR") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [14] @@ -201,7 +201,7 @@ QMap map; QMap::const_iterator i = map.lowerBound("HDR"); QMap::const_iterator upperBound = map.upperBound("HDR"); while (i != upperBound) { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [16] @@ -230,7 +230,7 @@ map.insert("December", 12); QMap::iterator i; for (i = map.begin(); i != map.end(); ++i) - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; //! [18] @@ -288,7 +288,7 @@ map.insert("December", 12); QMap::const_iterator i; for (i = map.constBegin(); i != map.constEnd(); ++i) - cout << i.key() << ": " << i.value() << endl; + cout << i.key() << ": " << i.value() << Qt::endl; //! [24] @@ -310,23 +310,23 @@ map3 = map1 + map2; //! [26] QList values = map.values("plenty"); for (int i = 0; i < values.size(); ++i) - cout << values.at(i) << endl; + cout << values.at(i) << Qt::endl; //! [26] //! [27] QMultiMap::iterator i = map.find("plenty"); while (i != map.end() && i.key() == "plenty") { - cout << i.value() << endl; + cout << i.value() << Qt::endl; ++i; } //! [27] //! [keyiterator1] for (QMap::const_iterator it = map.cbegin(), end = map.cend(); it != end; ++it) { - cout << "The key: " << it.key() << endl - cout << "The value: " << it.value() << endl; - cout << "Also the value: " << (*it) << endl; + cout << "The key: " << it.key() << Qt::endl + cout << "The value: " << it.value() << Qt::endl; + cout << "Also the value: " << (*it) << Qt::endl; } //! [keyiterator1] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp index b74ac31933..6046c73b0f 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qqueue.cpp @@ -54,5 +54,5 @@ queue.enqueue(1); queue.enqueue(2); queue.enqueue(3); while (!queue.isEmpty()) - cout << queue.dequeue() << endl; + cout << queue.dequeue() << Qt::endl; //! [0] diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp index 7a2b4812ef..eb09fb99e2 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp @@ -72,9 +72,9 @@ while (i.hasNext()) { //! [2] QStringIterator i(u"𝄞 is the G clef"); -qDebug() << hex << i.next(); // will print 1d11e (U+1D11E, MUSICAL SYMBOL G CLEF) -qDebug() << hex << i.next(); // will print 20 (U+0020, SPACE) -qDebug() << hex << i.next(); // will print 69 (U+0069, LATIN SMALL LETTER I) +qDebug() << Qt::hex << i.next(); // will print 1d11e (U+1D11E, MUSICAL SYMBOL G CLEF) +qDebug() << Qt::hex << i.next(); // will print 20 (U+0020, SPACE) +qDebug() << Qt::hex << i.next(); // will print 69 (U+0069, LATIN SMALL LETTER I) //! [2] } diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp index 1f2af4a408..a05233049f 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qvector.cpp @@ -73,7 +73,7 @@ if (vector[0] == "Liz") //! [4] for (int i = 0; i < vector.size(); ++i) { if (vector.at(i) == "Alfonso") - cout << "Found Alfonso at position " << i << endl; + cout << "Found Alfonso at position " << i << Qt::endl; } //! [4] @@ -81,7 +81,7 @@ for (int i = 0; i < vector.size(); ++i) { //! [5] int i = vector.indexOf("Harumi"); if (i != -1) - cout << "First occurrence of Harumi is at position " << i << endl; + cout << "First occurrence of Harumi is at position " << i << Qt::endl; //! [5] diff --git a/src/corelib/doc/snippets/qstack/main.cpp b/src/corelib/doc/snippets/qstack/main.cpp index af6b960e57..66823bcb59 100644 --- a/src/corelib/doc/snippets/qstack/main.cpp +++ b/src/corelib/doc/snippets/qstack/main.cpp @@ -60,6 +60,6 @@ int main(int argc, char *argv[]) stack.push(2); stack.push(3); while (!stack.isEmpty()) - cout << stack.pop() << endl; + cout << stack.pop() << Qt::endl; //! [0] } diff --git a/src/corelib/doc/snippets/qstringlist/main.cpp b/src/corelib/doc/snippets/qstringlist/main.cpp index 55c60650fe..80788ccd76 100644 --- a/src/corelib/doc/snippets/qstringlist/main.cpp +++ b/src/corelib/doc/snippets/qstringlist/main.cpp @@ -71,20 +71,20 @@ Widget::Widget(QWidget *parent) //! [1] for (int i = 0; i < fonts.size(); ++i) - cout << fonts.at(i).toLocal8Bit().constData() << endl; + cout << fonts.at(i).toLocal8Bit().constData() << Qt::endl; //! [1] //! [2] QStringListIterator javaStyleIterator(fonts); while (javaStyleIterator.hasNext()) - cout << javaStyleIterator.next().toLocal8Bit().constData() << endl; + cout << javaStyleIterator.next().toLocal8Bit().constData() << Qt::endl; //! [2] //! [3] QStringList::const_iterator constIterator; for (constIterator = fonts.constBegin(); constIterator != fonts.constEnd(); ++constIterator) - cout << (*constIterator).toLocal8Bit().constData() << endl; + cout << (*constIterator).toLocal8Bit().constData() << Qt::endl; //! [3] //! [4] diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 15c5e0ce96..6dc12cd83f 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -166,7 +166,7 @@ void QDebug::putUcs4(uint ucs4) { maybeQuote('\''); if (ucs4 < 0x20) { - stream->ts << "\\x" << hex << ucs4 << reset; + stream->ts << "\\x" << Qt::hex << ucs4 << Qt::reset; } else if (ucs4 < 0x80) { stream->ts << char(ucs4); } else { @@ -174,7 +174,7 @@ void QDebug::putUcs4(uint ucs4) stream->ts << "\\u" << qSetFieldWidth(4); else stream->ts << "\\U" << qSetFieldWidth(8); - stream->ts << hex << qSetPadChar(QLatin1Char('0')) << ucs4 << reset; + stream->ts << Qt::hex << qSetPadChar(QLatin1Char('0')) << ucs4 << Qt::reset; } maybeQuote('\''); } @@ -834,7 +834,7 @@ QDebug &QDebug::resetFormat() that QDebugStateSaver stores for the duration of the current block. The settings of the internal QTextStream are also saved and restored, - so that using << hex in a QDebug operator doesn't affect other QDebug + so that using << Qt::hex in a QDebug operator doesn't affect other QDebug operators. \since 5.1 diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index f9dc4203db..889fb6b571 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -350,7 +350,7 @@ void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value) { const QDebugStateSaver saver(debug); debug.resetFormat(); - debug.nospace() << "QFlags(" << hex << showbase; + debug.nospace() << "QFlags(" << Qt::hex << Qt::showbase; bool needSeparator = false; for (uint i = 0; i < sizeofT * 8; ++i) { if (value & (Int(1) << i)) { diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index a5e629b646..9d008947ba 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp @@ -388,7 +388,7 @@ void QInotifyFileSystemWatcherEngine::readFromInotify() const inotify_event &event = **it; ++it; - // qDebug() << "inotify event, wd" << event.wd << "mask" << hex << event.mask; + // qDebug() << "inotify event, wd" << event.wd << "mask" << Qt::hex << event.mask; int id = event.wd; QString path = getPathFromID(id); diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 7f4f9d345b..eb626fd541 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -79,7 +79,7 @@ static Qt::HANDLE createChangeNotification(const QString &path, uint flags) nativePath.append(QLatin1Char('\\')); const HANDLE result = FindFirstChangeNotification(reinterpret_cast(nativePath.utf16()), FALSE, flags); - DEBUG() << __FUNCTION__ << nativePath << hex <" << flags; const Qt::HANDLE fileHandle = createChangeNotification(absolutePath, flags); if (fileHandle != INVALID_HANDLE_VALUE) { diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm index b7b379e2c1..33c231987f 100644 --- a/src/corelib/kernel/qeventdispatcher_cf.mm +++ b/src/corelib/kernel/qeventdispatcher_cf.mm @@ -190,7 +190,7 @@ Q_ENUM_PRINTER(Result); QDebug operator<<(QDebug s, timespec tv) { - s << tv.tv_sec << "." << qSetFieldWidth(9) << qSetPadChar(QChar(48)) << tv.tv_nsec << reset; + s << tv.tv_sec << "." << qSetFieldWidth(9) << qSetPadChar(QChar(48)) << tv.tv_nsec << Qt::reset; return s; } diff --git a/src/corelib/kernel/qtimerinfo_unix.cpp b/src/corelib/kernel/qtimerinfo_unix.cpp index c3b8c86063..39010c19cb 100644 --- a/src/corelib/kernel/qtimerinfo_unix.cpp +++ b/src/corelib/kernel/qtimerinfo_unix.cpp @@ -215,7 +215,7 @@ static timespec roundToMillisecond(timespec val) QDebug operator<<(QDebug s, timeval tv) { QDebugStateSaver saver(s); - s.nospace() << tv.tv_sec << "." << qSetFieldWidth(6) << qSetPadChar(QChar(48)) << tv.tv_usec << reset; + s.nospace() << tv.tv_sec << "." << qSetFieldWidth(6) << qSetPadChar(QChar(48)) << tv.tv_usec << Qt::reset; return s; } QDebug operator<<(QDebug s, Qt::TimerType t) @@ -373,7 +373,7 @@ static void calculateNextTimeout(QTimerInfo *t, timespec currentTime) #ifdef QTIMERINFO_DEBUG if (t->timerType != Qt::PreciseTimer) - qDebug() << "timer" << t->timerType << hex << t->id << dec << "interval" << t->interval + qDebug() << "timer" << t->timerType << Qt::hex << t->id << Qt::dec << "interval" << t->interval << "originally expected at" << t->expected << "will fire at" << t->timeout << "or" << (t->timeout - t->expected) << "s late"; #endif @@ -500,7 +500,7 @@ void QTimerInfoList::registerTimer(int timerId, int interval, Qt::TimerType time t->cumulativeError = 0; t->count = 0; if (t->timerType != Qt::PreciseTimer) - qDebug() << "timer" << t->timerType << hex <id << dec << "interval" << t->interval << "expected at" + qDebug() << "timer" << t->timerType << Qt::hex <id << Qt::dec << "interval" << t->interval << "expected at" << t->expected << "will fire first at" << t->timeout; #endif } @@ -620,7 +620,7 @@ int QTimerInfoList::activateTimers() currentTimerInfo->cumulativeError += diff; ++currentTimerInfo->count; if (currentTimerInfo->timerType != Qt::PreciseTimer) - qDebug() << "timer" << currentTimerInfo->timerType << hex << currentTimerInfo->id << dec << "interval" + qDebug() << "timer" << currentTimerInfo->timerType << Qt::hex << currentTimerInfo->id << Qt::dec << "interval" << currentTimerInfo->interval << "firing at" << currentTime << "(orig" << currentTimerInfo->expected << "scheduled at" << currentTimerInfo->timeout << ") off by" << diff << "activation" << currentTimerInfo->count diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 35c64180d4..8e349f23ce 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -239,7 +239,7 @@ void QFactoryLoader::update() library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath()); if (!library->isPlugin()) { if (qt_debug_component()) { - qDebug() << library->errorString << endl + qDebug() << library->errorString << Qt::endl << " not a plugin"; } library->release(); diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index d469735ae9..b2e0ba6d53 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -2941,7 +2941,7 @@ static QDebug debugContents(QDebug &dbg, const QCborValue &v) } if (v.isSimpleType()) return dbg << v.toSimpleType(); - return dbg << "'; + return dbg << "'; } QDebug operator<<(QDebug dbg, const QCborValue &v) { diff --git a/src/corelib/serialization/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp index bfba95520e..f29348d593 100644 --- a/src/corelib/serialization/qjsonparser.cpp +++ b/src/corelib/serialization/qjsonparser.cpp @@ -316,7 +316,7 @@ QJsonDocument Parser::parse(QJsonParseError *error) eatBOM(); char token = nextToken(); - DEBUG << hex << (uint)token; + DEBUG << Qt::hex << (uint)token; if (token == BeginArray) { if (!parseArray()) goto error; diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp index 0d83bb6cd4..ef2a9c97ee 100644 --- a/src/corelib/serialization/qtextstream.cpp +++ b/src/corelib/serialization/qtextstream.cpp @@ -2356,7 +2356,7 @@ void QTextStreamPrivate::putNumber(qulonglong number, bool negative) } else if (negative) { // Workaround for backward compatibility for writing negative // numbers in octal and hex: - // QTextStream(result) << showbase << hex << -1 << oct << -1 + // QTextStream(result) << Qt::showbase << Qt::hex << -1 << oct << -1 // should output: -0x1 -0b1 result = dd->unsLongLongToString(number, -1, base, -1, flags); result.prepend(locale.negativeSign()); @@ -2978,7 +2978,7 @@ QTextStream ¢er(QTextStream &stream) */ QTextStream &endl(QTextStream &stream) { - return stream << QLatin1Char('\n') << flush; + return stream << QLatin1Char('\n') << Qt::flush; } /*! diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 029499039c..93d81b89b6 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -826,9 +826,9 @@ static int ucstricmp(const QChar *a, const QChar *ae, const QChar *b, const QCha uint alast = 0; uint blast = 0; while (a < e) { -// qDebug() << hex << alast << blast; -// qDebug() << hex << "*a=" << *a << "alast=" << alast << "folded=" << foldCase (*a, alast); -// qDebug() << hex << "*b=" << *b << "blast=" << blast << "folded=" << foldCase (*b, blast); +// qDebug() << Qt::hex << alast << blast; +// qDebug() << Qt::hex << "*a=" << *a << "alast=" << alast << "folded=" << foldCase (*a, alast); +// qDebug() << Qt::hex << "*b=" << *b << "blast=" << blast << "folded=" << foldCase (*b, blast); int diff = foldCase(a->unicode(), alast) - foldCase(b->unicode(), blast); if ((diff)) return diff; diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index 46dec7f28d..de76d12a5e 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -1858,7 +1858,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface) return d; } d.nospace(); - d << "QAccessibleInterface(" << hex << (const void *) iface << dec; + d << "QAccessibleInterface(" << Qt::hex << (const void *) iface << Qt::dec; if (iface->isValid()) { d << " name=" << iface->text(QAccessible::Name) << ' '; d << "role=" << qAccessibleRoleString(iface->role()) << ' '; @@ -1897,7 +1897,7 @@ QDebug operator<<(QDebug d, const QAccessibleEvent &ev) QDebugStateSaver saver(d); d.nospace() << "QAccessibleEvent("; if (ev.object()) { - d.nospace() << "object=" << hex << ev.object() << dec; + d.nospace() << "object=" << Qt::hex << ev.object() << Qt::dec; d.nospace() << "child=" << ev.child(); } else { d.nospace() << "no object, uniqueId=" << ev.uniqueId(); diff --git a/src/gui/doc/snippets/textdocumentendsnippet.cpp b/src/gui/doc/snippets/textdocumentendsnippet.cpp index c8de501838..cb7abd5ca7 100644 --- a/src/gui/doc/snippets/textdocumentendsnippet.cpp +++ b/src/gui/doc/snippets/textdocumentendsnippet.cpp @@ -59,7 +59,7 @@ int main(int argv, char **args) //! [0] for (QTextBlock it = doc->begin(); it != doc->end(); it = it.next()) - cout << it.text().toStdString() << endl; + cout << it.text().toStdString() << Qt::endl; //! [0] return 0; diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 892a686c89..2b47fb536b 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -1496,7 +1496,7 @@ QDebug operator<<(QDebug dbg, const QIcon &i) if (!i.name().isEmpty()) dbg << i.name() << ','; dbg << "availableSizes[normal,Off]=" << i.availableSizes() - << ",cacheKey=" << showbase << hex << i.cacheKey() << dec << noshowbase; + << ",cacheKey=" << Qt::showbase << Qt::hex << i.cacheKey() << Qt::dec << Qt::noshowbase; } dbg << ')'; return dbg; diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 5b4d218603..399ad7453d 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1689,7 +1689,7 @@ QDebug operator<<(QDebug dbg, const QPixmap &r) } else { dbg << r.size() << ",depth=" << r.depth() << ",devicePixelRatio=" << r.devicePixelRatio() - << ",cacheKey=" << showbase << hex << r.cacheKey() << dec << noshowbase; + << ",cacheKey=" << Qt::showbase << Qt::hex << r.cacheKey() << Qt::dec << Qt::noshowbase; } dbg << ')'; return dbg; diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index 7349a400a6..deff56aa58 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -1129,8 +1129,8 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const // write header QTextStream s(device); - s << "/* XPM */" << endl - << "static char *" << fbname(fileName) << "[]={" << endl + s << "/* XPM */" << Qt::endl + << "static char *" << fbname(fileName) << "[]={" << Qt::endl << '\"' << w << ' ' << h << ' ' << ncolors << ' ' << cpp << '\"'; // write palette @@ -1147,7 +1147,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const qGreen(color), qBlue(color)); ++c; - s << ',' << endl << line; + s << ',' << Qt::endl << line; } // write pixels, limit to 4 characters per pixel @@ -1169,9 +1169,9 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const } } } - s << ',' << endl << '\"' << line << '\"'; + s << ',' << Qt::endl << '\"' << line << '\"'; } - s << "};" << endl; + s << "};" << Qt::endl; return (s.status() == QTextStream::Ok); } diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index f6d1da45e3..563eab4655 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3764,13 +3764,13 @@ static inline void formatTouchEvent(QDebug d, const QTouchEvent &t) static void formatUnicodeString(QDebug d, const QString &s) { - d << '"' << hex; + d << '"' << Qt::hex; for (int i = 0; i < s.size(); ++i) { if (i) d << ','; d << "U+" << s.at(i).unicode(); } - d << dec << '"'; + d << Qt::dec << '"'; } static inline void formatInputMethodEvent(QDebug d, const QInputMethodEvent *e) @@ -3807,8 +3807,8 @@ static inline void formatInputMethodQueryEvent(QDebug d, const QInputMethodQuery QDebugStateSaver saver(d); d.noquote(); const Qt::InputMethodQueries queries = e->queries(); - d << "QInputMethodQueryEvent(queries=" << showbase << hex << int(queries) - << noshowbase << dec << ", {"; + d << "QInputMethodQueryEvent(queries=" << Qt::showbase << Qt::hex << int(queries) + << Qt::noshowbase << Qt::dec << ", {"; for (unsigned mask = 1; mask <= Qt::ImInputItemClipRectangle; mask<<=1) { if (queries & mask) { const Qt::InputMethodQuery query = static_cast(mask); @@ -4001,7 +4001,7 @@ QDebug operator<<(QDebug dbg, const QTouchEvent::TouchPoint &tp) { QDebugStateSaver saver(dbg); dbg.nospace(); - dbg << "TouchPoint(" << hex << tp.id() << dec << " ("; + dbg << "TouchPoint(" << Qt::hex << tp.id() << Qt::dec << " ("; QtDebugUtils::formatQPoint(dbg, tp.pos()); dbg << ") "; QtDebugUtils::formatQEnum(dbg, tp.state()); diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp index b4383c5bfc..f6e5fa0a52 100644 --- a/src/gui/kernel/qpalette.cpp +++ b/src/gui/kernel/qpalette.cpp @@ -1204,7 +1204,7 @@ QDebug operator<<(QDebug dbg, const QPalette &p) QDebugStateSaver saver(dbg); QDebug nospace = dbg.nospace(); const uint mask = p.resolve(); - nospace << "QPalette(resolve=" << hex << showbase << mask << ','; + nospace << "QPalette(resolve=" << Qt::hex << Qt::showbase << mask << ','; for (int role = 0; role < (int)QPalette::NColorRoles; ++role) { if (mask & (1<isTopLevel()) debug << ", toplevel"; debug << ", " << geometry.width() << 'x' << geometry.height() - << forcesign << geometry.x() << geometry.y() << noforcesign; + << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign; const QMargins margins = window->frameMargins(); if (!margins.isNull()) debug << ", margins=" << margins; debug << ", devicePixelRatio=" << window->devicePixelRatio(); if (const QPlatformWindow *platformWindow = window->handle()) - debug << ", winId=0x" << hex << platformWindow->winId() << dec; + debug << ", winId=0x" << Qt::hex << platformWindow->winId() << Qt::dec; if (const QScreen *screen = window->screen()) debug << ", on " << screen->name(); } diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h index 6a2a9e5bae..692c29c996 100644 --- a/src/gui/math3d/qgenericmatrix.h +++ b/src/gui/math3d/qgenericmatrix.h @@ -351,11 +351,11 @@ QDebug operator<<(QDebug dbg, const QGenericMatrix &m) QDebugStateSaver saver(dbg); dbg.nospace() << "QGenericMatrix<" << N << ", " << M << ", " << QTypeInfo::name() - << ">(" << endl << qSetFieldWidth(10); + << ">(" << Qt::endl << qSetFieldWidth(10); for (int row = 0; row < M; ++row) { for (int col = 0; col < N; ++col) dbg << m(row, col); - dbg << endl; + dbg << Qt::endl; } dbg << qSetFieldWidth(0) << ')'; return dbg; diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index 045fa210c4..ad4cdfdbf4 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -2037,12 +2037,12 @@ QDebug operator<<(QDebug dbg, const QMatrix4x4 &m) } // Output in row-major order because it is more human-readable. - dbg.nospace() << "QMatrix4x4(type:" << bits.constData() << endl + dbg.nospace() << "QMatrix4x4(type:" << bits.constData() << Qt::endl << qSetFieldWidth(10) - << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << endl - << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << endl - << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << endl - << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << endl + << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << Qt::endl + << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << Qt::endl + << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << Qt::endl + << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << Qt::endl << qSetFieldWidth(0) << ')'; return dbg; } diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp index 2b1e57a4bb..6b701fe52b 100644 --- a/src/gui/opengl/qopengl.cpp +++ b/src/gui/opengl/qopengl.cpp @@ -136,7 +136,7 @@ QDebug operator<<(QDebug d, const QOpenGLConfig::Gpu &g) d.nospace(); d << "Gpu("; if (g.isValid()) { - d << "vendor=" << hex << showbase <renderHints; + qDebug() << "QRasterPaintEngine::renderHintsChanged()" << Qt::hex << s->renderHints; #endif bool was_aa = s->flags.antialiased; @@ -1745,7 +1745,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush) QRectF rf = path.controlPointRect(); qDebug() << "QRasterPaintEngine::fill(): " << "size=" << path.elementCount() - << ", hints=" << hex << path.hints() + << ", hints=" << Qt::hex << path.hints() << rf << brush; #endif diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 22d3fb3001..8314e8bc8a 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -140,7 +140,7 @@ QDebug Q_GUI_EXPORT &operator<<(QDebug &s, const QVectorPath &path) QDebugStateSaver saver(s); QRectF rf = path.controlPointRect(); s << "QVectorPath(size:" << path.elementCount() - << " hints:" << hex << path.hints() + << " hints:" << Qt::hex << path.hints() << rf << ')'; return s; } diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 649cfd554b..7eaa4b6e3f 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -3576,10 +3576,10 @@ void QPainterPath::computeControlPointRect() const #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug s, const QPainterPath &p) { - s.nospace() << "QPainterPath: Element count=" << p.elementCount() << endl; + s.nospace() << "QPainterPath: Element count=" << p.elementCount() << Qt::endl; const char *types[] = {"MoveTo", "LineTo", "CurveTo", "CurveToData"}; for (int i=0; i " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ')' << endl; + s.nospace() << " -> " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ')' << Qt::endl; } return s; diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 1719855e68..99c9e1bfdc 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1213,7 +1213,7 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) end: std::sort(kerning_pairs.begin(), kerning_pairs.end()); // for (int i = 0; i < kerning_pairs.count(); ++i) -// qDebug() << 'i' << i << "left_right" << hex << kerning_pairs.at(i).left_right; +// qDebug() << 'i' << i << "left_right" << Qt::hex << kerning_pairs.at(i).left_right; } diff --git a/src/gui/text/qfontengine_qpf2.cpp b/src/gui/text/qfontengine_qpf2.cpp index 110d512d39..409176d41b 100644 --- a/src/gui/text/qfontengine_qpf2.cpp +++ b/src/gui/text/qfontengine_qpf2.cpp @@ -140,9 +140,9 @@ static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr) } #if defined(DEBUG_HEADER) if (length == 1) - qDebug() << "tag data" << hex << *tagPtr; + qDebug() << "tag data" << Qt::hex << *tagPtr; else if (length == 4) - qDebug() << "tag data" << hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3]; + qDebug() << "tag data" << Qt::hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3]; #endif } return tagPtr + length; @@ -367,7 +367,7 @@ bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyp #if 0 && defined(DEBUG_FONTENGINE) QChar c(uc); if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c)) - qDebug() << "glyph for character" << c << '/' << hex << uc << "is" << dec << glyphs[glyph_pos].glyph; + qDebug() << "glyph for character" << c << '/' << Qt::hex << uc << "is" << Qt::dec << glyphs[glyph_pos].glyph; seenGlyphs.insert(c); #endif diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 2616a42022..840448152f 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -990,7 +990,7 @@ struct QBidiAlgorithm { BIDI_DEBUG() << "before implicit level processing:"; IsolatedRunSequenceIterator it(runs, i); while (!it.atEnd()) { - BIDI_DEBUG() << " " << *it << hex << text[*it].unicode() << analysis[*it].bidiDirection; + BIDI_DEBUG() << " " << *it << Qt::hex << text[*it].unicode() << analysis[*it].bidiDirection; ++it; } } @@ -1003,7 +1003,7 @@ struct QBidiAlgorithm { BIDI_DEBUG() << "after W4/W5"; IsolatedRunSequenceIterator it(runs, i); while (!it.atEnd()) { - BIDI_DEBUG() << " " << *it << hex << text[*it].unicode() << analysis[*it].bidiDirection; + BIDI_DEBUG() << " " << *it << Qt::hex << text[*it].unicode() << analysis[*it].bidiDirection; ++it; } } @@ -1089,7 +1089,7 @@ struct QBidiAlgorithm { if (BidiDebugEnabled) { BIDI_DEBUG() << ">>>> start bidi, text length" << length; for (int i = 0; i < length; ++i) - BIDI_DEBUG() << hex << " (" << i << ")" << text[i].unicode() << text[i].direction(); + BIDI_DEBUG() << Qt::hex << " (" << i << ")" << text[i].unicode() << text[i].direction(); } { @@ -1158,7 +1158,7 @@ struct QBidiAlgorithm { if (BidiDebugEnabled) { BIDI_DEBUG() << "final resolved levels:"; for (int i = 0; i < length; ++i) - BIDI_DEBUG() << " " << i << hex << text[i].unicode() << dec << (int)analysis[i].bidiLevel; + BIDI_DEBUG() << " " << i << Qt::hex << text[i].unicode() << Qt::dec << (int)analysis[i].bidiLevel; } return true; diff --git a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp index 4baba64de3..1028d8ec02 100644 --- a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp @@ -127,7 +127,7 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q error = FT_New_Face(library, file.constData(), index, &face); } if (error != FT_Err_Ok) { - qDebug() << "FT_New_Face failed with index" << index << ':' << hex << error; + qDebug() << "FT_New_Face failed with index" << index << ':' << Qt::hex << error; break; } numFaces = face->num_faces; diff --git a/src/plugins/bearer/nla/qnlaengine.cpp b/src/plugins/bearer/nla/qnlaengine.cpp index 726e1efb92..bf10e0cc1f 100644 --- a/src/plugins/bearer/nla/qnlaengine.cpp +++ b/src/plugins/bearer/nla/qnlaengine.cpp @@ -75,38 +75,38 @@ QWindowsSockInit2::~QWindowsSockInit2() #ifdef BEARER_MANAGEMENT_DEBUG static void printBlob(NLA_BLOB *blob) { - qDebug() << "==== BEGIN NLA_BLOB ====" << endl + qDebug() << "==== BEGIN NLA_BLOB ====" << Qt::endl - << "type:" << blob->header.type << endl - << "size:" << blob->header.dwSize << endl + << "type:" << blob->header.type << Qt::endl + << "size:" << blob->header.dwSize << Qt::endl << "next offset:" << blob->header.nextOffset; switch (blob->header.type) { case NLA_RAW_DATA: - qDebug() << "Raw Data" << endl + qDebug() << "Raw Data" << Qt::endl << '\t' << blob->data.rawData; break; case NLA_INTERFACE: - qDebug() << "Interface" << endl - << "\ttype:" << blob->data.interfaceData.dwType << endl - << "\tspeed:" << blob->data.interfaceData.dwSpeed << endl + qDebug() << "Interface" << Qt::endl + << "\ttype:" << blob->data.interfaceData.dwType << Qt::endl + << "\tspeed:" << blob->data.interfaceData.dwSpeed << Qt::endl << "\tadapter:" << blob->data.interfaceData.adapterName; break; case NLA_802_1X_LOCATION: - qDebug() << "802.1x Location" << endl + qDebug() << "802.1x Location" << Qt::endl << '\t' << blob->data.locationData.information; break; case NLA_CONNECTIVITY: - qDebug() << "Connectivity" << endl - << "\ttype:" << blob->data.connectivity.type << endl + qDebug() << "Connectivity" << Qt::endl + << "\ttype:" << blob->data.connectivity.type << Qt::endl << "\tinternet:" << blob->data.connectivity.internet; break; case NLA_ICS: - qDebug() << "ICS" << endl - << "\tspeed:" << blob->data.ICS.remote.speed << endl - << "\ttype:" << blob->data.ICS.remote.type << endl - << "\tstate:" << blob->data.ICS.remote.state << endl - << "\tmachine name:" << blob->data.ICS.remote.machineName << endl + qDebug() << "ICS" << Qt::endl + << "\tspeed:" << blob->data.ICS.remote.speed << Qt::endl + << "\ttype:" << blob->data.ICS.remote.type << Qt::endl + << "\tstate:" << blob->data.ICS.remote.state << Qt::endl + << "\tmachine name:" << blob->data.ICS.remote.machineName << Qt::endl << "\tshared adapter name:" << blob->data.ICS.remote.sharedAdapterName; break; default: diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 6ae429b24e..70dde46ffa 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -485,7 +485,7 @@ static jboolean startQtAndroidPlugin(JNIEnv *env, jobject /*object*/, jstring pa } if (Q_UNLIKELY(!m_main)) { - qCritical() << "dlsym failed:" << dlerror() << endl + qCritical() << "dlsym failed:" << dlerror() << Qt::endl << "Could not find main method"; return false; } diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index 368cf56c80..db4ec251ae 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -177,7 +177,7 @@ NSString *macRole(QAccessibleInterface *interface) if (roleMap.isEmpty()) populateRoleMap(); - // MAC_ACCESSIBILTY_DEBUG() << "role for" << interface.object() << "interface role" << hex << qtRole; + // MAC_ACCESSIBILTY_DEBUG() << "role for" << interface.object() << "interface role" << Qt::hex << qtRole; if (roleMap.contains(qtRole)) { // MAC_ACCESSIBILTY_DEBUG() << "return" << roleMap[qtRole]; diff --git a/src/plugins/platforms/cocoa/qnsview_gestures.mm b/src/plugins/platforms/cocoa/qnsview_gestures.mm index 61d551ee0e..f6cd3af4da 100644 --- a/src/plugins/platforms/cocoa/qnsview_gestures.mm +++ b/src/plugins/platforms/cocoa/qnsview_gestures.mm @@ -70,7 +70,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") if ([self handleGestureAsBeginEnd:event]) return; - qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification] << "from device" << hex << [event deviceID]; + qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification] << "from device" << Qt::hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; @@ -85,7 +85,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") return; static bool zoomIn = true; - qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn << "from device" << hex << [event deviceID]; + qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn << "from device" << Qt::hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; @@ -116,7 +116,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") if (!m_platformWindow) return; - qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY] << "from device" << hex << [event deviceID]; + qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY] << "from device" << Qt::hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; @@ -145,7 +145,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") QPointF windowPoint; QPointF screenPoint; [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint << "from device" << hex << [event deviceID]; + qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::BeginNativeGesture, windowPoint, screenPoint); } @@ -155,7 +155,7 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") if (!m_platformWindow) return; - qCDebug(lcQpaGestures) << "endGestureWithEvent" << "from device" << hex << [event deviceID]; + qCDebug(lcQpaGestures) << "endGestureWithEvent" << "from device" << Qt::hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; diff --git a/src/plugins/platforms/cocoa/qnsview_touch.mm b/src/plugins/platforms/cocoa/qnsview_touch.mm index e789213f70..9330844aec 100644 --- a/src/plugins/platforms/cocoa/qnsview_touch.mm +++ b/src/plugins/platforms/cocoa/qnsview_touch.mm @@ -60,7 +60,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesBeganWithEvent" << points << "from device" << hex << [event deviceID]; + qCDebug(lcQpaTouch) << "touchesBeganWithEvent" << points << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } @@ -71,7 +71,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points << "from device" << hex << [event deviceID]; + qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } @@ -82,7 +82,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points << "from device" << hex << [event deviceID]; + qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } @@ -93,7 +93,7 @@ Q_LOGGING_CATEGORY(lcQpaTouch, "qt.qpa.input.touch") const NSTimeInterval timestamp = [event timestamp]; const QList points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points << "from device" << hex << [event deviceID]; + qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points << "from device" << Qt::hex << [event deviceID]; QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp index 24051c352e..09a10bcc9c 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp @@ -157,7 +157,7 @@ gbm_surface *QEglFSKmsGbmScreen::createSurface(EGLConfig eglConfig) const auto gbmDevice = static_cast(device())->gbmDevice(); EGLint native_format = -1; EGLBoolean success = eglGetConfigAttrib(display(), eglConfig, EGL_NATIVE_VISUAL_ID, &native_format); - qCDebug(qLcEglfsKmsDebug) << "Got native format" << hex << native_format << dec << "from eglGetConfigAttrib() with return code" << bool(success); + qCDebug(qLcEglfsKmsDebug) << "Got native format" << Qt::hex << native_format << Qt::dec << "from eglGetConfigAttrib() with return code" << bool(success); if (success) m_gbm_surface = gbm_surface_create(gbmDevice, diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 073d6da536..9ab9c2708b 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -590,7 +590,7 @@ QString QWindowsContext::registerWindowClass(QString cname, d->m_registeredWindowClassNames.insert(cname); qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << ' ' << cname - << " style=0x" << hex << style << dec + << " style=0x" << Qt::hex << style << Qt::dec << " brush=" << brush << " icon=" << icon << " atom=" << atom; return cname; } @@ -1570,7 +1570,7 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR if (QWindowsContext::verbose > 1 && lcQpaEvents().isDebugEnabled()) { if (const char *eventName = QWindowsGuiEventDispatcher::windowsMessageName(message)) { qCDebug(lcQpaEvents).nospace() << "EVENT: hwd=" << hwnd << ' ' << eventName - << " msg=0x" << hex << message << " et=0x" << et << dec << " wp=" + << " msg=0x" << Qt::hex << message << " et=0x" << et << Qt::dec << " wp=" << int(wParam) << " at " << GET_X_LPARAM(lParam) << ',' << GET_Y_LPARAM(lParam) << " handled=" << handled; } diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 9de3268fc8..e0bd38c951 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -736,7 +736,7 @@ QString QWindowsShellItem::libraryItemDefaultSaveFolder(IShellItem *item) #ifndef QT_NO_DEBUG_STREAM void QWindowsShellItem::format(QDebug &d) const { - d << "attributes=0x" << hex << attributes() << dec; + d << "attributes=0x" << Qt::hex << attributes() << Qt::dec; if (isFileSystem()) d << " [filesys]"; if (isDir()) @@ -972,7 +972,7 @@ void QWindowsNativeFileDialogBase::doExec(HWND owner) // gets a WM_CLOSE or the parent window is destroyed. const HRESULT hr = m_fileDialog->Show(owner); QWindowsDialogs::eatMouseMove(); - qCDebug(lcQpaDialogs) << '<' << __FUNCTION__ << " returns " << hex << hr; + qCDebug(lcQpaDialogs) << '<' << __FUNCTION__ << " returns " << Qt::hex << hr; // Emit accepted() only if there is a result as otherwise UI hangs occur. // For example, typing in invalid URLs results in empty result lists. if (hr == S_OK && !m_data.selectedFiles().isEmpty()) { @@ -1013,7 +1013,7 @@ void QWindowsNativeFileDialogBase::setMode(QFileDialogOptions::FileMode mode, } qCDebug(lcQpaDialogs) << __FUNCTION__ << "mode=" << mode << "acceptMode=" << acceptMode << "options=" << options - << "results in" << showbase << hex << flags; + << "results in" << Qt::showbase << Qt::hex << flags; if (FAILED(m_fileDialog->SetOptions(flags))) qErrnoWarning("%s: SetOptions() failed", __FUNCTION__); diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 322865b0f3..502c92ef59 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -428,7 +428,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) if (QWindowsContext::verbose > 1 || result != S_OK) { qCDebug(lcQpaMime) << __FUNCTION__ << "fEscapePressed=" << fEscapePressed << "grfKeyState=" << grfKeyState << "buttons" << m_currentButtons - << "returns 0x" << hex << int(result) << dec; + << "returns 0x" << Qt::hex << int(result) << Qt::dec; } return ResultFromScode(result); } @@ -710,7 +710,7 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag) const Qt::DropActions possibleActions = drag->supportedActions(); const DWORD allowedEffects = translateToWinDragEffects(possibleActions); qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x" - << hex << int(possibleActions) << "effects=0x" << allowedEffects << dec; + << Qt::hex << int(possibleActions) << "effects=0x" << allowedEffects << Qt::dec; // Indicate message handlers we are in DoDragDrop() event loop. QWindowsDrag::m_dragging = true; const HRESULT r = DoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect); @@ -734,9 +734,9 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag) dropDataObject->releaseQt(); dropDataObject->Release(); // Will delete obj if refcount becomes 0 windowDropSource->Release(); // Will delete src if refcount becomes 0 - qCDebug(lcQpaMime) << '<' << __FUNCTION__ << hex << "allowedEffects=0x" << allowedEffects + qCDebug(lcQpaMime) << '<' << __FUNCTION__ << Qt::hex << "allowedEffects=0x" << allowedEffects << "reportedPerformedEffect=0x" << reportedPerformedEffect - << " resultEffect=0x" << resultEffect << "hr=0x" << int(r) << dec << "dropAction=" << dragResult; + << " resultEffect=0x" << resultEffect << "hr=0x" << int(r) << Qt::dec << "dropAction=" << dragResult; return dragResult; } diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index e95eaef420..d534ce87cd 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -243,7 +243,7 @@ QDebug operator<<(QDebug d, const PIXELFORMATDESCRIPTOR &pd) QDebugStateSaver saver(d); d.nospace(); d << "PIXELFORMATDESCRIPTOR " - << "dwFlags=" << hex << showbase << pd.dwFlags << dec << noshowbase; + << "dwFlags=" << Qt::hex << Qt::showbase << pd.dwFlags << Qt::dec << Qt::noshowbase; if (pd.dwFlags & PFD_DRAW_TO_WINDOW) d << " PFD_DRAW_TO_WINDOW"; if (pd.dwFlags & PFD_DRAW_TO_BITMAP) d << " PFD_DRAW_TO_BITMAP"; if (pd.dwFlags & PFD_SUPPORT_GDI) d << " PFD_SUPPORT_GDI"; @@ -631,10 +631,10 @@ static int choosePixelFormat(HDC hdc, nsp << __FUNCTION__; if (sampleBuffersRequested) nsp << " samples=" << iAttributes[samplesValuePosition]; - nsp << " Attributes: " << hex << showbase; + nsp << " Attributes: " << Qt::hex << Qt::showbase; for (int ii = 0; ii < i; ++ii) nsp << iAttributes[ii] << ','; - nsp << noshowbase << dec << "\n obtained px #" << pixelFormat + nsp << Qt::noshowbase << Qt::dec << "\n obtained px #" << pixelFormat << " of " << numFormats << "\n " << *obtainedPfd; qCDebug(lcQpaGl) << message; } // Debug @@ -784,7 +784,7 @@ static HGLRC createContext(const QOpenGLStaticContext &staticContext, if (!result) { QString message; QDebug(&message).nospace() << __FUNCTION__ << ": wglCreateContextAttribsARB() failed (GL error code: 0x" - << hex << staticContext.opengl32.glGetError() << dec << ") for format: " << format << ", shared context: " << shared; + << Qt::hex << staticContext.opengl32.glGetError() << Qt::dec << ") for format: " << format << ", shared context: " << shared; qErrnoWarning("%s", qPrintable(message)); } return result; diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 878f55e56b..71ed33f85b 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -657,9 +657,9 @@ void QWindowsInputContext::handleInputLanguageChanged(WPARAM wparam, LPARAM lpar m_locale = qt_localeFromLCID(m_languageId); emitLocaleChanged(); - qCDebug(lcQpaInputMethods) << __FUNCTION__ << hex << showbase + qCDebug(lcQpaInputMethods) << __FUNCTION__ << Qt::hex << Qt::showbase << oldLanguageId << "->" << newLanguageId << "Character set:" - << DWORD(wparam) << dec << noshowbase << m_locale; + << DWORD(wparam) << Qt::dec << Qt::noshowbase << m_locale; } /*! diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 2c90b0484e..e896f9f0ee 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -324,7 +324,7 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons if (window->type() == Qt::Desktop) { QWindowsDesktopWindow *result = new QWindowsDesktopWindow(window); qCDebug(lcQpaWindows) << "Desktop window:" << window - << showbase << hex << result->winId() << noshowbase << dec << result->geometry(); + << Qt::showbase << Qt::hex << result->winId() << Qt::noshowbase << Qt::dec << result->geometry(); return result; } @@ -373,8 +373,8 @@ QPlatformWindow *QWindowsIntegration::createForeignWindow(QWindow *window, WId n screen = pScreen->screen(); if (screen && screen != window->screen()) window->setScreen(screen); - qCDebug(lcQpaWindows) << "Foreign window:" << window << showbase << hex - << result->winId() << noshowbase << dec << obtainedGeometry << screen; + qCDebug(lcQpaWindows) << "Foreign window:" << window << Qt::showbase << Qt::hex + << result->winId() << Qt::noshowbase << Qt::dec << obtainedGeometry << screen; return result; } diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index c5af4d8042..44668cde78 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -554,7 +554,7 @@ QDebug operator<<(QDebug d, const KeyboardLayoutItem &k) if (const quint32 qtKey = k.qtKey[i]) { d << '[' << i << ' '; QtDebugUtils::formatQFlags(d, ModsTbl[i]); - d << ' ' << hex << showbase << qtKey << dec << noshowbase << ' '; + d << ' ' << Qt::hex << Qt::showbase << qtKey << Qt::dec << Qt::noshowbase << ' '; QtDebugUtils::formatQEnum(d, Qt::Key(qtKey)); if (qtKey >= 32 && qtKey < 128) d << " '" << char(qtKey) << '\''; @@ -776,7 +776,7 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 ::ToAscii(vk_key, scancode, kbdBuffer, reinterpret_cast(&buffer), 0); } qCDebug(lcQpaEvents) << __FUNCTION__ << "for virtual key=" - << hex << showbase << vk_key << dec << noshowbase << keyLayout[vk_key]; + << Qt::hex << Qt::showbase << vk_key << Qt::dec << Qt::noshowbase << keyLayout[vk_key]; } static inline QString messageKeyText(const MSG &msg) @@ -1384,7 +1384,7 @@ QList QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const } } qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey=" - << showbase << hex << e->nativeVirtualKey() << dec << noshowbase + << Qt::showbase << Qt::hex << e->nativeVirtualKey() << Qt::dec << Qt::noshowbase << e->modifiers() << kbItem << "\n returns" << formatKeys(result); return result; } diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp index 17a1b94101..e55e283fe1 100644 --- a/src/plugins/platforms/windows/qwindowsmenu.cpp +++ b/src/plugins/platforms/windows/qwindowsmenu.cpp @@ -896,8 +896,8 @@ void QWindowsMenuItem::formatDebug(QDebug &d) const d << ", parentMenu=" << static_cast(m_parentMenu); if (m_subMenu) d << ", subMenu=" << static_cast(m_subMenu); - d << ", tag=" << showbase << hex - << tag() << noshowbase << dec << ", id=" << m_id; + d << ", tag=" << Qt::showbase << Qt::hex + << tag() << Qt::noshowbase << Qt::dec << ", id=" << m_id; #if QT_CONFIG(shortcut) if (!m_shortcut.isEmpty()) d << ", shortcut=" << m_shortcut; @@ -933,7 +933,7 @@ void QWindowsMenu::formatDebug(QDebug &d) const if (m_parentMenu != nullptr) d << " [on menu]"; if (tag()) - d << ", tag=" << showbase << hex << tag() << noshowbase << dec; + d << ", tag=" << Qt::showbase << Qt::hex << tag() << Qt::noshowbase << Qt::dec; if (m_visible) d << " [visible]"; if (m_enabled) diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 737fd1d2a9..c4d53855a5 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -124,8 +124,8 @@ static inline QTouchDevice *createTouchDevice() return nullptr; const int tabletPc = GetSystemMetrics(SM_TABLETPC); const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES); - qCDebug(lcQpaEvents) << "Digitizers:" << hex << showbase << (digitizers & ~NID_READY) - << "Ready:" << (digitizers & NID_READY) << dec << noshowbase + qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY) + << "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase << "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints; QTouchDevice *result = new QTouchDevice; result->setType(digitizers & NID_INTEGRATED_TOUCH diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index e9c3f2cbf6..fb6a74581a 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -110,7 +110,7 @@ QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) } if (QWindowsContext::verbose > 1 && lcQpaMime().isDebugEnabled()) - qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << hex << showbase << quint64(hr); + qCDebug(lcQpaMime) <<__FUNCTION__ << *pformatetc << "returns" << Qt::hex << Qt::showbase << quint64(hr); return hr; } @@ -135,7 +135,7 @@ QWindowsOleDataObject::QueryGetData(LPFORMATETC pformatetc) ResultFromScode(S_OK) : ResultFromScode(S_FALSE); } if (QWindowsContext::verbose > 1) - qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << hex << int(hr); + qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << Qt::hex << int(hr); return hr; } @@ -163,7 +163,7 @@ QWindowsOleDataObject::SetData(LPFORMATETC pFormatetc, STGMEDIUM *pMedium, BOOL hr = ResultFromScode(S_OK); } if (QWindowsContext::verbose > 1) - qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << hex << int(hr); + qCDebug(lcQpaMime) << __FUNCTION__ << " returns 0x" << Qt::hex << int(hr); return hr; } diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index 840a3a11c4..35418a18e7 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -188,9 +188,9 @@ QDebug operator<<(QDebug d, const GpuDescription &gd) { QDebugStateSaver s(d); d.nospace(); - d << hex << showbase << "GpuDescription(vendorId=" << gd.vendorId + d << Qt::hex << Qt::showbase << "GpuDescription(vendorId=" << gd.vendorId << ", deviceId=" << gd.deviceId << ", subSysId=" << gd.subSysId - << dec << noshowbase << ", revision=" << gd.revision + << Qt::dec << Qt::noshowbase << ", revision=" << gd.revision << ", driver: " << gd.driverName << ", version=" << gd.driverVersion << ", " << gd.description << gd.gpuSuitableScreen << ')'; @@ -207,11 +207,11 @@ QString GpuDescription::toString() const << "\n Driver Name : " << driverName << "\n Driver Version : " << driverVersion.toString() << "\n Vendor ID : 0x" << qSetPadChar(QLatin1Char('0')) - << uppercasedigits << hex << qSetFieldWidth(4) << vendorId + << Qt::uppercasedigits << Qt::hex << qSetFieldWidth(4) << vendorId << "\n Device ID : 0x" << qSetFieldWidth(4) << deviceId << "\n SubSys ID : 0x" << qSetFieldWidth(8) << subSysId << "\n Revision ID : 0x" << qSetFieldWidth(4) << revision - << dec; + << Qt::dec; if (!gpuSuitableScreen.isEmpty()) str << "\nGL windows forced to screen: " << gpuSuitableScreen; return result; diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index 9a8b5d5121..7da87a32d5 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -315,8 +315,8 @@ static QTouchDevice *createTouchDevice() return nullptr; const int tabletPc = GetSystemMetrics(SM_TABLETPC); const int maxTouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES); - qCDebug(lcQpaEvents) << "Digitizers:" << hex << showbase << (digitizers & ~NID_READY) - << "Ready:" << (digitizers & NID_READY) << dec << noshowbase + qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY) + << "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase << "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints; QTouchDevice *result = new QTouchDevice; result->setType(digitizers & NID_INTEGRATED_TOUCH @@ -469,19 +469,19 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, QList touchPoints; if (QWindowsContext::verbose > 1) - qCDebug(lcQpaEvents).noquote().nospace() << showbase + qCDebug(lcQpaEvents).noquote().nospace() << Qt::showbase << __FUNCTION__ - << " message=" << hex << msg.message - << " count=" << dec << count; + << " message=" << Qt::hex << msg.message + << " count=" << Qt::dec << count; Qt::TouchPointStates allStates = 0; for (quint32 i = 0; i < count; ++i) { if (QWindowsContext::verbose > 1) - qCDebug(lcQpaEvents).noquote().nospace() << showbase + qCDebug(lcQpaEvents).noquote().nospace() << Qt::showbase << " TouchPoint id=" << touchInfo[i].pointerInfo.pointerId << " frame=" << touchInfo[i].pointerInfo.frameId - << " flags=" << hex << touchInfo[i].pointerInfo.pointerFlags; + << " flags=" << Qt::hex << touchInfo[i].pointerInfo.pointerFlags; QWindowSystemInterface::TouchPoint touchPoint; const quint32 pointerId = touchInfo[i].pointerInfo.pointerId; @@ -563,11 +563,11 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin const int z = 0; if (QWindowsContext::verbose > 1) - qCDebug(lcQpaEvents).noquote().nospace() << showbase + qCDebug(lcQpaEvents).noquote().nospace() << Qt::showbase << __FUNCTION__ << " sourceDevice=" << sourceDevice << " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos - << " message=" << hex << msg.message - << " flags=" << hex << penInfo->pointerInfo.pointerFlags; + << " message=" << Qt::hex << msg.message + << " flags=" << Qt::hex << penInfo->pointerInfo.pointerFlags; const QTabletEvent::TabletDevice device = QTabletEvent::Stylus; QTabletEvent::PointerType type; diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index fa209f09c4..84c963af94 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -146,13 +146,13 @@ QDebug operator<<(QDebug d, const LOGCONTEXT &lc) QDebugStateSaver saver(d); d.nospace(); d << "LOGCONTEXT(\"" << QString::fromWCharArray(lc.lcName) << "\", options=0x" - << hex << lc.lcOptions << dec; + << Qt::hex << lc.lcOptions << Qt::dec; formatOptions(d, lc.lcOptions); - d << ", status=0x" << hex << lc.lcStatus << ", device=0x" << lc.lcDevice - << dec << ", PktRate=" << lc.lcPktRate + d << ", status=0x" << Qt::hex << lc.lcStatus << ", device=0x" << lc.lcDevice + << Qt::dec << ", PktRate=" << lc.lcPktRate << ", PktData=" << lc.lcPktData << ", PktMode=" << lc.lcPktMode - << ", MoveMask=0x" << hex << lc.lcMoveMask << ", BtnDnMask=0x" << lc.lcBtnDnMask - << ", BtnUpMask=0x" << lc.lcBtnUpMask << dec << ", SysMode=" << lc.lcSysMode + << ", MoveMask=0x" << Qt::hex << lc.lcMoveMask << ", BtnDnMask=0x" << lc.lcBtnDnMask + << ", BtnUpMask=0x" << lc.lcBtnUpMask << Qt::dec << ", SysMode=" << lc.lcSysMode << ", InOrg=(" << lc.lcInOrgX << ", " << lc.lcInOrgY << ", " << lc.lcInOrgZ << "), InExt=(" << lc.lcInExtX << ", " << lc.lcInExtY << ", " << lc.lcInExtZ << ") OutOrg=(" << lc.lcOutOrgX << ", " << lc.lcOutOrgY << ", " @@ -305,7 +305,7 @@ QString QWindowsTabletSupport::description() const << '.' << (specificationVersion & 0xFF) << " implementation: v" << (implementationVersion >> 8) << '.' << (implementationVersion & 0xFF) << ' ' << devices << " device(s), " << cursors << " cursor(s), " - << extensions << " extensions" << ", options: 0x" << hex << opts << dec; + << extensions << " extensions" << ", options: 0x" << Qt::hex << opts << Qt::dec; formatOptions(str, opts); if (m_tiltSupport) str << " tilt"; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 338e594c7b..d55545af42 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -238,7 +238,7 @@ QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp) QDebugStateSaver saver(d); d.nospace(); d.noquote(); - d << "WINDOWPLACEMENT(flags=0x" << hex << wp.flags << dec << ", showCmd=" + d << "WINDOWPLACEMENT(flags=0x" << Qt::hex << wp.flags << Qt::dec << ", showCmd=" << wp.showCmd << ", ptMinPosition=" << wp.ptMinPosition << ", ptMaxPosition=" << wp.ptMaxPosition << ", rcNormalPosition=" << wp.rcNormalPosition; return d; @@ -248,7 +248,7 @@ QDebug operator<<(QDebug d, const GUID &guid) { QDebugStateSaver saver(d); d.nospace(); - d << '{' << hex << uppercasedigits << qSetPadChar(QLatin1Char('0')) + d << '{' << Qt::hex << Qt::uppercasedigits << qSetPadChar(QLatin1Char('0')) << qSetFieldWidth(8) << guid.Data1 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) << guid.Data2 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4) @@ -883,7 +883,7 @@ QMargins QWindowsGeometryHint::frame(DWORD style, DWORD exStyle) const QMargins result(qAbs(rect.left), qAbs(rect.top), qAbs(rect.right), qAbs(rect.bottom)); qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << " style=" - << showbase << hex << style << " exStyle=" << exStyle << dec << noshowbase + << Qt::showbase << Qt::hex << style << " exStyle=" << exStyle << Qt::dec << Qt::noshowbase << ' ' << rect << ' ' << result; return result; } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 899081e752..81b889a80f 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -636,13 +636,13 @@ static void dumpNativeWindowsRecursion(const QXcbConnection *connection, xcb_win const QChar oldPadChar =str.padChar(); str.setFieldWidth(8); str.setPadChar(QLatin1Char('0')); - str << hex << window; + str << Qt::hex << window; str.setFieldWidth(oldFieldWidth); str.setPadChar(oldPadChar); - str << dec << " \"" + str << Qt::dec << " \"" << QXcbWindow::windowTitle(connection, window) << "\" " - << geom.width() << 'x' << geom.height() << forcesign << geom.x() << geom.y() - << noforcesign << '\n'; + << geom.width() << 'x' << geom.height() << Qt::forcesign << geom.x() << geom.y() + << Qt::noforcesign << '\n'; auto reply = Q_XCB_REPLY(xcb_query_tree, conn, window); if (reply) { diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 0fa0e8cd7b..bfc105a040 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -915,7 +915,7 @@ QByteArray QXcbScreen::getEdid() const static inline void formatRect(QDebug &debug, const QRect r) { debug << r.width() << 'x' << r.height() - << forcesign << r.x() << r.y() << noforcesign; + << Qt::forcesign << r.x() << r.y() << Qt::noforcesign; } static inline void formatSizeF(QDebug &debug, const QSizeF s) @@ -929,7 +929,7 @@ QDebug operator<<(QDebug debug, const QXcbScreen *screen) debug.nospace(); debug << "QXcbScreen(" << (const void *)screen; if (screen) { - debug << fixed << qSetRealNumberPrecision(1); + debug << Qt::fixed << qSetRealNumberPrecision(1); debug << ", name=" << screen->name(); debug << ", geometry="; formatRect(debug, screen->geometry()); @@ -947,7 +947,7 @@ QDebug operator<<(QDebug debug, const QXcbScreen *screen) debug << "), orientation=" << screen->orientation(); debug << ", depth=" << screen->depth(); debug << ", refreshRate=" << screen->refreshRate(); - debug << ", root=" << hex << screen->root(); + debug << ", root=" << Qt::hex << screen->root(); debug << ", windowManagerName=" << screen->windowManagerName(); } debug << ')'; diff --git a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp index a27feb1505..bba0487452 100644 --- a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp +++ b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp @@ -213,7 +213,7 @@ void QSqlQuery_snippets() while (i.hasNext()) { i.next(); cout << i.key().toUtf8().data() << ": " - << i.value().toString().toUtf8().data() << endl; + << i.value().toString().toUtf8().data() << Qt::endl; } //! [14] } @@ -223,7 +223,7 @@ void QSqlQuery_snippets() //! [15] QList list = query.boundValues().values(); for (int i = 0; i < list.size(); ++i) - cout << i << ": " << list.at(i).toString().toUtf8().data() << endl; + cout << i << ": " << list.at(i).toString().toUtf8().data() << Qt::endl; //! [15] } } diff --git a/src/sql/kernel/qsqlrecord.cpp b/src/sql/kernel/qsqlrecord.cpp index ecbe3eacdb..c4dc5d1adb 100644 --- a/src/sql/kernel/qsqlrecord.cpp +++ b/src/sql/kernel/qsqlrecord.cpp @@ -535,7 +535,7 @@ QDebug operator<<(QDebug dbg, const QSqlRecord &r) dbg << "QSqlRecord(" << count << ')'; for (int i = 0; i < count; ++i) { dbg.nospace(); - dbg << '\n' << qSetFieldWidth(2) << right << i << left << qSetFieldWidth(0) << ':'; + dbg << '\n' << qSetFieldWidth(2) << Qt::right << i << Qt::left << qSetFieldWidth(0) << ':'; dbg.space(); dbg << r.field(i) << r.value(i).toString(); } diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp index ea410cd257..ce4232f3e8 100644 --- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -161,22 +161,22 @@ static QString moc(const QString &name) static QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost) { - ts << "/*" << endl - << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << endl - << " * Command line was: " << commandLine << endl - << " *" << endl - << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << endl - << " *" << endl - << " * This is an auto-generated file." << endl; + ts << "/*" << Qt::endl + << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << Qt::endl + << " * Command line was: " << commandLine << Qt::endl + << " *" << Qt::endl + << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << Qt::endl + << " *" << Qt::endl + << " * This is an auto-generated file." << Qt::endl; if (changesWillBeLost) - ts << " * Do not edit! All changes made to it will be lost." << endl; + ts << " * Do not edit! All changes made to it will be lost." << Qt::endl; else - ts << " * This file may have been hand-edited. Look for HAND-EDIT comments" << endl - << " * before re-generating it." << endl; + ts << " * This file may have been hand-edited. Look for HAND-EDIT comments" << Qt::endl + << " * before re-generating it." << Qt::endl; - ts << " */" << endl - << endl; + ts << " */" << Qt::endl + << Qt::endl; return ts; } @@ -466,66 +466,66 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf } includeGuard = QString(QLatin1String("%1")) .arg(includeGuard); - hs << "#ifndef " << includeGuard << endl - << "#define " << includeGuard << endl - << endl; + hs << "#ifndef " << includeGuard << Qt::endl + << "#define " << includeGuard << Qt::endl + << Qt::endl; // include our stuff: - hs << "#include " << endl + hs << "#include " << Qt::endl << includeList - << "#include " << endl; + << "#include " << Qt::endl; for (const QString &include : qAsConst(includes)) { - hs << "#include \"" << include << "\"" << endl; + hs << "#include \"" << include << "\"" << Qt::endl; if (headerName.isEmpty()) - cs << "#include \"" << include << "\"" << endl; + cs << "#include \"" << include << "\"" << Qt::endl; } - hs << endl; + hs << Qt::endl; if (cppName != headerName) { if (!headerName.isEmpty() && headerName != QLatin1String("-")) - cs << "#include \"" << headerName << "\"" << endl << endl; + cs << "#include \"" << headerName << "\"" << Qt::endl << Qt::endl; } for (const QDBusIntrospection::Interface *interface : interfaces) { QString className = classNameForInterface(interface->name, Proxy); // comment: - hs << "/*" << endl - << " * Proxy class for interface " << interface->name << endl - << " */" << endl; - cs << "/*" << endl - << " * Implementation of interface class " << className << endl - << " */" << endl - << endl; + hs << "/*" << Qt::endl + << " * Proxy class for interface " << interface->name << Qt::endl + << " */" << Qt::endl; + cs << "/*" << Qt::endl + << " * Implementation of interface class " << className << Qt::endl + << " */" << Qt::endl + << Qt::endl; // class header: - hs << "class " << className << ": public QDBusAbstractInterface" << endl - << "{" << endl - << " Q_OBJECT" << endl; + hs << "class " << className << ": public QDBusAbstractInterface" << Qt::endl + << "{" << Qt::endl + << " Q_OBJECT" << Qt::endl; // the interface name - hs << "public:" << endl - << " static inline const char *staticInterfaceName()" << endl - << " { return \"" << interface->name << "\"; }" << endl - << endl; + hs << "public:" << Qt::endl + << " static inline const char *staticInterfaceName()" << Qt::endl + << " { return \"" << interface->name << "\"; }" << Qt::endl + << Qt::endl; // constructors/destructors: - hs << "public:" << endl - << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);" << endl - << endl - << " ~" << className << "();" << endl - << endl; - cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << endl - << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << endl - << "{" << endl - << "}" << endl - << endl - << className << "::~" << className << "()" << endl - << "{" << endl - << "}" << endl - << endl; + hs << "public:" << Qt::endl + << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);" << Qt::endl + << Qt::endl + << " ~" << className << "();" << Qt::endl + << Qt::endl; + cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << Qt::endl + << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << Qt::endl + << "{" << Qt::endl + << "}" << Qt::endl + << Qt::endl + << className << "::~" << className << "()" << Qt::endl + << "{" << Qt::endl + << "}" << Qt::endl + << Qt::endl; // properties: for (const QDBusIntrospection::Property &property : interface->properties) { @@ -545,27 +545,27 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // it's writeable hs << " WRITE " << setter; - hs << ")" << endl; + hs << ")" << Qt::endl; // getter: if (property.access != QDBusIntrospection::Property::Write) { - hs << " inline " << type << " " << getter << "() const" << endl + hs << " inline " << type << " " << getter << "() const" << Qt::endl << " { return qvariant_cast< " << type << " >(property(\"" - << property.name << "\")); }" << endl; + << property.name << "\")); }" << Qt::endl; } // setter: if (property.access != QDBusIntrospection::Property::Read) { - hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << endl + hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << Qt::endl << " { setProperty(\"" << property.name - << "\", QVariant::fromValue(value)); }" << endl; + << "\", QVariant::fromValue(value)); }" << Qt::endl; } - hs << endl; + hs << Qt::endl; } // methods: - hs << "public Q_SLOTS: // METHODS" << endl; + hs << "public Q_SLOTS: // METHODS" << Qt::endl; for (const QDBusIntrospection::Method &method : interface->methods) { bool isDeprecated = method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true"); bool isNoReply = @@ -595,26 +595,26 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QStringList argNames = makeArgNames(method.inputArgs); writeArgList(hs, argNames, method.annotations, method.inputArgs); - hs << ")" << endl - << " {" << endl - << " QList argumentList;" << endl; + hs << ")" << Qt::endl + << " {" << Qt::endl + << " QList argumentList;" << Qt::endl; if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (int argPos = 0; argPos < method.inputArgs.count(); ++argPos) hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";" << endl; + hs << ";" << Qt::endl; } if (isNoReply) hs << " callWithArgumentList(QDBus::NoBlock, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << endl; + << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; else hs << " return asyncCallWithArgumentList(QStringLiteral(\"" - << method.name << "\"), argumentList);" << endl; + << method.name << "\"), argumentList);" << Qt::endl; // close the function: - hs << " }" << endl; + hs << " }" << Qt::endl; if (method.outputArgs.count() > 1) { // generate the old-form QDBusReply methods with multiple incoming parameters @@ -627,39 +627,39 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs); writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); - hs << ")" << endl - << " {" << endl - << " QList argumentList;" << endl; + hs << ")" << Qt::endl + << " {" << Qt::endl + << " QList argumentList;" << Qt::endl; int argPos = 0; if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (argPos = 0; argPos < method.inputArgs.count(); ++argPos) hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";" << endl; + hs << ";" << Qt::endl; } hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << endl; + << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; argPos++; hs << " if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == " - << method.outputArgs.count() << ") {" << endl; + << method.outputArgs.count() << ") {" << Qt::endl; // yes, starting from 1 for (int i = 1; i < method.outputArgs.count(); ++i) hs << " " << argNames.at(argPos++) << " = qdbus_cast<" << templateArg(qtTypeName(method.outputArgs.at(i).type, method.annotations, i, "Out")) - << ">(reply.arguments().at(" << i << "));" << endl; - hs << " }" << endl - << " return reply;" << endl - << " }" << endl; + << ">(reply.arguments().at(" << i << "));" << Qt::endl; + hs << " }" << Qt::endl + << " return reply;" << Qt::endl + << " }" << Qt::endl; } - hs << endl; + hs << Qt::endl; } - hs << "Q_SIGNALS: // SIGNALS" << endl; + hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; for (const QDBusIntrospection::Signal &signal : interface->signals_) { hs << " "; if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == @@ -671,12 +671,12 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QStringList argNames = makeArgNames(signal.outputArgs); writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - hs << ");" << endl; // finished for header + hs << ");" << Qt::endl; // finished for header } // close the class: - hs << "};" << endl - << endl; + hs << "};" << Qt::endl + << Qt::endl; } if (!skipNamespaces) { @@ -698,17 +698,17 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // i parts matched // close last.arguments().count() - i namespaces: for (int j = i; j < last.count(); ++j) - hs << QString((last.count() - j - 1 + i) * 2, QLatin1Char(' ')) << "}" << endl; + hs << QString((last.count() - j - 1 + i) * 2, QLatin1Char(' ')) << "}" << Qt::endl; // open current.arguments().count() - i namespaces for (int j = i; j < current.count(); ++j) - hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" << endl; + hs << QString(j * 2, QLatin1Char(' ')) << "namespace " << current.at(j) << " {" << Qt::endl; // add this class: if (!name.isEmpty()) { hs << QString(current.count() * 2, QLatin1Char(' ')) << "typedef ::" << classNameForInterface(it->constData()->name, Proxy) - << " " << name << ";" << endl; + << " " << name << ";" << Qt::endl; } if (it == interfaces.constEnd()) @@ -719,12 +719,12 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf } // close the include guard - hs << "#endif" << endl; + hs << "#endif" << Qt::endl; QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) - cs << endl - << "#include \"" << mocName << "\"" << endl; + cs << Qt::endl + << "#include \"" << mocName << "\"" << Qt::endl; cs.flush(); hs.flush(); @@ -772,36 +772,36 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte } includeGuard = QString(QLatin1String("%1")) .arg(includeGuard); - hs << "#ifndef " << includeGuard << endl - << "#define " << includeGuard << endl - << endl; + hs << "#ifndef " << includeGuard << Qt::endl + << "#define " << includeGuard << Qt::endl + << Qt::endl; // include our stuff: - hs << "#include " << endl; + hs << "#include " << Qt::endl; if (cppName == headerName) - hs << "#include " << endl - << "#include " << endl; - hs << "#include " << endl; + hs << "#include " << Qt::endl + << "#include " << Qt::endl; + hs << "#include " << Qt::endl; for (const QString &include : qAsConst(includes)) { - hs << "#include \"" << include << "\"" << endl; + hs << "#include \"" << include << "\"" << Qt::endl; if (headerName.isEmpty()) - cs << "#include \"" << include << "\"" << endl; + cs << "#include \"" << include << "\"" << Qt::endl; } if (cppName != headerName) { if (!headerName.isEmpty() && headerName != QLatin1String("-")) - cs << "#include \"" << headerName << "\"" << endl; + cs << "#include \"" << headerName << "\"" << Qt::endl; - cs << "#include " << endl + cs << "#include " << Qt::endl << includeList - << endl; + << Qt::endl; hs << forwardDeclarations; } else { hs << includeList; } - hs << endl; + hs << Qt::endl; QString parent = parentClassName; if (parentClassName.isEmpty()) @@ -811,47 +811,47 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte QString className = classNameForInterface(interface->name, Adaptor); // comment: - hs << "/*" << endl - << " * Adaptor class for interface " << interface->name << endl - << " */" << endl; - cs << "/*" << endl - << " * Implementation of adaptor class " << className << endl - << " */" << endl - << endl; + hs << "/*" << Qt::endl + << " * Adaptor class for interface " << interface->name << Qt::endl + << " */" << Qt::endl; + cs << "/*" << Qt::endl + << " * Implementation of adaptor class " << className << Qt::endl + << " */" << Qt::endl + << Qt::endl; // class header: - hs << "class " << className << ": public QDBusAbstractAdaptor" << endl - << "{" << endl - << " Q_OBJECT" << endl - << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << endl - << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << endl + hs << "class " << className << ": public QDBusAbstractAdaptor" << Qt::endl + << "{" << Qt::endl + << " Q_OBJECT" << Qt::endl + << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << Qt::endl + << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << Qt::endl << stringify(interface->introspection) - << " \"\")" << endl - << "public:" << endl - << " " << className << "(" << parent << " *parent);" << endl - << " virtual ~" << className << "();" << endl - << endl; + << " \"\")" << Qt::endl + << "public:" << Qt::endl + << " " << className << "(" << parent << " *parent);" << Qt::endl + << " virtual ~" << className << "();" << Qt::endl + << Qt::endl; if (!parentClassName.isEmpty()) - hs << " inline " << parent << " *parent() const" << endl - << " { return static_cast<" << parent << " *>(QObject::parent()); }" << endl - << endl; + hs << " inline " << parent << " *parent() const" << Qt::endl + << " { return static_cast<" << parent << " *>(QObject::parent()); }" << Qt::endl + << Qt::endl; // constructor/destructor - cs << className << "::" << className << "(" << parent << " *parent)" << endl - << " : QDBusAbstractAdaptor(parent)" << endl - << "{" << endl - << " // constructor" << endl - << " setAutoRelaySignals(true);" << endl - << "}" << endl - << endl - << className << "::~" << className << "()" << endl - << "{" << endl - << " // destructor" << endl - << "}" << endl - << endl; + cs << className << "::" << className << "(" << parent << " *parent)" << Qt::endl + << " : QDBusAbstractAdaptor(parent)" << Qt::endl + << "{" << Qt::endl + << " // constructor" << Qt::endl + << " setAutoRelaySignals(true);" << Qt::endl + << "}" << Qt::endl + << Qt::endl + << className << "::~" << className << "()" << Qt::endl + << "{" << Qt::endl + << " // destructor" << Qt::endl + << "}" << Qt::endl + << Qt::endl; - hs << "public: // PROPERTIES" << endl; + hs << "public: // PROPERTIES" << Qt::endl; for (const QDBusIntrospection::Property &property : interface->properties) { QByteArray type = qtTypeName(property.type, property.annotations); QString constRefType = constRefArg(type); @@ -863,38 +863,38 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte hs << " READ " << getter; if (property.access != QDBusIntrospection::Property::Read) hs << " WRITE " << setter; - hs << ")" << endl; + hs << ")" << Qt::endl; // getter: if (property.access != QDBusIntrospection::Property::Write) { - hs << " " << type << " " << getter << "() const;" << endl; + hs << " " << type << " " << getter << "() const;" << Qt::endl; cs << type << " " - << className << "::" << getter << "() const" << endl - << "{" << endl - << " // get the value of property " << property.name << endl - << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << endl - << "}" << endl - << endl; + << className << "::" << getter << "() const" << Qt::endl + << "{" << Qt::endl + << " // get the value of property " << property.name << Qt::endl + << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << Qt::endl + << "}" << Qt::endl + << Qt::endl; } // setter if (property.access != QDBusIntrospection::Property::Read) { - hs << " void " << setter << "(" << constRefType << "value);" << endl; - cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << endl - << "{" << endl - << " // set the value of property " << property.name << endl + hs << " void " << setter << "(" << constRefType << "value);" << Qt::endl; + cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << Qt::endl + << "{" << Qt::endl + << " // set the value of property " << property.name << Qt::endl << " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value"; if (constRefType.contains(QLatin1String("QDBusVariant"))) cs << ".variant()"; - cs << "));" << endl - << "}" << endl - << endl; + cs << "));" << Qt::endl + << "}" << Qt::endl + << Qt::endl; } - hs << endl; + hs << Qt::endl; } - hs << "public Q_SLOTS: // METHODS" << endl; + hs << "public Q_SLOTS: // METHODS" << Qt::endl; for (const QDBusIntrospection::Method &method : interface->methods) { bool isNoReply = method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); @@ -930,10 +930,10 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); writeArgList(cs, argNames, method.annotations, method.inputArgs, method.outputArgs); - hs << ");" << endl; // finished for header - cs << ")" << endl - << "{" << endl - << " // handle method call " << interface->name << "." << methodName(method) << endl; + hs << ");" << Qt::endl; // finished for header + cs << ")" << Qt::endl + << "{" << Qt::endl + << " // handle method call " << interface->name << "." << methodName(method) << Qt::endl; // make the call bool usingInvokeMethod = false; @@ -945,7 +945,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte // we are using QMetaObject::invokeMethod if (!returnType.isEmpty()) cs << " " << returnType << " " << argNames.at(method.inputArgs.count()) - << ";" << endl; + << ";" << Qt::endl; static const char invoke[] = " QMetaObject::invokeMethod(parent(), \""; cs << invoke << name << "\""; @@ -966,10 +966,10 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte << argNames.at(i) << ")"; - cs << ");" << endl; + cs << ");" << Qt::endl; if (!returnType.isEmpty()) - cs << " return " << argNames.at(method.inputArgs.count()) << ";" << endl; + cs << " return " << argNames.at(method.inputArgs.count()) << ";" << Qt::endl; } else { if (parentClassName.isEmpty()) cs << " //"; @@ -997,13 +997,13 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte first = false; } - cs << ");" << endl; + cs << ");" << Qt::endl; } - cs << "}" << endl - << endl; + cs << "}" << Qt::endl + << Qt::endl; } - hs << "Q_SIGNALS: // SIGNALS" << endl; + hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; for (const QDBusIntrospection::Signal &signal : interface->signals_) { hs << " "; if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == @@ -1015,21 +1015,21 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte QStringList argNames = makeArgNames(signal.outputArgs); writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - hs << ");" << endl; // finished for header + hs << ");" << Qt::endl; // finished for header } // close the class: - hs << "};" << endl - << endl; + hs << "};" << Qt::endl + << Qt::endl; } // close the include guard - hs << "#endif" << endl; + hs << "#endif" << Qt::endl; QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) - cs << endl - << "#include \"" << mocName << "\"" << endl; + cs << Qt::endl + << "#include \"" << mocName << "\"" << Qt::endl; cs.flush(); hs.flush(); diff --git a/src/tools/qlalr/cppgenerator.cpp b/src/tools/qlalr/cppgenerator.cpp index 508db696b1..10b2d173ab 100644 --- a/src/tools/qlalr/cppgenerator.cpp +++ b/src/tools/qlalr/cppgenerator.cpp @@ -43,7 +43,7 @@ void generateSeparator(int i, QTextStream &out) if (!(i % 10)) { if (i) out << ","; - out << endl << " "; + out << Qt::endl << " "; } else { out << ", "; } @@ -187,14 +187,14 @@ void CppGenerator::operator () () { if (verbose) qout() << "*** Warning. Found a reduce/reduce conflict in state " << q << " on token ``" << s << "'' between rule " - << r << " and " << -u << endl; + << r << " and " << -u << Qt::endl; ++reduce_reduce_conflict_count; u = qMax (u, -r); if (verbose) - qout() << "\tresolved using rule " << -u << endl; + qout() << "\tresolved using rule " << -u << Qt::endl; } else if (u > 0) @@ -227,7 +227,7 @@ void CppGenerator::operator () () ++shift_reduce_conflict_count; if (verbose) - qout() << "*** Warning. Found a shift/reduce conflict in state " << q << " on token ``" << s << "'' with rule " << r << endl; + qout() << "*** Warning. Found a shift/reduce conflict in state " << q << " on token ``" << s << "'' with rule " << r << Qt::endl; } } } @@ -238,11 +238,11 @@ void CppGenerator::operator () () { if (shift_reduce_conflict_count != grammar.expected_shift_reduce || reduce_reduce_conflict_count != grammar.expected_reduce_reduce) - qerr() << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << endl; + qerr() << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << Qt::endl; if (verbose) - qout() << endl << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << endl - << endl; + qout() << Qt::endl << "*** Conflicts: " << shift_reduce_conflict_count << " shift/reduce, " << reduce_reduce_conflict_count << " reduce/reduce" << Qt::endl + << Qt::endl; } QBitArray used_rules (grammar.rules.count ()); @@ -266,7 +266,7 @@ void CppGenerator::operator () () RulePointer rule = grammar.rules.begin () + i; if (rule != grammar.goal) - qerr() << "*** Warning: Rule ``" << *rule << "'' is useless!" << endl; + qerr() << "*** Warning: Rule ``" << *rule << "'' is useless!" << Qt::endl; } } @@ -348,26 +348,26 @@ void CppGenerator::operator () () { out << copyrightHeader() << privateCopyrightHeader() - << endl; + << Qt::endl; } out << "// This file was generated by qlalr - DO NOT EDIT!\n"; - out << startIncludeGuard(grammar.merged_output) << endl; + out << startIncludeGuard(grammar.merged_output) << Qt::endl; if (copyright) { - out << "#if defined(ERROR)" << endl - << "# undef ERROR" << endl - << "#endif" << endl << endl; + out << "#if defined(ERROR)" << Qt::endl + << "# undef ERROR" << Qt::endl + << "#endif" << Qt::endl << Qt::endl; } generateDecl (out); generateImpl (out); out << p.decls(); out << p.impls(); - out << endl; + out << Qt::endl; - out << endIncludeGuard(grammar.merged_output) << endl; + out << endIncludeGuard(grammar.merged_output) << Qt::endl; return; } @@ -388,24 +388,24 @@ void CppGenerator::operator () () { out << copyrightHeader() << privateCopyrightHeader() - << endl; + << Qt::endl; } out << "// This file was generated by qlalr - DO NOT EDIT!\n"; - out << "#ifndef " << prot << endl - << "#define " << prot << endl - << endl; + out << "#ifndef " << prot << Qt::endl + << "#define " << prot << Qt::endl + << Qt::endl; if (copyright) { - out << "#include " << endl << endl; - out << "QT_BEGIN_NAMESPACE" << endl << endl; + out << "#include " << Qt::endl << Qt::endl; + out << "QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl; } generateDecl (out); if (copyright) - out << "QT_END_NAMESPACE" << endl; + out << "QT_END_NAMESPACE" << Qt::endl; - out << "#endif // " << prot << endl << endl; + out << "#endif // " << prot << Qt::endl << Qt::endl; } // end decls { // bits... @@ -419,12 +419,12 @@ void CppGenerator::operator () () out << "// This file was generated by qlalr - DO NOT EDIT!\n"; - out << "#include \"" << declFileName << "\"" << endl << endl; + out << "#include \"" << declFileName << "\"" << Qt::endl << Qt::endl; if (copyright) - out << "QT_BEGIN_NAMESPACE" << endl << endl; + out << "QT_BEGIN_NAMESPACE" << Qt::endl << Qt::endl; generateImpl(out); if (copyright) - out << "QT_END_NAMESPACE" << endl; + out << "QT_END_NAMESPACE" << Qt::endl; } // end bits @@ -455,10 +455,10 @@ QString CppGenerator::debugInfoProt() const void CppGenerator::generateDecl (QTextStream &out) { - out << "class " << grammar.table_name << endl - << "{" << endl - << "public:" << endl - << " enum VariousConstants {" << endl; + out << "class " << grammar.table_name << Qt::endl + << "{" << Qt::endl + << "public:" << Qt::endl + << " enum VariousConstants {" << Qt::endl; for (const Name &t : qAsConst(grammar.terminals)) { @@ -474,62 +474,62 @@ void CppGenerator::generateDecl (QTextStream &out) else name.prepend (grammar.token_prefix); - out << " " << name << " = " << value << "," << endl; + out << " " << name << " = " << value << "," << Qt::endl; } - out << endl - << " ACCEPT_STATE = " << accept_state << "," << endl - << " RULE_COUNT = " << grammar.rules.size () << "," << endl - << " STATE_COUNT = " << state_count << "," << endl - << " TERMINAL_COUNT = " << terminal_count << "," << endl - << " NON_TERMINAL_COUNT = " << non_terminal_count << "," << endl - << endl - << " GOTO_INDEX_OFFSET = " << compressed_action.index.size () << "," << endl - << " GOTO_INFO_OFFSET = " << compressed_action.info.size () << "," << endl - << " GOTO_CHECK_OFFSET = " << compressed_action.check.size () << endl - << " };" << endl - << endl - << " static const char *const spell[];" << endl - << " static const short lhs[];" << endl - << " static const short rhs[];" << endl; + out << Qt::endl + << " ACCEPT_STATE = " << accept_state << "," << Qt::endl + << " RULE_COUNT = " << grammar.rules.size () << "," << Qt::endl + << " STATE_COUNT = " << state_count << "," << Qt::endl + << " TERMINAL_COUNT = " << terminal_count << "," << Qt::endl + << " NON_TERMINAL_COUNT = " << non_terminal_count << "," << Qt::endl + << Qt::endl + << " GOTO_INDEX_OFFSET = " << compressed_action.index.size () << "," << Qt::endl + << " GOTO_INFO_OFFSET = " << compressed_action.info.size () << "," << Qt::endl + << " GOTO_CHECK_OFFSET = " << compressed_action.check.size () << Qt::endl + << " };" << Qt::endl + << Qt::endl + << " static const char *const spell[];" << Qt::endl + << " static const short lhs[];" << Qt::endl + << " static const short rhs[];" << Qt::endl; if (debug_info) { QString prot = debugInfoProt(); - out << endl << "#ifndef " << prot << endl - << " static const int rule_index[];" << endl - << " static const int rule_info[];" << endl - << "#endif // " << prot << endl << endl; + out << Qt::endl << "#ifndef " << prot << Qt::endl + << " static const int rule_index[];" << Qt::endl + << " static const int rule_info[];" << Qt::endl + << "#endif // " << prot << Qt::endl << Qt::endl; } - out << " static const short goto_default[];" << endl - << " static const short action_default[];" << endl - << " static const short action_index[];" << endl - << " static const short action_info[];" << endl - << " static const short action_check[];" << endl - << endl - << " static inline int nt_action (int state, int nt)" << endl - << " {" << endl - << " const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;" << endl - << " if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)" << endl - << " return goto_default [nt];" << endl - << endl - << " return action_info [GOTO_INFO_OFFSET + yyn];" << endl - << " }" << endl - << endl - << " static inline int t_action (int state, int token)" << endl - << " {" << endl - << " const int yyn = action_index [state] + token;" << endl - << endl - << " if (yyn < 0 || action_check [yyn] != token)" << endl - << " return - action_default [state];" << endl - << endl - << " return action_info [yyn];" << endl - << " }" << endl - << "};" << endl - << endl - << endl; + out << " static const short goto_default[];" << Qt::endl + << " static const short action_default[];" << Qt::endl + << " static const short action_index[];" << Qt::endl + << " static const short action_info[];" << Qt::endl + << " static const short action_check[];" << Qt::endl + << Qt::endl + << " static inline int nt_action (int state, int nt)" << Qt::endl + << " {" << Qt::endl + << " const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;" << Qt::endl + << " if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)" << Qt::endl + << " return goto_default [nt];" << Qt::endl + << Qt::endl + << " return action_info [GOTO_INFO_OFFSET + yyn];" << Qt::endl + << " }" << Qt::endl + << Qt::endl + << " static inline int t_action (int state, int token)" << Qt::endl + << " {" << Qt::endl + << " const int yyn = action_index [state] + token;" << Qt::endl + << Qt::endl + << " if (yyn < 0 || action_check [yyn] != token)" << Qt::endl + << " return - action_default [state];" << Qt::endl + << Qt::endl + << " return action_info [yyn];" << Qt::endl + << " }" << Qt::endl + << "};" << Qt::endl + << Qt::endl + << Qt::endl; } void CppGenerator::generateImpl (QTextStream &out) @@ -568,16 +568,16 @@ void CppGenerator::generateImpl (QTextStream &out) { first_nt = false; QString prot = debugInfoProt(); - out << endl << "#ifndef " << prot << endl; + out << Qt::endl << "#ifndef " << prot << Qt::endl; } out << "\"" << *t << "\""; } } if (debug_info) - out << endl << "#endif // " << debugInfoProt() << endl; + out << Qt::endl << "#endif // " << debugInfoProt() << Qt::endl; - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::lhs [] = {"; idx = 0; @@ -587,7 +587,7 @@ void CppGenerator::generateImpl (QTextStream &out) out << aut.id (rule->lhs); } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::rhs [] = {"; idx = 0; @@ -597,13 +597,13 @@ void CppGenerator::generateImpl (QTextStream &out) out << rule->rhs.size (); } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; if (debug_info) { QString prot = debugInfoProt(); - out << endl << "#ifndef " << prot << endl; + out << Qt::endl << "#ifndef " << prot << Qt::endl; out << "const int " << grammar.table_name << "::rule_info [] = {"; idx = 0; for (auto rule = grammar.rules.cbegin (); rule != grammar.rules.cend (); ++rule, ++idx) @@ -615,7 +615,7 @@ void CppGenerator::generateImpl (QTextStream &out) for (const Name &n : rule->rhs) out << ", " << name_ids.value (n); } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const int " << grammar.table_name << "::rule_index [] = {"; idx = 0; @@ -627,8 +627,8 @@ void CppGenerator::generateImpl (QTextStream &out) out << offset; offset += rule->rhs.size () + 1; } - out << endl << "};" << endl - << "#endif // " << prot << endl << endl; + out << Qt::endl << "};" << Qt::endl + << "#endif // " << prot << Qt::endl << Qt::endl; } out << "const short " << grammar.table_name << "::action_default [] = {"; @@ -642,27 +642,27 @@ void CppGenerator::generateImpl (QTextStream &out) else out << "0"; } - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::goto_default [] = {"; generateList(defgoto, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::action_index [] = {"; generateList(compressed_action.index, out); - out << "," << endl; + out << "," << Qt::endl; generateList(compressed_goto.index, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::action_info [] = {"; generateList(compressed_action.info, out); - out << "," << endl; + out << "," << Qt::endl; generateList(compressed_goto.info, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; out << "const short " << grammar.table_name << "::action_check [] = {"; generateList(compressed_action.check, out); - out << "," << endl; + out << "," << Qt::endl; generateList(compressed_goto.check, out); - out << endl << "};" << endl << endl; + out << Qt::endl << "};" << Qt::endl << Qt::endl; } diff --git a/src/tools/qlalr/dotgraph.cpp b/src/tools/qlalr/dotgraph.cpp index 1fa0a1ac77..1d479af2b2 100644 --- a/src/tools/qlalr/dotgraph.cpp +++ b/src/tools/qlalr/dotgraph.cpp @@ -41,9 +41,9 @@ void DotGraph::operator () (Automaton *aut) { Grammar *g = aut->_M_grammar; - out << "digraph {" << endl << endl; + out << "digraph {" << Qt::endl << Qt::endl; - out << "subgraph Includes {" << endl; + out << "subgraph Includes {" << Qt::endl; for (Automaton::IncludesGraph::iterator incl = Automaton::IncludesGraph::begin_nodes (); incl != Automaton::IncludesGraph::end_nodes (); ++incl) { @@ -53,14 +53,14 @@ void DotGraph::operator () (Automaton *aut) out << "\t->\t"; out << "\"(" << aut->id ((*edge)->data.state) << ", " << (*edge)->data.nt << ")\"\t"; out << "[label=\"" << incl->data.state->follows [incl->data.nt] << "\"]"; - out << endl; + out << Qt::endl; } } - out << "}" << endl << endl; + out << "}" << Qt::endl << Qt::endl; - out << "subgraph LRA {" << endl; - //out << "node [shape=record];" << endl << endl; + out << "subgraph LRA {" << Qt::endl; + //out << "node [shape=record];" << Qt::endl << Qt::endl; for (StatePointer q = aut->states.begin (); q != aut->states.end (); ++q) { @@ -74,16 +74,16 @@ void DotGraph::operator () (Automaton *aut) for (ItemPointer item = q->kernel.begin (); item != q->kernel.end (); ++item) out << "| <" << index++ << "> " << *item; - out << "}\"]" << endl; + out << "}\"]" << Qt::endl; for (Bundle::iterator a = q->bundle.begin (); a != q->bundle.end (); ++a) { const char *clr = g->isTerminal (a.key ()) ? "blue" : "red"; - out << "\t" << state << "\t->\t" << aut->id (*a) << "\t[color=\"" << clr << "\",label=\"" << a.key () << "\"]" << endl; + out << "\t" << state << "\t->\t" << aut->id (*a) << "\t[color=\"" << clr << "\",label=\"" << a.key () << "\"]" << Qt::endl; } - out << endl; + out << Qt::endl; } - out << "}" << endl; - out << endl << endl << "}" << endl; + out << "}" << Qt::endl; + out << Qt::endl << Qt::endl << "}" << Qt::endl; } diff --git a/src/tools/qlalr/lalr.cpp b/src/tools/qlalr/lalr.cpp index ec960925aa..2a82eb154e 100644 --- a/src/tools/qlalr/lalr.cpp +++ b/src/tools/qlalr/lalr.cpp @@ -313,7 +313,7 @@ void Automaton::buildNullables () } #ifndef QLALR_NO_DEBUG_NULLABLES - qerr() << "nullables = {" << nullables << endl; + qerr() << "nullables = {" << nullables << Qt::endl; #endif } @@ -456,7 +456,7 @@ void Automaton::buildLookbackSets () lookbacks.insert (item, Lookback (p, A)); #ifndef QLALR_NO_DEBUG_LOOKBACKS - qerr() << "*** (" << id (q) << ", " << *rule << ") lookback (" << id (p) << ", " << *A << ")" << endl; + qerr() << "*** (" << id (q) << ", " << *rule << ") lookback (" << id (p) << ", " << *A << ")" << Qt::endl; #endif } } @@ -487,7 +487,7 @@ void Automaton::buildDirectReads () #ifndef QLALR_NO_DEBUG_DIRECT_READS for (QMap::iterator dr = q->reads.begin (); dr != q->reads.end (); ++dr) - qerr() << "*** DR(" << id (q) << ", " << dr.key () << ") = " << dr.value () << endl; + qerr() << "*** DR(" << id (q) << ", " << dr.key () << ") = " << dr.value () << Qt::endl; #endif } } @@ -520,7 +520,7 @@ void Automaton::buildReadsDigraph () dump (qerr(), source); qerr() << " reads "; dump (qerr(), target); - qerr() << endl; + qerr() << Qt::endl; #endif } } @@ -555,7 +555,7 @@ void Automaton::visitReadNode (ReadNode node) _M_reads_stack.push (node); #ifndef QLALR_NO_DEBUG_INCLUDES - // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl; + // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << Qt::endl; #endif for (ReadsGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge) @@ -635,7 +635,7 @@ void Automaton::buildIncludesDigraph () source->insertEdge (target); #ifndef QLALR_NO_DEBUG_INCLUDES - qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl; + qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << Qt::endl; #endif // QLALR_NO_DEBUG_INCLUDES continue; @@ -657,7 +657,7 @@ void Automaton::buildIncludesDigraph () source->insertEdge (target); #ifndef QLALR_NO_DEBUG_INCLUDES - qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl; + qerr() << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << Qt::endl; #endif // QLALR_NO_DEBUG_INCLUDES } } @@ -674,7 +674,7 @@ void Automaton::visitIncludeNode (IncludeNode node) _M_includes_stack.push (node); #ifndef QLALR_NO_DEBUG_INCLUDES - // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl; + // qerr() << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << Qt::endl; #endif for (IncludesGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge) @@ -690,7 +690,7 @@ void Automaton::visitIncludeNode (IncludeNode node) dump (qerr(), node); qerr() << " += follows"; dump (qerr(), r); - qerr() << endl; + qerr() << Qt::endl; #endif NameSet &dst = node->data.state->follows [node->data.nt]; @@ -726,7 +726,7 @@ void Automaton::buildLookaheads () #ifndef QLALR_NO_DEBUG_LOOKAHEADS qerr() << "(" << id (p) << ", " << *item->rule << ") lookbacks "; dump (qerr(), lookback); - qerr() << " with follows (" << id (q) << ", " << lookback.nt << ") = " << q->follows [lookback.nt] << endl; + qerr() << " with follows (" << id (q) << ", " << lookback.nt << ") = " << q->follows [lookback.nt] << Qt::endl; #endif lookaheads [item].insert (q->follows [lookback.nt].begin (), q->follows [lookback.nt].end ()); diff --git a/src/tools/qlalr/lalr.g b/src/tools/qlalr/lalr.g index 05d30c21fd..a849800dd5 100644 --- a/src/tools/qlalr/lalr.g +++ b/src/tools/qlalr/lalr.g @@ -261,7 +261,7 @@ int Recognizer::nextToken() if (ch == QLatin1Char ('"')) inp (); else - qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << Qt::endl; _M_current_value = text; return (token = STRING_LITERAL); @@ -314,7 +314,7 @@ int Recognizer::nextToken() return (token = PREC); else { - qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << Qt::endl; exit (EXIT_FAILURE); return (token = ERROR); } @@ -659,7 +659,7 @@ case $rule_number: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -683,7 +683,7 @@ case $rule_number: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -712,7 +712,7 @@ case $rule_number: { Name tok = _M_grammar->intern (sym(2)); if (! _M_grammar->isTerminal (tok)) { - qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << endl; + qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << Qt::endl; _M_current_rule->prec = _M_grammar->names.end (); } else @@ -758,7 +758,7 @@ case $rule_number: { } } - qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << Qt::endl; return false; } diff --git a/src/tools/qlalr/main.cpp b/src/tools/qlalr/main.cpp index 5971eb201d..a920b13c85 100644 --- a/src/tools/qlalr/main.cpp +++ b/src/tools/qlalr/main.cpp @@ -44,15 +44,15 @@ static void help_me () { - qerr() << "Usage: qlalr [options] [input file name]" << endl - << endl - << " --help, -h\t\tdisplay this help and exit" << endl - << " --verbose, -v\t\tverbose output" << endl - << " --no-debug\t\tno debug information" << endl - << " --no-lines\t\tno #line directives" << endl - << " --dot\t\t\tgenerate a graph" << endl - << " --qt\t\tadd the Qt copyright header and Qt-specific types and macros" << endl - << endl; + qerr() << "Usage: qlalr [options] [input file name]" << Qt::endl + << Qt::endl + << " --help, -h\t\tdisplay this help and exit" << Qt::endl + << " --verbose, -v\t\tverbose output" << Qt::endl + << " --no-debug\t\tno debug information" << Qt::endl + << " --no-lines\t\tno #line directives" << Qt::endl + << " --dot\t\t\tgenerate a graph" << Qt::endl + << " --qt\t\tadd the Qt copyright header and Qt-specific types and macros" << Qt::endl + << Qt::endl; exit (0); } @@ -91,7 +91,7 @@ int main (int argc, char *argv[]) file_name = arg; else - qerr() << "*** Warning. Ignore argument `" << arg << "'" << endl; + qerr() << "*** Warning. Ignore argument `" << arg << "'" << Qt::endl; } if (file_name.isEmpty ()) @@ -108,13 +108,13 @@ int main (int argc, char *argv[]) if (grammar.rules.isEmpty ()) { - qerr() << "*** Fatal. No rules!" << endl; + qerr() << "*** Fatal. No rules!" << Qt::endl; exit (EXIT_FAILURE); } else if (grammar.start == grammar.names.end ()) { - qerr() << "*** Fatal. No start symbol!" << endl; + qerr() << "*** Fatal. No start symbol!" << Qt::endl; exit (EXIT_FAILURE); } diff --git a/src/tools/qlalr/parsetable.cpp b/src/tools/qlalr/parsetable.cpp index c88ac1291e..9e71acebb4 100644 --- a/src/tools/qlalr/parsetable.cpp +++ b/src/tools/qlalr/parsetable.cpp @@ -43,13 +43,13 @@ void ParseTable::operator () (Automaton *aut) int rindex = 1; for (RulePointer rule = g->rules.begin (); rule != g->rules.end (); ++rule) - out << rindex++ << ")\t" << *rule << endl; - out << endl << endl; + out << rindex++ << ")\t" << *rule << Qt::endl; + out << Qt::endl << Qt::endl; int index = 0; for (StatePointer state = aut->states.begin (); state != aut->states.end (); ++state) { - out << "state " << index++ << endl << endl; + out << "state " << index++ << Qt::endl << Qt::endl; for (ItemPointer item = state->kernel.begin (); item != state->kernel.end (); ++item) { @@ -58,7 +58,7 @@ void ParseTable::operator () (Automaton *aut) if (item->dot == item->end_rhs ()) out << " " << aut->lookaheads [item]; - out << endl; + out << Qt::endl; } bool first = true; @@ -68,11 +68,11 @@ void ParseTable::operator () (Automaton *aut) continue; if (first) - out << endl; + out << Qt::endl; first = false; - out << " " << *arrow.key () << " shift, and go to state " << std::distance (aut->states.begin (), *arrow) << endl; + out << " " << *arrow.key () << " shift, and go to state " << std::distance (aut->states.begin (), *arrow) << Qt::endl; } first = true; @@ -82,13 +82,13 @@ void ParseTable::operator () (Automaton *aut) continue; if (first) - out << endl; + out << Qt::endl; first = false; const auto lookaheads = aut->lookaheads.value(item); for (const Name &la : lookaheads) - out << " " << *la << " reduce using rule " << aut->id (item->rule) << " (" << *item->rule->lhs << ")" << endl; + out << " " << *la << " reduce using rule " << aut->id (item->rule) << " (" << *item->rule->lhs << ")" << Qt::endl; } first = true; @@ -98,19 +98,19 @@ void ParseTable::operator () (Automaton *aut) continue; if (first) - out << endl; + out << Qt::endl; first = false; - out << " " << *arrow.key () << " go to state " << std::distance (aut->states.begin (), *arrow) << endl; + out << " " << *arrow.key () << " go to state " << std::distance (aut->states.begin (), *arrow) << Qt::endl; } if (state->defaultReduce != g->rules.end ()) { - out << endl - << " $default reduce using rule " << aut->id (state->defaultReduce) << " (" << *state->defaultReduce->lhs << ")" << endl; + out << Qt::endl + << " $default reduce using rule " << aut->id (state->defaultReduce) << " (" << *state->defaultReduce->lhs << ")" << Qt::endl; } - out << endl; + out << Qt::endl; } } diff --git a/src/tools/qlalr/recognizer.cpp b/src/tools/qlalr/recognizer.cpp index ab797c85d0..3da54c0c6a 100644 --- a/src/tools/qlalr/recognizer.cpp +++ b/src/tools/qlalr/recognizer.cpp @@ -97,7 +97,7 @@ int Recognizer::nextToken() if (ch == QLatin1Char ('"')) inp (); else - qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Warning. Expected `\"'" << Qt::endl; _M_current_value = text; return (token = STRING_LITERAL); @@ -150,7 +150,7 @@ int Recognizer::nextToken() return (token = PREC); else { - qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Unknown keyword `" << text << "'" << Qt::endl; exit (EXIT_FAILURE); return (token = ERROR); } @@ -405,7 +405,7 @@ case 34: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -420,7 +420,7 @@ case 38: { if (_M_grammar->terminals.find (_M_current_rule->lhs) != _M_grammar->terminals.end ()) { - qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Invalid non terminal `" << *_M_current_rule->lhs << "'" << Qt::endl; return false; } @@ -443,7 +443,7 @@ case 40: { Name tok = _M_grammar->intern (sym(2)); if (! _M_grammar->isTerminal (tok)) { - qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << endl; + qerr() << _M_input_file << ":" << _M_line << ": `" << *tok << " is not a terminal symbol" << Qt::endl; _M_current_rule->prec = _M_grammar->names.end (); } else @@ -474,7 +474,7 @@ case 43: { } } - qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << endl; + qerr() << _M_input_file << ":" << _M_line << ": Syntax error" << Qt::endl; return false; } diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index b8ff91f354..a1ff26ba04 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -1626,7 +1626,7 @@ QString WriteInitialization::writeFontProperties(const DomFont *f) } if (f->hasElementWeight() && f->elementWeight() > 0) { m_output << m_indent << fontName << ".setWeight(" - << f->elementWeight() << ");" << endl; + << f->elementWeight() << ");" << Qt::endl; } if (f->hasElementStrikeOut()) { m_output << m_indent << fontName << ".setStrikeOut(" @@ -2614,7 +2614,7 @@ static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet &directives) @@ -2622,7 +2622,7 @@ static void generateMultiDirectiveEnd(QTextStream &outputStream, const QSetisWindow()) debug << ", window"; debug << ", " << geometry.width() << 'x' << geometry.height() - << forcesign << geometry.x() << geometry.y() << noforcesign; + << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign; if (frameGeometry != geometry) { const QMargins margins(geometry.x() - frameGeometry.x(), geometry.y() - frameGeometry.y(), @@ -13190,7 +13190,7 @@ QDebug operator<<(QDebug debug, const QWidget *widget) } debug << ", devicePixelRatio=" << widget->devicePixelRatioF(); if (const WId wid = widget->internalWinId()) - debug << ", winId=0x" << hex << wid << dec; + debug << ", winId=0x" << Qt::hex << wid << Qt::dec; } debug << ')'; } else { diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp index de838a8f93..4e251de501 100644 --- a/src/widgets/widgets/qsplitter.cpp +++ b/src/widgets/widgets/qsplitter.cpp @@ -1793,7 +1793,7 @@ void QSplitter::setStretchFactor(int index, int stretch) QTextStream& operator<<(QTextStream& ts, const QSplitter& splitter) { - ts << splitter.saveState() << endl; + ts << splitter.saveState() << Qt::endl; return ts; } diff --git a/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp b/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp index 2d18e0e537..f7d81f676f 100644 --- a/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp +++ b/src/xml/doc/snippets/code/src_xml_dom_qdom.cpp @@ -74,7 +74,7 @@ QDomNode n = d.firstChild(); while (!n.isNull()) { if (n.isElement()) { QDomElement e = n.toElement(); - cout << "Element name: " << e.tagName() << endl; + cout << "Element name: " << e.tagName() << Qt::endl; break; } n = n.nextSibling(); @@ -126,10 +126,10 @@ QDomElement element4 = document.createElement("MyElement"); QDomElement e = //... //... QDomAttr a = e.attributeNode("href"); -cout << a.value() << endl; // prints "http://qt-project.org" +cout << a.value() << Qt::endl; // prints "http://qt-project.org" a.setValue("http://qt-project.org/doc"); // change the node's attribute QDomAttr a2 = e.attributeNode("href"); -cout << a2.value() << endl; // prints "http://qt-project.org/doc" +cout << a2.value() << Qt::endl; // prints "http://qt-project.org/doc" //! [8] @@ -201,7 +201,7 @@ QDomNode n = docElem.firstChild(); while(!n.isNull()) { QDomElement e = n.toElement(); // try to convert the node to an element. if(!e.isNull()) { - cout << qPrintable(e.tagName()) << endl; // the node really is an element. + cout << qPrintable(e.tagName()) << Qt::endl; // the node really is an element. } n = n.nextSibling(); } diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index cffc1974af..fedd53f3a9 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -3598,7 +3598,7 @@ void QDomDocumentTypePrivate::save(QTextStream& s, int, int indent) const } if (entities->length()>0 || notations->length()>0) { - s << " [" << endl; + s << " [" << Qt::endl; QHash::const_iterator it2 = notations->map.constBegin(); for (; it2 != notations->map.constEnd(); ++it2) @@ -3611,7 +3611,7 @@ void QDomDocumentTypePrivate::save(QTextStream& s, int, int indent) const s << ']'; } - s << '>' << endl; + s << '>' << Qt::endl; } /************************************************************** @@ -4627,7 +4627,7 @@ void QDomElementPrivate::save(QTextStream& s, int depth, int indent) const /* -1 disables new lines. */ if (indent != -1) - s << endl; + s << Qt::endl; } QDomNodePrivate::save(s, depth + 1, indent); if (!last->isText()) s << QString(indent < 1 ? 0 : depth * indent, QLatin1Char(' ')); @@ -4639,7 +4639,7 @@ void QDomElementPrivate::save(QTextStream& s, int depth, int indent) const if (!(next && next->isText())) { /* -1 disables new lines. */ if (indent != -1) - s << endl; + s << Qt::endl; } } @@ -5329,7 +5329,7 @@ void QDomCommentPrivate::save(QTextStream& s, int depth, int indent) const s << "-->"; if (!(next && next->isText())) - s << endl; + s << Qt::endl; } /************************************************************** @@ -5552,7 +5552,7 @@ void QDomNotationPrivate::save(QTextStream& s, int, int) const } else { s << "SYSTEM " << quotedValue(m_sys); } - s << '>' << endl; + s << '>' << Qt::endl; } /************************************************************** @@ -5733,7 +5733,7 @@ void QDomEntityPrivate::save(QTextStream& s, int, int) const _name = QLatin1String("% ") + _name.mid(1); if (m_sys.isNull() && m_pub.isNull()) { - s << "" << endl; + s << "" << Qt::endl; } else { s << "' << endl; + s << '>' << Qt::endl; } } @@ -6014,7 +6014,7 @@ QDomNodePrivate* QDomProcessingInstructionPrivate::cloneNode(bool deep) void QDomProcessingInstructionPrivate::save(QTextStream& s, int, int) const { - s << "" << endl; + s << "" << Qt::endl; } /************************************************************** From 415c435d605827cf4f4d9d0f723ed27c9b6baba5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 12:53:42 +0200 Subject: [PATCH 046/122] Compile when bumping the Qt version to 6.0 Change-Id: Idae1a2df144598df3921ef9a12e0e0b740fd723d Reviewed-by: Allan Sandfeld Jensen --- src/corelib/serialization/qxmlstream.cpp | 12 +++++++++++- src/corelib/serialization/qxmlstream.h | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index 0170be7602..d43d9c4e14 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -2285,12 +2285,14 @@ QXmlStreamAttribute::QXmlStreamAttribute() m_isDefault = false; } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! Destructs an attribute. */ QXmlStreamAttribute::~QXmlStreamAttribute() { } +#endif /*! Constructs an attribute in the namespace described with \a namespaceUri with \a name and value \a value. @@ -2366,6 +2368,7 @@ QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QSt */ +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! Creates a copy of \a other. */ @@ -2386,7 +2389,7 @@ QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &o m_isDefault = other.m_isDefault; return *this; } - +#endif /*! \class QXmlStreamAttributes @@ -2442,6 +2445,8 @@ QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &o QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration() { } + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! Creates a copy of \a other. */ @@ -2467,6 +2472,7 @@ Destructs this notation declaration. QXmlStreamNotationDeclaration::~QXmlStreamNotationDeclaration() { } +#endif /*! \fn QStringRef QXmlStreamNotationDeclaration::name() const @@ -2539,6 +2545,7 @@ QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QString &pr m_namespaceUri = namespaceUri; } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! Creates a copy of \a other. */ @@ -2562,6 +2569,7 @@ Destructs this namespace declaration. QXmlStreamNamespaceDeclaration::~QXmlStreamNamespaceDeclaration() { } +#endif /*! \fn QStringRef QXmlStreamNamespaceDeclaration::prefix() const @@ -2609,6 +2617,7 @@ QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration() { } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! Creates a copy of \a other. */ @@ -2636,6 +2645,7 @@ QXmlStreamEntityDeclaration& QXmlStreamEntityDeclaration::operator=(const QXmlSt QXmlStreamEntityDeclaration::~QXmlStreamEntityDeclaration() { } +#endif /*! \fn QXmlStreamStringRef::swap(QXmlStreamStringRef &other) \since 5.6 diff --git a/src/corelib/serialization/qxmlstream.h b/src/corelib/serialization/qxmlstream.h index 55dcc4e4e8..7d0aa64570 100644 --- a/src/corelib/serialization/qxmlstream.h +++ b/src/corelib/serialization/qxmlstream.h @@ -104,8 +104,8 @@ class Q_CORE_EXPORT QXmlStreamAttribute { public: QXmlStreamAttribute(); QXmlStreamAttribute(const QString &qualifiedName, const QString &value); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QXmlStreamAttribute(const QXmlStreamAttribute &); QXmlStreamAttribute(QXmlStreamAttribute &&other) noexcept // = default; : m_name(std::move(other.m_name)), @@ -191,6 +191,7 @@ class Q_CORE_EXPORT QXmlStreamNamespaceDeclaration { friend class QXmlStreamReaderPrivate; public: QXmlStreamNamespaceDeclaration(); + QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QXmlStreamNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &); QXmlStreamNamespaceDeclaration(QXmlStreamNamespaceDeclaration &&other) noexcept // = default @@ -207,7 +208,6 @@ public: qSwap(reserved, other.reserved); return *this; } - QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri); ~QXmlStreamNamespaceDeclaration(); QXmlStreamNamespaceDeclaration& operator=(const QXmlStreamNamespaceDeclaration &); #endif // < Qt 6 From a08c0ca94974142af77ec30eee715a5eb9a2faf5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 13:25:33 +0200 Subject: [PATCH 047/122] Prepare QDataStream for Qt 6.0 Add the required datastream versions for 6.0. Of course the number for 5.15 and 6.0 is still something we can bump. Change-Id: I676385817befc06ea8d0ff1e9eba9c94cb4698b0 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/serialization/qdatastream.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h index 2acf7d8c4b..60d429d707 100644 --- a/src/corelib/serialization/qdatastream.h +++ b/src/corelib/serialization/qdatastream.h @@ -102,9 +102,17 @@ public: Qt_5_13 = 19, Qt_5_14 = Qt_5_13, #if QT_VERSION >= 0x050f00 + Qt_5_15 = Qt_5_14, + Qt_DefaultCompiledVersion = Qt_5_15 +#elif QT_VERSION >= 0x060000 + Qt_6_0 = Qt_5_15, + Qt_DefaultCompiledVersion = Qt_6_0 +#else + Qt_DefaultCompiledVersion = Qt_5_14 +#endif +#if QT_VERSION >= 0x060100 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif - Qt_DefaultCompiledVersion = Qt_5_14 }; enum ByteOrder { From 93d3248ed0c81cbe162781a3fac1243c774a7574 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:13:06 +0200 Subject: [PATCH 048/122] Compile for Qt 6 Change-Id: I3069081d1c706980a8133b06d46588c4310cb304 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/kernel/qobject.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 73b655cb36..eaf35adb90 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4031,6 +4031,7 @@ static void dumpRecursive(int level, const QObject *object) } } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! \overload \obsolete @@ -4044,6 +4045,7 @@ void QObject::dumpObjectTree() { const_cast(this)->dumpObjectTree(); } +#endif /*! Dumps a tree of children to the debug output. @@ -4058,6 +4060,7 @@ void QObject::dumpObjectTree() const dumpRecursive(0, this); } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) /*! \overload \obsolete @@ -4072,6 +4075,7 @@ void QObject::dumpObjectInfo() { const_cast(this)->dumpObjectInfo(); } +#endif /*! Dumps information about signal connections, etc. for this object From 857a83259d8f1cfe7d3673c15f5a3436be89b432 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:42:55 +0200 Subject: [PATCH 049/122] Compile with Qt 6 Change-Id: Ie45f4dc6d44723c8992872e6c4c2e30d7257ca0c Reviewed-by: Allan Sandfeld Jensen --- src/gui/image/qimagereader.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 61f20e0c65..ae433ff651 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -1115,8 +1115,10 @@ bool QImageReader::autoTransform() const case QImageReaderPrivate::DoNotApplyTransform: return false; case QImageReaderPrivate::UsePluginDefault: +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) if (d->initHandler()) return d->handler->supportsOption(QImageIOHandler::TransformedByDefault); +#endif Q_FALLTHROUGH(); default: break; From c7a5cdb98ca4694fa8364c79b5cf53adf7bf19b9 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:43:05 +0200 Subject: [PATCH 050/122] Compile with Qt 6 Change-Id: I2cd5f93d01b2a7645bf6bccede484fc301209007 Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qtransform.cpp | 8 ++++++++ src/gui/painting/qtransform.h | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 6110a548fd..7696da7d45 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -265,7 +265,9 @@ QTransform::QTransform() , m_13(0), m_23(0), m_33(1) , m_type(TxNone) , m_dirty(TxNone) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } @@ -284,7 +286,9 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h13, , m_13(h13), m_23(h23), m_33(h33) , m_type(TxNone) , m_dirty(TxProject) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } @@ -301,7 +305,9 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h21, , m_13(0), m_23(0), m_33(1) , m_type(TxNone) , m_dirty(TxShear) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } @@ -317,7 +323,9 @@ QTransform::QTransform(const QMatrix &mtx) m_13(0), m_23(0), m_33(1) , m_type(TxNone) , m_dirty(TxShear) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index 18c53f4a6f..b220770144 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -176,7 +176,9 @@ private: , m_13(h13), m_23(h23), m_33(h33) , m_type(TxNone) , m_dirty(TxProject) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } inline QTransform(bool) @@ -184,7 +186,9 @@ private: , m_13(0), m_23(0), m_33(1) , m_type(TxNone) , m_dirty(TxNone) +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , d(nullptr) +#endif { } inline TransformationType inline_type() const; From 1e4042d03f798aa088fea5d340342d56363d07ca Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:43:13 +0200 Subject: [PATCH 051/122] Compile with Qt 6 Change-Id: I6d8d562a871a2f49db5db8630a08f53a14c0f7d3 Reviewed-by: Allan Sandfeld Jensen --- src/sql/models/qsqltablemodel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 98d6ddf882..11d30ab2e8 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -50,6 +50,7 @@ #include "qsqltablemodel_p.h" #include +#include QT_BEGIN_NAMESPACE @@ -611,7 +612,7 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in /*! \reimp */ -bool QStringListModel::clearItemData(const QModelIndex &index) +bool QSqlTableModel::clearItemData(const QModelIndex &index) { return setData(index, QVariant(), Qt::EditRole); } From 9c04e7c61ebc87904c0fc40d5e421e862b406a58 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:57:31 +0200 Subject: [PATCH 052/122] Fix API for Qt 6 Change-Id: Ic07b5cf09ed410a27ca95f106747f98de4d86d68 Reviewed-by: Allan Sandfeld Jensen --- src/widgets/kernel/qwidget.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h index aec3eee639..e47deb5d0d 100644 --- a/src/widgets/kernel/qwidget.h +++ b/src/widgets/kernel/qwidget.h @@ -555,7 +555,7 @@ public: void addAction(QAction *action); #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) void addActions(const QList &actions); - void insertActions(const QAction *before, const QList &actions); + void insertActions(QAction *before, const QList &actions); #else void addActions(QList actions); void insertActions(QAction *before, QList actions); From 91b3099d713b25367aafaf0aa8b719b7bd316155 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 15:19:19 +0200 Subject: [PATCH 053/122] Compile with Qt 6 Change-Id: I6efa420acab070e625f99b49eee08076d4a6a9ff Reviewed-by: Allan Sandfeld Jensen --- src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp index b1ce39f363..f86bedbdcd 100644 --- a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp +++ b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp @@ -2017,7 +2017,7 @@ QImage QX11PlatformPixmap::toImage(const QXImageWrapper &xiWrapper, const QRect } } else if (xi->bits_per_pixel == d) { // compatible depth char *xidata = xi->data; // copy each scanline - int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line); + int bpl = qMin(int(image.bytesPerLine()),xi->bytes_per_line); for (int y=0; yheight; y++) { memcpy(image.scanLine(y), xidata, bpl); xidata += xi->bytes_per_line; From 936632c9c1e92de899bb17596a66167e8d515bc4 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 2 May 2019 11:46:32 +0200 Subject: [PATCH 054/122] QList: fix regression in swapItemsAt Commit e0d2b50249839d10ecf87abc296b8020046d1d75 makes swapItemsAt use ADL to find swap(). Problem is, QList has a swap() function (that swaps the elements at the specificed _indices_); that function will be found before ADL kicks in. So do the second best thing: use qSwap instead. Change-Id: Icf2b4e3ce09117e4056acbad3e2d8a625861d807 Reviewed-by: Lars Knoll --- src/corelib/tools/qlist.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 59578b1e61..b916dcfd24 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -707,8 +707,7 @@ inline void QList::swapItemsAt(int i, int j) Q_ASSERT_X(i >= 0 && i < p.size() && j >= 0 && j < p.size(), "QList::swap", "index out of range"); detach(); - using std::swap; - swap(d->array[d->begin + i], d->array[d->begin + j]); + qSwap(d->array[d->begin + i], d->array[d->begin + j]); } template From 884dc0be7f85e08d2f25d48d728db69b9557ce04 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Mon, 29 Apr 2019 12:14:22 +0200 Subject: [PATCH 055/122] Remove redundant file from tests Change-Id: Icb398f1ba32dd1cc3a1e042818750c253539fae3 Reviewed-by: Lars Knoll --- .../xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak diff --git a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak b/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak deleted file mode 100644 index 2d80c8f3fb..0000000000 --- a/tests/auto/xml/sax/qxmlsimplereader/xmldocs/valid/sa/089.xml.bak +++ /dev/null @@ -1,5 +0,0 @@ - - -]> -&e; From 0d39cf6865301c96b69cfdc0df587f5962252e8e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 2 May 2019 11:55:36 +0200 Subject: [PATCH 056/122] QTextMarkdownImporter: Fix deprecation warning Use QTextCharFormat::setAnchorNames(), fixing: text/qtextmarkdownimporter.cpp:322:36: warning: 'void QTextCharFormat::setAnchorName(const QString&)' is deprecated: Use setAnchorNames() instead [-Wdeprecated-declarations] Amends 65314b6ce88cdbb28a22be0cab9856ec9bc9604b. Task-number: QTBUG-72349 Change-Id: I7f909d1fcc5c4045c738b5a5c491b2ac1de6eac5 Reviewed-by: Shawn Rutledge --- src/gui/text/qtextmarkdownimporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index 2477e0bc74..bcb0b777d4 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -319,7 +319,7 @@ int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) QString url = QString::fromLatin1(detail->href.text, detail->href.size); QString title = QString::fromLatin1(detail->title.text, detail->title.size); charFmt.setAnchorHref(url); - charFmt.setAnchorName(title); + charFmt.setAnchorNames(QStringList(title)); charFmt.setForeground(m_palette.link()); qCDebug(lcMD) << "anchor" << url << title; } break; From 1b16f79bf2a4efa5c8f60ae48adbf563fa819611 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 2 May 2019 18:14:20 +0200 Subject: [PATCH 057/122] QSharedData: delete the copy assignment operator Do not merely declare it as private, use C++11's = delete. This has the nice side effect that subclasses are no longer implicitly copy assignable either (they shouldn't be). Change-Id: Icd03f71006c31baf7d079365fa3bea1a2a9d559b Reviewed-by: Thiago Macieira --- src/corelib/tools/qshareddata.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 04051472d6..c29a509209 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -60,9 +60,8 @@ public: inline QSharedData() : ref(0) { } inline QSharedData(const QSharedData &) : ref(0) { } -private: // using the assignment operator would lead to corruption in the ref-counting - QSharedData &operator=(const QSharedData &); + QSharedData &operator=(const QSharedData &) = delete; }; template class QSharedDataPointer From fe57936d8c6e1bdafea5ba3260cc05c137a88ead Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Sat, 27 Apr 2019 22:10:17 +0200 Subject: [PATCH 058/122] qIsNull: redo implementation The reason for using type-punning through an integer was to avoid compiler warnings about float comparisons. We have now a better mechanism to suppress such warnings, so there is no need to be "clever" and trigger UB because of the union usage. Drive-by change: add constexpr+noexcept because now there's no longer UB. Change-Id: I29f7514e39055658d4ef6c431daf5abfc660df16 Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- src/corelib/global/qglobal.h | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 4817acb48f..a1f191516a 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -902,38 +902,22 @@ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qFuzzyIsNul return qAbs(f) <= 0.00001f; } -/* - This function tests a double for a null value. It doesn't - check whether the actual value is 0 or close to 0, but whether - it is binary 0, disregarding sign. -*/ -Q_REQUIRED_RESULT static inline Q_DECL_UNUSED bool qIsNull(double d) +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wfloat-equal") +QT_WARNING_DISABLE_GCC("-Wfloat-equal") + +Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qIsNull(double d) noexcept { - union U { - double d; - quint64 u; - }; - U val; - val.d = d; - return (val.u & Q_UINT64_C(0x7fffffffffffffff)) == 0; + return d == 0.0; } -/* - This function tests a float for a null value. It doesn't - check whether the actual value is 0 or close to 0, but whether - it is binary 0, disregarding sign. -*/ -Q_REQUIRED_RESULT static inline Q_DECL_UNUSED bool qIsNull(float f) +Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qIsNull(float f) noexcept { - union U { - float f; - quint32 u; - }; - U val; - val.f = f; - return (val.u & 0x7fffffff) == 0; + return f == 0.0f; } +QT_WARNING_POP + /* Compilers which follow outdated template instantiation rules require a class to have a comparison operator to exist when From 78a7e54f8f5c4ca6ce1ee6b0ac82c42b21738ac5 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 3 Dec 2018 16:03:17 +0100 Subject: [PATCH 059/122] Custom color-space based on chromaticities Change-Id: I7fa6efa8993aa2b79ea60b6a21bf57c4f67a120f Reviewed-by: Eirik Aavitsland --- src/gui/painting/qcolormatrix_p.h | 45 ++++- src/gui/painting/qcolorspace.cpp | 155 +++++++++++++++--- src/gui/painting/qcolorspace.h | 3 + src/gui/painting/qcolorspace_p.h | 26 +++ .../painting/qcolorspace/tst_qcolorspace.cpp | 68 ++++++++ 5 files changed, 269 insertions(+), 28 deletions(-) diff --git a/src/gui/painting/qcolormatrix_p.h b/src/gui/painting/qcolormatrix_p.h index 3d1dca6222..66db95df7e 100644 --- a/src/gui/painting/qcolormatrix_p.h +++ b/src/gui/painting/qcolormatrix_p.h @@ -52,6 +52,7 @@ // #include +#include #include QT_BEGIN_NAMESPACE @@ -61,7 +62,13 @@ class QColorVector { public: QColorVector() = default; - constexpr QColorVector(float x, float y, float z) : x(x), y(y), z(z), _unused(0.0f) { } + Q_DECL_CONSTEXPR QColorVector(float x, float y, float z) : x(x), y(y), z(z), _unused(0.0f) { } + explicit Q_DECL_CONSTEXPR QColorVector(const QPointF &chr) // from XY chromaticity + : x(chr.x() / chr.y()) + , y(1.0f) + , z((1.0 - chr.x() - chr.y()) / chr.y()) + , _unused(0.0f) + { } float x; // X, x or red float y; // Y, y or green float z; // Z, Y or blue @@ -69,11 +76,28 @@ public: friend inline bool operator==(const QColorVector &v1, const QColorVector &v2); friend inline bool operator!=(const QColorVector &v1, const QColorVector &v2); + bool isNull() const + { + return !x && !y && !z; + } - static constexpr QColorVector null() { return QColorVector(0.0f, 0.0f, 0.0f); } - // Common whitepoints on normalized XYZ form: - static constexpr QColorVector D50() { return QColorVector(0.96421f, 1.0f, 0.82519f); } - static constexpr QColorVector D65() { return QColorVector(0.95043f, 1.0f, 1.08890f); } + static Q_DECL_CONSTEXPR QColorVector null() { return QColorVector(0.0f, 0.0f, 0.0f); } + static bool isValidChromaticity(const QPointF &chr) + { + if (chr.x() < qreal(0.0) || chr.x() > qreal(1.0)) + return false; + if (chr.y() <= qreal(0.0) || chr.y() > qreal(1.0)) + return false; + if (chr.x() + chr.y() > qreal(1.0)) + return false; + return true; + } + + // Common whitepoints: + static Q_DECL_CONSTEXPR QPointF D50Chromaticity() { return QPointF(0.34567, 0.35850); } + static Q_DECL_CONSTEXPR QPointF D65Chromaticity() { return QPointF(0.31271, 0.32902); } + static Q_DECL_CONSTEXPR QColorVector D50() { return QColorVector(D50Chromaticity()); } + static Q_DECL_CONSTEXPR QColorVector D65() { return QColorVector(D65Chromaticity()); } }; inline bool operator==(const QColorVector &v1, const QColorVector &v2) @@ -102,6 +126,10 @@ public: friend inline bool operator==(const QColorMatrix &m1, const QColorMatrix &m2); friend inline bool operator!=(const QColorMatrix &m1, const QColorMatrix &m2); + bool isNull() const + { + return r.isNull() && g.isNull() && b.isNull(); + } bool isValid() const { // A color matrix must be invertible @@ -167,6 +195,13 @@ public: { return { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } }; } + static QColorMatrix fromScale(QColorVector v) + { + return QColorMatrix { { v.x, 0.0f, 0.0f }, + { 0.0f, v.y, 0.0f }, + { 0.0f, 0.0f, v.z } }; + } + // These are used to recognize matrices from ICC profiles: static QColorMatrix toXyzFromSRgb() { return QColorMatrix { { 0.4360217452f, 0.2224751115f, 0.0139281144f }, diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp index 24785f7b61..c98c31fe05 100644 --- a/src/gui/painting/qcolorspace.cpp +++ b/src/gui/painting/qcolorspace.cpp @@ -53,6 +53,102 @@ QT_BEGIN_NAMESPACE +QColorSpacePrimaries::QColorSpacePrimaries(QColorSpace::Gamut gamut) +{ + switch (gamut) { + case QColorSpace::Gamut::SRgb: + redPoint = QPointF(0.640, 0.330); + greenPoint = QPointF(0.300, 0.600); + bluePoint = QPointF(0.150, 0.060); + whitePoint = QColorVector::D65Chromaticity(); + break; + case QColorSpace::Gamut::DciP3D65: + redPoint = QPointF(0.680, 0.320); + greenPoint = QPointF(0.265, 0.690); + bluePoint = QPointF(0.150, 0.060); + whitePoint = QColorVector::D65Chromaticity(); + break; + case QColorSpace::Gamut::Bt2020: + redPoint = QPointF(0.708, 0.292); + greenPoint = QPointF(0.190, 0.797); + bluePoint = QPointF(0.131, 0.046); + whitePoint = QColorVector::D65Chromaticity(); + break; + case QColorSpace::Gamut::AdobeRgb: + redPoint = QPointF(0.640, 0.330); + greenPoint = QPointF(0.210, 0.710); + bluePoint = QPointF(0.150, 0.060); + whitePoint = QColorVector::D65Chromaticity(); + break; + case QColorSpace::Gamut::ProPhotoRgb: + redPoint = QPointF(0.7347, 0.2653); + greenPoint = QPointF(0.1596, 0.8404); + bluePoint = QPointF(0.0366, 0.0001); + whitePoint = QColorVector::D50Chromaticity(); + break; + default: + Q_UNREACHABLE(); + } +} + +bool QColorSpacePrimaries::areValid() const +{ + if (!QColorVector::isValidChromaticity(redPoint)) + return false; + if (!QColorVector::isValidChromaticity(greenPoint)) + return false; + if (!QColorVector::isValidChromaticity(bluePoint)) + return false; + if (!QColorVector::isValidChromaticity(whitePoint)) + return false; + return true; +} + +QColorMatrix QColorSpacePrimaries::toXyzMatrix() const +{ + // This converts to XYZ in some undefined scale. + QColorMatrix toXyz = { QColorVector(redPoint), + QColorVector(greenPoint), + QColorVector(bluePoint) }; + + // Since the white point should be (1.0, 1.0, 1.0) in the + // input, we can figure out the scale by using the + // inverse conversion on the white point. + QColorVector wXyz(whitePoint); + QColorVector whiteScale = toXyz.inverted().map(wXyz); + + // Now we have scaled conversion to XYZ relative to the given whitepoint + toXyz = toXyz * QColorMatrix::fromScale(whiteScale); + + // But we want a conversion to XYZ relative to D50 + QColorVector wXyzD50 = QColorVector::D50(); + + if (wXyz != wXyzD50) { + // Do chromatic adaptation to map our white point to XYZ D50. + + // The Bradford method chromatic adaptation matrix: + QColorMatrix abrad = { { 0.8951f, -0.7502f, 0.0389f }, + { 0.2664f, 1.7135f, -0.0685f }, + { -0.1614f, 0.0367f, 1.0296f } }; + QColorMatrix abradinv = { { 0.9869929f, 0.4323053f, -0.0085287f }, + { -0.1470543f, 0.5183603f, 0.0400428f }, + { 0.1599627f, 0.0492912f, 0.9684867f } }; + + QColorVector srcCone = abrad.map(wXyz); + QColorVector dstCone = abrad.map(wXyzD50); + + QColorMatrix wToD50 = { { dstCone.x / srcCone.x, 0, 0 }, + { 0, dstCone.y / srcCone.y, 0 }, + { 0, 0, dstCone.z / srcCone.z } }; + + + QColorMatrix chromaticAdaptation = abradinv * (wToD50 * abrad); + toXyz = chromaticAdaptation * toXyz; + } + + return toXyz; +} + QColorSpacePrivate::QColorSpacePrivate() : id(QColorSpace::Unknown) , gamut(QColorSpace::Gamut::Custom) @@ -128,6 +224,21 @@ QColorSpacePrivate::QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::Tr initialize(); } +QColorSpacePrivate::QColorSpacePrivate(const QColorSpacePrimaries &primaries, + QColorSpace::TransferFunction fun, + float gamma) + : gamut(QColorSpace::Gamut::Custom) + , transferFunction(fun) + , gamma(gamma) +{ + Q_ASSERT(primaries.areValid()); + toXyz = primaries.toXyzMatrix(); + whitePoint = QColorVector(primaries.whitePoint); + if (!identifyColorSpace()) + id = QColorSpace::Unknown; + setTransferFunction(); +} + bool QColorSpacePrivate::identifyColorSpace() { switch (gamut) { @@ -195,33 +306,14 @@ void QColorSpacePrivate::initialize() void QColorSpacePrivate::setToXyzMatrix() { - switch (gamut) { - case QColorSpace::Gamut::SRgb: - toXyz = QColorMatrix::toXyzFromSRgb(); - whitePoint = QColorVector::D65(); - return; - case QColorSpace::Gamut::AdobeRgb: - toXyz = QColorMatrix::toXyzFromAdobeRgb(); - whitePoint = QColorVector::D65(); - return; - case QColorSpace::Gamut::DciP3D65: - toXyz = QColorMatrix::toXyzFromDciP3D65(); - whitePoint = QColorVector::D65(); - return; - case QColorSpace::Gamut::ProPhotoRgb: - toXyz = QColorMatrix::toXyzFromProPhotoRgb(); - whitePoint = QColorVector::D50(); - return; - case QColorSpace::Gamut::Bt2020: - toXyz = QColorMatrix::toXyzFromBt2020(); - whitePoint = QColorVector::D65(); - return; - case QColorSpace::Gamut::Custom: + if (gamut == QColorSpace::Gamut::Custom) { toXyz = QColorMatrix::null(); whitePoint = QColorVector::D50(); return; } - Q_UNREACHABLE(); + QColorSpacePrimaries primaries(gamut); + toXyz = primaries.toXyzMatrix(); + whitePoint = QColorVector(primaries.whitePoint); } void QColorSpacePrivate::setTransferFunction() @@ -386,6 +478,23 @@ QColorSpace::QColorSpace(QColorSpace::Gamut gamut, float gamma) { } +/*! + Creates a custom colorspace with a gamut based on the chromaticities of the primary colors \a whitePoint, + \a redPoint, \a greenPoint and \a bluePoint, and using the transfer function \a fun and optionally \a gamma. + */ +QColorSpace::QColorSpace(const QPointF &whitePoint, const QPointF &redPoint, + const QPointF &greenPoint, const QPointF &bluePoint, + QColorSpace::TransferFunction fun, float gamma) +{ + QColorSpacePrimaries primaries(whitePoint, redPoint, greenPoint, bluePoint); + if (!primaries.areValid()) { + qWarning() << "QColorSpace attempted constructed from invalid primaries:" << whitePoint << redPoint << greenPoint << bluePoint; + d_ptr = QColorSpace(QColorSpace::Undefined).d_ptr; + return; + } + d_ptr = new QColorSpacePrivate(primaries, fun, gamma); +} + QColorSpace::~QColorSpace() { } diff --git a/src/gui/painting/qcolorspace.h b/src/gui/painting/qcolorspace.h index 923546ec6f..56676826a9 100644 --- a/src/gui/painting/qcolorspace.h +++ b/src/gui/painting/qcolorspace.h @@ -85,6 +85,9 @@ public: QColorSpace(ColorSpaceId colorSpaceId = Undefined); QColorSpace(Gamut gamut, TransferFunction fun, float gamma = 0.0f); QColorSpace(Gamut gamut, float gamma); + QColorSpace(const QPointF &whitePoint, const QPointF &redPoint, + const QPointF &greenPoint, const QPointF &bluePoint, + TransferFunction fun, float gamma = 0.0f); ~QColorSpace(); QColorSpace(QColorSpace &&colorSpace); diff --git a/src/gui/painting/qcolorspace_p.h b/src/gui/painting/qcolorspace_p.h index 91107a9a89..21260a281d 100644 --- a/src/gui/painting/qcolorspace_p.h +++ b/src/gui/painting/qcolorspace_p.h @@ -57,15 +57,41 @@ #include "qcolortrclut_p.h" #include +#include QT_BEGIN_NAMESPACE +class Q_GUI_EXPORT QColorSpacePrimaries +{ +public: + QColorSpacePrimaries() = default; + QColorSpacePrimaries(QColorSpace::Gamut gamut); + QColorSpacePrimaries(QPointF whitePoint, + QPointF redPoint, + QPointF greenPoint, + QPointF bluePoint) + : whitePoint(whitePoint) + , redPoint(redPoint) + , greenPoint(greenPoint) + , bluePoint(bluePoint) + { } + + QColorMatrix toXyzMatrix() const; + bool areValid() const; + + QPointF whitePoint; + QPointF redPoint; + QPointF greenPoint; + QPointF bluePoint; +}; + class QColorSpacePrivate : public QSharedData { public: QColorSpacePrivate(); QColorSpacePrivate(QColorSpace::ColorSpaceId colorSpaceId); QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma); + QColorSpacePrivate(const QColorSpacePrimaries &primaries, QColorSpace::TransferFunction fun, float gamma); QColorSpacePrivate(const QColorSpacePrivate &other) = default; QColorSpacePrivate &operator=(const QColorSpacePrivate &other) = default; diff --git a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp index 35bca58854..7a88eb18b2 100644 --- a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp +++ b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp @@ -33,6 +33,8 @@ #include #include +#include + Q_DECLARE_METATYPE(QColorSpace::ColorSpaceId) Q_DECLARE_METATYPE(QColorSpace::Gamut) Q_DECLARE_METATYPE(QColorSpace::TransferFunction) @@ -59,6 +61,10 @@ private slots: void loadImage(); void gamut(); + void primariesXyz(); + void primaries2_data(); + void primaries2(); + void invalidPrimaries(); }; tst_QColorSpace::tst_QColorSpace() @@ -289,5 +295,67 @@ void tst_QColorSpace::gamut() QVERIFY(tgreen.blueF() > 0.2); } +void tst_QColorSpace::primariesXyz() +{ + QColorSpace sRgb = QColorSpace::SRgb; + QColorSpace adobeRgb = QColorSpace::AdobeRgb; + QColorSpace displayP3 = QColorSpace::DisplayP3; + QColorSpace proPhotoRgb = QColorSpace::ProPhotoRgb; + QColorSpace bt2020 = QColorSpace::Bt2020; + + // Check if our calculated matrices, match the precalculated ones. + QCOMPARE(sRgb.d_func()->toXyz, QColorMatrix::toXyzFromSRgb()); + QCOMPARE(adobeRgb.d_func()->toXyz, QColorMatrix::toXyzFromAdobeRgb()); + QCOMPARE(displayP3.d_func()->toXyz, QColorMatrix::toXyzFromDciP3D65()); + QCOMPARE(proPhotoRgb.d_func()->toXyz, QColorMatrix::toXyzFromProPhotoRgb()); + QCOMPARE(bt2020.d_func()->toXyz, QColorMatrix::toXyzFromBt2020()); +} + +void tst_QColorSpace::primaries2_data() +{ + QTest::addColumn("gamut"); + + QTest::newRow("sRGB") << QColorSpace::Gamut::SRgb; + QTest::newRow("DCI-P3 (D65)") << QColorSpace::Gamut::DciP3D65; + QTest::newRow("Adobe RGB (1998)") << QColorSpace::Gamut::AdobeRgb; + QTest::newRow("ProPhoto RGB") << QColorSpace::Gamut::ProPhotoRgb; + QTest::newRow("BT.2020") << QColorSpace::Gamut::Bt2020; +} + +void tst_QColorSpace::primaries2() +{ + QFETCH(QColorSpace::Gamut, gamut); + QColorSpacePrimaries primaries(gamut); + + QColorSpace original(gamut, QColorSpace::TransferFunction::Linear); + QColorSpace custom1(primaries.whitePoint, primaries.redPoint, + primaries.greenPoint, primaries.bluePoint, QColorSpace::TransferFunction::Linear); + QCOMPARE(original, custom1); + + // A custom color swizzled color-space: + QColorSpace custom2(primaries.whitePoint, primaries.bluePoint, + primaries.greenPoint, primaries.redPoint, QColorSpace::TransferFunction::Linear); + + QVERIFY(custom1 != custom2); + QColor color1(255, 127, 63); + QColor color2 = custom1.transformationToColorSpace(custom2).map(color1); + QCOMPARE(color2.red(), color1.blue()); + QCOMPARE(color2.green(), color1.green()); + QCOMPARE(color2.blue(), color1.red()); + QCOMPARE(color2.alpha(), color1.alpha()); + QColor color3 = custom2.transformationToColorSpace(custom1).map(color2); + QCOMPARE(color3.red(), color1.red()); + QCOMPARE(color3.green(), color1.green()); + QCOMPARE(color3.blue(), color1.blue()); + QCOMPARE(color3.alpha(), color1.alpha()); +} + +void tst_QColorSpace::invalidPrimaries() +{ + QColorSpace custom(QPointF(), QPointF(), QPointF(), QPointF(), QColorSpace::TransferFunction::Linear); + QVERIFY(!custom.isValid()); + QCOMPARE(custom.colorSpaceId(), QColorSpace::Undefined); +} + QTEST_MAIN(tst_QColorSpace) #include "tst_qcolorspace.moc" From d775b1fcb3fc7bd41af37f5d0a4d999320b62364 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 4 Apr 2019 18:13:32 +0200 Subject: [PATCH 060/122] Remove handling of missing Q_COMPILER_INITIALIZER_LISTS Change-Id: Id65b39c787235a051262544932e6717d076f1ea0 Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- .../widgets/widgets/icons/iconpreviewarea.cpp | 40 ------------------- src/corelib/global/qflags.h | 6 --- .../global/qoperatingsystemversion.cpp | 2 - src/corelib/global/qoperatingsystemversion.h | 2 - src/corelib/serialization/qjsonarray.h | 4 -- src/corelib/serialization/qjsonobject.h | 4 -- src/corelib/tools/qhash.h | 9 +---- src/corelib/tools/qlinkedlist.h | 10 +---- src/corelib/tools/qlist.h | 9 +---- src/corelib/tools/qmap.h | 11 +---- src/corelib/tools/qset.h | 5 --- src/corelib/tools/qstringlist.h | 2 - src/corelib/tools/qvarlengtharray.h | 12 ++---- src/corelib/tools/qvector.h | 16 +++----- src/corelib/tools/qversionnumber.h | 4 -- .../qtconcurrentrun/tst_qtconcurrentrun.cpp | 4 -- .../auto/corelib/global/qflags/tst_qflags.cpp | 5 --- .../corelib/serialization/json/tst_qtjson.cpp | 8 ---- .../tst_containerapisymmetry.cpp | 10 ----- .../qbytearraylist/tst_qbytearraylist.cpp | 4 -- .../tst_qcommandlineparser.cpp | 2 +- tests/auto/corelib/tools/qhash/tst_qhash.cpp | 4 -- .../tools/qlinkedlist/tst_qlinkedlist.cpp | 2 - tests/auto/corelib/tools/qlist/tst_qlist.cpp | 2 - tests/auto/corelib/tools/qmap/tst_qmap.cpp | 4 -- tests/auto/corelib/tools/qset/tst_qset.cpp | 12 ------ .../tools/qstringlist/tst_qstringlist.cpp | 5 --- .../qvarlengtharray/tst_qvarlengtharray.cpp | 4 -- .../corelib/tools/qvector/tst_qvector.cpp | 6 --- .../qversionnumber/tst_qversionnumber.cpp | 2 - 30 files changed, 16 insertions(+), 194 deletions(-) diff --git a/examples/widgets/widgets/icons/iconpreviewarea.cpp b/examples/widgets/widgets/icons/iconpreviewarea.cpp index 1a2f514ba8..7a73a137cd 100644 --- a/examples/widgets/widgets/icons/iconpreviewarea.cpp +++ b/examples/widgets/widgets/icons/iconpreviewarea.cpp @@ -79,8 +79,6 @@ IconPreviewArea::IconPreviewArea(QWidget *parent) } //! [0] -#ifdef Q_COMPILER_INITIALIZER_LISTS - //! [42] QVector IconPreviewArea::iconModes() { @@ -107,44 +105,6 @@ QStringList IconPreviewArea::iconStateNames() } //! [42] -#else // Q_COMPILER_INITIALIZER_LISTS - -//! [43] -QVector IconPreviewArea::iconModes() -{ - static QVector result; - if (result.isEmpty()) - result << QIcon::Normal << QIcon::Active << QIcon::Disabled << QIcon::Selected; - return result; -} -//! [43] - -QVector IconPreviewArea::iconStates() -{ - static QVector result; - if (result.isEmpty()) - result << QIcon::Off << QIcon::On; - return result; -} - -QStringList IconPreviewArea::iconModeNames() -{ - static QStringList result; - if (result.isEmpty()) - result << tr("Normal") << tr("Active") << tr("Disabled") << tr("Selected"); - return result; -} - -QStringList IconPreviewArea::iconStateNames() -{ - static QStringList result; - if (result.isEmpty()) - result << tr("Off") << tr("On"); - return result; -} - -#endif // !Q_COMPILER_INITIALIZER_LISTS - //! [1] void IconPreviewArea::setIcon(const QIcon &icon) { diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h index 65f4892472..bd3c219968 100644 --- a/src/corelib/global/qflags.h +++ b/src/corelib/global/qflags.h @@ -42,9 +42,7 @@ #ifndef QFLAGS_H #define QFLAGS_H -#ifdef Q_COMPILER_INITIALIZER_LISTS #include -#endif QT_BEGIN_NAMESPACE @@ -121,10 +119,8 @@ public: Q_DECL_CONSTEXPR inline QFlags(Zero = nullptr) noexcept : i(0) {} Q_DECL_CONSTEXPR inline QFlags(QFlag flag) noexcept : i(flag) {} -#ifdef Q_COMPILER_INITIALIZER_LISTS Q_DECL_CONSTEXPR inline QFlags(std::initializer_list flags) noexcept : i(initializer_list_helper(flags.begin(), flags.end())) {} -#endif Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(int mask) noexcept { i &= mask; return *this; } Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(uint mask) noexcept { i &= mask; return *this; } @@ -154,14 +150,12 @@ public: } private: -#ifdef Q_COMPILER_INITIALIZER_LISTS Q_DECL_CONSTEXPR static inline Int initializer_list_helper(typename std::initializer_list::const_iterator it, typename std::initializer_list::const_iterator end) noexcept { return (it == end ? Int(0) : (Int(*it) | initializer_list_helper(it + 1, end))); } -#endif Int i; }; diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp index 94dc261b41..42a1275621 100644 --- a/src/corelib/global/qoperatingsystemversion.cpp +++ b/src/corelib/global/qoperatingsystemversion.cpp @@ -340,7 +340,6 @@ QString QOperatingSystemVersion::name() const } } -#ifdef Q_COMPILER_INITIALIZER_LISTS /*! \fn bool QOperatingSystemVersion::isAnyOfType(std::initializer_list types) const @@ -355,7 +354,6 @@ bool QOperatingSystemVersion::isAnyOfType(std::initializer_list types) c } return false; } -#endif /*! \variable QOperatingSystemVersion::Windows7 diff --git a/src/corelib/global/qoperatingsystemversion.h b/src/corelib/global/qoperatingsystemversion.h index df01e5438a..e99e4f8997 100644 --- a/src/corelib/global/qoperatingsystemversion.h +++ b/src/corelib/global/qoperatingsystemversion.h @@ -119,9 +119,7 @@ public: Q_DECL_CONSTEXPR int segmentCount() const { return m_micro >= 0 ? 3 : m_minor >= 0 ? 2 : m_major >= 0 ? 1 : 0; } -#ifdef Q_COMPILER_INITIALIZER_LISTS bool isAnyOfType(std::initializer_list types) const; -#endif Q_DECL_CONSTEXPR OSType type() const { return m_os; } QString name() const; diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h index 86b7bf9d76..983a6753b5 100644 --- a/src/corelib/serialization/qjsonarray.h +++ b/src/corelib/serialization/qjsonarray.h @@ -42,9 +42,7 @@ #include #include -#if defined(Q_COMPILER_INITIALIZER_LISTS) #include -#endif QT_BEGIN_NAMESPACE @@ -58,14 +56,12 @@ class Q_CORE_EXPORT QJsonArray public: QJsonArray(); -#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC) QJsonArray(std::initializer_list args) { initialize(); for (std::initializer_list::const_iterator i = args.begin(); i != args.end(); ++i) append(*i); } -#endif ~QJsonArray(); diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h index 92d45cc838..d8e2ab9ca7 100644 --- a/src/corelib/serialization/qjsonobject.h +++ b/src/corelib/serialization/qjsonobject.h @@ -42,10 +42,8 @@ #include #include -#ifdef Q_COMPILER_INITIALIZER_LISTS #include #include -#endif QT_BEGIN_NAMESPACE @@ -60,14 +58,12 @@ class Q_CORE_EXPORT QJsonObject public: QJsonObject(); -#if defined(Q_COMPILER_INITIALIZER_LISTS) || defined(Q_QDOC) QJsonObject(std::initializer_list > args) { initialize(); for (std::initializer_list >::const_iterator i = args.begin(); i != args.end(); ++i) insert(i->first, i->second); } -#endif ~QJsonObject(); diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 0078bbbee9..4b4cb2d5f0 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -48,11 +48,8 @@ #include #include -#ifdef Q_COMPILER_INITIALIZER_LISTS -#include -#endif - #include +#include #if defined(Q_CC_MSVC) #pragma warning( push ) @@ -242,7 +239,6 @@ class QHash public: inline QHash() noexcept : d(const_cast(&QHashData::shared_null)) { } -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QHash(std::initializer_list > list) : d(const_cast(&QHashData::shared_null)) { @@ -250,7 +246,6 @@ public: for (typename std::initializer_list >::const_iterator it = list.begin(); it != list.end(); ++it) insert(it->first, it->second); } -#endif QHash(const QHash &other) : d(other.d) { d->ref.ref(); if (!d->sharable) detach(); } ~QHash() { if (!d->ref.deref()) freeData(d); } @@ -1042,14 +1037,12 @@ class QMultiHash : public QHash { public: QMultiHash() noexcept {} -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QMultiHash(std::initializer_list > list) { this->reserve(int(list.size())); for (typename std::initializer_list >::const_iterator it = list.begin(); it != list.end(); ++it) insert(it->first, it->second); } -#endif #ifdef Q_QDOC template QMultiHash(InputIterator f, InputIterator l); diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h index 0c8a99e258..8994449fbf 100644 --- a/src/corelib/tools/qlinkedlist.h +++ b/src/corelib/tools/qlinkedlist.h @@ -44,15 +44,11 @@ #include #include +#include +#include #include #include -#include - -#if defined(Q_COMPILER_INITIALIZER_LISTS) -# include -#endif - QT_BEGIN_NAMESPACE @@ -83,10 +79,8 @@ class QLinkedList public: inline QLinkedList() noexcept : d(const_cast(&QLinkedListData::shared_null)) { } inline QLinkedList(const QLinkedList &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); } -#if defined(Q_COMPILER_INITIALIZER_LISTS) inline QLinkedList(std::initializer_list list) : QLinkedList(list.begin(), list.end()) {} -#endif template = true> inline QLinkedList(InputIterator first, InputIterator last) : QLinkedList() diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index b916dcfd24..27868f7313 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -48,12 +48,10 @@ #include #include +#include +#include #include #include -#include -#ifdef Q_COMPILER_INITIALIZER_LISTS -#include -#endif #include #include @@ -166,13 +164,10 @@ public: inline QList &operator=(QList &&other) noexcept { QList moved(std::move(other)); swap(moved); return *this; } inline void swap(QList &other) noexcept { qSwap(d, other.d); } -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QList(std::initializer_list args) : QList(args.begin(), args.end()) {} -#endif template = true> QList(InputIterator first, InputIterator last); - bool operator==(const QList &l) const; inline bool operator!=(const QList &l) const { return !(*this == l); } diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 2d01a75a42..18c681581f 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -49,13 +49,10 @@ #include #endif +#include +#include #include #include -#include - -#ifdef Q_COMPILER_INITIALIZER_LISTS -#include -#endif QT_BEGIN_NAMESPACE @@ -326,14 +323,12 @@ class QMap public: inline QMap() noexcept : d(static_cast *>(const_cast(&QMapDataBase::shared_null))) { } -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QMap(std::initializer_list > list) : d(static_cast *>(const_cast(&QMapDataBase::shared_null))) { for (typename std::initializer_list >::const_iterator it = list.begin(); it != list.end(); ++it) insert(it->first, it->second); } -#endif QMap(const QMap &other); inline ~QMap() { if (!d->ref.deref()) d->destroy(); } @@ -1186,13 +1181,11 @@ class QMultiMap : public QMap { public: QMultiMap() noexcept {} -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QMultiMap(std::initializer_list > list) { for (typename std::initializer_list >::const_iterator it = list.begin(); it != list.end(); ++it) insert(it->first, it->second); } -#endif QMultiMap(const QMap &other) : QMap(other) {} QMultiMap(QMap &&other) noexcept : QMap(std::move(other)) {} void swap(QMultiMap &other) noexcept { QMap::swap(other); } diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 7ae715d247..8b31de71a9 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -43,10 +43,7 @@ #include #include -#ifdef Q_COMPILER_INITIALIZER_LISTS #include -#endif - #include QT_BEGIN_NAMESPACE @@ -59,10 +56,8 @@ class QSet public: inline QSet() noexcept {} -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QSet(std::initializer_list list) : QSet(list.begin(), list.end()) {} -#endif template = true> inline QSet(InputIterator first, InputIterator last) { diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index 73ac737643..cf136a64c6 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -105,9 +105,7 @@ public: inline explicit QStringList(const QString &i) { append(i); } inline QStringList(const QList &l) : QList(l) { } inline QStringList(QList &&l) noexcept : QList(std::move(l)) { } -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QStringList(std::initializer_list args) : QList(args) { } -#endif template = true> inline QStringList(InputIterator first, InputIterator last) : QList(first, last) { } diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index c81af68593..01fc63b677 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -45,14 +45,12 @@ #include #include +#include +#include +#include #include #include #include -#include -#ifdef Q_COMPILER_INITIALIZER_LISTS -#include -#endif -#include QT_BEGIN_NAMESPACE @@ -70,12 +68,10 @@ public: append(other.constData(), other.size()); } -#ifdef Q_COMPILER_INITIALIZER_LISTS QVarLengthArray(std::initializer_list args) : QVarLengthArray(args.begin(), args.end()) { } -#endif template = true> inline QVarLengthArray(InputIterator first, InputIterator last) @@ -103,7 +99,6 @@ public: return *this; } -#ifdef Q_COMPILER_INITIALIZER_LISTS QVarLengthArray &operator=(std::initializer_list list) { resize(list.size()); @@ -111,7 +106,6 @@ public: QT_MAKE_CHECKED_ARRAY_ITERATOR(this->begin(), this->size())); return *this; } -#endif inline void removeLast() { Q_ASSERT(s > 0); diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 7e14a0c9b2..d6baa76a30 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -48,12 +48,10 @@ #include #include +#include #include #include #include -#ifdef Q_COMPILER_INITIALIZER_LISTS -#include -#endif #include @@ -76,10 +74,8 @@ public: QVector &operator=(QVector &&other) noexcept { QVector moved(std::move(other)); swap(moved); return *this; } void swap(QVector &other) noexcept { qSwap(d, other.d); } -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QVector(std::initializer_list args); QVector &operator=(std::initializer_list args); -#endif template = true> inline QVector(InputIterator first, InputIterator last); @@ -521,11 +517,10 @@ QVector::QVector(int asize, const T &t) } } -#ifdef Q_COMPILER_INITIALIZER_LISTS -# if defined(Q_CC_MSVC) +#if defined(Q_CC_MSVC) QT_WARNING_PUSH QT_WARNING_DISABLE_MSVC(4127) // conditional expression is constant -# endif // Q_CC_MSVC +#endif // Q_CC_MSVC template QVector::QVector(std::initializer_list args) @@ -550,10 +545,9 @@ QVector &QVector::operator=(std::initializer_list args) return *this; } -# if defined(Q_CC_MSVC) +#if defined(Q_CC_MSVC) QT_WARNING_POP -# endif // Q_CC_MSVC -#endif // Q_COMPILER_INITIALIZER_LISTS +#endif // Q_CC_MSVC template template > diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h index 1488014d38..d43b86ba51 100644 --- a/src/corelib/tools/qversionnumber.h +++ b/src/corelib/tools/qversionnumber.h @@ -138,7 +138,6 @@ class QVersionNumber else pointer_segments = new QVector(std::move(seg)); } -#ifdef Q_COMPILER_INITIALIZER_LISTS SegmentStorage(std::initializer_list args) { if (dataFitsInline(args.begin(), int(args.size()))) { @@ -147,7 +146,6 @@ class QVersionNumber pointer_segments = new QVector(args); } } -#endif ~SegmentStorage() { if (isUsingPointer()) delete pointer_segments; } @@ -229,11 +227,9 @@ public: : m_segments(std::move(seg)) {} -#ifdef Q_COMPILER_INITIALIZER_LISTS inline QVersionNumber(std::initializer_list args) : m_segments(args) {} -#endif inline explicit QVersionNumber(int maj) { m_segments.setSegments(1, maj); } diff --git a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp index 8506d18dae..39d17e0a24 100644 --- a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp +++ b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp @@ -710,14 +710,12 @@ void tst_QtConcurrentRun::lambda() QCOMPARE(QtConcurrent::run([](int a, double b){ return a + b; }, 12, 15).result(), double(12+15)); QCOMPARE(QtConcurrent::run([](int a , int, int, int, int b){ return a + b; }, 1, 2, 3, 4, 5).result(), 1 + 5); -#ifdef Q_COMPILER_INITIALIZER_LISTS { QString str { "Hello World Foo" }; QFuture f1 = QtConcurrent::run([&](){ return str.split(' '); }); auto r = f1.result(); QCOMPARE(r, QStringList({"Hello", "World", "Foo"})); } -#endif // and now with explicit pool: QThreadPool pool; @@ -726,14 +724,12 @@ void tst_QtConcurrentRun::lambda() QCOMPARE(QtConcurrent::run(&pool, [](int a, double b){ return a + b; }, 12, 15).result(), double(12+15)); QCOMPARE(QtConcurrent::run(&pool, [](int a , int, int, int, int b){ return a + b; }, 1, 2, 3, 4, 5).result(), 1 + 5); -#ifdef Q_COMPILER_INITIALIZER_LISTS { QString str { "Hello World Foo" }; QFuture f1 = QtConcurrent::run(&pool, [&](){ return str.split(' '); }); auto r = f1.result(); QCOMPARE(r, QStringList({"Hello", "World", "Foo"})); } -#endif } QTEST_MAIN(tst_QtConcurrentRun) diff --git a/tests/auto/corelib/global/qflags/tst_qflags.cpp b/tests/auto/corelib/global/qflags/tst_qflags.cpp index 8265d21350..1568855032 100644 --- a/tests/auto/corelib/global/qflags/tst_qflags.cpp +++ b/tests/auto/corelib/global/qflags/tst_qflags.cpp @@ -258,7 +258,6 @@ void tst_QFlags::classEnum() void tst_QFlags::initializerLists() { -#if defined(Q_COMPILER_INITIALIZER_LISTS) Qt::MouseButtons bts = { Qt::LeftButton, Qt::RightButton }; QVERIFY(bts.testFlag(Qt::LeftButton)); QVERIFY(bts.testFlag(Qt::RightButton)); @@ -268,10 +267,6 @@ void tst_QFlags::initializerLists() QVERIFY(flags.testFlag(MyStrictNoOpEnum::StrictOne)); QVERIFY(flags.testFlag(MyStrictNoOpEnum::StrictFour)); QVERIFY(!flags.testFlag(MyStrictNoOpEnum::StrictTwo)); - -#else - QSKIP("This test requires C++11 initializer_list support."); -#endif // Q_COMPILER_INITIALIZER_LISTS } void tst_QFlags::testSetFlags() diff --git a/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/tests/auto/corelib/serialization/json/tst_qtjson.cpp index 083e78375a..548b6d0059 100644 --- a/tests/auto/corelib/serialization/json/tst_qtjson.cpp +++ b/tests/auto/corelib/serialization/json/tst_qtjson.cpp @@ -2754,9 +2754,6 @@ void tst_QtJson::testJsonValueRefDefault() void tst_QtJson::arrayInitializerList() { -#ifndef Q_COMPILER_INITIALIZER_LISTS - QSKIP("initializer_list is enabled only with c++11 support"); -#else QVERIFY(QJsonArray{}.isEmpty()); QCOMPARE(QJsonArray{"one"}.count(), 1); QCOMPARE(QJsonArray{1}.count(), 1); @@ -2802,14 +2799,10 @@ void tst_QtJson::arrayInitializerList() QCOMPARE(QJsonValue(a43["one"]), QJsonValue(1)); } } -#endif } void tst_QtJson::objectInitializerList() { -#ifndef Q_COMPILER_INITIALIZER_LISTS - QSKIP("initializer_list is enabled only with c++11 support"); -#else QVERIFY(QJsonObject{}.isEmpty()); { // one property @@ -2849,7 +2842,6 @@ void tst_QtJson::objectInitializerList() QCOMPARE(QJsonValue(nested[0]), QJsonValue("innerValue")); QCOMPARE(QJsonValue(nested[1]), QJsonValue(2.1)); } -#endif } void tst_QtJson::unicodeKeys() diff --git a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp index 7df220acf9..4b085d387d 100644 --- a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp +++ b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp @@ -233,13 +233,11 @@ public: { } -#ifdef Q_COMPILER_INITIALIZER_LISTS VarLengthArray(std::initializer_list args) : QVarLengthArray(args) { } #endif -#endif }; class tst_ContainerApiSymmetry : public QObject @@ -614,7 +612,6 @@ struct ContainerDuplicatedValuesStrategy> : Contai template struct ContainerDuplicatedValuesStrategy> : ContainerRejectsDuplicateValues {}; -#if defined(Q_COMPILER_INITIALIZER_LISTS) template void non_associative_container_check_duplicates_impl(const std::initializer_list &reference, const Container &c, ContainerAcceptsDuplicateValues) { @@ -716,13 +713,6 @@ void tst_ContainerApiSymmetry::non_associative_container_duplicates_strategy() c Container c2{reference.begin(), reference.end()}; non_associative_container_check_duplicates(reference, c2); } -#else -template class Container> -void tst_ContainerApiSymmetry::non_associative_container_duplicates_strategy() const -{ - QSKIP("Test requires a better compiler"); -} -#endif // Q_COMPILER_INITIALIZER_LISTS template void tst_ContainerApiSymmetry::ranged_ctor_associative_impl() const diff --git a/tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp b/tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp index a28bbc12c8..09ce41337e 100644 --- a/tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp +++ b/tests/auto/corelib/tools/qbytearraylist/tst_qbytearraylist.cpp @@ -287,7 +287,6 @@ void tst_QByteArrayList::indexOf() const void tst_QByteArrayList::initializerList() const { -#ifdef Q_COMPILER_INITIALIZER_LISTS // constructor QByteArrayList v1 = {QByteArray("hello"),"world",QByteArray("plop")}; QCOMPARE(v1, (QByteArrayList() << "hello" << "world" << "plop")); @@ -296,9 +295,6 @@ void tst_QByteArrayList::initializerList() const QByteArrayList v2; v2 = {QByteArray("hello"),"world",QByteArray("plop")}; QCOMPARE(v2, v1); -#else - QSKIP("This test requires C++11 initializer_list support in the compiler."); -#endif } QTEST_APPLESS_MAIN(tst_QByteArrayList) diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp index 811e9a0010..de51c866e1 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp @@ -499,7 +499,7 @@ void tst_QCommandLineParser::testSingleDashWordOptionModes() void tst_QCommandLineParser::testCpp11StyleInitialization() { -#if defined(Q_COMPILER_INITIALIZER_LISTS) && defined(Q_COMPILER_UNIFORM_INIT) +#if defined(Q_COMPILER_UNIFORM_INIT) QCoreApplication app(empty_argc, empty_argv); QCommandLineParser parser; diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp index 0015efacfa..d70d488e96 100644 --- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp +++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp @@ -1480,7 +1480,6 @@ void tst_QHash::twoArguments_qHash() void tst_QHash::initializerList() { -#ifdef Q_COMPILER_INITIALIZER_LISTS QHash hash = {{1, "bar"}, {1, "hello"}, {2, "initializer_list"}}; QCOMPARE(hash.count(), 2); QCOMPARE(hash[1], QString("hello")); @@ -1507,9 +1506,6 @@ void tst_QHash::initializerList() QMultiHash emptyPairs2{{}, {}}; QVERIFY(!emptyPairs2.isEmpty()); -#else - QSKIP("Compiler doesn't support initializer lists"); -#endif } void tst_QHash::eraseValidIteratorOnSharedHash() diff --git a/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp index f17d6695f0..deb3b68c5c 100644 --- a/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp +++ b/tests/auto/corelib/tools/qlinkedlist/tst_qlinkedlist.cpp @@ -1005,7 +1005,6 @@ void tst_QLinkedList::testSTLIteratorsComplex() const void tst_QLinkedList::initializeList() const { -#ifdef Q_COMPILER_INITIALIZER_LISTS QLinkedList v1 { 2, 3, 4 }; QCOMPARE(v1, QLinkedList() << 2 << 3 << 4); QCOMPARE(v1, (QLinkedList { 2, 3, 4})); @@ -1014,7 +1013,6 @@ void tst_QLinkedList::initializeList() const QLinkedList> v3; v3 << v1 << (QLinkedList() << 1) << QLinkedList() << v1; QCOMPARE(v3, v2); -#endif } diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp index b3f8130d27..16fb291bd2 100644 --- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp +++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp @@ -1871,7 +1871,6 @@ void tst_QList::testSTLIteratorsComplex() const void tst_QList::initializeList() const { -#ifdef Q_COMPILER_INITIALIZER_LISTS QList v1{2,3,4}; QCOMPARE(v1, QList() << 2 << 3 << 4); QCOMPARE(v1, (QList{2,3,4})); @@ -1880,7 +1879,6 @@ void tst_QList::initializeList() const QList> v3; v3 << v1 << (QList() << 1) << QList() << v1; QCOMPARE(v3, v2); -#endif } template diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp index b39444e76f..d66fd28779 100644 --- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp +++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp @@ -1319,7 +1319,6 @@ void tst_QMap::checkMostLeftNode() void tst_QMap::initializerList() { -#ifdef Q_COMPILER_INITIALIZER_LISTS QMap map = {{1, "bar"}, {1, "hello"}, {2, "initializer_list"}}; QCOMPARE(map.count(), 2); QCOMPARE(map[1], QString("hello")); @@ -1346,9 +1345,6 @@ void tst_QMap::initializerList() QMultiMap emptyPairs2{{}, {}}; QVERIFY(!emptyPairs2.isEmpty()); -#else - QSKIP("Compiler doesn't support initializer lists"); -#endif } void tst_QMap::testInsertWithHint() diff --git a/tests/auto/corelib/tools/qset/tst_qset.cpp b/tests/auto/corelib/tools/qset/tst_qset.cpp index 0b60350380..31b4c0449e 100644 --- a/tests/auto/corelib/tools/qset/tst_qset.cpp +++ b/tests/auto/corelib/tools/qset/tst_qset.cpp @@ -955,7 +955,6 @@ void tst_QSet::makeSureTheComfortFunctionsCompile() void tst_QSet::initializerList() { -#ifdef Q_COMPILER_INITIALIZER_LISTS QSet set = {1, 1, 2, 3, 4, 5}; QCOMPARE(set.count(), 5); QVERIFY(set.contains(1)); @@ -976,9 +975,6 @@ void tst_QSet::initializerList() QSet set3{{}, {}, {}}; QVERIFY(!set3.isEmpty()); -#else - QSKIP("Compiler doesn't support initializer lists"); -#endif } void tst_QSet::qhash() @@ -1011,15 +1007,7 @@ void tst_QSet::qhash() // check that sets of sets work: // { -#ifdef Q_COMPILER_INITIALIZER_LISTS QSet > intSetSet = { { 0, 1, 2 }, { 0, 1 }, { 1, 2 } }; -#else - QSet > intSetSet; - QSet intSet01, intSet12; - intSet01 << 0 << 1; - intSet12 << 1 << 2; - intSetSet << intSet01 << intSet12 << (intSet01|intSet12); -#endif QCOMPARE(intSetSet.size(), 3); } } diff --git a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp index 37368c3dfc..2b5aa8e98b 100644 --- a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp +++ b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp @@ -63,9 +63,7 @@ private slots: void joinChar() const; void joinChar_data() const; -#ifdef Q_COMPILER_INITIALIZER_LISTS void initializeList() const; -#endif }; extern const char email[]; @@ -519,8 +517,6 @@ void tst_QStringList::joinEmptiness() const QVERIFY(string.isNull()); } -#ifdef Q_COMPILER_INITIALIZER_LISTS -// C++0x support is required void tst_QStringList::initializeList() const { @@ -528,7 +524,6 @@ void tst_QStringList::initializeList() const QCOMPARE(v1, (QStringList() << "hello" << "world" << "plop")); QCOMPARE(v1, (QStringList{"hello","world","plop"})); } -#endif QTEST_APPLESS_MAIN(tst_QStringList) #include "tst_qstringlist.moc" diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp index 5737db760c..fff8c75a90 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp @@ -908,7 +908,6 @@ void tst_QVarLengthArray::initializeListComplex() template void tst_QVarLengthArray::initializeList() { -#ifdef Q_COMPILER_INITIALIZER_LISTS T val1(110); T val2(105); T val3(101); @@ -945,9 +944,6 @@ void tst_QVarLengthArray::initializeList() v6 = {}; // assign empty QCOMPARE(v6.size(), 0); -#else - QSKIP("This tests requires a compiler that supports initializer lists."); -#endif } void tst_QVarLengthArray::insertMove() diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index f7e7c3e3ae..172b03a445 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -549,7 +549,6 @@ void tst_QVector::assignmentCustom() const template void tst_QVector::assignFromInitializerList() const { -#ifdef Q_COMPILER_INITIALIZER_LISTS T val1(SimpleValue::at(1)); T val2(SimpleValue::at(2)); T val3(SimpleValue::at(3)); @@ -560,9 +559,6 @@ void tst_QVector::assignFromInitializerList() const v1 = {}; QCOMPARE(v1.size(), 0); -#else - QSKIP("This test requires support for C++11 initializer lists."); -#endif } void tst_QVector::assignFromInitializerListInt() const @@ -2553,7 +2549,6 @@ void tst_QVector::reallocAfterCopy() template void tst_QVector::initializeList() { -#ifdef Q_COMPILER_INITIALIZER_LISTS T val1(SimpleValue::at(1)); T val2(SimpleValue::at(2)); T val3(SimpleValue::at(3)); @@ -2570,7 +2565,6 @@ void tst_QVector::initializeList() QVector v4({}); QCOMPARE(v4.size(), 0); -#endif } void tst_QVector::initializeListInt() diff --git a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp index 9bc8c84ee4..7c4d1071ce 100644 --- a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp +++ b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp @@ -260,12 +260,10 @@ void tst_QVersionNumber::constructorExplicit() QCOMPARE(v5.segments(), v6.segments()); -#ifdef Q_COMPILER_INITIALIZER_LISTS QVersionNumber v7(4, 5, 6); QVersionNumber v8 = {4, 5, 6}; QCOMPARE(v7.segments(), v8.segments()); -#endif } void tst_QVersionNumber::constructorCopy_data() From f5de7896d78bb73eecbf65c2ac6864ccd8a86e0a Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 3 May 2019 10:17:04 +0200 Subject: [PATCH 061/122] Use -Wextra instead -W -W is a really old way of writing -Wextra. Change-Id: Ibc531749293fab9b03e404fe751fc1c7b4a7e6db Reviewed-by: Joerg Bornemann --- mkspecs/common/gcc-base.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf index 44b4267207..4d82321cba 100644 --- a/mkspecs/common/gcc-base.conf +++ b/mkspecs/common/gcc-base.conf @@ -38,7 +38,7 @@ QMAKE_CFLAGS_OPTIMIZE_SIZE = -Os !equals(QMAKE_HOST.os, Windows): QMAKE_CFLAGS += -pipe QMAKE_CFLAGS_DEPS += -M -QMAKE_CFLAGS_WARN_ON += -Wall -W +QMAKE_CFLAGS_WARN_ON += -Wall -Wextra QMAKE_CFLAGS_WARN_OFF += -w QMAKE_CFLAGS_RELEASE += $$QMAKE_CFLAGS_OPTIMIZE QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -g From f27f89f3357326f8cc3b6bbc560160e909af7ead Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 2 May 2019 08:53:24 +0200 Subject: [PATCH 062/122] Don't use deprecated API Change-Id: Ic56c22a1be5e69b371991c3e9ad98a1106848e78 Reviewed-by: Thiago Macieira --- .../tools/collections/tst_collections.cpp | 42 +++++++++---------- tests/auto/corelib/tools/qlist/tst_qlist.cpp | 4 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/tests/auto/corelib/tools/collections/tst_collections.cpp b/tests/auto/corelib/tools/collections/tst_collections.cpp index 104de4d783..9bd90d21cd 100644 --- a/tests/auto/corelib/tools/collections/tst_collections.cpp +++ b/tests/auto/corelib/tools/collections/tst_collections.cpp @@ -580,73 +580,73 @@ void tst_Collections::list() list1 << 0 << 1 << 2 << 3; list1.removeFirst(); - list1.swap(0, 0); + list1.swapItemsAt(0, 0); QVERIFY(list1 == QList() << 1 << 2 << 3); - list1.swap(1, 1); + list1.swapItemsAt(1, 1); QVERIFY(list1 == QList() << 1 << 2 << 3); - list1.swap(2, 2); + list1.swapItemsAt(2, 2); QVERIFY(list1 == QList() << 1 << 2 << 3); - list1.swap(0, 1); + list1.swapItemsAt(0, 1); QVERIFY(list1 == QList() << 2 << 1 << 3); - list1.swap(0, 2); + list1.swapItemsAt(0, 2); QVERIFY(list1 == QList() << 3 << 1 << 2); - list1.swap(1, 2); + list1.swapItemsAt(1, 2); QVERIFY(list1 == QList() << 3 << 2 << 1); - list1.swap(1, 2); + list1.swapItemsAt(1, 2); QVERIFY(list1 == QList() << 3 << 1 << 2); QList list2; list2 << "1" << "2" << "3"; - list2.swap(0, 0); + list2.swapItemsAt(0, 0); QVERIFY(list2 == QList() << "1" << "2" << "3"); - list2.swap(1, 1); + list2.swapItemsAt(1, 1); QVERIFY(list2 == QList() << "1" << "2" << "3"); - list2.swap(2, 2); + list2.swapItemsAt(2, 2); QVERIFY(list2 == QList() << "1" << "2" << "3"); - list2.swap(0, 1); + list2.swapItemsAt(0, 1); QVERIFY(list2 == QList() << "2" << "1" << "3"); - list2.swap(0, 2); + list2.swapItemsAt(0, 2); QVERIFY(list2 == QList() << "3" << "1" << "2"); - list2.swap(1, 2); + list2.swapItemsAt(1, 2); QVERIFY(list2 == QList() << "3" << "2" << "1"); - list2.swap(1, 2); + list2.swapItemsAt(1, 2); QVERIFY(list2 == QList() << "3" << "1" << "2"); QList list3; list3 << 1.0 << 2.0 << 3.0; - list3.swap(0, 0); + list3.swapItemsAt(0, 0); QVERIFY(list3 == QList() << 1.0 << 2.0 << 3.0); - list3.swap(1, 1); + list3.swapItemsAt(1, 1); QVERIFY(list3 == QList() << 1.0 << 2.0 << 3.0); - list3.swap(2, 2); + list3.swapItemsAt(2, 2); QVERIFY(list3 == QList() << 1.0 << 2.0 << 3.0); - list3.swap(0, 1); + list3.swapItemsAt(0, 1); QVERIFY(list3 == QList() << 2.0 << 1.0 << 3.0); - list3.swap(0, 2); + list3.swapItemsAt(0, 2); QVERIFY(list3 == QList() << 3.0 << 1.0 << 2.0); - list3.swap(1, 2); + list3.swapItemsAt(1, 2); QVERIFY(list3 == QList() << 3.0 << 2.0 << 1.0); - list3.swap(1, 2); + list3.swapItemsAt(1, 2); QVERIFY(list3 == QList() << 3.0 << 1.0 << 2.0); } diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp index 16fb291bd2..995aa245d1 100644 --- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp +++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp @@ -1457,11 +1457,11 @@ void tst_QList::swap() const list << T_FOO << T_BAR << T_BAZ; // swap - list.swap(0, 2); + list.swapItemsAt(0, 2); QCOMPARE(list, QList() << T_BAZ << T_BAR << T_FOO); // swap again - list.swap(1, 2); + list.swapItemsAt(1, 2); QCOMPARE(list, QList() << T_BAZ << T_FOO << T_BAR); QList list2; From e3b55616e2334570fed3855e1855216bd9f85769 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 2 May 2019 09:24:11 +0200 Subject: [PATCH 063/122] Prefix QTextStream operators with Qt:: in tests Change-Id: I852f016fcb619a9e634deee6efb1fe7930d974c8 Reviewed-by: Allan Sandfeld Jensen --- tests/auto/corelib/io/qdebug/tst_qdebug.cpp | 8 +++--- tests/auto/corelib/io/qfile/tst_qfile.cpp | 4 +-- .../corelib/io/qfileinfo/tst_qfileinfo.cpp | 2 +- .../qloggingcategory/tst_qloggingcategory.cpp | 2 +- .../qtextstream/readLineStdinProcess/main.cpp | 2 +- .../qtextstream/tst_qtextstream.cpp | 16 +++++------ .../qxmlstream/tst_qxmlstream.cpp | 28 +++++++++---------- .../tools/qalgorithms/tst_qalgorithms.cpp | 22 +++++++-------- .../gui/kernel/qkeyevent/tst_qkeyevent.cpp | 2 +- .../gui/text/qstatictext/tst_qstatictext.cpp | 2 +- .../socket/qlocalsocket/tst_qlocalsocket.cpp | 4 +-- .../qgraphicsitem/tst_qgraphicsitem.cpp | 2 +- .../xml/sax/qxmlsimplereader/parser/main.cpp | 4 +-- 13 files changed, 49 insertions(+), 49 deletions(-) diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index 7b8b1df166..a818c6c09d 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -309,7 +309,7 @@ void tst_QDebug::stateSaver() const QDebug d = qDebug(); { QDebugStateSaver saver(d); - d.nospace() << hex << right << qSetFieldWidth(3) << qSetPadChar('0') << 42; + d.nospace() << Qt::hex << Qt::right << qSetFieldWidth(3) << qSetPadChar('0') << 42; } d << 42; } @@ -327,7 +327,7 @@ void tst_QDebug::stateSaver() const { QDebug d = qDebug(); - d.noquote().nospace() << QStringLiteral("Hello") << hex << 42; + d.noquote().nospace() << QStringLiteral("Hello") << Qt::hex << 42; { QDebugStateSaver saver(d); d.resetFormat(); @@ -660,7 +660,7 @@ void tst_QDebug::textStreamModifiers() const QString file, function; int line = 0; MessageHandlerSetter mhs(myMessageHandler); - { qDebug() << hex << short(0xf) << int(0xf) << unsigned(0xf) << long(0xf) << qint64(0xf) << quint64(0xf); } + { qDebug() << Qt::hex << short(0xf) << int(0xf) << unsigned(0xf) << long(0xf) << qint64(0xf) << quint64(0xf); } #ifndef QT_NO_MESSAGELOGCONTEXT file = __FILE__; line = __LINE__ - 2; function = Q_FUNC_INFO; #endif @@ -678,7 +678,7 @@ void tst_QDebug::resetFormat() const MessageHandlerSetter mhs(myMessageHandler); { QDebug d = qDebug(); - d.nospace().noquote() << hex << int(0xf); + d.nospace().noquote() << Qt::hex << int(0xf); d.resetFormat() << int(0xf) << QStringLiteral("foo"); } #ifndef QT_NO_MESSAGELOGCONTEXT diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index 678a80c3f7..4f010f37c2 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -2099,7 +2099,7 @@ void tst_QFile::i18nFileName() QVERIFY2(file.open(QFile::WriteOnly | QFile::Text), msgOpenFailed(file).constData()); QTextStream ts(&file); ts.setCodec("UTF-8"); - ts << fileName << endl; + ts << fileName << Qt::endl; } { QFile file(fileName); @@ -2149,7 +2149,7 @@ void tst_QFile::longFileName() QFile file(fileName); QVERIFY2(file.open(QFile::WriteOnly | QFile::Text), msgOpenFailed(file).constData()); QTextStream ts(&file); - ts << fileName << endl; + ts << fileName << Qt::endl; } { QFile file(fileName); diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index a92b4bd1cb..64075a94f0 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -1182,7 +1182,7 @@ void tst_QFileInfo::fileTimes() QTest::qSleep(sleepTime); beforeWrite = QDateTime::currentDateTime().addMSecs(-fsClockSkew); QTextStream ts(&file); - ts << fileName << endl; + ts << fileName << Qt::endl; } { QFileInfo fileInfo(fileName); diff --git a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp index 08635d34c5..79ac6b0fc4 100644 --- a/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp +++ b/tests/auto/corelib/io/qloggingcategory/tst_qloggingcategory.cpp @@ -104,7 +104,7 @@ public: for (int a = 0; a < _configitemEntryOrder.count(); a++) { out << _configitemEntryOrder[a] << " = " - << _values.value(_configitemEntryOrder[a]) << endl; + << _values.value(_configitemEntryOrder[a]) << Qt::endl; } out.flush(); return ret.toLatin1(); diff --git a/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp b/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp index 41ea5e56f0..2d4aa452ca 100644 --- a/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp +++ b/tests/auto/corelib/serialization/qtextstream/readLineStdinProcess/main.cpp @@ -41,7 +41,7 @@ int main(int argc, char **argv) do { line = qin.readLine(); if (!line.isNull()) - qerr << line << flush; + qerr << line << Qt::flush; } while (!line.isNull()); return 0; } diff --git a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp index af97d4a003..c4fb623130 100644 --- a/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp +++ b/tests/auto/corelib/serialization/qtextstream/tst_qtextstream.cpp @@ -245,7 +245,7 @@ private: void runOnExit() { QByteArray buffer; - QTextStream(&buffer) << "This will try to use QTextCodec::codecForLocale" << endl; + QTextStream(&buffer) << "This will try to use QTextCodec::codecForLocale" << Qt::endl; } Q_DESTRUCTOR_FUNCTION(runOnExit) @@ -1506,9 +1506,9 @@ void tst_QTextStream::readStdin() stdinProcess.setReadChannel(QProcess::StandardError); QTextStream stream(&stdinProcess); - stream << "1" << endl; - stream << "2" << endl; - stream << "3" << endl; + stream << "1" << Qt::endl; + stream << "2" << Qt::endl; + stream << "3" << Qt::endl; stdinProcess.closeWriteChannel(); @@ -1534,7 +1534,7 @@ void tst_QTextStream::readAllFromStdin() QTextStream stream(&stdinProcess); stream.setCodec("ISO-8859-1"); - stream << "hello world" << flush; + stream << "hello world" << Qt::flush; stdinProcess.closeWriteChannel(); @@ -1824,7 +1824,7 @@ void tst_QTextStream::utf8IncompleteAtBufferBoundary() out.setFieldWidth(3); for (int i = 0; i < 1000; ++i) { - out << i << lineContents << endl; + out << i << lineContents << Qt::endl; } } data.close(); @@ -2726,7 +2726,7 @@ void tst_QTextStream::generateBOM() QTextStream stream(&file); stream.setCodec(QTextCodec::codecForName("UTF-16LE")); - stream << "Hello" << endl; + stream << "Hello" << Qt::endl; file.close(); QVERIFY(file.open(QFile::ReadOnly)); @@ -2740,7 +2740,7 @@ void tst_QTextStream::generateBOM() QTextStream stream(&file); stream.setCodec(QTextCodec::codecForName("UTF-16LE")); - stream << bom << "Hello" << endl; + stream << Qt::bom << "Hello" << Qt::endl; file.close(); QVERIFY(file.open(QFile::ReadOnly)); diff --git a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp index e4d50607b7..92a0d8bbfa 100644 --- a/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/corelib/serialization/qxmlstream/tst_qxmlstream.cpp @@ -115,7 +115,7 @@ static QByteArray makeCanonical(const QString &filename, writeDtd << "'; - writeDtd << endl; + writeDtd << Qt::endl; } writeDtd << "]>"; - writeDtd << endl; + writeDtd << Qt::endl; writer.writeDTD(dtd); } } else if (reader.isStartElement()) { @@ -740,7 +740,7 @@ QByteArray tst_QXmlStream::readFile(const QString &filename) const auto attributes = reader.attributes(); if (attributes.size()) { for (const QXmlStreamAttribute &attribute : attributes) { - writer << endl << " Attribute("; + writer << Qt::endl << " Attribute("; if (!attribute.name().isEmpty()) writer << " name=\"" << attribute.name().toString() << '"'; if (!attribute.namespaceUri().isEmpty()) @@ -751,37 +751,37 @@ QByteArray tst_QXmlStream::readFile(const QString &filename) writer << " prefix=\"" << attribute.prefix().toString() << '"'; if (!attribute.value().isEmpty()) writer << " value=\"" << attribute.value().toString() << '"'; - writer << " )" << endl; + writer << " )" << Qt::endl; } } const auto namespaceDeclarations = reader.namespaceDeclarations(); if (namespaceDeclarations.size()) { for (const QXmlStreamNamespaceDeclaration &namespaceDeclaration : namespaceDeclarations) { - writer << endl << " NamespaceDeclaration("; + writer << Qt::endl << " NamespaceDeclaration("; if (!namespaceDeclaration.prefix().isEmpty()) writer << " prefix=\"" << namespaceDeclaration.prefix().toString() << '"'; if (!namespaceDeclaration.namespaceUri().isEmpty()) writer << " namespaceUri=\"" << namespaceDeclaration.namespaceUri().toString() << '"'; - writer << " )" << endl; + writer << " )" << Qt::endl; } } const auto notationDeclarations = reader.notationDeclarations(); if (notationDeclarations.size()) { for (const QXmlStreamNotationDeclaration ¬ationDeclaration : notationDeclarations) { - writer << endl << " NotationDeclaration("; + writer << Qt::endl << " NotationDeclaration("; if (!notationDeclaration.name().isEmpty()) writer << " name=\"" << notationDeclaration.name().toString() << '"'; if (!notationDeclaration.systemId().isEmpty()) writer << " systemId=\"" << notationDeclaration.systemId().toString() << '"'; if (!notationDeclaration.publicId().isEmpty()) writer << " publicId=\"" << notationDeclaration.publicId().toString() << '"'; - writer << " )" << endl; + writer << " )" << Qt::endl; } } const auto entityDeclarations = reader.entityDeclarations(); if (entityDeclarations.size()) { for (const QXmlStreamEntityDeclaration &entityDeclaration : entityDeclarations) { - writer << endl << " EntityDeclaration("; + writer << Qt::endl << " EntityDeclaration("; if (!entityDeclaration.name().isEmpty()) writer << " name=\"" << entityDeclaration.name().toString() << '"'; if (!entityDeclaration.notationName().isEmpty()) @@ -792,13 +792,13 @@ QByteArray tst_QXmlStream::readFile(const QString &filename) writer << " publicId=\"" << entityDeclaration.publicId().toString() << '"'; if (!entityDeclaration.value().isEmpty()) writer << " value=\"" << entityDeclaration.value().toString() << '"'; - writer << " )" << endl; + writer << " )" << Qt::endl; } } - writer << " )" << endl; + writer << " )" << Qt::endl; } if (reader.hasError()) - writer << "ERROR: " << reader.errorString() << endl; + writer << "ERROR: " << reader.errorString() << Qt::endl; return outarray; } @@ -1169,7 +1169,7 @@ int main(int argc, char *argv[]) bool error = false; QByteArray canonical = makeCanonical(argv[2], "doc", error); QTextStream myStdOut(stdout); - myStdOut << canonical << endl; + myStdOut << canonical << Qt::endl; exit(0); } diff --git a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp index 72299402f0..06db0e8546 100644 --- a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp +++ b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp @@ -208,7 +208,7 @@ void printHeader(QStringList &headers) for (int h = 0; h < headers.count(); ++h) { cout << setw(20) << setiosflags(ios_base::left) << headers.at(h).toLatin1().constData(); } - cout << endl; + cout << Qt::endl; } template @@ -220,7 +220,7 @@ void print(ContainerType testContainer) cout << value << " "; } - cout << endl; + cout << Qt::endl; } template @@ -252,7 +252,7 @@ void testAlgorithm(Algorithm algorithm, QStringList &dataSetTypes) lessThan << setiosflags(ios_base::left) << setw(10) << result.lessThanRefCount / result.numSorts; cout << numSorts.str() << lessThan.str(); } - cout << endl; + cout << Qt::endl; } } #endif @@ -765,21 +765,21 @@ public: #if Q_TEST_PERFORMANCE void tst_QAlgorithms::performance() { - cout << endl << "Quick sort" << endl; + cout << Qt::endl << "Quick sort" << Qt::endl; testAlgorithm, TestInt>(QuickSortHelper(), dataSetTypes); - cout << endl << "stable sort" << endl; + cout << Qt::endl << "stable sort" << Qt::endl; testAlgorithm, TestInt>(StableSortHelper(), dataSetTypes); - cout << endl << "std::sort" << endl; + cout << Qt::endl << "std::sort" << Qt::endl; testAlgorithm, TestInt>(StlSortHelper(), dataSetTypes); - cout << endl << "std::stable_sort" << endl; + cout << Qt::endl << "std::stable_sort" << Qt::endl; testAlgorithm, TestInt>(StlStableSortHelper(), dataSetTypes); /* - cout << endl << "Sorting lists of ints" << endl; - cout << endl << "Quick sort" << endl; + cout << Qt::endl << "Sorting lists of ints" << Qt::endl; + cout << Qt::endl << "Quick sort" << Qt::endl; testAlgorithm, int>(QuickSortHelper(), dataSetTypes); - cout << endl << "std::sort" << endl; + cout << Qt::endl << "std::sort" << Qt::endl; testAlgorithm, int>(StlSortHelper(), dataSetTypes); - cout << endl << "std::stable_sort" << endl; + cout << Qt::endl << "std::stable_sort" << Qt::endl; testAlgorithm, int>(StlStableSortHelper(), dataSetTypes); */ } diff --git a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp index bad021c3b0..9a4c560a08 100644 --- a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp +++ b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp @@ -121,7 +121,7 @@ static QByteArray modifiersTestRowName(const QString &keySequence) if (uc > 32 && uc < 128) str << '"' << c << '"'; else - str << "U+" << hex << uc << dec; + str << "U+" << Qt::hex << uc << Qt::dec; if (i < size - 1) str << ','; } diff --git a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp index d00dc251d8..b091edb64d 100644 --- a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp +++ b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp @@ -681,7 +681,7 @@ static bool checkPixels(const QImage &image, if (pixel != expectedRgb1 && pixel != expectedRgb2) { QString message; QDebug(&message) << "Color mismatch in image" << image - << "at" << x << ',' << y << ':' << showbase << hex << pixel + << "at" << x << ',' << y << ':' << Qt::showbase << Qt::hex << pixel << "(expected: " << expectedRgb1 << ',' << expectedRgb2 << ')'; *errorMessage = message.toLocal8Bit(); return false; diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp index 45ab275510..f53c75c6a4 100644 --- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp @@ -552,7 +552,7 @@ void tst_QLocalSocket::sendData() QCOMPARE(serverSocket->state(), QLocalSocket::ConnectedState); QTextStream out(serverSocket); QTextStream in(&socket); - out << testLine << endl; + out << testLine << Qt::endl; bool wrote = serverSocket->waitForBytesWritten(3000); if (!socket.canReadLine()) { @@ -877,7 +877,7 @@ public: QLocalSocket *serverSocket = server.nextPendingConnection(); QVERIFY(serverSocket); QTextStream out(serverSocket); - out << testLine << endl; + out << testLine << Qt::endl; QCOMPARE(serverSocket->state(), QLocalSocket::ConnectedState); QVERIFY2(serverSocket->waitForBytesWritten(), serverSocket->errorString().toLatin1().constData()); QCOMPARE(serverSocket->errorString(), QString("Unknown error")); diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp index bca664c05b..0cfdecbcab 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp @@ -8386,7 +8386,7 @@ void tst_QGraphicsItem::focusProxy() QString err; QTextStream stream(&err); stream << "QGraphicsItem::setFocusProxy: " - << (void*)item << " is already in the focus proxy chain" << flush; + << (void*)item << " is already in the focus proxy chain" << Qt::flush; QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData()); item2->setFocusProxy(item); // fails QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2); diff --git a/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp b/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp index 15f10232bd..b5d9fea315 100644 --- a/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp +++ b/tests/auto/xml/sax/qxmlsimplereader/parser/main.cpp @@ -72,7 +72,7 @@ int main(int argc, const char *argv[]) QFile in_file(file_name); if (!in_file.open(QIODevice::ReadOnly)) { - qerr << "Could not open " << file_name << ": " << strerror(errno) << endl; + qerr << "Could not open " << file_name << ": " << strerror(errno) << Qt::endl; return 1; } @@ -87,7 +87,7 @@ int main(int argc, const char *argv[]) } else { _out_file.setFileName(out_file_name); if (!_out_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - qerr << "Could not open " << out_file_name << ": " << strerror(errno) << endl; + qerr << "Could not open " << out_file_name << ": " << strerror(errno) << Qt::endl; return 1; } _out_stream.setDevice(&_out_file); From 1f1e04f29f93401c8d0aa0941f92cc1e4a6c7688 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 2 May 2019 14:31:34 +0200 Subject: [PATCH 064/122] Deprecate providing a function as a property flag Property flags such as SCRIPTABLE should not get controlled by a function. I can't see this feature being used anywhere and it leads to additional overhead that I'd like to get rid of for Qt 6. Change-Id: Iaa10b2b3bfb7eec11401f7b6bb887c9467b67183 Reviewed-by: Thiago Macieira Reviewed-by: Simon Hausmann --- src/tools/moc/moc.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 7f43917f7e..2f0ea633fa 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -1194,6 +1194,15 @@ void Moc::createPropertyDef(PropertyDef &propDef) propDef.type = type; + auto checkIsFunction = [&](const QByteArray &def, const char *name) { + if (def.endsWith(')')) { + QByteArray msg = "Providing a function for "; + msg += name; + msg += " in a property declaration is deprecated and will not be supported in Qt 6 anymore."; + warning(msg.constData()); + } + }; + next(); propDef.name = lexem(); while (test(IDENTIFIER)) { @@ -1243,11 +1252,13 @@ void Moc::createPropertyDef(PropertyDef &propDef) error(2); break; case 'S': - if (l == "SCRIPTABLE") + if (l == "SCRIPTABLE") { propDef.scriptable = v + v2; - else if (l == "STORED") + checkIsFunction(propDef.scriptable, "SCRIPTABLE"); + } else if (l == "STORED") { propDef.stored = v + v2; - else + checkIsFunction(propDef.stored, "STORED"); + } else error(2); break; case 'W': if (l != "WRITE") error(2); @@ -1255,15 +1266,18 @@ void Moc::createPropertyDef(PropertyDef &propDef) break; case 'D': if (l != "DESIGNABLE") error(2); propDef.designable = v + v2; + checkIsFunction(propDef.designable, "DESIGNABLE"); break; case 'E': if (l != "EDITABLE") error(2); propDef.editable = v + v2; + checkIsFunction(propDef.editable, "EDITABLE"); break; case 'N': if (l != "NOTIFY") error(2); propDef.notify = v; break; case 'U': if (l != "USER") error(2); propDef.user = v + v2; + checkIsFunction(propDef.user, "USER"); break; default: error(2); From e929808c83e4a473135590c69413a98f36a3500a Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 3 May 2019 11:43:03 +0200 Subject: [PATCH 065/122] Prefix QTextStream operators with Qt:: Change-Id: I128769cb78abb8168f0bf29cef8c693073793ced Reviewed-by: Allan Sandfeld Jensen --- src/gui/text/qtextmarkdownwriter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index fed4a7b766..313d62bb8a 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -80,10 +80,10 @@ void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) QString s = table.headerData(col, Qt::Horizontal).toString(); m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); } - m_stream << "|" << endl; + m_stream << "|" << Qt::endl; for (int col = 0; col < tableColumnWidths.length(); ++col) m_stream << '|' << QString(tableColumnWidths[col], QLatin1Char('-')); - m_stream << '|'<< endl; + m_stream << '|'<< Qt::endl; // write the body for (int row = 0; row < table.rowCount(); ++row) { @@ -91,7 +91,7 @@ void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) QString s = table.data(table.index(row, col)).toString(); m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); } - m_stream << '|'<< endl; + m_stream << '|'<< Qt::endl; } } From b5547e49cd1760ba5d100dcc720e6366cbd23f06 Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Thu, 25 Apr 2019 16:33:20 +0200 Subject: [PATCH 066/122] Fix minor compiler warning from Clang Fixes: .../qcolorspace_p.h:70:25: warning: explicitly defaulted copy assignment operator is implicitly deleted [-Wdefaulted-function-deleted] QColorSpacePrivate &operator=(const QColorSpacePrivate &other) = default; ^ .../qcolorspace_p.h:63:28: note: copy assignment operator of 'QColorSpacePrivate' is implicitly deleted because base class 'QSharedData' has an inaccessible copy assignment operator class QColorSpacePrivate : public QSharedData ^ Change-Id: I20d453279ec2cb8b9b9d1364762c6e560d6f843d Reviewed-by: Simon Hausmann --- src/gui/painting/qcolorspace_p.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/painting/qcolorspace_p.h b/src/gui/painting/qcolorspace_p.h index 21260a281d..a6ab2ab5cd 100644 --- a/src/gui/painting/qcolorspace_p.h +++ b/src/gui/painting/qcolorspace_p.h @@ -93,7 +93,6 @@ public: QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma); QColorSpacePrivate(const QColorSpacePrimaries &primaries, QColorSpace::TransferFunction fun, float gamma); QColorSpacePrivate(const QColorSpacePrivate &other) = default; - QColorSpacePrivate &operator=(const QColorSpacePrivate &other) = default; void initialize(); void setToXyzMatrix(); From 82ddecfb17158c35de1d0740dd7ecd5562d41726 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 3 May 2019 11:53:18 +0200 Subject: [PATCH 067/122] Deprecate {to,from}Std{List,Vector} ask our users to use the range constructors instead. This will allow us to remove the include dependency towards and in Qt 6. Change-Id: Id90f2058432e19941de1fa847100a7920432ad71 Reviewed-by: Thiago Macieira --- src/corelib/tools/qlist.h | 6 ++++++ src/corelib/tools/qvector.h | 6 ++++++ tests/auto/corelib/tools/qlist/tst_qlist.cpp | 6 ++++++ tests/auto/corelib/tools/qvector/tst_qvector.cpp | 8 +++++++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 27868f7313..513d7eafe1 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -51,7 +51,9 @@ #include #include #include +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) #include +#endif #include #include @@ -403,10 +405,14 @@ public: static QList fromVector(const QVector &vector); static QList fromSet(const QSet &set); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + Q_DECL_DEPRECATED_X("Use QList(list.begin(), list.end()) instead.") static inline QList fromStdList(const std::list &list) { QList tmp; std::copy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; } + Q_DECL_DEPRECATED_X("Use std::list(list.begin(), list.end()) instead.") inline std::list toStdList() const { std::list tmp; std::copy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } +#endif private: Node *detach_helper_grow(int i, int n); diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index d6baa76a30..4e148c9c55 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -49,7 +49,9 @@ #include #include +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) #include +#endif #include #include @@ -292,10 +294,14 @@ public: static QVector fromList(const QList &list); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + Q_DECL_DEPRECATED_X("Use QVector(vector.begin(), vector.end()) instead.") static inline QVector fromStdVector(const std::vector &vector) { QVector tmp; tmp.reserve(int(vector.size())); std::copy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; } + Q_DECL_DEPRECATED_X("Use std::vector(vector.begin(), vector.end()) instead.") inline std::vector toStdVector() const { return std::vector(d->begin(), d->end()); } +#endif private: // ### Qt6: remove methods, they are unused void reallocData(const int size, const int alloc, QArrayData::AllocationOptions options = QArrayData::Default); diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp index 995aa245d1..7fb3e67462 100644 --- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp +++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp @@ -367,9 +367,11 @@ private slots: void toSetOptimal() const; void toSetMovable() const; void toSetComplex() const; +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) void toStdListOptimal() const; void toStdListMovable() const; void toStdListComplex() const; +#endif void toVectorOptimal() const; void toVectorMovable() const; void toVectorComplex() const; @@ -427,7 +429,9 @@ private: template void takeFirst() const; template void takeLast() const; template void toSet() const; +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) template void toStdList() const; +#endif template void toVector() const; template void value() const; @@ -1633,6 +1637,7 @@ void tst_QList::toSetComplex() const QCOMPARE(liveCount, Complex::getLiveCount()); } +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) template void tst_QList::toStdList() const { @@ -1669,6 +1674,7 @@ void tst_QList::toStdListComplex() const toStdList(); QCOMPARE(liveCount, Complex::getLiveCount()); } +#endif template void tst_QList::toVector() const diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index 172b03a445..f81ce11510 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -257,7 +257,6 @@ private slots: void fromListInt() const; void fromListMovable() const; void fromListCustom() const; - void fromStdVector() const; void indexOf() const; void insertInt() const; void insertMovable() const; @@ -296,7 +295,10 @@ private slots: void swapMovable() const; void swapCustom() const; void toList() const; +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + void fromStdVector() const; void toStdVector() const; +#endif void value() const; void testOperators() const; @@ -1426,6 +1428,7 @@ void tst_QVector::fromListCustom() const QCOMPARE(instancesCount, Custom::counter.loadAcquire()); } +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) void tst_QVector::fromStdVector() const { // stl = :( @@ -1439,6 +1442,7 @@ void tst_QVector::fromStdVector() const // test it converts ok QCOMPARE(myvec, QVector() << "aaa" << "bbb" << "ninjas" << "pirates"); } +#endif void tst_QVector::indexOf() const { @@ -2331,6 +2335,7 @@ void tst_QVector::toList() const QCOMPARE(myvec, QVector() << "A" << "B" << "C"); } +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) void tst_QVector::toStdVector() const { QVector myvec; @@ -2343,6 +2348,7 @@ void tst_QVector::toStdVector() const QCOMPARE(myvec, QVector() << "A" << "B" << "C"); } +#endif void tst_QVector::value() const { From 08101b2b27f7f2177993ddb62c15187c169ccd19 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 14:13:22 +0200 Subject: [PATCH 068/122] Fix qplugin.h for Qt 6 Change-Id: I3ae6594a2982f990a5b3851a063b0b2f02d16bd9 Reviewed-by: Thiago Macieira --- src/corelib/plugin/qplugin.h | 32 +++++++++++++++---- .../qguiapplication/tst_qguiapplication.cpp | 4 +++ tests/auto/tools/moc/tst_moc.cpp | 11 +++++++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index 676b5047d6..c176155c28 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -75,7 +75,12 @@ typedef QObject *(*QtPluginInstanceFunction)(); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) typedef const char *(*QtPluginMetaDataFunction)(); #else -typedef QPair (*QtPluginMetaDataFunction)(); +struct QPluginMetaData +{ + const uchar *data; + size_t size; +}; +typedef QPluginMetaData (*QtPluginMetaDataFunction)(); #endif @@ -84,12 +89,14 @@ struct Q_CORE_EXPORT QStaticPlugin #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) public: constexpr QStaticPlugin(QtPluginInstanceFunction i, QtPluginMetaDataFunction m) - : instance(i), rawMetaData(m().first), rawMetaDataSize(m().second) + : instance(i), rawMetaData(m().data), rawMetaDataSize(m().size) + {} QtPluginInstanceFunction instance; private: // ### Qt 6: revise, as this is not standard-layout const void *rawMetaData; - qsizetype rawMetaDataSize + qsizetype rawMetaDataSize; +public: #elif !defined(Q_QDOC) // Note: This struct is initialized using an initializer list. // As such, it cannot have any new constructors or variables. @@ -154,6 +161,16 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); #if defined(QT_STATICPLUGIN) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ + static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \ + Q_PLUGIN_INSTANCE(PLUGINCLASS) \ + static QPluginMetaData qt_plugin_query_metadata_##PLUGINCLASSNAME() \ + { return { qt_pluginMetaData, sizeof qt_pluginMetaData }; } \ + const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGINCLASSNAME() { \ + return { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \ + } +#else # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \ Q_PLUGIN_INSTANCE(PLUGINCLASS) \ @@ -162,13 +179,15 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); QT_PREPEND_NAMESPACE(QStaticPlugin) plugin = { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \ return plugin; \ } +#endif -#elif QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#else +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ Q_EXTERN_C Q_DECL_EXPORT \ - auto qt_plugin_query_metadata() \ - { return qMakePair(qt_pluginMetaData, sizeof qt_pluginMetaData); } \ + QPluginMetaData qt_plugin_query_metadata() \ + { return { qt_pluginMetaData, sizeof qt_pluginMetaData }; } \ Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \ Q_PLUGIN_INSTANCE(PLUGINCLASS) @@ -183,6 +202,7 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); #endif +#endif #define Q_EXPORT_PLUGIN(PLUGIN) \ Q_EXPORT_PLUGIN2(PLUGIN, PLUGIN) diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp index a304981cd1..09fec89de4 100644 --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp @@ -989,9 +989,13 @@ void tst_QGuiApplication::genericPluginsAndWindowSystemEvents() QCoreApplication::postEvent(&testReceiver, new QEvent(QEvent::User)); QCOMPARE(testReceiver.customEvents, 0); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + QStaticPlugin testPluginInfo(qt_plugin_instance, qt_plugin_query_metadata); +#else QStaticPlugin testPluginInfo; testPluginInfo.instance = qt_plugin_instance; testPluginInfo.rawMetaData = qt_plugin_query_metadata; +#endif qRegisterStaticPluginFunction(testPluginInfo); int argc = 3; char *argv[] = { const_cast(QTest::currentAppName()), const_cast("-plugin"), const_cast("testplugin") }; diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index f12df578f4..6b7aaf7c0a 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -1425,6 +1425,16 @@ void tst_Moc::environmentIncludePaths() // plugin_metadata.h contains a plugin which we register here. Since we're not building this // application as a plugin, we need top copy some of the initializer code found in qplugin.h: extern "C" QObject *qt_plugin_instance(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +extern "C" QPluginMetaData qt_plugin_query_metadata(); +class StaticPluginInstance{ +public: + StaticPluginInstance() { + QStaticPlugin plugin(qt_plugin_instance, qt_plugin_query_metadata); + qRegisterStaticPluginFunction(plugin); + } +}; +#else extern "C" const char *qt_plugin_query_metadata(); class StaticPluginInstance{ public: @@ -1433,6 +1443,7 @@ public: qRegisterStaticPluginFunction(plugin); } }; +#endif static StaticPluginInstance staticInstance; void tst_Moc::specifyMetaTagsFromCmdline() { From 298ab596a1e1fb147fde6d3c0d6c859d1e045781 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 5 May 2019 10:57:38 +0200 Subject: [PATCH 069/122] QtSql: mark QSqlite2 plugin as obsolete Mark QSqlite2 plugin as obsolete so it can be removed with Qt6. The last sqlite2 release was 2005 so it's time to remove this plugin in Qt6. [ChangeLog][QtSql][SQlite2] Marked QSQLITE2 plugin as obsolete - it will be removed with Qt6 together with the QTDS plugin Change-Id: I9861331d4eb2b13f38b9e0e09ad9472b70e9b6e2 Reviewed-by: Lars Knoll --- src/plugins/sqldrivers/sqlite2/smain.cpp | 1 + src/plugins/sqldrivers/tds/main.cpp | 1 + src/sql/doc/src/sql-driver.qdoc | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/sqldrivers/sqlite2/smain.cpp b/src/plugins/sqldrivers/sqlite2/smain.cpp index 3a5734f8c9..7d971d6e5a 100644 --- a/src/plugins/sqldrivers/sqlite2/smain.cpp +++ b/src/plugins/sqldrivers/sqlite2/smain.cpp @@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE +// ### Qt6: remove, obsolete since 5.14 class QSQLite2DriverPlugin : public QSqlDriverPlugin { Q_OBJECT diff --git a/src/plugins/sqldrivers/tds/main.cpp b/src/plugins/sqldrivers/tds/main.cpp index 4aa1444608..18efb22ea4 100644 --- a/src/plugins/sqldrivers/tds/main.cpp +++ b/src/plugins/sqldrivers/tds/main.cpp @@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE +// ### Qt6: remove, obsolete since 4.7 class QTDSDriverPlugin : public QSqlDriverPlugin { Q_OBJECT diff --git a/src/sql/doc/src/sql-driver.qdoc b/src/sql/doc/src/sql-driver.qdoc index cccce48bb3..c6ac4d17ff 100644 --- a/src/sql/doc/src/sql-driver.qdoc +++ b/src/sql/doc/src/sql-driver.qdoc @@ -54,9 +54,9 @@ \li Open Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases \row \li \l{#QPSQL}{QPSQL} \li PostgreSQL (versions 7.3 and above) - \row \li \l{#QSQLITE2}{QSQLITE2} \li SQLite version 2 + \row \li \l{#QSQLITE2}{QSQLITE2} \li SQLite version 2 \note obsolete since Qt 5.14 \row \li \l{#QSQLITE}{QSQLITE} \li SQLite version 3 - \row \li \l{#QTDS}{QTDS} \li Sybase Adaptive Server \note obsolete from Qt 4.7 + \row \li \l{#QTDS}{QTDS} \li Sybase Adaptive Server \note obsolete since Qt 4.7 \endtable SQLite is the in-process database system with the best test coverage From a43c3b456a9b0c341b05ac7bee07b863ebca3b7c Mon Sep 17 00:00:00 2001 From: Mikhail Svetkin Date: Mon, 19 Mar 2018 11:59:11 +0100 Subject: [PATCH 070/122] rtems: add mkspecs for new operation system RTEMS Change-Id: Idd01ccd69c296df1a67a90260fc4e5547acf3079 Reviewed-by: Volker Hilsheimer Reviewed-by: Ryan Chu --- mkspecs/common/rtems-base.conf | 73 ++++++++++++++++++++++++++++ mkspecs/common/rtems/qplatformdefs.h | 70 ++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 mkspecs/common/rtems-base.conf create mode 100644 mkspecs/common/rtems/qplatformdefs.h diff --git a/mkspecs/common/rtems-base.conf b/mkspecs/common/rtems-base.conf new file mode 100644 index 0000000000..0a015c3173 --- /dev/null +++ b/mkspecs/common/rtems-base.conf @@ -0,0 +1,73 @@ +# +# Base qmake configuration for GCC on RTEMS +# +# +# +MAKEFILE_GENERATOR = UNIX + +QMAKE_PLATFORM = rtems + +include(unix.conf) +include(gcc-base-unix.conf) +include(g++-unix.conf) + +rtems_bsp = $$(RTEMS_BSP) +isEmpty(rtems_bsp) { + error("This qmakespec requires $RTEMS_BSP to be set") +} + +rtems_compiler = $$(RTEMS_COMPILER) +isEmpty(rtems_compiler) { + error("This qmakespec requires $RTEMS_COMPILER to be set") +} + +isEmpty(RTEMS_CPU_FLAGS) { + error("The qmakespec is expected to set \$\$RTEMS_CPU_FLAGS") +} + +RTEMS_FLAGS = \ + -B$$rtems_bsp \ + -specs bsp_specs \ + -qrtems \ + $$RTEMS_CPU_FLAGS + +QMAKE_CFLAGS_OPTIMIZE_FULL = $$QMAKE_CFLAGS_OPTIMIZE +QMAKE_CFLAGS_OPTIMIZE_DEBUG = -O0 -g + +QMAKE_CFLAGS_DEBUG = $$QMAKE_CFLAGS_OPTIMIZE_DEBUG +QMAKE_CFLAGS_WARN_ON = -Wall +QMAKE_CFLAGS_PIC = +QMAKE_CFLAGS_SHLIB = +QMAKE_CFLAGS_STATIC_LIB = +QMAKE_CFLAGS_APP = +QMAKE_CFLAGS += $$RTEMS_FLAGS + +QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG +QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON +QMAKE_CXXFLAGS_SHLIB = +QMAKE_CXXFLAGS_STATIC_LIB = +QMAKE_CXXFLAGS_APP = +QMAKE_CXXFLAGS += $$RTEMS_FLAGS + +QMAKE_CXXFLAGS_CXX11 = +QMAKE_CXXFLAGS_CXX14 = +QMAKE_CXXFLAGS_CXX1Z = + +QMAKE_LFLAGS_GCSECTIONS = -Wl,--gc-sections +QMAKE_LFLAGS += $$RTEMS_FLAGS $$QMAKE_LFLAGS_GCSECTIONS + +QMAKE_CC = $${rtems_compiler}-gcc +QMAKE_CXX = $${rtems_compiler}-g++ +QMAKE_AR = $${rtems_compiler}-ar cqs +QMAKE_OBJCOPY = $${rtems_compiler}-objcopy +QMAKE_NM = $${rtems_compiler}-nm -P +QMAKE_RANLIB = $${rtems_compiler}-ranlib +QMAKE_STRIP = $${rtems_compiler}-strip + +QMAKE_LINK_C = $$QMAKE_CC +QMAKE_LINK_C_SHLIB = + +QMAKE_LINK = $$QMAKE_CXX +QMAKE_LINK_SHLIB = + +load(qt_config) diff --git a/mkspecs/common/rtems/qplatformdefs.h b/mkspecs/common/rtems/qplatformdefs.h new file mode 100644 index 0000000000..1baa7c7d74 --- /dev/null +++ b/mkspecs/common/rtems/qplatformdefs.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company. All rights reserved. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the qmake spec 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 Q_RTEMS_PLATFORMDEFS_H +#define Q_RTEMS_PLATFORMDEFS_H + +// Get Qt defines/settings + +#include "qglobal.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "../posix/qplatformdefs.h" + + +#ifdef __STRICT_ANSI__ +#undef __STRICT_ANSI__ +#endif + +#undef QT_OPEN_LARGEFILE +#define QT_OPEN_LARGEFILE 0 + +#endif // Q_RTEMS_PLATFORMDEFS_H From 5146582b8d0bb0cde518d57c379e5b97047c6c27 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 3 May 2019 15:57:15 +0200 Subject: [PATCH 071/122] Compile-fix: add private/ prefix to qnetconmonitor_p.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build was failing without it. Change-Id: I23a6e8a359e6208f78fa9ef571b8b27f8ecb3628 Reviewed-by: Mårten Nordheim --- src/network/access/qnetworkaccessmanager_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index d3a3936533..dfd747a767 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -55,7 +55,7 @@ #include "qnetworkaccessmanager.h" #include "qnetworkaccesscache_p.h" #include "qnetworkaccessbackend_p.h" -#include "qnetconmonitor_p.h" +#include "private/qnetconmonitor_p.h" #include "qnetworkrequest.h" #include "qhsts_p.h" #include "private/qobject_p.h" From b922c97c9c65ce28f4ea18106f384adf1bbf605a Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Sat, 4 May 2019 08:48:41 +0200 Subject: [PATCH 072/122] TextEdit example: add indent/unindent feature It was not possible to interactively create the example text without this feature; and in general it's necessary to work with nested lists. But currently it does not deal with all possible changes of list nesting, because the API seems incomplete for that purpose. Task-number: QTBUG-75589 Change-Id: I3e29ca15a2e7c37300a0103ceb90670716472ffb Reviewed-by: Gatis Paeglis --- .../images/mac/format-indent-less.png | Bin 0 -> 1201 bytes .../images/mac/format-indent-more.png | Bin 0 -> 993 bytes .../images/win/format-indent-less.png | Bin 0 -> 1201 bytes .../images/win/format-indent-more.png | Bin 0 -> 993 bytes .../widgets/richtext/textedit/textedit.cpp | 46 ++++++++++++++++++ examples/widgets/richtext/textedit/textedit.h | 5 ++ .../widgets/richtext/textedit/textedit.qrc | 4 ++ 7 files changed, 55 insertions(+) create mode 100644 examples/widgets/richtext/textedit/images/mac/format-indent-less.png create mode 100644 examples/widgets/richtext/textedit/images/mac/format-indent-more.png create mode 100644 examples/widgets/richtext/textedit/images/win/format-indent-less.png create mode 100644 examples/widgets/richtext/textedit/images/win/format-indent-more.png diff --git a/examples/widgets/richtext/textedit/images/mac/format-indent-less.png b/examples/widgets/richtext/textedit/images/mac/format-indent-less.png new file mode 100644 index 0000000000000000000000000000000000000000..e38074e78b78b384a1f7e8ab680fdd35175c0347 GIT binary patch literal 1201 zcmV;i1Wx;jP)1#w$1 zXjCZr%@it11(#rA5Tld5kx6d)ZG*GWj8c>B%)OlRyxmtH&S{Qq=8j^0$Qz#L!}HwF zb6@xM|NpQ5eTk~_Uk<~6Je*QLsBLP_xPhcbKhxqZ8MEW&%MJdcpa~~TmmEOOBlXU% z7Oo9}wGf6Di(-mP#bO38uwX5*n1eCk`(O;H7A|9yL;`8qyrrsS2vikgz=;&Lcji|p zOGH2*>KM*k02_vsmpOdfOf)ei#RSQA zhqJ}xj!w0X-9d4>s5jJ`mjAs9q^5Cu#tkH;<7izvtCLZiZrlG>bxAVJd8BsjX`ydG z@q>^lNe9;t$$O=F7{M`yQ<;!>^wwDIdhSgZ>}ZsRvrUn%&PMsB z^I2Icm3134PJA@0uP3=wR{O)*bjR19-VlP$)v_fq=YbvbUp-3De~Iols(x~QIJSHK z9cNmrn2rp4r!J^mKX2WKNRY+7d=7>1j?3`J21&-_9GtnNZpEBcJCSTR16?OMe{`Q8 zc)8_L)3`m8A5+`^&U)DdDgd-Brs*ReyjeYo#b-D%j#oVXd}T%L%jh59(RVJ*`Sue7 z8ie%^9n^Lw=aJgIr-gjJ0Dl--qES<1xFrY*N)Um80hfEG$K|zGw%nBMC+p>2Yxwg1 z2;6xx|;Fn$p z&`Ghq7Z~s$clA8>?0ZNgPIBQg1_Q&eKZ^2|bsKw}_>_5LRUjrpe(-7$4juhgyb`lU6CD1We?oKENSZEL!nnx^I+ zH;{Qu;01}OEkdHjS~Fe|$*88=_W!dYnw!-E8xAd#i|J#XJ02bii7$Q*gg@o6r?=}z z`&zLUTsOpVB3M<72-X%3AI1nlXfa~2s)&GEh(=-Ui(9q*@XkrQ>fu^>N@0Tv*!O5D`@E2rOf~K>gut`nJvkcl&};Kd5PJ&bZ-t@3^j-3Dp9{KH#$hZ&%+| z0C}I(p#v@WL7_Z{R*4uP47H#T1Y=|*F13mn!7(b0YsY)YE%XJpKvPx1KkH literal 0 HcmV?d00001 diff --git a/examples/widgets/richtext/textedit/images/mac/format-indent-more.png b/examples/widgets/richtext/textedit/images/mac/format-indent-more.png new file mode 100644 index 0000000000000000000000000000000000000000..1bdeabd354fa5274c69cd70b281c2ee9276d5f6b GIT binary patch literal 993 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyoCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#F)Irjvt)p8j1&U{@lwp-Sh+G@Qus?`lqaVZW zV1^4(3`@NjmU%Ipj$~Ns&2ToB;aoI`3q%mc*%*dpo(w?Jz&^sjA=1zxDk!NcI2nkl zgOh83TqDP5W9OLQl$wx~n$XnRbFs`oz2||tyckY_jXD>@u)&XEZwN>PXwJq!roEvI zYXUjW#4_84Ry#%3Z;0f-n9OPBm1XXgWgAdn8wf;&&f#Uw;pHyj-E1|@BZIzvAR9Q>-Ot^x8MA`1494r zy#Igi?f?7l{@;K9@BaJ$4|>|9;l zeM7=3DyB|dw|)-<>;;1Z2M-@Tdg9d8t2b^ufBxyyw{O3G{eyw)*Kha&O=C>*c6VXu zV3qX%vh6)x978NlCnqeBSYh?+cXf63?;pQ@{rdUyCv)Rsn=YpIU9aA3`m^cFjwLr{ z9GUXu$C4>U>>{k&c$ZpEOkFxt@#RcM&XorvGZR_OG`Oa$nKQ@6cCU@iox68qV&}}A zJ7>)j$qe=ogIX2m6Yga^cdW9S3|P%(*lkL?@Z#lpfkv%>BOfL%RcUs-K1Z@O$!CYG zTEa!c?5eda+Etx?mxTvvCx%appA?WbzPn6ir|& yv^?{$NP>$=LGSoH^#fdB%He>>qavwioD3RaUB_kZ*z`V literal 0 HcmV?d00001 diff --git a/examples/widgets/richtext/textedit/images/win/format-indent-less.png b/examples/widgets/richtext/textedit/images/win/format-indent-less.png new file mode 100644 index 0000000000000000000000000000000000000000..e38074e78b78b384a1f7e8ab680fdd35175c0347 GIT binary patch literal 1201 zcmV;i1Wx;jP)1#w$1 zXjCZr%@it11(#rA5Tld5kx6d)ZG*GWj8c>B%)OlRyxmtH&S{Qq=8j^0$Qz#L!}HwF zb6@xM|NpQ5eTk~_Uk<~6Je*QLsBLP_xPhcbKhxqZ8MEW&%MJdcpa~~TmmEOOBlXU% z7Oo9}wGf6Di(-mP#bO38uwX5*n1eCk`(O;H7A|9yL;`8qyrrsS2vikgz=;&Lcji|p zOGH2*>KM*k02_vsmpOdfOf)ei#RSQA zhqJ}xj!w0X-9d4>s5jJ`mjAs9q^5Cu#tkH;<7izvtCLZiZrlG>bxAVJd8BsjX`ydG z@q>^lNe9;t$$O=F7{M`yQ<;!>^wwDIdhSgZ>}ZsRvrUn%&PMsB z^I2Icm3134PJA@0uP3=wR{O)*bjR19-VlP$)v_fq=YbvbUp-3De~Iols(x~QIJSHK z9cNmrn2rp4r!J^mKX2WKNRY+7d=7>1j?3`J21&-_9GtnNZpEBcJCSTR16?OMe{`Q8 zc)8_L)3`m8A5+`^&U)DdDgd-Brs*ReyjeYo#b-D%j#oVXd}T%L%jh59(RVJ*`Sue7 z8ie%^9n^Lw=aJgIr-gjJ0Dl--qES<1xFrY*N)Um80hfEG$K|zGw%nBMC+p>2Yxwg1 z2;6xx|;Fn$p z&`Ghq7Z~s$clA8>?0ZNgPIBQg1_Q&eKZ^2|bsKw}_>_5LRUjrpe(-7$4juhgyb`lU6CD1We?oKENSZEL!nnx^I+ zH;{Qu;01}OEkdHjS~Fe|$*88=_W!dYnw!-E8xAd#i|J#XJ02bii7$Q*gg@o6r?=}z z`&zLUTsOpVB3M<72-X%3AI1nlXfa~2s)&GEh(=-Ui(9q*@XkrQ>fu^>N@0Tv*!O5D`@E2rOf~K>gut`nJvkcl&};Kd5PJ&bZ-t@3^j-3Dp9{KH#$hZ&%+| z0C}I(p#v@WL7_Z{R*4uP47H#T1Y=|*F13mn!7(b0YsY)YE%XJpKvPx1KkH literal 0 HcmV?d00001 diff --git a/examples/widgets/richtext/textedit/images/win/format-indent-more.png b/examples/widgets/richtext/textedit/images/win/format-indent-more.png new file mode 100644 index 0000000000000000000000000000000000000000..1bdeabd354fa5274c69cd70b281c2ee9276d5f6b GIT binary patch literal 993 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyoCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#F)Irjvt)p8j1&U{@lwp-Sh+G@Qus?`lqaVZW zV1^4(3`@NjmU%Ipj$~Ns&2ToB;aoI`3q%mc*%*dpo(w?Jz&^sjA=1zxDk!NcI2nkl zgOh83TqDP5W9OLQl$wx~n$XnRbFs`oz2||tyckY_jXD>@u)&XEZwN>PXwJq!roEvI zYXUjW#4_84Ry#%3Z;0f-n9OPBm1XXgWgAdn8wf;&&f#Uw;pHyj-E1|@BZIzvAR9Q>-Ot^x8MA`1494r zy#Igi?f?7l{@;K9@BaJ$4|>|9;l zeM7=3DyB|dw|)-<>;;1Z2M-@Tdg9d8t2b^ufBxyyw{O3G{eyw)*Kha&O=C>*c6VXu zV3qX%vh6)x978NlCnqeBSYh?+cXf63?;pQ@{rdUyCv)Rsn=YpIU9aA3`m^cFjwLr{ z9GUXu$C4>U>>{k&c$ZpEOkFxt@#RcM&XorvGZR_OG`Oa$nKQ@6cCU@iox68qV&}}A zJ7>)j$qe=ogIX2m6Yga^cdW9S3|P%(*lkL?@Z#lpfkv%>BOfL%RcUs-K1Z@O$!CYG zTEa!c?5eda+Etx?mxTvvCx%appA?WbzPn6ir|& yv^?{$NP>$=LGSoH^#fdB%He>>qavwioD3RaUB_kZ*z`V literal 0 HcmV?d00001 diff --git a/examples/widgets/richtext/textedit/textedit.cpp b/examples/widgets/richtext/textedit/textedit.cpp index 683e441fce..ced77a62ce 100644 --- a/examples/widgets/richtext/textedit/textedit.cpp +++ b/examples/widgets/richtext/textedit/textedit.cpp @@ -317,6 +317,14 @@ void TextEdit::setupTextActions() actionAlignJustify->setShortcut(Qt::CTRL + Qt::Key_J); actionAlignJustify->setCheckable(true); actionAlignJustify->setPriority(QAction::LowPriority); + const QIcon indentMoreIcon = QIcon::fromTheme("format-indent-more", QIcon(rsrcPath + "/format-indent-more.png")); + actionIndentMore = menu->addAction(indentMoreIcon, tr("&Indent"), this, &TextEdit::indent); + actionIndentMore->setShortcut(Qt::CTRL + Qt::Key_BracketRight); + actionIndentMore->setPriority(QAction::LowPriority); + const QIcon indentLessIcon = QIcon::fromTheme("format-indent-less", QIcon(rsrcPath + "/format-indent-less.png")); + actionIndentLess = menu->addAction(indentLessIcon, tr("&Unindent"), this, &TextEdit::unindent); + actionIndentLess->setShortcut(Qt::CTRL + Qt::Key_BracketLeft); + actionIndentLess->setPriority(QAction::LowPriority); // Make sure the alignLeft is always left of the alignRight QActionGroup *alignGroup = new QActionGroup(this); @@ -335,6 +343,10 @@ void TextEdit::setupTextActions() tb->addActions(alignGroup->actions()); menu->addActions(alignGroup->actions()); + tb->addAction(actionIndentMore); + tb->addAction(actionIndentLess); + menu->addAction(actionIndentMore); + menu->addAction(actionIndentLess); menu->addSeparator(); @@ -736,6 +748,40 @@ void TextEdit::setChecked(bool checked) textStyle(checked ? 5 : 4); } +void TextEdit::indent() +{ + modifyIndentation(1); +} + +void TextEdit::unindent() +{ + modifyIndentation(-1); +} + +void TextEdit::modifyIndentation(int amount) +{ + QTextCursor cursor = textEdit->textCursor(); + cursor.beginEditBlock(); + if (cursor.currentList()) { + QTextListFormat listFmt = cursor.currentList()->format(); + // See whether the line above is the list we want to move this item into, + // or whether we need a new list. + QTextCursor above(cursor); + above.movePosition(QTextCursor::Up); + if (above.currentList() && listFmt.indent() + amount == above.currentList()->format().indent()) { + above.currentList()->add(cursor.block()); + } else { + listFmt.setIndent(listFmt.indent() + amount); + cursor.createList(listFmt); + } + } else { + QTextBlockFormat blockFmt = cursor.blockFormat(); + blockFmt.setIndent(blockFmt.indent() + amount); + cursor.setBlockFormat(blockFmt); + } + cursor.endEditBlock(); +} + void TextEdit::currentCharFormatChanged(const QTextCharFormat &format) { fontChanged(format.font()); diff --git a/examples/widgets/richtext/textedit/textedit.h b/examples/widgets/richtext/textedit/textedit.h index c253548a4f..9e50166c6f 100644 --- a/examples/widgets/richtext/textedit/textedit.h +++ b/examples/widgets/richtext/textedit/textedit.h @@ -97,6 +97,8 @@ private slots: void textColor(); void textAlign(QAction *a); void setChecked(bool checked); + void indent(); + void unindent(); void currentCharFormatChanged(const QTextCharFormat &format); void cursorPositionChanged(); @@ -111,6 +113,7 @@ private: void setupTextActions(); bool maybeSave(); void setCurrentFileName(const QString &fileName); + void modifyIndentation(int amount); void mergeFormatOnWordOrSelection(const QTextCharFormat &format); void fontChanged(const QFont &f); @@ -126,6 +129,8 @@ private: QAction *actionAlignCenter; QAction *actionAlignRight; QAction *actionAlignJustify; + QAction *actionIndentLess; + QAction *actionIndentMore; QAction *actionToggleCheckState; QAction *actionUndo; QAction *actionRedo; diff --git a/examples/widgets/richtext/textedit/textedit.qrc b/examples/widgets/richtext/textedit/textedit.qrc index 8016a07ca0..1641acc207 100644 --- a/examples/widgets/richtext/textedit/textedit.qrc +++ b/examples/widgets/richtext/textedit/textedit.qrc @@ -13,6 +13,8 @@ images/mac/fileopen.png images/mac/fileprint.png images/mac/filesave.png + images/mac/format-indent-less.png + images/mac/format-indent-more.png images/mac/textbold.png images/mac/textcenter.png images/mac/textitalic.png @@ -34,6 +36,8 @@ images/win/fileopen.png images/win/fileprint.png images/win/filesave.png + images/win/format-indent-less.png + images/win/format-indent-more.png images/win/textbold.png images/win/textcenter.png images/win/textitalic.png From 1b8a1e04efb4ea71803edf8c122db2837fe23af9 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 6 May 2019 17:03:45 +0200 Subject: [PATCH 073/122] Fix heading level in style combobox in TextEdit example Amends 0df30ff22e50aa301791fc72f106ab15ce385a6a: when adding the checked and unchecked styles to the combobox, it changed the offsets for the heading styles; so the combobox stopped changing to the correct index when clicking on a heading, and also changed the heading two sizes smaller than it should when attempting to select a different heading level. Change-Id: Ib3f61987c786e34f32a81bf7b3ebc5ca730f40df Reviewed-by: Gatis Paeglis --- examples/widgets/richtext/textedit/textedit.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/widgets/richtext/textedit/textedit.cpp b/examples/widgets/richtext/textedit/textedit.cpp index ced77a62ce..996bb8e0a4 100644 --- a/examples/widgets/richtext/textedit/textedit.cpp +++ b/examples/widgets/richtext/textedit/textedit.cpp @@ -691,7 +691,7 @@ void TextEdit::textStyle(int styleIndex) if (style == QTextListFormat::ListStyleUndefined) { blockFmt.setObjectIndex(-1); - int headingLevel = styleIndex >= 9 ? styleIndex - 9 + 1 : 0; // H1 to H6, or Standard + int headingLevel = styleIndex >= 11 ? styleIndex - 11 + 1 : 0; // H1 to H6, or Standard blockFmt.setHeadingLevel(headingLevel); cursor.setBlockFormat(blockFmt); @@ -837,7 +837,7 @@ void TextEdit::cursorPositionChanged() } } else { int headingLevel = textEdit->textCursor().blockFormat().headingLevel(); - comboStyle->setCurrentIndex(headingLevel ? headingLevel + 8 : 0); + comboStyle->setCurrentIndex(headingLevel ? headingLevel + 10 : 0); } } From 5ced1ff9fcf85b43983bf4667c308bd1daaab379 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 2 May 2019 09:21:38 +0200 Subject: [PATCH 074/122] Fix compilation with Qt 6 Change-Id: Ie165ab2f17740a996112b7e918b595d5873674a1 Reviewed-by: Simon Hausmann --- .../qstandarditemmodel/tst_qstandarditemmodel.cpp | 10 +++++----- .../widgets/itemviews/qlistwidget/tst_qlistwidget.cpp | 4 ++-- .../itemviews/qtablewidget/tst_qtablewidget.cpp | 4 ++-- .../widgets/itemviews/qtreewidget/tst_qtreewidget.cpp | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp index 550f70890e..bc8bc38da6 100644 --- a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp +++ b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp @@ -734,7 +734,7 @@ void tst_QStandardItemModel::data() currentRoles.clear(); // bad args m_model->setData(QModelIndex(), "bla", Qt::DisplayRole); - QCOMPARE(currentRoles, {}); + QCOMPARE(currentRoles, QVector{}); QIcon icon; for (int r=0; r < m_model->rowCount(); ++r) { @@ -742,9 +742,9 @@ void tst_QStandardItemModel::data() m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole); QCOMPARE(currentRoles, QVector({Qt::DisplayRole, Qt::EditRole})); m_model->setData(m_model->index(r,c), "tooltip", Qt::ToolTipRole); - QCOMPARE(currentRoles, {Qt::ToolTipRole}); + QCOMPARE(currentRoles, QVector{Qt::ToolTipRole}); m_model->setData(m_model->index(r,c), icon, Qt::DecorationRole); - QCOMPARE(currentRoles, {Qt::DecorationRole}); + QCOMPARE(currentRoles, QVector{Qt::DecorationRole}); } } @@ -761,7 +761,7 @@ void tst_QStandardItemModel::clearItemData() { currentRoles.clear(); QVERIFY(!m_model->clearItemData(QModelIndex())); - QCOMPARE(currentRoles, {}); + QCOMPARE(currentRoles, QVector{}); const QModelIndex idx = m_model->index(0, 0); const QMap oldData = m_model->itemData(idx); m_model->setData(idx, QLatin1String("initialitem"), Qt::DisplayRole); @@ -773,7 +773,7 @@ void tst_QStandardItemModel::clearItemData() QCOMPARE(idx.data(Qt::ToolTipRole), QVariant()); QCOMPARE(idx.data(Qt::DisplayRole), QVariant()); QCOMPARE(idx.data(Qt::EditRole), QVariant()); - QCOMPARE(currentRoles, {}); + QCOMPARE(currentRoles, QVector{}); m_model->setItemData(idx, oldData); currentRoles.clear(); } diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp index 91088aeeca..fe2ede4183 100644 --- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp +++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp @@ -1525,11 +1525,11 @@ void tst_QListWidget::itemData() item.setData(Qt::DisplayRole, QString("0")); QCOMPARE(widget.currentRoles, QVector({Qt::DisplayRole, Qt::EditRole})); item.setData(Qt::CheckStateRole, Qt::PartiallyChecked); - QCOMPARE(widget.currentRoles, {Qt::CheckStateRole}); + QCOMPARE(widget.currentRoles, QVector{Qt::CheckStateRole}); for (int i = 0; i < 4; ++i) { item.setData(Qt::UserRole + i, QString::number(i + 1)); - QCOMPARE(widget.currentRoles, {Qt::UserRole + i}); + QCOMPARE(widget.currentRoles, QVector{Qt::UserRole + i}); } QMap flags = widget.model()->itemData(widget.model()->index(0, 0)); QCOMPARE(flags.count(), 6); diff --git a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp index c2de5c2761..6184962d93 100644 --- a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp +++ b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp @@ -1383,11 +1383,11 @@ void tst_QTableWidget::itemData() item->setData(Qt::DisplayRole, QString("0")); QCOMPARE(widget.currentRoles, QVector({Qt::DisplayRole, Qt::EditRole})); item->setData(Qt::CheckStateRole, Qt::PartiallyChecked); - QCOMPARE(widget.currentRoles, {Qt::CheckStateRole}); + QCOMPARE(widget.currentRoles, QVector{Qt::CheckStateRole}); for (int i = 0; i < 4; ++i) { item->setData(Qt::UserRole + i, QString::number(i + 1)); - QCOMPARE(widget.currentRoles, {Qt::UserRole + i}); + QCOMPARE(widget.currentRoles, QVector{Qt::UserRole + i}); } QMap flags = widget.model()->itemData(widget.model()->index(0, 0)); QCOMPARE(flags.count(), 6); diff --git a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp index 33d4f3bf91..0d97974b90 100644 --- a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp +++ b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp @@ -1999,10 +1999,10 @@ void tst_QTreeWidget::itemData() item.setData(0, Qt::DisplayRole, QString("0")); QCOMPARE(widget.currentRoles, QVector({Qt::DisplayRole, Qt::EditRole})); item.setData(0, Qt::CheckStateRole, Qt::PartiallyChecked); - QCOMPARE(widget.currentRoles, {Qt::CheckStateRole}); + QCOMPARE(widget.currentRoles, QVector{Qt::CheckStateRole}); for (int i = 0; i < 4; ++i) { item.setData(0, Qt::UserRole + i, QString::number(i + 1)); - QCOMPARE(widget.currentRoles, {Qt::UserRole + i}); + QCOMPARE(widget.currentRoles, QVector{Qt::UserRole + i}); } QMap flags = widget.model()->itemData(widget.model()->index(0, 0)); QCOMPARE(flags.count(), 6); From 0b373c2e36a68aedf3731fcb3cd84fd010c2d67c Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 2 May 2019 09:23:52 +0200 Subject: [PATCH 075/122] Don't rely on functions that are deprecated Change-Id: I4150368e44b43e45f3604bf0fc7dab38a15e5ec9 Reviewed-by: Simon Hausmann --- tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp index 68664cdd2f..8d197dc616 100644 --- a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp +++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp @@ -198,8 +198,8 @@ void tst_QFontDatabase::widthTwoTimes() f.setPixelSize(pixelSize); QFontMetrics fm(f); - int w1 = fm.charWidth(text, 0); - int w2 = fm.charWidth(text, 0); + int w1 = fm.horizontalAdvance(text, 0); + int w2 = fm.horizontalAdvance(text, 0); QCOMPARE(w1, w2); } From aea6ff4f57135b0f2f076e86e22cb87c0a7014fe Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Tue, 7 May 2019 01:35:04 +0200 Subject: [PATCH 076/122] Fix the generation of docs for qobject_pointer_cast QSharedPointer uses a dummy header for qdoc; the functions were implemented and documented as qdoc comments, but not added to the dummy header. Change-Id: Iec78e3566a528631557067fbeb5606916ea74f2d Reviewed-by: Martin Smith --- src/corelib/tools/qsharedpointer.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index 98b38b97d3..80d0618402 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -48,6 +48,8 @@ # include #else +#include // for std::shared_ptr + QT_BEGIN_NAMESPACE @@ -167,6 +169,10 @@ template QSharedPointer qSharedPointerConstCast(const QSha template QSharedPointer qSharedPointerConstCast(const QWeakPointer &src); template QSharedPointer qSharedPointerObjectCast(const QSharedPointer &src); template QSharedPointer qSharedPointerObjectCast(const QWeakPointer &src); +template std::shared_ptr qobject_pointer_cast(const std::shared_ptr &src); +template std::shared_ptr qobject_pointer_cast(std::shared_ptr &&src); +template std::shared_ptr qSharedPointerObjectCast(const std::shared_ptr &src); +template std::shared_ptr qSharedPointerObjectCast(std::shared_ptr &&src); template QWeakPointer qWeakPointerCast(const QWeakPointer &src); From 587bdd144b7e574e57f17167808774fa9783ee78 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 13 Nov 2018 10:26:50 +0100 Subject: [PATCH 077/122] Add QUrl to bootstrap set The QML language server needs to use QUrl as that is what the language server protocol uses to specify files. As we cannot implicitly cast char to QChar in the bootstrap library, we need to apply a build fix in qipaddress.cpp. Change-Id: Ifaf8421457b1f734402b5aad965ecdec764a73e8 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qipaddress.cpp | 2 +- src/tools/bootstrap/bootstrap.pro | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qipaddress.cpp b/src/corelib/io/qipaddress.cpp index 039e291b43..d9f7916dd4 100644 --- a/src/corelib/io/qipaddress.cpp +++ b/src/corelib/io/qipaddress.cpp @@ -253,7 +253,7 @@ const QChar *parseIp6(IPv6Address &address, const QChar *begin, const QChar *end static inline QChar toHex(uchar c) { - return QtMiscUtils::toHexLower(c); + return QChar::fromLatin1(QtMiscUtils::toHexLower(c)); } void toString(QString &appendTo, IPv6Address address) diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 1662e99674..708211279c 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -42,6 +42,7 @@ SOURCES += \ ../../corelib/io/qfsfileengine.cpp \ ../../corelib/io/qfsfileengine_iterator.cpp \ ../../corelib/io/qiodevice.cpp \ + ../../corelib/io/qipaddress.cpp \ ../../corelib/io/qfiledevice.cpp \ ../../corelib/io/qresource.cpp \ ../../corelib/io/qtemporarydir.cpp \ @@ -50,6 +51,9 @@ SOURCES += \ ../../corelib/io/qstandardpaths.cpp \ ../../corelib/io/qloggingcategory.cpp \ ../../corelib/io/qloggingregistry.cpp \ + ../../corelib/io/qurl.cpp \ + ../../corelib/io/qurlidna.cpp \ + ../../corelib/io/qurlrecode.cpp \ ../../corelib/kernel/qcoreapplication.cpp \ ../../corelib/kernel/qcoreglobaldata.cpp \ ../../corelib/kernel/qmetatype.cpp \ From d510e1e7f919e01a3b875ff5a575b818e5ee03e8 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 10 Oct 2018 08:51:04 +0200 Subject: [PATCH 078/122] Add swapItemsAt() to QVector This closes one compatibility gap with QList, to make it easier to replace QList with QVector in Qt6. Change-Id: I5655bc4cd2150a6f09a1ed68c0742f3b42ca47e4 Reviewed-by: Simon Hausmann --- src/corelib/tools/qvector.h | 7 +++++++ src/corelib/tools/qvector.qdoc | 10 ++++++++++ .../corelib/tools/qvector/tst_qvector.cpp | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 4e148c9c55..b763d6e7e2 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -251,6 +251,13 @@ public: T value(int i) const; T value(int i, const T &defaultValue) const; + void swapItemsAt(int i, int j) { + Q_ASSERT_X(i >= 0 && i < size() && j >= 0 && j < size(), + "QVector::swap", "index out of range"); + detach(); + qSwap(d->begin()[i], d->begin()[j]); + } + // STL compatibility typedef T value_type; typedef value_type* pointer; diff --git a/src/corelib/tools/qvector.qdoc b/src/corelib/tools/qvector.qdoc index cb47d36356..c1b5054f93 100644 --- a/src/corelib/tools/qvector.qdoc +++ b/src/corelib/tools/qvector.qdoc @@ -288,6 +288,16 @@ never fails. */ +/*! \fn template void QVector::swapItemsAt(int i, int j) + \since 5.14 + + Exchange the item at index position \a i with the item at index + position \a j. This function assumes that both \a i and \a j are + at least 0 but less than size(). To avoid failure, test that both + \a i and \a j are at least 0 and less than size(). +*/ + + /*! \fn template bool QVector::operator==(const QVector &other) const Returns \c true if \a other is equal to this vector; otherwise diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index f81ce11510..11c255b184 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -331,6 +331,8 @@ private slots: void insertMove() const; + void swapItemsAt() const; + private: template void copyConstructor() const; template void add() const; @@ -2990,5 +2992,22 @@ void tst_QVector::insertMove() const QCOMPARE(Movable::counter.loadAcquire(), instancesCount); } +void tst_QVector::swapItemsAt() const +{ + QVector v; + v << 0 << 1 << 2 << 3; + + v.swapItemsAt(0, 2); + QCOMPARE(v.at(0), 2); + QCOMPARE(v.at(2), 0); + + auto copy = v; + copy.swapItemsAt(0, 2); + QCOMPARE(v.at(0), 2); + QCOMPARE(v.at(2), 0); + QCOMPARE(copy.at(0), 0); + QCOMPARE(copy.at(2), 2); +} + QTEST_MAIN(tst_QVector) #include "tst_qvector.moc" From 92f984273262531f909ede17a324f546fe502b5c Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 6 May 2019 14:00:53 +0200 Subject: [PATCH 079/122] Deprecate conversion functions between QList and QSet Users should use range constructors instead to do the conversion. Keep conversion methods between QList and QVector as these will turn into a no-op in Qt 6, whereas forcing people to use range constructors would lead to deep copies of the data. Change-Id: Id9fc9e4d007044e019826da523e8418857c91283 Reviewed-by: Simon Hausmann --- examples/opengl/contextinfo/widget.cpp | 2 +- .../painting/pathstroke/pathstroke.cpp | 3 +- .../widgets/painting/shared/hoverpoints.cpp | 3 +- qmake/generators/makefile.cpp | 3 +- qmake/generators/win32/msvc_nmake.cpp | 2 +- src/corelib/statemachine/qstatemachine.cpp | 13 ++++--- src/corelib/tools/qlist.h | 10 +++-- src/corelib/tools/qset.h | 13 +++++-- src/corelib/tools/qvector.h | 3 +- src/gui/opengl/qopengl.cpp | 2 +- src/gui/text/qtextodfwriter.cpp | 2 +- .../ssl/qsslsocket_openssl_symbols.cpp | 2 +- src/tools/uic/cpp/cppwriteinitialization.cpp | 2 +- .../graphicsview/qgraphicsanchorlayout_p.cpp | 2 +- src/widgets/graphicsview/qgraphicsscene.cpp | 10 ++--- src/widgets/graphicsview/qsimplex_p.cpp | 2 +- src/widgets/itemviews/qtableview.cpp | 4 +- src/widgets/kernel/qapplication.cpp | 2 +- src/widgets/kernel/qgesturemanager.cpp | 2 +- .../tools/collections/tst_collections.cpp | 37 +++++++++++++++++-- tests/auto/corelib/tools/qlist/tst_qlist.cpp | 6 +-- .../gui/qopenglconfig/tst_qopenglconfig.cpp | 6 +-- .../kernel/qapplication/tst_qapplication.cpp | 8 +++- .../tst_qabstractscrollarea.cpp | 10 ++++- 24 files changed, 99 insertions(+), 50 deletions(-) diff --git a/examples/opengl/contextinfo/widget.cpp b/examples/opengl/contextinfo/widget.cpp index b1b7076503..0762c91662 100644 --- a/examples/opengl/contextinfo/widget.cpp +++ b/examples/opengl/contextinfo/widget.cpp @@ -384,7 +384,7 @@ void Widget::renderWindowReady() m_output->append(tr("Qt OpenGL library handle: %1") .arg(QString::number(qintptr(QOpenGLContext::openGLModuleHandle()), 16))); - QList extensionList = context->extensions().toList(); + QList extensionList = context->extensions().values(); std::sort(extensionList.begin(), extensionList.end()); m_extensions->append(tr("Found %1 extensions:").arg(extensionList.count())); for (const QByteArray &ext : qAsConst(extensionList)) diff --git a/examples/widgets/painting/pathstroke/pathstroke.cpp b/examples/widgets/painting/pathstroke/pathstroke.cpp index 03e55bb2a2..e4009f0b1a 100644 --- a/examples/widgets/painting/pathstroke/pathstroke.cpp +++ b/examples/widgets/painting/pathstroke/pathstroke.cpp @@ -611,7 +611,8 @@ bool PathStrokeRenderer::event(QEvent *e) case Qt::TouchPointPressed: { // find the point, move it - QSet activePoints = QSet::fromList(m_fingerPointMapping.values()); + const auto mappedPoints = m_fingerPointMapping.values(); + QSet activePoints = QSet(mappedPoints.begin(), mappedPoints.end()); int activePoint = -1; qreal distance = -1; const int pointsCount = m_points.size(); diff --git a/examples/widgets/painting/shared/hoverpoints.cpp b/examples/widgets/painting/shared/hoverpoints.cpp index 74c78088ad..2032fb5a2c 100644 --- a/examples/widgets/painting/shared/hoverpoints.cpp +++ b/examples/widgets/painting/shared/hoverpoints.cpp @@ -180,7 +180,8 @@ bool HoverPoints::eventFilter(QObject *object, QEvent *event) case Qt::TouchPointPressed: { // find the point, move it - QSet activePoints = QSet::fromList(m_fingerPointMapping.values()); + const auto mappedPoints = m_fingerPointMapping.values(); + QSet activePoints = QSet(mappedPoints.begin(), mappedPoints.end()); int activePoint = -1; qreal distance = -1; const int pointsCount = m_points.size(); diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index aae5a44e21..1a7a7a4322 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -2696,7 +2696,8 @@ MakefileGenerator::writeSubTargets(QTextStream &t, QList recurse; const ProKey rkey(*qut_it + ".recurse"); if (project->isSet(rkey)) { - recurse = project->values(rkey).toQStringList().toSet(); + const QStringList values = project->values(rkey).toQStringList(); + recurse = QSet(values.begin(), values.end()); } else { for(int target = 0; target < targets.size(); ++target) recurse.insert(targets.at(target)->name); diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 9c2e789932..f48eea9202 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -346,7 +346,7 @@ void NmakeMakefileGenerator::writeImplicitRulesPart(QTextStream &t) QHash fileNames; bool duplicatesFound = false; const QStringList sourceFilesFilter = sourceFilesForImplicitRulesFilter(); - QStringList fixifiedSourceDirs = fileFixify(source_directories.toList(), FileFixifyAbsolute); + QStringList fixifiedSourceDirs = fileFixify(QList(source_directories.constBegin(), source_directories.constEnd()), FileFixifyAbsolute); fixifiedSourceDirs.removeDuplicates(); for (const QString &sourceDir : qAsConst(fixifiedSourceDirs)) { QDirIterator dit(sourceDir, sourceFilesFilter, QDir::Files | QDir::NoDotAndDotDot); diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index ee3f7be279..be48dbc92f 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -370,10 +370,11 @@ static QList getEffectiveTargetStates(QAbstractTransition *tra QList historyConfiguration = QHistoryStatePrivate::get(historyState)->configuration; if (!historyConfiguration.isEmpty()) { // There is a saved history, so apply that. - targets.unite(historyConfiguration.toSet()); + targets.unite(QSet(historyConfiguration.constBegin(), historyConfiguration.constEnd())); } else if (QAbstractTransition *defaultTransition = historyState->defaultTransition()) { // No saved history, take all default transition targets. - targets.unite(defaultTransition->targetStates().toSet()); + const auto &targetStates = defaultTransition->targetStates(); + targets.unite(QSet(targetStates.constBegin(), targetStates.constEnd())); } else { // Woops, we found a history state without a default state. That's not valid! QStateMachinePrivate *m = QStateMachinePrivate::get(historyState->machine()); @@ -384,7 +385,7 @@ static QList getEffectiveTargetStates(QAbstractTransition *tra } } - targetsList = targets.toList(); + targetsList = targets.values(); cache->insert(transition, targetsList); return targetsList; } @@ -740,7 +741,7 @@ QList QStateMachinePrivate::computeExitSet(const QList statesToExit_sorted = computeExitSet_Unordered(enabledTransitions, cache).toList(); + QList statesToExit_sorted = computeExitSet_Unordered(enabledTransitions, cache).values(); std::sort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan); return statesToExit_sorted; } @@ -777,7 +778,7 @@ QSet QStateMachinePrivate::computeExitSet_Unordered(QAbstractTr // makes the state machine invalid. if (error == QStateMachine::NoError) setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState()); - QList lst = pendingErrorStates.toList(); + QList lst = pendingErrorStates.values(); lst.prepend(t->sourceState()); domain = findLCCA(lst); @@ -879,7 +880,7 @@ QList QStateMachinePrivate::computeEntrySet(const QList statesToEnter_sorted = statesToEnter.toList(); + QList statesToEnter_sorted = statesToEnter.values(); std::sort(statesToEnter_sorted.begin(), statesToEnter_sorted.end(), stateEntryLessThan); return statesToEnter_sorted; } diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 25380d45ec..04c1f12f5f 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -403,13 +403,15 @@ public: inline QList &operator<<(const QList &l) { *this += l; return *this; } - QVector toVector() const; - QSet toSet() const; - static QList fromVector(const QVector &vector); - static QList fromSet(const QSet &set); + QVector toVector() const; #if QT_VERSION < QT_VERSION_CHECK(6,0,0) + Q_DECL_DEPRECATED_X("Use QList(set.begin(), set.end()) instead.") + static QList fromSet(const QSet &set); + Q_DECL_DEPRECATED_X("Use QSet(list.begin(), list.end()) instead.") + QSet toSet() const; + Q_DECL_DEPRECATED_X("Use QList(list.begin(), list.end()) instead.") static inline QList fromStdList(const std::list &list) { QList tmp; std::copy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; } diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index 8b31de71a9..83e574bf1c 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -245,10 +245,13 @@ public: inline QSet operator-(const QSet &other) const { QSet result = *this; result -= other; return result; } - QList toList() const; - inline QList values() const { return toList(); } - + QList values() const; +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + Q_DECL_DEPRECATED_X("Use values() instead.") + QList toList() const { return values(); } + Q_DECL_DEPRECATED_X("Use QSet(list.begin(), list.end()) instead.") static QSet fromList(const QList &list); +#endif private: Hash q_hash; @@ -368,7 +371,7 @@ Q_INLINE_TEMPLATE bool QSet::contains(const QSet &other) const } template -Q_OUTOFLINE_TEMPLATE QList QSet::toList() const +Q_OUTOFLINE_TEMPLATE QList QSet::values() const { QList result; result.reserve(size()); @@ -380,6 +383,7 @@ Q_OUTOFLINE_TEMPLATE QList QSet::toList() const return result; } +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) template Q_OUTOFLINE_TEMPLATE QSet QList::toSet() const { @@ -401,6 +405,7 @@ QList QList::fromSet(const QSet &set) { return set.toList(); } +#endif Q_DECLARE_SEQUENTIAL_ITERATOR(Set) diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index b763d6e7e2..492afeac75 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -297,9 +297,8 @@ public: inline QVector &operator<<(T &&t) { append(std::move(t)); return *this; } - QList toList() const; - static QVector fromList(const QList &list); + QList toList() const; #if QT_VERSION < QT_VERSION_CHECK(6,0,0) Q_DECL_DEPRECATED_X("Use QVector(vector.begin(), vector.end()) instead.") diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp index 6b701fe52b..667d16317f 100644 --- a/src/gui/opengl/qopengl.cpp +++ b/src/gui/opengl/qopengl.cpp @@ -80,7 +80,7 @@ QOpenGLExtensionMatcher::QOpenGLExtensionMatcher() if (extensionStr) { QByteArray ba(extensionStr); QList extensions = ba.split(' '); - m_extensions = extensions.toSet(); + m_extensions = QSet(extensions.constBegin(), extensions.constEnd()); } else { #ifdef QT_OPENGL_3 // clear error state diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp index a62e7e425a..8eaad403d0 100644 --- a/src/gui/text/qtextodfwriter.cpp +++ b/src/gui/text/qtextodfwriter.cpp @@ -1007,7 +1007,7 @@ bool QTextOdfWriter::writeAll() // add objects for lists, frames and tables const QVector allFormats = m_document->allFormats(); - const QList copy = formats.toList(); + const QList copy = formats.values(); for (auto index : copy) { QTextObject *object = m_document->objectForFormat(allFormats[index]); if (object) { diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index e04d45c10c..6f935a02e4 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -693,7 +693,7 @@ static QStringList libraryPathList() // discover paths of already loaded libraries QSet loadedPaths; dl_iterate_phdr(dlIterateCallback, &loadedPaths); - paths.append(loadedPaths.toList()); + paths.append(loadedPaths.values()); #endif return paths; diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index a1ff26ba04..2510fd0edc 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -2607,7 +2607,7 @@ static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet getVariables(const QList &constraints) for (auto it = c->variables.cbegin(), end = c->variables.cend(); it != end; ++it) variableSet.insert(static_cast(it.key())); } - return variableSet.toList(); + return variableSet.values(); } /*! diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index 3897823e98..e5bd65d61e 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -6352,7 +6352,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) << "delivering override to" << item.data() << gestures; // send gesture override - QGestureEvent ev(gestures.toList()); + QGestureEvent ev(gestures.values()); ev.t = QEvent::GestureOverride; ev.setWidget(event->widget()); // mark event and individual gestures as ignored @@ -6442,7 +6442,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" << "delivering to" << receiver.data() << gestures; - QGestureEvent ev(gestures.toList()); + QGestureEvent ev(gestures.values()); ev.setWidget(event->widget()); sendEvent(receiver.data(), &ev); QSet ignoredGestures; @@ -6473,7 +6473,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) // look for new potential targets for gestures that were ignored // and should be propagated. - QSet targetsSet = cachedTargetItems.toSet(); + QSet targetsSet(cachedTargetItems.constBegin(), cachedTargetItems.constEnd()); if (receiver) { // first if the gesture should be propagated to parents only @@ -6505,7 +6505,7 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) gestureTargetsAtHotSpots(ignoredGestures, Qt::ReceivePartialGestures, &cachedItemGestures, &targetsSet, 0, 0); - cachedTargetItems = targetsSet.toList(); + cachedTargetItems = targetsSet.values(); std::sort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst); DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:" << "new targets:" << cachedTargetItems; @@ -6583,7 +6583,7 @@ void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original) } Q_ASSERT(target); - const QList list = gestures.toList(); + const QList list = gestures.values(); QGestureEvent ev(list); sendEvent(target, &ev); diff --git a/src/widgets/graphicsview/qsimplex_p.cpp b/src/widgets/graphicsview/qsimplex_p.cpp index e6ffa856f1..e18f1fa4c4 100644 --- a/src/widgets/graphicsview/qsimplex_p.cpp +++ b/src/widgets/graphicsview/qsimplex_p.cpp @@ -164,7 +164,7 @@ bool QSimplex::setConstraints(const QList &newConstraints) for (auto it = v.cbegin(), end = v.cend(); it != end; ++it) variablesSet.insert(it.key()); } - variables = variablesSet.toList(); + variables = variablesSet.values(); // Set Variables reverse mapping // We also need to be able to find the index for a given variable, to do that diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index 9e9aa63b53..0e03ff2a97 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -191,7 +191,7 @@ QList QSpanCollection::spansInRect(int x, int y, int w, break; --it_y; } - return list.toList(); + return list.values(); } #undef DEBUG_SPAN_UPDATE @@ -875,7 +875,7 @@ void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter, for(int y = firstVisualRow; y <= lastVisualRow; y++) set.insert(spans.spanAt(x,y)); set.remove(0); - visibleSpans = set.toList(); + visibleSpans = set.values(); } for (QSpanCollection::Span *span : qAsConst(visibleSpans)) { diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index c1c4014c6b..ca48a9e145 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1721,7 +1721,7 @@ QWidgetList QApplication::topLevelWidgets() QWidgetList QApplication::allWidgets() { if (QWidgetPrivate::allWidgets) - return QWidgetPrivate::allWidgets->toList(); + return QWidgetPrivate::allWidgets->values(); return QWidgetList(); } diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index cd27c9c5be..390602205c 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -171,7 +171,7 @@ void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType typ while (iter != m_objectGestures.end()) { ObjectGesture objectGesture = iter.key(); if (objectGesture.gesture == type && target == objectGesture.object) { - QSet gestures = iter.value().toSet(); + QSet gestures = QSet(iter.value().constBegin(), iter.value().constEnd()); for (QHash >::iterator it = m_obsoleteGestures.begin(), e = m_obsoleteGestures.end(); it != e; ++it) { it.value() -= gestures; diff --git a/tests/auto/corelib/tools/collections/tst_collections.cpp b/tests/auto/corelib/tools/collections/tst_collections.cpp index 9bd90d21cd..734b018b39 100644 --- a/tests/auto/corelib/tools/collections/tst_collections.cpp +++ b/tests/auto/corelib/tools/collections/tst_collections.cpp @@ -2531,14 +2531,18 @@ void tst_Collections::conversions() QCOMPARE(list2.size(), 4); QVERIFY(list2 == (QList() << STUFF)); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) QSet set1 = list1.toSet(); +#else + QSet set1(list1.begin(), list1.end()); +#endif QCOMPARE(set1.size(), 3); QVERIFY(set1.contains("A")); QVERIFY(set1.contains("B")); QVERIFY(set1.contains("C")); QVERIFY(!set1.contains("D")); - QList list3 = set1.toList(); + QList list3 = set1.values(); QCOMPARE(list3.size(), 3); QVERIFY(list3.contains("A")); QVERIFY(list3.contains("B")); @@ -2546,9 +2550,11 @@ void tst_Collections::conversions() QVERIFY(!list3.contains("D")); QVERIFY(QList().toVector().isEmpty()); - QVERIFY(QList().toSet().isEmpty()); QVERIFY(QVector().toList().isEmpty()); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + QVERIFY(QList().toSet().isEmpty()); QVERIFY(QSet().toList().isEmpty()); +#endif } { @@ -2563,14 +2569,22 @@ void tst_Collections::conversions() QCOMPARE(list2.size(), 4); QVERIFY(list2 == (QList() << STUFF)); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) QSet set1 = QSet::fromList(list1); +#else + QSet set1(list1.begin(), list1.end()); +#endif QCOMPARE(set1.size(), 3); QVERIFY(set1.contains("A")); QVERIFY(set1.contains("B")); QVERIFY(set1.contains("C")); QVERIFY(!set1.contains("D")); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) QList list3 = QList::fromSet(set1); +#else + QList list3 = set1.values(); +#endif QCOMPARE(list3.size(), 3); QVERIFY(list3.contains("A")); QVERIFY(list3.contains("B")); @@ -2578,9 +2592,11 @@ void tst_Collections::conversions() QVERIFY(!list3.contains("D")); QVERIFY(QVector::fromList(QList()).isEmpty()); - QVERIFY(QSet::fromList(QList()).isEmpty()); QVERIFY(QList::fromVector(QVector()).isEmpty()); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + QVERIFY(QSet::fromList(QList()).isEmpty()); QVERIFY(QList::fromSet(QSet()).isEmpty()); +#endif } #undef STUFF } @@ -2776,15 +2792,21 @@ void tst_Collections::vector_stl() for (int i = 0; i < elements.count(); ++i) vector << elements.at(i); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) std::vector stdVector = vector.toStdVector(); - +#else + std::vector stdVector(vector.begin(), vector.end()); +#endif QCOMPARE(int(stdVector.size()), elements.size()); std::vector::const_iterator it = stdVector.begin(); for (uint j = 0; j < stdVector.size() && it != stdVector.end(); ++j, ++it) QCOMPARE(*it, vector[j]); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) QCOMPARE(QVector::fromStdVector(stdVector), vector); +#endif + QCOMPARE(QVector(stdVector.begin(), stdVector.end()), vector); } void tst_Collections::linkedlist_stl_data() @@ -2830,7 +2852,11 @@ void tst_Collections::list_stl() for (int i = 0; i < elements.count(); ++i) list << elements.at(i); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) std::list stdList = list.toStdList(); +#else + std::list stdList(list.begin(), list.end()); +#endif QCOMPARE(int(stdList.size()), elements.size()); @@ -2838,7 +2864,10 @@ void tst_Collections::list_stl() for (uint j = 0; j < stdList.size() && it != stdList.end(); ++j, ++it) QCOMPARE(*it, list[j]); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) QCOMPARE(QList::fromStdList(stdList), list); +#endif + QCOMPARE(QList(stdList.begin(), stdList.end()), list); } template diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp index 7fb3e67462..5a485e88d2 100644 --- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp +++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp @@ -364,10 +364,10 @@ private slots: void takeLastOptimal() const; void takeLastMovable() const; void takeLastComplex() const; +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) void toSetOptimal() const; void toSetMovable() const; void toSetComplex() const; -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) void toStdListOptimal() const; void toStdListMovable() const; void toStdListComplex() const; @@ -428,8 +428,8 @@ private: template void takeAt() const; template void takeFirst() const; template void takeLast() const; - template void toSet() const; #if QT_VERSION < QT_VERSION_CHECK(6,0,0) + template void toSet() const; template void toStdList() const; #endif template void toVector() const; @@ -1599,6 +1599,7 @@ void tst_QList::takeLastComplex() const QCOMPARE(liveCount, Complex::getLiveCount()); } +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) template void tst_QList::toSet() const { @@ -1637,7 +1638,6 @@ void tst_QList::toSetComplex() const QCOMPARE(liveCount, Complex::getLiveCount()); } -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) template void tst_QList::toStdList() const { diff --git a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp index f8dfdbd3b0..b82b277781 100644 --- a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp +++ b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp @@ -200,7 +200,7 @@ static void dumpGlConfiguration(QOpenGLContext &context, QTextStream &str) << "\nShading language : " << reinterpret_cast(functions.glGetString(GL_SHADING_LANGUAGE_VERSION)) << "\nFormat : " << context.format(); - QList extensionList = context.extensions().toList(); + QList extensionList = context.extensions().values(); std::sort(extensionList.begin(), extensionList.end()); const int extensionCount = extensionList.size(); str << "\n\nFound " << extensionCount << " extensions:\n"; @@ -233,9 +233,9 @@ void tst_QOpenGlConfig::testGlConfiguration() static inline QByteArray msgSetMismatch(const QSet &expected, const QSet &actual) { - const QString result = QStringList(expected.toList()).join(QLatin1Char(',')) + const QString result = QStringList(expected.values()).join(QLatin1Char(',')) + QLatin1String(" != ") - + QStringList(actual.toList()).join(QLatin1Char(',')); + + QStringList(actual.values()).join(QLatin1Char(',')); return result.toLatin1(); } diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index e57ac77c39..af70b653ee 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -908,7 +908,9 @@ void tst_QApplication::libraryPaths() QStringList actual = QApplication::libraryPaths(); actual.sort(); - QStringList expected = QSet::fromList((QStringList() << testDir << appDirPath)).toList(); + QStringList expected; + expected << testDir << appDirPath; + expected = QSet(expected.constBegin(), expected.constEnd()).values(); expected.sort(); QVERIFY2(isPathListIncluded(actual, expected), @@ -925,7 +927,9 @@ void tst_QApplication::libraryPaths() QStringList actual = QApplication::libraryPaths(); actual.sort(); - QStringList expected = QSet::fromList((QStringList() << installPathPlugins << appDirPath)).toList(); + QStringList expected; + expected << installPathPlugins << appDirPath; + expected = QSet(expected.constBegin(), expected.constEnd()).values(); expected.sort(); #ifdef Q_OS_WINRT diff --git a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp index 007825d39c..a17a9f6c33 100644 --- a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp +++ b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp @@ -124,13 +124,19 @@ void tst_QAbstractScrollArea::scrollBarWidgets() QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList()); QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom), w2List); + auto sort = [](const QWidgetList l) { + QWidgetList list = l; + std::sort(list.begin(), list.end()); + return list; + }; + // two widgets at Bottom. area.addScrollBarWidget(w3, Qt::AlignBottom); - QCOMPARE(area.scrollBarWidgets(all).toSet(), allList.toSet()); + QCOMPARE(sort(area.scrollBarWidgets(all)), sort(allList)); QCOMPARE(area.scrollBarWidgets(Qt::AlignLeft), w1List); QCOMPARE(area.scrollBarWidgets(Qt::AlignRight), QWidgetList()); QCOMPARE(area.scrollBarWidgets(Qt::AlignTop), QWidgetList()); - QCOMPARE(area.scrollBarWidgets(Qt::AlignBottom).toSet(), (w2List + w3List).toSet()); + QCOMPARE(sort(area.scrollBarWidgets(Qt::AlignBottom)), sort(w2List + w3List)); //delete delete w1; From 06b8644953fc526707b5fe24c8ef08f4829ba1c6 Mon Sep 17 00:00:00 2001 From: Dmitry Kazakov Date: Thu, 6 Dec 2018 16:16:27 +0300 Subject: [PATCH 080/122] Fix notification of QDockWidget when it gets undocked Before the patch the notification was emitted only when the docker was attached to the panel or changed a position on it. It looks like the old behavior was documented in a unittest, so this patch might actually be a "behavior change". Change-Id: Id3ffbd2018a8e68844d174328dd1c4ceb7fa01d3 Reviewed-by: Richard Moe Gustavsen --- src/widgets/widgets/qdockwidget.cpp | 2 ++ tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index 4041c730b8..f98e0e44db 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -1182,6 +1182,8 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect QMainWindowLayout *mwlayout = qt_mainwindow_layout_from_dock(q); if (mwlayout) emit q->dockLocationChanged(mwlayout->dockWidgetArea(q)); + } else { + emit q->dockLocationChanged(Qt::NoDockWidgetArea); } } diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp index f8ce6a2c0a..625116654d 100644 --- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp +++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp @@ -670,7 +670,11 @@ void tst_QDockWidget::dockLocationChanged() spy.clear(); dw.setFloating(true); - QTest::qWait(100); + QTRY_COMPARE(spy.count(), 1); + QCOMPARE(qvariant_cast(spy.at(0).at(0)), + Qt::NoDockWidgetArea); + spy.clear(); + dw.setFloating(false); QTRY_COMPARE(spy.count(), 1); QCOMPARE(qvariant_cast(spy.at(0).at(0)), From 2841d5bf64d6228cdb5e42cdd1d4e2e8035217fa Mon Sep 17 00:00:00 2001 From: Dmitry Kazakov Date: Tue, 4 Dec 2018 20:11:34 +0300 Subject: [PATCH 081/122] Return QScreen's HMONITOR handle via QPlatformNativeInterface It is needed to be able to fetch extra information about the display via DXGI interface. Change-Id: Id83982eb07ade157719e430d0abcc2613409a343 Reviewed-by: Friedemann Kleint --- .../windows/qwindowsnativeinterface.cpp | 16 ++++++++++++++++ .../platforms/windows/qwindowsnativeinterface.h | 1 + src/plugins/platforms/windows/qwindowsscreen.cpp | 5 +++++ src/plugins/platforms/windows/qwindowsscreen.h | 2 ++ 4 files changed, 24 insertions(+) diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index b8ab7f8779..e581b30ced 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -40,6 +40,7 @@ #include "qwindowsnativeinterface.h" #include "qwindowsclipboard.h" #include "qwindowswindow.h" +#include "qwindowsscreen.h" #include "qwindowscontext.h" #include "qwindowscursor.h" #include "qwindowsopenglcontext.h" @@ -124,6 +125,21 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc return nullptr; } +void *QWindowsNativeInterface::nativeResourceForScreen(const QByteArray &resource, QScreen *screen) +{ + if (!screen || !screen->handle()) { + qWarning("%s: '%s' requested for null screen or screen without handle.", __FUNCTION__, resource.constData()); + return nullptr; + } + QWindowsScreen *bs = static_cast(screen->handle()); + int type = resourceType(resource); + if (type == HandleType) + return bs->handle(); + + qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData()); + return nullptr; +} + #ifndef QT_NO_CURSOR void *QWindowsNativeInterface::nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor) { diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index e6f8aae8fb..ce395dc5a4 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -74,6 +74,7 @@ public: void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) override; #endif void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override; + void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) override; #ifndef QT_NO_CURSOR void *nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor) override; #endif diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 0520f88935..b70b0bbe31 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -321,6 +321,11 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData) } } +HMONITOR QWindowsScreen::handle() const +{ + return m_data.hMonitor; +} + QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScreen::virtualGeometry() { QRect result; diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 824bcb1ad6..33c9effa2a 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -104,6 +104,8 @@ public: inline void handleChanges(const QWindowsScreenData &newData); + HMONITOR handle() const; + #ifndef QT_NO_CURSOR QPlatformCursor *cursor() const override { return m_cursor.data(); } const CursorPtr &cursorPtr() const { return m_cursor; } From add4b56b21bae5cef222ee23e00707664ca50e7f Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 7 May 2019 14:57:56 +0200 Subject: [PATCH 082/122] Add warning suppression for icc when comparing floating-point values The new implementations of qIsNull use naked floating point comparisons to 0 and suppress the warnings for clang and gcc; so add suppression also for icc. Fixes: QTBUG-75644 Change-Id: I59aa1443666a542f38197f2b124503cc562708cb Reviewed-by: Qt CI Bot Reviewed-by: Giuseppe D'Angelo --- src/corelib/global/qglobal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index a1f191516a..0a0c434a07 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -905,6 +905,7 @@ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qFuzzyIsNul QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_INTEL(1572) Q_REQUIRED_RESULT Q_DECL_CONSTEXPR static inline Q_DECL_UNUSED bool qIsNull(double d) noexcept { From ce1830fd21751e90060d77ba529bcd8904555587 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 24 Apr 2019 11:26:58 +0200 Subject: [PATCH 083/122] Migrate Windows system libs to external dependencies Started-by: Oswald Buddenhagen Change-Id: I211ce3252b836894aeeac1c85eb316d9596bca57 Reviewed-by: Oliver Wolff --- .../network/bearermonitor/bearermonitor.pro | 2 +- src/corelib/configure.json | 64 +++++++++++++++++++ src/corelib/corelib.pro | 6 +- src/corelib/io/io.pri | 3 +- src/dbus/dbus.pro | 10 +-- src/network/socket/socket.pri | 2 +- .../fontdatabases/windows/windows.pri | 4 +- .../fontdatabases/winrt/winrt.pri | 4 +- src/plugins/bearer/nla/nla.pro | 2 +- src/plugins/platforms/direct2d/direct2d.pro | 4 +- .../windows/uiautomation/uiautomation.pri | 3 +- src/plugins/platforms/windows/windows.pri | 14 ++-- src/plugins/platforms/windows/windows.pro | 3 +- src/plugins/platforms/winrt/winrt.pro | 3 +- src/plugins/printsupport/windows/windows.pro | 3 +- .../styles/windowsvista/windowsvista.pro | 2 +- src/printsupport/kernel/kernel.pri | 5 +- src/widgets/kernel/win.pri | 5 +- src/winmain/winmain.pro | 2 +- tests/auto/corelib/io/qfile/test.pro | 2 +- tests/auto/corelib/io/qfileinfo/qfileinfo.pro | 2 +- .../corelib/io/qlockfile/tst_qlockfile.pro | 2 +- .../testProcessEchoGui/testProcessEchoGui.pro | 2 +- .../io/qprocess/testSoftExit/testSoftExit.pro | 2 +- tests/auto/corelib/io/qsettings/qsettings.pro | 2 +- .../corelib/kernel/qeventloop/qeventloop.pro | 2 +- tests/auto/gui/image/qimage/qimage.pro | 2 +- tests/auto/gui/image/qpixmap/qpixmap.pro | 2 +- .../kernel/noqteventloop/noqteventloop.pro | 2 +- tests/auto/gui/kernel/qwindow/qwindow.pro | 2 +- .../kernel/qhostaddress/qhostaddress.pro | 2 +- .../network/kernel/qhostinfo/qhostinfo.pro | 2 +- .../platformsocketengine.pri | 2 +- .../network/socket/qtcpserver/test/test.pro | 2 +- .../network/socket/qtcpsocket/test/test.pro | 2 +- .../other/qaccessibility/qaccessibility.pro | 3 +- tests/auto/tools/qmakelib/qmakelib.pro | 2 +- .../qgraphicsitem/qgraphicsitem.pro | 2 +- .../qgraphicsscene/qgraphicsscene.pro | 2 +- .../itemviews/qitemdelegate/qitemdelegate.pro | 2 +- .../widgets/itemviews/qlistview/qlistview.pro | 2 +- tests/auto/widgets/kernel/qwidget/qwidget.pro | 2 +- .../widgets/widgets/qtabwidget/qtabwidget.pro | 2 +- tests/manual/diaglib/diaglib.pri | 2 +- 44 files changed, 133 insertions(+), 59 deletions(-) diff --git a/examples/network/bearermonitor/bearermonitor.pro b/examples/network/bearermonitor/bearermonitor.pro index 7d90b408e0..16ac41298a 100644 --- a/examples/network/bearermonitor/bearermonitor.pro +++ b/examples/network/bearermonitor/bearermonitor.pro @@ -13,7 +13,7 @@ FORMS = bearermonitor_240_320.ui \ bearermonitor_640_480.ui \ sessionwidget.ui -win32:LIBS += -lws2_32 +win32: QMAKE_USE += ws2_32 CONFIG += console diff --git a/src/corelib/configure.json b/src/corelib/configure.json index a6091d4825..d24867ffa0 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -235,6 +235,66 @@ "sources": [ "-lslog2" ] + }, + "advapi32": { + "label": "advapi32", + "sources": [ + "-ladvapi32" + ] + }, + "gdi32": { + "label": "gdi32", + "sources": [ + "-lgdi32" + ] + }, + "kernel32": { + "label": "kernel32", + "sources": [ + "-lkernel32" + ] + }, + "netapi32": { + "label": "netapi32", + "sources": [ + "-lnetapi32" + ] + }, + "ole32": { + "label": "ole32", + "sources": [ + "-lole32" + ] + }, + "shell32": { + "label": "shell32", + "sources": [ + "-lshell32" + ] + }, + "uuid": { + "label": "uuid", + "sources": [ + "-luuid" + ] + }, + "user32": { + "label": "user32", + "sources": [ + "-luser32" + ] + }, + "winmm": { + "label": "winmm", + "sources": [ + "-lwinmm" + ] + }, + "ws2_32": { + "label": "ws2_32", + "sources": [ + "-lws2_32" + ] } }, @@ -1017,6 +1077,10 @@ If enabled, a binary dump of the Public Suffix List (http://www.publicsuffix.org Mozilla License) is included. The data is then also used in QNetworkCookieJar::validateCookie.", "section": "Utilities", "output": [ "publicFeature" ] + }, + "win32_system_libs": { + "label": "Windows System Libraries", + "condition": "config.win32 && libs.advapi32 && libs.gdi32 && libs.kernel32 && libs.netapi32 && libs.ole32 && libs.shell32 && libs.uuid && libs.user32 && libs.winmm && libs.ws2_32" } }, diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index dc43e56836..6babbac8f5 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -47,10 +47,8 @@ include(mimetypes/mimetypes.pri) include(platform/platform.pri) win32 { - LIBS_PRIVATE += -lws2_32 - !winrt { - LIBS_PRIVATE += -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lwinmm - } + QMAKE_USE_PRIVATE += ws2_32 + !winrt: QMAKE_USE_PRIVATE += advapi32 kernel32 ole32 shell32 uuid user32 winmm } darwin { diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 9b6044752f..13b43ad8f7 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -158,7 +158,8 @@ win32 { io/qwindowspipereader.cpp \ io/qwindowspipewriter.cpp - LIBS += -lmpr -lnetapi32 -luserenv + LIBS += -lmpr -luserenv + QMAKE_USE_PRIVATE += netapi32 } else { SOURCES += \ io/qstandardpaths_winrt.cpp \ diff --git a/src/dbus/dbus.pro b/src/dbus/dbus.pro index 920a04315d..2cfd7e086c 100644 --- a/src/dbus/dbus.pro +++ b/src/dbus/dbus.pro @@ -9,11 +9,11 @@ qtConfig(dbus-linked) { } win32 { - LIBS_PRIVATE += \ - -lws2_32 \ - -ladvapi32 \ - -lnetapi32 \ - -luser32 + QMAKE_USE_PRIVATE += \ + advapi32 \ + netapi32 \ + user32 \ + ws2_32 } DEFINES += QT_NO_FOREACH diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index 44ff5b7b39..c3a98ea31a 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -58,7 +58,7 @@ unix { msvc: QMAKE_MOC_OPTIONS += -D_WINSOCK_DEPRECATED_NO_WARNINGS win32:!winrt:SOURCES += socket/qnativesocketengine_win.cpp -win32:!winrt:LIBS_PRIVATE += -ladvapi32 +win32:!winrt: QMAKE_USE_PRIVATE += advapi32 winrt { SOURCES += socket/qnativesocketengine_winrt.cpp diff --git a/src/platformsupport/fontdatabases/windows/windows.pri b/src/platformsupport/fontdatabases/windows/windows.pri index 9c529f55ea..7ddfb2c281 100644 --- a/src/platformsupport/fontdatabases/windows/windows.pri +++ b/src/platformsupport/fontdatabases/windows/windows.pri @@ -30,5 +30,5 @@ qtConfig(directwrite):qtConfig(direct2d) { DEFINES *= QT_NO_DIRECTWRITE } -LIBS += -lole32 -lgdi32 -luser32 -ladvapi32 -mingw: LIBS += -luuid +QMAKE_USE_PRIVATE += advapi32 ole32 user32 gdi32 +mingw: QMAKE_USE_PRIVATE += uuid diff --git a/src/platformsupport/fontdatabases/winrt/winrt.pri b/src/platformsupport/fontdatabases/winrt/winrt.pri index 7617df2e7a..1cd417c1fd 100644 --- a/src/platformsupport/fontdatabases/winrt/winrt.pri +++ b/src/platformsupport/fontdatabases/winrt/winrt.pri @@ -8,6 +8,4 @@ HEADERS += \ DEFINES += __WRL_NO_DEFAULT_LIB__ -LIBS += -lws2_32 - -QMAKE_USE_PRIVATE += dwrite_1 +QMAKE_USE_PRIVATE += dwrite_1 ws2_32 diff --git a/src/plugins/bearer/nla/nla.pro b/src/plugins/bearer/nla/nla.pro index 113d0667d2..76f3279d25 100644 --- a/src/plugins/bearer/nla/nla.pro +++ b/src/plugins/bearer/nla/nla.pro @@ -2,7 +2,7 @@ TARGET = qnlabearer QT = core core-private network network-private -LIBS += -lws2_32 +QMAKE_USE_PRIVATE += ws2_32 HEADERS += qnlaengine.h \ ../platformdefs_win.h \ diff --git a/src/plugins/platforms/direct2d/direct2d.pro b/src/plugins/platforms/direct2d/direct2d.pro index 9764272632..6e73bd14f9 100644 --- a/src/plugins/platforms/direct2d/direct2d.pro +++ b/src/plugins/platforms/direct2d/direct2d.pro @@ -8,8 +8,8 @@ QT += \ qtConfig(accessibility): QT += accessibility_support-private qtConfig(vulkan): QT += vulkan_support-private -LIBS += -ldwmapi -lversion -lgdi32 -QMAKE_USE_PRIVATE += dwrite_1 d2d1_1 d3d11_1 dxgi1_2 +LIBS += -ldwmapi -lversion +QMAKE_USE_PRIVATE += gdi32 dwrite_1 d2d1_1 d3d11_1 dxgi1_2 include(../windows/windows.pri) diff --git a/src/plugins/platforms/windows/uiautomation/uiautomation.pri b/src/plugins/platforms/windows/uiautomation/uiautomation.pri index e3071766d9..b79e42cdec 100644 --- a/src/plugins/platforms/windows/uiautomation/uiautomation.pri +++ b/src/plugins/platforms/windows/uiautomation/uiautomation.pri @@ -39,5 +39,4 @@ HEADERS += \ $$PWD/qwindowsuiagriditemprovider.h \ $$PWD/qwindowsuiautils.h -mingw: LIBS *= -luuid - +mingw: QMAKE_USE *= uuid diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 7004d7e854..95ba961df1 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -1,15 +1,21 @@ # Note: OpenGL32 must precede Gdi32 as it overwrites some functions. -LIBS += -lole32 -luser32 -lwinspool -limm32 -lwinmm -loleaut32 +LIBS += -lwinspool -limm32 -loleaut32 QT_FOR_CONFIG += gui qtConfig(opengl):!qtConfig(opengles2):!qtConfig(dynamicgl): LIBS *= -lopengl32 -mingw: LIBS *= -luuid +mingw: QMAKE_USE *= uuid # For the dialog helpers: -LIBS += -lshlwapi -lshell32 -ladvapi32 -lwtsapi32 +LIBS += -lshlwapi -lwtsapi32 -QMAKE_USE_PRIVATE += d3d9/nolink +QMAKE_USE_PRIVATE += \ + advapi32 \ + d3d9/nolink \ + ole32 \ + shell32 \ + user32 \ + winmm DEFINES *= QT_NO_CAST_FROM_ASCII QT_NO_FOREACH diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro index 174bc7b609..50a3bb41a9 100644 --- a/src/plugins/platforms/windows/windows.pro +++ b/src/plugins/platforms/windows/windows.pro @@ -8,7 +8,8 @@ QT += \ qtConfig(accessibility): QT += accessibility_support-private qtConfig(vulkan): QT += vulkan_support-private -LIBS += -lgdi32 -ldwmapi +LIBS += -ldwmapi +QMAKE_USE_PRIVATE += gdi32 include(windows.pri) diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index 43132a1a76..43dc8f074c 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -8,8 +8,7 @@ QT += \ DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ -LIBS += -lws2_32 -QMAKE_USE_PRIVATE += d3d11 +QMAKE_USE_PRIVATE += d3d11 ws2_32 SOURCES = \ main.cpp \ diff --git a/src/plugins/printsupport/windows/windows.pro b/src/plugins/printsupport/windows/windows.pro index 06694fb7fe..6ca601b2a4 100644 --- a/src/plugins/printsupport/windows/windows.pro +++ b/src/plugins/printsupport/windows/windows.pro @@ -18,7 +18,8 @@ HEADERS += \ OTHER_FILES += windows.json -LIBS += -lwinspool -lcomdlg32 -lgdi32 -luser32 +LIBS += -lwinspool -lcomdlg32 +QMAKE_USE_PRIVATE += user32 gdi32 PLUGIN_TYPE = printsupport PLUGIN_CLASS_NAME = QWindowsPrinterSupportPlugin diff --git a/src/plugins/styles/windowsvista/windowsvista.pro b/src/plugins/styles/windowsvista/windowsvista.pro index f82bcfc91b..c08db7f533 100644 --- a/src/plugins/styles/windowsvista/windowsvista.pro +++ b/src/plugins/styles/windowsvista/windowsvista.pro @@ -10,7 +10,7 @@ SOURCES += qwindowsvistastyle.cpp HEADERS += qwindowsxpstyle_p.h qwindowsxpstyle_p_p.h SOURCES += qwindowsxpstyle.cpp -LIBS_PRIVATE += -lgdi32 -luser32 +QMAKE_USE_PRIVATE += user32 gdi32 # DEFINES/LIBS needed for qwizard_win.cpp and the styles include(../../../widgets/kernel/win.pri) diff --git a/src/printsupport/kernel/kernel.pri b/src/printsupport/kernel/kernel.pri index ea7b4b9780..2ceaf152eb 100644 --- a/src/printsupport/kernel/kernel.pri +++ b/src/printsupport/kernel/kernel.pri @@ -33,7 +33,10 @@ win32 { $$PWD/qprintengine_win_p.h SOURCES += \ $$PWD/qprintengine_win.cpp - !winrt: LIBS_PRIVATE += -lwinspool -lcomdlg32 -lgdi32 -luser32 + !winrt { + LIBS_PRIVATE += -lwinspool -lcomdlg32 + QMAKE_USE_PRIVATE += user32 gdi32 + } } unix:!darwin:qtConfig(cups) { diff --git a/src/widgets/kernel/win.pri b/src/widgets/kernel/win.pri index f6877b02db..3b3170beb1 100644 --- a/src/widgets/kernel/win.pri +++ b/src/widgets/kernel/win.pri @@ -2,4 +2,7 @@ # -------------------------------------------------------------------- INCLUDEPATH += ../3rdparty/wintab -!winrt: LIBS_PRIVATE *= -lshell32 -luxtheme -ldwmapi +!winrt { + LIBS_PRIVATE *= -luxtheme -ldwmapi + QMAKE_USE_PRIVATE += shell32 +} diff --git a/src/winmain/winmain.pro b/src/winmain/winmain.pro index 9cb6ab0c59..1f54c846ec 100644 --- a/src/winmain/winmain.pro +++ b/src/winmain/winmain.pro @@ -23,7 +23,7 @@ winrt { } else { CONFIG -= qt SOURCES = qtmain_win.cpp - LIBS += -lshell32 + QMAKE_USE_PRIVATE += shell32 } load(qt_installs) diff --git a/tests/auto/corelib/io/qfile/test.pro b/tests/auto/corelib/io/qfile/test.pro index 95389ab3e2..7a2767bf3c 100644 --- a/tests/auto/corelib/io/qfile/test.pro +++ b/tests/auto/corelib/io/qfile/test.pro @@ -23,4 +23,4 @@ TESTDATA += \ Makefile forCopying.txt forRenaming.txt \ resources/file1.ext1 -win32:!winrt: LIBS += -lole32 -luuid +win32:!winrt: QMAKE_USE += ole32 uuid diff --git a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro index 496729f9f1..d181d16a3e 100644 --- a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro +++ b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro @@ -5,4 +5,4 @@ SOURCES = tst_qfileinfo.cpp RESOURCES += qfileinfo.qrc \ testdata.qrc -win32:!winrt: LIBS += -ladvapi32 -lnetapi32 +win32:!winrt: QMAKE_USE += advapi32 netapi32 diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro index da2660fd02..e33e22b36f 100644 --- a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro +++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro @@ -3,4 +3,4 @@ TARGET = tst_qlockfile SOURCES += tst_qlockfile.cpp QT = core-private testlib concurrent -win32:!winrt:LIBS += -ladvapi32 +win32:!winrt: QMAKE_USE += advapi32 diff --git a/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro b/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro index 935f43630c..e41ed0a425 100644 --- a/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro +++ b/tests/auto/corelib/io/qprocess/testProcessEchoGui/testProcessEchoGui.pro @@ -1,6 +1,6 @@ win32 { SOURCES = main_win.cpp - LIBS += -luser32 + QMAKE_USE += user32 } CONFIG -= qt app_bundle diff --git a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro b/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro index 2cfcb4794e..964c47f6ae 100644 --- a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro +++ b/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro @@ -1,6 +1,6 @@ win32 { SOURCES = main_win.cpp - LIBS += -luser32 + QMAKE_USE += user32 } unix { SOURCES = main_unix.cpp diff --git a/tests/auto/corelib/io/qsettings/qsettings.pro b/tests/auto/corelib/io/qsettings/qsettings.pro index 79552b62df..98ea337e7f 100644 --- a/tests/auto/corelib/io/qsettings/qsettings.pro +++ b/tests/auto/corelib/io/qsettings/qsettings.pro @@ -5,7 +5,7 @@ SOURCES = tst_qsettings.cpp RESOURCES += qsettings.qrc INCLUDEPATH += $$PWD/../../kernel/qmetatype -msvc: LIBS += advapi32.lib +msvc: QMAKE_USE += advapi32 darwin: LIBS += -framework CoreFoundation DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/kernel/qeventloop/qeventloop.pro b/tests/auto/corelib/kernel/qeventloop/qeventloop.pro index 295a42aa9c..159761c0c6 100644 --- a/tests/auto/corelib/kernel/qeventloop/qeventloop.pro +++ b/tests/auto/corelib/kernel/qeventloop/qeventloop.pro @@ -3,6 +3,6 @@ TARGET = tst_qeventloop QT = core network testlib core-private SOURCES = $$PWD/tst_qeventloop.cpp -win32:!winrt: LIBS += -luser32 +win32:!winrt: QMAKE_USE += user32 qtConfig(glib): DEFINES += HAVE_GLIB diff --git a/tests/auto/gui/image/qimage/qimage.pro b/tests/auto/gui/image/qimage/qimage.pro index b40866892e..0593cfbc23 100644 --- a/tests/auto/gui/image/qimage/qimage.pro +++ b/tests/auto/gui/image/qimage/qimage.pro @@ -7,7 +7,7 @@ qtConfig(c++11): CONFIG += c++11 android:!android-embedded: RESOURCES += qimage.qrc -win32:!winrt: LIBS += -lgdi32 -luser32 +win32:!winrt: QMAKE_USE += user32 gdi32 darwin: LIBS += -framework CoreGraphics TESTDATA += images/* diff --git a/tests/auto/gui/image/qpixmap/qpixmap.pro b/tests/auto/gui/image/qpixmap/qpixmap.pro index e6a020af1a..c9219dad1d 100644 --- a/tests/auto/gui/image/qpixmap/qpixmap.pro +++ b/tests/auto/gui/image/qpixmap/qpixmap.pro @@ -5,7 +5,7 @@ QT += core-private gui-private testlib qtHaveModule(widgets): QT += widgets widgets-private SOURCES += tst_qpixmap.cpp -win32:!winrt:LIBS += -lgdi32 -luser32 +win32:!winrt: QMAKE_USE += user32 gdi32 RESOURCES += qpixmap.qrc TESTDATA += convertFromImage/* convertFromToHICON/* loadFromData/* images/* diff --git a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro index 7e98704aea..293a6a8581 100644 --- a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro +++ b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro @@ -5,4 +5,4 @@ QT += core-private network gui-private testlib SOURCES += tst_noqteventloop.cpp -qtConfig(dynamicgl):win32:!winrt: LIBS += -luser32 +qtConfig(dynamicgl):win32:!winrt: QMAKE_USE += user32 diff --git a/tests/auto/gui/kernel/qwindow/qwindow.pro b/tests/auto/gui/kernel/qwindow/qwindow.pro index 844b3e8507..e7931ca773 100644 --- a/tests/auto/gui/kernel/qwindow/qwindow.pro +++ b/tests/auto/gui/kernel/qwindow/qwindow.pro @@ -5,4 +5,4 @@ QT += core-private gui-private testlib SOURCES += tst_qwindow.cpp -qtConfig(dynamicgl):win32:!winrt: LIBS += -luser32 +qtConfig(dynamicgl):win32:!winrt: QMAKE_USE += user32 diff --git a/tests/auto/network/kernel/qhostaddress/qhostaddress.pro b/tests/auto/network/kernel/qhostaddress/qhostaddress.pro index b5d6ea6459..d170d879e6 100644 --- a/tests/auto/network/kernel/qhostaddress/qhostaddress.pro +++ b/tests/auto/network/kernel/qhostaddress/qhostaddress.pro @@ -4,4 +4,4 @@ SOURCES += tst_qhostaddress.cpp QT = core network-private testlib -win32:LIBS += -lws2_32 +win32: QMAKE_USE += ws2_32 diff --git a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro index 3d8457dd46..d358cdf52c 100644 --- a/tests/auto/network/kernel/qhostinfo/qhostinfo.pro +++ b/tests/auto/network/kernel/qhostinfo/qhostinfo.pro @@ -6,6 +6,6 @@ SOURCES += tst_qhostinfo.cpp requires(qtConfig(private_tests)) QT = core-private network-private testlib -win32:LIBS += -lws2_32 +win32: QMAKE_USE += ws2_32 winrt: WINRT_MANIFEST.capabilities += internetClientServer diff --git a/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri b/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri index 46c722deba..868439de6a 100644 --- a/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri +++ b/tests/auto/network/socket/platformsocketengine/platformsocketengine.pri @@ -4,7 +4,7 @@ QNETWORK_SRC = $$QT_SOURCE_TREE/src/network INCLUDEPATH += $$QNETWORK_SRC -win32:LIBS += -lws2_32 +win32: QMAKE_USE += ws2_32 unix:qtConfig(reduce_exports) { SOURCES += $$QNETWORK_SRC/socket/qnativesocketengine_unix.cpp diff --git a/tests/auto/network/socket/qtcpserver/test/test.pro b/tests/auto/network/socket/qtcpserver/test/test.pro index de02fb032d..7e2e60a1e3 100644 --- a/tests/auto/network/socket/qtcpserver/test/test.pro +++ b/tests/auto/network/socket/qtcpserver/test/test.pro @@ -1,7 +1,7 @@ CONFIG += testcase SOURCES += ../tst_qtcpserver.cpp -win32:LIBS += -lws2_32 +win32: QMAKE_USE += ws2_32 TARGET = ../tst_qtcpserver diff --git a/tests/auto/network/socket/qtcpsocket/test/test.pro b/tests/auto/network/socket/qtcpsocket/test/test.pro index 05699bbe4e..4c07b1ec66 100644 --- a/tests/auto/network/socket/qtcpsocket/test/test.pro +++ b/tests/auto/network/socket/qtcpsocket/test/test.pro @@ -2,8 +2,8 @@ CONFIG += testcase QT = core-private network-private testlib SOURCES += ../tst_qtcpsocket.cpp -win32:LIBS += -lws2_32 +win32: QMAKE_USE += ws2_32 TARGET = tst_qtcpsocket win32 { diff --git a/tests/auto/other/qaccessibility/qaccessibility.pro b/tests/auto/other/qaccessibility/qaccessibility.pro index 3587c38e76..6f3740a24f 100644 --- a/tests/auto/other/qaccessibility/qaccessibility.pro +++ b/tests/auto/other/qaccessibility/qaccessibility.pro @@ -11,5 +11,6 @@ win32 { !winrt { QT += windowsuiautomation_support-private } - LIBS += -luuid -loleacc -loleaut32 -lole32 + LIBS += -loleacc -loleaut32 + QMAKE_USE += ole32 uuid } diff --git a/tests/auto/tools/qmakelib/qmakelib.pro b/tests/auto/tools/qmakelib/qmakelib.pro index 29f17f6a14..5e9e9fe637 100644 --- a/tests/auto/tools/qmakelib/qmakelib.pro +++ b/tests/auto/tools/qmakelib/qmakelib.pro @@ -1,7 +1,7 @@ CONFIG += testcase TARGET = tst_qmakelib QT = core testlib -win32: LIBS += -ladvapi32 +win32: QMAKE_USE += advapi32 INCLUDEPATH += ../../../../qmake/library VPATH += ../../../../qmake/library diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro index ae6de48195..16818a98f9 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro @@ -5,4 +5,4 @@ QT += core-private gui-private SOURCES += tst_qgraphicsitem.cpp DEFINES += QT_NO_CAST_TO_ASCII -win32:!winrt: LIBS += -luser32 +win32:!winrt: QMAKE_USE += user32 diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro index 351cecd92e..2f648a2212 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro +++ b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro @@ -4,7 +4,7 @@ QT += widgets widgets-private testlib QT += core-private gui-private SOURCES += tst_qgraphicsscene.cpp RESOURCES += images.qrc -win32:!winrt: LIBS += -luser32 +win32:!winrt: QMAKE_USE += user32 DEFINES += SRCDIR=\\\"$$PWD\\\" DEFINES += QT_NO_CAST_TO_ASCII diff --git a/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro index 10cd1dcc54..916694fd0f 100644 --- a/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro +++ b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro @@ -3,4 +3,4 @@ TARGET = tst_qitemdelegate QT += widgets widgets-private testlib SOURCES += tst_qitemdelegate.cpp -win32:!winrt: LIBS += -luser32 +win32:!winrt: QMAKE_USE += user32 diff --git a/tests/auto/widgets/itemviews/qlistview/qlistview.pro b/tests/auto/widgets/itemviews/qlistview/qlistview.pro index 75f45ab432..c3e19adc81 100644 --- a/tests/auto/widgets/itemviews/qlistview/qlistview.pro +++ b/tests/auto/widgets/itemviews/qlistview/qlistview.pro @@ -2,4 +2,4 @@ CONFIG += testcase TARGET = tst_qlistview QT += widgets gui-private widgets-private core-private testlib testlib-private SOURCES += tst_qlistview.cpp -win32:!winrt: LIBS += -luser32 +win32:!winrt: QMAKE_USE += user32 diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.pro b/tests/auto/widgets/kernel/qwidget/qwidget.pro index c1908af2a2..d3fbd6d0d9 100644 --- a/tests/auto/widgets/kernel/qwidget/qwidget.pro +++ b/tests/auto/widgets/kernel/qwidget/qwidget.pro @@ -16,4 +16,4 @@ mac { OBJECTIVE_SOURCES += tst_qwidget_mac_helpers.mm } -win32:!winrt: LIBS += -luser32 -lgdi32 +win32:!winrt: QMAKE_USE += user32 gdi32 diff --git a/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro b/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro index 6523209c32..b61cc8fa13 100644 --- a/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro +++ b/tests/auto/widgets/widgets/qtabwidget/qtabwidget.pro @@ -8,4 +8,4 @@ INCLUDEPATH += ../ HEADERS += SOURCES += tst_qtabwidget.cpp -win32:!winrt: LIBS += -luser32 +win32:!winrt: QMAKE_USE += user32 diff --git a/tests/manual/diaglib/diaglib.pri b/tests/manual/diaglib/diaglib.pri index 9f10167136..b57ee75841 100644 --- a/tests/manual/diaglib/diaglib.pri +++ b/tests/manual/diaglib/diaglib.pri @@ -12,7 +12,7 @@ HEADERS += \ win32:!winrt: { SOURCES += $$PWD/nativewindowdump_win.cpp - LIBS *= -luser32 + QMAKE_USE += user32 } else { SOURCES += $$PWD/nativewindowdump.cpp } From c1721cc859cc58cf04b73ba3e8db51f628684b26 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 8 May 2019 08:52:56 +0200 Subject: [PATCH 084/122] uic/Python: Generate empty strings as "" instead of QString() Task-number: PYSIDE-797 Change-Id: I4ce12ba01318e5ed7e88178dfd2450d9fe78c708 Reviewed-by: Cristian Maureira-Fredes --- src/tools/uic/cpp/cppwriteinitialization.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index 2510fd0edc..55541db98a 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -2465,8 +2465,10 @@ void WriteInitialization::initializeTableWidget(DomWidget *w) QString WriteInitialization::trCall(const QString &str, const QString &commentHint, const QString &id) const { - if (str.isEmpty()) - return QLatin1String("QString()"); + if (str.isEmpty()) { + return language::language() == Language::Cpp + ? QLatin1String("QString()") : QLatin1String("\"\""); + } QString result; QTextStream ts(&result); From 6a58a68ae3feb27dca48ebb3274b748f784b3d12 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 7 May 2019 17:25:59 +0200 Subject: [PATCH 085/122] Remove 3rdparty include from QTextMarkdownImporter header file It's a private header; but to be able to use it in a test, it has to be as clean as a public header. Change-Id: I868372406e62acc24051a6523fee89bb911a61f9 Reviewed-by: Gatis Paeglis --- src/gui/text/qtextmarkdownimporter.cpp | 49 +++++++++++++------------- src/gui/text/qtextmarkdownimporter_p.h | 45 ++++++++++++----------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index bcb0b777d4..2c520a71c9 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -46,6 +46,7 @@ #include #include #include +#include "../../3rdparty/md4c/md4c.h" QT_BEGIN_NAMESPACE @@ -57,31 +58,31 @@ Q_LOGGING_CATEGORY(lcMD, "qt.text.markdown") static int CbEnterBlock(MD_BLOCKTYPE type, void *detail, void *userdata) { QTextMarkdownImporter *mdi = static_cast(userdata); - return mdi->cbEnterBlock(type, detail); + return mdi->cbEnterBlock(int(type), detail); } static int CbLeaveBlock(MD_BLOCKTYPE type, void *detail, void *userdata) { QTextMarkdownImporter *mdi = static_cast(userdata); - return mdi->cbLeaveBlock(type, detail); + return mdi->cbLeaveBlock(int(type), detail); } static int CbEnterSpan(MD_SPANTYPE type, void *detail, void *userdata) { QTextMarkdownImporter *mdi = static_cast(userdata); - return mdi->cbEnterSpan(type, detail); + return mdi->cbEnterSpan(int(type), detail); } static int CbLeaveSpan(MD_SPANTYPE type, void *detail, void *userdata) { QTextMarkdownImporter *mdi = static_cast(userdata); - return mdi->cbLeaveSpan(type, detail); + return mdi->cbLeaveSpan(int(type), detail); } static int CbText(MD_TEXTTYPE type, const MD_CHAR *text, MD_SIZE size, void *userdata) { QTextMarkdownImporter *mdi = static_cast(userdata); - return mdi->cbText(type, text, size); + return mdi->cbText(int(type), text, size); } static void CbDebugLog(const char *msg, void *userdata) @@ -131,15 +132,15 @@ void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown) doc->clear(); qCDebug(lcMD) << "default font" << doc->defaultFont() << "mono font" << m_monoFont; QByteArray md = markdown.toUtf8(); - md_parse(md.constData(), md.size(), &callbacks, this); + md_parse(md.constData(), MD_SIZE(md.size()), &callbacks, this); delete m_cursor; m_cursor = nullptr; } -int QTextMarkdownImporter::cbEnterBlock(MD_BLOCKTYPE type, void *det) +int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) { - m_blockType = type; - switch (type) { + m_blockType = blockType; + switch (blockType) { case MD_BLOCK_P: { QTextBlockFormat blockFmt; int margin = m_doc->defaultFont().pointSize() / 2; @@ -157,10 +158,10 @@ int QTextMarkdownImporter::cbEnterBlock(MD_BLOCKTYPE type, void *det) MD_BLOCK_H_DETAIL *detail = static_cast(det); QTextBlockFormat blockFmt; QTextCharFormat charFmt; - int sizeAdjustment = 4 - detail->level; // H1 to H6: +3 to -2 + int sizeAdjustment = 4 - int(detail->level); // H1 to H6: +3 to -2 charFmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment); charFmt.setFontWeight(QFont::Bold); - blockFmt.setHeadingLevel(detail->level); + blockFmt.setHeadingLevel(int(detail->level)); m_cursor->insertBlock(blockFmt, charFmt); } break; case MD_BLOCK_LI: { @@ -258,10 +259,10 @@ int QTextMarkdownImporter::cbEnterBlock(MD_BLOCKTYPE type, void *det) return 0; // no error } -int QTextMarkdownImporter::cbLeaveBlock(MD_BLOCKTYPE type, void *detail) +int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail) { Q_UNUSED(detail) - switch (type) { + switch (blockType) { case MD_BLOCK_UL: case MD_BLOCK_OL: m_listStack.pop(); @@ -304,10 +305,10 @@ int QTextMarkdownImporter::cbLeaveBlock(MD_BLOCKTYPE type, void *detail) return 0; // no error } -int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) +int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det) { QTextCharFormat charFmt; - switch (type) { + switch (spanType) { case MD_SPAN_EM: charFmt.setFontItalic(true); break; @@ -316,8 +317,8 @@ int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) break; case MD_SPAN_A: { MD_SPAN_A_DETAIL *detail = static_cast(det); - QString url = QString::fromLatin1(detail->href.text, detail->href.size); - QString title = QString::fromLatin1(detail->title.text, detail->title.size); + QString url = QString::fromLatin1(detail->href.text, int(detail->href.size)); + QString title = QString::fromLatin1(detail->title.text, int(detail->title.size)); charFmt.setAnchorHref(url); charFmt.setAnchorNames(QStringList(title)); charFmt.setForeground(m_palette.link()); @@ -326,8 +327,8 @@ int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) case MD_SPAN_IMG: { m_imageSpan = true; MD_SPAN_IMG_DETAIL *detail = static_cast(det); - QString src = QString::fromUtf8(detail->src.text, detail->src.size); - QString title = QString::fromUtf8(detail->title.text, detail->title.size); + QString src = QString::fromUtf8(detail->src.text, int(detail->src.size)); + QString title = QString::fromUtf8(detail->title.text, int(detail->title.size)); QTextImageFormat img; img.setName(src); qCDebug(lcMD) << "image" << src << "title" << title << "relative to" << m_doc->baseUrl(); @@ -346,7 +347,7 @@ int QTextMarkdownImporter::cbEnterSpan(MD_SPANTYPE type, void *det) return 0; // no error } -int QTextMarkdownImporter::cbLeaveSpan(MD_SPANTYPE type, void *detail) +int QTextMarkdownImporter::cbLeaveSpan(int spanType, void *detail) { Q_UNUSED(detail) QTextCharFormat charFmt; @@ -356,20 +357,20 @@ int QTextMarkdownImporter::cbLeaveSpan(MD_SPANTYPE type, void *detail) charFmt = m_spanFormatStack.top(); } m_cursor->setCharFormat(charFmt); - if (type == MD_SPAN_IMG) + if (spanType == int(MD_SPAN_IMG)) m_imageSpan = false; return 0; // no error } -int QTextMarkdownImporter::cbText(MD_TEXTTYPE type, const MD_CHAR *text, MD_SIZE size) +int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) { if (m_imageSpan) return 0; // it's the alt-text static const QRegularExpression openingBracket(QStringLiteral("<[a-zA-Z]")); static const QRegularExpression closingBracket(QStringLiteral("(/>| #include -#include "../../3rdparty/md4c/md4c.h" - QT_BEGIN_NAMESPACE class QTextCursor; @@ -69,22 +67,23 @@ class Q_GUI_EXPORT QTextMarkdownImporter { public: enum Feature { - FeatureCollapseWhitespace = MD_FLAG_COLLAPSEWHITESPACE, - FeaturePermissiveATXHeaders = MD_FLAG_PERMISSIVEATXHEADERS, - FeaturePermissiveURLAutoLinks = MD_FLAG_PERMISSIVEURLAUTOLINKS, - FeaturePermissiveMailAutoLinks = MD_FLAG_PERMISSIVEEMAILAUTOLINKS, - FeatureNoIndentedCodeBlocks = MD_FLAG_NOINDENTEDCODEBLOCKS, - FeatureNoHTMLBlocks = MD_FLAG_NOHTMLBLOCKS, - FeatureNoHTMLSpans = MD_FLAG_NOHTMLSPANS, - FeatureTables = MD_FLAG_TABLES, - FeatureStrikeThrough = MD_FLAG_STRIKETHROUGH, - FeaturePermissiveWWWAutoLinks = MD_FLAG_PERMISSIVEWWWAUTOLINKS, - FeatureTasklists = MD_FLAG_TASKLISTS, + // Must be kept in sync with MD_FLAG_* in md4c.h + FeatureCollapseWhitespace = 0x0001, // MD_FLAG_COLLAPSEWHITESPACE + FeaturePermissiveATXHeaders = 0x0002, // MD_FLAG_PERMISSIVEATXHEADERS + FeaturePermissiveURLAutoLinks = 0x0004, // MD_FLAG_PERMISSIVEURLAUTOLINKS + FeaturePermissiveMailAutoLinks = 0x0008, // MD_FLAG_PERMISSIVEEMAILAUTOLINKS + FeatureNoIndentedCodeBlocks = 0x0010, // MD_FLAG_NOINDENTEDCODEBLOCKS + FeatureNoHTMLBlocks = 0x0020, // MD_FLAG_NOHTMLBLOCKS + FeatureNoHTMLSpans = 0x0040, // MD_FLAG_NOHTMLSPANS + FeatureTables = 0x0100, // MD_FLAG_TABLES + FeatureStrikeThrough = 0x0200, // MD_FLAG_STRIKETHROUGH + FeaturePermissiveWWWAutoLinks = 0x0400, // MD_FLAG_PERMISSIVEWWWAUTOLINKS + FeatureTasklists = 0x0800, // MD_FLAG_TASKLISTS // composite flags - FeaturePermissiveAutoLinks = MD_FLAG_PERMISSIVEAUTOLINKS, - FeatureNoHTML = MD_FLAG_NOHTML, - DialectCommonMark = MD_DIALECT_COMMONMARK, - DialectGitHub = MD_DIALECT_GITHUB + FeaturePermissiveAutoLinks = FeaturePermissiveMailAutoLinks | FeaturePermissiveURLAutoLinks | FeaturePermissiveWWWAutoLinks, // MD_FLAG_PERMISSIVEAUTOLINKS + FeatureNoHTML = FeatureNoHTMLBlocks | FeatureNoHTMLSpans, // MD_FLAG_NOHTML + DialectCommonMark = 0, // MD_DIALECT_COMMONMARK + DialectGitHub = FeaturePermissiveAutoLinks | FeatureTables | FeatureStrikeThrough | FeatureTasklists // MD_DIALECT_GITHUB }; Q_DECLARE_FLAGS(Features, Feature) @@ -94,11 +93,11 @@ public: public: // MD4C callbacks - int cbEnterBlock(MD_BLOCKTYPE type, void* detail); - int cbLeaveBlock(MD_BLOCKTYPE type, void* detail); - int cbEnterSpan(MD_SPANTYPE type, void* detail); - int cbLeaveSpan(MD_SPANTYPE type, void* detail); - int cbText(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size); + int cbEnterBlock(int blockType, void* detail); + int cbLeaveBlock(int blockType, void* detail); + int cbEnterSpan(int spanType, void* detail); + int cbLeaveSpan(int spanType, void* detail); + int cbText(int textType, const char* text, unsigned size); private: QTextDocument *m_doc = nullptr; @@ -115,7 +114,7 @@ private: int m_tableRowCount = 0; int m_tableCol = -1; // because relative cell movements (e.g. m_cursor->movePosition(QTextCursor::NextCell)) don't work Features m_features; - MD_BLOCKTYPE m_blockType = MD_BLOCK_DOC; + int m_blockType = 0; bool m_emptyList = false; // true when the last thing we did was insertList bool m_imageSpan = false; }; From 040dd7fe26bfa34aae19e2db698ff0d69346ed56 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 26 Apr 2019 07:40:34 +0200 Subject: [PATCH 086/122] Markdown: fix several issues with lists and continuations Importer fixes: - the first list item after a heading doesn't keep the heading font - the first text fragment after a bullet is the bullet text, not a separate paragraph - detect continuation lines and append to the list item text - detect continuation paragraphs and indent them properly - indent nested list items properly - add a test for QTextMarkdownImporter Writer fixes: - after bullet items, continuation lines and paragraphs are indented - indentation of continuations isn't affected by checkboxes - add extra newlines between list items in "loose" lists - avoid writing triple newlines - enhance the test for QTextMarkdownWriter Change-Id: Ib1dda514832f6dc0cdad177aa9a423a7038ac8c6 Reviewed-by: Gatis Paeglis --- src/gui/text/qtextmarkdownimporter.cpp | 59 +++++++-- src/gui/text/qtextmarkdownimporter_p.h | 2 + src/gui/text/qtextmarkdownwriter.cpp | 107 +++++++++++++--- src/gui/text/qtextmarkdownwriter_p.h | 11 ++ .../data/headingBulletsContinuations.md | 28 ++++ .../qtextmarkdownimporter.pro | 7 + .../tst_qtextmarkdownimporter.cpp | 121 ++++++++++++++++++ .../text/qtextmarkdownwriter/data/example.md | 18 +-- .../tst_qtextmarkdownwriter.cpp | 104 +++++++++++++-- tests/auto/gui/text/text.pro | 1 + 10 files changed, 410 insertions(+), 48 deletions(-) create mode 100644 tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md create mode 100644 tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro create mode 100644 tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index 2c520a71c9..a65d8f270e 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -52,6 +52,9 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcMD, "qt.text.markdown") +static const QChar Newline = QLatin1Char('\n'); +static const QChar Space = QLatin1Char(' '); + // -------------------------------------------------------- // MD4C callback function wrappers @@ -141,18 +144,33 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) { m_blockType = blockType; switch (blockType) { - case MD_BLOCK_P: { - QTextBlockFormat blockFmt; - int margin = m_doc->defaultFont().pointSize() / 2; - blockFmt.setTopMargin(margin); - blockFmt.setBottomMargin(margin); - m_cursor->insertBlock(blockFmt, QTextCharFormat()); - } break; + case MD_BLOCK_P: + if (m_listStack.isEmpty()) { + QTextBlockFormat blockFmt; + int margin = m_doc->defaultFont().pointSize() / 2; + blockFmt.setTopMargin(margin); + blockFmt.setBottomMargin(margin); + m_cursor->insertBlock(blockFmt, QTextCharFormat()); + qCDebug(lcMD, "P"); + } else { + if (m_emptyListItem) { + qCDebug(lcMD, "LI text block at level %d -> BlockIndent %d", + m_listStack.count(), m_cursor->blockFormat().indent()); + m_emptyListItem = false; + } else { + qCDebug(lcMD, "P inside LI at level %d", m_listStack.count()); + QTextBlockFormat blockFmt; + blockFmt.setIndent(m_listStack.count()); + m_cursor->insertBlock(blockFmt, QTextCharFormat()); + } + } + break; case MD_BLOCK_CODE: { QTextBlockFormat blockFmt; QTextCharFormat charFmt; charFmt.setFont(m_monoFont); m_cursor->insertBlock(blockFmt, charFmt); + qCDebug(lcMD, "CODE"); } break; case MD_BLOCK_H: { MD_BLOCK_H_DETAIL *detail = static_cast(det); @@ -163,6 +181,7 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) charFmt.setFontWeight(QFont::Bold); blockFmt.setHeadingLevel(int(detail->level)); m_cursor->insertBlock(blockFmt, charFmt); + qCDebug(lcMD, "H%d", detail->level); } break; case MD_BLOCK_LI: { MD_BLOCK_LI_DETAIL *detail = static_cast(det); @@ -176,7 +195,10 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) list->add(m_cursor->block()); } m_cursor->setBlockFormat(bfmt); + qCDebug(lcMD) << (m_emptyList ? "LI (first in list)" : "LI"); m_emptyList = false; // Avoid insertBlock for the first item (because insertList already did that) + m_listItem = true; + m_emptyListItem = true; } break; case MD_BLOCK_UL: { MD_BLOCK_UL_DETAIL *detail = static_cast(det); @@ -193,6 +215,7 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) fmt.setStyle(QTextListFormat::ListDisc); break; } + qCDebug(lcMD, "UL %c level %d", detail->mark, m_listStack.count()); m_listStack.push(m_cursor->insertList(fmt)); m_emptyList = true; } break; @@ -202,6 +225,7 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) fmt.setIndent(m_listStack.count() + 1); fmt.setNumberSuffix(QChar::fromLatin1(detail->mark_delimiter)); fmt.setStyle(QTextListFormat::ListDecimal); + qCDebug(lcMD, "OL xx%d level %d", detail->mark_delimiter, m_listStack.count()); m_listStack.push(m_cursor->insertList(fmt)); m_emptyList = true; } break; @@ -265,6 +289,7 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail) switch (blockType) { case MD_BLOCK_UL: case MD_BLOCK_OL: + qCDebug(lcMD, "list at level %d ended", m_listStack.count()); m_listStack.pop(); break; case MD_BLOCK_TR: { @@ -299,6 +324,14 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail) m_currentTable = nullptr; m_cursor->movePosition(QTextCursor::End); break; + case MD_BLOCK_LI: + qCDebug(lcMD, "LI at level %d ended", m_listStack.count()); + m_listItem = false; + break; + case MD_BLOCK_CODE: + case MD_BLOCK_H: + m_cursor->setCharFormat(QTextCharFormat()); + break; default: break; } @@ -381,10 +414,10 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) s = QString(QChar(0xFFFD)); // CommonMark-required replacement for null break; case MD_TEXT_BR: - s = QLatin1String("\n"); + s = QString(Newline); break; case MD_TEXT_SOFTBR: - s = QLatin1String(" "); + s = QString(Space); break; case MD_TEXT_CODE: // We'll see MD_SPAN_CODE too, which will set the char format, and that's enough. @@ -431,6 +464,14 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) if (!s.isEmpty()) m_cursor->insertText(s); + if (m_cursor->currentList()) { + // The list item will indent the list item's text, so we don't need indentation on the block. + QTextBlockFormat blockFmt = m_cursor->blockFormat(); + blockFmt.setIndent(0); + m_cursor->setBlockFormat(blockFmt); + } + qCDebug(lcMD) << textType << "in block" << m_blockType << s << "in list?" << m_cursor->currentList() + << "indent" << m_cursor->blockFormat().indent(); return 0; // no error } diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h index dee24a8e22..8ab119d051 100644 --- a/src/gui/text/qtextmarkdownimporter_p.h +++ b/src/gui/text/qtextmarkdownimporter_p.h @@ -116,6 +116,8 @@ private: Features m_features; int m_blockType = 0; bool m_emptyList = false; // true when the last thing we did was insertList + bool m_listItem = false; + bool m_emptyListItem = false; bool m_imageSpan = false; }; diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index 313d62bb8a..2f4c8587ad 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -46,12 +46,17 @@ #include "qtexttable.h" #include "qtextcursor.h" #include "qtextimagehandler_p.h" +#include "qloggingcategory.h" QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcMDW, "qt.text.markdown.writer") + static const QChar Space = QLatin1Char(' '); static const QChar Newline = QLatin1Char('\n'); +static const QChar LineBreak = QChar(0x2028); static const QChar Backtick = QLatin1Char('`'); +static const QChar Period = QLatin1Char('.'); QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features) : m_stream(stream), m_features(features) @@ -93,6 +98,7 @@ void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) } m_stream << '|'<< Qt::endl; } + m_listInfo.clear(); } void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) @@ -144,6 +150,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) m_stream << Newline; } int endingCol = writeBlock(block, !table, table && tableRow == 0); + m_doubleNewlineWritten = false; if (table) { QTextTableCell cell = table->cellAt(block.position()); int paddingLen = -endingCol; @@ -158,14 +165,48 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) m_stream << Newline; } else if (endingCol > 0) { m_stream << Newline << Newline; + m_doubleNewlineWritten = true; } lastWasList = block.textList(); } child = iterator.currentFrame(); ++iterator; } - if (table) + if (table) { m_stream << Newline << Newline; + m_doubleNewlineWritten = true; + } + m_listInfo.clear(); +} + +QTextMarkdownWriter::ListInfo QTextMarkdownWriter::listInfo(QTextList *list) +{ + if (!m_listInfo.contains(list)) { + // decide whether this list is loose or tight + ListInfo info; + info.loose = false; + if (list->count() > 1) { + QTextBlock first = list->item(0); + QTextBlock last = list->item(list->count() - 1); + QTextBlock next = first.next(); + while (next.isValid()) { + if (next == last) + break; + qCDebug(lcMDW) << "next block in list" << list << next.text() << "part of list?" << next.textList(); + if (!next.textList()) { + // If we find a continuation paragraph, this list is "loose" + // because it will need a blank line to separate that paragraph. + qCDebug(lcMDW) << "decided list beginning with" << first.text() << "is loose after" << next.text(); + info.loose = true; + break; + } + next = next.next(); + } + } + m_listInfo.insert(list, info); + return info; + } + return m_listInfo.value(list); } static int nearestWordWrapIndex(const QString &s, int before) @@ -211,7 +252,6 @@ static void maybeEscapeFirstChar(QString &s) int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat) { int ColumnLimit = 80; - int wrapIndent = 0; if (block.textList()) { // it's a list-item auto fmt = block.textList()->format(); const int listLevel = fmt.indent(); @@ -219,9 +259,18 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign QByteArray bullet = " "; bool numeric = false; switch (fmt.style()) { - case QTextListFormat::ListDisc: bullet = "-"; break; - case QTextListFormat::ListCircle: bullet = "*"; break; - case QTextListFormat::ListSquare: bullet = "+"; break; + case QTextListFormat::ListDisc: + bullet = "-"; + m_wrappedLineIndent = 2; + break; + case QTextListFormat::ListCircle: + bullet = "*"; + m_wrappedLineIndent = 2; + break; + case QTextListFormat::ListSquare: + bullet = "+"; + m_wrappedLineIndent = 2; + break; case QTextListFormat::ListStyleUndefined: break; case QTextListFormat::ListDecimal: case QTextListFormat::ListLowerAlpha: @@ -229,6 +278,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign case QTextListFormat::ListLowerRoman: case QTextListFormat::ListUpperRoman: numeric = true; + m_wrappedLineIndent = 4; break; } switch (block.blockFormat().marker()) { @@ -241,23 +291,36 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign default: break; } - QString prefix((listLevel - 1) * (numeric ? 4 : 2), Space); - if (numeric) - prefix += QString::number(number) + fmt.numberSuffix() + Space; - else + int indentFirstLine = (listLevel - 1) * (numeric ? 4 : 2); + m_wrappedLineIndent += indentFirstLine; + if (m_lastListIndent != listLevel && !m_doubleNewlineWritten && listInfo(block.textList()).loose) + m_stream << Newline; + m_lastListIndent = listLevel; + QString prefix(indentFirstLine, Space); + if (numeric) { + QString suffix = fmt.numberSuffix(); + if (suffix.isEmpty()) + suffix = QString(Period); + QString numberStr = QString::number(number) + suffix + Space; + if (numberStr.length() == 3) + numberStr += Space; + prefix += numberStr; + } else { prefix += QLatin1String(bullet) + Space; + } m_stream << prefix; - wrapIndent = prefix.length(); + } else if (!block.blockFormat().indent()) { + m_wrappedLineIndent = 0; } if (block.blockFormat().headingLevel()) m_stream << QByteArray(block.blockFormat().headingLevel(), '#') << ' '; - QString wrapIndentString(wrapIndent, Space); + QString wrapIndentString(m_wrappedLineIndent, Space); // It would be convenient if QTextStream had a lineCharPos() accessor, // to keep track of how many characters (not bytes) have been written on the current line, // but it doesn't. So we have to keep track with this col variable. - int col = wrapIndent; + int col = m_wrappedLineIndent; bool mono = false; bool startsOrEndsWithBacktick = false; bool bold = false; @@ -267,8 +330,16 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign QString backticks(Backtick); for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) { QString fragmentText = frag.fragment().text(); - while (fragmentText.endsWith(QLatin1Char('\n'))) + while (fragmentText.endsWith(Newline)) fragmentText.chop(1); + if (block.textList()) { //
  • first line
    continuation
  • + QString newlineIndent = QString(Newline) + QString(m_wrappedLineIndent, Space); + fragmentText.replace(QString(LineBreak), newlineIndent); + } else if (block.blockFormat().indent() > 0) { //
  • first line

    continuation

  • + m_stream << QString(m_wrappedLineIndent, Space); + } else { + fragmentText.replace(LineBreak, Newline); + } startsOrEndsWithBacktick |= fragmentText.startsWith(Backtick) || fragmentText.endsWith(Backtick); QTextCharFormat fmt = frag.fragment().charFormat(); if (fmt.isImageFormat()) { @@ -276,7 +347,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign QString s = QLatin1String("![image](") + ifmt.name() + QLatin1Char(')'); if (wrap && col + s.length() > ColumnLimit) { m_stream << Newline << wrapIndentString; - col = wrapIndent; + col = m_wrappedLineIndent; } m_stream << s; col += s.length(); @@ -285,7 +356,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign fmt.property(QTextFormat::AnchorHref).toString() + QLatin1Char(')'); if (wrap && col + s.length() > ColumnLimit) { m_stream << Newline << wrapIndentString; - col = wrapIndent; + col = m_wrappedLineIndent; } m_stream << s; col += s.length(); @@ -296,7 +367,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign if (!ignoreFormat) { if (monoFrag != mono) { if (monoFrag) - backticks = QString::fromLatin1(QByteArray(adjacentBackticksCount(fragmentText) + 1, '`')); + backticks = QString(adjacentBackticksCount(fragmentText) + 1, Backtick); markers += backticks; if (startsOrEndsWithBacktick) markers += Space; @@ -347,12 +418,12 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign m_stream << markers; col += markers.length(); } - if (col == wrapIndent) + if (col == m_wrappedLineIndent) maybeEscapeFirstChar(subfrag); m_stream << subfrag; if (breakingLine) { m_stream << Newline << wrapIndentString; - col = wrapIndent; + col = m_wrappedLineIndent; } else { col += subfrag.length(); } diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h index 2a9388ca2d..250288bcff 100644 --- a/src/gui/text/qtextmarkdownwriter_p.h +++ b/src/gui/text/qtextmarkdownwriter_p.h @@ -70,9 +70,20 @@ public: int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat); void writeFrame(const QTextFrame *frame); +private: + struct ListInfo { + bool loose; + }; + + ListInfo listInfo(QTextList *list); + private: QTextStream &m_stream; QTextDocument::MarkdownFeatures m_features; + QMap m_listInfo; + int m_wrappedLineIndent = 0; + int m_lastListIndent = 1; + bool m_doubleNewlineWritten = false; }; QT_END_NAMESPACE diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md b/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md new file mode 100644 index 0000000000..99eb633d17 --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md @@ -0,0 +1,28 @@ +# heading +- bullet 1 + continuation line 1, indented via tab +- bullet 2 + continuation line 2, indented via 4 spaces +- bullet 3 + + continuation paragraph 3, indented via tab + + - bullet 3.1 + + continuation paragraph 3.1, indented via 4 spaces + + - bullet 3.2 + continuation line, indented via 2 tabs +- bullet 4 + + continuation paragraph 4, indented via 4 spaces + and continuing onto another line too + +- bullet 5 + + continuation paragraph 5, indented via 2 spaces and continuing onto another + line too + +- bullet 6 + +plain old paragraph at the end diff --git a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro new file mode 100644 index 0000000000..3b63a67228 --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro @@ -0,0 +1,7 @@ +CONFIG += testcase +TARGET = tst_qtextmarkdownimporter +QT += core-private gui-private testlib +SOURCES += tst_qtextmarkdownimporter.cpp +TESTDATA += data/headingBulletsContinuations.md + +DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp new file mode 100644 index 0000000000..2ede2e73ad --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** 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-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// #define DEBUG_WRITE_HTML + +Q_LOGGING_CATEGORY(lcTests, "qt.text.tests") + +static const QChar LineBreak = QChar(0x2028); +static const QChar Tab = QLatin1Char('\t'); +static const QChar Space = QLatin1Char(' '); +static const QChar Period = QLatin1Char('.'); + +class tst_QTextMarkdownImporter : public QObject +{ + Q_OBJECT + +private slots: + void headingBulletsContinuations(); +}; + +void tst_QTextMarkdownImporter::headingBulletsContinuations() +{ + const QStringList expectedBlocks = QStringList() << + "" << // we could do without this blank line before the heading, but currently it happens + "heading" << + "bullet 1 continuation line 1, indented via tab" << + "bullet 2 continuation line 2, indented via 4 spaces" << + "bullet 3" << + "continuation paragraph 3, indented via tab" << + "bullet 3.1" << + "continuation paragraph 3.1, indented via 4 spaces" << + "bullet 3.2 continuation line, indented via 2 tabs" << + "bullet 4" << + "continuation paragraph 4, indented via 4 spaces and continuing onto another line too" << + "bullet 5" << + // indenting by only 2 spaces is perhaps non-standard but currently is OK + "continuation paragraph 5, indented via 2 spaces and continuing onto another line too" << + "bullet 6" << + "plain old paragraph at the end"; + + QFile f(QFINDTESTDATA("data/headingBulletsContinuations.md")); + QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text)); + QString md = QString::fromUtf8(f.readAll()); + f.close(); + + QTextDocument doc; + QTextMarkdownImporter(QTextMarkdownImporter::DialectGitHub).import(&doc, md); + QTextFrame::iterator iterator = doc.rootFrame()->begin(); + QTextFrame *currentFrame = iterator.currentFrame(); + QStringList::const_iterator expectedIt = expectedBlocks.constBegin(); + int i = 0; + while (!iterator.atEnd()) { + // There are no child frames + QCOMPARE(iterator.currentFrame(), currentFrame); + // Check whether we got the right child block + QTextBlock block = iterator.currentBlock(); + QCOMPARE(block.text().contains(LineBreak), false); + QCOMPARE(block.text().contains(Tab), false); + QVERIFY(!block.text().startsWith(Space)); + int expectedIndentation = 0; + if (block.text().contains(QLatin1String("continuation paragraph"))) + expectedIndentation = (block.text().contains(Period) ? 2 : 1); + qCDebug(lcTests) << i << "child block" << block.text() << "indentation" << block.blockFormat().indent(); + QVERIFY(expectedIt != expectedBlocks.constEnd()); + QCOMPARE(block.text(), *expectedIt); + if (i > 2) + QCOMPARE(block.blockFormat().indent(), expectedIndentation); + ++iterator; + ++expectedIt; + ++i; + } + QCOMPARE(expectedIt, expectedBlocks.constEnd()); + +#ifdef DEBUG_WRITE_HTML + { + QFile out("/tmp/headingBulletsContinuations.html"); + out.open(QFile::WriteOnly); + out.write(doc.toHtml().toLatin1()); + out.close(); + } +#endif +} + +QTEST_MAIN(tst_QTextMarkdownImporter) +#include "tst_qtextmarkdownimporter.moc" diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/example.md b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md index 3c63f209a2..0c3f34e09d 100644 --- a/tests/auto/gui/text/qtextmarkdownwriter/data/example.md +++ b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md @@ -27,8 +27,8 @@ text layout changes.* Different kinds of lists can be included in rich text documents. Standard bullet lists can be nested, using different symbols for each level of the list: -* Disc symbols are typically used for top-level list items. - - Circle symbols can be used to distinguish between items in lower-level +- Disc symbols are typically used for top-level list items. + * Circle symbols can be used to distinguish between items in lower-level lists. + Square symbols provide a reasonable alternative to discs and circles. @@ -36,13 +36,13 @@ Ordered lists can be created that can be used for tables of contents. Different characters can be used to enumerate items, and we can use both Roman and Arabic numerals in the same list structure: -1. Introduction -2. Qt Tools - 1) Qt Assistant - 2) Qt Designer - 1. Form Editor - 2. Component Architecture - 3) Qt Linguist +1. Introduction +2. Qt Tools + 1) Qt Assistant + 2) Qt Designer + 1. Form Editor + 2. Component Architecture + 3) Qt Linguist The list will automatically be renumbered if you add or remove items. *Try adding new sections to the above list or removing existing item to see the diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp index bf7c9708de..dca6d90a48 100644 --- a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp +++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp @@ -50,6 +50,7 @@ private slots: void testWriteParagraph_data(); void testWriteParagraph(); void testWriteList(); + void testWriteNestedBulletLists_data(); void testWriteNestedBulletLists(); void testWriteNestedNumericLists(); void testWriteTable(); @@ -122,9 +123,44 @@ void tst_QTextMarkdownWriter::testWriteList() "- ListItem 1\n- ListItem 2\n")); } +void tst_QTextMarkdownWriter::testWriteNestedBulletLists_data() +{ + QTest::addColumn("checkbox"); + QTest::addColumn("checked"); + QTest::addColumn("continuationLine"); + QTest::addColumn("continuationParagraph"); + QTest::addColumn("expectedOutput"); + + QTest::newRow("plain bullets") << false << false << false << false << + "- ListItem 1\n * ListItem 2\n + ListItem 3\n- ListItem 4\n * ListItem 5\n"; + QTest::newRow("bullets with continuation lines") << false << false << true << false << + "- ListItem 1\n * ListItem 2\n + ListItem 3 with text that won't fit on one line and thus needs a\n continuation\n- ListItem 4\n * ListItem 5 with text that won't fit on one line and thus needs a\n continuation\n"; + QTest::newRow("bullets with continuation paragraphs") << false << false << false << true << + "- ListItem 1\n\n * ListItem 2\n + ListItem 3\n\n continuation\n\n- ListItem 4\n\n * ListItem 5\n\n continuation\n\n"; + QTest::newRow("unchecked") << true << false << false << false << + "- [ ] ListItem 1\n * [ ] ListItem 2\n + [ ] ListItem 3\n- [ ] ListItem 4\n * [ ] ListItem 5\n"; + QTest::newRow("checked") << true << true << false << false << + "- [x] ListItem 1\n * [x] ListItem 2\n + [x] ListItem 3\n- [x] ListItem 4\n * [x] ListItem 5\n"; + QTest::newRow("checked with continuation lines") << true << true << true << false << + "- [x] ListItem 1\n * [x] ListItem 2\n + [x] ListItem 3 with text that won't fit on one line and thus needs a\n continuation\n- [x] ListItem 4\n * [x] ListItem 5 with text that won't fit on one line and thus needs a\n continuation\n"; + QTest::newRow("checked with continuation paragraphs") << true << true << false << true << + "- [x] ListItem 1\n\n * [x] ListItem 2\n + [x] ListItem 3\n\n continuation\n\n- [x] ListItem 4\n\n * [x] ListItem 5\n\n continuation\n\n"; +} + void tst_QTextMarkdownWriter::testWriteNestedBulletLists() { + QFETCH(bool, checkbox); + QFETCH(bool, checked); + QFETCH(bool, continuationParagraph); + QFETCH(bool, continuationLine); + QFETCH(QString, expectedOutput); + QTextCursor cursor(document); + QTextBlockFormat blockFmt = cursor.blockFormat(); + if (checkbox) { + blockFmt.setMarker(checked ? QTextBlockFormat::Checked : QTextBlockFormat::Unchecked); + cursor.setBlockFormat(blockFmt); + } QTextList *list1 = cursor.createList(QTextListFormat::ListDisc); cursor.insertText("ListItem 1"); @@ -140,18 +176,42 @@ void tst_QTextMarkdownWriter::testWriteNestedBulletLists() fmt3.setStyle(QTextListFormat::ListSquare); fmt3.setIndent(3); cursor.insertList(fmt3); - cursor.insertText("ListItem 3"); + cursor.insertText(continuationLine ? + "ListItem 3 with text that won't fit on one line and thus needs a continuation" : + "ListItem 3"); + if (continuationParagraph) { + QTextBlockFormat blockFmt; + blockFmt.setIndent(2); + cursor.insertBlock(blockFmt); + cursor.insertText("continuation"); + } - cursor.insertBlock(); + cursor.insertBlock(blockFmt); cursor.insertText("ListItem 4"); list1->add(cursor.block()); cursor.insertBlock(); - cursor.insertText("ListItem 5"); + cursor.insertText(continuationLine ? + "ListItem 5 with text that won't fit on one line and thus needs a continuation" : + "ListItem 5"); list2->add(cursor.block()); + if (continuationParagraph) { + QTextBlockFormat blockFmt; + blockFmt.setIndent(2); + cursor.insertBlock(blockFmt); + cursor.insertText("continuation"); + } - QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1( - "- ListItem 1\n * ListItem 2\n + ListItem 3\n- ListItem 4\n * ListItem 5\n")); + QString output = documentToUnixMarkdown(); +#ifdef DEBUG_WRITE_OUTPUT + { + QFile out("/tmp/" + QLatin1String(QTest::currentDataTag()) + ".md"); + out.open(QFile::WriteOnly); + out.write(output.toUtf8()); + out.close(); + } +#endif + QCOMPARE(documentToUnixMarkdown(), expectedOutput); } void tst_QTextMarkdownWriter::testWriteNestedNumericLists() @@ -185,7 +245,7 @@ void tst_QTextMarkdownWriter::testWriteNestedNumericLists() // There's no QTextList API to set the starting number so we hard-coded all lists to start at 1 (QTBUG-65384) QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1( - "1 ListItem 1\n 1) ListItem 2\n 1 ListItem 3\n2 ListItem 4\n 2) ListItem 5\n")); + "1. ListItem 1\n 1) ListItem 2\n 1. ListItem 3\n2. ListItem 4\n 2) ListItem 5\n")); } void tst_QTextMarkdownWriter::testWriteTable() @@ -312,8 +372,8 @@ void tst_QTextMarkdownWriter::rewriteDocument() void tst_QTextMarkdownWriter::fromHtml_data() { - QTest::addColumn("input"); - QTest::addColumn("output"); + QTest::addColumn("expectedInput"); + QTest::addColumn("expectedOutput"); QTest::newRow("long URL") << "https://www.example.com/dir/subdir/subsubdir/subsubsubdir/subsubsubsubdir/subsubsubsubsubdir/" << @@ -329,6 +389,15 @@ void tst_QTextMarkdownWriter::fromHtml_data() QTest::newRow("escaped hyphen after newline") << "The first sentence of this paragraph holds 80 characters, then there's a minus. - This is wrapped, but is not a bullet point." << "The first sentence of this paragraph holds 80 characters, then there's a minus.\n\\- This is wrapped, but is *not* a bullet point.\n\n"; + QTest::newRow("list items with indented continuations") << + "
    • bullet

      continuation paragraph

    • another bullet
      continuation line
    " << + "- bullet\n\n continuation paragraph\n\n- another bullet\n continuation line\n"; + QTest::newRow("nested list items with continuations") << + "
    • bullet

      continuation paragraph

    • another bullet
      continuation line
      • bullet

        continuation paragraph

      • another bullet
        continuation line
    " << + "- bullet\n\n continuation paragraph\n\n- another bullet\n continuation line\n\n - bullet\n\n continuation paragraph\n\n - another bullet\n continuation line\n"; + QTest::newRow("nested ordered list items with continuations") << + "
    1. item

      continuation paragraph

    2. another item
      continuation line
      1. item

        continuation paragraph

      2. another item
        continuation line
    3. another
    4. another
    " << + "1. item\n\n continuation paragraph\n\n2. another item\n continuation line\n\n 1. item\n\n continuation paragraph\n\n 2. another item\n continuation line\n\n3. another\n4. another\n"; // TODO // QTest::newRow("escaped number and paren after double newline") << // "

    (The first sentence of this paragraph is a line, the next paragraph has a number

    13) but that's not part of an ordered list" << @@ -340,11 +409,22 @@ void tst_QTextMarkdownWriter::fromHtml_data() void tst_QTextMarkdownWriter::fromHtml() { - QFETCH(QString, input); - QFETCH(QString, output); + QFETCH(QString, expectedInput); + QFETCH(QString, expectedOutput); - document->setHtml(input); - QCOMPARE(documentToUnixMarkdown(), output); + document->setHtml(expectedInput); + QString output = documentToUnixMarkdown(); + +#ifdef DEBUG_WRITE_OUTPUT + { + QFile out("/tmp/" + QLatin1String(QTest::currentDataTag()) + ".md"); + out.open(QFile::WriteOnly); + out.write(output.toUtf8()); + out.close(); + } +#endif + + QCOMPARE(output, expectedOutput); } QString tst_QTextMarkdownWriter::documentToUnixMarkdown() diff --git a/tests/auto/gui/text/text.pro b/tests/auto/gui/text/text.pro index a98debe35c..794d9ea8d3 100644 --- a/tests/auto/gui/text/text.pro +++ b/tests/auto/gui/text/text.pro @@ -28,6 +28,7 @@ SUBDIRS=\ win32:SUBDIRS -= qtextpiecetable +qtConfig(textmarkdownreader): SUBDIRS += qtextmarkdownimporter qtConfig(textmarkdownwriter): SUBDIRS += qtextmarkdownwriter !qtConfig(private_tests): SUBDIRS -= \ From 76716c4a9adc3f9aeb251d3ebe4d1d0be38b97ee Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 26 Apr 2019 08:29:07 +0200 Subject: [PATCH 087/122] Markdown: deal with horizontal rules (thematic breaks) Change-Id: I14d4bcfe1a6c3bd87d1328f0abb81b2138545e4e Reviewed-by: Gatis Paeglis --- src/gui/text/qtextmarkdownimporter.cpp | 3 +- src/gui/text/qtextmarkdownwriter.cpp | 3 ++ .../data/thematicBreaks.md | 17 ++++++++ .../qtextmarkdownimporter.pro | 3 +- .../tst_qtextmarkdownimporter.cpp | 42 +++++++++++++++++++ .../tst_qtextmarkdownwriter.cpp | 3 ++ 6 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index a65d8f270e..5cee01d932 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -273,7 +273,8 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) m_currentTable = m_cursor->insertTable(1, 1); // we don't know the dimensions yet break; case MD_BLOCK_HR: { - QTextBlockFormat blockFmt = m_cursor->blockFormat(); + qCDebug(lcMD, "HR"); + QTextBlockFormat blockFmt; blockFmt.setProperty(QTextFormat::BlockTrailingHorizontalRulerWidth, 1); m_cursor->insertBlock(blockFmt, QTextCharFormat()); } break; diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index 2f4c8587ad..0634d324b1 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -309,6 +309,9 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign prefix += QLatin1String(bullet) + Space; } m_stream << prefix; + } else if (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) { + m_stream << "- - -\n"; // unambiguous horizontal rule, not an underline under a heading + return 0; } else if (!block.blockFormat().indent()) { m_wrappedLineIndent = 0; } diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md b/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md new file mode 100644 index 0000000000..7a0d5388ad --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md @@ -0,0 +1,17 @@ +Heading +------- +*** +stars +- bullet + ** not a bullet or a rule, just two stars +- [ ] unchecked + + --- indented too far, so not a rule +* * * +stars with tabs between +*** +stars with whitespace after +--- +hyphens with whitespace after +_____ +underscores with whitespace after diff --git a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro index 3b63a67228..7afc807c9b 100644 --- a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro +++ b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro @@ -2,6 +2,7 @@ CONFIG += testcase TARGET = tst_qtextmarkdownimporter QT += core-private gui-private testlib SOURCES += tst_qtextmarkdownimporter.cpp -TESTDATA += data/headingBulletsContinuations.md +TESTDATA += \ + data/thematicBreaks.md \ DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp index 2ede2e73ad..8f51a7a474 100644 --- a/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp +++ b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp @@ -52,6 +52,7 @@ class tst_QTextMarkdownImporter : public QObject private slots: void headingBulletsContinuations(); + void thematicBreaks(); }; void tst_QTextMarkdownImporter::headingBulletsContinuations() @@ -117,5 +118,46 @@ void tst_QTextMarkdownImporter::headingBulletsContinuations() #endif } +void tst_QTextMarkdownImporter::thematicBreaks() +{ + int horizontalRuleCount = 0; + int textLinesCount = 0; + + QFile f(QFINDTESTDATA("data/thematicBreaks.md")); + QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text)); + QString md = QString::fromUtf8(f.readAll()); + f.close(); + + QTextDocument doc; + QTextMarkdownImporter(QTextMarkdownImporter::DialectGitHub).import(&doc, md); + QTextFrame::iterator iterator = doc.rootFrame()->begin(); + QTextFrame *currentFrame = iterator.currentFrame(); + int i = 0; + while (!iterator.atEnd()) { + // There are no child frames + QCOMPARE(iterator.currentFrame(), currentFrame); + // Check whether the block is text or a horizontal rule + QTextBlock block = iterator.currentBlock(); + if (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) + ++horizontalRuleCount; + else if (!block.text().isEmpty()) + ++textLinesCount; + qCDebug(lcTests) << i << (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth) ? QLatin1String("- - -") : block.text()); + ++iterator; + ++i; + } + QCOMPARE(horizontalRuleCount, 5); + QCOMPARE(textLinesCount, 9); + +#ifdef DEBUG_WRITE_HTML + { + QFile out("/tmp/thematicBreaks.html"); + out.open(QFile::WriteOnly); + out.write(doc.toHtml().toLatin1()); + out.close(); + } +#endif +} + QTEST_MAIN(tst_QTextMarkdownImporter) #include "tst_qtextmarkdownimporter.moc" diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp index dca6d90a48..4fbc64e408 100644 --- a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp +++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp @@ -398,6 +398,9 @@ void tst_QTextMarkdownWriter::fromHtml_data() QTest::newRow("nested ordered list items with continuations") << "
    1. item

      continuation paragraph

    2. another item
      continuation line
      1. item

        continuation paragraph

      2. another item
        continuation line
    3. another
    4. another
    " << "1. item\n\n continuation paragraph\n\n2. another item\n continuation line\n\n 1. item\n\n continuation paragraph\n\n 2. another item\n continuation line\n\n3. another\n4. another\n"; + QTest::newRow("thematic break") << + "something
    something else" << + "something\n\n- - -\nsomething else\n\n"; // TODO // QTest::newRow("escaped number and paren after double newline") << // "

    (The first sentence of this paragraph is a line, the next paragraph has a number

    13) but that's not part of an ordered list" << From 82b26444a456d4d5ddf5f483b7766977659bee35 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 7 May 2019 17:49:32 +0200 Subject: [PATCH 088/122] Change QTextMarkdownWriter to pass by const pointer and QAIM - QObjects are always passed by pointer not by reference, by convention - writeTable() takes QAIM rather than QATM to make testing via QStandardItemModel possible in the future Change-Id: I5bc6b8cd9709da4fb5d57d98fa22e0cb34360944 Reviewed-by: Gatis Paeglis --- src/gui/text/qtextdocument.cpp | 2 +- src/gui/text/qtextdocumentwriter.cpp | 2 +- src/gui/text/qtextmarkdownwriter.cpp | 26 +++++++++---------- src/gui/text/qtextmarkdownwriter_p.h | 4 +-- .../tst_qtextmarkdownwriter.cpp | 2 +- .../itemviews/qtableview/tst_qtableview.cpp | 2 +- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 0a59bfb838..b5ff72e706 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -3301,7 +3301,7 @@ QString QTextDocument::toMarkdown(QTextDocument::MarkdownFeatures features) cons QString ret; QTextStream s(&ret); QTextMarkdownWriter w(s, features); - if (w.writeAll(*this)) + if (w.writeAll(this)) return ret; return QString(); } diff --git a/src/gui/text/qtextdocumentwriter.cpp b/src/gui/text/qtextdocumentwriter.cpp index c82ff873cd..193d2c0dd3 100644 --- a/src/gui/text/qtextdocumentwriter.cpp +++ b/src/gui/text/qtextdocumentwriter.cpp @@ -278,7 +278,7 @@ bool QTextDocumentWriter::write(const QTextDocument *document) } QTextStream s(d->device); QTextMarkdownWriter writer(s, QTextDocument::MarkdownDialectGitHub); - return writer.writeAll(*document); + return writer.writeAll(document); } #endif // textmarkdownwriter diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index 0634d324b1..a445ee7e83 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -63,26 +63,26 @@ QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::Mar { } -bool QTextMarkdownWriter::writeAll(const QTextDocument &document) +bool QTextMarkdownWriter::writeAll(const QTextDocument *document) { - writeFrame(document.rootFrame()); + writeFrame(document->rootFrame()); return true; } -void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) +void QTextMarkdownWriter::writeTable(const QAbstractItemModel *table) { - QVector tableColumnWidths(table.columnCount()); - for (int col = 0; col < table.columnCount(); ++col) { - tableColumnWidths[col] = table.headerData(col, Qt::Horizontal).toString().length(); - for (int row = 0; row < table.rowCount(); ++row) { + QVector tableColumnWidths(table->columnCount()); + for (int col = 0; col < table->columnCount(); ++col) { + tableColumnWidths[col] = table->headerData(col, Qt::Horizontal).toString().length(); + for (int row = 0; row < table->rowCount(); ++row) { tableColumnWidths[col] = qMax(tableColumnWidths[col], - table.data(table.index(row, col)).toString().length()); + table->data(table->index(row, col)).toString().length()); } } // write the header and separator - for (int col = 0; col < table.columnCount(); ++col) { - QString s = table.headerData(col, Qt::Horizontal).toString(); + for (int col = 0; col < table->columnCount(); ++col) { + QString s = table->headerData(col, Qt::Horizontal).toString(); m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); } m_stream << "|" << Qt::endl; @@ -91,9 +91,9 @@ void QTextMarkdownWriter::writeTable(const QAbstractTableModel &table) m_stream << '|'<< Qt::endl; // write the body - for (int row = 0; row < table.rowCount(); ++row) { - for (int col = 0; col < table.columnCount(); ++col) { - QString s = table.data(table.index(row, col)).toString(); + for (int row = 0; row < table->rowCount(); ++row) { + for (int col = 0; col < table->columnCount(); ++col) { + QString s = table->data(table->index(row, col)).toString(); m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space); } m_stream << '|'<< Qt::endl; diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h index 250288bcff..4c07bad2e7 100644 --- a/src/gui/text/qtextmarkdownwriter_p.h +++ b/src/gui/text/qtextmarkdownwriter_p.h @@ -64,8 +64,8 @@ class Q_GUI_EXPORT QTextMarkdownWriter { public: QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features); - bool writeAll(const QTextDocument &document); - void writeTable(const QAbstractTableModel &table); + bool writeAll(const QTextDocument *document); + void writeTable(const QAbstractItemModel *table); int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat); void writeFrame(const QTextFrame *frame); diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp index 4fbc64e408..3d77ccd9d8 100644 --- a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp +++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp @@ -435,7 +435,7 @@ QString tst_QTextMarkdownWriter::documentToUnixMarkdown() QString ret; QTextStream ts(&ret, QIODevice::WriteOnly); QTextMarkdownWriter writer(ts, QTextDocument::MarkdownDialectGitHub); - writer.writeAll(*document); + writer.writeAll(document); return ret; } diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp index e7822ef7de..bf87408056 100644 --- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp @@ -4579,7 +4579,7 @@ void tst_QTableView::markdownWriter() { QTextStream stream(&md); QTextMarkdownWriter writer(stream, QTextDocument::MarkdownDialectGitHub); - writer.writeTable(model); + writer.writeTable(&model); } #ifdef DEBUG_WRITE_OUTPUT From 7dd71e812542c561a00dd792d314843a81c5687c Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 26 Apr 2019 08:12:18 +0200 Subject: [PATCH 089/122] Markdown: blockquotes, code blocks, and generalized nesting Can now detect nested quotes and code blocks inside quotes, and can rewrite the markdown too. QTextHtmlParser sets hard-coded left and right margins, so we need to do the same to be able to read HTML and write markdown, or vice-versa, and to ensure that all views (QTextEdit, QTextBrowser, QML Text etc.) will render it with margins. But now we add a semantic memory too: BlockQuoteLevel is similar to HeadingLevel, which was added in 310daae53926628f80c08e4415b94b90ad525c8f to preserve H1..H6 heading levels, because detecting it via font size didn't make sense in QTextMarkdownWriter. Likewise detecting quote level by its margins didn't make sense; markdown supports nesting quotes; and indenting nested quotes via 40 pixels may be a bit too much, so we should consider it subject to change (and perhaps be able to change it via CSS later on). Since we're adding BlockQuoteLevel and depending on it in QTextMarkdownWriter, it's necessary to set it in QTextHtmlParser to enable HTML->markdown conversion. (But so far, nested blockquotes in HTML are not supported.) Quotes (and nested quotes) can contain indented code blocks, but it seems the reverse is not true (according to https://spec.commonmark.org/0.29/#example-201 ) Quotes can contain fenced code blocks. Quotes can contain lists. Nested lists can be interrupted with nested code blocks and nested quotes. So far the writer assumes all code blocks are the indented type. It will be necessary to add another attribute to remember whether the code block is indented or fenced (assuming that's necessary). Fenced code blocks would work better for writing inside block quotes and list items because the fence is less ambiguous than the indent. Postponing cursor->insertBlock() as long as possible helps with nesting. cursor->insertBlock() needs to be done "just in time" before inserting text that will go in the block. The block and char formats aren't necessarily known until that time. When a nested block (such as a nested quote) ends, the context reverts to the previous block format, which then needs to be re-determined and set before we insert text into the outer block; but if no text will be inserted, no new block is necessary. But we can't use QTextBlockFormat itself as storage, because for some reason bullets become very "sticky" and it becomes impossible to have plain continuation paragraphs inside list items: they all get bullets. Somehow QTextBlockFormat remembers, if we copy it. But we can create a new one each time and it's OK. Change-Id: Icd0529eb90d2b6a3cb57f0104bf78a7be81ede52 Reviewed-by: Gatis Paeglis --- src/gui/text/qtextformat.h | 4 +- src/gui/text/qtexthtmlparser.cpp | 1 + src/gui/text/qtextmarkdownimporter.cpp | 103 ++++++++++++++---- src/gui/text/qtextmarkdownimporter_p.h | 8 ++ src/gui/text/qtextmarkdownwriter.cpp | 58 ++++++---- src/gui/text/qtextmarkdownwriter_p.h | 1 + .../qtextmarkdownimporter.pro | 1 + .../qtextmarkdownwriter/data/blockquotes.md | 39 +++++++ .../qtextmarkdownwriter.pro | 4 +- .../tst_qtextmarkdownwriter.cpp | 17 ++- 10 files changed, 191 insertions(+), 45 deletions(-) create mode 100644 tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h index 1eb52a379c..a631309ae0 100644 --- a/src/gui/text/qtextformat.h +++ b/src/gui/text/qtextformat.h @@ -176,7 +176,9 @@ public: BlockNonBreakableLines = 0x1050, BlockTrailingHorizontalRulerWidth = 0x1060, HeadingLevel = 0x1070, - BlockMarker = 0x1080, + BlockQuoteLevel = 0x1080, + BlockCodeLanguage = 0x1090, + BlockMarker = 0x10A0, // character properties FirstFontProperty = 0x1FE0, diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index 895232e4c7..37051502fa 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -1125,6 +1125,7 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent margin[QTextHtmlParser::MarginBottom] = 12; margin[QTextHtmlParser::MarginLeft] = 40; margin[QTextHtmlParser::MarginRight] = 40; + blockFormat.setProperty(QTextFormat::BlockQuoteLevel, 1); break; case Html_dl: margin[QTextHtmlParser::MarginTop] = 8; diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index 5cee01d932..d8ffec2496 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -55,6 +55,9 @@ Q_LOGGING_CATEGORY(lcMD, "qt.text.markdown") static const QChar Newline = QLatin1Char('\n'); static const QChar Space = QLatin1Char(' '); +// TODO maybe eliminate the margins after all views recognize BlockQuoteLevel, CSS can format it, etc. +static const int BlockQuoteIndent = 40; // pixels, same as in QTextHtmlParserNode::initializeProperties + // -------------------------------------------------------- // MD4C callback function wrappers @@ -131,6 +134,7 @@ void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown) nullptr // syntax }; m_doc = doc; + m_paragraphMargin = m_doc->defaultFont().pointSize() * 2 / 3; m_cursor = new QTextCursor(doc); doc->clear(); qCDebug(lcMD) << "default font" << doc->defaultFont() << "mono font" << m_monoFont; @@ -146,11 +150,7 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) switch (blockType) { case MD_BLOCK_P: if (m_listStack.isEmpty()) { - QTextBlockFormat blockFmt; - int margin = m_doc->defaultFont().pointSize() / 2; - blockFmt.setTopMargin(margin); - blockFmt.setBottomMargin(margin); - m_cursor->insertBlock(blockFmt, QTextCharFormat()); + m_needsInsertBlock = true; qCDebug(lcMD, "P"); } else { if (m_emptyListItem) { @@ -159,18 +159,25 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) m_emptyListItem = false; } else { qCDebug(lcMD, "P inside LI at level %d", m_listStack.count()); - QTextBlockFormat blockFmt; - blockFmt.setIndent(m_listStack.count()); - m_cursor->insertBlock(blockFmt, QTextCharFormat()); + m_needsInsertBlock = true; } } break; + case MD_BLOCK_QUOTE: { + ++m_blockQuoteDepth; + qCDebug(lcMD, "QUOTE level %d", m_blockQuoteDepth); + break; + } case MD_BLOCK_CODE: { - QTextBlockFormat blockFmt; - QTextCharFormat charFmt; - charFmt.setFont(m_monoFont); - m_cursor->insertBlock(blockFmt, charFmt); - qCDebug(lcMD, "CODE"); + MD_BLOCK_CODE_DETAIL *detail = static_cast(det); + m_codeBlock = true; + m_blockCodeLanguage = QLatin1String(detail->lang.text, int(detail->lang.size)); + QString info = QLatin1String(detail->info.text, int(detail->info.size)); + m_needsInsertBlock = true; + if (m_blockQuoteDepth) + qCDebug(lcMD, "CODE lang '%s' info '%s' inside QUOTE %d", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockQuoteDepth); + else + qCDebug(lcMD, "CODE lang '%s' info '%s'", qPrintable(m_blockCodeLanguage), qPrintable(info)); } break; case MD_BLOCK_H: { MD_BLOCK_H_DETAIL *detail = static_cast(det); @@ -180,10 +187,12 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det) charFmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment); charFmt.setFontWeight(QFont::Bold); blockFmt.setHeadingLevel(int(detail->level)); + m_needsInsertBlock = false; m_cursor->insertBlock(blockFmt, charFmt); qCDebug(lcMD, "H%d", detail->level); } break; case MD_BLOCK_LI: { + m_needsInsertBlock = false; MD_BLOCK_LI_DETAIL *detail = static_cast(det); QTextList *list = m_listStack.top(); QTextBlockFormat bfmt = list->item(list->count() - 1).blockFormat(); @@ -316,9 +325,9 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail) } } break; case MD_BLOCK_QUOTE: { - QTextBlockFormat blockFmt = m_cursor->blockFormat(); - blockFmt.setIndent(1); - m_cursor->setBlockFormat(blockFmt); + qCDebug(lcMD, "QUOTE level %d ended", m_blockQuoteDepth); + --m_blockQuoteDepth; + m_needsInsertBlock = true; } break; case MD_BLOCK_TABLE: qCDebug(lcMD) << "table ended with" << m_currentTable->columns() << "cols and" << m_currentTable->rows() << "rows"; @@ -329,7 +338,15 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail) qCDebug(lcMD, "LI at level %d ended", m_listStack.count()); m_listItem = false; break; - case MD_BLOCK_CODE: + case MD_BLOCK_CODE: { + m_codeBlock = false; + m_blockCodeLanguage.clear(); + if (m_blockQuoteDepth) + qCDebug(lcMD, "CODE ended inside QUOTE %d", m_blockQuoteDepth); + else + qCDebug(lcMD, "CODE ended"); + m_needsInsertBlock = true; + } break; case MD_BLOCK_H: m_cursor->setCharFormat(QTextCharFormat()); break; @@ -365,6 +382,8 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det) QString title = QString::fromUtf8(detail->title.text, int(detail->title.size)); QTextImageFormat img; img.setName(src); + if (m_needsInsertBlock) + insertBlock(); qCDebug(lcMD) << "image" << src << "title" << title << "relative to" << m_doc->baseUrl(); m_cursor->insertImage(img); break; @@ -377,6 +396,8 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det) break; } m_spanFormatStack.push(charFmt); + qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().family() << charFmt.fontWeight() + << (charFmt.fontItalic() ? "italic" : "") << charFmt.foreground().color().name(); m_cursor->setCharFormat(charFmt); return 0; // no error } @@ -391,6 +412,8 @@ int QTextMarkdownImporter::cbLeaveSpan(int spanType, void *detail) charFmt = m_spanFormatStack.top(); } m_cursor->setCharFormat(charFmt); + qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().family() << charFmt.fontWeight() + << (charFmt.fontItalic() ? "italic" : "") << charFmt.foreground().color().name(); if (spanType == int(MD_SPAN_IMG)) m_imageSpan = false; return 0; // no error @@ -400,6 +423,8 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) { if (m_imageSpan) return 0; // it's the alt-text + if (m_needsInsertBlock) + insertBlock(); static const QRegularExpression openingBracket(QStringLiteral("<[a-zA-Z]")); static const QRegularExpression closingBracket(QStringLiteral("(/>|insertText(s); if (m_cursor->currentList()) { // The list item will indent the list item's text, so we don't need indentation on the block. - QTextBlockFormat blockFmt = m_cursor->blockFormat(); - blockFmt.setIndent(0); - m_cursor->setBlockFormat(blockFmt); + QTextBlockFormat bfmt = m_cursor->blockFormat(); + bfmt.setIndent(0); + m_cursor->setBlockFormat(bfmt); + } + if (lcMD().isEnabled(QtDebugMsg)) { + QTextBlockFormat bfmt = m_cursor->blockFormat(); + QString debugInfo; + if (m_cursor->currentList()) + debugInfo = QLatin1String("in list at depth ") + QString::number(m_cursor->currentList()->format().indent()); + if (bfmt.hasProperty(QTextFormat::BlockQuoteLevel)) + debugInfo += QLatin1String("in blockquote at depth ") + + QString::number(bfmt.intProperty(QTextFormat::BlockQuoteLevel)); + if (bfmt.hasProperty(QTextFormat::BlockCodeLanguage)) + debugInfo += QLatin1String("in a code block"); + qCDebug(lcMD) << textType << "in block" << m_blockType << s << qPrintable(debugInfo) + << "bindent" << bfmt.indent() << "tindent" << bfmt.textIndent() + << "margins" << bfmt.leftMargin() << bfmt.topMargin() << bfmt.bottomMargin() << bfmt.rightMargin(); } qCDebug(lcMD) << textType << "in block" << m_blockType << s << "in list?" << m_cursor->currentList() << "indent" << m_cursor->blockFormat().indent(); return 0; // no error } +void QTextMarkdownImporter::insertBlock() +{ + QTextCharFormat charFormat; + if (!m_spanFormatStack.isEmpty()) + charFormat = m_spanFormatStack.top(); + QTextBlockFormat blockFormat; + if (m_blockQuoteDepth) { + blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth); + blockFormat.setLeftMargin(BlockQuoteIndent * m_blockQuoteDepth); + blockFormat.setRightMargin(BlockQuoteIndent); + } + if (m_listStack.count()) + blockFormat.setIndent(m_listStack.count()); + if (m_codeBlock) { + blockFormat.setProperty(QTextFormat::BlockCodeLanguage, m_blockCodeLanguage); + charFormat.setFont(m_monoFont); + } else { + blockFormat.setTopMargin(m_paragraphMargin); + blockFormat.setBottomMargin(m_paragraphMargin); + } + m_cursor->insertBlock(blockFormat, charFormat); + m_needsInsertBlock = false; +} + QT_END_NAMESPACE diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h index 8ab119d051..1716530b1d 100644 --- a/src/gui/text/qtextmarkdownimporter_p.h +++ b/src/gui/text/qtextmarkdownimporter_p.h @@ -99,26 +99,34 @@ public: int cbLeaveSpan(int spanType, void* detail); int cbText(int textType, const char* text, unsigned size); +private: + void insertBlock(); + private: QTextDocument *m_doc = nullptr; QTextCursor *m_cursor = nullptr; QTextTable *m_currentTable = nullptr; // because m_cursor->currentTable() doesn't work QString m_htmlAccumulator; + QString m_blockCodeLanguage; QVector m_nonEmptyTableCells; // in the current row QStack m_listStack; QStack m_spanFormatStack; QFont m_monoFont; QPalette m_palette; int m_htmlTagDepth = 0; + int m_blockQuoteDepth = 0; int m_tableColumnCount = 0; int m_tableRowCount = 0; int m_tableCol = -1; // because relative cell movements (e.g. m_cursor->movePosition(QTextCursor::NextCell)) don't work + int m_paragraphMargin = 0; Features m_features; int m_blockType = 0; bool m_emptyList = false; // true when the last thing we did was insertList bool m_listItem = false; bool m_emptyListItem = false; + bool m_codeBlock = false; bool m_imageSpan = false; + bool m_needsInsertBlock = false; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QTextMarkdownImporter::Features) diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index a445ee7e83..f180098db2 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -106,7 +106,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) Q_ASSERT(frame); const QTextTable *table = qobject_cast (frame); QTextFrame::iterator iterator = frame->begin(); - QTextFrame *child = 0; + QTextFrame *child = nullptr; int tableRow = -1; bool lastWasList = false; QVector tableColumnWidths; @@ -161,7 +161,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame) m_stream << QString(paddingLen, Space); for (int col = cell.column(); col < spanEndCol; ++col) m_stream << "|"; - } else if (block.textList()) { + } else if (block.textList() || block.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) { m_stream << Newline; } else if (endingCol > 0) { m_stream << Newline << Newline; @@ -252,6 +252,8 @@ static void maybeEscapeFirstChar(QString &s) int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat) { int ColumnLimit = 80; + QTextBlockFormat blockFmt = block.blockFormat(); + bool indentedCodeBlock = false; if (block.textList()) { // it's a list-item auto fmt = block.textList()->format(); const int listLevel = fmt.indent(); @@ -281,7 +283,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign m_wrappedLineIndent = 4; break; } - switch (block.blockFormat().marker()) { + switch (blockFmt.marker()) { case QTextBlockFormat::Checked: bullet += " [x]"; break; @@ -309,21 +311,35 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign prefix += QLatin1String(bullet) + Space; } m_stream << prefix; - } else if (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) { + } else if (blockFmt.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) { m_stream << "- - -\n"; // unambiguous horizontal rule, not an underline under a heading return 0; - } else if (!block.blockFormat().indent()) { + } else if (!blockFmt.indent()) { m_wrappedLineIndent = 0; + m_linePrefix.clear(); + if (blockFmt.hasProperty(QTextFormat::BlockQuoteLevel)) { + int level = blockFmt.intProperty(QTextFormat::BlockQuoteLevel); + QString quoteMarker = QStringLiteral("> "); + m_linePrefix.reserve(level * 2); + for (int i = 0; i < level; ++i) + m_linePrefix += quoteMarker; + } + if (blockFmt.hasProperty(QTextFormat::BlockCodeLanguage)) { + // A block quote can contain an indented code block, but not vice-versa. + m_linePrefix += QString(4, Space); + indentedCodeBlock = true; + } } + if (blockFmt.headingLevel()) + m_stream << QByteArray(blockFmt.headingLevel(), '#') << ' '; + else + m_stream << m_linePrefix; - if (block.blockFormat().headingLevel()) - m_stream << QByteArray(block.blockFormat().headingLevel(), '#') << ' '; - - QString wrapIndentString(m_wrappedLineIndent, Space); + QString wrapIndentString = m_linePrefix + QString(m_wrappedLineIndent, Space); // It would be convenient if QTextStream had a lineCharPos() accessor, // to keep track of how many characters (not bytes) have been written on the current line, // but it doesn't. So we have to keep track with this col variable. - int col = m_wrappedLineIndent; + int col = wrapIndentString.length(); bool mono = false; bool startsOrEndsWithBacktick = false; bool bold = false; @@ -338,7 +354,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign if (block.textList()) { //
  • first line
    continuation
  • QString newlineIndent = QString(Newline) + QString(m_wrappedLineIndent, Space); fragmentText.replace(QString(LineBreak), newlineIndent); - } else if (block.blockFormat().indent() > 0) { //
  • first line

    continuation

  • + } else if (blockFmt.indent() > 0) { //
  • first line

    continuation

  • m_stream << QString(m_wrappedLineIndent, Space); } else { fragmentText.replace(LineBreak, Newline); @@ -368,7 +384,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign bool monoFrag = fontInfo.fixedPitch(); QString markers; if (!ignoreFormat) { - if (monoFrag != mono) { + if (monoFrag != mono && !indentedCodeBlock) { if (monoFrag) backticks = QString(adjacentBackticksCount(fragmentText) + 1, Backtick); markers += backticks; @@ -376,25 +392,25 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign markers += Space; mono = monoFrag; } - if (!block.blockFormat().headingLevel() && !mono) { - if (fmt.font().bold() != bold) { + if (!blockFmt.headingLevel() && !mono) { + if (fontInfo.bold() != bold) { markers += QLatin1String("**"); - bold = fmt.font().bold(); + bold = fontInfo.bold(); } - if (fmt.font().italic() != italic) { + if (fontInfo.italic() != italic) { markers += QLatin1Char('*'); - italic = fmt.font().italic(); + italic = fontInfo.italic(); } - if (fmt.font().strikeOut() != strikeOut) { + if (fontInfo.strikeOut() != strikeOut) { markers += QLatin1String("~~"); - strikeOut = fmt.font().strikeOut(); + strikeOut = fontInfo.strikeOut(); } - if (fmt.font().underline() != underline) { + if (fontInfo.underline() != underline) { // Markdown doesn't support underline, but the parser will treat a single underline // the same as a single asterisk, and the marked fragment will be rendered in italics. // That will have to do. markers += QLatin1Char('_'); - underline = fmt.font().underline(); + underline = fontInfo.underline(); } } } diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h index 4c07bad2e7..96ceb445cd 100644 --- a/src/gui/text/qtextmarkdownwriter_p.h +++ b/src/gui/text/qtextmarkdownwriter_p.h @@ -81,6 +81,7 @@ private: QTextStream &m_stream; QTextDocument::MarkdownFeatures m_features; QMap m_listInfo; + QString m_linePrefix; int m_wrappedLineIndent = 0; int m_lastListIndent = 1; bool m_doubleNewlineWritten = false; diff --git a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro index 7afc807c9b..7b7fb61244 100644 --- a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro +++ b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro @@ -4,5 +4,6 @@ QT += core-private gui-private testlib SOURCES += tst_qtextmarkdownimporter.cpp TESTDATA += \ data/thematicBreaks.md \ + data/headingBulletsContinuations.md \ DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md new file mode 100644 index 0000000000..f429fcc21b --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md @@ -0,0 +1,39 @@ +In 1958, Mahatma Gandhi was quoted as follows: + +> The Earth provides enough to satisfy every man's need but not for every man's +> greed. + +In [The CommonMark Specification](https://spec.commonmark.org/0.29/) John +MacFarlane writes: + +> What distinguishes Markdown from many other lightweight markup syntaxes, +> which are often easier to write, is its readability. As Gruber writes: + +> > The overriding design goal for Markdown's formatting syntax is to make it +> > as readable as possible. The idea is that a Markdown-formatted document should +> > be publishable as-is, as plain text, without looking like it's been marked up +> > with tags or formatting instructions. ( +> > [http://daringfireball.net/projects/markdown/](http://daringfireball.net/projects/markdown/)) + +> The point can be illustrated by comparing a sample of AsciiDoc with an +> equivalent sample of Markdown. Here is a sample of AsciiDoc from the AsciiDoc +> manual: + +> 1. List item one. +> + +> List item one continued with a second paragraph followed by an +> Indented block. +> + +> ................. +> $ ls *.sh +> $ mv *.sh ~/tmp +> ................. +> + +> List item continued with a third paragraph. +> +> 2. List item two continued with an open block. +> ... +> +The quotation includes an embedded quotation and a code quotation and ends with +an ellipsis due to being incomplete. + diff --git a/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro index 04cf7ef5dd..6144710b99 100644 --- a/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro +++ b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro @@ -2,6 +2,8 @@ CONFIG += testcase TARGET = tst_qtextmarkdownwriter QT += core-private gui-private testlib SOURCES += tst_qtextmarkdownwriter.cpp -TESTDATA += data/example.md +TESTDATA += \ + data/example.md \ + data/blockquotes.md \ DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp index 3d77ccd9d8..9998794762 100644 --- a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp +++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp @@ -54,6 +54,7 @@ private slots: void testWriteNestedBulletLists(); void testWriteNestedNumericLists(); void testWriteTable(); + void rewriteDocument_data(); void rewriteDocument(); void fromHtml_data(); void fromHtml(); @@ -350,10 +351,19 @@ void tst_QTextMarkdownWriter::testWriteTable() QCOMPARE(md, QString::fromLatin1("\n|a ||b|\n|-|-|-|\n|c|d ||\n|e|f| |\n\n")); } +void tst_QTextMarkdownWriter::rewriteDocument_data() +{ + QTest::addColumn("inputFile"); + + QTest::newRow("block quotes") << "blockquotes.md"; + QTest::newRow("example") << "example.md"; +} + void tst_QTextMarkdownWriter::rewriteDocument() { + QFETCH(QString, inputFile); QTextDocument doc; - QFile f(QFINDTESTDATA("data/example.md")); + QFile f(QFINDTESTDATA("data/" + inputFile)); QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text)); QString orig = QString::fromUtf8(f.readAll()); f.close(); @@ -361,7 +371,7 @@ void tst_QTextMarkdownWriter::rewriteDocument() QString md = doc.toMarkdown(); #ifdef DEBUG_WRITE_OUTPUT - QFile out("/tmp/rewrite.md"); + QFile out("/tmp/rewrite-" + inputFile); out.open(QFile::WriteOnly); out.write(md.toUtf8()); out.close(); @@ -401,6 +411,9 @@ void tst_QTextMarkdownWriter::fromHtml_data() QTest::newRow("thematic break") << "something
    something else" << "something\n\n- - -\nsomething else\n\n"; + QTest::newRow("block quote") << + "

    In 1958, Mahatma Gandhi was quoted as follows:

    The Earth provides enough to satisfy every man's need but not for every man's greed.
    " << + "In 1958, Mahatma Gandhi was quoted as follows:\n\n> The Earth provides enough to satisfy every man's need but not for every man's\n> greed.\n\n"; // TODO // QTest::newRow("escaped number and paren after double newline") << // "

    (The first sentence of this paragraph is a line, the next paragraph has a number

    13) but that's not part of an ordered list" << From 5652d33f973a03b93c9b5ce9e49db8cf0430b675 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 30 Apr 2019 11:54:31 +0200 Subject: [PATCH 090/122] Bump version to Qt 6 Needed to disable QT_NO_UNSHARABLE_CONTAINERS, as this triggers asserts. QMetaType also has some Qt 6 specific code disabled to get things to compile. Fix various details in autotests to accommodate for the changes with Qt 6. Add a workaround for black lists on macos, where QSysInfo::productType() now returns 'macos' and not 'osx' anymore. Change-Id: Ie26afb12a2aac36521472715934a7e34639ea4d0 Reviewed-by: Simon Hausmann --- .qmake.conf | 2 +- src/corelib/global/qglobal.h | 3 +- src/corelib/global/qlogging.cpp | 2 +- src/corelib/io/qfileselector.cpp | 7 -- src/corelib/io/qfilesystemwatcher_win.cpp | 2 +- src/corelib/itemmodels/qabstractitemmodel.cpp | 4 + src/corelib/itemmodels/qabstractproxymodel.h | 6 +- src/corelib/kernel/qcoreapplication.cpp | 6 +- src/corelib/kernel/qmetatype.h | 2 +- src/corelib/mimetypes/qmimedatabase_p.h | 1 + src/corelib/plugin/qlibrary.cpp | 4 +- src/gui/image/qimage_p.h | 2 +- src/gui/itemmodels/qstandarditemmodel.h | 7 +- src/network/ssl/qsslsocket_winrt.cpp | 6 +- .../platforms/cocoa/qcocoaintegration.mm | 2 +- src/testlib/qtestblacklist.cpp | 10 ++ .../corelib/io/qfileinfo/tst_qfileinfo.cpp | 2 +- .../io/qfileselector/platforms/+mac/test5 | 0 .../io/qfileselector/platforms/+osx/test4 | 0 .../{+mac => +unix/+darwin/+ios}/test | 0 .../platforms/+unix/+darwin/+mac/+ios/test | 0 .../platforms/+unix/+darwin/+mac/+macos/test | 0 .../+unix/+darwin/+mac/+osx/+macos/test | 0 .../platforms/+unix/+darwin/+mac/+osx/test | 0 .../platforms/+unix/+darwin/+mac/test | 0 .../{+osx => +unix/+darwin/+macos}/test | 0 .../io/qfileselector/qfileselector.qrc | 114 ++++++++---------- .../io/qfileselector/tst_qfileselector.cpp | 8 -- .../corelib/tools/qvector/outofline.cpp | 2 +- .../qfile_vs_qnetworkaccessmanager/main.cpp | 6 +- 30 files changed, 96 insertions(+), 102 deletions(-) delete mode 100644 tests/auto/corelib/io/qfileselector/platforms/+mac/test5 delete mode 100644 tests/auto/corelib/io/qfileselector/platforms/+osx/test4 rename tests/auto/corelib/io/qfileselector/platforms/{+mac => +unix/+darwin/+ios}/test (100%) delete mode 100644 tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+ios/test delete mode 100644 tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+macos/test delete mode 100644 tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+osx/+macos/test delete mode 100644 tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+osx/test delete mode 100644 tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/test rename tests/auto/corelib/io/qfileselector/platforms/{+osx => +unix/+darwin/+macos}/test (100%) diff --git a/.qmake.conf b/.qmake.conf index 08e1a4723c..1d049940d8 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ CONFIG += warning_clean QT_SOURCE_TREE = $$PWD QT_BUILD_TREE = $$shadowed($$PWD) -MODULE_VERSION = 5.14.0 +MODULE_VERSION = 6.0.0 diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 0a0c434a07..499558d7e6 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -87,7 +87,8 @@ #define QT_REQUIRE_CONFIG(feature) Q_STATIC_ASSERT_X(QT_FEATURE_##feature == 1, "Required feature " #feature " for file " __FILE__ " not available.") #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) -# define QT_NO_UNSHARABLE_CONTAINERS +// ### Qt6: FIXME and get rid of unsharable containers +//# define QT_NO_UNSHARABLE_CONTAINERS # define QT6_VIRTUAL virtual # define QT6_NOT_VIRTUAL #else diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 4941ca45aa..23cb5ba61e 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -1318,7 +1318,7 @@ static QStringList backtraceFramesForLogMessage(int frameCount) QString function = m.captured(2); // skip the trace from QtCore that are because of the qDebug itself - if (!numberPrinted && library.contains(QLatin1String("Qt5Core")) + if (!numberPrinted && library.contains(QLatin1String("Qt6Core")) && (function.isEmpty() || function.contains(QLatin1String("Message"), Qt::CaseInsensitive) || function.contains(QLatin1String("QDebug")))) { continue; diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index ce06c8e00b..7f65b0f8f7 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -331,7 +331,6 @@ void QFileSelectorPrivate::updateSelectors() QStringList QFileSelectorPrivate::platformSelectors() { // similar, but not identical to QSysInfo::osType - // ### Qt6: remove macOS fallbacks to "mac" and the future compatibility QStringList ret; #if defined(Q_OS_WIN) ret << QStringLiteral("windows"); @@ -344,16 +343,10 @@ QStringList QFileSelectorPrivate::platformSelectors() # if !defined(Q_OS_ANDROID) && !defined(Q_OS_QNX) // we don't want "linux" for Android or two instances of "qnx" for QNX ret << QSysInfo::kernelType(); -# ifdef Q_OS_MAC - ret << QStringLiteral("mac"); // compatibility, since kernelType() is "darwin" -# endif # endif QString productName = QSysInfo::productType(); if (productName != QLatin1String("unknown")) ret << productName; // "opensuse", "fedora", "osx", "ios", "android" -# if defined(Q_OS_MACOS) - ret << QStringLiteral("macos"); // future compatibility -# endif #endif return ret; } diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index eb626fd541..e1949e9697 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -79,7 +79,7 @@ static Qt::HANDLE createChangeNotification(const QString &path, uint flags) nativePath.append(QLatin1Char('\\')); const HANDLE result = FindFirstChangeNotification(reinterpret_cast(nativePath.utf16()), FALSE, flags); - DEBUG() << __FUNCTION__ << nativePath << Qt::hex <invalidatePersistentIndexes(); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + resetInternalData(); +#else QMetaObject::invokeMethod(this, "resetInternalData"); +#endif emit modelReset(QPrivateSignal()); } diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h index c9a73b6a31..f6f6e45c1a 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.h +++ b/src/corelib/itemmodels/qabstractproxymodel.h @@ -103,7 +103,11 @@ Q_SIGNALS: void sourceModelChanged(QPrivateSignal); protected Q_SLOTS: - void resetInternalData(); + void resetInternalData() +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + override +#endif + ; protected: QAbstractProxyModel(QAbstractProxyModelPrivate &, QObject *parent); diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 7a6faf2e2b..fc8b9227d4 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -152,10 +152,10 @@ private: extern QString qAppFileName(); #endif -#if QT_VERSION >= 0x060000 -# error "Bump QCoreApplicatoinPrivate::app_compile_version to 0x060000" +#if QT_VERSION >= 0x070000 +# error "Bump QCoreApplicatoinPrivate::app_compile_version to 0x070000" #endif -int QCoreApplicationPrivate::app_compile_version = 0x050000; //we don't know exactly, but it's at least 5.0.0 +int QCoreApplicationPrivate::app_compile_version = 0x060000; //we don't know exactly, but it's at least 6.0.0 bool QCoreApplicationPrivate::setuidAllowed = false; diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 79ee5eec11..7f512b6cb1 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -493,7 +493,7 @@ public: typedef void (*Deleter)(void *); typedef void *(*Creator)(const void *); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#if 1 || QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt6: fix this typedef void (*Destructor)(void *); typedef void *(*Constructor)(void *, const void *); // TODO Qt6: remove me #endif diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h index d9cf446d44..831390de1f 100644 --- a/src/corelib/mimetypes/qmimedatabase_p.h +++ b/src/corelib/mimetypes/qmimedatabase_p.h @@ -63,6 +63,7 @@ QT_REQUIRE_CONFIG(mimetype); #include #include +#include #include QT_BEGIN_NAMESPACE diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 0e32776c71..c059851fce 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -692,7 +692,7 @@ static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg) }; #else auto getMetaData = [](QFunctionPointer fptr) { - auto f = reinterpret_cast (*)()>(fptr); + auto f = reinterpret_cast(fptr); return f(); }; #endif @@ -702,7 +702,7 @@ static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg) return false; auto metaData = getMetaData(pfn); - QJsonDocument doc = qJsonFromRawLibraryMetaData(metaData.first, metaData.second, errMsg); + QJsonDocument doc = qJsonFromRawLibraryMetaData(reinterpret_cast(metaData.data), metaData.size, errMsg); if (doc.isNull()) return false; priv->metaData = doc.object(); diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index 9da6acd0a7..1cd0e8e0aa 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -140,7 +140,7 @@ QImageData::calculateImageParameters(qsizetype width, qsizetype height, qsizetyp qsizetype dummy; if (mul_overflow(height, qsizetype(sizeof(uchar *)), &dummy)) return invalid; // why is this here? -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) +#if 1 || QT_VERSION < QT_VERSION_CHECK(6,0,0) // ### can only fix this if QImage dimensions are not int anymore // Disallow images where width * depth calculations might overflow if (width > (INT_MAX - 31) / depth) return invalid; diff --git a/src/gui/itemmodels/qstandarditemmodel.h b/src/gui/itemmodels/qstandarditemmodel.h index a9ee25da75..435b66591c 100644 --- a/src/gui/itemmodels/qstandarditemmodel.h +++ b/src/gui/itemmodels/qstandarditemmodel.h @@ -344,8 +344,11 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - // Qt 6: add override keyword - bool clearItemData(const QModelIndex &index); + bool clearItemData(const QModelIndex &index) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + override +#endif + ; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp index d54ac2ad73..0bbe6fe57d 100644 --- a/src/network/ssl/qsslsocket_winrt.cpp +++ b/src/network/ssl/qsslsocket_winrt.cpp @@ -274,7 +274,7 @@ void QSslSocketBackendPrivate::startClientEncryption() } // Sync custom certificates - const QSet caCertificates = configuration.caCertificates.toSet(); + const QSet caCertificates(configuration.caCertificates.constBegin(), configuration.caCertificates.constEnd()); const QSet newCertificates = caCertificates - previousCaCertificates; const QSet oldCertificates = previousCaCertificates - caCertificates; g->syncCaCertificates(newCertificates, oldCertificates); @@ -397,7 +397,7 @@ void QSslSocketBackendPrivate::continueHandshake() hr = control2->get_IgnorableServerCertificateErrors(&ignoreList); Q_ASSERT_SUCCEEDED(hr); - QSet ignoreErrors = ignoreErrorsList.toSet(); + QSet ignoreErrors(ignoreErrorsList.constBegin(), ignoreErrorsList.constEnd()); for (int i = ChainValidationResult_Untrusted; i < ChainValidationResult_OtherErrors + 1; ++i) { // Populate the native ignore list - break to add, continue to skip switch (i) { @@ -600,7 +600,7 @@ HRESULT QSslSocketBackendPrivate::onSslUpgrade(IAsyncAction *action, AsyncStatus } } - sslErrors = errors.toList(); + sslErrors = QList(errors.constBegin(), errors.constEnd()); // Peer validation if (!configuration.peerCertificate.isNull()) { diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index fb3d05d3e4..eb18e573ea 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -272,7 +272,7 @@ void QCocoaIntegration::updateScreens() [screens addObject:[NSScreen mainScreen]]; if ([screens count] == 0) return; - QSet remainingScreens = QSet::fromList(mScreens); + QSet remainingScreens = QSet(mScreens.constBegin(), mScreens.constEnd()); QList siblings; uint screenCount = [screens count]; for (uint i = 0; i < screenCount; i++) { diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index 886f1f75b9..72bb5688ef 100644 --- a/src/testlib/qtestblacklist.cpp +++ b/src/testlib/qtestblacklist.cpp @@ -186,10 +186,20 @@ static QSet activeConditions() if (!distributionName.isEmpty()) { if (result.find(distributionName) == result.end()) result.insert(distributionName); + // backwards compatibility with Qt 5 + if (distributionName == "macos") { + if (result.find(distributionName) == result.end()) + result.insert("osx"); + } if (!distributionRelease.isEmpty()) { QByteArray versioned = distributionName + "-" + distributionRelease; if (result.find(versioned) == result.end()) result.insert(versioned); + if (distributionName == "macos") { + QByteArray versioned = "osx-" + distributionRelease; + if (result.find(versioned) == result.end()) + result.insert(versioned); + } } } diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp index 64075a94f0..98830bbc9b 100644 --- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -115,7 +115,7 @@ static DWORD createSymbolicLink(const QString &symLinkName, const QString &targe reinterpret_cast(nativeTarget.utf16()), flags) == FALSE) { result = GetLastError(); QTextStream(errorMessage) << "CreateSymbolicLink(" << nativeSymLinkName << ", " - << nativeTarget << ", 0x" << hex << flags << dec << ") failed with error " << result + << nativeTarget << ", 0x" << Qt::hex << flags << Qt::dec << ") failed with error " << result << ": " << qt_error_string(int(result)); } return result; diff --git a/tests/auto/corelib/io/qfileselector/platforms/+mac/test5 b/tests/auto/corelib/io/qfileselector/platforms/+mac/test5 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+osx/test4 b/tests/auto/corelib/io/qfileselector/platforms/+osx/test4 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+mac/test b/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+ios/test similarity index 100% rename from tests/auto/corelib/io/qfileselector/platforms/+mac/test rename to tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+ios/test diff --git a/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+ios/test b/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+ios/test deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+macos/test b/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+macos/test deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+osx/+macos/test b/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+osx/+macos/test deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+osx/test b/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+osx/test deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/test b/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/test deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+osx/test b/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+macos/test similarity index 100% rename from tests/auto/corelib/io/qfileselector/platforms/+osx/test rename to tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+macos/test diff --git a/tests/auto/corelib/io/qfileselector/qfileselector.qrc b/tests/auto/corelib/io/qfileselector/qfileselector.qrc index 54b2e0a0e2..f3b3ede575 100644 --- a/tests/auto/corelib/io/qfileselector/qfileselector.qrc +++ b/tests/auto/corelib/io/qfileselector/qfileselector.qrc @@ -1,65 +1,51 @@ - - - extras/test - extras/test2 - extras/+custom1/test - extras/+custom1/test3 - extras/+custom2/test - extras/+custom3/test - extras/+custom3/+custom2/test - extras/+custom3/+custom4/test - extras/+custom3/+custom5/test - extras/+custom5/+custom3/test - - - platforms/test - platforms/+unix/+android/test - platforms/+unix/+darwin/+mac/+ios/test - platforms/+unix/+darwin/+mac/+osx/+macos/test - platforms/+unix/+darwin/+mac/+osx/test - platforms/+unix/+darwin/+mac/test - platforms/+unix/+darwin/test - platforms/+unix/+haiku/test - platforms/+unix/+linux/test - platforms/+unix/+qnx/test - platforms/+unix/test - platforms/+windows/+wince/test - platforms/+windows/+winnt/test - platforms/+windows/+winrt/test - platforms/+windows/test - platforms/+android/test - platforms/+ios/test - platforms/+macos/test - platforms/+osx/test - platforms/+darwin/test - platforms/+mac/test - platforms/+haiku/test - platforms/+linux/test - platforms/+qnx/test - platforms/+wince/test - platforms/+winrt/test - - - platforms/test2 - platforms/+android/test2 - platforms/+ios/test2 - platforms/+macos/test2 - platforms/+haiku/test2 - platforms/+linux/test2 - platforms/+qnx/test2 - platforms/+wince/test2 - platforms/+winnt/test2 - platforms/+winrt/test2 - - - platforms/test3 - platforms/+windows/test3 - platforms/+unix/test3 - - - platforms/test4 - platforms/+osx/test4 - platforms/test5 - platforms/+mac/test5 - + + + extras/test + extras/test2 + extras/+custom1/test + extras/+custom1/test3 + extras/+custom2/test + extras/+custom3/test + extras/+custom3/+custom2/test + extras/+custom3/+custom4/test + extras/+custom3/+custom5/test + extras/+custom5/+custom3/test + platforms/test + platforms/+unix/+android/test + platforms/+unix/+darwin/test + platforms/+unix/+haiku/test + platforms/+unix/+linux/test + platforms/+unix/+qnx/test + platforms/+unix/test + platforms/+windows/+wince/test + platforms/+windows/+winnt/test + platforms/+windows/+winrt/test + platforms/+windows/test + platforms/+android/test + platforms/+ios/test + platforms/+macos/test + platforms/+darwin/test + platforms/+haiku/test + platforms/+linux/test + platforms/+qnx/test + platforms/+wince/test + platforms/+winrt/test + platforms/test2 + platforms/+android/test2 + platforms/+ios/test2 + platforms/+macos/test2 + platforms/+haiku/test2 + platforms/+linux/test2 + platforms/+qnx/test2 + platforms/+wince/test2 + platforms/+winnt/test2 + platforms/+winrt/test2 + platforms/test3 + platforms/+windows/test3 + platforms/+unix/test3 + platforms/test4 + platforms/test5 + platforms/+unix/+darwin/+macos/test + platforms/+unix/+darwin/+ios/test + diff --git a/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp b/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp index c9f1e3d9f6..b98a98df9c 100644 --- a/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp +++ b/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp @@ -126,14 +126,6 @@ void tst_QFileSelector::basicTest_data() QTest::newRow("platform3") << QString(":/platforms/test3") << QStringList() << expectedPlatform3File; -#ifdef Q_OS_MACOS - // special case for compatibility code - QTest::newRow("osx-compat") << QString(":/platforms/test4") << QStringList() - << ":/platforms/+osx/test4"; - QTest::newRow("mac-compat") << QString(":/platforms/test5") << QStringList() - << ":/platforms/+mac/test5"; -#endif - QString resourceTestPath(":/extras/test"); QString custom1("custom1"); QTest::newRow("custom1-noselector") << resourceTestPath << QStringList() diff --git a/tests/benchmarks/corelib/tools/qvector/outofline.cpp b/tests/benchmarks/corelib/tools/qvector/outofline.cpp index 76a4edaa10..7182a43008 100644 --- a/tests/benchmarks/corelib/tools/qvector/outofline.cpp +++ b/tests/benchmarks/corelib/tools/qvector/outofline.cpp @@ -54,7 +54,7 @@ QVector mixedvector_fill_and_return_helper() std::vector v(N); for (int i = 0; i != N; ++i) v[i] = i; - return QVector::fromStdVector(v); + return QVector(v.begin(), v.end()); } diff --git a/tests/benchmarks/network/access/qfile_vs_qnetworkaccessmanager/main.cpp b/tests/benchmarks/network/access/qfile_vs_qnetworkaccessmanager/main.cpp index 46bb1791b4..1f3f38eaaf 100644 --- a/tests/benchmarks/network/access/qfile_vs_qnetworkaccessmanager/main.cpp +++ b/tests/benchmarks/network/access/qfile_vs_qnetworkaccessmanager/main.cpp @@ -105,7 +105,7 @@ void qfile_vs_qnetworkaccessmanager::qnamFileRead() } qint64 elapsed = t.elapsed(); - qDebug() << endl << "Finished!"; + qDebug() << Qt::endl << "Finished!"; qDebug() << "Bytes:" << size; qDebug() << "Speed:" << (qreal(size*iterations) / 1024.0) / (qreal(elapsed) / 1000.0) << "KB/sec"; } @@ -138,7 +138,7 @@ void qfile_vs_qnetworkaccessmanager::qnamImmediateFileRead() } qint64 elapsed = t.elapsed(); - qDebug() << endl << "Finished!"; + qDebug() << Qt::endl << "Finished!"; qDebug() << "Bytes:" << size; qDebug() << "Speed:" << (qreal(size*iterations) / 1024.0) / (qreal(elapsed) / 1000.0) << "KB/sec"; } @@ -167,7 +167,7 @@ void qfile_vs_qnetworkaccessmanager::qfileFileRead() } qint64 elapsed = t.elapsed(); - qDebug() << endl << "Finished!"; + qDebug() << Qt::endl << "Finished!"; qDebug() << "Bytes:" << size; qDebug() << "Speed:" << (qreal(size*iterations) / 1024.0) / (qreal(elapsed) / 1000.0) << "KB/sec"; } From 1dde5a7b9523ab7f62a6965edfd7b87ed40eecb8 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 13 Mar 2019 09:46:20 +0100 Subject: [PATCH 091/122] Remove deprecated QEasingCurve::cubicBezierSpline() function It has been deprecated since Qt 5.0 so hopefully nobody is using it anymore. Change-Id: If3466f8a2d25ea87cd51ca71606d2a27a428efcf Reviewed-by: Christian Ehrlicher --- src/corelib/tools/qeasingcurve.cpp | 5 ----- src/corelib/tools/qeasingcurve.h | 7 ------- 2 files changed, 12 deletions(-) diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 9169b5c7f1..c807bbd2e1 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -1365,11 +1365,6 @@ void QEasingCurve::addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qre } -/*! - \fn QList QEasingCurve::cubicBezierSpline() const - \obsolete Use toCubicSpline() instead. - */ - /*! \since 5.0 diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h index 725ddd5dcc..f7a1d6bdc0 100644 --- a/src/corelib/tools/qeasingcurve.h +++ b/src/corelib/tools/qeasingcurve.h @@ -43,10 +43,6 @@ #include #include #include -#if QT_DEPRECATED_SINCE(5, 0) -# include -# include -#endif QT_BEGIN_NAMESPACE @@ -102,9 +98,6 @@ public: void addCubicBezierSegment(const QPointF & c1, const QPointF & c2, const QPointF & endPoint); void addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qreal b); QVector toCubicSpline() const; -#if QT_DEPRECATED_SINCE(5, 0) - QT_DEPRECATED QList cubicBezierSpline() const { return toCubicSpline().toList(); } -#endif Type type() const; void setType(Type type); From 237fa21feef63884043bd6cf32682b2b08c78454 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 20 May 2019 12:58:36 +0200 Subject: [PATCH 092/122] Markdown and HTML: support image alt text and title It's a required CommonMark feature: https://spec.commonmark.org/0.29/#images and alt text is also required in HTML: https://www.w3.org/wiki/Html/Elements/img#Requirements_for_providing_text_to_act_as_an_alternative_for_images Now we are able to read these attributes from either html or markdown and rewrite either an html or markdown document that preserves them. This patch does not add viewing or editing support in QTextEdit etc. Change-Id: I51307389f8f9fc00809808390e583a83111a7b33 Reviewed-by: Gatis Paeglis --- src/gui/text/qtextdocument.cpp | 6 +++++ src/gui/text/qtextdocumentfragment.cpp | 4 ++++ src/gui/text/qtextformat.cpp | 8 ++++++- src/gui/text/qtextformat.h | 2 ++ src/gui/text/qtexthtmlparser.cpp | 4 ++++ src/gui/text/qtexthtmlparser_p.h | 1 + src/gui/text/qtextmarkdownimporter.cpp | 24 +++++++++++-------- src/gui/text/qtextmarkdownimporter_p.h | 1 + src/gui/text/qtextmarkdownwriter.cpp | 10 +++++++- .../tst_qtextmarkdownwriter.cpp | 3 +++ 10 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index c800cea3f6..899801ca39 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -2709,6 +2709,12 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment) if (imgFmt.hasProperty(QTextFormat::ImageName)) emitAttribute("src", imgFmt.name()); + if (imgFmt.hasProperty(QTextFormat::ImageAltText)) + emitAttribute("alt", imgFmt.stringProperty(QTextFormat::ImageAltText)); + + if (imgFmt.hasProperty(QTextFormat::ImageTitle)) + emitAttribute("title", imgFmt.stringProperty(QTextFormat::ImageTitle)); + if (imgFmt.hasProperty(QTextFormat::ImageWidth)) emitAttribute("width", QString::number(imgFmt.width())); diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp index aef4ea1522..1905d9a1b1 100644 --- a/src/gui/text/qtextdocumentfragment.cpp +++ b/src/gui/text/qtextdocumentfragment.cpp @@ -715,6 +715,10 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processSpecialNodes() case Html_img: { QTextImageFormat fmt; fmt.setName(currentNode->imageName); + if (!currentNode->text.isEmpty()) + fmt.setProperty(QTextFormat::ImageTitle, currentNode->text); + if (!currentNode->imageAlt.isEmpty()) + fmt.setProperty(QTextFormat::ImageAltText, currentNode->imageAlt); fmt.merge(currentNode->charFormat); diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index 895b9034e0..644dd5558d 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -659,7 +659,13 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt) Image properties - \value ImageName + \value ImageName The filename or source of the image. + \value ImageTitle The title attribute of an HTML image tag, or + the quoted string that comes after the URL in a Markdown image link. + This enum value has been added in Qt 5.14. + \value ImageAltText The alt attribute of an HTML image tag, or + the image description in a Markdown image link. + This enum value has been added in Qt 5.14. \value ImageWidth \value ImageHeight \value ImageQuality diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h index a631309ae0..4f534fb65d 100644 --- a/src/gui/text/qtextformat.h +++ b/src/gui/text/qtextformat.h @@ -253,6 +253,8 @@ public: // image properties ImageName = 0x5000, + ImageTitle = 0x5001, + ImageAltText = 0x5002, ImageWidth = 0x5010, ImageHeight = 0x5011, ImageQuality = 0x5014, diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index 37051502fa..49ee6394ee 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -1556,6 +1556,10 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes) } else if (key == QLatin1String("height")) { node->imageHeight = -2; // register that there is a value for it. setFloatAttribute(&node->imageHeight, value); + } else if (key == QLatin1String("alt")) { + node->imageAlt = value; + } else if (key == QLatin1String("title")) { + node->text = value; } break; case Html_tr: diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h index 73dac38b82..6ce294d211 100644 --- a/src/gui/text/qtexthtmlparser_p.h +++ b/src/gui/text/qtexthtmlparser_p.h @@ -184,6 +184,7 @@ struct QTextHtmlParserNode { QString textListNumberPrefix; QString textListNumberSuffix; QString imageName; + QString imageAlt; qreal imageWidth; qreal imageHeight; QTextLength width; diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index b96acba0e6..223eb01e55 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -362,15 +362,10 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det) } break; case MD_SPAN_IMG: { m_imageSpan = true; + m_imageFormat = QTextImageFormat(); MD_SPAN_IMG_DETAIL *detail = static_cast(det); - QString src = QString::fromUtf8(detail->src.text, int(detail->src.size)); - QString title = QString::fromUtf8(detail->title.text, int(detail->title.size)); - QTextImageFormat img; - img.setName(src); - if (m_needsInsertBlock) - insertBlock(); - qCDebug(lcMD) << "image" << src << "title" << title << "relative to" << m_doc->baseUrl(); - m_cursor->insertImage(img); + m_imageFormat.setName(QString::fromUtf8(detail->src.text, int(detail->src.size))); + m_imageFormat.setProperty(QTextFormat::ImageTitle, QString::fromUtf8(detail->title.text, int(detail->title.size))); break; } case MD_SPAN_CODE: @@ -406,8 +401,6 @@ int QTextMarkdownImporter::cbLeaveSpan(int spanType, void *detail) int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) { - if (m_imageSpan) - return 0; // it's the alt-text if (m_needsInsertBlock) insertBlock(); #if QT_CONFIG(regularexpression) @@ -481,6 +474,17 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size) break; } + if (m_imageSpan) { + // TODO we don't yet support alt text with formatting, because of the cases where m_cursor + // already inserted the text above. Rather need to accumulate it in case we need it here. + m_imageFormat.setProperty(QTextFormat::ImageAltText, s); + qCDebug(lcMD) << "image" << m_imageFormat.name() + << "title" << m_imageFormat.stringProperty(QTextFormat::ImageTitle) + << "alt" << s << "relative to" << m_doc->baseUrl(); + m_cursor->insertImage(m_imageFormat); + return 0; // no error + } + if (!s.isEmpty()) m_cursor->insertText(s); if (m_cursor->currentList()) { diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h index f905aa0f87..fdce74483b 100644 --- a/src/gui/text/qtextmarkdownimporter_p.h +++ b/src/gui/text/qtextmarkdownimporter_p.h @@ -125,6 +125,7 @@ private: int m_paragraphMargin = 0; int m_blockType = 0; Features m_features; + QTextImageFormat m_imageFormat; QTextListFormat m_listFormat; QTextBlockFormat::MarkerType m_markerType = QTextBlockFormat::NoMarker; bool m_needsInsertBlock = false; diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index 02643acdca..58e0c86b95 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -55,6 +55,7 @@ Q_LOGGING_CATEGORY(lcMDW, "qt.text.markdown.writer") static const QChar Space = QLatin1Char(' '); static const QChar Newline = QLatin1Char('\n'); static const QChar LineBreak = QChar(0x2028); +static const QChar DoubleQuote = QLatin1Char('"'); static const QChar Backtick = QLatin1Char('`'); static const QChar Period = QLatin1Char('.'); @@ -372,7 +373,14 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign QTextCharFormat fmt = frag.fragment().charFormat(); if (fmt.isImageFormat()) { QTextImageFormat ifmt = fmt.toImageFormat(); - QString s = QLatin1String("![image](") + ifmt.name() + QLatin1Char(')'); + QString desc = ifmt.stringProperty(QTextFormat::ImageAltText); + if (desc.isEmpty()) + desc = QLatin1String("image"); + QString s = QLatin1String("![") + desc + QLatin1String("](") + ifmt.name(); + QString title = ifmt.stringProperty(QTextFormat::ImageTitle); + if (!title.isEmpty()) + s += Space + DoubleQuote + title + DoubleQuote; + s += QLatin1Char(')'); if (wrap && col + s.length() > ColumnLimit) { m_stream << Newline << wrapIndentString; col = m_wrappedLineIndent; diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp index acc74a9060..1935e58dec 100644 --- a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp +++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp @@ -416,6 +416,9 @@ void tst_QTextMarkdownWriter::fromHtml_data() QTest::newRow("block quote") << "

    In 1958, Mahatma Gandhi was quoted as follows:

    The Earth provides enough to satisfy every man's need but not for every man's greed.
    " << "In 1958, Mahatma Gandhi was quoted as follows:\n\n> The Earth provides enough to satisfy every man's need but not for every man's\n> greed.\n\n"; + QTest::newRow("image") << + "\"foo\"" << + "![foo](/url \"title\")\n\n"; // TODO // QTest::newRow("escaped number and paren after double newline") << // "

    (The first sentence of this paragraph is a line, the next paragraph has a number

    13) but that's not part of an ordered list" << From 3af85b92d7ae19cc229ebccb3291799c4d9b23cf Mon Sep 17 00:00:00 2001 From: Mikhail Svetkin Date: Tue, 20 Mar 2018 14:03:54 +0100 Subject: [PATCH 093/122] rtems: Fix pcre2 build (madvise undefined) RTEMS does not have madvise. We can use only posix_madvise Change-Id: Ia18b7cd2d7f9db84331f7e2350d060b9e85b30c8 Reviewed-by: Volker Hilsheimer --- ...001-fix-rtems-build-undefine-madvise.patch | 28 +++++++++++++++++++ src/3rdparty/pcre2/src/sljit/sljitUtils.c | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch diff --git a/src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch b/src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch new file mode 100644 index 0000000000..074b39df85 --- /dev/null +++ b/src/3rdparty/pcre2/patches/0001-fix-rtems-build-undefine-madvise.patch @@ -0,0 +1,28 @@ +From ac10063196685fe6124055feb1275e13a78f562e Mon Sep 17 00:00:00 2001 +From: Mikhail Svetkin +Date: Tue, 20 Mar 2018 14:03:54 +0100 +Subject: [PATCH] rtems: Fix pcre2 build (madvise undefined) + +RTEMS does not have madvise. We can use only posix_madvise + +Change-Id: Ia18b7cd2d7f9db84331f7e2350d060b9e85b30c8 +--- + src/3rdparty/pcre2/src/sljit/sljitUtils.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/3rdparty/pcre2/src/sljit/sljitUtils.c b/src/3rdparty/pcre2/src/sljit/sljitUtils.c +index 5c2a838932..2ead044b1b 100644 +--- a/src/3rdparty/pcre2/src/sljit/sljitUtils.c ++++ b/src/3rdparty/pcre2/src/sljit/sljitUtils.c +@@ -315,7 +315,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_st + aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; + aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; + /* If madvise is available, we release the unnecessary space. */ +-#if defined(MADV_DONTNEED) ++#if defined(MADV_DONTNEED) && !defined(__rtems__) + if (aligned_new_start > aligned_old_start) + madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED); + #elif defined(POSIX_MADV_DONTNEED) +-- +2.21.0 + diff --git a/src/3rdparty/pcre2/src/sljit/sljitUtils.c b/src/3rdparty/pcre2/src/sljit/sljitUtils.c index 5c2a838932..2ead044b1b 100644 --- a/src/3rdparty/pcre2/src/sljit/sljitUtils.c +++ b/src/3rdparty/pcre2/src/sljit/sljitUtils.c @@ -315,7 +315,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_st aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; /* If madvise is available, we release the unnecessary space. */ -#if defined(MADV_DONTNEED) +#if defined(MADV_DONTNEED) && !defined(__rtems__) if (aligned_new_start > aligned_old_start) madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED); #elif defined(POSIX_MADV_DONTNEED) From 57f38bc49d43140f3b04e625a47eb1e6de8d2ae3 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 4 Jun 2019 14:29:14 +0200 Subject: [PATCH 094/122] Do not "fixify" the content of extra compiler input variables twice MakefileGenerator::initOutPaths should only do that: init out paths. It's not supposed to modify the content of input variables for extra compilers. Those get "fixed" in MakefileGenerator::init below the "do the path fixifying" comment. The first "fixifying" would turn an absolute path in SOURCES (input variable for the moc_source extra compiler) into a path relative to the output directory. The second "fixifying" would mess everything up. Fixes: QTBUG-76097 Change-Id: I8c50ef33d097dba4a1db76144c70b0677beffb6c Reviewed-by: Kai Koehne --- qmake/generators/makefile.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index f3ca192ab2..f911f81020 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -199,7 +199,6 @@ MakefileGenerator::initOutPaths() ProStringList &inputs = project->values((*it2).toKey()); for (ProStringList::Iterator input = inputs.begin(); input != inputs.end(); ++input) { QString finp = fileFixify((*input).toQString(), FileFixifyFromOutdir); - *input = ProString(finp); QString path = replaceExtraCompilerVariables(tmp_out, finp, QString(), NoShell); path = Option::normalizePath(path); int slash = path.lastIndexOf('/'); From b3cc9403c4f7814d3e14915fdacee42b3a805073 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 20 May 2019 17:40:12 +0200 Subject: [PATCH 095/122] QTextMarkdownWriter: write fenced code blocks with language declaration MD4C now makes it possible to detect indented and fenced code blocks: https://github.com/mity/md4c/issues/81 Fenced code blocks have the advantages of being easier to write by hand, and having an "info string" following the opening fence, which is commonly used to declare the language. Also, the HTML parser now recognizes tags of the form
    which is one convention for declaring the programming language
    (as opposed to human language, for which the lang attribute would be used):
    https://stackoverflow.com/questions/5134242/semantics-standards-and-using-the-lang-attribute-for-source-code-in-markup
    So it's possible to read HTML and write markdown without losing this information.
    
    It's also possible to read markdown with any type of code block:
    fenced with ``` or ~~~, or indented, and rewrite it the same way.
    
    Change-Id: I33c2bf7d7b66c8f3ba5bdd41ab32572f09349c47
    Reviewed-by: Gatis Paeglis 
    ---
     src/gui/text/qtextformat.cpp                  |  3 +
     src/gui/text/qtextformat.h                    |  1 +
     src/gui/text/qtexthtmlparser.cpp              |  4 ++
     src/gui/text/qtextmarkdownimporter.cpp        |  8 ++-
     src/gui/text/qtextmarkdownimporter_p.h        |  1 +
     src/gui/text/qtextmarkdownwriter.cpp          | 68 ++++++++++++++++---
     src/gui/text/qtextmarkdownwriter_p.h          |  5 +-
     .../qtextmarkdownwriter/data/blockquotes.md   | 52 ++++++++++----
     .../tst_qtextmarkdownwriter.cpp               |  3 +
     9 files changed, 119 insertions(+), 26 deletions(-)
    
    diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
    index 644dd5558d..090c6cc4ce 100644
    --- a/src/gui/text/qtextformat.cpp
    +++ b/src/gui/text/qtextformat.cpp
    @@ -564,6 +564,9 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
         \value BlockTrailingHorizontalRulerWidth The width of a horizontal ruler element.
         \value HeadingLevel     The level of a heading, for example 1 corresponds to an HTML H1 tag; otherwise 0.
                                 This enum value has been added in Qt 5.12.
    +    \value BlockCodeFence   The character that was used in the "fences" around a Markdown code block.
    +                            If the code block was indented rather than fenced, the block should not have this property.
    +                            This enum value has been added in Qt 5.14.
     
         \value BlockQuoteLevel  The depth of nested quoting on this block: 1 means the block is a top-level block quote.
                                 Blocks that are not block quotes should not have this property.
    diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
    index 4f534fb65d..a91461dcae 100644
    --- a/src/gui/text/qtextformat.h
    +++ b/src/gui/text/qtextformat.h
    @@ -178,6 +178,7 @@ public:
             HeadingLevel = 0x1070,
             BlockQuoteLevel = 0x1080,
             BlockCodeLanguage = 0x1090,
    +        BlockCodeFence = 0x1091,
             BlockMarker = 0x10A0,
     
             // character properties
    diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
    index 49ee6394ee..642f0893b4 100644
    --- a/src/gui/text/qtexthtmlparser.cpp
    +++ b/src/gui/text/qtexthtmlparser.cpp
    @@ -1635,6 +1635,10 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
                     else if (key == QLatin1String("type"))
                         linkType = value;
                     break;
    +            case Html_pre:
    +                if (key == QLatin1String("class") && value.startsWith(QLatin1String("language-")))
    +                    node->blockFormat.setProperty(QTextFormat::BlockCodeLanguage, value.mid(9));
    +                break;
                 default:
                     break;
             }
    diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp
    index 223eb01e55..8a9bb3953c 100644
    --- a/src/gui/text/qtextmarkdownimporter.cpp
    +++ b/src/gui/text/qtextmarkdownimporter.cpp
    @@ -165,12 +165,13 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
             MD_BLOCK_CODE_DETAIL *detail = static_cast(det);
             m_codeBlock = true;
             m_blockCodeLanguage = QLatin1String(detail->lang.text, int(detail->lang.size));
    +        m_blockCodeFence = detail->fence_char;
             QString info = QLatin1String(detail->info.text, int(detail->info.size));
             m_needsInsertBlock = true;
             if (m_blockQuoteDepth)
    -            qCDebug(lcMD, "CODE lang '%s' info '%s' inside QUOTE %d", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockQuoteDepth);
    +            qCDebug(lcMD, "CODE lang '%s' info '%s' fenced with '%c' inside QUOTE %d", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockCodeFence, m_blockQuoteDepth);
             else
    -            qCDebug(lcMD, "CODE lang '%s' info '%s'", qPrintable(m_blockCodeLanguage), qPrintable(info));
    +            qCDebug(lcMD, "CODE lang '%s' info '%s' fenced with '%c'", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockCodeFence);
         } break;
         case MD_BLOCK_H: {
             MD_BLOCK_H_DETAIL *detail = static_cast(det);
    @@ -326,6 +327,7 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail)
         case MD_BLOCK_CODE: {
             m_codeBlock = false;
             m_blockCodeLanguage.clear();
    +        m_blockCodeFence = 0;
             if (m_blockQuoteDepth)
                 qCDebug(lcMD, "CODE ended inside QUOTE %d", m_blockQuoteDepth);
             else
    @@ -540,6 +542,8 @@ void QTextMarkdownImporter::insertBlock()
         }
         if (m_codeBlock) {
             blockFormat.setProperty(QTextFormat::BlockCodeLanguage, m_blockCodeLanguage);
    +        if (m_blockCodeFence)
    +            blockFormat.setProperty(QTextFormat::BlockCodeFence, QString(QLatin1Char(m_blockCodeFence)));
             charFormat.setFont(m_monoFont);
         } else {
             blockFormat.setTopMargin(m_paragraphMargin);
    diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h
    index fdce74483b..1b8c2ca354 100644
    --- a/src/gui/text/qtextmarkdownimporter_p.h
    +++ b/src/gui/text/qtextmarkdownimporter_p.h
    @@ -124,6 +124,7 @@ private:
         int m_tableCol = -1; // because relative cell movements (e.g. m_cursor->movePosition(QTextCursor::NextCell)) don't work
         int m_paragraphMargin = 0;
         int m_blockType = 0;
    +    char m_blockCodeFence = 0;
         Features m_features;
         QTextImageFormat m_imageFormat;
         QTextListFormat m_listFormat;
    diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp
    index 58e0c86b95..f351c8d20b 100644
    --- a/src/gui/text/qtextmarkdownwriter.cpp
    +++ b/src/gui/text/qtextmarkdownwriter.cpp
    @@ -134,6 +134,24 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
                 writeFrame(iterator.currentFrame());
             else { // no frame, it's a block
                 QTextBlock block = iterator.currentBlock();
    +            // Look ahead and detect some cases when we should
    +            // suppress needless blank lines, when there will be a big change in block format
    +            bool nextIsDifferent = false;
    +            bool ending = false;
    +            {
    +                QTextFrame::iterator next = iterator;
    +                ++next;
    +                if (next.atEnd()) {
    +                    nextIsDifferent = true;
    +                    ending = true;
    +                } else {
    +                    QTextBlockFormat format = iterator.currentBlock().blockFormat();
    +                    QTextBlockFormat nextFormat = next.currentBlock().blockFormat();
    +                    if (nextFormat.indent() != format.indent() ||
    +                            nextFormat.property(QTextFormat::BlockCodeLanguage) != format.property(QTextFormat::BlockCodeLanguage))
    +                        nextIsDifferent = true;
    +                }
    +            }
                 if (table) {
                     QTextTableCell cell = table->cellAt(block.position());
                     if (tableRow < cell.row()) {
    @@ -150,7 +168,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
                     if (lastWasList)
                         m_stream << Newline;
                 }
    -            int endingCol = writeBlock(block, !table, table && tableRow == 0);
    +            int endingCol = writeBlock(block, !table, table && tableRow == 0, nextIsDifferent);
                 m_doubleNewlineWritten = false;
                 if (table) {
                     QTextTableCell cell = table->cellAt(block.position());
    @@ -162,11 +180,19 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
                         m_stream << QString(paddingLen, Space);
                     for (int col = cell.column(); col < spanEndCol; ++col)
                         m_stream << "|";
    -            } else if (block.textList() || block.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
    +            } else if (m_fencedCodeBlock && ending) {
    +                m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space)
    +                         << m_codeBlockFence << Newline << Newline;
    +                m_codeBlockFence.clear();
    +            } else if (m_indentedCodeBlock && nextIsDifferent) {
                     m_stream << Newline;
                 } else if (endingCol > 0) {
    -                m_stream << Newline << Newline;
    -                m_doubleNewlineWritten = true;
    +                if (block.textList() || block.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
    +                    m_stream << Newline;
    +                } else {
    +                    m_stream << Newline << Newline;
    +                    m_doubleNewlineWritten = true;
    +                }
                 }
                 lastWasList = block.textList();
             }
    @@ -259,11 +285,13 @@ static void maybeEscapeFirstChar(QString &s)
         }
     }
     
    -int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat)
    +int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat, bool ignoreEmpty)
     {
    +    if (block.text().isEmpty() && ignoreEmpty)
    +        return 0;
         const int ColumnLimit = 80;
         QTextBlockFormat blockFmt = block.blockFormat();
    -    bool indentedCodeBlock = false;
    +    bool missedBlankCodeBlockLine = false;
         if (block.textList()) { // it's a list-item
             auto fmt = block.textList()->format();
             const int listLevel = fmt.indent();
    @@ -324,7 +352,28 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
         } else if (blockFmt.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) {
             m_stream << "- - -\n"; // unambiguous horizontal rule, not an underline under a heading
             return 0;
    +    } else if (blockFmt.hasProperty(QTextFormat::BlockCodeFence) || blockFmt.stringProperty(QTextFormat::BlockCodeLanguage).length() > 0) {
    +        // It's important to preserve blank lines in code blocks.  But blank lines in code blocks
    +        // inside block quotes are getting preserved anyway (along with the "> " prefix).
    +        if (!blockFmt.hasProperty(QTextFormat::BlockQuoteLevel))
    +            missedBlankCodeBlockLine = true; // only if we don't get any fragments below
    +        if (!m_fencedCodeBlock) {
    +            QString fenceChar = blockFmt.stringProperty(QTextFormat::BlockCodeFence);
    +            if (fenceChar.isEmpty())
    +                fenceChar = QLatin1String("`");
    +            m_codeBlockFence = QString(3, fenceChar.at(0));
    +            // A block quote can contain an indented code block, but not vice-versa.
    +            m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space) << m_codeBlockFence
    +                     << Space << blockFmt.stringProperty(QTextFormat::BlockCodeLanguage) << Newline;
    +            m_fencedCodeBlock = true;
    +        }
         } else if (!blockFmt.indent()) {
    +        if (m_fencedCodeBlock) {
    +            m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space)
    +                     << m_codeBlockFence << Newline;
    +            m_fencedCodeBlock = false;
    +            m_codeBlockFence.clear();
    +        }
             m_wrappedLineIndent = 0;
             m_linePrefix.clear();
             if (blockFmt.hasProperty(QTextFormat::BlockQuoteLevel)) {
    @@ -337,7 +386,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
             if (blockFmt.hasProperty(QTextFormat::BlockCodeLanguage)) {
                 // A block quote can contain an indented code block, but not vice-versa.
                 m_linePrefix += QString(4, Space);
    -            indentedCodeBlock = true;
    +            m_indentedCodeBlock = true;
             }
         }
         if (blockFmt.headingLevel())
    @@ -358,6 +407,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
         bool strikeOut = false;
         QString backticks(Backtick);
         for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) {
    +        missedBlankCodeBlockLine = false;
             QString fragmentText = frag.fragment().text();
             while (fragmentText.endsWith(Newline))
                 fragmentText.chop(1);
    @@ -401,7 +451,7 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
                 bool monoFrag = fontInfo.fixedPitch();
                 QString markers;
                 if (!ignoreFormat) {
    -                if (monoFrag != mono && !indentedCodeBlock) {
    +                if (monoFrag != mono && !m_indentedCodeBlock && !m_fencedCodeBlock) {
                         if (monoFrag)
                             backticks = QString(adjacentBackticksCount(fragmentText) + 1, Backtick);
                         markers += backticks;
    @@ -501,6 +551,8 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
             m_stream << "~~";
             col += 2;
         }
    +    if (missedBlankCodeBlockLine)
    +        m_stream << Newline;
         return col;
     }
     
    diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h
    index 96ceb445cd..90310250ac 100644
    --- a/src/gui/text/qtextmarkdownwriter_p.h
    +++ b/src/gui/text/qtextmarkdownwriter_p.h
    @@ -67,7 +67,7 @@ public:
         bool writeAll(const QTextDocument *document);
         void writeTable(const QAbstractItemModel *table);
     
    -    int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat);
    +    int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat, bool ignoreEmpty);
         void writeFrame(const QTextFrame *frame);
     
     private:
    @@ -82,9 +82,12 @@ private:
         QTextDocument::MarkdownFeatures m_features;
         QMap m_listInfo;
         QString m_linePrefix;
    +    QString m_codeBlockFence;
         int m_wrappedLineIndent = 0;
         int m_lastListIndent = 1;
         bool m_doubleNewlineWritten = false;
    +    bool m_indentedCodeBlock = false;
    +    bool m_fencedCodeBlock = false;
     };
     
     QT_END_NAMESPACE
    diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
    index 44c198fdc5..6336d0219f 100644
    --- a/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
    +++ b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
    @@ -20,21 +20,43 @@ MacFarlane writes:
     > equivalent sample of Markdown. Here is a sample of AsciiDoc from the AsciiDoc
     > manual:
     
    ->     1. List item one.
    ->     +
    ->     List item one continued with a second paragraph followed by an
    ->     Indented block.
    ->     +
    ->     .................
    ->     $ ls *.sh
    ->     $ mv *.sh ~/tmp
    ->     .................
    ->     +
    ->     List item continued with a third paragraph.
    ->     
    ->     2. List item two continued with an open block.
    ->     ...
    ->     
    +> ``` AsciiDoc
    +> 1. List item one.
    +> +
    +> List item one continued with a second paragraph followed by an
    +> Indented block.
    +> +
    +> .................
    +> $ ls *.sh
    +> $ mv *.sh ~/tmp
    +> .................
    +> +
    +> List item continued with a third paragraph.
    +> 
    +> 2. List item two continued with an open block.
    +> ...
    +> ```
     The quotation includes an embedded quotation and a code quotation and ends with
     an ellipsis due to being incomplete.
     
    +Now let's have an indented code block:
    +
    +    #include 
    +    
    +    int main(void)
    +    {
    +        printf("# hello markdown\n");
    +        return 0;
    +    }
    +
    +and end with a fenced code block:
    +~~~ pseudocode
    +#include 
    +#include 
    +
    +a block {
    +    a statement;
    +    another statement;
    +}
    +~~~
    +
    diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
    index 1935e58dec..8d38cbb18a 100644
    --- a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
    +++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
    @@ -419,6 +419,9 @@ void tst_QTextMarkdownWriter::fromHtml_data()
         QTest::newRow("image") <<
             "\"foo\"" <<
             "![foo](/url \"title\")\n\n";
    +    QTest::newRow("code") <<
    +        "
    \n#include \"foo.h\"\n\nblock {\n    statement();\n}\n\n
    " << + "``` pseudocode\n#include \"foo.h\"\n\nblock {\n statement();\n}\n```\n\n"; // TODO // QTest::newRow("escaped number and paren after double newline") << // "

    (The first sentence of this paragraph is a line, the next paragraph has a number

    13) but that's not part of an ordered list" << From 29e3a4dfeaf5d4924eaa68824fb21998de687809 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 5 Jun 2019 12:58:54 +0200 Subject: [PATCH 096/122] Fix warnings & deprs in tst_qcoreapplication and tst_qguiapplication It's perhaps best to ensure that functions we are deprecating shall no longer be used in tests. Also, fix the "0 as nullptr" warnings. Change-Id: I2f22c9b9482e80fa120bcd728ec269198a36678f Reviewed-by: Richard Moe Gustavsen --- .../qcoreapplication/tst_qcoreapplication.cpp | 2 +- .../qguiapplication/qguiapplication.pro | 1 + .../qguiapplication/tst_qguiapplication.cpp | 50 +++++++++---------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp index 6adb393ddd..d68cefc807 100644 --- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp +++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp @@ -611,7 +611,7 @@ void tst_QCoreApplication::processEventsAlwaysSendsPostedEvents() TestApplication app(argc, argv); ProcessEventsAlwaysSendsPostedEventsObject object; - QTime t; + QElapsedTimer t; t.start(); int i = 1; do { diff --git a/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro b/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro index 895c2a0307..34b75a8397 100644 --- a/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro +++ b/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro @@ -6,6 +6,7 @@ INCLUDEPATH += $$CORE_TEST_PATH TARGET = tst_qguiapplication QT += gui-private +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050E00 SOURCES += tst_qguiapplication.cpp RESOURCES = tst_qguiapplication.qrc diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp index 09fec89de4..5ee25677bf 100644 --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp @@ -184,7 +184,7 @@ void tst_QGuiApplication::windowIcon() class DummyWindow : public QWindow { public: - DummyWindow() : m_focusObject(0) {} + DummyWindow() : m_focusObject(nullptr) {} virtual QObject *focusObject() const { @@ -204,7 +204,7 @@ public: void tst_QGuiApplication::focusObject() { int argc = 0; - QGuiApplication app(argc, 0); + QGuiApplication app(argc, nullptr); if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) QSKIP("QWindow::requestActivate() is not supported."); @@ -271,15 +271,15 @@ void tst_QGuiApplication::focusObject() void tst_QGuiApplication::allWindows() { int argc = 0; - QGuiApplication app(argc, 0); + QGuiApplication app(argc, nullptr); QWindow *window1 = new QWindow; QWindow *window2 = new QWindow(window1); QVERIFY(app.allWindows().contains(window1)); QVERIFY(app.allWindows().contains(window2)); QCOMPARE(app.allWindows().count(), 2); delete window1; - window1 = 0; - window2 = 0; + window1 = nullptr; + window2 = nullptr; QVERIFY(!app.allWindows().contains(window2)); QVERIFY(!app.allWindows().contains(window1)); QCOMPARE(app.allWindows().count(), 0); @@ -288,15 +288,15 @@ void tst_QGuiApplication::allWindows() void tst_QGuiApplication::topLevelWindows() { int argc = 0; - QGuiApplication app(argc, 0); + QGuiApplication app(argc, nullptr); QWindow *window1 = new QWindow; QWindow *window2 = new QWindow(window1); QVERIFY(app.topLevelWindows().contains(window1)); QVERIFY(!app.topLevelWindows().contains(window2)); QCOMPARE(app.topLevelWindows().count(), 1); delete window1; - window1 = 0; - window2 = 0; + window1 = nullptr; + window2 = nullptr; QVERIFY(!app.topLevelWindows().contains(window2)); QVERIFY(!app.topLevelWindows().contains(window1)); QCOMPARE(app.topLevelWindows().count(), 0); @@ -306,7 +306,7 @@ class ShowCloseShowWindow : public QWindow { Q_OBJECT public: - ShowCloseShowWindow(bool showAgain, QWindow *parent = 0) + ShowCloseShowWindow(bool showAgain, QWindow *parent = nullptr) : QWindow(parent), showAgain(showAgain) { QTimer::singleShot(0, this, SLOT(doClose())); @@ -331,7 +331,7 @@ private: void tst_QGuiApplication::abortQuitOnShow() { int argc = 0; - QGuiApplication app(argc, 0); + QGuiApplication app(argc, nullptr); const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry(); QScopedPointer window1(new ShowCloseShowWindow(false)); @@ -366,7 +366,7 @@ protected: } public: - FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(0), windowDuringFocusOut(0) {} + FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(nullptr), windowDuringFocusOut(nullptr) {} QWindow *windowDuringFocusAboutToChange; QWindow *windowDuringFocusOut; @@ -378,7 +378,7 @@ void tst_QGuiApplication::changeFocusWindow() QSKIP("WinRt does not support multiple native windows."); #endif int argc = 0; - QGuiApplication app(argc, 0); + QGuiApplication app(argc, nullptr); if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) QSKIP("QWindow::requestActivate() is not supported."); @@ -430,7 +430,7 @@ void tst_QGuiApplication::changeFocusWindow() void tst_QGuiApplication::keyboardModifiers() { int argc = 0; - QGuiApplication app(argc, 0); + QGuiApplication app(argc, nullptr); const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry(); QScopedPointer window(new QWindow); @@ -564,7 +564,7 @@ public: int leaves; int enters; - inline explicit BlockableWindow(QWindow *parent = 0) + inline explicit BlockableWindow(QWindow *parent = nullptr) : QWindow(parent), blocked(false), leaves(0), enters(0) {} bool event(QEvent *e) @@ -601,7 +601,7 @@ void tst_QGuiApplication::modalWindow() QSKIP("WinRt does not support multiple native windows."); #endif int argc = 0; - QGuiApplication app(argc, 0); + QGuiApplication app(argc, nullptr); const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry(); int x = screenGeometry.left() + spacing; @@ -654,7 +654,7 @@ void tst_QGuiApplication::modalWindow() window2->show(); QVERIFY(QTest::qWaitForWindowExposed(window1.data())); QVERIFY(QTest::qWaitForWindowExposed(window2.data())); - QCOMPARE(app.modalWindow(), static_cast(0)); + QCOMPARE(app.modalWindow(), static_cast(nullptr)); QCOMPARE(window1->blocked, 0); QCOMPARE(childWindow1->blocked, 0); QCOMPARE(window2->blocked, 0); @@ -698,7 +698,7 @@ void tst_QGuiApplication::modalWindow() // everything is unblocked when applicationModalWindow1 is hidden applicationModalWindow1->hide(); - QCOMPARE(app.modalWindow(), static_cast(0)); + QCOMPARE(app.modalWindow(), static_cast(nullptr)); QCOMPARE(window1->blocked, 0); QCOMPARE(childWindow1->blocked, 0); // QTBUG-32242, blocked status needs to be set on children as well. QCOMPARE(window2->blocked, 0); @@ -750,7 +750,7 @@ void tst_QGuiApplication::modalWindow() // hide windowModalWindow2, windowModalWindow1 and window1 are unblocked windowModalWindow2->hide(); - QCOMPARE(app.modalWindow(), static_cast(0)); + QCOMPARE(app.modalWindow(), static_cast(nullptr)); QCOMPARE(window1->blocked, 0); QCOMPARE(window2->blocked, 0); QCOMPARE(windowModalWindow1->blocked, 0); @@ -815,7 +815,7 @@ void tst_QGuiApplication::modalWindow() // hide windowModalWindow1, everything is unblocked windowModalWindow1->hide(); - QCOMPARE(app.modalWindow(), static_cast(0)); + QCOMPARE(app.modalWindow(), static_cast(nullptr)); QCOMPARE(window1->blocked, 0); QCOMPARE(window2->blocked, 0); QCOMPARE(windowModalWindow1->blocked, 0); @@ -829,7 +829,7 @@ void tst_QGuiApplication::modalWindow() void tst_QGuiApplication::quitOnLastWindowClosed() { int argc = 0; - QGuiApplication app(argc, 0); + QGuiApplication app(argc, nullptr); const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry(); QTimer timer; @@ -869,7 +869,7 @@ void tst_QGuiApplication::quitOnLastWindowClosed() void tst_QGuiApplication::quitOnLastWindowClosedMulti() { int argc = 0; - QGuiApplication app(argc, 0); + QGuiApplication app(argc, nullptr); const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry(); QTimer timer; @@ -909,7 +909,7 @@ void tst_QGuiApplication::quitOnLastWindowClosedMulti() void tst_QGuiApplication::dontQuitOnLastWindowClosed() { int argc = 0; - QGuiApplication app(argc, 0); + QGuiApplication app(argc, nullptr); app.setQuitOnLastWindowClosed(false); QTimer timer; @@ -959,7 +959,7 @@ public: { if (key == "testplugin") return new TestPlugin; - return 0; + return nullptr; } }; @@ -1069,7 +1069,7 @@ void tst_QGuiApplication::testSetPaletteAttribute() QVERIFY(!QCoreApplication::testAttribute(Qt::AA_SetPalette)); QPalette palette; - palette.setColor(QPalette::Foreground, Qt::red); + palette.setColor(QPalette::WindowText, Qt::red); QGuiApplication::setPalette(palette); QVERIFY(QCoreApplication::testAttribute(Qt::AA_SetPalette)); @@ -1126,7 +1126,7 @@ void tst_QGuiApplication::settableStyleHints() int argc = 0; QScopedPointer app; if (appInstance) - app.reset(new QGuiApplication(argc, 0)); + app.reset(new QGuiApplication(argc, nullptr)); const int keyboardInputInterval = 555; QGuiApplication::styleHints()->setKeyboardInputInterval(keyboardInputInterval); From 548513a4bd050d3df0a85fed6e2d1a00ce06d2ab Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 27 May 2019 17:47:22 +0200 Subject: [PATCH 097/122] Separate out the time, zone, date code from corelib/tools/ We'll be adding calendar code here as well, and tools/ was getting rather crowded, so it looks like time to move out a reasonably coherent sub-bundle of it all. Change-Id: I7e8030f38c31aa307f519dd918a43fc44baa6aa1 Reviewed-by: Lars Knoll --- qmake/Makefile.unix | 4 +-- qmake/Makefile.win32 | 3 ++ src/corelib/corelib.pro | 1 + src/corelib/{tools => time}/qdatetime.cpp | 0 src/corelib/{tools => time}/qdatetime.h | 0 src/corelib/{tools => time}/qdatetime_p.h | 0 .../{tools => time}/qdatetimeparser.cpp | 0 .../{tools => time}/qdatetimeparser_p.h | 0 src/corelib/{tools => time}/qtimezone.cpp | 0 src/corelib/{tools => time}/qtimezone.h | 0 .../{tools => time}/qtimezoneprivate.cpp | 0 .../qtimezoneprivate_android.cpp | 0 .../{tools => time}/qtimezoneprivate_data_p.h | 0 .../{tools => time}/qtimezoneprivate_icu.cpp | 0 .../{tools => time}/qtimezoneprivate_mac.mm | 0 .../{tools => time}/qtimezoneprivate_p.h | 2 +- .../{tools => time}/qtimezoneprivate_tz.cpp | 3 +- .../{tools => time}/qtimezoneprivate_win.cpp | 0 src/corelib/time/time.pri | 34 +++++++++++++++++++ src/corelib/tools/qlocale.cpp | 2 +- src/corelib/tools/tools.pri | 30 ---------------- src/tools/bootstrap/bootstrap.pro | 2 +- tests/auto/corelib/corelib.pro | 1 + .../corelib/{tools => time}/qdate/.gitignore | 0 .../corelib/{tools => time}/qdate/qdate.pro | 0 .../{tools => time}/qdate/tst_qdate.cpp | 0 .../{tools => time}/qdatetime/.gitignore | 0 .../{tools => time}/qdatetime/BLACKLIST | 0 .../{tools => time}/qdatetime/qdatetime.pro | 0 .../qdatetime/tst_qdatetime.cpp | 0 .../qdatetime/tst_qdatetime_mac.mm | 0 .../corelib/{tools => time}/qtime/.gitignore | 0 .../corelib/{tools => time}/qtime/qtime.pro | 0 .../{tools => time}/qtime/tst_qtime.cpp | 0 .../{tools => time}/qtimezone/BLACKLIST | 0 .../{tools => time}/qtimezone/qtimezone.pro | 0 .../qtimezone/tst_qtimezone.cpp | 0 .../qtimezone/tst_qtimezone_darwin.mm | 0 tests/auto/corelib/time/time.pro | 6 ++++ tests/auto/corelib/tools/tools.pro | 4 --- tests/benchmarks/corelib/corelib.pro | 1 + .../corelib/{tools => time}/qdate/qdate.pro | 0 .../{tools => time}/qdate/tst_bench_qdate.cpp | 0 .../{tools => time}/qdatetime/main.cpp | 0 .../{tools => time}/qdatetime/qdatetime.pro | 0 .../{tools => time}/qtimezone/main.cpp | 0 .../{tools => time}/qtimezone/qtimezone.pro | 0 tests/benchmarks/corelib/time/time.pro | 5 +++ tests/benchmarks/corelib/tools/tools.pro | 2 -- util/locale_database/cldr2qtimezone.py | 4 +-- 50 files changed, 59 insertions(+), 45 deletions(-) rename src/corelib/{tools => time}/qdatetime.cpp (100%) rename src/corelib/{tools => time}/qdatetime.h (100%) rename src/corelib/{tools => time}/qdatetime_p.h (100%) rename src/corelib/{tools => time}/qdatetimeparser.cpp (100%) rename src/corelib/{tools => time}/qdatetimeparser_p.h (100%) rename src/corelib/{tools => time}/qtimezone.cpp (100%) rename src/corelib/{tools => time}/qtimezone.h (100%) rename src/corelib/{tools => time}/qtimezoneprivate.cpp (100%) rename src/corelib/{tools => time}/qtimezoneprivate_android.cpp (100%) rename src/corelib/{tools => time}/qtimezoneprivate_data_p.h (100%) rename src/corelib/{tools => time}/qtimezoneprivate_icu.cpp (100%) rename src/corelib/{tools => time}/qtimezoneprivate_mac.mm (100%) rename src/corelib/{tools => time}/qtimezoneprivate_p.h (99%) rename src/corelib/{tools => time}/qtimezoneprivate_tz.cpp (99%) rename src/corelib/{tools => time}/qtimezoneprivate_win.cpp (100%) create mode 100644 src/corelib/time/time.pri rename tests/auto/corelib/{tools => time}/qdate/.gitignore (100%) rename tests/auto/corelib/{tools => time}/qdate/qdate.pro (100%) rename tests/auto/corelib/{tools => time}/qdate/tst_qdate.cpp (100%) rename tests/auto/corelib/{tools => time}/qdatetime/.gitignore (100%) rename tests/auto/corelib/{tools => time}/qdatetime/BLACKLIST (100%) rename tests/auto/corelib/{tools => time}/qdatetime/qdatetime.pro (100%) rename tests/auto/corelib/{tools => time}/qdatetime/tst_qdatetime.cpp (100%) rename tests/auto/corelib/{tools => time}/qdatetime/tst_qdatetime_mac.mm (100%) rename tests/auto/corelib/{tools => time}/qtime/.gitignore (100%) rename tests/auto/corelib/{tools => time}/qtime/qtime.pro (100%) rename tests/auto/corelib/{tools => time}/qtime/tst_qtime.cpp (100%) rename tests/auto/corelib/{tools => time}/qtimezone/BLACKLIST (100%) rename tests/auto/corelib/{tools => time}/qtimezone/qtimezone.pro (100%) rename tests/auto/corelib/{tools => time}/qtimezone/tst_qtimezone.cpp (100%) rename tests/auto/corelib/{tools => time}/qtimezone/tst_qtimezone_darwin.mm (100%) create mode 100644 tests/auto/corelib/time/time.pro rename tests/benchmarks/corelib/{tools => time}/qdate/qdate.pro (100%) rename tests/benchmarks/corelib/{tools => time}/qdate/tst_bench_qdate.cpp (100%) rename tests/benchmarks/corelib/{tools => time}/qdatetime/main.cpp (100%) rename tests/benchmarks/corelib/{tools => time}/qdatetime/qdatetime.pro (100%) rename tests/benchmarks/corelib/{tools => time}/qtimezone/main.cpp (100%) rename tests/benchmarks/corelib/{tools => time}/qtimezone/qtimezone.pro (100%) create mode 100644 tests/benchmarks/corelib/time/time.pro diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 9898346dbe..069cb0f12d 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -105,12 +105,12 @@ DEPEND_SRC = \ $(SOURCE_PATH)/src/corelib/serialization/qtextstream.cpp \ $(SOURCE_PATH)/src/corelib/serialization/qxmlstream.cpp \ $(SOURCE_PATH)/src/corelib/serialization/qxmlutils.cpp \ + $(SOURCE_PATH)/src/corelib/time/qdatetime.cpp \ $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp \ $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp \ $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\ $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \ $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp \ - $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp \ $(SOURCE_PATH)/src/corelib/tools/qhash.cpp \ $(SOURCE_PATH)/src/corelib/tools/qlist.cpp \ $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp \ @@ -425,7 +425,7 @@ quuid.o: $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp qfileinfo.o: $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< -qdatetime.o: $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp +qdatetime.o: $(SOURCE_PATH)/src/corelib/time/qdatetime.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index 5fa49d2f7f..d300e49215 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -196,6 +196,9 @@ qmake_pch.obj: {$(SOURCE_PATH)\src\corelib\serialization}.cpp{}.obj:: $(CXX) $(CXXFLAGS) $< +{$(SOURCE_PATH)\src\corelib\time}.cpp{}.obj:: + $(CXX) $(CXXFLAGS) $< + {$(SOURCE_PATH)\src\corelib\tools}.cpp{}.obj:: $(CXX) $(CXXFLAGS) $< diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index 6babbac8f5..521f840292 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -36,6 +36,7 @@ qtConfig(animation): include(animation/animation.pri) include(global/global.pri) include(thread/thread.pri) include(tools/tools.pri) +include(time/time.pri) include(io/io.pri) include(itemmodels/itemmodels.pri) include(plugin/plugin.pri) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/time/qdatetime.cpp similarity index 100% rename from src/corelib/tools/qdatetime.cpp rename to src/corelib/time/qdatetime.cpp diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/time/qdatetime.h similarity index 100% rename from src/corelib/tools/qdatetime.h rename to src/corelib/time/qdatetime.h diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/time/qdatetime_p.h similarity index 100% rename from src/corelib/tools/qdatetime_p.h rename to src/corelib/time/qdatetime_p.h diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp similarity index 100% rename from src/corelib/tools/qdatetimeparser.cpp rename to src/corelib/time/qdatetimeparser.cpp diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/time/qdatetimeparser_p.h similarity index 100% rename from src/corelib/tools/qdatetimeparser_p.h rename to src/corelib/time/qdatetimeparser_p.h diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/time/qtimezone.cpp similarity index 100% rename from src/corelib/tools/qtimezone.cpp rename to src/corelib/time/qtimezone.cpp diff --git a/src/corelib/tools/qtimezone.h b/src/corelib/time/qtimezone.h similarity index 100% rename from src/corelib/tools/qtimezone.h rename to src/corelib/time/qtimezone.h diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp similarity index 100% rename from src/corelib/tools/qtimezoneprivate.cpp rename to src/corelib/time/qtimezoneprivate.cpp diff --git a/src/corelib/tools/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp similarity index 100% rename from src/corelib/tools/qtimezoneprivate_android.cpp rename to src/corelib/time/qtimezoneprivate_android.cpp diff --git a/src/corelib/tools/qtimezoneprivate_data_p.h b/src/corelib/time/qtimezoneprivate_data_p.h similarity index 100% rename from src/corelib/tools/qtimezoneprivate_data_p.h rename to src/corelib/time/qtimezoneprivate_data_p.h diff --git a/src/corelib/tools/qtimezoneprivate_icu.cpp b/src/corelib/time/qtimezoneprivate_icu.cpp similarity index 100% rename from src/corelib/tools/qtimezoneprivate_icu.cpp rename to src/corelib/time/qtimezoneprivate_icu.cpp diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/time/qtimezoneprivate_mac.mm similarity index 100% rename from src/corelib/tools/qtimezoneprivate_mac.mm rename to src/corelib/time/qtimezoneprivate_mac.mm diff --git a/src/corelib/tools/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h similarity index 99% rename from src/corelib/tools/qtimezoneprivate_p.h rename to src/corelib/time/qtimezoneprivate_p.h index b5e9286f6a..5f6491ef81 100644 --- a/src/corelib/tools/qtimezoneprivate_p.h +++ b/src/corelib/time/qtimezoneprivate_p.h @@ -53,7 +53,7 @@ // #include "qtimezone.h" -#include "qlocale_p.h" +#include "private/qlocale_p.h" #include "qvector.h" #if QT_CONFIG(icu) diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp similarity index 99% rename from src/corelib/tools/qtimezoneprivate_tz.cpp rename to src/corelib/time/qtimezoneprivate_tz.cpp index f5440799ab..2c845b1bce 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/time/qtimezoneprivate_tz.cpp @@ -40,6 +40,7 @@ #include "qtimezone.h" #include "qtimezoneprivate_p.h" #include "qdatetime_p.h" // ### Qt 5.14: remove once YearRange is on QDateTime +#include "private/qlocale_tools_p.h" #include #include @@ -48,8 +49,6 @@ #include -#include "qlocale_tools_p.h" - #include QT_BEGIN_NAMESPACE diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/time/qtimezoneprivate_win.cpp similarity index 100% rename from src/corelib/tools/qtimezoneprivate_win.cpp rename to src/corelib/time/qtimezoneprivate_win.cpp diff --git a/src/corelib/time/time.pri b/src/corelib/time/time.pri new file mode 100644 index 0000000000..bacb7e875d --- /dev/null +++ b/src/corelib/time/time.pri @@ -0,0 +1,34 @@ +# Qt time / date / zone / calendar module + +HEADERS += \ + time/qdatetime.h \ + time/qdatetime_p.h + +SOURCES += time/qdatetime.cpp + +qtConfig(timezone) { + HEADERS += \ + time/qtimezone.h \ + time/qtimezoneprivate_p.h \ + time/qtimezoneprivate_data_p.h + SOURCES += \ + time/qtimezone.cpp \ + time/qtimezoneprivate.cpp + !nacl:darwin: { + SOURCES += time/qtimezoneprivate_mac.mm + } else: android:!android-embedded: { + SOURCES += time/qtimezoneprivate_android.cpp + } else: unix: { + SOURCES += time/qtimezoneprivate_tz.cpp + qtConfig(icu): SOURCES += time/qtimezoneprivate_icu.cpp + } else: qtConfig(icu): { + SOURCES += time/qtimezoneprivate_icu.cpp + } else: win32: { + SOURCES += time/qtimezoneprivate_win.cpp + } +} + +qtConfig(datetimeparser) { + HEADERS += time/qdatetimeparser_p.h + SOURCES += time/qdatetimeparser.cpp +} diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index f6eaa53c3a..c8740e55f3 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -55,7 +55,7 @@ #include "qlocale_p.h" #include "qlocale_tools_p.h" #if QT_CONFIG(datetimeparser) -#include "qdatetimeparser_p.h" +#include "private/qdatetimeparser_p.h" #endif #include "qnamespace.h" #include "qdatetime.h" diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 5dcb6c9ee0..52eddd5d6b 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -20,8 +20,6 @@ HEADERS += \ tools/qcontainerfwd.h \ tools/qcontainertools_impl.h \ tools/qcryptographichash.h \ - tools/qdatetime.h \ - tools/qdatetime_p.h \ tools/qdoublescanprint_p.h \ tools/qeasingcurve.h \ tools/qfreelist_p.h \ @@ -86,7 +84,6 @@ SOURCES += \ tools/qbytearraymatcher.cpp \ tools/qcollator.cpp \ tools/qcryptographichash.cpp \ - tools/qdatetime.cpp \ tools/qeasingcurve.cpp \ tools/qfreelist.cpp \ tools/qhash.cpp \ @@ -154,33 +151,6 @@ qtConfig(icu) { SOURCES += tools/qcollator_posix.cpp } -qtConfig(timezone) { - HEADERS += \ - tools/qtimezone.h \ - tools/qtimezoneprivate_p.h \ - tools/qtimezoneprivate_data_p.h - SOURCES += \ - tools/qtimezone.cpp \ - tools/qtimezoneprivate.cpp - !nacl:darwin: { - SOURCES += tools/qtimezoneprivate_mac.mm - } else: android:!android-embedded: { - SOURCES += tools/qtimezoneprivate_android.cpp - } else: unix: { - SOURCES += tools/qtimezoneprivate_tz.cpp - qtConfig(icu): SOURCES += tools/qtimezoneprivate_icu.cpp - } else: qtConfig(icu): { - SOURCES += tools/qtimezoneprivate_icu.cpp - } else: win32: { - SOURCES += tools/qtimezoneprivate_win.cpp - } -} - -qtConfig(datetimeparser) { - HEADERS += tools/qdatetimeparser_p.h - SOURCES += tools/qdatetimeparser.cpp -} - qtConfig(regularexpression) { QMAKE_USE_PRIVATE += pcre2 diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 3aeca6e7af..40c0702f0a 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -72,6 +72,7 @@ SOURCES += \ ../../corelib/serialization/qtextstream.cpp \ ../../corelib/serialization/qxmlutils.cpp \ ../../corelib/serialization/qxmlstream.cpp \ + ../../corelib/time/qdatetime.cpp \ ../../corelib/tools/qbitarray.cpp \ ../../corelib/tools/qbytearray.cpp \ ../../corelib/tools/qarraydata.cpp \ @@ -79,7 +80,6 @@ SOURCES += \ ../../corelib/tools/qcommandlineparser.cpp \ ../../corelib/tools/qcommandlineoption.cpp \ ../../corelib/tools/qcryptographichash.cpp \ - ../../corelib/tools/qdatetime.cpp \ ../../corelib/tools/qhash.cpp \ ../../corelib/tools/qlist.cpp \ ../../corelib/tools/qlinkedlist.cpp \ diff --git a/tests/auto/corelib/corelib.pro b/tests/auto/corelib/corelib.pro index 44e1c519b0..1d76e1549b 100644 --- a/tests/auto/corelib/corelib.pro +++ b/tests/auto/corelib/corelib.pro @@ -14,4 +14,5 @@ SUBDIRS = \ serialization \ statemachine \ thread \ + time \ tools diff --git a/tests/auto/corelib/tools/qdate/.gitignore b/tests/auto/corelib/time/qdate/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qdate/.gitignore rename to tests/auto/corelib/time/qdate/.gitignore diff --git a/tests/auto/corelib/tools/qdate/qdate.pro b/tests/auto/corelib/time/qdate/qdate.pro similarity index 100% rename from tests/auto/corelib/tools/qdate/qdate.pro rename to tests/auto/corelib/time/qdate/qdate.pro diff --git a/tests/auto/corelib/tools/qdate/tst_qdate.cpp b/tests/auto/corelib/time/qdate/tst_qdate.cpp similarity index 100% rename from tests/auto/corelib/tools/qdate/tst_qdate.cpp rename to tests/auto/corelib/time/qdate/tst_qdate.cpp diff --git a/tests/auto/corelib/tools/qdatetime/.gitignore b/tests/auto/corelib/time/qdatetime/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qdatetime/.gitignore rename to tests/auto/corelib/time/qdatetime/.gitignore diff --git a/tests/auto/corelib/tools/qdatetime/BLACKLIST b/tests/auto/corelib/time/qdatetime/BLACKLIST similarity index 100% rename from tests/auto/corelib/tools/qdatetime/BLACKLIST rename to tests/auto/corelib/time/qdatetime/BLACKLIST diff --git a/tests/auto/corelib/tools/qdatetime/qdatetime.pro b/tests/auto/corelib/time/qdatetime/qdatetime.pro similarity index 100% rename from tests/auto/corelib/tools/qdatetime/qdatetime.pro rename to tests/auto/corelib/time/qdatetime/qdatetime.pro diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp similarity index 100% rename from tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp rename to tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm b/tests/auto/corelib/time/qdatetime/tst_qdatetime_mac.mm similarity index 100% rename from tests/auto/corelib/tools/qdatetime/tst_qdatetime_mac.mm rename to tests/auto/corelib/time/qdatetime/tst_qdatetime_mac.mm diff --git a/tests/auto/corelib/tools/qtime/.gitignore b/tests/auto/corelib/time/qtime/.gitignore similarity index 100% rename from tests/auto/corelib/tools/qtime/.gitignore rename to tests/auto/corelib/time/qtime/.gitignore diff --git a/tests/auto/corelib/tools/qtime/qtime.pro b/tests/auto/corelib/time/qtime/qtime.pro similarity index 100% rename from tests/auto/corelib/tools/qtime/qtime.pro rename to tests/auto/corelib/time/qtime/qtime.pro diff --git a/tests/auto/corelib/tools/qtime/tst_qtime.cpp b/tests/auto/corelib/time/qtime/tst_qtime.cpp similarity index 100% rename from tests/auto/corelib/tools/qtime/tst_qtime.cpp rename to tests/auto/corelib/time/qtime/tst_qtime.cpp diff --git a/tests/auto/corelib/tools/qtimezone/BLACKLIST b/tests/auto/corelib/time/qtimezone/BLACKLIST similarity index 100% rename from tests/auto/corelib/tools/qtimezone/BLACKLIST rename to tests/auto/corelib/time/qtimezone/BLACKLIST diff --git a/tests/auto/corelib/tools/qtimezone/qtimezone.pro b/tests/auto/corelib/time/qtimezone/qtimezone.pro similarity index 100% rename from tests/auto/corelib/tools/qtimezone/qtimezone.pro rename to tests/auto/corelib/time/qtimezone/qtimezone.pro diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp similarity index 100% rename from tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp rename to tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm b/tests/auto/corelib/time/qtimezone/tst_qtimezone_darwin.mm similarity index 100% rename from tests/auto/corelib/tools/qtimezone/tst_qtimezone_darwin.mm rename to tests/auto/corelib/time/qtimezone/tst_qtimezone_darwin.mm diff --git a/tests/auto/corelib/time/time.pro b/tests/auto/corelib/time/time.pro new file mode 100644 index 0000000000..6f9ff038db --- /dev/null +++ b/tests/auto/corelib/time/time.pro @@ -0,0 +1,6 @@ +TEMPLATE = subdirs +SUBDIRS = \ + qdate \ + qdatetime \ + qtime \ + qtimezone diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro index c6da33cce0..243e7e96f5 100644 --- a/tests/auto/corelib/tools/tools.pro +++ b/tests/auto/corelib/tools/tools.pro @@ -16,8 +16,6 @@ SUBDIRS=\ qcommandlineparser \ qcontiguouscache \ qcryptographichash \ - qdate \ - qdatetime \ qeasingcurve \ qexplicitlyshareddatapointer \ qfreelist \ @@ -62,8 +60,6 @@ SUBDIRS=\ qstringref \ qstringview \ qtextboundaryfinder \ - qtime \ - qtimezone \ qtimeline \ qvarlengtharray \ qvector \ diff --git a/tests/benchmarks/corelib/corelib.pro b/tests/benchmarks/corelib/corelib.pro index b5781ad49e..99af4c138f 100644 --- a/tests/benchmarks/corelib/corelib.pro +++ b/tests/benchmarks/corelib/corelib.pro @@ -5,6 +5,7 @@ SUBDIRS = \ mimetypes \ kernel \ thread \ + time \ tools \ codecs \ plugin diff --git a/tests/benchmarks/corelib/tools/qdate/qdate.pro b/tests/benchmarks/corelib/time/qdate/qdate.pro similarity index 100% rename from tests/benchmarks/corelib/tools/qdate/qdate.pro rename to tests/benchmarks/corelib/time/qdate/qdate.pro diff --git a/tests/benchmarks/corelib/tools/qdate/tst_bench_qdate.cpp b/tests/benchmarks/corelib/time/qdate/tst_bench_qdate.cpp similarity index 100% rename from tests/benchmarks/corelib/tools/qdate/tst_bench_qdate.cpp rename to tests/benchmarks/corelib/time/qdate/tst_bench_qdate.cpp diff --git a/tests/benchmarks/corelib/tools/qdatetime/main.cpp b/tests/benchmarks/corelib/time/qdatetime/main.cpp similarity index 100% rename from tests/benchmarks/corelib/tools/qdatetime/main.cpp rename to tests/benchmarks/corelib/time/qdatetime/main.cpp diff --git a/tests/benchmarks/corelib/tools/qdatetime/qdatetime.pro b/tests/benchmarks/corelib/time/qdatetime/qdatetime.pro similarity index 100% rename from tests/benchmarks/corelib/tools/qdatetime/qdatetime.pro rename to tests/benchmarks/corelib/time/qdatetime/qdatetime.pro diff --git a/tests/benchmarks/corelib/tools/qtimezone/main.cpp b/tests/benchmarks/corelib/time/qtimezone/main.cpp similarity index 100% rename from tests/benchmarks/corelib/tools/qtimezone/main.cpp rename to tests/benchmarks/corelib/time/qtimezone/main.cpp diff --git a/tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro b/tests/benchmarks/corelib/time/qtimezone/qtimezone.pro similarity index 100% rename from tests/benchmarks/corelib/tools/qtimezone/qtimezone.pro rename to tests/benchmarks/corelib/time/qtimezone/qtimezone.pro diff --git a/tests/benchmarks/corelib/time/time.pro b/tests/benchmarks/corelib/time/time.pro new file mode 100644 index 0000000000..b5184845d9 --- /dev/null +++ b/tests/benchmarks/corelib/time/time.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs +SUBDIRS = \ + qdate \ + qdatetime \ + qtimezone diff --git a/tests/benchmarks/corelib/tools/tools.pro b/tests/benchmarks/corelib/tools/tools.pro index ca9c0a6f89..33cbe00438 100644 --- a/tests/benchmarks/corelib/tools/tools.pro +++ b/tests/benchmarks/corelib/tools/tools.pro @@ -5,7 +5,6 @@ SUBDIRS = \ qbytearray \ qcontiguouscache \ qcryptographichash \ - qdatetime \ qlist \ qlocale \ qmap \ @@ -15,7 +14,6 @@ SUBDIRS = \ qstring \ qstringbuilder \ qstringlist \ - qtimezone \ qvector \ qalgorithms diff --git a/util/locale_database/cldr2qtimezone.py b/util/locale_database/cldr2qtimezone.py index 256839317c..0817435d40 100755 --- a/util/locale_database/cldr2qtimezone.py +++ b/util/locale_database/cldr2qtimezone.py @@ -32,7 +32,7 @@ Script to parse the CLDR supplemental/windowsZones.xml file and encode for use in QTimeZone. See ``./cldr2qlocalexml.py`` for where to get the CLDR data. Pass its common/ directory as first parameter to this script and the qtbase root directory as second parameter. It shall -update qtbase's src/corelib/tools/qtimezoneprivate_data_p.h ready for +update qtbase's src/corelib/time/qtimezoneprivate_data_p.h ready for use. The XML structure is as follows: @@ -268,7 +268,7 @@ if not os.path.isdir(cldrPath) or not os.path.isdir(qtPath): windowsZonesPath = cldrPath + "/supplemental/windowsZones.xml" tempFileDir = qtPath -dataFilePath = qtPath + "/src/corelib/tools/qtimezoneprivate_data_p.h" +dataFilePath = qtPath + "/src/corelib/time/qtimezoneprivate_data_p.h" if not os.path.isfile(windowsZonesPath): usage() From e85aa551ebe5f882c9771dc3ea2b90b02b286a49 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 8 Apr 2019 17:05:28 +0200 Subject: [PATCH 098/122] vulkan: Add debug message filtering [ChangeLog][QtGui] Added support for filtering Vulkan debug messages in QVulkanInstance. This is especially useful for processing or suppressing messages from the validation layers. Change-Id: Idf0d7889085948daf5b1a53d2a9b11081e967609 Reviewed-by: Paul Olav Tvete --- src/gui/vulkan/qplatformvulkaninstance.cpp | 5 ++ src/gui/vulkan/qplatformvulkaninstance.h | 1 + src/gui/vulkan/qvulkaninstance.cpp | 46 +++++++++++++++++++ src/gui/vulkan/qvulkaninstance.h | 5 ++ .../qbasicvulkanplatforminstance.cpp | 16 +++++-- .../qbasicvulkanplatforminstance_p.h | 4 ++ 6 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/gui/vulkan/qplatformvulkaninstance.cpp b/src/gui/vulkan/qplatformvulkaninstance.cpp index 6201d3ec11..9d044bfd58 100644 --- a/src/gui/vulkan/qplatformvulkaninstance.cpp +++ b/src/gui/vulkan/qplatformvulkaninstance.cpp @@ -85,4 +85,9 @@ void QPlatformVulkanInstance::presentQueued(QWindow *window) Q_UNUSED(window); } +void QPlatformVulkanInstance::setDebugFilters(const QVector &filters) +{ + Q_UNUSED(filters); +} + QT_END_NAMESPACE diff --git a/src/gui/vulkan/qplatformvulkaninstance.h b/src/gui/vulkan/qplatformvulkaninstance.h index 9f34803f7b..d47c59b5db 100644 --- a/src/gui/vulkan/qplatformvulkaninstance.h +++ b/src/gui/vulkan/qplatformvulkaninstance.h @@ -78,6 +78,7 @@ public: virtual PFN_vkVoidFunction getInstanceProcAddr(const char *name) = 0; virtual bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) = 0; virtual void presentQueued(QWindow *window); + virtual void setDebugFilters(const QVector &filters); private: QScopedPointer d_ptr; diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp index 2941bfd01f..0605d88cca 100644 --- a/src/gui/vulkan/qvulkaninstance.cpp +++ b/src/gui/vulkan/qvulkaninstance.cpp @@ -269,6 +269,7 @@ public: VkResult errorCode; QScopedPointer funcs; QHash deviceFuncs; + QVector debugFilters; }; bool QVulkanInstancePrivate::ensureVulkan() @@ -570,6 +571,7 @@ bool QVulkanInstance::create() d_ptr->extensions = d_ptr->platformInst->enabledExtensions(); d_ptr->errorCode = VK_SUCCESS; d_ptr->funcs.reset(new QVulkanFunctions(this)); + d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters); return true; } @@ -785,6 +787,50 @@ void QVulkanInstance::presentQueued(QWindow *window) d_ptr->platformInst->presentQueued(window); } +/*! + \typedef QVulkanInstance::DebugFilter + + Typedef for debug filtering callback functions. + + \sa installDebugOutputFilter(), removeDebugOutputFilter() + */ + +/*! + Installs a \a filter function that is called for every Vulkan debug + message. When the callback returns \c true, the message is stopped (filtered + out) and will not appear on the debug output. + + \note Filtering is only effective when NoDebugOutputRedirect is not + \l{setFlags()}{set}. Installing filters has no effect otherwise. + + \note This function can be called before create(). + + \sa removeDebugOutputFilter() + */ +void QVulkanInstance::installDebugOutputFilter(DebugFilter filter) +{ + if (!d_ptr->debugFilters.contains(filter)) { + d_ptr->debugFilters.append(filter); + if (d_ptr->platformInst) + d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters); + } +} + +/*! + Removes a \a filter function previously installed by + installDebugOutputFilter(). + + \note This function can be called before create(). + + \sa installDebugOutputFilter() + */ +void QVulkanInstance::removeDebugOutputFilter(DebugFilter filter) +{ + d_ptr->debugFilters.removeOne(filter); + if (d_ptr->platformInst) + d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters); +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug dbg, const QVulkanLayer &layer) { diff --git a/src/gui/vulkan/qvulkaninstance.h b/src/gui/vulkan/qvulkaninstance.h index f28975f911..70f2fd5102 100644 --- a/src/gui/vulkan/qvulkaninstance.h +++ b/src/gui/vulkan/qvulkaninstance.h @@ -188,6 +188,11 @@ public: void presentQueued(QWindow *window); + typedef bool (*DebugFilter)(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, + size_t location, int32_t messageCode, const char *pLayerPrefix, const char *pMessage); + void installDebugOutputFilter(DebugFilter filter); + void removeDebugOutputFilter(DebugFilter filter); + private: QScopedPointer d_ptr; Q_DISABLE_COPY(QVulkanInstance) diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp index b9c5669b3f..68340a3173 100644 --- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp +++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp @@ -330,6 +330,11 @@ bool QBasicPlatformVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevi return supported; } +void QBasicPlatformVulkanInstance::setDebugFilters(const QVector &filters) +{ + m_debugFilters = filters; +} + void QBasicPlatformVulkanInstance::destroySurface(VkSurfaceKHR surface) const { if (m_destroySurface && surface) @@ -345,11 +350,11 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugReportFlag const char *pMessage, void *pUserData) { - Q_UNUSED(flags); - Q_UNUSED(objectType); - Q_UNUSED(object); - Q_UNUSED(location); - Q_UNUSED(pUserData); + QBasicPlatformVulkanInstance *self = static_cast(pUserData); + for (QVulkanInstance::DebugFilter filter : *self->debugFilters()) { + if (filter(flags, objectType, object, location, messageCode, pLayerPrefix, pMessage)) + return VK_FALSE; + } // not categorized, just route to plain old qDebug qDebug("vkDebug: %s: %d: %s", pLayerPrefix, messageCode, pMessage); @@ -374,6 +379,7 @@ void QBasicPlatformVulkanInstance::setupDebugOutput() | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; dbgCallbackInfo.pfnCallback = defaultDebugCallbackFunc; + dbgCallbackInfo.pUserData = this; VkResult err = createDebugReportCallback(m_vkInst, &dbgCallbackInfo, nullptr, &m_debugCallback); if (err != VK_SUCCESS) diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h index 566140b032..e59d9219fb 100644 --- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h +++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h @@ -73,7 +73,10 @@ public: QByteArrayList enabledExtensions() const override; PFN_vkVoidFunction getInstanceProcAddr(const char *name) override; bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override; + void setDebugFilters(const QVector &filters) override; + void destroySurface(VkSurfaceKHR surface) const; + const QVector *debugFilters() const { return &m_debugFilters; } protected: void loadVulkanLibrary(const QString &defaultLibraryName); @@ -105,6 +108,7 @@ private: VkDebugReportCallbackEXT m_debugCallback; PFN_vkDestroyDebugReportCallbackEXT m_vkDestroyDebugReportCallbackEXT; + QVector m_debugFilters; }; QT_END_NAMESPACE From 27e723496351bf4077b3f5e548fddb252e032579 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 24 May 2019 16:34:40 +0200 Subject: [PATCH 099/122] Windows QPA: Fix clang warnings about using typedef Replace by using (except for function pointers). Change-Id: I0dfe03c22f9f87155003d13a6376381623df7217 Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowscursor.h | 2 +- .../platforms/windows/qwindowsdialoghelpers.cpp | 10 +++++----- src/plugins/platforms/windows/qwindowsdialoghelpers.h | 2 +- src/plugins/platforms/windows/qwindowsmenu.h | 4 ++-- src/plugins/platforms/windows/qwindowsmousehandler.cpp | 4 ++-- src/plugins/platforms/windows/qwindowsscreen.cpp | 2 +- src/plugins/platforms/windows/qwindowsscreen.h | 4 ++-- .../platforms/windows/qwindowssystemtrayicon.cpp | 2 +- src/plugins/platforms/windows/qwindowswindow.cpp | 4 ++-- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index d5c189b5ca..b896f4c7a9 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -84,7 +84,7 @@ private: const HCURSOR m_hcursor; }; -typedef QSharedPointer CursorHandlePtr; +using CursorHandlePtr = QSharedPointer; class QWindowsCursor : public QPlatformCursor { diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index e55b8fd7b8..57f19b5ff2 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -271,7 +271,7 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase::ensureNativeDialo class QWindowsDialogThread : public QThread { public: - typedef QSharedPointer QWindowsNativeDialogBasePtr; + using QWindowsNativeDialogBasePtr = QSharedPointer; explicit QWindowsDialogThread(const QWindowsNativeDialogBasePtr &d, HWND owner) : m_dialog(d), m_owner(owner) {} @@ -551,7 +551,7 @@ IFileDialogEvents *QWindowsNativeFileDialogEventHandler::create(QWindowsNativeFi class QWindowsShellItem { public: - typedef std::vector IShellItems; + using IShellItems = std::vector; explicit QWindowsShellItem(IShellItem *item); @@ -1688,7 +1688,7 @@ class QWindowsXpNativeFileDialog : public QWindowsNativeDialogBase { Q_OBJECT public: - typedef QSharedPointer OptionsPtr; + using OptionsPtr = QSharedPointer; static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data); @@ -1779,7 +1779,7 @@ static int QT_WIN_CALLBACK xpFileDialogGetExistingDirCallbackProc(HWND hwnd, UIN #if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3) typedef ITEMIDLIST *qt_LpItemIdList; #else -typedef PIDLIST_ABSOLUTE qt_LpItemIdList; +using qt_LpItemIdList = PIDLIST_ABSOLUTE; #endif int QWindowsXpNativeFileDialog::existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam) @@ -2007,7 +2007,7 @@ QString QWindowsXpFileDialogHelper::selectedNameFilter() const \ingroup qt-lighthouse-win */ -typedef QSharedPointer SharedPointerColor; +using SharedPointerColor = QSharedPointer; #ifdef USE_NATIVE_COLOR_DIALOG class QWindowsNativeColorDialog : public QWindowsNativeDialogBase diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h index f0a7ef5e90..8686749011 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h @@ -66,7 +66,7 @@ class QWindowsDialogHelperBase : public BaseClass { Q_DISABLE_COPY_MOVE(QWindowsDialogHelperBase) public: - typedef QSharedPointer QWindowsNativeDialogBasePtr; + using QWindowsNativeDialogBasePtr = QSharedPointer; ~QWindowsDialogHelperBase() { cleanupThread(); } void exec() override; diff --git a/src/plugins/platforms/windows/qwindowsmenu.h b/src/plugins/platforms/windows/qwindowsmenu.h index 6de1553f35..aa36846ec0 100644 --- a/src/plugins/platforms/windows/qwindowsmenu.h +++ b/src/plugins/platforms/windows/qwindowsmenu.h @@ -120,7 +120,7 @@ class QWindowsMenu : public QPlatformMenu { Q_OBJECT public: - typedef QVector MenuItems; + using MenuItems = QVector; QWindowsMenu(); ~QWindowsMenu(); @@ -196,7 +196,7 @@ class QWindowsMenuBar : public QPlatformMenuBar { Q_OBJECT public: - typedef QVector Menus; + using Menus = QVector; QWindowsMenuBar(); ~QWindowsMenuBar() override; diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 97e1319e8d..c15819a65f 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -609,8 +609,8 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, QtWindows::WindowsEventType, MSG msg, LRESULT *) { - typedef QWindowSystemInterface::TouchPoint QTouchPoint; - typedef QList QTouchPointList; + using QTouchPoint = QWindowSystemInterface::TouchPoint; + using QTouchPointList = QList; if (!QWindowsContext::instance()->initTouch()) { qWarning("Unable to initialize touch handling."); diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 2f8850cbe0..e3931b3bb1 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -72,7 +72,7 @@ static inline QDpi monitorDPI(HMONITOR hMonitor) return {0, 0}; } -typedef QList WindowsScreenDataList; +using WindowsScreenDataList = QList; static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data) { diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 3eb2d35b27..0ccebf6d71 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -76,7 +76,7 @@ class QWindowsScreen : public QPlatformScreen { public: #ifndef QT_NO_CURSOR - typedef QScopedPointer CursorPtr; + using CursorPtr = QScopedPointer; #endif explicit QWindowsScreen(const QWindowsScreenData &data); @@ -127,7 +127,7 @@ private: class QWindowsScreenManager { public: - typedef QList WindowsScreenList; + using WindowsScreenList = QList; QWindowsScreenManager(); diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp index c0f4e4d014..f2dba4d06b 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp @@ -117,7 +117,7 @@ struct QWindowsHwndSystemTrayIconEntry QWindowsSystemTrayIcon *trayIcon; }; -typedef QVector HwndTrayIconEntries; +using HwndTrayIconEntries = QVector; Q_GLOBAL_STATIC(HwndTrayIconEntries, hwndTrayIconEntries) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 174c63bbbd..3669407765 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -86,7 +86,7 @@ QT_BEGIN_NAMESPACE -typedef QSharedPointer QWindowCreationContextPtr; +using QWindowCreationContextPtr = QSharedPointer; enum { defaultWindowWidth = 160, @@ -494,7 +494,7 @@ static QMargins invisibleMargins(QPoint screenPoint) struct WindowCreationData { - typedef QWindowsWindowData WindowData; + using WindowData = QWindowsWindowData; enum Flags { ForceChild = 0x1, ForceTopLevel = 0x2 }; void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0); From a3b931e7c4a5702da5fd99df0746f9ff511b7fdc Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 28 May 2019 11:53:05 +0200 Subject: [PATCH 100/122] Construct from an array instead of assigning just past a string's end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assigning past the end used to be supported, but isn't a good way to do the job. Exposed by a qtxmlpatterns test that exercised this code, which gets a warning thanks to Giuseppe's recent changes to QCharRef. Task-number: QTBUG-76070 Change-Id: Ic254c7ffce60e3b2aafce76ab03ea5db8c68fafc Reviewed-by: Giuseppe D'Angelo Reviewed-by: Mårten Nordheim --- src/network/access/qftp.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp index b6b721030b..cc230a5411 100644 --- a/src/network/access/qftp.cpp +++ b/src/network/access/qftp.cpp @@ -955,11 +955,9 @@ void QFtpPI::readyRead() } } } - QString endOfMultiLine; - endOfMultiLine[0] = '0' + replyCode[0]; - endOfMultiLine[1] = '0' + replyCode[1]; - endOfMultiLine[2] = '0' + replyCode[2]; - endOfMultiLine[3] = QLatin1Char(' '); + const char count[4] = { char('0' + replyCode[0]), char('0' + replyCode[1]), + char('0' + replyCode[2]), char(' ') }; + QString endOfMultiLine(QLatin1String(count, 4)); QString lineCont(endOfMultiLine); lineCont[3] = QLatin1Char('-'); QStringRef lineLeft4 = line.leftRef(4); From c7e6407f84eb51db64871a001dc44010d822061c Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 29 May 2019 12:22:09 +0200 Subject: [PATCH 101/122] Move container block-size calculations to qarraydata.cpp These were in qbytearray.cpp, which doesn't use them, is big and I intend to move it to a different directory than the header, qtools_p.h, that declares them. So move them to a small file that does use them. Change-Id: I5a4684f8c7628e617546019cc3f01d92d829f085 Reviewed-by: Thiago Macieira --- src/corelib/tools/qarraydata.cpp | 105 ++++++++++++++++++++++++++++++- src/corelib/tools/qbytearray.cpp | 102 +----------------------------- src/corelib/tools/qtools_p.h | 4 +- 3 files changed, 107 insertions(+), 104 deletions(-) diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index bcc0688a91..88d8b8244d 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -41,11 +41,114 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE +/* + * This pair of functions is declared in qtools_p.h and is used by the Qt + * containers to allocate memory and grow the memory block during append + * operations. + * + * They take size_t parameters and return size_t so they will change sizes + * according to the pointer width. However, knowing Qt containers store the + * container size and element indexes in ints, these functions never return a + * size larger than INT_MAX. This is done by casting the element count and + * memory block size to int in several comparisons: the check for negative is + * very fast on most platforms as the code only needs to check the sign bit. + * + * These functions return SIZE_MAX on overflow, which can be passed to malloc() + * and will surely cause a NULL return (there's no way you can allocate a + * memory block the size of your entire VM space). + */ + +/*! + \internal + \since 5.7 + + Returns the memory block size for a container containing \a elementCount + elements, each of \a elementSize bytes, plus a header of \a headerSize + bytes. That is, this function returns \c + {elementCount * elementSize + headerSize} + + but unlike the simple calculation, it checks for overflows during the + multiplication and the addition. + + Both \a elementCount and \a headerSize can be zero, but \a elementSize + cannot. + + This function returns SIZE_MAX (~0) on overflow or if the memory block size + would not fit an int. +*/ +size_t qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept +{ + unsigned count = unsigned(elementCount); + unsigned size = unsigned(elementSize); + unsigned header = unsigned(headerSize); + Q_ASSERT(elementSize); + Q_ASSERT(size == elementSize); + Q_ASSERT(header == headerSize); + + if (Q_UNLIKELY(count != elementCount)) + return std::numeric_limits::max(); + + unsigned bytes; + if (Q_UNLIKELY(mul_overflow(size, count, &bytes)) || + Q_UNLIKELY(add_overflow(bytes, header, &bytes))) + return std::numeric_limits::max(); + if (Q_UNLIKELY(int(bytes) < 0)) // catches bytes >= 2GB + return std::numeric_limits::max(); + + return bytes; +} + +/*! + \internal + \since 5.7 + + Returns the memory block size and the number of elements that will fit in + that block for a container containing \a elementCount elements, each of \a + elementSize bytes, plus a header of \a headerSize bytes. This function + assumes the container will grow and pre-allocates a growth factor. + + Both \a elementCount and \a headerSize can be zero, but \a elementSize + cannot. + + This function returns SIZE_MAX (~0) on overflow or if the memory block size + would not fit an int. + + \note The memory block may contain up to \a elementSize - 1 bytes more than + needed. +*/ +CalculateGrowingBlockSizeResult +qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept +{ + CalculateGrowingBlockSizeResult result = { + std::numeric_limits::max(),std::numeric_limits::max() + }; + + unsigned bytes = unsigned(qCalculateBlockSize(elementCount, elementSize, headerSize)); + if (int(bytes) < 0) // catches std::numeric_limits::max() + return result; + + unsigned morebytes = qNextPowerOfTwo(bytes); + if (Q_UNLIKELY(int(morebytes) < 0)) { + // catches morebytes == 2GB + // grow by half the difference between bytes and morebytes + bytes += (morebytes - bytes) / 2; + } else { + bytes = morebytes; + } + + result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize); + result.size = bytes; + return result; +} + +// End of qtools_p.h implementation + QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers") diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 9816b5cb32..5c2af7e058 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -130,106 +130,6 @@ int qFindByteArray( const char *haystack0, int haystackLen, int from, const char *needle0, int needleLen); -/* - * This pair of functions is declared in qtools_p.h and is used by the Qt - * containers to allocate memory and grow the memory block during append - * operations. - * - * They take size_t parameters and return size_t so they will change sizes - * according to the pointer width. However, knowing Qt containers store the - * container size and element indexes in ints, these functions never return a - * size larger than INT_MAX. This is done by casting the element count and - * memory block size to int in several comparisons: the check for negative is - * very fast on most platforms as the code only needs to check the sign bit. - * - * These functions return SIZE_MAX on overflow, which can be passed to malloc() - * and will surely cause a NULL return (there's no way you can allocate a - * memory block the size of your entire VM space). - */ - -/*! - \internal - \since 5.7 - - Returns the memory block size for a container containing \a elementCount - elements, each of \a elementSize bytes, plus a header of \a headerSize - bytes. That is, this function returns \c - {elementCount * elementSize + headerSize} - - but unlike the simple calculation, it checks for overflows during the - multiplication and the addition. - - Both \a elementCount and \a headerSize can be zero, but \a elementSize - cannot. - - This function returns SIZE_MAX (~0) on overflow or if the memory block size - would not fit an int. -*/ -size_t qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept -{ - unsigned count = unsigned(elementCount); - unsigned size = unsigned(elementSize); - unsigned header = unsigned(headerSize); - Q_ASSERT(elementSize); - Q_ASSERT(size == elementSize); - Q_ASSERT(header == headerSize); - - if (Q_UNLIKELY(count != elementCount)) - return std::numeric_limits::max(); - - unsigned bytes; - if (Q_UNLIKELY(mul_overflow(size, count, &bytes)) || - Q_UNLIKELY(add_overflow(bytes, header, &bytes))) - return std::numeric_limits::max(); - if (Q_UNLIKELY(int(bytes) < 0)) // catches bytes >= 2GB - return std::numeric_limits::max(); - - return bytes; -} - -/*! - \internal - \since 5.7 - - Returns the memory block size and the number of elements that will fit in - that block for a container containing \a elementCount elements, each of \a - elementSize bytes, plus a header of \a headerSize bytes. This function - assumes the container will grow and pre-allocates a growth factor. - - Both \a elementCount and \a headerSize can be zero, but \a elementSize - cannot. - - This function returns SIZE_MAX (~0) on overflow or if the memory block size - would not fit an int. - - \note The memory block may contain up to \a elementSize - 1 bytes more than - needed. -*/ -CalculateGrowingBlockSizeResult -qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) noexcept -{ - CalculateGrowingBlockSizeResult result = { - std::numeric_limits::max(),std::numeric_limits::max() - }; - - unsigned bytes = unsigned(qCalculateBlockSize(elementCount, elementSize, headerSize)); - if (int(bytes) < 0) // catches std::numeric_limits::max() - return result; - - unsigned morebytes = qNextPowerOfTwo(bytes); - if (Q_UNLIKELY(int(morebytes) < 0)) { - // catches morebytes == 2GB - // grow by half the difference between bytes and morebytes - bytes += (morebytes - bytes) / 2; - } else { - bytes = morebytes; - } - - result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize); - result.size = bytes; - return result; -} - /***************************************************************************** Safe and portable C string functions; extensions to standard string.h *****************************************************************************/ diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h index b239987871..d48318b474 100644 --- a/src/corelib/tools/qtools_p.h +++ b/src/corelib/tools/qtools_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -96,7 +96,7 @@ struct CalculateGrowingBlockSizeResult { size_t elementCount; }; -// implemented in qbytearray.cpp +// Implemented in qarraydata.cpp: size_t Q_CORE_EXPORT Q_DECL_CONST_FUNCTION qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) noexcept; CalculateGrowingBlockSizeResult Q_CORE_EXPORT Q_DECL_CONST_FUNCTION From 325d5b58a25a2893261c2c69fc8381abc87cceac Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 28 May 2019 17:39:14 +0200 Subject: [PATCH 102/122] Regenerate Windows Time Zone ID table Re-ran util/locale_database/cldr2qtimezone.py to add new zones to the table. Change-Id: I70258a9abbe9815494291deff528f3c18703de40 Reviewed-by: Thiago Macieira --- src/corelib/tools/qtimezoneprivate_data_p.h | 2101 ++++++++++--------- 1 file changed, 1102 insertions(+), 999 deletions(-) diff --git a/src/corelib/tools/qtimezoneprivate_data_p.h b/src/corelib/tools/qtimezoneprivate_data_p.h index 5cedac3b49..40d6c972c2 100644 --- a/src/corelib/tools/qtimezoneprivate_data_p.h +++ b/src/corelib/tools/qtimezoneprivate_data_p.h @@ -114,8 +114,8 @@ struct QUtcData { // GENERATED PART STARTS HERE /* - This part of the file was generated on 2017-05-23 from the - Common Locale Data Repository v29 supplemental/windowsZones.xml file $Revision: 12348 $ + This part of the file was generated on 2019-05-28 from the + Common Locale Data Repository v35.1 supplemental/windowsZones.xml file $Revision: 14742 $ http://www.unicode.org/cldr/ @@ -125,1027 +125,1130 @@ struct QUtcData { // Windows ID Key, Country Enum, IANA ID Index static const QZoneData zoneDataTable[] = { - { 22, 57, 0 }, // Central Europe Standard Time / CzechRepublic - { 69, 139, 14 }, // Pacific Standard Time / Mexico - { 53, 188, 51 }, // Mauritius Standard Time / Seychelles - { 50, 122, 63 }, // Libya Standard Time / Libya - { 79, 38, 78 }, // SA Western Standard Time / Canada - { 83, 35, 99 }, // South Africa Standard Time / Burundi - { 102, 205, 116 }, // W. Europe Standard Time / Sweden - { 89, 213, 133 }, // Tonga Standard Time / Tokelau - { 77, 76, 149 }, // SA Eastern Standard Time / FrenchGuiana - { 79, 215, 165 }, // SA Western Standard Time / TrinidadAndTobago - { 69, 38, 187 }, // Pacific Standard Time / Canada - { 97, 0, 239 }, // UTC+12 / AnyCountry - { 19, 65, 250 }, // Central America Standard Time / ElSalvador - { 82, 101, 270 }, // Singapore Standard Time / Indonesia - { 37, 248, 284 }, // FLE Standard Time / AlandIslands - { 16, 0, 301 }, // Cape Verde Standard Time / AnyCountry - { 97, 220, 311 }, // UTC+12 / Tuvalu - { 79, 182, 328 }, // SA Western Standard Time / SaintVincentAndTheGrenadines - { 83, 179, 347 }, // South Africa Standard Time / Rwanda - { 102, 125, 361 }, // W. Europe Standard Time / Luxembourg - { 41, 34, 379 }, // Greenwich Standard Time / BurkinaFaso - { 20, 116, 398 }, // Central Asia Standard Time / Kyrgyzstan - { 101, 216, 411 }, // W. Central Africa Standard Time / Tunisia - { 101, 79, 424 }, // W. Central Africa Standard Time / Gabon - { 19, 96, 442 }, // Central America Standard Time / Honduras - { 81, 36, 462 }, // SE Asia Standard Time / Cambodia - { 82, 170, 478 }, // Singapore Standard Time / Philippines - { 101, 41, 490 }, // W. Central Africa Standard Time / CentralAfricanRepublic - { 5, 103, 504 }, // Arabic Standard Time / Iraq - { 72, 21, 517 }, // Romance Standard Time / Belgium - { 74, 178, 533 }, // Russia Time Zone 10 / Russia - { 20, 44, 552 }, // Central Asia Standard Time / China - { 3, 17, 564 }, // Arab Standard Time / Bahrain - { 88, 62, 577 }, // Tokyo Standard Time / EastTimor - { 37, 68, 587 }, // FLE Standard Time / Estonia - { 41, 136, 602 }, // Greenwich Standard Time / Mauritania - { 83, 49, 620 }, // South Africa Standard Time / CongoKinshasa - { 72, 74, 638 }, // Romance Standard Time / France - { 35, 178, 651 }, // Ekaterinburg Standard Time / Russia - { 32, 16, 670 }, // Eastern Standard Time / Bahamas - { 94, 30, 685 }, // UTC-02 / Brazil - { 12, 30, 701 }, // Bahia Standard Time / Brazil - { 82, 0, 715 }, // Singapore Standard Time / AnyCountry - { 29, 201, 725 }, // E. Africa Standard Time / Sudan - { 24, 229, 741 }, // Central Pacific Standard Time / Vanuatu - { 55, 227, 755 }, // Montevideo Standard Time / Uruguay - { 79, 233, 774 }, // SA Western Standard Time / BritishVirginIslands - { 29, 221, 790 }, // E. Africa Standard Time / Uganda - { 101, 6, 805 }, // W. Central Africa Standard Time / Angola - { 68, 141, 819 }, // E. Europe Standard Time / Moldova - { 51, 112, 835 }, // Line Islands Standard Time / Kiribati - { 89, 0, 854 }, // Tonga Standard Time / AnyCountry - { 79, 61, 865 }, // SA Western Standard Time / DominicanRepublic - { 39, 75, 887 }, // GMT Standard Time / Guernsey - { 37, 222, 903 }, // FLE Standard Time / Ukraine - { 83, 28, 949 }, // South Africa Standard Time / Botswana - { 82, 130, 965 }, // Singapore Standard Time / Malaysia - { 95, 4, 996 }, // UTC-11 / AmericanSamoa - { 41, 189, 1014 }, // Greenwich Standard Time / SierraLeone - { 29, 194, 1030 }, // E. Africa Standard Time / Somalia - { 94, 196, 1047 }, // UTC-02 / SouthGeorgiaAndTheSouthSandwichIslands - { 96, 0, 1070 }, // UTC / AnyCountry - { 101, 37, 1078 }, // W. Central Africa Standard Time / Cameroon - { 13, 25, 1092 }, // Bangladesh Standard Time / Bhutan - { 102, 151, 1105 }, // W. Europe Standard Time / Netherlands - { 37, 118, 1122 }, // FLE Standard Time / Latvia - { 29, 48, 1134 }, // E. Africa Standard Time / Comoros - { 60, 178, 1148 }, // N. Central Asia Standard Time / Russia - { 81, 117, 1175 }, // SE Asia Standard Time / Laos - { 22, 242, 1190 }, // Central Europe Standard Time / Montenegro - { 37, 33, 1207 }, // FLE Standard Time / Bulgaria - { 11, 173, 1220 }, // Azores Standard Time / Portugal - { 97, 149, 1236 }, // UTC+12 / Nauru - { 83, 146, 1250 }, // South Africa Standard Time / Mozambique - { 102, 82, 1264 }, // W. Europe Standard Time / Germany - { 79, 255, 1294 }, // SA Western Standard Time / Bonaire - { 24, 153, 1313 }, // Central Pacific Standard Time / NewCaledonia - { 45, 102, 1328 }, // Iran Standard Time / Iran - { 13, 18, 1340 }, // Bangladesh Standard Time / Bangladesh - { 69, 225, 1351 }, // Pacific Standard Time / UnitedStates - { 102, 142, 1371 }, // W. Europe Standard Time / Monaco - { 29, 128, 1385 }, // E. Africa Standard Time / Madagascar - { 65, 178, 1405 }, // North Asia East Standard Time / Russia - { 20, 8, 1418 }, // Central Asia Standard Time / Antarctica - { 22, 2, 1436 }, // Central Europe Standard Time / Albania - { 79, 87, 1450 }, // SA Western Standard Time / Grenada - { 81, 0, 1466 }, // SE Asia Standard Time / AnyCountry - { 39, 173, 1476 }, // GMT Standard Time / Portugal - { 103, 228, 1507 }, // West Asia Standard Time / Uzbekistan - { 58, 139, 1536 }, // Mountain Standard Time / Mexico - { 83, 129, 1552 }, // South Africa Standard Time / Malawi - { 78, 107, 1568 }, // SA Pacific Standard Time / Jamaica - { 41, 91, 1584 }, // Greenwich Standard Time / Guinea - { 101, 49, 1599 }, // W. Central Africa Standard Time / CongoKinshasa - { 43, 226, 1615 }, // Hawaiian Standard Time / UnitedStatesMinorOutlyingIslands - { 77, 8, 1632 }, // SA Eastern Standard Time / Antarctica - { 97, 235, 1651 }, // UTC+12 / WallisAndFutunaIslands - { 81, 232, 1666 }, // SE Asia Standard Time / Vietnam - { 34, 64, 1678 }, // Egypt Standard Time / Egypt - { 102, 106, 1691 }, // W. Europe Standard Time / Italy - { 79, 256, 1703 }, // SA Western Standard Time / SintMaarten - { 59, 147, 1725 }, // Myanmar Standard Time / Myanmar - { 78, 166, 1738 }, // SA Pacific Standard Time / Panama - { 56, 236, 1753 }, // Morocco Standard Time / WesternSahara - { 24, 193, 1769 }, // Central Pacific Standard Time / SolomonIslands - { 48, 178, 1789 }, // Kaliningrad Standard Time / Russia - { 47, 109, 1808 }, // Jordan Standard Time / Jordan - { 42, 177, 1819 }, // GTB Standard Time / Romania - { 41, 92, 1836 }, // Greenwich Standard Time / GuineaBissau - { 102, 184, 1850 }, // W. Europe Standard Time / SanMarino - { 103, 209, 1868 }, // West Asia Standard Time / Tajikistan - { 75, 178, 1882 }, // Russia Time Zone 11 / Russia - { 101, 157, 1909 }, // W. Central Africa Standard Time / Nigeria - { 79, 152, 1922 }, // SA Western Standard Time / CuraSao - { 57, 139, 1938 }, // Mountain Standard Time (Mexico) / Mexico - { 4, 162, 1973 }, // Arabian Standard Time / Oman - { 78, 169, 1985 }, // SA Pacific Standard Time / Peru - { 102, 206, 1998 }, // W. Europe Standard Time / Switzerland - { 41, 99, 2012 }, // Greenwich Standard Time / Iceland - { 33, 139, 2031 }, // Eastern Standard Time (Mexico) / Mexico - { 58, 225, 2046 }, // Mountain Standard Time / UnitedStates - { 100, 8, 2075 }, // W. Australia Standard Time / Antarctica - { 79, 30, 2092 }, // SA Western Standard Time / Brazil - { 101, 23, 2145 }, // W. Central Africa Standard Time / Benin - { 78, 43, 2163 }, // SA Pacific Standard Time / Chile - { 104, 0, 2178 }, // West Pacific Standard Time / AnyCountry - { 79, 181, 2189 }, // SA Western Standard Time / SaintLucia - { 27, 126, 2206 }, // China Standard Time / Macau - { 101, 66, 2217 }, // W. Central Africa Standard Time / EquatorialGuinea - { 43, 51, 2231 }, // Hawaiian Standard Time / CookIslands - { 41, 80, 2249 }, // Greenwich Standard Time / Gambia - { 51, 0, 2263 }, // Line Islands Standard Time / AnyCountry - { 52, 178, 2274 }, // Magadan Standard Time / Russia - { 22, 191, 2287 }, // Central Europe Standard Time / Slovakia - { 102, 5, 2305 }, // W. Europe Standard Time / Andorra - { 81, 211, 2320 }, // SE Asia Standard Time / Thailand - { 103, 0, 2333 }, // West Asia Standard Time / AnyCountry - { 24, 167, 2343 }, // Central Pacific Standard Time / PapuaNewGuinea - { 102, 230, 2364 }, // W. Europe Standard Time / VaticanCityState - { 58, 38, 2379 }, // Mountain Standard Time / Canada - { 77, 202, 2453 }, // SA Eastern Standard Time / Suriname - { 9, 13, 2472 }, // AUS Eastern Standard Time / Australia - { 29, 210, 2509 }, // E. Africa Standard Time / Tanzania - { 58, 0, 2530 }, // Mountain Standard Time / AnyCountry - { 83, 120, 2538 }, // South Africa Standard Time / Lesotho - { 97, 134, 2552 }, // UTC+12 / MarshallIslands - { 29, 111, 2585 }, // E. Africa Standard Time / Kenya - { 103, 218, 2600 }, // West Asia Standard Time / Turkmenistan - { 27, 97, 2614 }, // China Standard Time / HongKong - { 29, 0, 2629 }, // E. Africa Standard Time / AnyCountry - { 19, 22, 2639 }, // Central America Standard Time / Belize - { 31, 30, 2654 }, // E. South America Standard Time / Brazil - { 72, 197, 2672 }, // Romance Standard Time / Spain - { 81, 101, 2699 }, // SE Asia Standard Time / Indonesia - { 88, 0, 2727 }, // Tokyo Standard Time / AnyCountry - { 2, 225, 2737 }, // Alaskan Standard Time / UnitedStates - { 72, 58, 2832 }, // Romance Standard Time / Denmark - { 63, 8, 2850 }, // New Zealand Standard Time / Antarctica - { 3, 175, 2869 }, // Arab Standard Time / Qatar - { 79, 245, 2880 }, // SA Western Standard Time / Saint Martin - { 79, 19, 2896 }, // SA Western Standard Time / Barbados - { 97, 226, 2913 }, // UTC+12 / UnitedStatesMinorOutlyingIslands - { 37, 73, 2926 }, // FLE Standard Time / Finland - { 29, 138, 2942 }, // E. Africa Standard Time / Mayotte - { 39, 71, 2957 }, // GMT Standard Time / FaroeIslands - { 78, 38, 2973 }, // SA Pacific Standard Time / Canada - { 43, 0, 2995 }, // Hawaiian Standard Time / AnyCountry - { 23, 27, 3006 }, // Central European Standard Time / BosniaAndHerzegowina - { 38, 81, 3022 }, // Georgian Standard Time / Georgia - { 95, 0, 3035 }, // UTC-11 / AnyCountry - { 24, 13, 3046 }, // Central Pacific Standard Time / Australia - { 104, 167, 3067 }, // West Pacific Standard Time / PapuaNewGuinea - { 71, 168, 3088 }, // Paraguay Standard Time / Paraguay - { 43, 77, 3105 }, // Hawaiian Standard Time / FrenchPolynesia - { 41, 212, 3120 }, // Greenwich Standard Time / Togo - { 39, 197, 3132 }, // GMT Standard Time / Spain - { 83, 195, 3148 }, // South Africa Standard Time / SouthAfrica - { 18, 13, 3168 }, // Cen. Australia Standard Time / Australia - { 104, 160, 3209 }, // West Pacific Standard Time / NorthernMarianaIslands - { 77, 70, 3224 }, // SA Eastern Standard Time / FalklandIslands - { 42, 56, 3241 }, // GTB Standard Time / Cyprus - { 4, 223, 3254 }, // Arabian Standard Time / UnitedArabEmirates - { 103, 78, 3265 }, // West Asia Standard Time / FrenchSouthernTerritories - { 101, 42, 3282 }, // W. Central Africa Standard Time / Chad - { 23, 127, 3298 }, // Central European Standard Time / Macedonia - { 3, 237, 3312 }, // Arab Standard Time / Yemen - { 80, 183, 3322 }, // Samoa Standard Time / Samoa - { 43, 225, 3335 }, // Hawaiian Standard Time / UnitedStates - { 28, 0, 3352 }, // Dateline Standard Time / AnyCountry - { 93, 139, 3363 }, // US Mountain Standard Time / Mexico - { 64, 38, 3382 }, // Newfoundland Standard Time / Canada - { 63, 154, 3399 }, // New Zealand Standard Time / NewZealand - { 76, 178, 3416 }, // Russian Standard Time / Russia - { 82, 190, 3465 }, // Singapore Standard Time / Singapore - { 1, 1, 3480 }, // Afghanistan Standard Time / Afghanistan - { 102, 133, 3491 }, // W. Europe Standard Time / Malta - { 79, 12, 3504 }, // SA Western Standard Time / Aruba - { 25, 139, 3518 }, // Central Standard Time (Mexico) / Mexico - { 39, 251, 3594 }, // GMT Standard Time / IsleOfMan - { 102, 123, 3613 }, // W. Europe Standard Time / Liechtenstein - { 77, 30, 3626 }, // SA Eastern Standard Time / Brazil - { 49, 114, 3723 }, // Korea Standard Time / SouthKorea - { 79, 88, 3734 }, // SA Western Standard Time / Guadeloupe - { 94, 0, 3753 }, // UTC-02 / AnyCountry - { 59, 46, 3763 }, // Myanmar Standard Time / CocosIslands - { 102, 203, 3776 }, // W. Europe Standard Time / SvalbardAndJanMayenIslands - { 29, 69, 3796 }, // E. Africa Standard Time / Ethiopia - { 73, 178, 3815 }, // Russia Time Zone 3 / Russia - { 83, 240, 3829 }, // South Africa Standard Time / Zimbabwe - { 100, 13, 3843 }, // W. Australia Standard Time / Australia - { 101, 0, 3859 }, // W. Central Africa Standard Time / AnyCountry - { 32, 55, 3869 }, // Eastern Standard Time / Cuba - { 56, 145, 3884 }, // Morocco Standard Time / Morocco - { 17, 11, 3902 }, // Caucasus Standard Time / Armenia - { 7, 24, 3915 }, // Atlantic Standard Time / Bermuda - { 86, 208, 3932 }, // Taipei Standard Time / Taiwan - { 20, 0, 3944 }, // Central Asia Standard Time / AnyCountry - { 40, 86, 3954 }, // Greenland Standard Time / Greenland - { 23, 172, 3970 }, // Central European Standard Time / Poland - { 89, 214, 3984 }, // Tonga Standard Time / Tonga - { 20, 110, 4002 }, // Central Asia Standard Time / Kazakhstan - { 81, 8, 4029 }, // SE Asia Standard Time / Antarctica - { 54, 119, 4046 }, // Middle East Standard Time / Lebanon - { 19, 90, 4058 }, // Central America Standard Time / Guatemala - { 70, 163, 4076 }, // Pakistan Standard Time / Pakistan - { 41, 83, 4089 }, // Greenwich Standard Time / Ghana - { 79, 174, 4102 }, // SA Western Standard Time / PuertoRico - { 79, 26, 4122 }, // SA Western Standard Time / Bolivia - { 32, 225, 4137 }, // Eastern Standard Time / UnitedStates - { 85, 207, 4294 }, // Syria Standard Time / Syria - { 97, 112, 4308 }, // UTC+12 / Kiribati - { 79, 0, 4323 }, // SA Western Standard Time / AnyCountry - { 78, 47, 4333 }, // SA Pacific Standard Time / Colombia - { 16, 39, 4348 }, // Cape Verde Standard Time / CapeVerde - { 8, 13, 4368 }, // AUS Central Standard Time / Australia - { 106, 113, 4385 }, // North Korea Standard Time / NorthKorea - { 10, 15, 4400 }, // Azerbaijan Standard Time / Azerbaijan - { 102, 84, 4410 }, // W. Europe Standard Time / Gibraltar - { 46, 105, 4427 }, // Israel Standard Time / Israel - { 22, 192, 4442 }, // Central Europe Standard Time / Slovenia - { 24, 159, 4459 }, // Central Pacific Standard Time / NorfolkIsland - { 82, 32, 4475 }, // Singapore Standard Time / Brunei - { 101, 50, 4487 }, // W. Central Africa Standard Time / CongoBrazzaville - { 62, 150, 4506 }, // Nepal Standard Time / Nepal - { 44, 100, 4520 }, // India Standard Time / India - { 79, 9, 4534 }, // SA Western Standard Time / AntiguaAndBarbuda - { 39, 252, 4550 }, // GMT Standard Time / Jersey - { 79, 144, 4564 }, // SA Western Standard Time / Montserrat - { 93, 0, 4583 }, // US Mountain Standard Time / AnyCountry - { 79, 93, 4593 }, // SA Western Standard Time / Guyana - { 41, 187, 4608 }, // Greenwich Standard Time / Senegal - { 102, 161, 4621 }, // W. Europe Standard Time / Norway - { 42, 85, 4633 }, // GTB Standard Time / Greece - { 3, 115, 4647 }, // Arab Standard Time / Kuwait - { 24, 140, 4659 }, // Central Pacific Standard Time / Micronesia - { 19, 52, 4689 }, // Central America Standard Time / CostaRica - { 79, 60, 4708 }, // SA Western Standard Time / Dominica - { 83, 204, 4725 }, // South Africa Standard Time / Swaziland - { 79, 135, 4740 }, // SA Western Standard Time / Martinique - { 53, 176, 4759 }, // Mauritius Standard Time / Reunion - { 19, 0, 4774 }, // Central America Standard Time / AnyCountry - { 90, 217, 4784 }, // Turkey Standard Time / Turkey - { 66, 178, 4800 }, // North Asia Standard Time / Russia - { 41, 53, 4835 }, // Greenwich Standard Time / IvoryCoast - { 78, 30, 4850 }, // SA Pacific Standard Time / Brazil - { 26, 0, 4886 }, // Central Standard Time / AnyCountry - { 93, 225, 4894 }, // US Mountain Standard Time / UnitedStates - { 15, 38, 4910 }, // Canada Central Standard Time / Canada - { 78, 0, 4947 }, // SA Pacific Standard Time / AnyCountry - { 103, 8, 4957 }, // West Asia Standard Time / Antarctica - { 103, 131, 4975 }, // West Asia Standard Time / Maldives - { 22, 243, 4991 }, // Central Europe Standard Time / Serbia - { 29, 67, 5007 }, // E. Africa Standard Time / Eritrea - { 93, 38, 5021 }, // US Mountain Standard Time / Canada - { 22, 98, 5078 }, // Central Europe Standard Time / Hungary - { 61, 148, 5094 }, // Namibia Standard Time / Namibia - { 88, 101, 5110 }, // Tokyo Standard Time / Indonesia - { 30, 13, 5124 }, // E. Australia Standard Time / Australia - { 4, 0, 5162 }, // Arabian Standard Time / AnyCountry - { 98, 231, 5172 }, // Venezuela Standard Time / Venezuela - { 29, 8, 5188 }, // E. Africa Standard Time / Antarctica - { 23, 54, 5205 }, // Central European Standard Time / Croatia - { 6, 10, 5219 }, // Argentina Standard Time / Argentina - { 67, 8, 5492 }, // Pacific SA Standard Time / Antarctica - { 32, 38, 5510 }, // Eastern Standard Time / Canada - { 41, 132, 5615 }, // Greenwich Standard Time / Mali - { 3, 186, 5629 }, // Arab Standard Time / SaudiArabia - { 104, 140, 5641 }, // West Pacific Standard Time / Micronesia - { 88, 108, 5654 }, // Tokyo Standard Time / Japan - { 89, 112, 5665 }, // Tonga Standard Time / Kiribati - { 39, 224, 5683 }, // GMT Standard Time / UnitedKingdom - { 92, 225, 5697 }, // US Eastern Standard Time / UnitedStates - { 84, 198, 5764 }, // Sri Lanka Standard Time / SriLanka - { 26, 38, 5777 }, // Central Standard Time / Canada - { 29, 59, 5852 }, // E. Africa Standard Time / Djibouti - { 7, 38, 5868 }, // Atlantic Standard Time / Canada - { 41, 185, 5936 }, // Greenwich Standard Time / SaoTomeAndPrincipe - { 79, 234, 5952 }, // SA Western Standard Time / UnitedStatesVirginIslands - { 83, 239, 5970 }, // South Africa Standard Time / Zambia - { 32, 94, 5984 }, // Eastern Standard Time / Haiti - { 101, 156, 6007 }, // W. Central Africa Standard Time / Niger - { 77, 0, 6021 }, // SA Eastern Standard Time / AnyCountry - { 101, 3, 6031 }, // W. Central Africa Standard Time / Algeria - { 78, 63, 6046 }, // SA Pacific Standard Time / Ecuador - { 20, 31, 6064 }, // Central Asia Standard Time / BritishIndianOceanTerritory - { 27, 44, 6078 }, // China Standard Time / China - { 21, 30, 6092 }, // Central Brazilian Standard Time / Brazil - { 95, 226, 6128 }, // UTC-11 / UnitedStatesMinorOutlyingIslands - { 32, 0, 6143 }, // Eastern Standard Time / AnyCountry - { 81, 45, 6151 }, // SE Asia Standard Time / ChristmasIsland - { 19, 63, 6168 }, // Central America Standard Time / Ecuador - { 79, 7, 6186 }, // SA Western Standard Time / Anguilla - { 78, 40, 6203 }, // SA Pacific Standard Time / CaymanIslands - { 79, 180, 6218 }, // SA Western Standard Time / SaintKittsAndNevis - { 67, 43, 6235 }, // Pacific SA Standard Time / Chile - { 88, 164, 6252 }, // Tokyo Standard Time / Palau - { 105, 178, 6266 }, // Yakutsk Standard Time / Russia - { 37, 124, 6304 }, // FLE Standard Time / Lithuania - { 41, 121, 6319 }, // Greenwich Standard Time / Liberia - { 104, 89, 6335 }, // West Pacific Standard Time / Guam - { 96, 86, 6348 }, // UTC / Greenland - { 36, 72, 6369 }, // Fiji Standard Time / Fiji - { 19, 155, 6382 }, // Central America Standard Time / Nicaragua - { 11, 86, 6398 }, // Azores Standard Time / Greenland - { 79, 244, 6419 }, // SA Western Standard Time / Saint Barthelemy - { 69, 0, 6441 }, // Pacific Standard Time / AnyCountry - { 79, 219, 6449 }, // SA Western Standard Time / TurksAndCaicosIslands - { 103, 110, 6468 }, // West Asia Standard Time / Kazakhstan - { 26, 225, 6501 }, // Central Standard Time / UnitedStates - { 26, 139, 6669 }, // Central Standard Time / Mexico - { 7, 86, 6687 }, // Atlantic Standard Time / Greenland - { 24, 0, 6701 }, // Central Pacific Standard Time / AnyCountry - { 41, 199, 6712 }, // Greenwich Standard Time / SaintHelena - { 95, 158, 6731 }, // UTC-11 / Niue - { 53, 137, 6744 }, // Mauritius Standard Time / Mauritius - { 91, 143, 6761 }, // Ulaanbaatar Standard Time / Mongolia - { 83, 0, 6794 }, // South Africa Standard Time / AnyCountry - { 14, 20, 6804 }, // Belarus Standard Time / Belarus - { 29, 254, 6817 }, // E. Africa Standard Time / SouthSudan - { 87, 13, 6829 }, // Tasmania Standard Time / Australia - { 99, 178, 6863 }, // Vladivostok Standard Time / Russia - { 104, 8, 6908 }, // West Pacific Standard Time / Antarctica - { 39, 104, 6934 }, // GMT Standard Time / Ireland - { 102, 14, 6948 }, // W. Europe Standard Time / Austria + { 131, 143, 0 }, // W. Mongolia Standard Time / Mongolia + { 124, 112, 10 }, // UTC+12 / Kiribati + { 52, 94, 25 }, // Haiti Standard Time / Haiti + { 32, 44, 48 }, // China Standard Time / China + { 95, 244, 62 }, // SA Western Standard Time / Saint Barthelemy + { 25, 116, 84 }, // Central Asia Standard Time / Kyrgyzstan + { 36, 8, 97 }, // E. Africa Standard Time / Antarctica + { 33, 154, 114 }, // Chatham Islands Standard Time / New Zealand + { 95, 144, 130 }, // SA Western Standard Time / Montserrat + { 37, 13, 149 }, // E. Australia Standard Time / Australia + { 61, 0, 187 }, // Line Islands Standard Time / AnyCountry + { 132, 218, 198 }, // West Asia Standard Time / Turkmenistan + { 122, 30, 212 }, // UTC-02 / Brazil + { 24, 52, 228 }, // Central America Standard Time / Costa Rica + { 36, 67, 247 }, // E. Africa Standard Time / Eritrea + { 128, 8, 261 }, // W. Australia Standard Time / Antarctica + { 101, 101, 278 }, // SE Asia Standard Time / Indonesia + { 93, 8, 306 }, // SA Eastern Standard Time / Antarctica + { 4, 178, 325 }, // Altai Standard Time / Russia + { 95, 256, 338 }, // SA Western Standard Time / Sint Maarten + { 95, 60, 360 }, // SA Western Standard Time / Dominica + { 134, 167, 377 }, // West Pacific Standard Time / Papua New Guinea + { 13, 13, 398 }, // AUS Eastern Standard Time / Australia + { 69, 236, 435 }, // Morocco Standard Time / Western Sahara + { 39, 30, 451 }, // E. South America Standard Time / Brazil + { 124, 134, 469 }, // UTC+12 / Marshall Islands + { 125, 112, 502 }, // UTC+13 / Kiribati + { 103, 146, 520 }, // South Africa Standard Time / Mozambique + { 94, 30, 534 }, // SA Pacific Standard Time / Brazil + { 88, 74, 570 }, // Romance Standard Time / France + { 71, 38, 583 }, // Mountain Standard Time / Canada + { 72, 147, 657 }, // Myanmar Standard Time / Myanmar + { 26, 30, 670 }, // Central Brazilian Standard Time / Brazil + { 130, 123, 706 }, // W. Europe Standard Time / Liechtenstein + { 46, 73, 719 }, // FLE Standard Time / Finland + { 93, 70, 735 }, // SA Eastern Standard Time / Falkland Islands + { 78, 159, 752 }, // Norfolk Standard Time / Norfolk Island + { 53, 0, 768 }, // Hawaiian Standard Time / AnyCountry + { 28, 54, 779 }, // Central European Standard Time / Croatia + { 75, 150, 793 }, // Nepal Standard Time / Nepal + { 46, 33, 807 }, // FLE Standard Time / Bulgaria + { 6, 162, 820 }, // Arabian Standard Time / Oman + { 132, 131, 832 }, // West Asia Standard Time / Maldives + { 88, 197, 848 }, // Romance Standard Time / Spain + { 50, 91, 875 }, // Greenwich Standard Time / Guinea + { 5, 237, 890 }, // Arab Standard Time / Yemen + { 92, 222, 900 }, // Russian Standard Time / Ukraine + { 103, 204, 918 }, // South Africa Standard Time / Swaziland + { 130, 203, 933 }, // W. Europe Standard Time / Svalbard And Jan Mayen Islands + { 7, 103, 953 }, // Arabic Standard Time / Iraq + { 119, 226, 966 }, // UTC-11 / United States Minor Outlying Islands + { 5, 115, 981 }, // Arab Standard Time / Kuwait + { 50, 189, 993 }, // Greenwich Standard Time / Sierra Leone + { 31, 0, 1009 }, // Central Standard Time / AnyCountry + { 53, 51, 1017 }, // Hawaiian Standard Time / Cook Islands + { 129, 50, 1035 }, // W. Central Africa Standard Time / Congo Brazzaville + { 64, 43, 1054 }, // Magallanes Standard Time / Chile + { 119, 0, 1075 }, // UTC-11 / AnyCountry + { 84, 38, 1086 }, // Pacific Standard Time / Canada + { 22, 11, 1138 }, // Caucasus Standard Time / Armenia + { 130, 142, 1151 }, // W. Europe Standard Time / Monaco + { 103, 239, 1165 }, // South Africa Standard Time / Zambia + { 46, 222, 1179 }, // FLE Standard Time / Ukraine + { 87, 168, 1225 }, // Paraguay Standard Time / Paraguay + { 57, 109, 1242 }, // Jordan Standard Time / Jordan + { 109, 30, 1253 }, // Tocantins Standard Time / Brazil + { 55, 102, 1271 }, // Iran Standard Time / Iran + { 101, 8, 1283 }, // SE Asia Standard Time / Antarctica + { 27, 57, 1300 }, // Central Europe Standard Time / Czech Republic + { 95, 215, 1314 }, // SA Western Standard Time / Trinidad And Tobago + { 103, 28, 1336 }, // South Africa Standard Time / Botswana + { 132, 0, 1352 }, // West Asia Standard Time / AnyCountry + { 94, 63, 1362 }, // SA Pacific Standard Time / Ecuador + { 51, 85, 1380 }, // GTB Standard Time / Greece + { 36, 128, 1394 }, // E. Africa Standard Time / Madagascar + { 53, 226, 1414 }, // Hawaiian Standard Time / United States Minor Outlying Islands + { 94, 107, 1431 }, // SA Pacific Standard Time / Jamaica + { 104, 198, 1447 }, // Sri Lanka Standard Time / Sri Lanka + { 27, 243, 1460 }, // Central Europe Standard Time / Serbia + { 25, 110, 1476 }, // Central Asia Standard Time / Kazakhstan + { 125, 0, 1502 }, // UTC+13 / AnyCountry + { 94, 38, 1513 }, // SA Pacific Standard Time / Canada + { 25, 31, 1535 }, // Central Asia Standard Time / British Indian Ocean Territory + { 108, 13, 1549 }, // Tasmania Standard Time / Australia + { 95, 174, 1583 }, // SA Western Standard Time / Puerto Rico + { 95, 180, 1603 }, // SA Western Standard Time / Saint Kitts And Nevis + { 130, 206, 1620 }, // W. Europe Standard Time / Switzerland + { 117, 225, 1634 }, // US Eastern Standard Time / United States + { 29, 140, 1701 }, // Central Pacific Standard Time / Micronesia + { 120, 77, 1731 }, // UTC-09 / French Polynesia + { 129, 156, 1747 }, // W. Central Africa Standard Time / Niger + { 118, 139, 1761 }, // US Mountain Standard Time / Mexico + { 36, 194, 1780 }, // E. Africa Standard Time / Somalia + { 118, 0, 1797 }, // US Mountain Standard Time / AnyCountry + { 10, 24, 1807 }, // Atlantic Standard Time / Bermuda + { 103, 240, 1824 }, // South Africa Standard Time / Zimbabwe + { 32, 126, 1838 }, // China Standard Time / Macau + { 129, 66, 1849 }, // W. Central Africa Standard Time / Equatorial Guinea + { 66, 137, 1863 }, // Mauritius Standard Time / Mauritius + { 46, 68, 1880 }, // FLE Standard Time / Estonia + { 50, 187, 1895 }, // Greenwich Standard Time / Senegal + { 132, 110, 1908 }, // West Asia Standard Time / Kazakhstan + { 25, 44, 1968 }, // Central Asia Standard Time / China + { 130, 106, 1980 }, // W. Europe Standard Time / Italy + { 48, 251, 1992 }, // GMT Standard Time / Isle Of Man + { 36, 210, 2011 }, // E. Africa Standard Time / Tanzania + { 10, 86, 2032 }, // Atlantic Standard Time / Greenland + { 123, 86, 2046 }, // UTC / Greenland + { 20, 38, 2067 }, // Canada Central Standard Time / Canada + { 15, 86, 2104 }, // Azores Standard Time / Greenland + { 69, 145, 2125 }, // Morocco Standard Time / Morocco + { 115, 219, 2143 }, // Turks And Caicos Standard Time / Turks And Caicos Islands + { 50, 80, 2162 }, // Greenwich Standard Time / Gambia + { 129, 42, 2176 }, // W. Central Africa Standard Time / Chad + { 56, 105, 2192 }, // Israel Standard Time / Israel + { 64, 8, 2207 }, // Magallanes Standard Time / Antarctica + { 12, 13, 2225 }, // Aus Central W. Standard Time / Australia + { 24, 155, 2241 }, // Central America Standard Time / Nicaragua + { 102, 170, 2257 }, // Singapore Standard Time / Philippines + { 134, 160, 2269 }, // West Pacific Standard Time / Northern Mariana Islands + { 43, 64, 2284 }, // Egypt Standard Time / Egypt + { 88, 21, 2297 }, // Romance Standard Time / Belgium + { 76, 8, 2313 }, // New Zealand Standard Time / Antarctica + { 51, 177, 2332 }, // GTB Standard Time / Romania + { 103, 0, 2349 }, // South Africa Standard Time / AnyCountry + { 41, 225, 2359 }, // Eastern Standard Time / United States + { 129, 23, 2516 }, // W. Central Africa Standard Time / Benin + { 79, 178, 2534 }, // North Asia East Standard Time / Russia + { 116, 143, 2547 }, // Ulaanbaatar Standard Time / Mongolia + { 130, 14, 2580 }, // W. Europe Standard Time / Austria + { 41, 38, 2594 }, // Eastern Standard Time / Canada + { 95, 255, 2699 }, // SA Western Standard Time / Bonaire + { 124, 149, 2718 }, // UTC+12 / Nauru + { 134, 8, 2732 }, // West Pacific Standard Time / Antarctica + { 63, 178, 2758 }, // Magadan Standard Time / Russia + { 130, 161, 2771 }, // W. Europe Standard Time / Norway + { 110, 0, 2783 }, // Tokyo Standard Time / AnyCountry + { 24, 63, 2793 }, // Central America Standard Time / Ecuador + { 103, 35, 2811 }, // South Africa Standard Time / Burundi + { 10, 38, 2828 }, // Atlantic Standard Time / Canada + { 29, 0, 2896 }, // Central Pacific Standard Time / AnyCountry + { 95, 87, 2907 }, // SA Western Standard Time / Grenada + { 29, 153, 2923 }, // Central Pacific Standard Time / New Caledonia + { 42, 139, 2938 }, // Eastern Standard Time (Mexico) / Mexico + { 2, 225, 2953 }, // Alaskan Standard Time / United States + { 49, 86, 3029 }, // Greenland Standard Time / Greenland + { 50, 92, 3045 }, // Greenwich Standard Time / Guinea Bissau + { 130, 184, 3059 }, // W. Europe Standard Time / San Marino + { 27, 98, 3077 }, // Central Europe Standard Time / Hungary + { 24, 96, 3093 }, // Central America Standard Time / Honduras + { 62, 13, 3113 }, // Lord Howe Standard Time / Australia + { 36, 0, 3133 }, // E. Africa Standard Time / AnyCountry + { 129, 79, 3143 }, // W. Central Africa Standard Time / Gabon + { 95, 182, 3161 }, // SA Western Standard Time / Saint Vincent And The Grenadines + { 48, 224, 3180 }, // GMT Standard Time / United Kingdom + { 68, 227, 3194 }, // Montevideo Standard Time / Uruguay + { 124, 0, 3213 }, // UTC+12 / AnyCountry + { 130, 230, 3224 }, // W. Europe Standard Time / Vatican City State + { 50, 99, 3239 }, // Greenwich Standard Time / Iceland + { 34, 55, 3258 }, // Cuba Standard Time / Cuba + { 41, 16, 3273 }, // Eastern Standard Time / Bahamas + { 122, 196, 3288 }, // UTC-02 / South Georgia And The South Sandwich Islands + { 24, 65, 3311 }, // Central America Standard Time / El Salvador + { 31, 225, 3331 }, // Central Standard Time / United States + { 95, 0, 3499 }, // SA Western Standard Time / AnyCountry + { 94, 166, 3509 }, // SA Pacific Standard Time / Panama + { 94, 47, 3524 }, // SA Pacific Standard Time / Colombia + { 70, 139, 3539 }, // Mountain Standard Time (Mexico) / Mexico + { 124, 220, 3574 }, // UTC+12 / Tuvalu + { 130, 84, 3591 }, // W. Europe Standard Time / Gibraltar + { 82, 178, 3608 }, // Omsk Standard Time / Russia + { 60, 122, 3618 }, // Libya Standard Time / Libya + { 25, 8, 3633 }, // Central Asia Standard Time / Antarctica + { 95, 12, 3651 }, // SA Western Standard Time / Aruba + { 67, 119, 3665 }, // Middle East Standard Time / Lebanon + { 102, 0, 3677 }, // Singapore Standard Time / AnyCountry + { 74, 148, 3687 }, // Namibia Standard Time / Namibia + { 126, 231, 3703 }, // Venezuela Standard Time / Venezuela + { 95, 234, 3719 }, // SA Western Standard Time / United States Virgin Islands + { 21, 0, 3737 }, // Cape Verde Standard Time / AnyCountry + { 95, 9, 3747 }, // SA Western Standard Time / Antigua And Barbuda + { 94, 169, 3763 }, // SA Pacific Standard Time / Peru + { 46, 248, 3776 }, // FLE Standard Time / Aland Islands + { 50, 199, 3793 }, // Greenwich Standard Time / Saint Helena + { 134, 140, 3812 }, // West Pacific Standard Time / Micronesia + { 102, 190, 3825 }, // Singapore Standard Time / Singapore + { 95, 61, 3840 }, // SA Western Standard Time / Dominican Republic + { 103, 129, 3862 }, // South Africa Standard Time / Malawi + { 30, 139, 3878 }, // Central Standard Time (Mexico) / Mexico + { 102, 130, 3954 }, // Singapore Standard Time / Malaysia + { 45, 72, 3985 }, // Fiji Standard Time / Fiji + { 118, 225, 3998 }, // US Mountain Standard Time / United States + { 17, 25, 4014 }, // Bangladesh Standard Time / Bhutan + { 130, 133, 4027 }, // W. Europe Standard Time / Malta + { 92, 178, 4040 }, // Russian Standard Time / Russia + { 95, 135, 4084 }, // SA Western Standard Time / Martinique + { 35, 0, 4103 }, // Dateline Standard Time / AnyCountry + { 135, 178, 4114 }, // Yakutsk Standard Time / Russia + { 1, 1, 4141 }, // Afghanistan Standard Time / Afghanistan + { 123, 0, 4152 }, // UTC / AnyCountry + { 31, 139, 4168 }, // Central Standard Time / Mexico + { 6, 0, 4186 }, // Arabian Standard Time / AnyCountry + { 101, 45, 4196 }, // SE Asia Standard Time / Christmas Island + { 15, 173, 4213 }, // Azores Standard Time / Portugal + { 129, 0, 4229 }, // W. Central Africa Standard Time / AnyCountry + { 17, 18, 4239 }, // Bangladesh Standard Time / Bangladesh + { 31, 38, 4250 }, // Central Standard Time / Canada + { 94, 0, 4325 }, // SA Pacific Standard Time / AnyCountry + { 125, 213, 4335 }, // UTC+13 / Tokelau + { 73, 178, 4351 }, // N. Central Asia Standard Time / Russia + { 133, 165, 4368 }, // West Bank Standard Time / Palestinian Territories + { 114, 217, 4390 }, // Turkey Standard Time / Turkey + { 3, 225, 4406 }, // Aleutian Standard Time / United States + { 101, 0, 4419 }, // SE Asia Standard Time / AnyCountry + { 71, 225, 4429 }, // Mountain Standard Time / United States + { 36, 69, 4458 }, // E. Africa Standard Time / Ethiopia + { 130, 151, 4477 }, // W. Europe Standard Time / Netherlands + { 95, 245, 4494 }, // SA Western Standard Time / Saint Martin + { 48, 173, 4510 }, // GMT Standard Time / Portugal + { 46, 124, 4541 }, // FLE Standard Time / Lithuania + { 130, 82, 4556 }, // W. Europe Standard Time / Germany + { 65, 77, 4586 }, // Marquesas Standard Time / French Polynesia + { 80, 178, 4604 }, // North Asia Standard Time / Russia + { 61, 112, 4639 }, // Line Islands Standard Time / Kiribati + { 96, 200, 4658 }, // Saint Pierre Standard Time / Saint Pierre And Miquelon + { 48, 104, 4675 }, // GMT Standard Time / Ireland + { 5, 186, 4689 }, // Arab Standard Time / Saudi Arabia + { 83, 43, 4701 }, // Pacific SA Standard Time / Chile + { 91, 178, 4718 }, // Russia Time Zone 11 / Russia + { 36, 48, 4745 }, // E. Africa Standard Time / Comoros + { 95, 152, 4759 }, // SA Western Standard Time / Cura Sao + { 38, 141, 4775 }, // E. Europe Standard Time / Moldova + { 24, 22, 4791 }, // Central America Standard Time / Belize + { 103, 195, 4806 }, // South Africa Standard Time / South Africa + { 127, 178, 4826 }, // Vladivostok Standard Time / Russia + { 122, 0, 4857 }, // UTC-02 / AnyCountry + { 106, 207, 4867 }, // Syria Standard Time / Syria + { 93, 76, 4881 }, // SA Eastern Standard Time / French Guiana + { 50, 136, 4897 }, // Greenwich Standard Time / Mauritania + { 41, 0, 4915 }, // Eastern Standard Time / AnyCountry + { 16, 30, 4923 }, // Bahia Standard Time / Brazil + { 40, 43, 4937 }, // Easter Island Standard Time / Chile + { 93, 0, 4952 }, // SA Eastern Standard Time / AnyCountry + { 9, 178, 4962 }, // Astrakhan Standard Time / Russia + { 95, 30, 4996 }, // SA Western Standard Time / Brazil + { 18, 20, 5049 }, // Belarus Standard Time / Belarus + { 95, 181, 5062 }, // SA Western Standard Time / Saint Lucia + { 129, 6, 5079 }, // W. Central Africa Standard Time / Angola + { 129, 157, 5093 }, // W. Central Africa Standard Time / Nigeria + { 130, 5, 5106 }, // W. Europe Standard Time / Andorra + { 58, 178, 5121 }, // Kaliningrad Standard Time / Russia + { 71, 0, 5140 }, // Mountain Standard Time / AnyCountry + { 95, 7, 5148 }, // SA Western Standard Time / Anguilla + { 124, 235, 5165 }, // UTC+12 / Wallis And Futuna Islands + { 6, 223, 5180 }, // Arabian Standard Time / United Arab Emirates + { 94, 40, 5191 }, // SA Pacific Standard Time / Cayman Islands + { 101, 211, 5206 }, // SE Asia Standard Time / Thailand + { 29, 193, 5219 }, // Central Pacific Standard Time / Solomon Islands + { 47, 81, 5239 }, // Georgian Standard Time / Georgia + { 101, 36, 5252 }, // SE Asia Standard Time / Cambodia + { 132, 228, 5268 }, // West Asia Standard Time / Uzbekistan + { 51, 56, 5297 }, // GTB Standard Time / Cyprus + { 95, 88, 5325 }, // SA Western Standard Time / Guadeloupe + { 101, 232, 5344 }, // SE Asia Standard Time / Vietnam + { 113, 178, 5356 }, // Transbaikal Standard Time / Russia + { 50, 121, 5367 }, // Greenwich Standard Time / Liberia + { 95, 233, 5383 }, // SA Western Standard Time / British Virgin Islands + { 129, 49, 5399 }, // W. Central Africa Standard Time / Congo Kinshasa + { 97, 178, 5415 }, // Sakhalin Standard Time / Russia + { 124, 226, 5429 }, // UTC+12 / United States Minor Outlying Islands + { 50, 83, 5442 }, // Greenwich Standard Time / Ghana + { 76, 154, 5455 }, // New Zealand Standard Time / New Zealand + { 23, 13, 5472 }, // Cen. Australia Standard Time / Australia + { 53, 77, 5513 }, // Hawaiian Standard Time / French Polynesia + { 50, 34, 5528 }, // Greenwich Standard Time / Burkina Faso + { 132, 78, 5547 }, // West Asia Standard Time / French Southern Territories + { 121, 0, 5564 }, // UTC-08 / AnyCountry + { 27, 2, 5574 }, // Central Europe Standard Time / Albania + { 107, 208, 5588 }, // Taipei Standard Time / Taiwan + { 88, 58, 5600 }, // Romance Standard Time / Denmark + { 36, 221, 5618 }, // E. Africa Standard Time / Uganda + { 95, 19, 5633 }, // SA Western Standard Time / Barbados + { 14, 15, 5650 }, // Azerbaijan Standard Time / Azerbaijan + { 32, 97, 5660 }, // China Standard Time / Hong Kong + { 110, 101, 5675 }, // Tokyo Standard Time / Indonesia + { 53, 225, 5689 }, // Hawaiian Standard Time / United States + { 36, 111, 5706 }, // E. Africa Standard Time / Kenya + { 134, 89, 5721 }, // West Pacific Standard Time / Guam + { 36, 254, 5734 }, // E. Africa Standard Time / South Sudan + { 48, 71, 5746 }, // GMT Standard Time / Faroe Islands + { 90, 178, 5762 }, // Russia Time Zone 10 / Russia + { 119, 158, 5781 }, // UTC-11 / Niue + { 129, 3, 5794 }, // W. Central Africa Standard Time / Algeria + { 110, 62, 5809 }, // Tokyo Standard Time / East Timor + { 93, 30, 5819 }, // SA Eastern Standard Time / Brazil + { 27, 242, 5898 }, // Central Europe Standard Time / Montenegro + { 129, 37, 5915 }, // W. Central Africa Standard Time / Cameroon + { 101, 117, 5929 }, // SE Asia Standard Time / Laos + { 85, 139, 5944 }, // Pacific Standard Time (Mexico) / Mexico + { 50, 212, 5981 }, // Greenwich Standard Time / Togo + { 46, 118, 5993 }, // FLE Standard Time / Latvia + { 95, 38, 6005 }, // SA Western Standard Time / Canada + { 132, 209, 6026 }, // West Asia Standard Time / Tajikistan + { 77, 38, 6040 }, // Newfoundland Standard Time / Canada + { 110, 108, 6057 }, // Tokyo Standard Time / Japan + { 25, 0, 6068 }, // Central Asia Standard Time / AnyCountry + { 28, 27, 6078 }, // Central European Standard Time / Bosnia And Herzegowina + { 27, 191, 6094 }, // Central Europe Standard Time / Slovakia + { 95, 93, 6112 }, // SA Western Standard Time / Guyana + { 48, 197, 6127 }, // GMT Standard Time / Spain + { 19, 167, 6143 }, // Bougainville Standard Time / Papua New Guinea + { 5, 17, 6164 }, // Arab Standard Time / Bahrain + { 24, 90, 6177 }, // Central America Standard Time / Guatemala + { 95, 26, 6195 }, // SA Western Standard Time / Bolivia + { 81, 113, 6210 }, // North Korea Standard Time / North Korea + { 119, 4, 6225 }, // UTC-11 / American Samoa + { 66, 176, 6243 }, // Mauritius Standard Time / Reunion + { 103, 120, 6258 }, // South Africa Standard Time / Lesotho + { 84, 0, 6272 }, // Pacific Standard Time / AnyCountry + { 120, 0, 6280 }, // UTC-09 / AnyCountry + { 129, 216, 6290 }, // W. Central Africa Standard Time / Tunisia + { 99, 185, 6303 }, // Sao Tome Standard Time / Sao Tome And Principe + { 100, 178, 6319 }, // Saratov Standard Time / Russia + { 105, 201, 6334 }, // Sudan Standard Time / Sudan + { 48, 252, 6350 }, // GMT Standard Time / Jersey + { 29, 13, 6364 }, // Central Pacific Standard Time / Australia + { 71, 139, 6385 }, // Mountain Standard Time / Mexico + { 21, 39, 6401 }, // Cape Verde Standard Time / Cape Verde + { 102, 101, 6421 }, // Singapore Standard Time / Indonesia + { 27, 192, 6435 }, // Central Europe Standard Time / Slovenia + { 48, 75, 6452 }, // GMT Standard Time / Guernsey + { 132, 8, 6468 }, // West Asia Standard Time / Antarctica + { 8, 10, 6486 }, // Argentina Standard Time / Argentina + { 98, 183, 6759 }, // Samoa Standard Time / Samoa + { 129, 41, 6772 }, // W. Central Africa Standard Time / Central African Republic + { 111, 178, 6786 }, // Tomsk Standard Time / Russia + { 110, 164, 6797 }, // Tokyo Standard Time / Palau + { 11, 13, 6811 }, // AUS Central Standard Time / Australia + { 121, 171, 6828 }, // UTC-08 / Pitcairn + { 102, 32, 6845 }, // Singapore Standard Time / Brunei + { 112, 214, 6857 }, // Tonga Standard Time / Tonga + { 89, 178, 6875 }, // Russia Time Zone 3 / Russia + { 128, 13, 6889 }, // W. Australia Standard Time / Australia + { 28, 172, 6905 }, // Central European Standard Time / Poland + { 72, 46, 6919 }, // Myanmar Standard Time / Cocos Islands + { 66, 188, 6932 }, // Mauritius Standard Time / Seychelles + { 84, 225, 6944 }, // Pacific Standard Time / United States + { 54, 100, 6983 }, // India Standard Time / India + { 50, 53, 6997 }, // Greenwich Standard Time / Ivory Coast + { 24, 0, 7012 }, // Central America Standard Time / AnyCountry + { 29, 229, 7022 }, // Central Pacific Standard Time / Vanuatu + { 130, 125, 7036 }, // W. Europe Standard Time / Luxembourg + { 50, 132, 7054 }, // Greenwich Standard Time / Mali + { 103, 179, 7068 }, // South Africa Standard Time / Rwanda + { 5, 175, 7082 }, // Arab Standard Time / Qatar + { 86, 163, 7093 }, // Pakistan Standard Time / Pakistan + { 134, 0, 7106 }, // West Pacific Standard Time / AnyCountry + { 36, 59, 7117 }, // E. Africa Standard Time / Djibouti + { 44, 178, 7133 }, // Ekaterinburg Standard Time / Russia + { 118, 38, 7152 }, // US Mountain Standard Time / Canada + { 36, 138, 7209 }, // E. Africa Standard Time / Mayotte + { 28, 127, 7224 }, // Central European Standard Time / Macedonia + { 59, 114, 7238 }, // Korea Standard Time / South Korea + { 93, 202, 7249 }, // SA Eastern Standard Time / Suriname + { 130, 205, 7268 }, // W. Europe Standard Time / Sweden + { 103, 49, 7285 }, // South Africa Standard Time / Congo Kinshasa { 0, 0, 0 } // Trailing zeroes }; // Windows ID Key, Windows ID Index, IANA ID Index, UTC Offset static const QWindowsData windowsDataTable[] = { - { 1, 0, 3480, 16200 }, // Afghanistan Standard Time - { 2, 26, 6962,-32400 }, // Alaskan Standard Time - { 3, 48, 5629, 10800 }, // Arab Standard Time - { 4, 67, 3254, 14400 }, // Arabian Standard Time - { 5, 89, 504, 10800 }, // Arabic Standard Time - { 6, 110, 6980,-10800 }, // Argentina Standard Time - { 7, 134, 7001,-14400 }, // Atlantic Standard Time - { 8, 157, 4368, 34200 }, // AUS Central Standard Time - { 9, 183, 7017, 36000 }, // AUS Eastern Standard Time - { 10, 209, 4400, 14400 }, // Azerbaijan Standard Time - { 11, 234, 1220, -3600 }, // Azores Standard Time - { 12, 255, 701,-10800 }, // Bahia Standard Time - { 13, 275, 1340, 21600 }, // Bangladesh Standard Time - { 14, 300, 6804, 10800 }, // Belarus Standard Time - { 15, 322, 7034,-21600 }, // Canada Central Standard Time - { 16, 351, 4348, -3600 }, // Cape Verde Standard Time - { 17, 376, 3902, 14400 }, // Caucasus Standard Time - { 18, 399, 7049, 34200 }, // Cen. Australia Standard Time - { 19, 428, 4058,-21600 }, // Central America Standard Time - { 20, 458, 7068, 21600 }, // Central Asia Standard Time - { 21, 485, 7080,-14400 }, // Central Brazilian Standard Time - { 22, 517, 5078, 3600 }, // Central Europe Standard Time - { 23, 546, 3970, 3600 }, // Central European Standard Time - { 24, 577, 1769, 39600 }, // Central Pacific Standard Time - { 25, 607, 7095,-21600 }, // Central Standard Time (Mexico) - { 26, 638, 7115,-21600 }, // Central Standard Time - { 27, 660, 6078, 28800 }, // China Standard Time - { 28, 680, 3352,-43200 }, // Dateline Standard Time - { 29, 703, 2585, 10800 }, // E. Africa Standard Time - { 30, 727, 7131, 36000 }, // E. Australia Standard Time - { 31, 754, 2654,-10800 }, // E. South America Standard Time - { 32, 785, 7150,-18000 }, // Eastern Standard Time - { 33, 807, 2031,-18000 }, // Eastern Standard Time (Mexico) - { 34, 838, 1678, 7200 }, // Egypt Standard Time - { 35, 858, 651, 18000 }, // Ekaterinburg Standard Time - { 36, 885, 6369, 43200 }, // Fiji Standard Time - { 37, 904, 7167, 7200 }, // FLE Standard Time - { 38, 922, 3022, 14400 }, // Georgian Standard Time - { 39, 945, 5683, 0 }, // GMT Standard Time - { 40, 963, 3954,-10800 }, // Greenland Standard Time - { 41, 987, 2012, 0 }, // Greenwich Standard Time - { 42, 1011, 1819, 7200 }, // GTB Standard Time - { 43, 1029, 3335,-36000 }, // Hawaiian Standard Time - { 44, 1052, 4520, 19800 }, // India Standard Time - { 45, 1072, 1328, 12600 }, // Iran Standard Time - { 46, 1091, 4427, 7200 }, // Israel Standard Time - { 47, 1112, 1808, 7200 }, // Jordan Standard Time - { 48, 1133, 1789, 7200 }, // Kaliningrad Standard Time - { 49, 1159, 3723, 32400 }, // Korea Standard Time - { 50, 1179, 63, 7200 }, // Libya Standard Time - { 51, 1199, 835, 50400 }, // Line Islands Standard Time - { 52, 1226, 2274, 36000 }, // Magadan Standard Time - { 53, 1248, 6744, 14400 }, // Mauritius Standard Time - { 54, 1272, 4046, 7200 }, // Middle East Standard Time - { 55, 1298, 755,-10800 }, // Montevideo Standard Time - { 56, 1323, 3884, 0 }, // Morocco Standard Time - { 57, 1345, 7179,-25200 }, // Mountain Standard Time (Mexico) - { 58, 1377, 7197,-25200 }, // Mountain Standard Time - { 59, 1400, 1725, 23400 }, // Myanmar Standard Time - { 60, 1422, 7212, 21600 }, // N. Central Asia Standard Time - { 61, 1452, 5094, 3600 }, // Namibia Standard Time - { 62, 1474, 4506, 20700 }, // Nepal Standard Time - { 63, 1494, 3399, 43200 }, // New Zealand Standard Time - { 64, 1520, 3382,-12600 }, // Newfoundland Standard Time - { 65, 1547, 1405, 28800 }, // North Asia East Standard Time - { 66, 1577, 7229, 25200 }, // North Asia Standard Time - { 67, 1602, 6235,-10800 }, // Pacific SA Standard Time - { 68, 1627, 819, 7200 }, // E. Europe Standard Time - { 69, 1651, 1351,-28800 }, // Pacific Standard Time - { 70, 1673, 4076, 18000 }, // Pakistan Standard Time - { 71, 1696, 3088,-14400 }, // Paraguay Standard Time - { 72, 1719, 638, 3600 }, // Romance Standard Time - { 73, 1741, 3815, 14400 }, // Russia Time Zone 3 - { 74, 1760, 533, 39600 }, // Russia Time Zone 10 - { 75, 1780, 7246, 43200 }, // Russia Time Zone 11 - { 76, 1800, 7261, 10800 }, // Russian Standard Time - { 77, 1822, 149,-10800 }, // SA Eastern Standard Time - { 78, 1847, 4333,-18000 }, // SA Pacific Standard Time - { 79, 1872, 4122,-14400 }, // SA Western Standard Time - { 80, 1897, 3322, 46800 }, // Samoa Standard Time - { 81, 1917, 2320, 25200 }, // SE Asia Standard Time - { 82, 1939, 3465, 28800 }, // Singapore Standard Time - { 83, 1963, 3148, 7200 }, // South Africa Standard Time - { 84, 1990, 5764, 19800 }, // Sri Lanka Standard Time - { 85, 2014, 4294, 7200 }, // Syria Standard Time - { 86, 2034, 3932, 28800 }, // Taipei Standard Time - { 87, 2055, 7275, 36000 }, // Tasmania Standard Time - { 88, 2078, 5654, 32400 }, // Tokyo Standard Time - { 89, 2098, 3984, 46800 }, // Tonga Standard Time - { 90, 2118, 4784, 7200 }, // Turkey Standard Time - { 91, 2139, 7292, 28800 }, // Ulaanbaatar Standard Time - { 92, 2165, 7309,-18000 }, // US Eastern Standard Time - { 93, 2190, 4894,-25200 }, // US Mountain Standard Time - { 94, 2216, 3753, -7200 }, // UTC-02 - { 95, 2223, 3035,-39600 }, // UTC-11 - { 96, 2230, 1070, 0 }, // UTC - { 97, 2234, 239, 43200 }, // UTC+12 - { 98, 2241, 5172,-16200 }, // Venezuela Standard Time - { 99, 2265, 7330, 36000 }, // Vladivostok Standard Time - { 100, 2291, 3843, 28800 }, // W. Australia Standard Time - { 101, 2318, 1909, 3600 }, // W. Central Africa Standard Time - { 102, 2350, 7347, 3600 }, // W. Europe Standard Time - { 103, 2374, 7361, 18000 }, // West Asia Standard Time - { 104, 2398, 3067, 36000 }, // West Pacific Standard Time - { 105, 2425, 7375, 32400 }, // Yakutsk Standard Time - { 106, 2447, 4385, 30600 }, // North Korea Standard Time + { 1, 0, 4141, 16200 }, // Afghanistan Standard Time + { 2, 26, 7303,-32400 }, // Alaskan Standard Time + { 3, 48, 4406,-36000 }, // Aleutian Standard Time + { 4, 71, 325, 25200 }, // Altai Standard Time + { 5, 91, 4689, 10800 }, // Arab Standard Time + { 6, 110, 5180, 14400 }, // Arabian Standard Time + { 7, 132, 953, 10800 }, // Arabic Standard Time + { 8, 153, 7321,-10800 }, // Argentina Standard Time + { 9, 177, 7342, 14400 }, // Astrakhan Standard Time + { 10, 201, 7359,-14400 }, // Atlantic Standard Time + { 11, 224, 6811, 34200 }, // AUS Central Standard Time + { 12, 250, 2225, 31500 }, // Aus Central W. Standard Time + { 13, 279, 7375, 36000 }, // AUS Eastern Standard Time + { 14, 305, 5650, 14400 }, // Azerbaijan Standard Time + { 15, 330, 4213, -3600 }, // Azores Standard Time + { 16, 351, 4923,-10800 }, // Bahia Standard Time + { 17, 371, 4239, 21600 }, // Bangladesh Standard Time + { 18, 396, 5049, 10800 }, // Belarus Standard Time + { 19, 418, 6143, 39600 }, // Bougainville Standard Time + { 20, 445, 7392,-21600 }, // Canada Central Standard Time + { 21, 474, 6401, -3600 }, // Cape Verde Standard Time + { 22, 499, 1138, 14400 }, // Caucasus Standard Time + { 23, 522, 7407, 34200 }, // Cen. Australia Standard Time + { 24, 551, 6177,-21600 }, // Central America Standard Time + { 25, 581, 7426, 21600 }, // Central Asia Standard Time + { 26, 608, 7438,-14400 }, // Central Brazilian Standard Time + { 27, 640, 3077, 3600 }, // Central Europe Standard Time + { 28, 669, 6905, 3600 }, // Central European Standard Time + { 29, 700, 5219, 39600 }, // Central Pacific Standard Time + { 30, 730, 7453,-21600 }, // Central Standard Time (Mexico) + { 31, 761, 7473,-21600 }, // Central Standard Time + { 32, 783, 48, 28800 }, // China Standard Time + { 33, 803, 114, 45900 }, // Chatham Islands Standard Time + { 34, 833, 3258,-18000 }, // Cuba Standard Time + { 35, 852, 4103,-43200 }, // Dateline Standard Time + { 36, 875, 5706, 10800 }, // E. Africa Standard Time + { 37, 899, 7489, 36000 }, // E. Australia Standard Time + { 38, 926, 4775, 7200 }, // E. Europe Standard Time + { 39, 950, 451,-10800 }, // E. South America Standard Time + { 40, 981, 4937,-21600 }, // Easter Island Standard Time + { 41, 1009, 7508,-18000 }, // Eastern Standard Time + { 42, 1031, 2938,-18000 }, // Eastern Standard Time (Mexico) + { 43, 1062, 2284, 7200 }, // Egypt Standard Time + { 44, 1082, 7133, 18000 }, // Ekaterinburg Standard Time + { 45, 1109, 3985, 43200 }, // Fiji Standard Time + { 46, 1128, 7525, 7200 }, // FLE Standard Time + { 47, 1146, 5239, 14400 }, // Georgian Standard Time + { 48, 1169, 3180, 0 }, // GMT Standard Time + { 49, 1187, 3029,-10800 }, // Greenland Standard Time + { 50, 1211, 3239, 0 }, // Greenwich Standard Time + { 51, 1235, 2332, 7200 }, // GTB Standard Time + { 52, 1253, 25,-18000 }, // Haiti Standard Time + { 53, 1273, 5689,-36000 }, // Hawaiian Standard Time + { 54, 1296, 6983, 19800 }, // India Standard Time + { 55, 1316, 1271, 12600 }, // Iran Standard Time + { 56, 1335, 2192, 7200 }, // Israel Standard Time + { 57, 1356, 1242, 7200 }, // Jordan Standard Time + { 58, 1377, 5121, 7200 }, // Kaliningrad Standard Time + { 59, 1403, 7238, 32400 }, // Korea Standard Time + { 60, 1423, 3618, 7200 }, // Libya Standard Time + { 61, 1443, 4639, 50400 }, // Line Islands Standard Time + { 62, 1470, 3113, 37800 }, // Lord Howe Standard Time + { 63, 1494, 2758, 36000 }, // Magadan Standard Time + { 64, 1516, 1054,-10800 }, // Magallanes Standard Time + { 65, 1541, 4586,-34200 }, // Marquesas Standard Time + { 66, 1565, 1863, 14400 }, // Mauritius Standard Time + { 67, 1589, 3665, 7200 }, // Middle East Standard Time + { 68, 1615, 3194,-10800 }, // Montevideo Standard Time + { 69, 1640, 2125, 0 }, // Morocco Standard Time + { 70, 1662, 7537,-25200 }, // Mountain Standard Time (Mexico) + { 71, 1694, 7555,-25200 }, // Mountain Standard Time + { 72, 1717, 657, 23400 }, // Myanmar Standard Time + { 73, 1739, 4351, 21600 }, // N. Central Asia Standard Time + { 74, 1769, 3687, 3600 }, // Namibia Standard Time + { 75, 1791, 793, 20700 }, // Nepal Standard Time + { 76, 1811, 5455, 43200 }, // New Zealand Standard Time + { 77, 1837, 6040,-12600 }, // Newfoundland Standard Time + { 78, 1864, 752, 39600 }, // Norfolk Standard Time + { 79, 1886, 2534, 28800 }, // North Asia East Standard Time + { 80, 1916, 7570, 25200 }, // North Asia Standard Time + { 81, 1941, 6210, 30600 }, // North Korea Standard Time + { 82, 1967, 3608, 21600 }, // Omsk Standard Time + { 83, 1986, 4701,-10800 }, // Pacific SA Standard Time + { 84, 2011, 7587,-28800 }, // Pacific Standard Time + { 85, 2033, 7607,-28800 }, // Pacific Standard Time (Mexico) + { 86, 2064, 7093, 18000 }, // Pakistan Standard Time + { 87, 2087, 1225,-14400 }, // Paraguay Standard Time + { 88, 2110, 570, 3600 }, // Romance Standard Time + { 89, 2132, 6875, 14400 }, // Russia Time Zone 3 + { 90, 2151, 5762, 39600 }, // Russia Time Zone 10 + { 91, 2171, 7623, 43200 }, // Russia Time Zone 11 + { 92, 2191, 7638, 10800 }, // Russian Standard Time + { 93, 2213, 4881,-10800 }, // SA Eastern Standard Time + { 94, 2238, 3524,-18000 }, // SA Pacific Standard Time + { 95, 2263, 6195,-14400 }, // SA Western Standard Time + { 96, 2288, 4658,-10800 }, // Saint Pierre Standard Time + { 97, 2315, 5415, 39600 }, // Sakhalin Standard Time + { 98, 2338, 6759, 46800 }, // Samoa Standard Time + { 99, 2358, 6303, 0 }, // Sao Tome Standard Time + { 100, 2381, 6319, 14400 }, // Saratov Standard Time + { 101, 2403, 5206, 25200 }, // SE Asia Standard Time + { 102, 2425, 3825, 28800 }, // Singapore Standard Time + { 103, 2449, 4806, 7200 }, // South Africa Standard Time + { 104, 2476, 1447, 19800 }, // Sri Lanka Standard Time + { 105, 2500, 6334, 7200 }, // Sudan Standard Time + { 106, 2520, 4867, 7200 }, // Syria Standard Time + { 107, 2540, 5588, 28800 }, // Taipei Standard Time + { 108, 2561, 7652, 36000 }, // Tasmania Standard Time + { 109, 2584, 1253,-10800 }, // Tocantins Standard Time + { 110, 2608, 6057, 32400 }, // Tokyo Standard Time + { 111, 2628, 6786, 25200 }, // Tomsk Standard Time + { 112, 2648, 6857, 46800 }, // Tonga Standard Time + { 113, 2668, 5356, 32400 }, // Transbaikal Standard Time + { 114, 2694, 4390, 7200 }, // Turkey Standard Time + { 115, 2715, 2143,-14400 }, // Turks And Caicos Standard Time + { 116, 2746, 7669, 28800 }, // Ulaanbaatar Standard Time + { 117, 2772, 7686,-18000 }, // US Eastern Standard Time + { 118, 2797, 3998,-25200 }, // US Mountain Standard Time + { 119, 2823, 1075,-39600 }, // UTC-11 + { 120, 2830, 6280,-32400 }, // UTC-09 + { 121, 2837, 5564,-28800 }, // UTC-08 + { 122, 2844, 4857, -7200 }, // UTC-02 + { 123, 2851, 7707, 0 }, // UTC + { 124, 2855, 3213, 43200 }, // UTC+12 + { 125, 2862, 1502, 46800 }, // UTC+13 + { 126, 2869, 3703,-16200 }, // Venezuela Standard Time + { 127, 2893, 7715, 36000 }, // Vladivostok Standard Time + { 128, 2919, 6889, 28800 }, // W. Australia Standard Time + { 129, 2946, 5093, 3600 }, // W. Central Africa Standard Time + { 130, 2978, 7732, 3600 }, // W. Europe Standard Time + { 131, 3002, 0, 25200 }, // W. Mongolia Standard Time + { 132, 3028, 7746, 18000 }, // West Asia Standard Time + { 133, 3052, 7760, 7200 }, // West Bank Standard Time + { 134, 3076, 377, 36000 }, // West Pacific Standard Time + { 135, 3103, 7772, 32400 }, // Yakutsk Standard Time { 0, 0, 0, 0 } // Trailing zeroes }; // IANA ID Index, UTC Offset static const QUtcData utcDataTable[] = { - { 7388, 0 }, // UTC - { 7392,-50400 }, // UTC-14:00 - { 7402,-46800 }, // UTC-13:00 - { 7412,-43200 }, // UTC-12:00 - { 7422,-39600 }, // UTC-11:00 - { 7432,-36000 }, // UTC-10:00 - { 7442,-32400 }, // UTC-09:00 - { 7452,-28800 }, // UTC-08:00 - { 7462,-25200 }, // UTC-07:00 - { 7472,-21600 }, // UTC-06:00 - { 7482,-18000 }, // UTC-05:00 - { 7492,-16200 }, // UTC-04:30 - { 7502,-14400 }, // UTC-04:00 - { 7512,-12600 }, // UTC-03:30 - { 7522,-10800 }, // UTC-03:00 - { 7532, -7200 }, // UTC-02:00 - { 7542, -3600 }, // UTC-01:00 - { 7552, 0 }, // UTC-00:00 - { 7562, 0 }, // UTC+00:00 - { 7572, 3600 }, // UTC+01:00 - { 7582, 7200 }, // UTC+02:00 - { 7592, 10800 }, // UTC+03:00 - { 7602, 12600 }, // UTC+03:30 - { 7612, 14400 }, // UTC+04:00 - { 7622, 16200 }, // UTC+04:30 - { 7632, 18000 }, // UTC+05:00 - { 7642, 19800 }, // UTC+05:30 - { 7652, 20700 }, // UTC+05:45 - { 7662, 21600 }, // UTC+06:00 - { 7672, 23400 }, // UTC+06:30 - { 7682, 25200 }, // UTC+07:00 - { 7692, 28800 }, // UTC+08:00 - { 7702, 32400 }, // UTC+09:00 - { 7712, 34200 }, // UTC+09:30 - { 7722, 36000 }, // UTC+10:00 - { 7732, 39600 }, // UTC+11:00 - { 7742, 43200 }, // UTC+12:00 - { 7752, 46800 }, // UTC+13:00 - { 7762, 50400 }, // UTC+14:00 - { 7772, 30600 }, // UTC+08:30 + { 7785, 0 }, // UTC + { 7789,-50400 }, // UTC-14:00 + { 7799,-46800 }, // UTC-13:00 + { 7809,-43200 }, // UTC-12:00 + { 7819,-39600 }, // UTC-11:00 + { 7829,-36000 }, // UTC-10:00 + { 7839,-32400 }, // UTC-09:00 + { 7849,-28800 }, // UTC-08:00 + { 7859,-25200 }, // UTC-07:00 + { 7869,-21600 }, // UTC-06:00 + { 7879,-18000 }, // UTC-05:00 + { 7889,-16200 }, // UTC-04:30 + { 7899,-14400 }, // UTC-04:00 + { 7909,-12600 }, // UTC-03:30 + { 7919,-10800 }, // UTC-03:00 + { 7929, -7200 }, // UTC-02:00 + { 7939, -3600 }, // UTC-01:00 + { 7949, 0 }, // UTC-00:00 + { 7959, 0 }, // UTC+00:00 + { 7969, 3600 }, // UTC+01:00 + { 7979, 7200 }, // UTC+02:00 + { 7989, 10800 }, // UTC+03:00 + { 7999, 12600 }, // UTC+03:30 + { 8009, 14400 }, // UTC+04:00 + { 8019, 16200 }, // UTC+04:30 + { 8029, 18000 }, // UTC+05:00 + { 8039, 19800 }, // UTC+05:30 + { 8049, 20700 }, // UTC+05:45 + { 8059, 21600 }, // UTC+06:00 + { 8069, 23400 }, // UTC+06:30 + { 8079, 25200 }, // UTC+07:00 + { 8089, 28800 }, // UTC+08:00 + { 8099, 30600 }, // UTC+08:30 + { 8109, 32400 }, // UTC+09:00 + { 8119, 34200 }, // UTC+09:30 + { 8129, 36000 }, // UTC+10:00 + { 8139, 39600 }, // UTC+11:00 + { 8149, 43200 }, // UTC+12:00 + { 8159, 46800 }, // UTC+13:00 + { 8169, 50400 }, // UTC+14:00 { 0, 0 } // Trailing zeroes }; static const char windowsIdData[] = { 0x41, 0x66, 0x67, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x20, -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, -0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x55, 0x53, -0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, -0x6d, 0x65, 0x0, 0x41, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x65, 0x72, 0x62, 0x61, 0x69, 0x6a, 0x61, 0x6e, 0x20, -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x68, 0x69, 0x61, -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x6e, 0x67, 0x6c, -0x61, 0x64, 0x65, 0x73, 0x68, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, -0x42, 0x65, 0x6c, 0x61, 0x72, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, -0x65, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x70, 0x65, 0x20, 0x56, 0x65, 0x72, 0x64, -0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x75, 0x63, -0x61, 0x73, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, -0x65, 0x6e, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x6d, 0x65, 0x72, -0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, -0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, -0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x69, -0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, -0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, -0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, -0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, -0x74, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x43, 0x65, -0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, -0x43, 0x68, 0x69, 0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, -0x44, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, -0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x53, 0x6f, 0x75, -0x74, 0x68, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, -0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x45, 0x67, -0x79, 0x70, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x6b, -0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, -0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x69, 0x6a, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, -0x69, 0x6d, 0x65, 0x0, 0x46, 0x4c, 0x45, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, -0x65, 0x0, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, -0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x4d, 0x54, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, -0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x20, 0x53, 0x74, 0x61, -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x54, 0x42, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, -0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x20, 0x53, 0x74, -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x72, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x20, 0x53, 0x74, -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4a, 0x6f, 0x72, 0x64, 0x61, 0x6e, 0x20, 0x53, -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, -0x67, 0x72, 0x61, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b, -0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c, -0x69, 0x62, 0x79, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c, -0x69, 0x6e, 0x65, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, -0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x20, 0x53, 0x74, -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x20, 0x45, -0x61, 0x73, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, -0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, -0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x72, 0x6f, 0x63, 0x63, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, -0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, -0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x4d, 0x6f, 0x75, -0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, -0x4d, 0x79, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, -0x65, 0x0, 0x4e, 0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20, -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x70, 0x61, 0x6c, 0x20, -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, -0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, -0x4e, 0x65, 0x77, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x45, 0x61, -0x73, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, -0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, -0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x41, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x6c, 0x74, 0x61, 0x69, 0x20, 0x53, 0x74, 0x61, +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x20, 0x53, 0x74, 0x61, 0x6e, +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x61, 0x62, 0x69, 0x63, 0x20, 0x53, +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, +0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x73, 0x74, +0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, +0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, +0x69, 0x6d, 0x65, 0x0, 0x41, 0x55, 0x53, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x75, 0x73, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, +0x6c, 0x20, 0x57, 0x2e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, +0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, +0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x65, 0x72, 0x62, 0x61, 0x69, 0x6a, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61, +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x68, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x61, 0x6e, 0x67, 0x6c, 0x61, 0x64, 0x65, 0x73, +0x68, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x65, 0x6c, 0x61, +0x72, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x42, 0x6f, +0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, +0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, +0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x61, 0x70, 0x65, 0x20, 0x56, +0x65, 0x72, 0x64, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, +0x61, 0x75, 0x63, 0x61, 0x73, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, +0x65, 0x0, 0x43, 0x65, 0x6e, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, +0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x42, 0x72, 0x61, 0x7a, +0x69, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, +0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x45, 0x75, 0x72, +0x6f, 0x70, 0x65, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, +0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, +0x0, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, +0x6d, 0x65, 0x0, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, +0x6d, 0x65, 0x0, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53, +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x43, 0x75, 0x62, 0x61, 0x20, 0x53, 0x74, +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x44, 0x61, 0x74, 0x65, 0x6c, 0x69, 0x6e, 0x65, +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x41, 0x66, +0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, +0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x2e, 0x20, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, +0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, +0x29, 0x0, 0x45, 0x67, 0x79, 0x70, 0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, +0x65, 0x0, 0x45, 0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x69, 0x6a, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x46, 0x4c, 0x45, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x4d, 0x54, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, +0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x47, 0x54, 0x42, 0x20, 0x53, +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x69, 0x74, 0x69, 0x20, 0x53, +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x61, +0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69, +0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x72, 0x61, 0x6e, +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x49, 0x73, 0x72, 0x61, 0x65, +0x6c, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4a, 0x6f, 0x72, 0x64, +0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4b, 0x61, 0x6c, +0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, +0x6d, 0x65, 0x0, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, +0x6d, 0x65, 0x0, 0x4c, 0x69, 0x62, 0x79, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, +0x6d, 0x65, 0x0, 0x4c, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4c, 0x6f, 0x72, 0x64, 0x20, 0x48, 0x6f, 0x77, 0x65, 0x20, +0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, +0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x67, 0x61, +0x6c, 0x6c, 0x61, 0x6e, 0x65, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, +0x0, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, +0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x20, 0x45, 0x61, 0x73, 0x74, +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x6f, 0x6e, 0x74, 0x65, +0x76, 0x69, 0x64, 0x65, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, +0x4d, 0x6f, 0x72, 0x6f, 0x63, 0x63, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, +0x65, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, +0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x29, 0x0, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, +0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4d, 0x79, 0x61, +0x6e, 0x6d, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, +0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x70, 0x61, 0x6c, 0x20, 0x53, 0x74, 0x61, +0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, +0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x65, 0x77, +0x66, 0x6f, 0x75, 0x6e, 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, +0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x45, 0x61, 0x73, +0x74, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, +0x68, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, +0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, +0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x41, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, -0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x72, 0x61, -0x67, 0x75, 0x61, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, -0x6f, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, -0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x33, 0x0, -0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x30, 0x0, -0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x31, 0x0, -0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, -0x65, 0x0, 0x53, 0x41, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, -0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x57, 0x65, 0x73, 0x74, 0x65, -0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x6d, -0x6f, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x45, 0x20, -0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, -0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, -0x6d, 0x65, 0x0, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x72, 0x69, 0x20, 0x4c, 0x61, 0x6e, 0x6b, 0x61, 0x20, -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x79, 0x72, 0x69, 0x61, 0x20, -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, -0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x61, 0x73, 0x6d, 0x61, -0x6e, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, -0x6b, 0x79, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, -0x6e, 0x67, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, -0x72, 0x6b, 0x65, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, -0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, -0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, -0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x54, 0x43, 0x2d, -0x30, 0x32, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32, -0x0, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, -0x54, 0x69, 0x6d, 0x65, 0x0, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x20, 0x53, 0x74, 0x61, -0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, -0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, -0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, -0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, -0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x41, -0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, -0x73, 0x74, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, -0x54, 0x69, 0x6d, 0x65, 0x0, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, -0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x4b, 0x6f, 0x72, 0x65, 0x61, 0x20, 0x53, -0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0 +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x28, 0x4d, 0x65, 0x78, 0x69, +0x63, 0x6f, 0x29, 0x0, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, +0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x20, 0x53, 0x74, 0x61, 0x6e, +0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x6f, 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x53, 0x74, +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, +0x69, 0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x33, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, +0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x30, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x20, 0x54, 0x69, +0x6d, 0x65, 0x20, 0x5a, 0x6f, 0x6e, 0x65, 0x20, 0x31, 0x31, 0x0, 0x52, 0x75, 0x73, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x53, +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x45, 0x61, 0x73, 0x74, +0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x41, +0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, +0x6d, 0x65, 0x0, 0x53, 0x41, 0x20, 0x57, 0x65, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x20, 0x50, 0x69, 0x65, 0x72, 0x72, 0x65, +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, 0x6b, 0x68, 0x61, +0x6c, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, +0x6d, 0x6f, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x61, +0x6f, 0x20, 0x54, 0x6f, 0x6d, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, +0x0, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, +0x6d, 0x65, 0x0, 0x53, 0x45, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, +0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, +0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, +0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x53, 0x72, 0x69, 0x20, +0x4c, 0x61, 0x6e, 0x6b, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, +0x53, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, +0x53, 0x79, 0x72, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, +0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, +0x0, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, +0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x63, 0x61, 0x6e, 0x74, 0x69, 0x6e, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x62, 0x61, 0x69, 0x6b, 0x61, 0x6c, 0x20, +0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79, +0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x54, 0x75, 0x72, 0x6b, 0x73, +0x20, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x53, 0x74, +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, 0x45, 0x61, 0x73, 0x74, 0x65, +0x72, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x55, 0x53, 0x20, +0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, +0x6d, 0x65, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x39, 0x0, 0x55, 0x54, 0x43, +0x2d, 0x30, 0x38, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, +0x32, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x0, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x20, 0x53, +0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, +0x73, 0x74, 0x6f, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, +0x2e, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, +0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, 0x20, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, +0x69, 0x63, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x2e, +0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, +0x65, 0x0, 0x57, 0x2e, 0x20, 0x4d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69, 0x61, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, +0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x20, 0x53, 0x74, +0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, 0x20, 0x42, 0x61, 0x6e, +0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x0, 0x57, 0x65, 0x73, 0x74, +0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, +0x6d, 0x65, 0x0, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, +0x54, 0x69, 0x6d, 0x65, 0x0 }; static const char ianaIdData[] = { +0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x76, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61, +0x72, 0x61, 0x77, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75, +0x2d, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, +0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65, 0x6c, +0x65, 0x6d, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65, 0x6b, 0x0, 0x41, 0x6e, 0x74, +0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79, 0x6f, 0x77, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, +0x63, 0x2f, 0x43, 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, +0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, +0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x69, +0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0, 0x41, 0x73, +0x69, 0x61, 0x2f, 0x41, 0x73, 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, +0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x73, 0x74, +0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61, +0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0, 0x41, 0x73, +0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74, +0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74, +0x68, 0x65, 0x72, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x6e, 0x61, 0x75, 0x6c, 0x0, 0x41, 0x6d, +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x0, +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x0, 0x50, 0x61, 0x63, +0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0, 0x41, 0x75, +0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, +0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, +0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a, +0x75, 0x72, 0x6f, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, +0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0, +0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x45, 0x69, 0x72, 0x75, 0x6e, 0x65, 0x70, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x61, 0x72, +0x69, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x20, +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61, +0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x75, 0x76, 0x69, 0x6b, 0x20, 0x41, 0x6d, 0x65, +0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x0, 0x41, 0x73, 0x69, +0x61, 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, +0x69, 0x61, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f, 0x47, +0x72, 0x61, 0x6e, 0x64, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x64, 0x75, 0x7a, 0x0, 0x45, +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, +0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, +0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x45, +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, +0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6f, 0x66, 0x69, 0x61, 0x0, +0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75, 0x73, 0x63, 0x61, 0x74, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, +0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x64, 0x72, 0x69, +0x64, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0, +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d, 0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x0, 0x41, 0x66, +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x72, 0x63, 0x74, 0x69, 0x63, 0x2f, +0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, +0x67, 0x68, 0x64, 0x61, 0x64, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, 0x61, 0x79, +0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x77, 0x61, 0x69, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, +0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0, 0x50, 0x61, 0x63, +0x69, 0x66, 0x69, 0x63, 0x2f, 0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, +0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61, 0x6e, 0x63, 0x6f, 0x75, +0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x20, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0, 0x41, 0x73, +0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, +0x6e, 0x61, 0x63, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61, 0x0, 0x45, +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x7a, +0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x70, 0x6f, 0x72, 0x6f, +0x7a, 0x68, 0x79, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63, 0x69, 0x6f, +0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, 0x68, 0x72, +0x61, 0x6e, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, -0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, -0x68, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53, 0x61, 0x62, 0x6c, 0x6f, 0x6e, 0x0, 0x41, -0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, -0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, -0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, -0x65, 0x6e, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, -0x5f, 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61, 0x6e, 0x63, 0x6f, -0x75, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x20, -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0, 0x45, -0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x32, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, -0x5f, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, -0x73, 0x61, 0x72, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, -0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, -0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, -0x69, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c, 0x69, -0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x0, 0x41, -0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67, 0x61, 0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0, 0x41, 0x73, -0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65, 0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, -0x6e, 0x69, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c, 0x6c, -0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, -0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e, 0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0, 0x41, 0x73, -0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, -0x67, 0x75, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x67, 0x68, 0x64, 0x61, 0x64, 0x0, 0x45, 0x75, 0x72, -0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x72, -0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, -0x6d, 0x71, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, -0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x61, 0x6c, 0x6c, 0x69, 0x6e, -0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68, 0x6f, 0x74, 0x74, 0x0, -0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73, 0x68, 0x69, 0x0, 0x45, 0x75, -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x61, 0x72, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x6b, 0x61, -0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, -0x73, 0x73, 0x61, 0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, -0x4d, 0x54, 0x2d, 0x38, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75, 0x6d, -0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x66, 0x61, 0x74, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x54, 0x6f, 0x72, 0x74, 0x6f, 0x6c, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, -0x70, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0, 0x45, -0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x61, 0x75, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, -0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72, 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, -0x54, 0x2d, 0x31, 0x33, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, -0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73, -0x65, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, -0x65, 0x2f, 0x55, 0x7a, 0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, -0x70, 0x6f, 0x72, 0x6f, 0x7a, 0x68, 0x79, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, -0x72, 0x6f, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, -0x75, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, -0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, -0x2f, 0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, -0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75, 0x74, -0x68, 0x5f, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0, 0x41, 0x66, -0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69, -0x6d, 0x70, 0x68, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, -0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x69, 0x67, 0x61, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, -0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x73, 0x69, 0x62, -0x69, 0x72, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, -0x56, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x6f, 0x64, -0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6f, 0x66, 0x69, 0x61, 0x0, -0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, -0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, -0x75, 0x74, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x20, 0x45, 0x75, -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x65, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, -0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65, 0x68, 0x72, 0x61, 0x6e, 0x0, -0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, -0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, -0x6e, 0x61, 0x63, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, -0x72, 0x69, 0x76, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x72, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x6e, -0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, -0x70, 0x65, 0x2f, 0x54, 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, -0x65, 0x6e, 0x61, 0x64, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0, 0x45, 0x75, 0x72, 0x6f, -0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73, 0x62, 0x6f, 0x6e, 0x20, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x4d, -0x61, 0x64, 0x65, 0x69, 0x72, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, -0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72, -0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e, 0x61, 0x67, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, -0x6c, 0x61, 0x6e, 0x74, 0x79, 0x72, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x61, 0x6d, 0x61, -0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0, 0x41, -0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, -0x69, 0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, -0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, -0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67, 0x6f, 0x6e, 0x0, 0x41, 0x66, -0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, -0x6d, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x50, 0x72, 0x69, -0x6e, 0x63, 0x65, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, -0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, -0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61, 0x6c, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69, -0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61, 0x6e, 0x0, 0x45, -0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, -0x5f, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, -0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x73, 0x69, -0x61, 0x2f, 0x41, 0x6e, 0x61, 0x64, 0x79, 0x72, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x67, 0x6f, -0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, 0x6c, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75, -0x73, 0x63, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0, 0x45, 0x75, -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, -0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, -0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, -0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x69, 0x73, 0x65, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, -0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, -0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x61, 0x5f, 0x56, -0x69, 0x73, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x56, -0x65, 0x6c, 0x68, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, -0x76, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0, 0x45, 0x74, -0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, -0x4c, 0x75, 0x63, 0x69, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0, 0x41, 0x66, 0x72, -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61, 0x62, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x52, -0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x6a, -0x75, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, -0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, -0x6c, 0x61, 0x76, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x0, -0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, -0x2d, 0x35, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69, -0x6c, 0x6c, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0, 0x41, -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, -0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x75, 0x76, 0x69, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, -0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, -0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, -0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, -0x65, 0x6c, 0x62, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x72, 0x5f, -0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0, 0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0, 0x41, 0x66, -0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, -0x4d, 0x61, 0x6a, 0x75, 0x72, 0x6f, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, -0x6c, 0x65, 0x69, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69, 0x0, -0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73, 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, -0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x33, 0x0, 0x41, -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, -0x61, 0x64, 0x72, 0x69, 0x64, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0, 0x41, -0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, -0x74, 0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x39, 0x0, 0x41, 0x6d, 0x65, -0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6e, 0x65, 0x61, 0x75, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, -0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74, 0x6c, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d, -0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, -0x69, 0x63, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, -0x6f, 0x70, 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, -0x2f, 0x4d, 0x63, 0x4d, 0x75, 0x72, 0x64, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0, -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, -0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, -0x2f, 0x57, 0x61, 0x6b, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, -0x69, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f, 0x74, 0x74, 0x65, 0x0, 0x41, 0x74, 0x6c, -0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x65, 0x72, 0x6f, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, -0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, -0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x6a, 0x65, 0x76, -0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, -0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, -0x71, 0x75, 0x61, 0x72, 0x69, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, -0x4d, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, -0x63, 0x69, 0x6f, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0, -0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, -0x2f, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x79, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e, -0x6e, 0x65, 0x73, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, -0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x6f, -0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69, -0x70, 0x61, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, -0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, -0x75, 0x62, 0x61, 0x69, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65, 0x6c, 0x65, -0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x0, 0x45, 0x75, -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, -0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, -0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e, 0x6f, 0x6c, 0x75, 0x6c, 0x75, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, -0x31, 0x32, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, -0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x50, -0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x45, 0x75, 0x72, 0x6f, -0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d, -0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x6f, 0x6c, 0x67, 0x6f, -0x67, 0x72, 0x61, 0x64, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0, -0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, -0x6c, 0x74, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x75, 0x62, 0x61, 0x0, 0x41, 0x6d, +0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f, 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, +0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, +0x35, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0, +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, +0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, +0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, +0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0, +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, +0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x6f, 0x73, 0x74, 0x61, 0x6e, 0x61, +0x79, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x33, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48, 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, +0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48, +0x6f, 0x62, 0x61, 0x72, 0x74, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72, +0x69, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69, +0x63, 0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0, +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, +0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67, 0x6f, 0x20, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79, +0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65, 0x20, 0x50, 0x61, 0x63, 0x69, +0x66, 0x69, 0x63, 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, +0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79, +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x0, +0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0, 0x45, 0x74, 0x63, +0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x37, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d, +0x75, 0x64, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0, 0x41, 0x73, +0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61, +0x62, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0, +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, +0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65, +0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79, 0x72, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x79, +0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0, +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, +0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, +0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, +0x54, 0x68, 0x75, 0x6c, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, +0x6b, 0x73, 0x68, 0x61, 0x76, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e, +0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x43, 0x75, 0x72, 0x72, +0x65, 0x6e, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, +0x73, 0x75, 0x6e, 0x64, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e, +0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72, +0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x6a, 0x75, 0x6c, 0x0, 0x41, 0x66, 0x72, 0x69, +0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72, +0x75, 0x73, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, +0x6c, 0x6d, 0x65, 0x72, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45, 0x75, 0x63, 0x6c, 0x61, +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0, 0x41, 0x73, 0x69, +0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69, +0x70, 0x61, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0, 0x45, 0x75, 0x72, +0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, +0x69, 0x63, 0x61, 0x2f, 0x4d, 0x63, 0x4d, 0x75, 0x72, 0x64, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, +0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32, 0x0, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, +0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, +0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x20, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65, +0x6e, 0x6e, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, +0x2f, 0x57, 0x69, 0x6e, 0x61, 0x6d, 0x61, 0x63, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, +0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x41, 0x6d, 0x65, +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, +0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, +0x72, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, +0x74, 0x61, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0, +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71, +0x61, 0x6c, 0x75, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65, +0x61, 0x6c, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69, 0x67, 0x6f, 0x6e, 0x20, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x20, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61, 0x79, 0x0, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0, 0x50, 0x61, +0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, +0x63, 0x61, 0x2f, 0x44, 0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55, 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, +0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73, +0x6c, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x39, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, +0x2f, 0x47, 0x61, 0x6c, 0x61, 0x70, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, +0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, +0x66, 0x61, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x42, 0x61, +0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20, +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63, 0x74, 0x6f, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, +0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65, 0x6e, 0x61, +0x64, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0, 0x41, 0x6d, +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, +0x75, 0x6e, 0x65, 0x61, 0x75, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d, 0x65, 0x20, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x64, +0x74, 0x68, 0x61, 0x62, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x0, 0x45, +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x0, 0x45, 0x75, 0x72, +0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, +0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64, 0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, +0x2d, 0x33, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c, 0x6c, 0x65, +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x0, +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, +0x2d, 0x31, 0x32, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0, 0x41, +0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0, 0x41, 0x6d, +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61, 0x75, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75, +0x74, 0x68, 0x5f, 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, +0x6c, 0x5f, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, +0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, +0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, +0x61, 0x6e, 0x61, 0x2f, 0x54, 0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, +0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x20, +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, +0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, +0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x45, +0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, +0x61, 0x6d, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x67, 0x6f, 0x74, 0x61, 0x0, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x20, 0x41, 0x6d, 0x65, +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74, 0x6c, 0x61, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, +0x63, 0x2f, 0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x69, +0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d, 0x73, 0x6b, 0x0, 0x41, 0x66, +0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, +0x69, 0x63, 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, +0x72, 0x75, 0x62, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69, 0x72, 0x75, 0x74, 0x0, 0x45, 0x74, 0x63, +0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f, +0x65, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x45, 0x74, 0x63, +0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67, +0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, +0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, +0x63, 0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, +0x54, 0x72, 0x75, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0, +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67, +0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74, 0x79, 0x72, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, -0x2f, 0x49, 0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, -0x56, 0x61, 0x64, 0x75, 0x7a, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, -0x65, 0x7a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69, 0x6e, -0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x20, 0x41, 0x6d, 0x65, 0x72, -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x65, 0x69, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, -0x65, 0x63, 0x69, 0x66, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x72, -0x65, 0x6d, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f, 0x75, 0x70, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, -0x2b, 0x32, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0, 0x41, 0x72, 0x63, 0x74, -0x69, 0x63, 0x2f, 0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, -0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, -0x72, 0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50, 0x65, 0x72, 0x74, 0x68, 0x0, 0x45, -0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, -0x61, 0x6e, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e, 0x63, -0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, -0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, -0x70, 0x65, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x36, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x47, 0x6f, 0x64, 0x74, 0x68, 0x61, 0x62, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x57, 0x61, 0x72, -0x73, 0x61, 0x77, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, -0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, -0x79, 0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, -0x44, 0x61, 0x76, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69, 0x72, 0x75, 0x74, 0x0, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, -0x2f, 0x4b, 0x61, 0x72, 0x61, 0x63, 0x68, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x63, 0x63, 0x72, -0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69, 0x63, -0x6f, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0, 0x41, 0x6d, 0x65, -0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, -0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x20, 0x41, 0x6d, 0x65, -0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x6e, -0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x57, -0x69, 0x6e, 0x61, 0x6d, 0x61, 0x63, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75, -0x63, 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, -0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x61, 0x72, 0x61, -0x77, 0x61, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, -0x2f, 0x42, 0x6f, 0x67, 0x6f, 0x74, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, -0x65, 0x5f, 0x56, 0x65, 0x72, 0x64, 0x65, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61, -0x72, 0x77, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67, 0x79, 0x61, 0x6e, 0x67, 0x0, -0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, 0x69, 0x62, -0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72, 0x75, 0x73, 0x61, 0x6c, 0x65, -0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0, 0x50, -0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, -0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, -0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0, -0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72, -0x73, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, -0x61, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x37, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, -0x2f, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, -0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73, 0x6c, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, -0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x77, 0x61, 0x69, 0x74, 0x0, 0x50, -0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, -0x63, 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x73, -0x74, 0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, -0x6e, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0, -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x0, 0x49, -0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, -0x54, 0x2b, 0x36, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0, -0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, -0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a, 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x41, 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x69, -0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x69, 0x72, -0x75, 0x6e, 0x65, 0x70, 0x65, 0x0, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, -0x67, 0x69, 0x6e, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x43, -0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0, 0x41, 0x6e, 0x74, -0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, -0x6e, 0x2f, 0x4d, 0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, -0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61, -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, -0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0, 0x45, 0x75, -0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, -0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f, 0x65, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x79, 0x61, 0x70, -0x75, 0x72, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x69, 0x73, 0x62, 0x61, -0x6e, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x69, 0x6e, 0x64, 0x65, 0x6d, 0x61, -0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, -0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, -0x79, 0x6f, 0x77, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0, 0x41, -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x20, -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, -0x5f, 0x52, 0x69, 0x6f, 0x6a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, -0x74, 0x69, 0x6e, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c, 0x65, 0x67, 0x6f, 0x73, 0x20, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6c, 0x74, -0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, -0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, -0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75, 0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, -0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, -0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, -0x55, 0x73, 0x68, 0x75, 0x61, 0x69, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, -0x6d, 0x61, 0x72, 0x63, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, -0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, -0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, -0x63, 0x61, 0x2f, 0x50, 0x61, 0x6c, 0x6d, 0x65, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, -0x72, 0x6f, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71, 0x61, 0x6c, 0x75, 0x69, -0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x41, -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69, 0x67, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e, 0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61, 0x79, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x42, 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x69, 0x79, 0x61, 0x64, 0x68, -0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, -0x6f, 0x6b, 0x79, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x75, -0x72, 0x79, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, -0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x20, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67, -0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, -0x76, 0x61, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0, 0x41, 0x6d, 0x65, -0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79, 0x5f, 0x52, 0x69, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x52, 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, -0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, -0x66, 0x61, 0x78, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x42, 0x61, -0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x20, -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63, 0x74, 0x6f, 0x6e, 0x0, 0x41, 0x66, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, -0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, -0x61, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75, 0x2d, -0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79, -0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6c, -0x67, 0x69, 0x65, 0x72, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x79, 0x61, 0x71, -0x75, 0x69, 0x6c, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x73, -0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, -0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, -0x5f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, -0x61, 0x79, 0x0, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44, 0x54, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, -0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6c, 0x61, -0x70, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c, -0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, -0x50, 0x61, 0x6c, 0x61, 0x75, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x41, -0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x6e, 0x64, -0x79, 0x67, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0, 0x41, -0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76, 0x69, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, -0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, -0x61, 0x72, 0x6b, 0x73, 0x68, 0x61, 0x76, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x69, 0x6a, -0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x73, 0x75, 0x6e, 0x64, 0x0, 0x41, -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65, 0x6c, 0x65, 0x6d, 0x79, -0x0, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, -0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x73, -0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65, -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x20, 0x41, 0x6d, 0x65, -0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x20, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x54, 0x65, 0x6c, 0x6c, 0x5f, 0x43, -0x69, 0x74, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, -0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, -0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, -0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x41, 0x6d, -0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, -0x65, 0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, -0x61, 0x6d, 0x6f, 0x72, 0x6f, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6c, 0x65, -0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, -0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, -0x69, 0x75, 0x65, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, -0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x20, 0x41, 0x73, -0x69, 0x61, 0x2f, 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, -0x54, 0x2d, 0x32, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73, 0x6b, 0x0, 0x41, 0x66, 0x72, -0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x62, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48, -0x6f, 0x62, 0x61, 0x72, 0x74, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72, -0x69, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x20, -0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, -0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, -0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55, 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, -0x2f, 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x6e, -0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0, -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, -0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0, 0x41, 0x75, 0x73, -0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, -0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, -0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0, -0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, -0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, -0x2f, 0x42, 0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, -0x77, 0x5f, 0x59, 0x6f, 0x72, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x41, -0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, -0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, -0x6f, 0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f, -0x79, 0x61, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, -0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, -0x61, 0x6c, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, -0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, -0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, -0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, -0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, -0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x34, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x32, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x30, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x36, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x33, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x33, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x30, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x31, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x34, -0x35, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x33, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x33, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x31, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30, -0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x33, -0x30, 0x0 +0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, +0x75, 0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75, 0x63, +0x68, 0x69, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x46, 0x69, 0x6a, 0x69, 0x0, 0x41, 0x6d, +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, +0x68, 0x69, 0x6d, 0x70, 0x68, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0, +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, +0x2f, 0x4b, 0x69, 0x72, 0x6f, 0x76, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x6f, 0x6c, 0x67, 0x6f, 0x67, +0x72, 0x61, 0x64, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, +0x75, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x32, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, +0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x6e, 0x64, 0x79, 0x67, 0x61, +0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x20, +0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, 0x61, +0x6d, 0x6f, 0x72, 0x6f, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0, 0x49, 0x6e, 0x64, 0x69, +0x61, 0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, +0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x0, 0x41, +0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, +0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79, +0x5f, 0x52, 0x69, 0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x6e, 0x6b, 0x69, +0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f, +0x6c, 0x75, 0x74, 0x65, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, +0x69, 0x63, 0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, +0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x20, +0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, +0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0, 0x45, +0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, +0x76, 0x65, 0x72, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x69, 0x73, 0x65, 0x0, 0x41, 0x66, +0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x64, 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0, 0x45, 0x75, 0x72, +0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73, +0x62, 0x6f, 0x6e, 0x20, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x64, 0x65, 0x69, 0x72, 0x61, +0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56, 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, +0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x20, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73, +0x69, 0x6e, 0x67, 0x65, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, +0x73, 0x61, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, +0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a, 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0, 0x50, +0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72, 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0, 0x41, 0x6d, +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, +0x65, 0x2f, 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52, 0x69, 0x79, 0x61, 0x64, 0x68, +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x73, +0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e, +0x61, 0x64, 0x79, 0x72, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, +0x65, 0x2f, 0x43, 0x68, 0x69, 0x73, 0x69, 0x6e, 0x61, 0x75, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, +0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e, 0x6e, 0x65, +0x73, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, +0x6f, 0x6b, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0, 0x45, 0x74, 0x63, +0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x32, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73, +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x65, 0x6e, 0x6e, 0x65, 0x0, 0x41, 0x66, 0x72, +0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68, 0x6f, 0x74, 0x74, 0x0, 0x45, 0x53, 0x54, 0x35, 0x45, +0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69, 0x61, 0x0, 0x50, 0x61, 0x63, +0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, +0x33, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x20, 0x45, +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55, 0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, +0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, +0x6f, 0x61, 0x5f, 0x56, 0x69, 0x73, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, +0x74, 0x6f, 0x5f, 0x56, 0x65, 0x6c, 0x68, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73, +0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x0, 0x41, +0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, +0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, +0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72, 0x61, 0x64, 0x0, +0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75, +0x69, 0x6c, 0x6c, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0, +0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x62, 0x61, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, +0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0, 0x50, +0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61, 0x6c, 0x0, 0x41, +0x73, 0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e, +0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, +0x74, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x73, 0x69, +0x61, 0x2f, 0x46, 0x61, 0x6d, 0x61, 0x67, 0x75, 0x73, 0x74, 0x61, 0x20, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63, +0x6f, 0x73, 0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f, +0x75, 0x70, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, +0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76, +0x69, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x74, 0x6f, 0x6c, 0x61, 0x0, 0x41, +0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, +0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b, +0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x63, 0x63, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, +0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, +0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65, 0x20, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, +0x2f, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, +0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67, 0x61, +0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65, +0x6c, 0x65, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x38, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, +0x2f, 0x54, 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0, +0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70, 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0, 0x41, 0x66, +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0, +0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, +0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72, 0x61, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e, +0x6f, 0x6c, 0x75, 0x6c, 0x75, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69, +0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x4a, 0x75, 0x62, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46, 0x61, 0x65, 0x72, 0x6f, +0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b, +0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x20, 0x41, 0x6d, 0x65, +0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, +0x61, 0x63, 0x65, 0x69, 0x6f, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69, 0x66, 0x65, +0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65, 0x6d, 0x0, 0x45, 0x75, +0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50, 0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69, +0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, 0x6e, 0x61, 0x20, +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c, +0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, +0x52, 0x69, 0x67, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53, +0x61, 0x62, 0x6c, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x65, 0x0, +0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0, 0x41, 0x73, 0x69, +0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x36, 0x0, 0x45, 0x75, +0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x6a, 0x65, 0x76, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, +0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, +0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x6e, 0x61, +0x72, 0x79, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e, 0x76, 0x69, +0x6c, 0x6c, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0, 0x41, 0x6d, 0x65, +0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, +0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67, +0x79, 0x61, 0x6e, 0x67, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61, +0x67, 0x6f, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0, 0x41, 0x66, +0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x0, +0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x39, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, 0x6e, +0x69, 0x73, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0, 0x45, +0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x76, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75, 0x6d, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72, +0x73, 0x65, 0x79, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75, +0x61, 0x72, 0x69, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e, 0x61, 0x67, 0x61, +0x0, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56, 0x65, 0x72, 0x64, 0x65, +0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, +0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47, +0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x0, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, +0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, +0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, +0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69, 0x6f, 0x6a, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, +0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c, +0x65, 0x67, 0x6f, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, +0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6c, 0x74, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, +0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, +0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75, +0x69, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, +0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, +0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68, 0x75, 0x61, 0x69, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, +0x63, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x6a, +0x75, 0x79, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0, 0x50, +0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, +0x61, 0x6e, 0x67, 0x75, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0, 0x50, 0x61, 0x63, +0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, +0x2f, 0x44, 0x61, 0x72, 0x77, 0x69, 0x6e, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74, 0x63, +0x61, 0x69, 0x72, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0, 0x50, 0x61, 0x63, +0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, +0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50, +0x65, 0x72, 0x74, 0x68, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0, 0x49, +0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, +0x61, 0x68, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, +0x6c, 0x65, 0x73, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74, +0x6c, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0, 0x41, 0x66, 0x72, +0x69, 0x63, 0x61, 0x2f, 0x41, 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, +0x36, 0x0, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x66, 0x61, 0x74, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, +0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x42, 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c, +0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, +0x72, 0x61, 0x63, 0x68, 0x69, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0, 0x41, 0x66, 0x72, +0x69, 0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, +0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, +0x44, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, 0x6b, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, +0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f, +0x74, 0x74, 0x65, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0, 0x41, 0x73, +0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x72, +0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f, 0x63, 0x6b, +0x68, 0x6f, 0x6c, 0x6d, 0x0, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73, +0x68, 0x69, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, +0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, +0x73, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x0, 0x41, +0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, +0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, +0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, +0x6c, 0x61, 0x69, 0x64, 0x65, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0, 0x41, 0x6d, +0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, +0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, +0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, +0x59, 0x6f, 0x72, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0, 0x41, 0x6d, 0x65, +0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, +0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73, 0x6e, +0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, +0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61, +0x6e, 0x61, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x0, 0x45, 0x75, +0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, +0x61, 0x2f, 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, +0x61, 0x61, 0x74, 0x61, 0x72, 0x0, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, +0x61, 0x70, 0x6f, 0x6c, 0x69, 0x73, 0x0, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, +0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, +0x65, 0x72, 0x6c, 0x69, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0, +0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b, +0x75, 0x74, 0x73, 0x6b, 0x0, 0x55, 0x54, 0x43, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2d, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2d, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2d, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2d, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2d, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2d, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2d, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2d, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2d, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2b, 0x30, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2b, 0x30, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2b, 0x30, 0x33, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2b, 0x30, 0x34, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x35, 0x3a, 0x34, 0x35, 0x0, 0x55, +0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x36, 0x3a, 0x33, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2b, 0x30, 0x37, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2b, 0x30, 0x38, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2b, 0x30, 0x39, 0x3a, 0x33, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x30, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2b, 0x31, 0x31, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x0, 0x55, +0x54, 0x43, 0x2b, 0x31, 0x33, 0x3a, 0x30, 0x30, 0x0, 0x55, 0x54, 0x43, 0x2b, 0x31, 0x34, 0x3a, 0x30, 0x30, 0x0 }; // GENERATED PART ENDS HERE From 9ff6df892925b4b56b842ff206dd672e75e36138 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 24 May 2019 14:40:54 +0200 Subject: [PATCH 103/122] Convert the one extant use of QTime as a timer to use a local class Use QDateTime::currentMSecsSinceEpoch() instead of a QTime with funky wrapping at midnight and potential DST glitches. Change-Id: I2455db5778635fc00b4ffdef6edee6d6793e50eb Reviewed-by: Thiago Macieira --- src/tools/androiddeployqt/main.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp index 01c392f8f9..65d95362f7 100644 --- a/src/tools/androiddeployqt/main.cpp +++ b/src/tools/androiddeployqt/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. @@ -52,6 +52,21 @@ #define QT_POPEN_READ "r" #endif +class ActionTimer +{ + qint64 started; +public: + ActionTimer() = default; + void start() + { + started = QDateTime::currentMSecsSinceEpoch(); + } + int elapsed() + { + return int(QDateTime::currentMSecsSinceEpoch() - started); + } +}; + static const bool mustReadOutputAnyway = true; // pclose seems to return the wrong error code unless we read the output void deleteRecursively(const QString &dirName) @@ -138,7 +153,7 @@ struct Options bool gradle; bool auxMode; bool stripLibraries = true; - QTime timer; + ActionTimer timer; // External tools QString sdkPath; From d2090b764aa23f9b50215aa5d276583117c328d3 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 24 May 2019 14:29:54 +0200 Subject: [PATCH 104/122] Convert some deprecations to QT_DEPRECATED_X To make their replacements easier to find. They're in the documentation, but weren't in the source. Change-Id: Iea936062feaead636e3dd8e93f0b4c82ed8876cb Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetime.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index 79fd25d762..1ff187a9bd 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -107,8 +107,8 @@ public: QString toString(QStringView format) const; #endif #if QT_DEPRECATED_SINCE(5,0) -QT_DEPRECATED inline bool setYMD(int y, int m, int d) -{ if (uint(y) <= 99) y += 1900; return setDate(y, m, d); } + QT_DEPRECATED_X("Use setDate() instead") inline bool setYMD(int y, int m, int d) + { if (uint(y) <= 99) y += 1900; return setDate(y, m, d); } #endif bool setDate(int year, int month, int day); @@ -342,8 +342,8 @@ public: inline bool operator>=(const QDateTime &other) const { return !(*this < other); } #if QT_DEPRECATED_SINCE(5, 2) // ### Qt 6: remove - QT_DEPRECATED void setUtcOffset(int seconds); - QT_DEPRECATED int utcOffset() const; + QT_DEPRECATED_X("Use setOffsetFromUtc() instead") void setUtcOffset(int seconds); + QT_DEPRECATED_X("Use offsetFromUtc() instead") int utcOffset() const; #endif // QT_DEPRECATED_SINCE static QDateTime currentDateTime(); From ed99a591a83a399458f12341d0a1c0b3152f247a Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 6 May 2019 18:19:06 +0200 Subject: [PATCH 105/122] Deprecate use of QTime as a timer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QElapsedTimer does the job better and without the DST kludges. Change-Id: Ic4a566f695648cbe069a21ea8d3e84562b665a3c Reviewed-by: André Hartmann Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetime.cpp | 16 ++++++---------- src/corelib/tools/qdatetime.h | 8 +++++--- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 0f8c8629a8..9220d210f1 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -1686,12 +1686,10 @@ bool QDate::isLeapYear(int y) \brief The QTime class provides clock time functions. - A QTime object contains a clock time, which it can express as the - numbers of hours, minutes, seconds, and milliseconds since - midnight. It can read the current time from the system clock and - measure a span of elapsed time. It provides functions for - comparing times and for manipulating a time by adding a number of - milliseconds. + A QTime object contains a clock time, which it can express as the numbers of + hours, minutes, seconds, and milliseconds since midnight. It provides + functions for comparing times and for manipulating a time by adding a number + of milliseconds. QTime uses the 24-hour clock format; it has no concept of AM/PM. Unlike QDateTime, QTime knows nothing about time zones or @@ -1718,9 +1716,6 @@ bool QDate::isLeapYear(int y) objects; an earlier time is considered smaller than a later one; if A.msecsTo(B) is positive, then A < B. - QTime can be used to measure a span of elapsed time using the - start(), restart(), and elapsed() functions. - \sa QDate, QDateTime */ @@ -2364,7 +2359,7 @@ bool QTime::isValid(int h, int m, int s, int ms) return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000; } - +#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove /*! Sets this time to the current time. This is practical for timing: @@ -2433,6 +2428,7 @@ int QTime::elapsed() const n += 86400 * 1000; return n; } +#endif // Use QElapsedTimer instead ! /***************************************************************************** QDateTime static helper functions diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index 1ff187a9bd..3e3b953b52 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -206,9 +206,11 @@ public: #endif static bool isValid(int h, int m, int s, int ms = 0); - void start(); - int restart(); - int elapsed() const; +#if QT_DEPRECATED_SINCE(5, 14) // ### Qt 6: remove + QT_DEPRECATED_X("Use QElapsedTimer instead") void start(); + QT_DEPRECATED_X("Use QElapsedTimer instead") int restart(); + QT_DEPRECATED_X("Use QElapsedTimer instead") int elapsed() const; +#endif private: enum TimeFlag { NullTime = -1 }; Q_DECL_CONSTEXPR inline int ds() const { return mds == -1 ? 0 : mds; } From 5505d25be972948db1621e1511b89b4144aa8bfc Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 17 May 2019 14:30:10 +0200 Subject: [PATCH 106/122] uic: Remove deprecated options The --no-stringliteral option got introduced by commit d12d2949d1e4ac0 for 5.10.0, but already deprecated in commit ff18b02f21a04f7 for 5.12.0. [ChangeLog][uic] uic does not accept the --no-stringliteral/-s option anymore. Change-Id: I7a0f647ad91b3760bc826884702bf8581f5565f2 Reviewed-by: Jarek Kobus --- src/tools/uic/main.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/tools/uic/main.cpp b/src/tools/uic/main.cpp index 166fe78ff7..e689d477bd 100644 --- a/src/tools/uic/main.cpp +++ b/src/tools/uic/main.cpp @@ -76,10 +76,6 @@ int runUic(int argc, char *argv[]) noImplicitIncludesOption.setDescription(QStringLiteral("Disable generation of #include-directives.")); parser.addOption(noImplicitIncludesOption); - QCommandLineOption noStringLiteralOption(QStringList() << QStringLiteral("s") << QStringLiteral("no-stringliteral")); - noStringLiteralOption.setDescription(QStringLiteral("Deprecated. The use of this option won't take any effect.")); - parser.addOption(noStringLiteralOption); - QCommandLineOption postfixOption(QStringLiteral("postfix")); postfixOption.setDescription(QStringLiteral("Postfix to add to all generated classnames.")); postfixOption.setValueName(QStringLiteral("postfix")); @@ -124,9 +120,6 @@ int runUic(int argc, char *argv[]) } language::setLanguage(language); - if (parser.isSet(noStringLiteralOption)) - fprintf(stderr, "The -s, --no-stringliteral option is deprecated and it won't take any effect.\n"); - QString inputFile; if (!parser.positionalArguments().isEmpty()) inputFile = parser.positionalArguments().at(0); From deaf044b2e5efd2d2c60e80f2593c7f9ab1feda9 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 24 May 2019 10:51:36 +0200 Subject: [PATCH 107/122] Fix deprecation warnings in tst_QUrl Change-Id: I8b1877c57d0bd061908d83c0feacfb4a4d4c3868 Reviewed-by: David Faure --- tests/auto/corelib/io/qurl/tst_qurl.cpp | 129 +++++++++++------------- 1 file changed, 58 insertions(+), 71 deletions(-) diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index 9c106c7f58..daaa5516cd 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -136,8 +136,8 @@ private slots: void emptyQueryOrFragment(); void hasFragment_data(); void hasFragment(); - void setEncodedFragment_data(); - void setEncodedFragment(); + void setFragment_data(); + void setFragment(); void fromEncoded(); void stripTrailingSlash_data(); void stripTrailingSlash(); @@ -350,15 +350,15 @@ void tst_QUrl::comparison() // 6.2.2.1 Make sure hexdecimal characters in percent encoding are // treated case-insensitively QUrl url5; - url5.setEncodedQuery("a=%2a"); + url5.setQuery(QLatin1String("a=%2a")); QUrl url6; - url6.setEncodedQuery("a=%2A"); + url6.setQuery(QLatin1String("a=%2A")); QCOMPARE(url5, url6); QUrl url7; - url7.setEncodedQuery("a=C"); + url7.setQuery(QLatin1String("a=C")); QUrl url8; - url8.setEncodedQuery("a=c"); + url8.setQuery(QLatin1String("a=c")); QVERIFY(url7 != url8); QVERIFY(url7 < url8); @@ -502,7 +502,7 @@ void tst_QUrl::setUrl() QVERIFY(url.isValid()); QCOMPARE(url.scheme(), QString::fromLatin1("file")); QCOMPARE(url.path(), QString::fromLatin1("/")); - QVERIFY(url.encodedQuery().isEmpty()); + QVERIFY(url.query().isEmpty()); QVERIFY(url.userInfo().isEmpty()); QVERIFY(url.authority().isEmpty()); QVERIFY(url.fragment().isEmpty()); @@ -517,7 +517,7 @@ void tst_QUrl::setUrl() QVERIFY(url.isValid()); QCOMPARE(url.scheme(), QString::fromLatin1("http")); QCOMPARE(url.path(), QString()); - QVERIFY(url.encodedQuery().isEmpty()); + QVERIFY(url.query().isEmpty()); QVERIFY(url.userInfo().isEmpty()); QVERIFY(url.fragment().isEmpty()); QCOMPARE(url.host(), QString::fromLatin1("www.foo.bar")); @@ -536,7 +536,7 @@ void tst_QUrl::setUrl() QVERIFY(url.isValid()); QCOMPARE(url.scheme(), QString::fromLatin1("http")); QCOMPARE(url.path(), QString()); - QVERIFY(url.encodedQuery().isEmpty()); + QVERIFY(url.query().isEmpty()); QCOMPARE(url.userName(), QString::fromLatin1("user:")); QCOMPARE(url.password(), QString::fromLatin1("pass@")); QCOMPARE(url.userInfo(), QString::fromLatin1("user%3A:pass@")); @@ -781,7 +781,7 @@ void tst_QUrl::setUrl() QVERIFY(url.isValid()); QCOMPARE(url.scheme(), QString("http")); QCOMPARE(url.host(), QString("1.2.3.4")); - QCOMPARE(url.encodedQuery(), QByteArray("foo")); + QCOMPARE(url.query(QUrl::FullyEncoded), QLatin1String("foo")); } { QUrl url; @@ -798,13 +798,13 @@ void tst_QUrl::setUrl() QCOMPARE(url.scheme(), QString("data")); QCOMPARE(url.host(), QString()); QCOMPARE(url.path(), QString("text/javascript,d5 = 'five\\u0027s';")); - QCOMPARE(url.encodedPath().constData(), "text/javascript,d5%20%3D%20'five%5Cu0027s'%3B"); + QCOMPARE(url.path(QUrl::FullyEncoded), QLatin1String("text/javascript,d5%20%3D%20'five%5Cu0027s'%3B")); } { // invalid port number QUrl url; - url.setEncodedUrl("foo://tel:2147483648"); + url.setUrl(QLatin1String("foo://tel:2147483648"), QUrl::StrictMode); QVERIFY(!url.isValid()); } @@ -1144,7 +1144,7 @@ void tst_QUrl::toString_constructed_data() QTest::addColumn("host"); QTest::addColumn("port"); QTest::addColumn("path"); - QTest::addColumn("query"); + QTest::addColumn("query"); QTest::addColumn("fragment"); QTest::addColumn("asString"); QTest::addColumn("asEncoded"); @@ -1153,19 +1153,19 @@ void tst_QUrl::toString_constructed_data() QString n(""); QTest::newRow("data1") << n << n << n << QString::fromLatin1("qt-project.org") << -1 << QString::fromLatin1("/index.html") - << QByteArray() << n << QString::fromLatin1("//qt-project.org/index.html") + << QString() << n << QString::fromLatin1("//qt-project.org/index.html") << QByteArray("//qt-project.org/index.html") << 0u; - QTest::newRow("data2") << QString::fromLatin1("file") << n << n << n << -1 << QString::fromLatin1("/root") << QByteArray() + QTest::newRow("data2") << QString::fromLatin1("file") << n << n << n << -1 << QString::fromLatin1("/root") << QString() << n << QString::fromLatin1("file:///root") << QByteArray("file:///root") << 0u; QTest::newRow("userAndPass") << QString::fromLatin1("http") << QString::fromLatin1("dfaure") << QString::fromLatin1("kde") - << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n + << "kde.org" << 443 << QString::fromLatin1("/") << QString() << n << QString::fromLatin1("http://dfaure:kde@kde.org:443/") << QByteArray("http://dfaure:kde@kde.org:443/") << 0u; QTest::newRow("PassWithoutUser") << QString::fromLatin1("http") << n << QString::fromLatin1("kde") - << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n + << "kde.org" << 443 << QString::fromLatin1("/") << QString() << n << QString::fromLatin1("http://:kde@kde.org:443/") << QByteArray("http://:kde@kde.org:443/") << 0u; QTest::newRow("PassWithoutUser-RemovePassword") << QString::fromLatin1("http") << n << QString::fromLatin1("kde") - << "kde.org" << 443 << QString::fromLatin1("/") << QByteArray() << n + << "kde.org" << 443 << QString::fromLatin1("/") << QString() << n << QString::fromLatin1("http://kde.org:443/") << QByteArray("http://kde.org:443/") << uint(QUrl::RemovePassword); } @@ -1178,7 +1178,7 @@ void tst_QUrl::toString_constructed() QFETCH(QString, host); QFETCH(int, port); QFETCH(QString, path); - QFETCH(QByteArray, query); + QFETCH(QString, query); QFETCH(QString, fragment); QFETCH(QString, asString); QFETCH(QByteArray, asEncoded); @@ -1198,7 +1198,7 @@ void tst_QUrl::toString_constructed() if (!path.isEmpty()) url.setPath(path); if (!query.isEmpty()) - url.setEncodedQuery(query); + url.setQuery(query, QUrl::StrictMode); if (!fragment.isEmpty()) url.setFragment(fragment); @@ -1757,7 +1757,7 @@ void tst_QUrl::symmetry() QCOMPARE(url.host(QUrl::EncodeUnicode | QUrl::EncodeSpaces), QString::fromUtf8("www.xn--rksmrgs-5wao1o.se")); QCOMPARE(url.path(), QString::fromLatin1("/pub")); // this will be encoded ... - QCOMPARE(url.encodedQuery().constData(), QString::fromLatin1("a=b&a=d%C3%B8&a=f").toLatin1().constData()); + QCOMPARE(url.query(QUrl::FullyEncoded), QLatin1String("a=b&a=d%C3%B8&a=f")); QCOMPARE(url.fragment(), QString::fromUtf8("vræl")); QUrl onlyHost("//qt-project.org"); @@ -2009,7 +2009,7 @@ void tst_QUrl::hasQuery() QUrl qurl(url); QCOMPARE(qurl.hasQuery(), trueFalse); - QCOMPARE(qurl.encodedQuery().isNull(), !trueFalse); + QCOMPARE(qurl.query().isNull(), !trueFalse); } void tst_QUrl::nameprep() @@ -2342,7 +2342,7 @@ void tst_QUrl::tolerantParser() QVERIFY(url.isValid()); QVERIFY(!url.toString().isEmpty()); QCOMPARE(url.path(), QString("/path with spaces.html")); - url.setEncodedUrl("http://www.example.com/path%20with spaces.html", QUrl::StrictMode); + url.setUrl(QLatin1String("http://www.example.com/path%20with spaces.html"), QUrl::StrictMode); QVERIFY(!url.isValid()); QVERIFY(url.toString().isEmpty()); } @@ -2392,36 +2392,36 @@ void tst_QUrl::tolerantParser() QCOMPARE(url.toEncoded(), QByteArray("%25hello.com/f%25")); QCOMPARE(url.toString(), QString("%25hello.com/f%25")); - url.setEncodedUrl("http://www.host.com/foo.php?P0=[2006-3-8]"); + url.setUrl(QLatin1String("http://www.host.com/foo.php?P0=[2006-3-8]"), QUrl::StrictMode); QVERIFY(url.isValid()); QVERIFY(!url.toString().isEmpty()); - url.setEncodedUrl("http://foo.bar/[image][1].jpg"); + url.setUrl(QLatin1String("http://foo.bar/[image][1].jpg"), QUrl::StrictMode); QVERIFY(url.isValid()); QCOMPARE(url.toString(QUrl::FullyEncoded), QString("http://foo.bar/[image][1].jpg")); QCOMPARE(url.toEncoded(), QByteArray("http://foo.bar/[image][1].jpg")); QCOMPARE(url.toString(), QString("http://foo.bar/[image][1].jpg")); - url.setEncodedUrl("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"); + url.setUrl(QLatin1String("http://foo.bar/%5Bimage%5D%5B1%5D.jpg"), QUrl::StrictMode); QVERIFY(url.isValid()); QCOMPARE(url.toString(QUrl::FullyEncoded), QString("http://foo.bar/%5Bimage%5D%5B1%5D.jpg")); QCOMPARE(url.toEncoded(), QByteArray("http://foo.bar/%5Bimage%5D%5B1%5D.jpg")); QCOMPARE(url.toString(), QString("http://foo.bar/%5Bimage%5D%5B1%5D.jpg")); - url.setEncodedUrl("//[::56:56:56:56:56:56:56]"); + url.setUrl(QLatin1String("//[::56:56:56:56:56:56:56]"), QUrl::StrictMode); QCOMPARE(url.toString(QUrl::FullyEncoded), QString("//[0:56:56:56:56:56:56:56]")); QCOMPARE(url.toEncoded(), QByteArray("//[0:56:56:56:56:56:56:56]")); - url.setEncodedUrl("data:text/css,div%20{%20border-right:%20solid;%20}"); + url.setUrl(QLatin1String("data:text/css,div%20{%20border-right:%20solid;%20}"), QUrl::TolerantMode); QCOMPARE(url.toString(QUrl::FullyEncoded), QString("data:text/css,div%20%7B%20border-right:%20solid;%20%7D")); QCOMPARE(url.toEncoded(), QByteArray("data:text/css,div%20%7B%20border-right:%20solid;%20%7D")); QCOMPARE(url.toString(), QString("data:text/css,div %7B border-right: solid; %7D")); } { - QByteArray tsdgeos("http://google.com/c?c=Translation+%C2%BB+trunk|"); + const QString tsdgeos = QLatin1String("http://google.com/c?c=Translation+%C2%BB+trunk|"); QUrl tsdgeosQUrl; - tsdgeosQUrl.setEncodedUrl(tsdgeos, QUrl::TolerantMode); + tsdgeosQUrl.setUrl(tsdgeos, QUrl::TolerantMode); QVERIFY(tsdgeosQUrl.isValid()); // failed in Qt-4.4, works in Qt-4.5 QByteArray tsdgeosExpected("http://google.com/c?c=Translation+%C2%BB+trunk%7C"); QCOMPARE(QString(tsdgeosQUrl.toEncoded()), QString(tsdgeosExpected)); @@ -2626,31 +2626,31 @@ void tst_QUrl::emptyQueryOrFragment() // start with an empty one QUrl url("http://www.foo.bar/baz"); QVERIFY(!url.hasQuery()); - QVERIFY(url.encodedQuery().isNull()); + QVERIFY(url.query().isNull()); // add encodedQuery url.setQuery("abc=def"); QVERIFY(url.hasQuery()); QCOMPARE(url.query(), QString(QLatin1String("abc=def"))); QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?abc=def"))); - url.setEncodedQuery("abc=def"); + url.setQuery(QLatin1String("abc=def")); QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?abc=def"))); // remove encodedQuery url.setQuery(QString()); QVERIFY(!url.hasQuery()); - QVERIFY(url.encodedQuery().isNull()); + QVERIFY(url.query().isNull()); QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz"))); - url.setEncodedQuery(QByteArray()); + url.setQuery(QString()); QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz"))); // add empty encodedQuery url.setQuery(""); QVERIFY(url.hasQuery()); - QVERIFY(url.encodedQuery().isEmpty()); - QVERIFY(!url.encodedQuery().isNull()); + QVERIFY(url.query().isEmpty()); + QVERIFY(!url.query().isNull()); QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?"))); - url.setEncodedQuery(""); + url.setQuery(QLatin1String("")); QCOMPARE(url.toString(), QString(QLatin1String("http://www.foo.bar/baz?"))); } } @@ -2682,35 +2682,33 @@ void tst_QUrl::hasFragment() QCOMPARE(qurl.fragment().isNull(), !trueFalse); } -void tst_QUrl::setEncodedFragment_data() +void tst_QUrl::setFragment_data() { - QTest::addColumn("base"); - QTest::addColumn("fragment"); - QTest::addColumn("expected"); + QTest::addColumn("base"); + QTest::addColumn("fragment"); + QTest::addColumn("expected"); - typedef QByteArray BA; - QTest::newRow("null") << BA("http://www.kde.org") << BA() << BA("http://www.kde.org"); - QTest::newRow("empty") << BA("http://www.kde.org") << BA("") << BA("http://www.kde.org#"); - QTest::newRow("basic test") << BA("http://www.kde.org") << BA("abc") << BA("http://www.kde.org#abc"); - QTest::newRow("initial url has fragment") << BA("http://www.kde.org#old") << BA("new") << BA("http://www.kde.org#new"); - QTest::newRow("encoded fragment") << BA("http://www.kde.org") << BA("a%20c") << BA("http://www.kde.org#a%20c"); - QTest::newRow("with #") << BA("http://www.kde.org") << BA("a#b") << BA("http://www.kde.org#a%23b"); // toString uses "a#b" - QTest::newRow("unicode") << BA("http://www.kde.org") << BA("\xc3\xa9") << BA("http://www.kde.org#%C3%A9"); - QTest::newRow("binary") << BA("http://www.kde.org") << BA("\x00\xc0\x80", 3) << BA("http://www.kde.org#%00%C0%80"); + QTest::newRow("null") << QString::fromLatin1("http://www.kde.org") << QString() << QString::fromLatin1("http://www.kde.org"); + QTest::newRow("empty") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("") << QString::fromLatin1("http://www.kde.org#"); + QTest::newRow("basic test") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("abc") << QString::fromLatin1("http://www.kde.org#abc"); + QTest::newRow("initial url has fragment") << QString::fromLatin1("http://www.kde.org#old") << QString::fromLatin1("new") << QString::fromLatin1("http://www.kde.org#new"); + QTest::newRow("encoded fragment") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("a%20c") << QString::fromLatin1("http://www.kde.org#a%20c"); + QTest::newRow("with #") << QString::fromLatin1("http://www.kde.org") << QString::fromLatin1("a#b") << QString::fromLatin1("http://www.kde.org#a%23b"); // toString uses "a#b" + QTest::newRow("unicode") << QString::fromLatin1("http://www.kde.org") << QString::fromUtf8("\xc3\xa9") << QString::fromLatin1("http://www.kde.org#%C3%A9"); } -void tst_QUrl::setEncodedFragment() +void tst_QUrl::setFragment() { - QFETCH(QByteArray, base); - QFETCH(QByteArray, fragment); - QFETCH(QByteArray, expected); + QFETCH(QString, base); + QFETCH(QString, fragment); + QFETCH(QString, expected); QUrl u; - u.setEncodedUrl(base, QUrl::TolerantMode); + u.setUrl(base, QUrl::TolerantMode); QVERIFY(u.isValid()); - u.setEncodedFragment(fragment); + u.setFragment(fragment); QVERIFY(u.isValid()); QCOMPARE(!fragment.isNull(), u.hasFragment()); - QCOMPARE(QString::fromLatin1(u.toEncoded()), QString::fromLatin1(expected)); + QCOMPARE(QString::fromUtf8(u.toEncoded()), expected); } void tst_QUrl::fromEncoded() @@ -3258,14 +3256,14 @@ void tst_QUrl::isEmptyForEncodedUrl() { { QUrl url; - url.setEncodedUrl("LABEL=USB_STICK", QUrl::TolerantMode); + url.setUrl(QLatin1String("LABEL=USB_STICK"), QUrl::TolerantMode); QVERIFY( url.isValid() ); QCOMPARE( url.path(), QString("LABEL=USB_STICK") ); QVERIFY( !url.isEmpty() ); } { QUrl url; - url.setEncodedUrl("LABEL=USB_STICK", QUrl::TolerantMode); + url.setUrl(QLatin1String("LABEL=USB_STICK"), QUrl::TolerantMode); QVERIFY( url.isValid() ); QVERIFY( !url.isEmpty() ); QCOMPARE( url.path(), QString("LABEL=USB_STICK") ); @@ -3277,7 +3275,7 @@ void tst_QUrl::isEmptyForEncodedUrl() void tst_QUrl::toEncodedNotUsingUninitializedPath() { QUrl url; - url.setEncodedPath("/test.txt"); + url.setPath(QLatin1String("/test.txt")); url.setHost("example.com"); QCOMPARE(url.toEncoded().constData(), "//example.com/test.txt"); @@ -3657,17 +3655,6 @@ void tst_QUrl::componentEncodings() QCOMPARE(url.toString(formatting), (((QString(toString ))))); // the weird () and space is to align the output - if (formatting == QUrl::FullyEncoded) { - QCOMPARE(url.encodedUserName(), userName.toUtf8()); - QCOMPARE(url.encodedPassword(), password.toUtf8()); - // no encodedUserInfo - QCOMPARE(url.encodedHost(), host.toUtf8()); - // no encodedAuthority - QCOMPARE(url.encodedPath(), path.toUtf8()); - QCOMPARE(url.encodedQuery(), query.toUtf8()); - QCOMPARE(url.encodedFragment(), fragment.toUtf8()); - } - // repeat with the URL we got from toString QUrl url2(toString); QCOMPARE(url2.userName(formatting), userName); From de752e8994220639b2934b769e83bab0e56a00c9 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 3 Jun 2019 23:03:30 +0200 Subject: [PATCH 108/122] QLatin1Char: add comparison operators with char When QT_NO_CAST_FROM_ASCII is in effect, `char == QLatinChar` no longer compiles, because the QChar(char) ctor has become private. Fix by supplying the missing mixed-type operators. [ChangeLog][QtCore][QLatin1Char] Comparison against char now works even in QT_NO_CAST_FROM_ASCII builds. Change-Id: I86f5ec8e2ddfcda72f5928086cb298bd00b42544 Reviewed-by: Thiago Macieira --- src/corelib/tools/qchar.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h index be344838ed..73344ecf52 100644 --- a/src/corelib/tools/qchar.h +++ b/src/corelib/tools/qchar.h @@ -58,6 +58,19 @@ private: char ch; }; +Q_DECL_CONSTEXPR inline bool operator==(char lhs, QLatin1Char rhs) noexcept { return lhs == rhs.toLatin1(); } +Q_DECL_CONSTEXPR inline bool operator!=(char lhs, QLatin1Char rhs) noexcept { return lhs != rhs.toLatin1(); } +Q_DECL_CONSTEXPR inline bool operator<=(char lhs, QLatin1Char rhs) noexcept { return lhs <= rhs.toLatin1(); } +Q_DECL_CONSTEXPR inline bool operator>=(char lhs, QLatin1Char rhs) noexcept { return lhs >= rhs.toLatin1(); } +Q_DECL_CONSTEXPR inline bool operator< (char lhs, QLatin1Char rhs) noexcept { return lhs < rhs.toLatin1(); } +Q_DECL_CONSTEXPR inline bool operator> (char lhs, QLatin1Char rhs) noexcept { return lhs > rhs.toLatin1(); } + +Q_DECL_CONSTEXPR inline bool operator==(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() == rhs; } +Q_DECL_CONSTEXPR inline bool operator!=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() != rhs; } +Q_DECL_CONSTEXPR inline bool operator<=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() <= rhs; } +Q_DECL_CONSTEXPR inline bool operator>=(QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() >= rhs; } +Q_DECL_CONSTEXPR inline bool operator< (QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() < rhs; } +Q_DECL_CONSTEXPR inline bool operator> (QLatin1Char lhs, char rhs) noexcept { return lhs.toLatin1() > rhs; } class Q_CORE_EXPORT QChar { public: From a76ae0a631c8387bc96ec7d358e14f6c86b73f35 Mon Sep 17 00:00:00 2001 From: Mikhail Svetkin Date: Tue, 20 Mar 2018 14:20:23 +0100 Subject: [PATCH 109/122] rtems: Fix build sha3 (undef ALIGN) ALIGN macro exists in RTEMS system headers and in sha3 library. Change-Id: I00cbb5be5598a6a6ca1f011f199da62d658ef9d5 Reviewed-by: Ryan Chu --- src/corelib/tools/qcryptographichash.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index 3c79bb797d..ee7657789c 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -58,6 +58,10 @@ typedef unsigned char BitSequence; typedef unsigned long long DataLength; typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn; +#ifdef Q_OS_RTEMS +# undef ALIGN +#endif + #include "../../3rdparty/sha3/KeccakSponge.c" typedef spongeState hashState; From 2c51a91e03de48e6a0fa215e265fe4a6a85c02f6 Mon Sep 17 00:00:00 2001 From: Mikhail Svetkin Date: Thu, 6 Jun 2019 10:18:20 +0200 Subject: [PATCH 110/122] rtems: Disable sys/sem.h include RTEMS does not have sys/sem.h Change-Id: I9fe5c5244a4205521493885b39fa0051abcc4539 Reviewed-by: Volker Hilsheimer Reviewed-by: Thiago Macieira --- src/corelib/kernel/qsharedmemory_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index 59802eb6ce..bf7c42dc62 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -69,7 +69,7 @@ namespace QSharedMemoryPrivate #include "qsystemsemaphore.h" #include "private/qobject_p.h" -#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY) +#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_RTEMS) # include #endif From 0624c99ea3d52f07c93378fcf75c3121df1b3928 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 6 Jun 2019 22:03:58 +0200 Subject: [PATCH 111/122] QDistanceField: add missing copy assignment operator As found by GCC, while compiling qt5/qttools/src/distancefieldgenerator/mainwindow.cpp. Change-Id: I155c0b8b09bd12c12af0bd69e19747485be960e1 Reviewed-by: Thiago Macieira --- src/gui/text/qdistancefield.cpp | 3 +++ src/gui/text/qdistancefield_p.h | 1 + 2 files changed, 4 insertions(+) diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp index 82bb617733..5967c8d3de 100644 --- a/src/gui/text/qdistancefield.cpp +++ b/src/gui/text/qdistancefield.cpp @@ -904,6 +904,9 @@ QDistanceField::QDistanceField(const QDistanceField &other) d = other.d; } +QDistanceField &QDistanceField::operator=(const QDistanceField &) + = default; + QDistanceField::QDistanceField(const QRawFont &font, glyph_t glyph, bool doubleResolution) { setGlyph(font, glyph, doubleResolution); diff --git a/src/gui/text/qdistancefield_p.h b/src/gui/text/qdistancefield_p.h index 1a1b6866a2..dc5d5a9a02 100644 --- a/src/gui/text/qdistancefield_p.h +++ b/src/gui/text/qdistancefield_p.h @@ -95,6 +95,7 @@ public: QDistanceField(QFontEngine *fontEngine, glyph_t glyph, bool doubleResolution = false); QDistanceField(const QPainterPath &path, glyph_t glyph, bool doubleResolution = false); QDistanceField(const QDistanceField &other); + QDistanceField &operator=(const QDistanceField &other); bool isNull() const; From 3619e87ba1c0b11b8406fee3e1fe5c1e96abb7ef Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 4 Jun 2019 19:49:12 +0200 Subject: [PATCH 112/122] Fix a minor grammar glitch in new string / byte-array doc note Amends 8845caa057cfcf54f7d46621adb3393c13747ffb. Change-Id: I4bf09b9c1fff52815de58070fbe4ff0c08eff53f Reviewed-by: Marc Mutz Reviewed-by: Thiago Macieira --- src/corelib/tools/qbytearray.cpp | 2 +- src/corelib/tools/qstring.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 5c2af7e058..9526350126 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -1439,7 +1439,7 @@ QByteArray &QByteArray::operator=(const char *str) \note Before Qt 5.14 it was possible to use this operator to access a character at an out-of-bounds position in the byte array, and - then assign to such position, causing the byte array to be + then assign to such a position, causing the byte array to be automatically resized. Furthermore, assigning a value to the returned QByteRef would cause a detach of the byte array, even if the byte array has been copied in the meanwhile (and the QByteRef kept diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 06636098af..963c2a4d34 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -5800,7 +5800,7 @@ QString QString::trimmed_helper(QString &str) \note Before Qt 5.14 it was possible to use this operator to access a character at an out-of-bounds position in the string, and - then assign to such position, causing the string to be + then assign to such a position, causing the string to be automatically resized. Furthermore, assigning a value to the returned QCharRef would cause a detach of the string, even if the string has been copied in the meanwhile (and the QCharRef kept From cbc9d8947842b97f28e3acb2d87d80b4861d00b9 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 5 Jun 2019 21:59:46 +0200 Subject: [PATCH 113/122] QInputDeviceManager: replace a QMap with a std::array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QInputDeviceManager::DeviceType is a (non-flag) enum with all of five values. Using a self-rebalancing rb-tree to map these to an int is overkill. An array can do the job just as well and better, given the enum values are consecutive, and even if some don't make sense (like Unknown), the waste caused by unused array slots is more than compensated by the lack of any memory allocations. Even more so as the array API is 1:1 identical with the map's for the use-case at hand. Saves 1.2KiB in text size on optimized Linux AMD64 GCC 9.1 builds. Change-Id: I1bfa115ac75e2f7d9a4bd9a0e3f3241bf68c9989 Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qinputdevicemanager.cpp | 4 ++-- src/gui/kernel/qinputdevicemanager_p.h | 4 +++- src/gui/kernel/qinputdevicemanager_p_p.h | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/gui/kernel/qinputdevicemanager.cpp b/src/gui/kernel/qinputdevicemanager.cpp index 6e4e5a9c93..11442407e1 100644 --- a/src/gui/kernel/qinputdevicemanager.cpp +++ b/src/gui/kernel/qinputdevicemanager.cpp @@ -75,13 +75,13 @@ int QInputDeviceManager::deviceCount(DeviceType type) const int QInputDeviceManagerPrivate::deviceCount(QInputDeviceManager::DeviceType type) const { - return m_deviceCount.value(type); + return m_deviceCount[type]; } void QInputDeviceManagerPrivate::setDeviceCount(QInputDeviceManager::DeviceType type, int count) { Q_Q(QInputDeviceManager); - if (m_deviceCount.value(type) != count) { + if (m_deviceCount[type] != count) { m_deviceCount[type] = count; emit q->deviceListChanged(type); } diff --git a/src/gui/kernel/qinputdevicemanager_p.h b/src/gui/kernel/qinputdevicemanager_p.h index 74494d712b..1d20b102e3 100644 --- a/src/gui/kernel/qinputdevicemanager_p.h +++ b/src/gui/kernel/qinputdevicemanager_p.h @@ -69,7 +69,9 @@ public: DeviceTypePointer, DeviceTypeKeyboard, DeviceTypeTouch, - DeviceTypeTablet + DeviceTypeTablet, + + NumDeviceTypes }; QInputDeviceManager(QObject *parent = nullptr); diff --git a/src/gui/kernel/qinputdevicemanager_p_p.h b/src/gui/kernel/qinputdevicemanager_p_p.h index 0a91252fbc..871f9315c3 100644 --- a/src/gui/kernel/qinputdevicemanager_p_p.h +++ b/src/gui/kernel/qinputdevicemanager_p_p.h @@ -52,10 +52,11 @@ // #include -#include #include #include "qinputdevicemanager_p.h" +#include + QT_BEGIN_NAMESPACE class Q_GUI_EXPORT QInputDeviceManagerPrivate : public QObjectPrivate @@ -68,7 +69,7 @@ public: int deviceCount(QInputDeviceManager::DeviceType type) const; void setDeviceCount(QInputDeviceManager::DeviceType type, int count); - QMap m_deviceCount; + std::array m_deviceCount; Qt::KeyboardModifiers keyboardModifiers; }; From b16fab1b636c94cb1fd723f46a1714e010a4dc54 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Mon, 27 May 2019 22:03:33 +0200 Subject: [PATCH 114/122] Fix deprecation warnings Fix deprecation warnings - replace qFindChild/Children() with QObject::findChild/Children() and replace some 0 with nullptr. Change-Id: If2f01d12fa91d09d98a61f73b0449a6773ac93db Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll --- .../corelib/kernel/qobject/tst_qobject.cpp | 107 +++++++++--------- 1 file changed, 52 insertions(+), 55 deletions(-) diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index e0394a5d25..f1c4effa95 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -537,91 +536,91 @@ void tst_QObject::findChildren() QObject *op = 0; - op = qFindChild(&o, "o1"); + op = o.findChild("o1"); QCOMPARE(op, &o1); - op = qFindChild(&o, "o2"); + op = o.findChild("o2"); QCOMPARE(op, &o2); - op = qFindChild(&o, "o11"); + op = o.findChild("o11"); QCOMPARE(op, &o11); - op = qFindChild(&o, "o12"); + op = o.findChild("o12"); QCOMPARE(op, &o12); - op = qFindChild(&o, "o111"); + op = o.findChild("o111"); QCOMPARE(op, &o111); - op = qFindChild(&o, "t1"); + op = o.findChild("t1"); QCOMPARE(op, static_cast(&t1)); - op = qFindChild(&o, "t121"); + op = o.findChild("t121"); QCOMPARE(op, static_cast(&t121)); - op = qFindChild(&o, "t1"); + op = o.findChild("t1"); QCOMPARE(op, static_cast(&t1)); - op = qFindChild(&o, "t121"); + op = o.findChild("t121"); QCOMPARE(op, static_cast(&t121)); - op = qFindChild(&o, "o12"); + op = o.findChild("o12"); QCOMPARE(op, static_cast(0)); - op = qFindChild(&o, "o"); + op = o.findChild("o"); QCOMPARE(op, static_cast(0)); - op = qFindChild(&o, "harry"); + op = o.findChild("harry"); QCOMPARE(op, static_cast(0)); - op = qFindChild(&o, "o1"); + op = o.findChild("o1"); QCOMPARE(op, &o1); QList l; QList tl; - l = qFindChildren(&o, "o1"); + l = o.findChildren("o1"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o1); - l = qFindChildren(&o, "o2"); + l = o.findChildren("o2"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o2); - l = qFindChildren(&o, "o11"); + l = o.findChildren("o11"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o11); - l = qFindChildren(&o, "o12"); + l = o.findChildren("o12"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o12); - l = qFindChildren(&o, "o111"); + l = o.findChildren("o111"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o111); - l = qFindChildren(&o, "t1"); + l = o.findChildren("t1"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), static_cast(&t1)); - l = qFindChildren(&o, "t121"); + l = o.findChildren("t121"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), static_cast(&t121)); - tl = qFindChildren(&o, "t1"); + tl = o.findChildren("t1"); QCOMPARE(tl.size(), 1); QCOMPARE(tl.at(0), &t1); - tl = qFindChildren(&o, "t121"); + tl = o.findChildren("t121"); QCOMPARE(tl.size(), 1); QCOMPARE(tl.at(0), &t121); - l = qFindChildren(&o, "o"); + l = o.findChildren("o"); QCOMPARE(l.size(), 0); - l = qFindChildren(&o, "harry"); + l = o.findChildren("harry"); QCOMPARE(l.size(), 0); - tl = qFindChildren(&o, "o12"); + tl = o.findChildren("o12"); QCOMPARE(tl.size(), 0); - l = qFindChildren(&o, "o1"); + l = o.findChildren("o1"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o1); - l = qFindChildren(&o, QRegExp("o.*")); + l = o.findChildren(QRegularExpression("^o.*$")); QCOMPARE(l.size(), 5); QVERIFY(l.contains(&o1)); QVERIFY(l.contains(&o2)); QVERIFY(l.contains(&o11)); QVERIFY(l.contains(&o12)); QVERIFY(l.contains(&o111)); - l = qFindChildren(&o, QRegExp("t.*")); + l = o.findChildren(QRegularExpression("t.*")); QCOMPARE(l.size(), 2); QVERIFY(l.contains(&t1)); QVERIFY(l.contains(&t121)); - tl = qFindChildren(&o, QRegExp(".*")); + tl = o.findChildren(QRegularExpression("^.*$")); QCOMPARE(tl.size(), 3); QVERIFY(tl.contains(&t1)); QVERIFY(tl.contains(&t121)); - tl = qFindChildren(&o, QRegExp("o.*")); + tl = o.findChildren(QRegularExpression("^o.*$")); QCOMPARE(tl.size(), 0); - l = qFindChildren(&o, QRegExp("harry")); + l = o.findChildren(QRegularExpression("^harry$")); QCOMPARE(l.size(), 0); l = o.findChildren(QRegularExpression("o.*")); @@ -645,18 +644,18 @@ void tst_QObject::findChildren() QCOMPARE(l.size(), 0); // empty and null string check - op = qFindChild(&o); + op = o.findChild(); QCOMPARE(op, &o1); - op = qFindChild(&o, ""); + op = o.findChild(""); QCOMPARE(op, &unnamed); - op = qFindChild(&o, "unnamed"); + op = o.findChild("unnamed"); QCOMPARE(op, static_cast(0)); - l = qFindChildren(&o); + l = o.findChildren(); QCOMPARE(l.size(), 9); - l = qFindChildren(&o, ""); + l = o.findChildren(""); QCOMPARE(l.size(), 2); - l = qFindChildren(&o, "unnamed"); + l = o.findChildren("unnamed"); QCOMPARE(l.size(), 0); tl = o.findChildren("t1"); @@ -724,19 +723,19 @@ void tst_QObject::findChildren() QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o1); - l = o.findChildren(QRegExp("o.*"), Qt::FindDirectChildrenOnly); + l = o.findChildren(QRegularExpression("^o.*$"), Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 2); QVERIFY(l.contains(&o1)); QVERIFY(l.contains(&o2)); - l = o.findChildren(QRegExp("t.*"), Qt::FindDirectChildrenOnly); + l = o.findChildren(QRegularExpression("^t.*$"), Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 1); QVERIFY(l.contains(&t1)); - tl = o.findChildren(QRegExp(".*"), Qt::FindDirectChildrenOnly); + tl = o.findChildren(QRegularExpression("^.*$"), Qt::FindDirectChildrenOnly); QCOMPARE(tl.size(), 2); QVERIFY(tl.contains(&t1)); - tl = o.findChildren(QRegExp("o.*"), Qt::FindDirectChildrenOnly); + tl = o.findChildren(QRegularExpression("^o.*$"), Qt::FindDirectChildrenOnly); QCOMPARE(tl.size(), 0); - l = o.findChildren(QRegExp("harry"), Qt::FindDirectChildrenOnly); + l = o.findChildren(QRegularExpression("^harry$"), Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 0); // empty and null string check @@ -1035,18 +1034,16 @@ public Q_SLOTS: void tst_QObject::connectNotify_connectSlotsByName() { ConnectByNameNotifyReceiverObject testObject; - QList senders = - qFindChildren(&testObject); - for (int i = 0; i < senders.size(); ++i) { - ConnectByNameNotifySenderObject *o = senders.at(i); + const QList senders = + testObject.findChildren(); + for (ConnectByNameNotifySenderObject *o : senders) { QVERIFY(o->connectedSignals.isEmpty()); QVERIFY(o->disconnectedSignals.isEmpty()); } QMetaObject::connectSlotsByName(&testObject); - for (int i = 0; i < senders.size(); ++i) { - ConnectByNameNotifySenderObject *o = senders.at(i); + for (ConnectByNameNotifySenderObject *o : senders) { QCOMPARE(o->connectedSignals.size(), 1); QCOMPARE(o->connectedSignals.at(0), QMetaMethod::fromSignal(&ConnectByNameNotifySenderObject::signal1)); QVERIFY(o->disconnectedSignals.isEmpty()); @@ -1631,7 +1628,7 @@ void tst_QObject::thread() QObject object; // thread affinity for objects with no parent should be the // current thread - QVERIFY(object.thread() != 0); + QVERIFY(object.thread() != nullptr); QCOMPARE(object.thread(), currentThread); // children inherit their parent's thread QObject child(&object); @@ -1643,7 +1640,7 @@ void tst_QObject::thread() { TestThread thr; - QVERIFY(thr.thread() != 0); + QVERIFY(thr.thread() != nullptr); QCOMPARE(thr.thread(), currentThread); thr.object = &object; @@ -1802,8 +1799,8 @@ void tst_QObject::moveToThread() QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection); thread.wait(); - QVERIFY(opointer == 0); - QVERIFY(cpointer == 0); + QVERIFY(opointer == nullptr); + QVERIFY(cpointer == nullptr); } { @@ -2379,7 +2376,7 @@ void tst_QObject::testUserData() for (int i=0; i(my_test_object.userData(id)); - QVERIFY(data != 0); + QVERIFY(data != nullptr); QCOMPARE(data->id, id); } } @@ -3627,7 +3624,7 @@ class OverloadObject : public QObject void sig(int i, int j = 12); void sig(QObject *o, QObject *p, QObject *q = 0, QObject *r = 0) const; void other(int a = 0); - void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = 0); + void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = nullptr); void sig(double r = 0.5); public slots: void slo(int i, int j = 43) From 638f2749a052a22622de5ab01dfe3913644c2c25 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Thu, 11 Apr 2019 15:57:59 +0300 Subject: [PATCH 115/122] QLatin1String, QStringView: add contains [ChangeLog][QtCore][QLatin1String] Added contains(). [ChangeLog][QtCore][QStringView] Added contains(). Change-Id: I19fd2e155180edd8620c520f4e60a1f86f0603ac Reviewed-by: Marc Mutz --- src/corelib/tools/qstring.cpp | 51 ++++++- src/corelib/tools/qstring.h | 29 +++- src/corelib/tools/qstringview.cpp | 15 +++ src/corelib/tools/qstringview.h | 6 + .../tst_qstringapisymmetry.cpp | 124 ++++++++++++++++++ 5 files changed, 220 insertions(+), 5 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index aa602559fe..06636098af 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -4273,7 +4273,7 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const return int(qt_string_count(QStringView(unicode(), size()), QStringView(str.unicode(), str.size()), cs)); } - +#if QT_STRINGVIEW_LEVEL < 2 /*! \fn bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Returns \c true if this string contains an occurrence of the string @@ -4287,6 +4287,7 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const \sa indexOf(), count() */ +#endif // QT_STRINGVIEW_LEVEL < 2 /*! \fn bool QString::contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const \since 5.3 @@ -4305,6 +4306,7 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const character \a ch; otherwise returns \c false. */ +#if QT_STRINGVIEW_LEVEL < 2 /*! \fn bool QString::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const \since 4.8 @@ -4316,6 +4318,20 @@ int QString::count(const QStringRef &str, Qt::CaseSensitivity cs) const \sa indexOf(), count() */ +#endif // QT_STRINGVIEW_LEVEL < 2 + +/*! \fn bool QString::contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \since 5.14 + \overload contains() + + Returns \c true if this string contains an occurrence of the string view + \a str; otherwise returns \c false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ /*! \fn bool QString::contains(const QRegExp &rx) const @@ -9530,6 +9546,21 @@ QString &QString::setRawData(const QChar *unicode, int size) \sa QString::indexOf() */ +/*! + \fn bool QLatin1String::contains(QStringView str, Qt::CaseSensitivity cs) const + \fn bool QLatin1String::contains(QLatin1String l1, Qt::CaseSensitivity cs) const + \fn bool QLatin1String::contains(QChar c, Qt::CaseSensitivity cs) const + \since 5.14 + + Returns \c true if this Latin-1 string contains an occurrence of the string-view + \a str, Latin-1 string \a l1, or character \a ch; otherwise returns \c false. + + If \a cs is Qt::CaseSensitive (the default), the search is + case-sensitive; otherwise the search is case-insensitive. + + \sa indexOf(), QStringView::contains(), QStringView::indexOf(), QString::indexOf() +*/ + /*! \fn QLatin1String::const_iterator QLatin1String::begin() const \since 5.10 @@ -11514,7 +11545,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const return qt_ends_with(*this, str, cs); } - +#if QT_STRINGVIEW_LEVEL < 2 /*! \fn bool QStringRef::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const \since 4.8 @@ -11526,6 +11557,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const \sa indexOf(), count() */ +#endif // QT_STRINGVIEW_LEVEL < 2 /*! \fn bool QStringRef::contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const @@ -11540,6 +11572,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const */ +#if QT_STRINGVIEW_LEVEL < 2 /*! \fn bool QStringRef::contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const \overload contains() \since 4.8 @@ -11552,6 +11585,7 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const \sa indexOf(), count() */ +#endif // QT_STRINGVIEW_LEVEL < 2 /*! \fn bool QStringRef::contains(QLatin1String str, Qt::CaseSensitivity cs) const \since 4.8 @@ -11566,6 +11600,19 @@ bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const \sa indexOf(), count() */ +/*! \fn bool QStringRef::contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \since 5.14 + \overload contains() + + Returns \c true if this string reference contains an occurrence of + the string view \a str; otherwise returns \c false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa indexOf(), count() +*/ + static inline qsizetype qt_last_index_of(QStringView haystack, QChar needle, qsizetype from, Qt::CaseSensitivity cs) { diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 0f7b015bef..da8260a999 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -138,6 +138,13 @@ public: Q_REQUIRED_RESULT inline int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept { return int(QtPrivate::findString(*this, from, QStringView(&c, 1), cs)); } // ### Qt6: qsize + Q_REQUIRED_RESULT bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return indexOf(s, 0, cs) != -1; } + Q_REQUIRED_RESULT bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return indexOf(s, 0, cs) != -1; } + Q_REQUIRED_RESULT inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return indexOf(QStringView(&c, 1), 0, cs) != -1; } + using value_type = const char; using reference = value_type&; using const_reference = reference; @@ -224,6 +231,8 @@ bool QStringView::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexce { return QtPrivate::endsWith(*this, s, cs); } qsizetype QStringView::indexOf(QLatin1String s, qsizetype from, Qt::CaseSensitivity cs) const noexcept { return QtPrivate::findString(*this, from, s, cs); } +bool QStringView::contains(QLatin1String s, Qt::CaseSensitivity cs) const noexcept +{ return indexOf(s, 0, cs) != qsizetype(-1); } class Q_CORE_EXPORT QString { @@ -351,9 +360,12 @@ public: int lastIndexOf(const QStringRef &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; +#if QT_STRINGVIEW_LEVEL < 2 inline bool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; - inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline bool contains(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; +#endif + inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -1240,14 +1252,18 @@ inline QString::const_iterator QString::cend() const { return reinterpret_cast(d->data() + d->size); } inline QString::const_iterator QString::constEnd() const { return reinterpret_cast(d->data() + d->size); } +#if QT_STRINGVIEW_LEVEL < 2 inline bool QString::contains(const QString &s, Qt::CaseSensitivity cs) const { return indexOf(s, 0, cs) != -1; } inline bool QString::contains(const QStringRef &s, Qt::CaseSensitivity cs) const { return indexOf(s, 0, cs) != -1; } +#endif inline bool QString::contains(QLatin1String s, Qt::CaseSensitivity cs) const { return indexOf(s, 0, cs) != -1; } inline bool QString::contains(QChar c, Qt::CaseSensitivity cs) const { return indexOf(c, 0, cs) != -1; } +inline bool QString::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept +{ return indexOf(s, 0, cs) != -1; } #if QT_DEPRECATED_SINCE(5, 9) inline bool operator==(QString::Null, QString::Null) { return true; } @@ -1528,10 +1544,13 @@ public: int lastIndexOf(QLatin1String str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int lastIndexOf(const QStringRef &str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; +#if QT_STRINGVIEW_LEVEL < 2 inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline bool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; +#endif inline bool contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline bool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; - inline bool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline bool contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -1893,13 +1912,17 @@ inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QString &s inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef &s2) { return QString::localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); } +#if QT_STRINGVIEW_LEVEL < 2 inline bool QStringRef::contains(const QString &s, Qt::CaseSensitivity cs) const { return indexOf(s, 0, cs) != -1; } +inline bool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const +{ return indexOf(s, 0, cs) != -1; } +#endif inline bool QStringRef::contains(QLatin1String s, Qt::CaseSensitivity cs) const { return indexOf(s, 0, cs) != -1; } inline bool QStringRef::contains(QChar c, Qt::CaseSensitivity cs) const { return indexOf(c, 0, cs) != -1; } -inline bool QStringRef::contains(const QStringRef &s, Qt::CaseSensitivity cs) const +inline bool QStringRef::contains(QStringView s, Qt::CaseSensitivity cs) const noexcept { return indexOf(s, 0, cs) != -1; } inline QString &QString::insert(int i, const QStringRef &s) diff --git a/src/corelib/tools/qstringview.cpp b/src/corelib/tools/qstringview.cpp index 8c2b52ea09..050097b443 100644 --- a/src/corelib/tools/qstringview.cpp +++ b/src/corelib/tools/qstringview.cpp @@ -739,6 +739,21 @@ QT_BEGIN_NAMESPACE \sa QString::indexOf() */ +/*! + \fn bool QStringView::contains(QStringView str, Qt::CaseSensitivity cs) const + \fn bool QStringView::contains(QLatin1String l1, Qt::CaseSensitivity cs) const + \fn bool QStringView::contains(QChar c, Qt::CaseSensitivity cs) const + \since 5.14 + + Returns \c true if this string-view contains an occurrence of the string-view + \a str, Latin-1 string \a l1, or character \a ch; otherwise returns \c false. + + If \a cs is Qt::CaseSensitive (the default), the search is + case-sensitive; otherwise the search is case-insensitive. + + \sa indexOf() +*/ + /*! \fn QByteArray QStringView::toLatin1() const diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h index bbf51b24f6..2c93b31385 100644 --- a/src/corelib/tools/qstringview.h +++ b/src/corelib/tools/qstringview.h @@ -276,6 +276,12 @@ public: { return QtPrivate::findString(*this, from, s, cs); } Q_REQUIRED_RESULT inline qsizetype indexOf(QLatin1String s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; + Q_REQUIRED_RESULT bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return indexOf(QStringView(&c, 1), 0, cs) != qsizetype(-1); } + Q_REQUIRED_RESULT bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept + { return indexOf(s, 0, cs) != qsizetype(-1); } + Q_REQUIRED_RESULT inline bool contains(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; + Q_REQUIRED_RESULT bool isRightToLeft() const noexcept { return QtPrivate::isRightToLeft(*this); } diff --git a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp index 7e5a855552..a74ae2eb71 100644 --- a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp +++ b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp @@ -485,6 +485,47 @@ private Q_SLOTS: void indexOf_QStringView_QStringRef() { indexOf_impl(); } void indexOf_QStringView_QStringView_data() { indexOf_data(); } void indexOf_QStringView_QStringView() { indexOf_impl(); } + +private: + template void contains_impl() const; + void contains_data(); + +private Q_SLOTS: + void contains_QString_QString_data() { contains_data(); } + void contains_QString_QString() { contains_impl(); } + void contains_QString_QLatin1String_data() { contains_data(); } + void contains_QString_QLatin1String() { contains_impl(); } + void contains_QString_QStringRef_data() { contains_data(); } + void contains_QString_QStringRef() { contains_impl(); } + void contains_QString_QStringView_data() { contains_data(); } + void contains_QString_QStringView() { contains_impl(); } + + void contains_QLatin1String_QString_data() { contains_data(); } + void contains_QLatin1String_QString() { contains_impl(); } + void contains_QLatin1String_QLatin1String_data() { contains_data(); } + void contains_QLatin1String_QLatin1String() { contains_impl(); } + void contains_QLatin1String_QStringRef_data() { contains_data(); } + void contains_QLatin1String_QStringRef() { contains_impl(); } + void contains_QLatin1String_QStringView_data() { contains_data(); } + void contains_QLatin1String_QStringView() { contains_impl(); } + + void contains_QStringRef_QString_data() { contains_data(); } + void contains_QStringRef_QString() { contains_impl(); } + void contains_QStringRef_QLatin1String_data() { contains_data(); } + void contains_QStringRef_QLatin1String() { contains_impl(); } + void contains_QStringRef_QStringRef_data() { contains_data(); } + void contains_QStringRef_QStringRef() { contains_impl(); } + void contains_QStringRef_QStringView_data() { contains_data(); } + void contains_QStringRef_QStringView() { contains_impl(); } + + void contains_QStringView_QString_data() { contains_data(); } + void contains_QStringView_QString() { contains_impl(); } + void contains_QStringView_QLatin1String_data() { contains_data(); } + void contains_QStringView_QLatin1String() { contains_impl(); } + void contains_QStringView_QStringRef_data() { contains_data(); } + void contains_QStringView_QStringRef() { contains_impl(); } + void contains_QStringView_QStringView_data() { contains_data(); } + void contains_QStringView_QStringView() { contains_impl(); } }; void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty) @@ -617,6 +658,14 @@ static QString b = QStringLiteral("b"); static QString B = QStringLiteral("B"); static QString c = QStringLiteral("c"); static QString C = QStringLiteral("C"); +static QString d = QStringLiteral("d"); +static QString D = QStringLiteral("D"); +static QString e = QStringLiteral("e"); +static QString E = QStringLiteral("E"); +static QString f = QStringLiteral("f"); +static QString F = QStringLiteral("F"); +static QString g = QStringLiteral("g"); +static QString G = QStringLiteral("G"); static QString ab = QStringLiteral("ab"); static QString aB = QStringLiteral("aB"); static QString Ab = QStringLiteral("Ab"); @@ -1501,6 +1550,81 @@ void tst_QStringApiSymmetry::indexOf_impl() const } } +static QString ABCDEFGHIEfGEFG = QStringLiteral("ABCDEFGHIEfGEFG"); +static QString EFG = QStringLiteral("EFG"); +static QString efg = QStringLiteral("efg"); +static QString asd = QStringLiteral("asd"); +static QString asdf = QStringLiteral("asdf"); +static QString Z = QStringLiteral("Z"); + +void tst_QStringApiSymmetry::contains_data() +{ + QTest::addColumn("haystackU16"); + QTest::addColumn("haystackL1"); + QTest::addColumn("needleU16"); + QTest::addColumn("needleL1"); + QTest::addColumn("resultCS"); + QTest::addColumn("resultCIS"); + + QTest::addRow("haystack: null, needle: null") << null << QLatin1String() + << null << QLatin1String() << true << true; + QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("") + << null << QLatin1String() << true << true; + QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") + << null << QLatin1String() << true << true; + QTest::addRow("haystack: null, needle: empty") << null << QLatin1String() + << empty << QLatin1String("") << true << true; + QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") + << empty << QLatin1String("") << true << true;; + QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("") + << empty << QLatin1String("") << true << true; + QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("") + << a << QLatin1String("a") << false << false; + QTest::addRow("haystack: null, needle: a") << null << QLatin1String() + << a << QLatin1String("a") << false << false; + +#define ROW(h, n, cs, cis) \ + QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \ + << n << QLatin1String(#n) \ + << cs << cis + + ROW(ABCDEFGHIEfGEFG, A, true, true); + ROW(ABCDEFGHIEfGEFG, a, false, true); + ROW(ABCDEFGHIEfGEFG, Z, false, false); + ROW(ABCDEFGHIEfGEFG, EFG, true, true); + ROW(ABCDEFGHIEfGEFG, efg, false, true); + ROW(ABCDEFGHIEfGEFG, E, true, true); + ROW(ABCDEFGHIEfGEFG, e, false, true); +#undef ROW +} + +template +void tst_QStringApiSymmetry::contains_impl() const +{ + QFETCH(const QString, haystackU16); + QFETCH(const QLatin1String, haystackL1); + QFETCH(const QString, needleU16); + QFETCH(const QLatin1String, needleL1); + QFETCH(const bool, resultCS); + QFETCH(const bool, resultCIS); + + const auto haystackU8 = haystackU16.toUtf8(); + const auto needleU8 = needleU16.toUtf8(); + + const auto haystack = make(QStringRef(&haystackU16), haystackL1, haystackU8); + const auto needle = make(QStringRef(&needleU16), needleL1, needleU8); + + QCOMPARE(haystack.contains(needle), resultCS); + QCOMPARE(haystack.contains(needle, Qt::CaseSensitive), resultCS); + QCOMPARE(haystack.contains(needle, Qt::CaseInsensitive), resultCIS); + + if (needle.size() == 1) + { + QCOMPARE(haystack.contains(needle[0]), resultCS); + QCOMPARE(haystack.contains(needle[0], Qt::CaseSensitive), resultCS); + QCOMPARE(haystack.contains(needle[0], Qt::CaseInsensitive), resultCIS); + } +} QTEST_APPLESS_MAIN(tst_QStringApiSymmetry) From 5905f7a4af4885024455ede3dc2daf5d3adaa18c Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 4 Jun 2019 14:44:42 +0200 Subject: [PATCH 116/122] Fix definition of QT_DEPRECATED_SINCE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise any use of QT_DEPRECATED_SINCE will cause a warning: src/corelib/global/qglobal.h:382:77: error: expected unqualified-id before ‘)’ token This amends 220028d37c Change-Id: Ifa2be1dd8852e4aac0db83b0b4ae15d2f666c550 Reviewed-by: Christian Ehrlicher --- src/corelib/global/qglobal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 24d250d923..87ae704ca4 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -379,7 +379,7 @@ typedef double qreal; #define QT_DEPRECATED_VERSION_X_5(minor, text) QT_DEPRECATED_VERSION_X_5_##minor(text) #define QT_DEPRECATED_VERSION_X(major, minor, text) QT_DEPRECATED_VERSION_X_##major(minor, text) -#define QT_DEPRECATED_VERSION_5(minor) QT_DEPRECATED_VERSION_5_##minor() +#define QT_DEPRECATED_VERSION_5(minor) QT_DEPRECATED_VERSION_5_##minor #define QT_DEPRECATED_VERSION(major, minor) QT_DEPRECATED_VERSION_##major(minor) /* From b2587f9ea40c89e8d7c21bfeb34ccdb67c804c81 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 1 Jun 2019 06:25:38 +0200 Subject: [PATCH 117/122] QFile: fix coding style violation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Amends dd8131e3b25a4ac60eb55022b69b374f0b9a476c. Change-Id: Ic7d440816ee7bada49740f15919e404860dd8ac7 Reviewed-by: Giuseppe D'Angelo Reviewed-by: Thiago Macieira Reviewed-by: Mårten Nordheim --- src/corelib/io/qfile.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 13af113da1..8d871904bc 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -62,7 +62,8 @@ QT_BEGIN_NAMESPACE Q_DECL_COLD_FUNCTION -static bool file_already_open(QFile &file, const char *where = nullptr) { +static bool file_already_open(QFile &file, const char *where = nullptr) +{ qWarning("QFile::%s: File (%ls) already open", where ? where : "open", qUtf16Printable(file.fileName())); return false; } From 2596a8a55ce3c9532701c2cf1f353b93df4bd893 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 27 May 2019 16:56:12 +0200 Subject: [PATCH 118/122] QSharedNetworkSessionManager: clean up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Under no circumstance must Qt code define a non-public qHash() overload of a public Qt type. If you can't provide a public qHash() for the type, you can't use QHash. Period. This is because if we don't provide a qHash() function, the user will have to provide one, and then we have an ODR violation, iow: UB. So, port away from QHash and qHash and use std::unordered_map, which allows to pass a custom hash function - just what we needed. Also fix other issues of the code: - Use a function object as the deleter of the QSharedPointer, to allow inlining the function call. - Avoid double lookup in case of a cache miss. - Don't use direct initialization syntax for pointer variables. That's just ... weird. Change-Id: Ica8bff728c1bd1cbb2fb43aa03a99bcb7ac2f7cc Reviewed-by: Mårten Nordheim --- src/network/bearer/qsharednetworksession.cpp | 34 ++++++++------------ src/network/bearer/qsharednetworksession_p.h | 16 +++++++-- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/network/bearer/qsharednetworksession.cpp b/src/network/bearer/qsharednetworksession.cpp index fc01acb8b4..af543f77e3 100644 --- a/src/network/bearer/qsharednetworksession.cpp +++ b/src/network/bearer/qsharednetworksession.cpp @@ -57,36 +57,30 @@ inline QSharedNetworkSessionManager* sharedNetworkSessionManager() return rv; } -static void doDeleteLater(QObject* obj) -{ - obj->deleteLater(); -} +struct DeleteLater { + void operator()(QObject* obj) const + { + obj->deleteLater(); + } +}; QSharedPointer QSharedNetworkSessionManager::getSession(const QNetworkConfiguration &config) { - QSharedNetworkSessionManager *m(sharedNetworkSessionManager()); - const auto it = m->sessions.constFind(config); + QSharedNetworkSessionManager *m = sharedNetworkSessionManager(); + auto &entry = m->sessions[config]; //if already have a session, return it - if (it != m->sessions.cend()) { - QSharedPointer p = it.value().toStrongRef(); - if (!p.isNull()) - return p; - } + if (auto p = entry.toStrongRef()) + return p; //otherwise make one - QSharedPointer session(new QNetworkSession(config), doDeleteLater); - m->sessions[config] = session; + QSharedPointer session(new QNetworkSession(config), DeleteLater{}); + entry = session; return session; } void QSharedNetworkSessionManager::setSession(const QNetworkConfiguration &config, QSharedPointer session) { - QSharedNetworkSessionManager *m(sharedNetworkSessionManager()); - m->sessions[config] = session; -} - -uint qHash(const QNetworkConfiguration& config) -{ - return ((uint)config.type()) | (((uint)config.bearerType()) << 8) | (((uint)config.purpose()) << 16); + QSharedNetworkSessionManager *m = sharedNetworkSessionManager(); + m->sessions[config] = std::move(session); } QT_END_NAMESPACE diff --git a/src/network/bearer/qsharednetworksession_p.h b/src/network/bearer/qsharednetworksession_p.h index 001b8af02a..f22f9eeacb 100644 --- a/src/network/bearer/qsharednetworksession_p.h +++ b/src/network/bearer/qsharednetworksession_p.h @@ -54,16 +54,26 @@ #include #include "qnetworksession.h" #include "qnetworkconfiguration.h" -#include #include #include #include +#include + #ifndef QT_NO_BEARERMANAGEMENT QT_BEGIN_NAMESPACE -uint qHash(const QNetworkConfiguration& config); +namespace QtPrivate { +struct NetworkConfigurationHash { + using result_type = size_t; + using argument_type = QNetworkConfiguration; + size_t operator()(const QNetworkConfiguration &config) const noexcept + { + return std::hash{}(size_t(config.type()) | (size_t(config.bearerType()) << 8) | (size_t(config.purpose()) << 16)); + } +}; +} class QSharedNetworkSessionManager { @@ -71,7 +81,7 @@ public: static QSharedPointer getSession(const QNetworkConfiguration &config); static void setSession(const QNetworkConfiguration &config, QSharedPointer session); private: - QHash > sessions; + std::unordered_map, QtPrivate::NetworkConfigurationHash> sessions; }; QT_END_NAMESPACE From dea7110b29c5c68a5b09454c968324042ed1b607 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 16 Dec 2017 19:19:38 +0100 Subject: [PATCH 119/122] QGestureManager: clean up cleanupCachedGestures() - use logarithmic QMap::find() instead of iterate-and-compare-with-key (linear) - don't convert a QList to a QSet just to use QSet -=, just iterate over QSet::remove(): QSet::subtract() doesn't do anything more fancy, either (saves memory allocations) - replace Q_FOREACH with ranged-for, avoid copies Change-Id: I451f034767b079efa9ee19e2c1fe7dc4af2d9bea Reviewed-by: Richard Moe Gustavsen --- src/widgets/kernel/qgesturemanager.cpp | 40 ++++++++++++-------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index 7632521117..ff7bc1eccf 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -167,30 +167,26 @@ void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type) void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType type) { - QMap >::Iterator iter = m_objectGestures.begin(); - while (iter != m_objectGestures.end()) { - ObjectGesture objectGesture = iter.key(); - if (objectGesture.gesture == type && target == objectGesture.object) { - QSet gestures = QSet(iter.value().constBegin(), iter.value().constEnd()); - for (QHash >::iterator - it = m_obsoleteGestures.begin(), e = m_obsoleteGestures.end(); it != e; ++it) { - it.value() -= gestures; - } - foreach (QGesture *g, gestures) { - m_deletedRecognizers.remove(g); - m_gestureToRecognizer.remove(g); - m_maybeGestures.remove(g); - m_activeGestures.remove(g); - m_gestureOwners.remove(g); - m_gestureTargets.remove(g); - m_gesturesToDelete.insert(g); - } + const auto iter = m_objectGestures.find({target, type}); + if (iter == m_objectGestures.end()) + return; - iter = m_objectGestures.erase(iter); - } else { - ++iter; - } + const QList &gestures = iter.value(); + for (auto &e : m_obsoleteGestures) { + for (QGesture *g : gestures) + e -= g; } + for (QGesture *g : gestures) { + m_deletedRecognizers.remove(g); + m_gestureToRecognizer.remove(g); + m_maybeGestures.remove(g); + m_activeGestures.remove(g); + m_gestureOwners.remove(g); + m_gestureTargets.remove(g); + m_gesturesToDelete.insert(g); + } + + m_objectGestures.erase(iter); } // get or create a QGesture object that will represent the state for a given object, used by the recognizer From b3c52e82245f46af9ce633a6de1e4e41fb9f3f6d Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Sun, 10 Feb 2019 18:43:05 +0100 Subject: [PATCH 120/122] Simplify {to,from}Std{List,Vector} Use the newly-added range constructors. Change-Id: I7f1d2699d88656fb7dddd11a9d781d810d45b0b4 Reviewed-by: Marc Mutz --- src/corelib/tools/qlist.h | 15 ++++----------- src/corelib/tools/qvector.h | 2 +- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 04c1f12f5f..70bbc11ad2 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -414,10 +414,10 @@ public: Q_DECL_DEPRECATED_X("Use QList(list.begin(), list.end()) instead.") static inline QList fromStdList(const std::list &list) - { QList tmp; std::copy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; } + { return QList(list.begin(), list.end()); } Q_DECL_DEPRECATED_X("Use std::list(list.begin(), list.end()) instead.") inline std::list toStdList() const - { std::list tmp; std::copy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } + { return std::list(begin(), end()); } #endif private: @@ -1105,10 +1105,7 @@ inline int QList::count_impl(const T &t, QListData::ArrayCompatibleLayout) co template Q_OUTOFLINE_TEMPLATE QVector QList::toVector() const { - QVector result(size()); - for (int i = 0; i < size(); ++i) - result[i] = at(i); - return result; + return QVector(begin(), end()); } template @@ -1120,11 +1117,7 @@ QList QList::fromVector(const QVector &vector) template Q_OUTOFLINE_TEMPLATE QList QVector::toList() const { - QList result; - result.reserve(size()); - for (int i = 0; i < size(); ++i) - result.append(at(i)); - return result; + return QList(begin(), end()); } template diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index c223e4efa0..5d68a283bd 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -303,7 +303,7 @@ public: #if QT_VERSION < QT_VERSION_CHECK(6,0,0) Q_DECL_DEPRECATED_X("Use QVector(vector.begin(), vector.end()) instead.") static inline QVector fromStdVector(const std::vector &vector) - { QVector tmp; tmp.reserve(int(vector.size())); std::copy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; } + { return QVector(vector.begin(), vector.end()); } Q_DECL_DEPRECATED_X("Use std::vector(vector.begin(), vector.end()) instead.") inline std::vector toStdVector() const { return std::vector(d->begin(), d->end()); } From d7093487a36b0b1a35c28d065f4f0a5890676216 Mon Sep 17 00:00:00 2001 From: Mikhail Svetkin Date: Tue, 20 Mar 2018 14:27:45 +0100 Subject: [PATCH 121/122] rtems: Disable fork feature and fix compilation in corelib/io RTEMS does not support fork. RTEMS has LOCK_EX and LOCK_NB defines but does not have flock. Change-Id: I2b1774435bc972f53596f4163ec410b9d22aca4a Reviewed-by: Ryan Chu --- src/corelib/io/io.pri | 2 +- src/corelib/io/qlockfile_unix.cpp | 5 +++++ src/corelib/io/qstorageinfo_unix.cpp | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 13b43ad8f7..fe81689932 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -172,7 +172,7 @@ win32 { io/qlockfile_unix.cpp \ io/qfilesystemiterator_unix.cpp - !integrity:!uikit { + !integrity:!uikit:!rtems { SOURCES += io/forkfd_qt.cpp HEADERS += \ ../3rdparty/forkfd/forkfd.h diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 4a12157607..b2bf77c0da 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -58,6 +58,11 @@ #include // flock #endif +#if defined(Q_OS_RTEMS) +# undef LOCK_EX +# undef LOCK_NB +#endif + #include // kill #include // kill #include // gethostname diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index b7621b5d2f..d25a607d9f 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -812,7 +812,7 @@ void QStorageInfoPrivate::retrieveVolumeInfo() valid = true; ready = true; -#if defined(Q_OS_INTEGRITY) || (defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)) +#if defined(Q_OS_INTEGRITY) || (defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)) || defined(Q_OS_RTEMS) bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize; bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize; bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize; @@ -822,7 +822,7 @@ void QStorageInfoPrivate::retrieveVolumeInfo() bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize; #endif blockSize = statfs_buf.f_bsize; -#if defined(Q_OS_ANDROID) || defined(Q_OS_BSD4) || defined(Q_OS_INTEGRITY) +#if defined(Q_OS_ANDROID) || defined(Q_OS_BSD4) || defined(Q_OS_INTEGRITY) || defined(Q_OS_RTEMS) #if defined(_STATFS_F_FLAGS) readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0; #endif From 3e75c2965c96fa014ab74121e84d623fd04a27f7 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 10 Jun 2019 00:09:10 +0200 Subject: [PATCH 122/122] Remove QLatin1Literal usages That's an undocumented Qt 4/3/2 remnant, start remove usages. Fix incorrect include header in qclass_lib_map.h as a drive-by. Change-Id: I939be2621bc03e5c75f7e3f152546d3af6d37b91 Reviewed-by: Marc Mutz Reviewed-by: Thiago Macieira --- qmake/generators/mac/pbuilder_pbx.cpp | 2 +- src/gui/painting/qbrush.cpp | 16 +++++----- src/plugins/platforms/ios/qioscontext.mm | 2 +- .../xcb/nativepainting/qpaintengine_x11.cpp | 2 +- src/testlib/qtaptestlogger.cpp | 24 +++++++-------- src/tools/uic/qclass_lib_map.h | 2 +- .../qmetaproperty/tst_qmetaproperty.cpp | 6 ++-- .../corelib/kernel/qobject/tst_qobject.cpp | 2 +- tests/auto/gui/painting/qbrush/tst_qbrush.cpp | 6 ++-- .../qdatetimeedit/tst_qdatetimeedit.cpp | 30 +++++++++---------- .../qdoublespinbox/tst_qdoublespinbox.cpp | 18 +++++------ .../widgets/widgets/qspinbox/tst_qspinbox.cpp | 18 +++++------ .../corelib/tools/qstringbuilder/main.cpp | 2 +- 13 files changed, 65 insertions(+), 65 deletions(-) diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index b3c6ba4869..3acc351b12 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -1467,7 +1467,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("name", "Qt Test") << ";\n" << "\t\t};\n"; - QLatin1Literal testTargetID("TestTargetID"); + QLatin1String testTargetID("TestTargetID"); project->values(ProKey("QMAKE_PBX_TARGET_ATTRIBUTES_" + testTargetKey + "_" + testTargetID)).append(keyFor(pbx_dir + "QMAKE_PBX_TARGET")); project->values(ProKey("QMAKE_PBX_TARGET_ATTRIBUTES_" + testTargetKey)).append(ProKey(testTargetID)); } diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 13d986073e..21e41979af 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -1385,16 +1385,16 @@ QGradient::QGradient(Preset preset) setCoordinateMode(ObjectMode); setSpread(PadSpread); - const QJsonValue start = presetData[QLatin1Literal("start")]; - const QJsonValue end = presetData[QLatin1Literal("end")]; - m_data.linear.x1 = start[QLatin1Literal("x")].toDouble(); - m_data.linear.y1 = start[QLatin1Literal("y")].toDouble(); - m_data.linear.x2 = end[QLatin1Literal("x")].toDouble(); - m_data.linear.y2 = end[QLatin1Literal("y")].toDouble(); + const QJsonValue start = presetData[QLatin1String("start")]; + const QJsonValue end = presetData[QLatin1String("end")]; + m_data.linear.x1 = start[QLatin1String("x")].toDouble(); + m_data.linear.y1 = start[QLatin1String("y")].toDouble(); + m_data.linear.x2 = end[QLatin1String("x")].toDouble(); + m_data.linear.y2 = end[QLatin1String("y")].toDouble(); for (const QJsonValue &stop : presetData[QLatin1String("stops")].toArray()) { - setColorAt(stop[QLatin1Literal("position")].toDouble(), - QColor(QRgb(stop[QLatin1Literal("color")].toInt()))); + setColorAt(stop[QLatin1String("position")].toDouble(), + QColor(QRgb(stop[QLatin1String("color")].toInt()))); } cachedPresets.insert(preset, *this); diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index 535e7d7aa6..c9509ae599 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -118,7 +118,7 @@ QSurfaceFormat QIOSContext::format() const return m_format; } -#define QT_IOS_GL_STATUS_CASE(val) case val: return QLatin1Literal(#val) +#define QT_IOS_GL_STATUS_CASE(val) case val: return QLatin1String(#val) static QString fboStatusString(GLenum status) { diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp index 8d958aae94..82b6d60bcd 100644 --- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp +++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp @@ -455,7 +455,7 @@ static const uchar base_dither_matrix[DITHER_SIZE][DITHER_SIZE] = { static QPixmap qt_patternForAlpha(uchar alpha, int screen) { QPixmap pm; - QString key = QLatin1Literal("$qt-alpha-brush$") + QString key = QLatin1String("$qt-alpha-brush$") % HexString(alpha) % HexString(screen); diff --git a/src/testlib/qtaptestlogger.cpp b/src/testlib/qtaptestlogger.cpp index 540b36e273..476761e602 100644 --- a/src/testlib/qtaptestlogger.cpp +++ b/src/testlib/qtaptestlogger.cpp @@ -154,10 +154,10 @@ void QTapTestLogger::addIncident(IncidentTypes type, const char *description, // This is fragile, but unfortunately testlib doesn't plumb // the expected and actual values to the loggers (yet). static QRegularExpression verifyRegex( - QLatin1Literal("^'(?.*)' returned (?\\w+).+\\((?.*)\\)$")); + QLatin1String("^'(?.*)' returned (?\\w+).+\\((?.*)\\)$")); static QRegularExpression comparRegex( - QLatin1Literal("^(?.*)\n" + QLatin1String("^(?.*)\n" "\\s*Actual\\s+\\((?.*)\\)\\s*: (?.*)\n" "\\s*Expected\\s+\\((?.*)\\)\\s*: (?.*)$")); @@ -168,22 +168,22 @@ void QTapTestLogger::addIncident(IncidentTypes type, const char *description, if (match.hasMatch()) { bool isVerify = match.regularExpression() == verifyRegex; - QString message = match.captured(QLatin1Literal("message")); + QString message = match.captured(QLatin1String("message")); QString expected; QString actual; if (isVerify) { - QString expression = QLatin1Literal(" (") - % match.captured(QLatin1Literal("actualexpression")) % QLatin1Char(')') ; - actual = match.captured(QLatin1Literal("actual")).toLower() % expression; - expected = (actual.startsWith(QLatin1Literal("true")) ? QLatin1Literal("false") : QLatin1Literal("true")) % expression; + QString expression = QLatin1String(" (") + % match.captured(QLatin1String("actualexpression")) % QLatin1Char(')') ; + actual = match.captured(QLatin1String("actual")).toLower() % expression; + expected = (actual.startsWith(QLatin1String("true")) ? QLatin1String("false") : QLatin1String("true")) % expression; if (message.isEmpty()) - message = QLatin1Literal("Verification failed"); + message = QLatin1String("Verification failed"); } else { - expected = match.captured(QLatin1Literal("expected")) - % QLatin1Literal(" (") % match.captured(QLatin1Literal("expectedexpresssion")) % QLatin1Char(')'); - actual = match.captured(QLatin1Literal("actual")) - % QLatin1Literal(" (") % match.captured(QLatin1Literal("actualexpression")) % QLatin1Char(')'); + expected = match.captured(QLatin1String("expected")) + % QLatin1String(" (") % match.captured(QLatin1String("expectedexpresssion")) % QLatin1Char(')'); + actual = match.captured(QLatin1String("actual")) + % QLatin1String(" (") % match.captured(QLatin1String("actualexpression")) % QLatin1Char(')'); } QTestCharBuffer diagnosticsYamlish; diff --git a/src/tools/uic/qclass_lib_map.h b/src/tools/uic/qclass_lib_map.h index 8e1afa0878..8cebe65a00 100644 --- a/src/tools/uic/qclass_lib_map.h +++ b/src/tools/uic/qclass_lib_map.h @@ -249,7 +249,7 @@ QT_CLASS_LIB(QLatin1String, QtCore, qstring.h) QT_CLASS_LIB(QCharRef, QtCore, qstring.h) QT_CLASS_LIB(QConstString, QtCore, qstring.h) QT_CLASS_LIB(QStringRef, QtCore, qstring.h) -QT_CLASS_LIB(QLatin1Literal, QtCore, qstringbuilder.h) +QT_CLASS_LIB(QLatin1Literal, QtCore, qstring.h) QT_CLASS_LIB(QAbstractConcatenable, QtCore, qstringbuilder.h) QT_CLASS_LIB(QConcatenable, QtCore, qstringbuilder.h) QT_CLASS_LIB(QStringBuilder, QtCore, qstringbuilder.h) diff --git a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp index 681a5d0146..cc67fc7884 100644 --- a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp +++ b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp @@ -130,7 +130,7 @@ public: QString m_value; void setValue(const QString &value) { m_value = value; } QString getValue() { return m_value; } - void resetValue() { m_value = QLatin1Literal("reset"); } + void resetValue() { m_value = QLatin1String("reset"); } }; void tst_QMetaProperty::gadget() @@ -140,7 +140,7 @@ void tst_QMetaProperty::gadget() QVERIFY(valueProp.isValid()); { MyGadget g; - QString hello = QLatin1Literal("hello"); + QString hello = QLatin1String("hello"); QVERIFY(valueProp.writeOnGadget(&g, hello)); QCOMPARE(g.m_value, QLatin1String("hello")); QCOMPARE(valueProp.readOnGadget(&g), QVariant(hello)); @@ -242,7 +242,7 @@ void tst_QMetaProperty::conversion() QCOMPARE(custom.str, QString()); // or reset resetable QVERIFY(value7P.write(this, QVariant())); - QCOMPARE(value7, QLatin1Literal("reset")); + QCOMPARE(value7, QLatin1String("reset")); } QTEST_MAIN(tst_QMetaProperty) diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index f1c4effa95..7c9d8a476a 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -5979,7 +5979,7 @@ void ConnectToPrivateSlot::test(SenderObject* obj1) { obj1->signal1(); QCOMPARE(d->receivedCount, 1); QCOMPARE(d->receivedValue, QVariant()); - obj1->signal7(666, QLatin1Literal("_")); + obj1->signal7(666, QLatin1String("_")); QCOMPARE(d->receivedCount, 2); QCOMPARE(d->receivedValue, QVariant(666)); QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot, Qt::UniqueConnection)); diff --git a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp index ce6ce15767..f35d4f330b 100644 --- a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp +++ b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp @@ -338,9 +338,9 @@ void tst_QBrush::gradientPresets() QCOMPARE(lg->finalStop(), QPointF(1, 0)); QCOMPARE(lg->stops().size(), 3); - QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1Literal("#ff9a9e")))); - QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1Literal("#fad0c4")))); - QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1Literal("#fad0c4")))); + QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1String("#ff9a9e")))); + QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1String("#fad0c4")))); + QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1String("#fad0c4")))); QGradient invalidPreset(QGradient::Preset(-1)); diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp index b5ef454b14..c6f6900def 100644 --- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp +++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp @@ -307,19 +307,19 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier) { switch (modifier) { case Qt::NoModifier: - return QLatin1Literal("No"); + return QLatin1String("No"); break; case Qt::ControlModifier: - return QLatin1Literal("Ctrl"); + return QLatin1String("Ctrl"); break; case Qt::ShiftModifier: - return QLatin1Literal("Shift"); + return QLatin1String("Shift"); break; case Qt::AltModifier: - return QLatin1Literal("Alt"); + return QLatin1String("Alt"); break; case Qt::MetaModifier: - return QLatin1Literal("Meta"); + return QLatin1String("Meta"); break; default: qFatal("Unexpected keyboard modifier"); @@ -331,17 +331,17 @@ static QLatin1String sectionToName(const QDateTimeEdit::Section section) { switch (section) { case QDateTimeEdit::SecondSection: - return QLatin1Literal("Second"); + return QLatin1String("Second"); case QDateTimeEdit::MinuteSection: - return QLatin1Literal("Minute"); + return QLatin1String("Minute"); case QDateTimeEdit::HourSection: - return QLatin1Literal("Hours"); + return QLatin1String("Hours"); case QDateTimeEdit::DaySection: - return QLatin1Literal("Day"); + return QLatin1String("Day"); case QDateTimeEdit::MonthSection: - return QLatin1Literal("Month"); + return QLatin1String("Month"); case QDateTimeEdit::YearSection: - return QLatin1Literal("Year"); + return QLatin1String("Year"); default: qFatal("Unexpected section"); return QLatin1String(); @@ -3217,16 +3217,16 @@ void tst_QDateTimeEdit::wheelEvent_data() QLatin1String sourceName; switch (source) { case Qt::MouseEventNotSynthesized: - sourceName = QLatin1Literal("NotSynthesized"); + sourceName = QLatin1String("NotSynthesized"); break; case Qt::MouseEventSynthesizedBySystem: - sourceName = QLatin1Literal("SynthesizedBySystem"); + sourceName = QLatin1String("SynthesizedBySystem"); break; case Qt::MouseEventSynthesizedByQt: - sourceName = QLatin1Literal("SynthesizedByQt"); + sourceName = QLatin1String("SynthesizedByQt"); break; case Qt::MouseEventSynthesizedByApplication: - sourceName = QLatin1Literal("SynthesizedByApplication"); + sourceName = QLatin1String("SynthesizedByApplication"); break; default: qFatal("Unexpected wheel event source"); diff --git a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp index 954ee6471d..a20b5568da 100644 --- a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp +++ b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp @@ -221,19 +221,19 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier) { switch (modifier) { case Qt::NoModifier: - return QLatin1Literal("No"); + return QLatin1String("No"); break; case Qt::ControlModifier: - return QLatin1Literal("Ctrl"); + return QLatin1String("Ctrl"); break; case Qt::ShiftModifier: - return QLatin1Literal("Shift"); + return QLatin1String("Shift"); break; case Qt::AltModifier: - return QLatin1Literal("Alt"); + return QLatin1String("Alt"); break; case Qt::MetaModifier: - return QLatin1Literal("Meta"); + return QLatin1String("Meta"); break; default: qFatal("Unexpected keyboard modifier"); @@ -1448,16 +1448,16 @@ void tst_QDoubleSpinBox::wheelEvents_data() QLatin1String sourceName; switch (source) { case Qt::MouseEventNotSynthesized: - sourceName = QLatin1Literal("NotSynthesized"); + sourceName = QLatin1String("NotSynthesized"); break; case Qt::MouseEventSynthesizedBySystem: - sourceName = QLatin1Literal("SynthesizedBySystem"); + sourceName = QLatin1String("SynthesizedBySystem"); break; case Qt::MouseEventSynthesizedByQt: - sourceName = QLatin1Literal("SynthesizedByQt"); + sourceName = QLatin1String("SynthesizedByQt"); break; case Qt::MouseEventSynthesizedByApplication: - sourceName = QLatin1Literal("SynthesizedByApplication"); + sourceName = QLatin1String("SynthesizedByApplication"); break; default: qFatal("Unexpected wheel event source"); diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp index 7bce23af26..3dd29b0214 100644 --- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp +++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp @@ -222,19 +222,19 @@ static QLatin1String modifierToName(Qt::KeyboardModifier modifier) { switch (modifier) { case Qt::NoModifier: - return QLatin1Literal("No"); + return QLatin1String("No"); break; case Qt::ControlModifier: - return QLatin1Literal("Ctrl"); + return QLatin1String("Ctrl"); break; case Qt::ShiftModifier: - return QLatin1Literal("Shift"); + return QLatin1String("Shift"); break; case Qt::AltModifier: - return QLatin1Literal("Alt"); + return QLatin1String("Alt"); break; case Qt::MetaModifier: - return QLatin1Literal("Meta"); + return QLatin1String("Meta"); break; default: qFatal("Unexpected keyboard modifier"); @@ -1402,16 +1402,16 @@ void tst_QSpinBox::wheelEvents_data() QLatin1String sourceName; switch (source) { case Qt::MouseEventNotSynthesized: - sourceName = QLatin1Literal("NotSynthesized"); + sourceName = QLatin1String("NotSynthesized"); break; case Qt::MouseEventSynthesizedBySystem: - sourceName = QLatin1Literal("SynthesizedBySystem"); + sourceName = QLatin1String("SynthesizedBySystem"); break; case Qt::MouseEventSynthesizedByQt: - sourceName = QLatin1Literal("SynthesizedByQt"); + sourceName = QLatin1String("SynthesizedByQt"); break; case Qt::MouseEventSynthesizedByApplication: - sourceName = QLatin1Literal("SynthesizedByApplication"); + sourceName = QLatin1String("SynthesizedByApplication"); break; default: qFatal("Unexpected wheel event source"); diff --git a/tests/benchmarks/corelib/tools/qstringbuilder/main.cpp b/tests/benchmarks/corelib/tools/qstringbuilder/main.cpp index d0dfe3b1a7..0de6d33846 100644 --- a/tests/benchmarks/corelib/tools/qstringbuilder/main.cpp +++ b/tests/benchmarks/corelib/tools/qstringbuilder/main.cpp @@ -401,7 +401,7 @@ private slots: } private: - const QLatin1Literal l1literal; + const QLatin1String l1literal; const QLatin1String l1string; const QByteArray ba; const QString string;