Merge "Merge remote-tracking branch 'origin/5.9' into 5.10" into refs/staging/5.10
This commit is contained in:
commit
1759510201
@ -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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
@ -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$
|
||||
**
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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]);
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -1,3 +0,0 @@
|
||||
[operator_eqeq]
|
||||
ubuntu-16.04
|
||||
b2qt
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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$
|
||||
**
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user