diff options
author | Lars Knoll <lars.knoll@digia.com> | 2014-08-27 12:57:14 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@digia.com> | 2014-09-10 21:11:11 +0200 |
commit | c17563eca879845deef542173f5fb479c9aa2d0e (patch) | |
tree | b967050c3502458043998288292d6da952252649 /src/corelib/tools/qcollator_win.cpp | |
parent | 6316a681f3f3dde46d5ab5c915f31a2098b463bb (diff) |
Fix several issues in QCollator
Refactor the code and move more things into the cross platform
code path.
Make sure the flags survive changing the locale of QCollator.
Use the correct locale on Windows, WinRT and OS X. We now
pass all QCollator autotests on these platforms.
Task-number: QTBUG-40778
Change-Id: Ic2d3334b5018c323a35a3ea8fc1d7ab5f99b4e62
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools/qcollator_win.cpp')
-rw-r--r-- | src/corelib/tools/qcollator_win.cpp | 119 |
1 files changed, 45 insertions, 74 deletions
diff --git a/src/corelib/tools/qcollator_win.cpp b/src/corelib/tools/qcollator_win.cpp index 4141ba1205..7f95a3539f 100644 --- a/src/corelib/tools/qcollator_win.cpp +++ b/src/corelib/tools/qcollator_win.cpp @@ -50,90 +50,64 @@ QT_BEGIN_NAMESPACE -void QCollatorPrivate::init() -{ - collator = 0; -} - -void QCollatorPrivate::cleanup() -{ -} - -void QCollator::setCaseSensitivity(Qt::CaseSensitivity cs) -{ - detach(); - - if (cs == Qt::CaseSensitive) - d->collator &= ~NORM_IGNORECASE; - else - d->collator |= NORM_IGNORECASE; -} - -Qt::CaseSensitivity QCollator::caseSensitivity() const -{ - return d->collator & NORM_IGNORECASE ? Qt::CaseInsensitive : Qt::CaseSensitive; -} - //NOTE: SORT_DIGITSASNUMBERS is available since win7 #ifndef SORT_DIGITSASNUMBERS #define SORT_DIGITSASNUMBERS 8 #endif -void QCollator::setNumericMode(bool on) -{ - if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) { - detach(); - if (on) - d->collator |= SORT_DIGITSASNUMBERS; - else - d->collator &= ~SORT_DIGITSASNUMBERS; - } else { - Q_UNUSED(on); - qWarning() << "unsupported in the win collation implementation"; - } -} +// implemented in qlocale_win.cpp +extern LCID qt_inIsoNametoLCID(const char *name); -bool QCollator::numericMode() const +void QCollatorPrivate::init() { - if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) { - return bool(d->collator & SORT_DIGITSASNUMBERS); - } else { - qWarning() << "unsupported in the win collation implementation"; - return false; + collator = 0; + +#ifndef USE_COMPARESTRINGEX + localeID = qt_inIsoNametoLCID(locale.bcp47Name().toUtf8().constData()); +#else + localeName = locale.bcp47Name(); +#endif + + if (caseSensitivity == Qt::CaseInsensitive) + collator |= NORM_IGNORECASE; + + if (numericMode) { + if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) + collator |= SORT_DIGITSASNUMBERS; + else + qWarning() << "Numeric sorting unsupported on Windows versions older than Windows 7."; } -} -void QCollator::setIgnorePunctuation(bool on) -{ - detach(); + if (ignorePunctuation) + collator |= NORM_IGNORESYMBOLS; - if (on) - d->collator |= NORM_IGNORESYMBOLS; - else - d->collator &= ~NORM_IGNORESYMBOLS; + dirty = false; } -bool QCollator::ignorePunctuation() const +void QCollatorPrivate::cleanup() { - return bool(d->collator & NORM_IGNORESYMBOLS); } + int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const { + if (d->dirty) + d->init(); + //* from Windows documentation * // Returns one of the following values if successful. To maintain the C runtime convention of // comparing strings, the value 2 can be subtracted from a nonzero return value. Then, the // meaning of <0, ==0, and >0 is consistent with the C runtime. -#ifndef Q_OS_WINRT - return CompareString(LOCALE_USER_DEFAULT, d->collator, +#ifndef USE_COMPARESTRINGEX + return CompareString(d->localeID, d->collator, reinterpret_cast<const wchar_t*>(s1), len1, reinterpret_cast<const wchar_t*>(s2), len2) - 2; -#else // !Q_OS_WINRT - return CompareStringEx(LOCALE_NAME_USER_DEFAULT, d->collator, +#else + return CompareStringEx(LPCWSTR(d->localeName.utf16()), d->collator, reinterpret_cast<LPCWSTR>(s1), len1, reinterpret_cast<LPCWSTR>(s2), len2, NULL, NULL, 0) - 2; -#endif // Q_OS_WINRT +#endif } int QCollator::compare(const QString &str1, const QString &str2) const @@ -148,32 +122,29 @@ int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const QCollatorSortKey QCollator::sortKey(const QString &string) const { -#ifndef Q_OS_WINRT - int size = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | d->collator, + if (d->dirty) + d->init(); + +#ifndef USE_COMPARESTRINGEX + int size = LCMapStringW(d->localeID, LCMAP_SORTKEY | d->collator, reinterpret_cast<const wchar_t*>(string.constData()), string.size(), 0, 0); -#elif defined(Q_OS_WINPHONE) - int size = 0; - Q_UNIMPLEMENTED(); - Q_UNUSED(string) -#else // Q_OS_WINPHONE - int size = LCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_SORTKEY | d->collator, +#else + int size = LCMapStringEx(LPCWSTR(d->localeName.utf16()), LCMAP_SORTKEY | d->collator, reinterpret_cast<LPCWSTR>(string.constData()), string.size(), 0, 0, NULL, NULL, 0); -#endif // !Q_OS_WINPHONE +#endif QString ret(size, Qt::Uninitialized); -#ifndef Q_OS_WINRT - int finalSize = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | d->collator, +#ifndef USE_COMPARESTRINGEX + int finalSize = LCMapStringW(d->localeID, LCMAP_SORTKEY | d->collator, reinterpret_cast<const wchar_t*>(string.constData()), string.size(), reinterpret_cast<wchar_t*>(ret.data()), ret.size()); -#elif defined(Q_OS_WINPHONE) - int finalSize = 0; -#else // Q_OS_WINPHONE - int finalSize = LCMapStringEx(LOCALE_NAME_USER_DEFAULT, LCMAP_SORTKEY | d->collator, +#else + int finalSize = LCMapStringEx(LPCWSTR(d->localeName.utf16()), LCMAP_SORTKEY | d->collator, reinterpret_cast<LPCWSTR>(string.constData()), string.size(), reinterpret_cast<LPWSTR>(ret.data()), ret.size(), NULL, NULL, 0); -#endif // !Q_OS_WINPHONE +#endif if (finalSize == 0) { qWarning() << "there were problems when generating the ::sortKey by LCMapStringW with error:" << GetLastError(); } |