summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2018-01-09 21:27:29 +0100
committerLiang Qi <liang.qi@qt.io>2018-01-09 21:27:30 +0100
commit9bee6712fc7fd4c8083b4c2c9b1eb0c54d4725dd (patch)
tree91c2306fc1c8b90fe81f678bbf3618084641c9e3
parent50deb8cf70f61e21fb0c35182341477af11adbc1 (diff)
parenta5ad605dfec2ab4e921d5c5843b23916ed5ae3bf (diff)
Merge remote-tracking branch 'origin/5.9' into 5.10
-rw-r--r--header.LGPL2133
-rw-r--r--mkspecs/integrity-armv8-rcar/qplatformdefs.h30
-rw-r--r--src/corelib/Qt5CoreMacros.cmake2
-rw-r--r--src/gui/kernel/qevent.cpp1
-rw-r--r--src/gui/text/qfontdatabase.cpp35
-rw-r--r--src/gui/text/qfontengine.cpp37
-rw-r--r--src/network/access/qftp.cpp12
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm3
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp14
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp9
-rw-r--r--src/widgets/dialogs/qfilesystemmodel_p.h19
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp3
-rw-r--r--src/widgets/itemviews/qtablewidget.cpp3
-rw-r--r--src/widgets/itemviews/qtreewidget.cpp3
-rw-r--r--tests/auto/corelib/tools/qdatetime/BLACKLIST3
-rw-r--r--tests/auto/gui/text/qrawfont/tst_qrawfont.cpp37
-rw-r--r--tests/auto/network/access/qftp/tst_qftp.cpp209
-rw-r--r--tests/auto/tools/qmake/testdata/rawString/object2.h34
-rw-r--r--tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp29
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);
+ }
}
}