From 8a33077853e851e2795476cd502444c2d8535f9a Mon Sep 17 00:00:00 2001 From: David Faure Date: Thu, 28 Jul 2016 12:25:59 +0200 Subject: QUrl: fix resolved() for data URLs They look relative because the path doesn't start with a '/' but they have a scheme so they shouldn't be combined as if it was one absolute and one relative URL. [ChangeLog][QtCore][QUrl] QUrl::resolved() no longer treats a URL with a scheme as a relative URL if it matches this URL's scheme. This special casing was incompatible with RFC 3986 and broke resolving data: URLs, for instance. Change-Id: I3758d3a2141cea7c6d13514243eb8dee5d510dd0 Reviewed-by: Thiago Macieira --- tests/auto/corelib/io/qurl/tst_qurl.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'tests/auto/corelib') diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index eb29646053..8f99047df3 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -903,13 +903,11 @@ void tst_QUrl::resolving_data() // Some parsers allow the scheme name to be present in a relative URI // reference if it is the same as the base URI scheme. This is - // considered to be a loophole in prior specifications of partial URI - // [RFC1630]. Its use should be avoided, but is allowed for backward - // compatibility. - // For strict parsers : -// QTest::newRow("http:g [for strict parsers]") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("http:g") << QString::fromLatin1("http:g"); - // For backward compatibility : - QTest::newRow("http:g [for backward compatibility]") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("http:g") << QString::fromLatin1("http://a/b/c/g"); + // considered to be a loophole in prior specifications of partial URI [RFC1630], + //QTest::newRow("http:g [for backward compatibility]") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("http:g") << QString::fromLatin1("http://a/b/c/g"); + // However we don't do that anymore, as per RFC3986, in order for the data:subpage testcase below to work. + QTest::newRow("http:g") << QString::fromLatin1("http://a/b/c/d;p?q") << QString::fromLatin1("http:g") << QString::fromLatin1("http:g"); + QTest::newRow("data:subpage") << QString::fromLatin1("data:text/plain, main page") << QString::fromLatin1("data:text/plain, subpage") << QString::fromLatin1("data:text/plain, subpage"); // Resolve relative with relative QTest::newRow("../a (1)") << QString::fromLatin1("b") << QString::fromLatin1("../a") << QString::fromLatin1("a"); @@ -921,6 +919,10 @@ void tst_QUrl::resolving_data() QTest::newRow("../a (6)") << QString::fromLatin1("/b/a") << QString::fromLatin1("../a") << QString::fromLatin1("/a"); QTest::newRow("../a (7)") << QString::fromLatin1("/b/c/a") << QString::fromLatin1("../a") << QString::fromLatin1("/b/a"); QTest::newRow("../a (8)") << QString::fromLatin1("/b") << QString::fromLatin1("/a") << QString::fromLatin1("/a"); + + // More tests from KDE + QTest::newRow("brackets") << QString::fromLatin1("http://www.calorieking.com/personal/diary/") << QString::fromLatin1("/personal/diary/rpc.php?C=jsrs1&F=getDiaryDay&P0=[2006-3-8]&U=1141858921458") << QString::fromLatin1("http://www.calorieking.com/personal/diary/rpc.php?C=jsrs1&F=getDiaryDay&P0=[2006-3-8]&U=1141858921458"); + QTest::newRow("javascript")<< QString::fromLatin1("http://www.youtube.com/?v=JvOSnRD5aNk") << QString::fromLatin1("javascript:window.location+\"__flashplugin_unique__\"") << QString::fromLatin1("javascript:window.location+%22__flashplugin_unique__%22"); } void tst_QUrl::resolving() -- cgit v1.2.3 From 49c892328223dfa2502b462d8e5e8e181f4f6cd5 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 25 Jul 2016 13:24:59 +0200 Subject: QSortFilterProxyModel: Don't forward the hint from source's layoutChanged signal We can't forward a VerticalSortHint or HorizontalSortHint hint, because we might be filtering extra items. The documentation of QAbstractItemModel::LayoutChangeHint states: Note that VerticalSortHint and HorizontalSortHint carry the meaning that items are being moved within the same parent, not moved to a different parent in the model, and not filtered out or in. And some of the views rely on this assumption (QQmlDelegateModel for example) What happens in the test is the following: - 'model' emit the dataChanged signal when its data is changed. - 'proxi1' QSortFilterProxyModelPrivate::_q_sourceDataChanged does not forward the dataChanged signal imediatly, it will instead first re-sort the model and call layoutAboutToBeChanged / layouChanged with the VerticalSortHint - 'proxy2' would forward the layoutAboutToBeChanged with the hint, but in QSortFilterProxyModelPrivate::_q_sourceLayoutChanged, it will redo the mapping which will cause the changed data to be filtered. So proxy2 can't forward the VerticalSortHint as it removed rows in the process. Change-Id: I20b6983e9d18bf7509fe6144c74f37d24e4a18c2 Reviewed-by: Tobias Koenig Reviewed-by: David Faure --- .../tst_qsortfilterproxymodel.cpp | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'tests/auto/corelib') diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index 0302ae5cbf..5928ee8688 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp @@ -148,6 +148,7 @@ private slots: void noMapAfterSourceDelete(); void forwardDropApi(); void canDropMimeData(); + void filterHint(); protected: void buildHierarchy(const QStringList &data, QAbstractItemModel *model); @@ -3804,6 +3805,12 @@ void tst_QSortFilterProxyModel::moveSourceRows() QCOMPARE(filterBeforeParents.size(), 1); QCOMPARE(filterAfterParents.size(), 1); + QCOMPARE( + filterBeforeParentLayoutSpy.first().at(1).value(), + QAbstractItemModel::NoLayoutChangeHint); + QCOMPARE(filterAfterParentLayoutSpy.first().at(1).value(), + QAbstractItemModel::NoLayoutChangeHint); + QCOMPARE(filterBothBeforeParentLayoutSpy.size(), 0); QCOMPARE(filterBothAfterParentLayoutSpy.size(), 0); } @@ -4124,5 +4131,50 @@ void tst_QSortFilterProxyModel::resortingDoesNotBreakTreeModels() QCOMPARE(proxy.rowCount(pi1), 1); } +void tst_QSortFilterProxyModel::filterHint() +{ + // test that a filtering model does not emit layoutChanged with a hint + QStringListModel model(QStringList() << "one" + << "two" + << "three" + << "four" + << "five" + << "six"); + QSortFilterProxyModel proxy1; + proxy1.setSourceModel(&model); + proxy1.setSortRole(Qt::DisplayRole); + proxy1.setDynamicSortFilter(true); + proxy1.sort(0); + + QSortFilterProxyModel proxy2; + proxy2.setSourceModel(&proxy1); + proxy2.setFilterRole(Qt::DisplayRole); + proxy2.setFilterRegExp("^[^ ]*$"); + proxy2.setDynamicSortFilter(true); + + QSignalSpy proxy1BeforeSpy(&proxy1, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy proxy1AfterSpy(&proxy1, &QSortFilterProxyModel::layoutChanged); + QSignalSpy proxy2BeforeSpy(&proxy2, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy proxy2AfterSpy(&proxy2, &QSortFilterProxyModel::layoutChanged); + + model.setData(model.index(2), QStringLiteral("modified three"), Qt::DisplayRole); + + // The first proxy was re-sorted as one item as changed. + QCOMPARE(proxy1BeforeSpy.size(), 1); + QCOMPARE(proxy1BeforeSpy.first().at(1).value(), + QAbstractItemModel::VerticalSortHint); + QCOMPARE(proxy1AfterSpy.size(), 1); + QCOMPARE(proxy1AfterSpy.first().at(1).value(), + QAbstractItemModel::VerticalSortHint); + + // But the second proxy must not have the VerticalSortHint since an item was filtered + QCOMPARE(proxy2BeforeSpy.size(), 1); + QCOMPARE(proxy2BeforeSpy.first().at(1).value(), + QAbstractItemModel::NoLayoutChangeHint); + QCOMPARE(proxy2AfterSpy.size(), 1); + QCOMPARE(proxy2AfterSpy.first().at(1).value(), + QAbstractItemModel::NoLayoutChangeHint); +} + QTEST_MAIN(tst_QSortFilterProxyModel) #include "tst_qsortfilterproxymodel.moc" -- cgit v1.2.3 From 2a24c3c268d443fb260d731d9f65b57726a40354 Mon Sep 17 00:00:00 2001 From: Clemens Sielaff Date: Sun, 24 Jul 2016 11:21:34 +1200 Subject: Fixed Bug in QVariant comparison when containing QStringLists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As it were, QStringLists were not handled explicitly when comparing QVariants. If both QStringLists contained only a single entry, they were treated as QStrings - if both QStringLists were empty, there were equal (correctly so) - but if one of the QStringLists had more than one entry, the compare function fell through to returning always 1. As discussed here: https://stackoverflow.com/a/38492467/3444217 Added rich comparison tests for all non-numerical, non-recursive QVariants that support them (except QModelIndex and QPersistentModelIndex) Task-number: QTBUG-54893 Change-Id: Icc5480d9ba056ee5efe83da566c5829caa1509d7 Reviewed-by: Jędrzej Nowacki --- .../auto/corelib/kernel/qvariant/tst_qvariant.cpp | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'tests/auto/corelib') diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 76230ccec8..509eed231d 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -279,6 +279,7 @@ private slots: void metaEnums(); void compareSanity_data(); void compareSanity(); + void compareRich(); void accessSequentialContainerKey(); @@ -4745,6 +4746,60 @@ void tst_QVariant::compareSanity() } } +static void richComparison(const QVariant& less, const QVariant& more) +{ + QVERIFY(less.type() == more.type()); + + QVERIFY(less < more); + QVERIFY(!(more < less)); + + QVERIFY(more > less); + QVERIFY(!(less > more)); + + QVERIFY(less <= more); + QVERIFY(!(more <= less)); + QVERIFY(less <= less); + + QVERIFY(more >= less); + QVERIFY(!(less >= more)); + QVERIFY(more >= more); +} + +void tst_QVariant::compareRich() +{ + richComparison(QUuid("{49d8ad2a-2ee8-4c3d-949f-1b5a3765ddf0}"), + QUuid("{f6d56824-16e9-4543-a375-add2877c2d05}")); + richComparison(QByteArray::fromRawData("a", 1), + QByteArray::fromRawData("b", 1)); + richComparison(QStringLiteral("a"), QStringLiteral("b")); + richComparison(QLatin1String("a"), QLatin1String("b")); + richComparison(QChar('a'), QChar('b')); + richComparison(QDate(2016, 7, 23), QDate(2016, 7, 24)); + richComparison(QTime(0, 0), QTime(0, 1)); + richComparison(QDateTime(QDate(2016, 7, 23), QTime(0, 0)), + QDateTime(QDate(2016, 7, 23), QTime(0, 1))); + + richComparison(QStringList(), QStringList() << QStringLiteral("a")); + richComparison(QStringList(), QStringList() << QStringLiteral("a") + << QStringLiteral("b")); + richComparison(QStringList() << QStringLiteral("a"), + QStringList() << QStringLiteral("b")); + richComparison(QStringList() << QStringLiteral("a"), + QStringList() << QStringLiteral("b") + << QStringLiteral("c")); + richComparison(QStringList() << QStringLiteral("a") + << QStringLiteral("c"), + QStringList() << QStringLiteral("b")); + richComparison(QStringList() << QStringLiteral("a") + << QStringLiteral("c"), + QStringList() << QStringLiteral("b") + << QStringLiteral("d")); + richComparison(QStringList() << QStringLiteral("a") + << QStringLiteral("c"), + QStringList() << QStringLiteral("a") + << QStringLiteral("d")); +} + void tst_QVariant::accessSequentialContainerKey() { QString nameResult; -- cgit v1.2.3 From 9c8a8e90a6514c23bcbeb14073a9d6bdd926d68b Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Mon, 11 Jul 2016 17:23:21 +0300 Subject: QString: fix append(const QStringRef &str) Use QStringRef::isNull instead of QStringRef::string() for validation. Non-NULL str.string() may yet leave us with a useless str.unicode(), which is the actual problem here; whereas !str.isNull() does really confirm that str.unicode() is sensible. Such test prevents situation like: const QString a; QString b; b.append(a); // b.isNull() == true b.append(QStringRef(&a)); // b.isNull() == false Auto test updated: create QStringRef from QString directly, without any condition. Change-Id: I082cd58ef656d8a53e3c1223aca01feea82fffb9 Reviewed-by: Thiago Macieira Reviewed-by: Marc Mutz --- tests/auto/corelib/tools/qstring/tst_qstring.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/auto/corelib') diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index da6cdddd4f..db4c33afde 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -131,7 +131,7 @@ template <> class Arg : ArgBase { QStringRef ref() const - { return this->pinned.isNull() ? QStringRef() : this->pinned.midRef(0) ; } + { return QStringRef(&pinned); } public: explicit Arg(const char *str) : ArgBase(str) {} -- cgit v1.2.3