From dbe8ffd5de81a180fd88d5a2c2c322883aa472c4 Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sun, 28 Aug 2011 23:24:54 +0100 Subject: [PATCH] Try to sort by "quality", ie. matches at the start of the song metadata rate higher. --- src/globalsearch/globalsearchitemdelegate.cpp | 11 ++++- src/globalsearch/globalsearchsortmodel.cpp | 49 +++++++++---------- src/globalsearch/librarysearchprovider.cpp | 10 +++- src/globalsearch/searchprovider.cpp | 14 ++++-- src/globalsearch/searchprovider.h | 14 +++++- 5 files changed, 65 insertions(+), 33 deletions(-) diff --git a/src/globalsearch/globalsearchitemdelegate.cpp b/src/globalsearch/globalsearchitemdelegate.cpp index 8b6ccce94..467d8093b 100644 --- a/src/globalsearch/globalsearchitemdelegate.cpp +++ b/src/globalsearch/globalsearchitemdelegate.cpp @@ -121,7 +121,7 @@ void GlobalSearchItemDelegate::paint(QPainter* p, p->setPen(pen); DrawAndShrink(p, &text_rect_1, m.title()); - // Line 2 is Artist - Album + // Line 2 is Artist - Album - Track n p->setFont(option.font); // Artist @@ -142,6 +142,15 @@ void GlobalSearchItemDelegate::paint(QPainter* p, DrawAndShrink(p, &text_rect_2, m.album()); } + if (m.track() > 0) { + // Dash + p->setPen(light_pen); + DrawAndShrink(p, &text_rect_2, " - "); + + // Album + DrawAndShrink(p, &text_rect_2, tr("track %1").arg(m.track())); + } + break; } diff --git a/src/globalsearch/globalsearchsortmodel.cpp b/src/globalsearch/globalsearchsortmodel.cpp index 92a549592..1be202f99 100644 --- a/src/globalsearch/globalsearchsortmodel.cpp +++ b/src/globalsearch/globalsearchsortmodel.cpp @@ -31,38 +31,35 @@ bool GlobalSearchSortModel::lessThan(const QModelIndex& left, const QModelIndex& const SearchProvider::Result r2 = right.data(GlobalSearchWidget::Role_Result) .value(); - // Compare types first - if (r1.type_ < r2.type_) return true; - if (r1.type_ > r2.type_) return false; - int ret = 0; + +#define CompareInt(field) \ + if (r1.field < r2.field) return true; \ + if (r1.field > r2.field) return false + +#define CompareString(field) \ + ret = QString::localeAwareCompare(r1.metadata_.field(), r2.metadata_.field()); \ + if (ret < 0) return true; \ + if (ret > 0) return false + + + // Compare match quality and types first + CompareInt(match_quality_); + CompareInt(type_); + + // Then compare title, artist and album switch (r1.type_) { case SearchProvider::Result::Type_Track: - ret = QString::localeAwareCompare(r1.metadata_.title(), r2.metadata_.title()); - if (ret < 0) return true; - if (ret > 0) return false; - - ret = QString::localeAwareCompare(r1.metadata_.artist(), r2.metadata_.artist()); - if (ret < 0) return true; - if (ret > 0) return false; - - ret = QString::localeAwareCompare(r1.metadata_.album(), r2.metadata_.album()); - if (ret < 0) return true; - if (ret > 0) return false; - - break; - + CompareString(title); + // fallthrough case SearchProvider::Result::Type_Album: - ret = QString::localeAwareCompare(r1.metadata_.artist(), r2.metadata_.artist()); - if (ret < 0) return true; - if (ret > 0) return false; - - ret = QString::localeAwareCompare(r1.metadata_.album(), r2.metadata_.album()); - if (ret < 0) return true; - if (ret > 0) return false; - + CompareString(artist); + CompareString(album); break; } return false; + +#undef CompareInt +#undef CompareString } diff --git a/src/globalsearch/librarysearchprovider.cpp b/src/globalsearch/librarysearchprovider.cpp index 5e5379a96..d12c6120e 100644 --- a/src/globalsearch/librarysearchprovider.cpp +++ b/src/globalsearch/librarysearchprovider.cpp @@ -70,12 +70,15 @@ SearchProvider::ResultList LibrarySearchProvider::Search(int id, const QString& album_key.prepend(song.artist()); } - if (TokenMatches(tokens, song.title())) { + Result::MatchQuality quality = MatchQuality(tokens, song.title()); + + if (quality != Result::Quality_None) { // If the query matched in the song title then we're interested in this // as an individual song. Result result(this); result.type_ = Result::Type_Track; result.metadata_ = song; + result.match_quality_ = quality; ret << result; } else { // Otherwise we record this as being an interesting album. @@ -92,6 +95,11 @@ SearchProvider::ResultList LibrarySearchProvider::Search(int id, const QString& result.type_ = Result::Type_Album; result.metadata_ = albums.value(key); result.album_size_ = albums.count(key); + result.match_quality_ = + qMin( + MatchQuality(tokens, result.metadata_.albumartist()), + qMin(MatchQuality(tokens, result.metadata_.artist()), + MatchQuality(tokens, result.metadata_.album()))); ret << result; } diff --git a/src/globalsearch/searchprovider.cpp b/src/globalsearch/searchprovider.cpp index 7e9414aab..4f9776b9e 100644 --- a/src/globalsearch/searchprovider.cpp +++ b/src/globalsearch/searchprovider.cpp @@ -48,13 +48,19 @@ QStringList SearchProvider::TokenizeQuery(const QString& query) { return tokens; } -int SearchProvider::TokenMatches(const QStringList& tokens, const QString& string) { - int ret = 0; +SearchProvider::Result::MatchQuality SearchProvider::MatchQuality( + const QStringList& tokens, const QString& string) { + Result::MatchQuality ret = Result::Quality_None; + foreach (const QString& token, tokens) { - if (string.contains(token, Qt::CaseInsensitive)) { - ret ++; + const int index = string.indexOf(token, 0, Qt::CaseInsensitive); + if (index == 0) { + return Result::Quality_AtStart; + } else if (index != -1) { + ret = Result::Quality_Middle; } } + return ret; } diff --git a/src/globalsearch/searchprovider.h b/src/globalsearch/searchprovider.h index 4adc8f232..48fa39603 100644 --- a/src/globalsearch/searchprovider.h +++ b/src/globalsearch/searchprovider.h @@ -42,12 +42,24 @@ public: Type_Album }; + enum MatchQuality { + // A token in the search string matched at the beginning of the song + // metadata. + Quality_AtStart = 0, + + // A token matched somewhere else. + Quality_Middle, + + Quality_None + }; + // This must be set by the provder using the constructor. SearchProvider* provider_; // These must be set explicitly by the provider. Type type_; Song metadata_; + MatchQuality match_quality_; // How many songs in the album - valid only if type == Type_Album. int album_size_; @@ -84,7 +96,7 @@ protected: // useful for figuring out whether you got a result because it matched in // the song title or the artist/album name. static QStringList TokenizeQuery(const QString& query); - static int TokenMatches(const QStringList& tokens, const QString& string); + static Result::MatchQuality MatchQuality(const QStringList& tokens, const QString& string); private: QString name_;