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);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user