Try to sort by "quality", ie. matches at the start of the song metadata rate higher.

This commit is contained in:
David Sansome 2011-08-28 23:24:54 +01:00
parent 415c86ab90
commit dbe8ffd5de
5 changed files with 65 additions and 33 deletions

View File

@ -121,7 +121,7 @@ void GlobalSearchItemDelegate::paint(QPainter* p,
p->setPen(pen); p->setPen(pen);
DrawAndShrink(p, &text_rect_1, m.title()); DrawAndShrink(p, &text_rect_1, m.title());
// Line 2 is Artist - Album // Line 2 is Artist - Album - Track n
p->setFont(option.font); p->setFont(option.font);
// Artist // Artist
@ -142,6 +142,15 @@ void GlobalSearchItemDelegate::paint(QPainter* p,
DrawAndShrink(p, &text_rect_2, m.album()); 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; break;
} }

View File

@ -31,38 +31,35 @@ bool GlobalSearchSortModel::lessThan(const QModelIndex& left, const QModelIndex&
const SearchProvider::Result r2 = right.data(GlobalSearchWidget::Role_Result) const SearchProvider::Result r2 = right.data(GlobalSearchWidget::Role_Result)
.value<SearchProvider::Result>(); .value<SearchProvider::Result>();
// Compare types first
if (r1.type_ < r2.type_) return true;
if (r1.type_ > r2.type_) return false;
int ret = 0; 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_) { switch (r1.type_) {
case SearchProvider::Result::Type_Track: case SearchProvider::Result::Type_Track:
ret = QString::localeAwareCompare(r1.metadata_.title(), r2.metadata_.title()); CompareString(title);
if (ret < 0) return true; // fallthrough
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;
case SearchProvider::Result::Type_Album: case SearchProvider::Result::Type_Album:
ret = QString::localeAwareCompare(r1.metadata_.artist(), r2.metadata_.artist()); CompareString(artist);
if (ret < 0) return true; CompareString(album);
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; break;
} }
return false; return false;
#undef CompareInt
#undef CompareString
} }

View File

@ -70,12 +70,15 @@ SearchProvider::ResultList LibrarySearchProvider::Search(int id, const QString&
album_key.prepend(song.artist()); 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 // If the query matched in the song title then we're interested in this
// as an individual song. // as an individual song.
Result result(this); Result result(this);
result.type_ = Result::Type_Track; result.type_ = Result::Type_Track;
result.metadata_ = song; result.metadata_ = song;
result.match_quality_ = quality;
ret << result; ret << result;
} else { } else {
// Otherwise we record this as being an interesting album. // 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.type_ = Result::Type_Album;
result.metadata_ = albums.value(key); result.metadata_ = albums.value(key);
result.album_size_ = albums.count(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; ret << result;
} }

View File

@ -48,13 +48,19 @@ QStringList SearchProvider::TokenizeQuery(const QString& query) {
return tokens; return tokens;
} }
int SearchProvider::TokenMatches(const QStringList& tokens, const QString& string) { SearchProvider::Result::MatchQuality SearchProvider::MatchQuality(
int ret = 0; const QStringList& tokens, const QString& string) {
Result::MatchQuality ret = Result::Quality_None;
foreach (const QString& token, tokens) { foreach (const QString& token, tokens) {
if (string.contains(token, Qt::CaseInsensitive)) { const int index = string.indexOf(token, 0, Qt::CaseInsensitive);
ret ++; if (index == 0) {
return Result::Quality_AtStart;
} else if (index != -1) {
ret = Result::Quality_Middle;
} }
} }
return ret; return ret;
} }

View File

@ -42,12 +42,24 @@ public:
Type_Album 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. // This must be set by the provder using the constructor.
SearchProvider* provider_; SearchProvider* provider_;
// These must be set explicitly by the provider. // These must be set explicitly by the provider.
Type type_; Type type_;
Song metadata_; Song metadata_;
MatchQuality match_quality_;
// How many songs in the album - valid only if type == Type_Album. // How many songs in the album - valid only if type == Type_Album.
int album_size_; int album_size_;
@ -84,7 +96,7 @@ protected:
// useful for figuring out whether you got a result because it matched in // useful for figuring out whether you got a result because it matched in
// the song title or the artist/album name. // the song title or the artist/album name.
static QStringList TokenizeQuery(const QString& query); 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: private:
QString name_; QString name_;