diff options
author | Liang Qi <liang.qi@qt.io> | 2018-01-09 21:27:29 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2018-01-09 21:27:30 +0100 |
commit | 9bee6712fc7fd4c8083b4c2c9b1eb0c54d4725dd (patch) | |
tree | 91c2306fc1c8b90fe81f678bbf3618084641c9e3 | |
parent | 50deb8cf70f61e21fb0c35182341477af11adbc1 (diff) | |
parent | a5ad605dfec2ab4e921d5c5843b23916ed5ae3bf (diff) |
Merge remote-tracking branch 'origin/5.9' into 5.10
Change-Id: I840849c072075a69819eb185b20bc42c3de0f825
-rw-r--r-- | header.LGPL21 | 33 | ||||
-rw-r--r-- | mkspecs/integrity-armv8-rcar/qplatformdefs.h | 30 | ||||
-rw-r--r-- | src/corelib/Qt5CoreMacros.cmake | 2 | ||||
-rw-r--r-- | src/gui/kernel/qevent.cpp | 1 | ||||
-rw-r--r-- | src/gui/text/qfontdatabase.cpp | 35 | ||||
-rw-r--r-- | src/gui/text/qfontengine.cpp | 37 | ||||
-rw-r--r-- | src/network/access/qftp.cpp | 12 | ||||
-rw-r--r-- | src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm | 3 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 14 | ||||
-rw-r--r-- | src/widgets/dialogs/qfilesystemmodel.cpp | 9 | ||||
-rw-r--r-- | src/widgets/dialogs/qfilesystemmodel_p.h | 19 | ||||
-rw-r--r-- | src/widgets/itemviews/qlistwidget.cpp | 3 | ||||
-rw-r--r-- | src/widgets/itemviews/qtablewidget.cpp | 3 | ||||
-rw-r--r-- | src/widgets/itemviews/qtreewidget.cpp | 3 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qdatetime/BLACKLIST | 3 | ||||
-rw-r--r-- | tests/auto/gui/text/qrawfont/tst_qrawfont.cpp | 37 | ||||
-rw-r--r-- | tests/auto/network/access/qftp/tst_qftp.cpp | 209 | ||||
-rw-r--r-- | tests/auto/tools/qmake/testdata/rawString/object2.h | 34 | ||||
-rw-r--r-- | tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp | 29 |
19 files changed, 432 insertions, 84 deletions
diff --git a/header.LGPL21 b/header.LGPL21 deleted file mode 100644 index 533390b078..0000000000 --- a/header.LGPL21 +++ /dev/null @@ -1,33 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the FOO module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - diff --git a/mkspecs/integrity-armv8-rcar/qplatformdefs.h b/mkspecs/integrity-armv8-rcar/qplatformdefs.h index 55afd0c3c7..a743326346 100644 --- a/mkspecs/integrity-armv8-rcar/qplatformdefs.h +++ b/mkspecs/integrity-armv8-rcar/qplatformdefs.h @@ -5,27 +5,33 @@ ** ** This file is part of the qmake spec of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake index 8b65db95cb..8d3dbe3ecf 100644 --- a/src/corelib/Qt5CoreMacros.cmake +++ b/src/corelib/Qt5CoreMacros.cmake @@ -257,7 +257,7 @@ function(QT5_ADD_BINARY_RESOURCES target ) add_custom_command(OUTPUT ${rcc_destination} COMMAND ${Qt5Core_RCC_EXECUTABLE} ARGS ${rcc_options} --binary --name ${target} --output ${rcc_destination} ${infiles} - DEPENDS ${rc_depends} ${out_depends} VERBATIM) + DEPENDS ${rc_depends} ${out_depends} ${infiles} VERBATIM) add_custom_target(${target} ALL DEPENDS ${rcc_destination}) endfunction() diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 916b13df44..139b36ef71 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -972,6 +972,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, \li scrolling is about to begin, but the distance did not yet change (Qt::ScrollBegin), \li or scrolling has ended and the distance did not change anymore (Qt::ScrollEnd). \endlist + \note On X11 this value is driver specific and unreliable, use angleDelta() instead */ /*! diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 2cc071d67b..33dc27983a 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -2837,6 +2837,41 @@ QString QFontDatabase::resolveFontFamilyAlias(const QString &family) return QGuiApplicationPrivate::platformIntegration()->fontDatabase()->resolveFontFamilyAlias(family); } +Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QChar::Script script, const QStringList &families) +{ + size_t writingSystem = std::find(scriptForWritingSystem, + scriptForWritingSystem + QFontDatabase::WritingSystemsCount, + script) - scriptForWritingSystem; + if (writingSystem == QFontDatabase::Any + || writingSystem >= QFontDatabase::WritingSystemsCount) { + return families; + } + + QFontDatabasePrivate *db = privateDb(); + QMultiMap<uint, QString> supported; + for (int i = 0; i < families.size(); ++i) { + const QString &family = families.at(i); + + QtFontFamily *testFamily = nullptr; + for (int x = 0; x < db->count; ++x) { + if (Q_UNLIKELY(matchFamilyName(family, db->families[x]))) { + testFamily = db->families[x]; + testFamily->ensurePopulated(); + break; + } + } + + uint order = i; + if (testFamily == nullptr + || (testFamily->writingSystems[writingSystem] & QtFontFamily::Supported) == 0) { + order |= 1 << 31; + } + + supported.insert(order, family); + } + + return supported.values(); +} QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index e4f9b8b9d4..33df020a6c 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -1845,7 +1845,12 @@ QFontEngine *QFontEngineMulti::loadEngine(int at) request.styleStrategy |= QFont::NoFontMerging; request.family = fallbackFamilyAt(at - 1); - if (QFontEngine *engine = QFontDatabase::findFont(request, m_script)) { + // At this point, the main script of the text has already been considered + // when fetching the list of fallback families from the database, and the + // info about the actual script of the characters may have been discarded, + // so we do not check for writing system support, but instead just load + // the family indiscriminately. + if (QFontEngine *engine = QFontDatabase::findFont(request, QFontDatabase::Any)) { engine->fontDef.weight = request.weight; if (request.style > QFont::StyleNormal) engine->fontDef.style = request.style; @@ -1898,8 +1903,33 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, int glyph_pos = 0; QStringIterator it(str, str + len); + + int lastFallback = -1; while (it.hasNext()) { const uint ucs4 = it.peekNext(); + + // If we applied a fallback font to previous glyph, and the current is either + // ZWJ or ZWNJ, we should also try applying the same fallback font to that, in order + // to get the correct shaping rules applied. + if (lastFallback >= 0 && (ucs4 == QChar(0x200d) || ucs4 == QChar(0x200c))) { + QFontEngine *engine = m_engines.at(lastFallback); + glyph_t glyph = engine->glyphIndex(ucs4); + if (glyph != 0) { + glyphs->glyphs[glyph_pos] = glyph; + if (!(flags & GlyphIndicesOnly)) { + QGlyphLayout g = glyphs->mid(glyph_pos, 1); + engine->recalcAdvances(&g, flags); + } + + // set the high byte to indicate which engine the glyph came from + glyphs->glyphs[glyph_pos] |= (lastFallback << 24); + } else { + lastFallback = -1; + } + } else { + lastFallback = -1; + } + if (glyphs->glyphs[glyph_pos] == 0 && ucs4 != QChar::LineSeparator && ucs4 != QChar::LineFeed @@ -1928,6 +1958,9 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout g = glyphs->mid(glyph_pos, 1); engine->recalcAdvances(&g, flags); } + + lastFallback = x; + // set the high byte to indicate which engine the glyph came from glyphs->glyphs[glyph_pos] |= (x << 24); break; diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp index 762ef00225..719e3536b4 100644 --- a/src/network/access/qftp.cpp +++ b/src/network/access/qftp.cpp @@ -1702,8 +1702,16 @@ int QFtp::connectToHost(const QString &host, quint16 port) int QFtp::login(const QString &user, const QString &password) { QStringList cmds; - cmds << (QLatin1String("USER ") + (user.isNull() ? QLatin1String("anonymous") : user) + QLatin1String("\r\n")); - cmds << (QLatin1String("PASS ") + (password.isNull() ? QLatin1String("anonymous@") : password) + QLatin1String("\r\n")); + + if (user.isNull() || user.compare(QLatin1String("anonymous"), Qt::CaseInsensitive) == 0) { + cmds << (QLatin1String("USER ") + (user.isNull() ? QLatin1String("anonymous") : user) + QLatin1String("\r\n")); + cmds << (QLatin1String("PASS ") + (password.isNull() ? QLatin1String("anonymous@") : password) + QLatin1String("\r\n")); + } else { + cmds << (QLatin1String("USER ") + user + QLatin1String("\r\n")); + if (!password.isNull()) + cmds << (QLatin1String("PASS ") + password + QLatin1String("\r\n")); + } + return d_func()->addCommand(new QFtpCommand(Login, cmds)); } diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 237e8a89a5..7397312820 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -544,6 +544,9 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo fallbackList.append(QStringLiteral("Arial Unicode MS")); #endif + extern QStringList qt_sort_families_by_writing_system(QChar::Script, const QStringList &); + fallbackList = qt_sort_families_by_writing_system(script, fallbackList); + return fallbackList; } } diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index b2dcf7c3e7..335ec344d5 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -1019,10 +1019,12 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin double delta = scrollingDevice.lastScrollPosition.y() - value; scrollingDevice.lastScrollPosition.setY(value); angleDelta.setY((delta / scrollingDevice.verticalIncrement) * 120); - // We do not set "pixel" delta if it is only measured in ticks. - if (scrollingDevice.verticalIncrement > 1) + // With most drivers the increment is 1 for wheels. + // For libinput it is hardcoded to a useless 15. + // For a proper touchpad driver it should be in the same order of magnitude as 120 + if (scrollingDevice.verticalIncrement > 15) rawDelta.setY(delta); - else if (scrollingDevice.verticalIncrement < -1) + else if (scrollingDevice.verticalIncrement < -15) rawDelta.setY(-delta); } } @@ -1031,10 +1033,10 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin double delta = scrollingDevice.lastScrollPosition.x() - value; scrollingDevice.lastScrollPosition.setX(value); angleDelta.setX((delta / scrollingDevice.horizontalIncrement) * 120); - // We do not set "pixel" delta if it is only measured in ticks. - if (scrollingDevice.horizontalIncrement > 1) + // See comment under vertical + if (scrollingDevice.horizontalIncrement > 15) rawDelta.setX(delta); - else if (scrollingDevice.horizontalIncrement < -1) + else if (scrollingDevice.horizontalIncrement < -15) rawDelta.setX(-delta); } } diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 2b79831a74..14ac6ad31b 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -1086,8 +1086,8 @@ void QFileSystemModelPrivate::sortChildren(int column, const QModelIndex &parent return; QVector<QFileSystemModelPrivate::QFileSystemNode*> values; - QHash<QString, QFileSystemNode *>::const_iterator iterator; - for(iterator = indexNode->children.constBegin() ; iterator != indexNode->children.constEnd() ; ++iterator) { + + for (auto iterator = indexNode->children.constBegin(), cend = indexNode->children.constEnd(); iterator != cend; ++iterator) { if (filtersAcceptsNode(iterator.value())) { values.append(iterator.value()); } else { @@ -1647,13 +1647,10 @@ void QFileSystemModelPrivate::_q_directoryChanged(const QString &directory, cons QStringList toRemove; QStringList newFiles = files; std::sort(newFiles.begin(), newFiles.end()); - QHash<QString, QFileSystemNode*>::const_iterator i = parentNode->children.constBegin(); - while (i != parentNode->children.constEnd()) { + for (auto i = parentNode->children.constBegin(), cend = parentNode->children.constEnd(); i != cend; ++i) { QStringList::iterator iterator = std::lower_bound(newFiles.begin(), newFiles.end(), i.value()->fileName); if ((iterator == newFiles.end()) || (i.value()->fileName < *iterator)) toRemove.append(i.value()->fileName); - - ++i; } for (int i = 0 ; i < toRemove.count() ; ++i ) removeNode(parentNode, toRemove[i]); diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h index 640225529b..e8bae4f659 100644 --- a/src/widgets/dialogs/qfilesystemmodel_p.h +++ b/src/widgets/dialogs/qfilesystemmodel_p.h @@ -72,6 +72,23 @@ class ExtendedInformation; class QFileSystemModelPrivate; class QFileIconProvider; +#if defined(Q_OS_WIN) +class QFileSystemModelNodePathKey : public QString +{ +public: + QFileSystemModelNodePathKey() {} + QFileSystemModelNodePathKey(const QString &other) : QString(other) {} + QFileSystemModelNodePathKey(const QFileSystemModelNodePathKey &other) : QString(other) {} + bool operator==(const QFileSystemModelNodePathKey &other) const { return !compare(other, Qt::CaseInsensitive); } +}; + +Q_DECLARE_TYPEINFO(QFileSystemModelNodePathKey, Q_MOVABLE_TYPE); + +inline uint qHash(const QFileSystemModelNodePathKey &key) { return qHash(key.toCaseFolded()); } +#else // Q_OS_WIN +typedef QString QFileSystemModelNodePathKey; +#endif + class Q_AUTOTEST_EXPORT QFileSystemModelPrivate : public QAbstractItemModelPrivate { Q_DECLARE_PUBLIC(QFileSystemModel) @@ -189,7 +206,7 @@ public: bool populatedChildren; bool isVisible; - QHash<QString,QFileSystemNode *> children; + QHash<QFileSystemModelNodePathKey, QFileSystemNode *> children; QList<QString> visibleChildren; int dirtyChildrenIndex; QFileSystemNode *parent; diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp index 95ad3f82d0..61b2c5e78f 100644 --- a/src/widgets/itemviews/qlistwidget.cpp +++ b/src/widgets/itemviews/qlistwidget.cpp @@ -690,6 +690,9 @@ QListWidgetItem *QListWidgetItem::clone() const Sets the data for a given \a role to the given \a value. Reimplement this function if you need extra roles or special behavior for certain roles. + \note The default implementation treats Qt::EditRole and Qt::DisplayRole as + referring to the same data. + \sa Qt::ItemDataRole, data() */ void QListWidgetItem::setData(int role, const QVariant &value) diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp index bb1970e3ac..892a8d3a22 100644 --- a/src/widgets/itemviews/qtablewidget.cpp +++ b/src/widgets/itemviews/qtablewidget.cpp @@ -1365,6 +1365,9 @@ QTableWidgetItem *QTableWidgetItem::clone() const /*! Sets the item's data for the given \a role to the specified \a value. + \note The default implementation treats Qt::EditRole and Qt::DisplayRole as + referring to the same data. + \sa Qt::ItemDataRole, data() */ void QTableWidgetItem::setData(int role, const QVariant &value) diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp index d7b46a0835..b253abac73 100644 --- a/src/widgets/itemviews/qtreewidget.cpp +++ b/src/widgets/itemviews/qtreewidget.cpp @@ -1699,6 +1699,9 @@ Qt::ItemFlags QTreeWidgetItem::flags() const The \a role describes the type of data specified by \a value, and is defined by the Qt::ItemDataRole enum. + + \note The default implementation treats Qt::EditRole and Qt::DisplayRole as + referring to the same data. */ void QTreeWidgetItem::setData(int column, int role, const QVariant &value) { diff --git a/tests/auto/corelib/tools/qdatetime/BLACKLIST b/tests/auto/corelib/tools/qdatetime/BLACKLIST deleted file mode 100644 index e78f5cfd87..0000000000 --- a/tests/auto/corelib/tools/qdatetime/BLACKLIST +++ /dev/null @@ -1,3 +0,0 @@ -[operator_eqeq] -ubuntu-16.04 -b2qt diff --git a/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp index 3cf108ed62..37f94d0278 100644 --- a/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp +++ b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp @@ -90,6 +90,9 @@ private slots: void rawFontFromInvalidData(); void kernedAdvances(); + + void fallbackFontsOrder(); + private: QString testFont; QString testFontBoldItalic; @@ -887,7 +890,7 @@ void tst_QRawFont::unsupportedWritingSystem() QCOMPARE(rawFont.familyName(), QString::fromLatin1("QtBidiTestFont")); QCOMPARE(rawFont.pixelSize(), 12.0); - QString arabicText = QFontDatabase::writingSystemSample(QFontDatabase::Arabic); + QString arabicText = QFontDatabase::writingSystemSample(QFontDatabase::Arabic).simplified().remove(QLatin1Char(' ')); QTextLayout layout; layout.setFont(font); @@ -1009,6 +1012,38 @@ void tst_QRawFont::kernedAdvances() QVERIFY(FUZZY_LTEQ(qAbs(advances.at(0).x() - expectedAdvanceWidth), errorMargin)); } +void tst_QRawFont::fallbackFontsOrder() +{ + QFontDatabase fontDatabase; + int id = fontDatabase.addApplicationFont(testFont); + + QFont font("QtBidiTestFont"); + font.setPixelSize(12.0); + + QString arabicText = QFontDatabase::writingSystemSample(QFontDatabase::Arabic); + + // If this fails, then the writing system sample has changed and we need to create + // a new text containing both a space and Arabic characters. + QVERIFY(arabicText.contains(QLatin1Char(' '))); + + QTextLayout layout; + layout.setFont(font); + layout.setText(arabicText); + layout.setCacheEnabled(true); + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QList<QGlyphRun> glyphRuns = layout.glyphRuns(); + + // Since QtBidiTestFont does not support Arabic nor the space, both should map to + // the same font. If this fails, it is an indication that the list of fallbacks fonts + // is not sorted by writing system support. + QCOMPARE(glyphRuns.size(), 1); + + fontDatabase.removeApplicationFont(id); +} + #endif // QT_NO_RAWFONT QTEST_MAIN(tst_QRawFont) diff --git a/tests/auto/network/access/qftp/tst_qftp.cpp b/tests/auto/network/access/qftp/tst_qftp.cpp index 4bc43f068c..f9f48506d6 100644 --- a/tests/auto/network/access/qftp/tst_qftp.cpp +++ b/tests/auto/network/access/qftp/tst_qftp.cpp @@ -41,6 +41,8 @@ #include <qnetworkconfigmanager.h> #include <QNetworkSession> #include <QtNetwork/private/qnetworksession_p.h> +#include <QTcpServer> +#include <QHostInfo> #include "../../../network-settings.h" @@ -108,6 +110,9 @@ private slots: void qtbug7359Crash(); + void loginURL_data(); + void loginURL(); + protected slots: void stateChanged( int ); void listInfo( const QUrlInfo & ); @@ -395,11 +400,11 @@ void tst_QFtp::login_data() QTest::addColumn<int>("success"); QTest::newRow( "ok01" ) << QtNetworkSettings::serverName() << (uint)21 << QString() << QString() << 1; - QTest::newRow( "ok02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString() << 1; + QTest::newRow( "ok02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("") << 1; QTest::newRow( "ok03" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftp") << QString("foo") << 1; QTest::newRow( "ok04" ) << QtNetworkSettings::serverName() << (uint)21 << QString("ftptest") << QString("password") << 1; - QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString() << 0; + QTest::newRow( "error01" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString("") << 0; QTest::newRow( "error02" ) << QtNetworkSettings::serverName() << (uint)21 << QString("foo") << QString("bar") << 0; } @@ -2150,6 +2155,206 @@ void tst_QFtp::qtbug7359Crash() QCoreApplication::processEvents(QEventLoop::AllEvents, 2000 - elapsed); } +class FtpLocalServer : public QTcpServer +{ + Q_OBJECT + +public: + explicit FtpLocalServer(QObject *parent = 0) : QTcpServer(parent) {} + virtual ~FtpLocalServer() { delete mSocket; } + void startServer(qint16 port = 0); + void stopServer(); + + enum class ReplyCodes { + ServiceReady = 220, + ServiceClose = 221, + NeedPassword = 331, + LoginFailed = 530, + RequestDeny = 550 + }; + + void sendResponse(ReplyCodes code); + + inline QString getRawUser() { return rawUser; } + inline QString getRawPassword() { return rawPass; } + +signals: + void onStarted(); + void onStopped(); + +public slots: + void socketReadyRead(); + void socketDisconnected(); + +protected: + virtual void incomingConnection(qintptr handle); + +private: + QTcpSocket *mSocket = nullptr; + QString rawUser; + QString rawPass; +}; + +void FtpLocalServer::startServer(qint16 port) +{ + if (listen(QHostAddress::Any, port)) + emit onStarted(); // Notify connected objects + else + qDebug("Could not start FTP server"); +} + +void FtpLocalServer::stopServer() +{ + close(); + emit onStopped(); // Notify connected objects +} + +void FtpLocalServer::sendResponse(ReplyCodes code) +{ + if (mSocket) + { + QString response; + switch (code) { + case ReplyCodes::ServiceReady: + response = QString("220 Service ready for new user.\r\n"); + break; + case ReplyCodes::ServiceClose: + response = QString("221 Service closing control connection.\r\n"); + break; + case ReplyCodes::NeedPassword: + response = QString("331 User name okay, need password.\r\n"); + break; + case ReplyCodes::LoginFailed: + response = QString("530 Not logged in.\r\n"); + break; + case ReplyCodes::RequestDeny: + response = QString("550 Requested action not taken.\r\n"); + break; + default: + qDebug("Unimplemented response code: %u", static_cast<uint>(code)); + break; + } + + if (!response.isEmpty()) + mSocket->write(response.toLatin1()); + } +} + +void FtpLocalServer::incomingConnection(qintptr handle) +{ + mSocket = new QTcpSocket(this); + if (mSocket == nullptr || !mSocket->setSocketDescriptor(handle)) + { + delete mSocket; + mSocket = nullptr; + qDebug() << handle << " Error binding socket"; + return; + } + + connect(mSocket, SIGNAL(readyRead()), this, SLOT(socketReadyRead())); + connect(mSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); + + // Accept client connection + sendResponse(ReplyCodes::ServiceReady); +} + +void FtpLocalServer::socketReadyRead() +{ + QString data; + if (mSocket) + data.append(mSocket->readAll()); + + // RFC959 Upper and lower case alphabetic characters are to be treated identically. + if (data.startsWith("USER", Qt::CaseInsensitive)) { + rawUser = data; + sendResponse(ReplyCodes::NeedPassword); + } else if (data.startsWith("PASS", Qt::CaseInsensitive)) { + rawPass = data; + sendResponse(ReplyCodes::LoginFailed); + } else { + sendResponse(ReplyCodes::RequestDeny); + } +} + +void FtpLocalServer::socketDisconnected() +{ + // Cleanup + if (mSocket) + mSocket->deleteLater(); + deleteLater(); +} + +void tst_QFtp::loginURL_data() +{ + QTest::addColumn<QString>("user"); + QTest::addColumn<QString>("password"); + QTest::addColumn<QString>("rawUser"); + QTest::addColumn<QString>("rawPass"); + + QTest::newRow("no username, no password") + << QString() << QString() + << QString("USER anonymous\r\n") << QString("PASS anonymous@\r\n"); + + QTest::newRow("username, no password") + << QString("someone") << QString() + << QString("USER someone\r\n") << QString(); + + QTest::newRow("username, empty password") + << QString("someone") << QString("") + << QString("USER someone\r\n") << QString("PASS \r\n"); + + QTest::newRow("username, password") + << QString("someone") << QString("nonsense") + << QString("USER someone\r\n") << QString("PASS nonsense\r\n"); + + QTest::newRow("anonymous, no password") + << QString("anonymous") << QString() + << QString("USER anonymous\r\n") << QString("PASS anonymous@\r\n"); + + QTest::newRow("Anonymous, no password") + << QString("Anonymous") << QString() + << QString("USER Anonymous\r\n") << QString("PASS anonymous@\r\n"); + + QTest::newRow("anonymous, empty password") + << QString("anonymous") << QString("") + << QString("USER anonymous\r\n") << QString("PASS \r\n"); + + QTest::newRow("ANONYMOUS, password") + << QString("ANONYMOUS") << QString("nonsense") + << QString("USER ANONYMOUS\r\n") << QString("PASS nonsense\r\n"); +} + +void tst_QFtp::loginURL() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + QSKIP("This test should be verified on the local machine without proxies"); + + QFETCH(QString, user); + QFETCH(QString, password); + QFETCH(QString, rawUser); + QFETCH(QString, rawPass); + + FtpLocalServer server; + server.startServer(); + uint port = server.serverPort(); + + ftp = newFtp(); + addCommand(QFtp::ConnectToHost, + ftp->connectToHost(QHostInfo::localHostName(), port)); + addCommand(QFtp::Login, ftp->login(user, password)); + + QTestEventLoop::instance().enterLoop(5); + delete ftp; + ftp = nullptr; + server.stopServer(); + if (QTestEventLoop::instance().timeout()) + QFAIL(msgTimedOut(QHostInfo::localHostName(), port)); + + QCOMPARE(server.getRawUser(), rawUser); + QCOMPARE(server.getRawPassword(), rawPass); +} + QTEST_MAIN(tst_QFtp) #include "tst_qftp.moc" diff --git a/tests/auto/tools/qmake/testdata/rawString/object2.h b/tests/auto/tools/qmake/testdata/rawString/object2.h index 2ab77cd3bd..d29f0c72ec 100644 --- a/tests/auto/tools/qmake/testdata/rawString/object2.h +++ b/tests/auto/tools/qmake/testdata/rawString/object2.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2017 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:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 979d5c632e..71efe1d59a 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -43,6 +43,7 @@ #if defined(Q_OS_WIN) # include <qt_windows.h> // for SetFileAttributes #endif +#include <private/qfilesystemengine_p.h> #include <algorithm> @@ -883,6 +884,18 @@ void tst_QFileSystemModel::deleteFile() QVERIFY(!newFile.exists()); } +static QString flipCase(QString s) +{ + for (int i = 0, size = s.size(); i < size; ++i) { + const QChar c = s.at(i); + if (c.isUpper()) + s[i] = c.toLower(); + else if (c.isLower()) + s[i] = c.toUpper(); + } + return s; +} + void tst_QFileSystemModel::caseSensitivity() { QString tmp = flatDirTestPath; @@ -890,9 +903,23 @@ void tst_QFileSystemModel::caseSensitivity() files << "a" << "c" << "C"; QVERIFY(createFiles(tmp, files)); QModelIndex root = model->index(tmp); + QStringList paths; + QModelIndexList indexes; QCOMPARE(model->rowCount(root), 0); for (int i = 0; i < files.count(); ++i) { - QVERIFY(model->index(tmp + '/' + files.at(i)).isValid()); + const QString path = tmp + '/' + files.at(i); + const QModelIndex index = model->index(path); + QVERIFY(index.isValid()); + paths.append(path); + indexes.append(index); + } + + if (!QFileSystemEngine::isCaseSensitive()) { + // QTBUG-31103, QTBUG-64147: Verify that files can be accessed by paths with fLipPeD case. + for (int i = 0; i < paths.count(); ++i) { + const QModelIndex flippedCaseIndex = model->index(flipCase(paths.at(i))); + QCOMPARE(indexes.at(i), flippedCaseIndex); + } } } |