Try to sort by "quality", ie. matches at the start of the song metadata rate higher.
This commit is contained in:
parent
415c86ab90
commit
dbe8ffd5de
@ -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;
|
||||
}
|
||||
|
||||
|
@ -31,38 +31,35 @@ bool GlobalSearchSortModel::lessThan(const QModelIndex& left, const QModelIndex&
|
||||
const SearchProvider::Result r2 = right.data(GlobalSearchWidget::Role_Result)
|
||||
.value<SearchProvider::Result>();
|
||||
|
||||
// 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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user