From 6f67e46d1e3627e35fde47257a0b93c3d4218aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Mon, 10 Dec 2018 22:17:16 +0100 Subject: [PATCH 1/3] Use QCollator for sort library. --- src/util/db/dbconnection.cpp | 20 ++++++++------------ src/util/db/dbconnection.h | 2 ++ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/util/db/dbconnection.cpp b/src/util/db/dbconnection.cpp index 4a66fa9ff40..2a6240d056b 100644 --- a/src/util/db/dbconnection.cpp +++ b/src/util/db/dbconnection.cpp @@ -64,12 +64,6 @@ void removeDatabase( QSqlDatabase::removeDatabase(connectionName); } -// The default comparison of strings for sorting. -inline int compareLocaleAwareCaseInsensitive( - const QString& first, const QString& second) { - return QString::localeAwareCompare(first.toLower(), second.toLower()); -} - void makeLatinLow(QChar* c, int count) { for (int i = 0; i < count; ++i) { if (c[i].decompositionTag() != QChar::NoDecomposition) { @@ -181,13 +175,13 @@ int likeCompareInner( int sqliteStringCompareUTF16(void* pArg, int len1, const void* data1, int len2, const void* data2) { - Q_UNUSED(pArg); + QCollator* pCollator = reinterpret_cast(pArg); // Construct a QString without copy QString string1 = QString::fromRawData(reinterpret_cast(data1), len1 / sizeof(QChar)); QString string2 = QString::fromRawData(reinterpret_cast(data2), len2 / sizeof(QChar)); - return compareLocaleAwareCaseInsensitive(string1, string2); + return pCollator->compare(string1, string2); } const char* const kLexicographicalCollationFunc = "mixxxLexicographicalCollationFunc"; @@ -234,7 +228,7 @@ void sqliteLike(sqlite3_context *context, #endif // __SQLITE3__ -bool initDatabase(QSqlDatabase database) { +bool initDatabase(QSqlDatabase database, QCollator* pCollator) { DEBUG_ASSERT(database.isOpen()); #ifdef __SQLITE3__ QVariant v = database.driver()->handle(); @@ -260,7 +254,7 @@ bool initDatabase(QSqlDatabase database) { handle, kLexicographicalCollationFunc, SQLITE_UTF16, - nullptr, + pCollator, sqliteStringCompareUTF16); VERIFY_OR_DEBUG_ASSERT(result == SQLITE_OK) { kLogger.warning() @@ -304,7 +298,9 @@ bool initDatabase(QSqlDatabase database) { DbConnection::DbConnection( const Params& params, const QString& connectionName) - : m_sqlDatabase(createDatabase(params, connectionName)) { + : m_sqlDatabase(createDatabase(params, connectionName)), + m_collator() { + m_collator.setCaseSensitivity(Qt::CaseInsensitive); } DbConnection::DbConnection( @@ -331,7 +327,7 @@ bool DbConnection::open() { << m_sqlDatabase.lastError(); return false; // abort } - if (!initDatabase(m_sqlDatabase)) { + if (!initDatabase(m_sqlDatabase, &m_collator)) { kLogger.warning() << "Failed to initialize database connection" << *this; diff --git a/src/util/db/dbconnection.h b/src/util/db/dbconnection.h index 1b344ac8fff..bfac2c49ea0 100644 --- a/src/util/db/dbconnection.h +++ b/src/util/db/dbconnection.h @@ -3,6 +3,7 @@ #include +#include #include @@ -63,6 +64,7 @@ class DbConnection final { DbConnection(const DbConnection&&) = delete; QSqlDatabase m_sqlDatabase; + QCollator m_collator; }; } // namespace mixxx From c5c570bd4352f52ec2aeb72d1273327cd7e0449e Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Tue, 11 Dec 2018 20:21:29 +0100 Subject: [PATCH 2/3] Encapsulate locale-aware string comparison in reusable class --- src/util/db/dbconnection.cpp | 12 +++++------- src/util/db/dbconnection.h | 5 ++--- src/util/string.h | 25 +++++++++++++++++++++---- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/util/db/dbconnection.cpp b/src/util/db/dbconnection.cpp index 2a6240d056b..b74ab5982f6 100644 --- a/src/util/db/dbconnection.cpp +++ b/src/util/db/dbconnection.cpp @@ -175,11 +175,11 @@ int likeCompareInner( int sqliteStringCompareUTF16(void* pArg, int len1, const void* data1, int len2, const void* data2) { - QCollator* pCollator = reinterpret_cast(pArg); + StringCollator* pCollator = static_cast(pArg); // Construct a QString without copy - QString string1 = QString::fromRawData(reinterpret_cast(data1), + QString string1 = QString::fromRawData(static_cast(data1), len1 / sizeof(QChar)); - QString string2 = QString::fromRawData(reinterpret_cast(data2), + QString string2 = QString::fromRawData(static_cast(data2), len2 / sizeof(QChar)); return pCollator->compare(string1, string2); } @@ -228,7 +228,7 @@ void sqliteLike(sqlite3_context *context, #endif // __SQLITE3__ -bool initDatabase(QSqlDatabase database, QCollator* pCollator) { +bool initDatabase(QSqlDatabase database, StringCollator* pCollator) { DEBUG_ASSERT(database.isOpen()); #ifdef __SQLITE3__ QVariant v = database.driver()->handle(); @@ -298,9 +298,7 @@ bool initDatabase(QSqlDatabase database, QCollator* pCollator) { DbConnection::DbConnection( const Params& params, const QString& connectionName) - : m_sqlDatabase(createDatabase(params, connectionName)), - m_collator() { - m_collator.setCaseSensitivity(Qt::CaseInsensitive); + : m_sqlDatabase(createDatabase(params, connectionName)) { } DbConnection::DbConnection( diff --git a/src/util/db/dbconnection.h b/src/util/db/dbconnection.h index bfac2c49ea0..aef106bed54 100644 --- a/src/util/db/dbconnection.h +++ b/src/util/db/dbconnection.h @@ -3,10 +3,9 @@ #include -#include - #include +#include "util/string.h" namespace mixxx { @@ -64,7 +63,7 @@ class DbConnection final { DbConnection(const DbConnection&&) = delete; QSqlDatabase m_sqlDatabase; - QCollator m_collator; + StringCollator m_collator; }; } // namespace mixxx diff --git a/src/util/string.h b/src/util/string.h index 1e0dd686a1b..264b006c8b1 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -1,12 +1,29 @@ #ifndef MIXXX_STRING_H #define MIXXX_STRING_H +#include +#include #include +#include // The default comparison of strings for sorting. -inline int compareLocaleAwareCaseInsensitive( - const QString& first, const QString& second) { - return QString::localeAwareCompare(first.toLower(), second.toLower()); -} +class StringCollator { + public: + explicit StringCollator(QLocale locale = QLocale()) + : m_collator(std::move(locale)) { + m_collator.setCaseSensitivity(Qt::CaseInsensitive); + } + + int compare(const QString& s1, const QString& s2) const { + return m_collator.compare(s1, s2); + } + + int compare(const QStringRef& s1, const QStringRef& s2) const { + return m_collator.compare(s1, s2); + } + + private: + QCollator m_collator; +}; #endif // MIXXX_STRING_H From b06c12e608ce807cb15f0e150983860da38ad3a0 Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Tue, 11 Dec 2018 20:22:10 +0100 Subject: [PATCH 3/3] Reuse locale-aware string comparison in BaseTrackCache --- src/library/basetrackcache.cpp | 2 +- src/library/basetrackcache.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/library/basetrackcache.cpp b/src/library/basetrackcache.cpp index 1a54d75faf1..192b76b7da3 100644 --- a/src/library/basetrackcache.cpp +++ b/src/library/basetrackcache.cpp @@ -730,7 +730,7 @@ int BaseTrackCache::compareColumnValues(int sortColumn, Qt::SortOrder sortOrder, result = 0; } } else { - result = val1.toString().localeAwareCompare(val2.toString()); + result = m_collator.compare(val1.toString(), val2.toString()); } // If we're in descending order, flip the comparison. diff --git a/src/library/basetrackcache.h b/src/library/basetrackcache.h index 68bb6e92a49..a009618b285 100644 --- a/src/library/basetrackcache.h +++ b/src/library/basetrackcache.h @@ -18,6 +18,7 @@ #include "track/track.h" #include "util/class.h" #include "util/memory.h" +#include "util/string.h" class SearchQueryParser; class QueryNode; @@ -122,6 +123,8 @@ class BaseTrackCache : public QObject { const ColumnCache m_columnCache; + const StringCollator m_collator; + QStringList m_searchColumns; QVector m_searchColumnIndices;