macOS/iOS: Correctly ignore punctuation in QCollator

When punctuation is ignored then the kUCCollatePunctionSignificantMask
should not be set. This was originally thought to not be working due to
a bug on the Apple platforms, but this is not the case.

[ChangeLog][Platform Specific Changes][macOS][iOS] QCollator now
respects the ignorePunctuation property on Apple based platforms
correctly.

Task-number: QTBUG-41978
Change-Id: I62044076387d6e4479f4aaef3c2f48f49dbd160e
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
bb10
Andy Shaw 2017-05-30 21:45:23 +02:00
parent ea568c310d
commit 26fd805f50
3 changed files with 57 additions and 31 deletions

View File

@ -254,7 +254,7 @@ bool QCollator::numericMode() const
The default is locale dependent.
\note This method is not currently supported on Apple platforms or if Qt is configured to not use ICU on Linux.
\note This method is not currently supported if Qt is configured to not use ICU on Linux.
\sa ignorePunctuation()
*/

View File

@ -66,7 +66,7 @@ void QCollatorPrivate::init()
options |= kUCCollateCaseInsensitiveMask;
if (numericMode)
options |= kUCCollateDigitsAsNumberMask | kUCCollateDigitsOverrideMask;
if (ignorePunctuation)
if (!ignorePunctuation)
options |= kUCCollatePunctuationSignificantMask;
OSStatus status = UCCreateCollator(

View File

@ -30,6 +30,7 @@
#include <qlocale.h>
#include <qcollator.h>
#include <private/qglobal_p.h>
#include <cstring>
@ -88,6 +89,8 @@ void tst_QCollator::compare_data()
QTest::addColumn<int>("result");
QTest::addColumn<int>("caseInsensitiveResult");
QTest::addColumn<bool>("numericMode");
QTest::addColumn<bool>("ignorePunctuation");
QTest::addColumn<int>("punctuationResult");
/*
A few tests below are commented out on the mac. It's unclear why they fail,
@ -102,55 +105,72 @@ void tst_QCollator::compare_data()
comparison of Latin-1 values, although I'm not sure. So I
just test digits to make sure that it's not totally broken.
*/
QTest::newRow("english1") << QString("en_US") << QString("5") << QString("4") << 1 << 1 << false;
QTest::newRow("english2") << QString("en_US") << QString("4") << QString("6") << -1 << -1 << false;
QTest::newRow("english3") << QString("en_US") << QString("5") << QString("6") << -1 << -1 << false;
QTest::newRow("english4") << QString("en_US") << QString("a") << QString("b") << -1 << -1 << false;
QTest::newRow("english5") << QString("en_US") << QString("test 9") << QString("test 19") << -1 << -1 << true;
QTest::newRow("english1") << QString("en_US") << QString("5") << QString("4") << 1 << 1 << false << false << 1;
QTest::newRow("english2") << QString("en_US") << QString("4") << QString("6") << -1 << -1 << false << false << -1;
QTest::newRow("english3") << QString("en_US") << QString("5") << QString("6") << -1 << -1 << false << false << -1;
QTest::newRow("english4") << QString("en_US") << QString("a") << QString("b") << -1 << -1 << false << false << -1;
QTest::newRow("english5") << QString("en_US") << QString("test 9") << QString("test 19") << -1 << -1 << true << false << -1;
QTest::newRow("english6") << QString("en_US") << QString("test 9") << QString("test_19") << -1 << -1 << true << true << -1;
QTest::newRow("english7") << QString("en_US") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1;
QTest::newRow("english8") << QString("en_US") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0;
/*
In Swedish, a with ring above (E5) comes before a with
diaresis (E4), which comes before o diaresis (F6), which
all come after z.
*/
QTest::newRow("swedish1") << QString("sv_SE") << QString::fromLatin1("\xe5") << QString::fromLatin1("\xe4") << -1 << -1 << false;
QTest::newRow("swedish2") << QString("sv_SE") << QString::fromLatin1("\xe4") << QString::fromLatin1("\xf6") << -1 << -1 << false;
QTest::newRow("swedish3") << QString("sv_SE") << QString::fromLatin1("\xe5") << QString::fromLatin1("\xf6") << -1 << -1 << false;
QTest::newRow("swedish4") << QString("sv_SE") << QString::fromLatin1("z") << QString::fromLatin1("\xe5") << -1 << -1 << false;
QTest::newRow("swedish5") << QString("sv_SE") << QString("9") << QString("19") << -1 << -1 << true;
QTest::newRow("swedish1") << QString("sv_SE") << QString::fromLatin1("\xe5") << QString::fromLatin1("\xe4") << -1 << -1 << false << false << -1;
QTest::newRow("swedish2") << QString("sv_SE") << QString::fromLatin1("\xe4") << QString::fromLatin1("\xf6") << -1 << -1 << false << false << -1;
QTest::newRow("swedish3") << QString("sv_SE") << QString::fromLatin1("\xe5") << QString::fromLatin1("\xf6") << -1 << -1 << false << false << -1;
QTest::newRow("swedish4") << QString("sv_SE") << QString::fromLatin1("z") << QString::fromLatin1("\xe5") << -1 << -1 << false << false << -1;
QTest::newRow("swedish5") << QString("sv_SE") << QString("9") << QString("19") << -1 << -1 << true << false << -1;
QTest::newRow("swedish6") << QString("sv_SE") << QString("Test 9") << QString("Test_19") << -1 << -1 << true << true << -1;
QTest::newRow("swedish7") << QString("sv_SE") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1;
QTest::newRow("swedish8") << QString("sv_SE") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0;
/*
In Norwegian, ae (E6) comes before o with stroke (D8), which
comes before a with ring above (E5).
*/
QTest::newRow("norwegian1") << QString("no_NO") << QString::fromLatin1("\xe6") << QString::fromLatin1("\xd8") << -1 << -1 << false;
QTest::newRow("norwegian2") << QString("no_NO") << QString::fromLatin1("\xd8") << QString::fromLatin1("\xe5") << -1 << -1 << false;
QTest::newRow("norwegian3") << QString("no_NO") << QString::fromLatin1("\xe6") << QString::fromLatin1("\xe5") << -1 << -1 << false;
QTest::newRow("norwegian4") << QString("no_NO") << QString("9") << QString("19") << -1 << -1 << true;
QTest::newRow("norwegian1") << QString("no_NO") << QString::fromLatin1("\xe6") << QString::fromLatin1("\xd8") << -1 << -1 << false << false << -1;
QTest::newRow("norwegian2") << QString("no_NO") << QString::fromLatin1("\xd8") << QString::fromLatin1("\xe5") << -1 << -1 << false << false << -1;
QTest::newRow("norwegian3") << QString("no_NO") << QString::fromLatin1("\xe6") << QString::fromLatin1("\xe5") << -1 << -1 << false << false << -1;
QTest::newRow("norwegian4") << QString("no_NO") << QString("9") << QString("19") << -1 << -1 << true << false << -1;
QTest::newRow("norwegian5") << QString("no_NO") << QString("Test 9") << QString("Test_19") << -1 << -1 << true << true << -1;
QTest::newRow("norwegian6") << QString("no_NO") << QString("Test 9") << QString("Test_19") << -1 << -1 << true << true << -1;
QTest::newRow("norwegian7") << QString("no_NO") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1;
QTest::newRow("norwegian8") << QString("no_NO") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0;
/*
In German, z comes *after* a with diaresis (E4),
which comes before o diaresis (F6).
*/
QTest::newRow("german1") << QString("de_DE") << QString::fromLatin1("a") << QString::fromLatin1("\xe4") << -1 << -1 << false;
QTest::newRow("german2") << QString("de_DE") << QString::fromLatin1("b") << QString::fromLatin1("\xe4") << 1 << 1 << false;
QTest::newRow("german3") << QString("de_DE") << QString::fromLatin1("z") << QString::fromLatin1("\xe4") << 1 << 1 << false;
QTest::newRow("german4") << QString("de_DE") << QString::fromLatin1("\xe4") << QString::fromLatin1("\xf6") << -1 << -1 << false;
QTest::newRow("german5") << QString("de_DE") << QString::fromLatin1("z") << QString::fromLatin1("\xf6") << 1 << 1 << false;
QTest::newRow("german6") << QString("de_DE") << QString::fromLatin1("\xc0") << QString::fromLatin1("\xe0") << 1 << 0 << false;
QTest::newRow("german7") << QString("de_DE") << QString::fromLatin1("\xd6") << QString::fromLatin1("\xf6") << 1 << 0 << false;
QTest::newRow("german8") << QString("de_DE") << QString::fromLatin1("oe") << QString::fromLatin1("\xf6") << 1 << 1 << false;
QTest::newRow("german9") << QString("de_DE") << QString("A") << QString("a") << 1 << 0 << false;
QTest::newRow("german10") << QString("de_DE") << QString("9") << QString("19") << -1 << -1 << true;
QTest::newRow("german1") << QString("de_DE") << QString::fromLatin1("a") << QString::fromLatin1("\xe4") << -1 << -1 << false << false << -1;
QTest::newRow("german2") << QString("de_DE") << QString::fromLatin1("b") << QString::fromLatin1("\xe4") << 1 << 1 << false << false << 1;
QTest::newRow("german3") << QString("de_DE") << QString::fromLatin1("z") << QString::fromLatin1("\xe4") << 1 << 1 << false << false << 1;
QTest::newRow("german4") << QString("de_DE") << QString::fromLatin1("\xe4") << QString::fromLatin1("\xf6") << -1 << -1 << false << false << -1;
QTest::newRow("german5") << QString("de_DE") << QString::fromLatin1("z") << QString::fromLatin1("\xf6") << 1 << 1 << false << false << 1;
QTest::newRow("german6") << QString("de_DE") << QString::fromLatin1("\xc0") << QString::fromLatin1("\xe0") << 1 << 0 << false << false << 0;
QTest::newRow("german7") << QString("de_DE") << QString::fromLatin1("\xd6") << QString::fromLatin1("\xf6") << 1 << 0 << false << false << 0;
QTest::newRow("german8") << QString("de_DE") << QString::fromLatin1("oe") << QString::fromLatin1("\xf6") << 1 << 1 << false << false << 1;
QTest::newRow("german9") << QString("de_DE") << QString("A") << QString("a") << 1 << 0 << false << false << 0;
QTest::newRow("german10") << QString("de_DE") << QString("9") << QString("19") << -1 << -1 << true << false << -1;
QTest::newRow("german11") << QString("de_DE") << QString("Test 9") << QString("Test_19") << -1 << -1 << true << true << -1;
QTest::newRow("german12") << QString("de_DE") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1;
QTest::newRow("german13") << QString("de_DE") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0;
/*
French sorting of e and e with accent
*/
QTest::newRow("french1") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("e") << 1 << 1 << false;
QTest::newRow("french2") << QString("fr_FR") << QString::fromLatin1("\xe9t") << QString::fromLatin1("et") << 1 << 1 << false;
QTest::newRow("french3") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("d") << 1 << 1 << false;
QTest::newRow("french4") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("f") << -1 << -1 << false;
QTest::newRow("french5") << QString("fr_FR") << QString("9") << QString("19") << -1 << -1 << true;
QTest::newRow("french1") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("e") << 1 << 1 << false << false << 1;
QTest::newRow("french2") << QString("fr_FR") << QString::fromLatin1("\xe9t") << QString::fromLatin1("et") << 1 << 1 << false << false << 1;
QTest::newRow("french3") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("d") << 1 << 1 << false << false << 1;
QTest::newRow("french4") << QString("fr_FR") << QString::fromLatin1("\xe9") << QString::fromLatin1("f") << -1 << -1 << false << false << -1;
QTest::newRow("french5") << QString("fr_FR") << QString("9") << QString("19") << -1 << -1 << true << false << -1;
QTest::newRow("french6") << QString("fr_FR") << QString("Test 9") << QString("Test_19") << -1 << -1 << true << true << -1;
QTest::newRow("french7") << QString("fr_FR") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1;
QTest::newRow("french8") << QString("fr_FR") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0;
}
@ -162,6 +182,8 @@ void tst_QCollator::compare()
QFETCH(int, result);
QFETCH(int, caseInsensitiveResult);
QFETCH(bool, numericMode);
QFETCH(bool, ignorePunctuation);
QFETCH(int, punctuationResult);
QCollator collator(locale);
@ -176,6 +198,10 @@ void tst_QCollator::compare()
QCOMPARE(collator.compare(s1, s2), result);
collator.setCaseSensitivity(Qt::CaseInsensitive);
QCOMPARE(collator.compare(s1, s2), caseInsensitiveResult);
#if !QT_CONFIG(iconv)
collator.setIgnorePunctuation(ignorePunctuation);
QCOMPARE(collator.compare(s1, s2), punctuationResult);
#endif
}