Make CollectionQuery subclass QSqlQuery, don't copy QSqlQuery
This commit is contained in:
parent
0c4edc4d17
commit
5a58ac2845
|
@ -612,12 +612,14 @@ void CollectionBackend::MarkSongsUnavailable(const SongList &songs, const bool u
|
||||||
|
|
||||||
QStringList CollectionBackend::GetAll(const QString &column, const QueryOptions &opt) {
|
QStringList CollectionBackend::GetAll(const QString &column, const QueryOptions &opt) {
|
||||||
|
|
||||||
CollectionQuery query(opt);
|
QMutexLocker l(db_->Mutex());
|
||||||
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
|
CollectionQuery query(db, songs_table_, fts_table_, opt);
|
||||||
query.SetColumnSpec("DISTINCT " + column);
|
query.SetColumnSpec("DISTINCT " + column);
|
||||||
query.AddCompilationRequirement(false);
|
query.AddCompilationRequirement(false);
|
||||||
|
|
||||||
QMutexLocker l(db_->Mutex());
|
if (!query.Exec()) return QStringList();
|
||||||
if (!ExecQuery(&query)) return QStringList();
|
|
||||||
|
|
||||||
QStringList ret;
|
QStringList ret;
|
||||||
while (query.Next()) {
|
while (query.Next()) {
|
||||||
|
@ -634,25 +636,25 @@ QStringList CollectionBackend::GetAllArtists(const QueryOptions &opt) {
|
||||||
|
|
||||||
QStringList CollectionBackend::GetAllArtistsWithAlbums(const QueryOptions &opt) {
|
QStringList CollectionBackend::GetAllArtistsWithAlbums(const QueryOptions &opt) {
|
||||||
|
|
||||||
|
QMutexLocker l(db_->Mutex());
|
||||||
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
// Albums with 'albumartist' field set:
|
// Albums with 'albumartist' field set:
|
||||||
CollectionQuery query(opt);
|
CollectionQuery query(db, songs_table_, fts_table_, opt);
|
||||||
query.SetColumnSpec("DISTINCT albumartist");
|
query.SetColumnSpec("DISTINCT albumartist");
|
||||||
query.AddCompilationRequirement(false);
|
query.AddCompilationRequirement(false);
|
||||||
query.AddWhere("album", "", "!=");
|
query.AddWhere("album", "", "!=");
|
||||||
|
|
||||||
// Albums with no 'albumartist' (extract 'artist'):
|
// Albums with no 'albumartist' (extract 'artist'):
|
||||||
CollectionQuery query2(opt);
|
CollectionQuery query2(db, songs_table_, fts_table_, opt);
|
||||||
query2.SetColumnSpec("DISTINCT artist");
|
query2.SetColumnSpec("DISTINCT artist");
|
||||||
query2.AddCompilationRequirement(false);
|
query2.AddCompilationRequirement(false);
|
||||||
query2.AddWhere("album", "", "!=");
|
query2.AddWhere("album", "", "!=");
|
||||||
query2.AddWhere("albumartist", "", "=");
|
query2.AddWhere("albumartist", "", "=");
|
||||||
|
|
||||||
{
|
if (!query.Exec() || !query2.Exec()) {
|
||||||
QMutexLocker l(db_->Mutex());
|
|
||||||
if (!ExecQuery(&query) || !ExecQuery(&query2)) {
|
|
||||||
return QStringList();
|
return QStringList();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> artists;
|
QSet<QString> artists;
|
||||||
while (query.Next()) {
|
while (query.Next()) {
|
||||||
|
@ -677,28 +679,40 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbumsByArtist(const QString
|
||||||
|
|
||||||
SongList CollectionBackend::GetArtistSongs(const QString &effective_albumartist, const QueryOptions &opt) {
|
SongList CollectionBackend::GetArtistSongs(const QString &effective_albumartist, const QueryOptions &opt) {
|
||||||
|
|
||||||
CollectionQuery query(opt);
|
QSqlDatabase db(db_->Connect());
|
||||||
|
QMutexLocker l(db_->Mutex());
|
||||||
|
|
||||||
|
CollectionQuery query(db, songs_table_, fts_table_, opt);
|
||||||
query.AddCompilationRequirement(false);
|
query.AddCompilationRequirement(false);
|
||||||
query.AddWhere("effective_albumartist", effective_albumartist);
|
query.AddWhere("effective_albumartist", effective_albumartist);
|
||||||
|
|
||||||
return ExecCollectionQuery(&query);
|
return ExecCollectionQuery(&query);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SongList CollectionBackend::GetAlbumSongs(const QString &effective_albumartist, const QString &album, const QueryOptions &opt) {
|
SongList CollectionBackend::GetAlbumSongs(const QString &effective_albumartist, const QString &album, const QueryOptions &opt) {
|
||||||
|
|
||||||
CollectionQuery query(opt);
|
QSqlDatabase db(db_->Connect());
|
||||||
|
QMutexLocker l(db_->Mutex());
|
||||||
|
|
||||||
|
CollectionQuery query(db, songs_table_, fts_table_, opt);
|
||||||
query.AddCompilationRequirement(false);
|
query.AddCompilationRequirement(false);
|
||||||
query.AddWhere("effective_albumartist", effective_albumartist);
|
query.AddWhere("effective_albumartist", effective_albumartist);
|
||||||
query.AddWhere("album", album);
|
query.AddWhere("album", album);
|
||||||
|
|
||||||
return ExecCollectionQuery(&query);
|
return ExecCollectionQuery(&query);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SongList CollectionBackend::GetSongsByAlbum(const QString &album, const QueryOptions &opt) {
|
SongList CollectionBackend::GetSongsByAlbum(const QString &album, const QueryOptions &opt) {
|
||||||
|
|
||||||
CollectionQuery query(opt);
|
QSqlDatabase db(db_->Connect());
|
||||||
|
QMutexLocker l(db_->Mutex());
|
||||||
|
|
||||||
|
CollectionQuery query(db, songs_table_, fts_table_, opt);
|
||||||
query.AddCompilationRequirement(false);
|
query.AddCompilationRequirement(false);
|
||||||
query.AddWhere("album", album);
|
query.AddWhere("album", album);
|
||||||
|
|
||||||
return ExecCollectionQuery(&query);
|
return ExecCollectionQuery(&query);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -706,8 +720,8 @@ SongList CollectionBackend::GetSongsByAlbum(const QString &album, const QueryOpt
|
||||||
SongList CollectionBackend::ExecCollectionQuery(CollectionQuery *query) {
|
SongList CollectionBackend::ExecCollectionQuery(CollectionQuery *query) {
|
||||||
|
|
||||||
query->SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
query->SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
||||||
QMutexLocker l(db_->Mutex());
|
|
||||||
if (!ExecQuery(query)) return SongList();
|
if (!query->Exec()) return SongList();
|
||||||
|
|
||||||
SongList ret;
|
SongList ret;
|
||||||
while (query->Next()) {
|
while (query->Next()) {
|
||||||
|
@ -720,12 +734,15 @@ SongList CollectionBackend::ExecCollectionQuery(CollectionQuery *query) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Song CollectionBackend::GetSongById(const int id) {
|
Song CollectionBackend::GetSongById(const int id) {
|
||||||
|
|
||||||
QMutexLocker l(db_->Mutex());
|
QMutexLocker l(db_->Mutex());
|
||||||
QSqlDatabase db(db_->Connect());
|
QSqlDatabase db(db_->Connect());
|
||||||
return GetSongById(id, db);
|
return GetSongById(id, db);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SongList CollectionBackend::GetSongsById(const QList<int> &ids) {
|
SongList CollectionBackend::GetSongsById(const QList<int> &ids) {
|
||||||
|
|
||||||
QMutexLocker l(db_->Mutex());
|
QMutexLocker l(db_->Mutex());
|
||||||
QSqlDatabase db(db_->Connect());
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
|
@ -735,13 +752,16 @@ SongList CollectionBackend::GetSongsById(const QList<int> &ids) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetSongsById(str_ids, db);
|
return GetSongsById(str_ids, db);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SongList CollectionBackend::GetSongsById(const QStringList &ids) {
|
SongList CollectionBackend::GetSongsById(const QStringList &ids) {
|
||||||
|
|
||||||
QMutexLocker l(db_->Mutex());
|
QMutexLocker l(db_->Mutex());
|
||||||
QSqlDatabase db(db_->Connect());
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
return GetSongsById(ids, db);
|
return GetSongsById(ids, db);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SongList CollectionBackend::GetSongsByForeignId(const QStringList &ids, const QString &table, const QString &column) {
|
SongList CollectionBackend::GetSongsByForeignId(const QStringList &ids, const QString &table, const QString &column) {
|
||||||
|
@ -769,9 +789,11 @@ SongList CollectionBackend::GetSongsByForeignId(const QStringList &ids, const QS
|
||||||
}
|
}
|
||||||
|
|
||||||
Song CollectionBackend::GetSongById(const int id, QSqlDatabase &db) {
|
Song CollectionBackend::GetSongById(const int id, QSqlDatabase &db) {
|
||||||
|
|
||||||
SongList list = GetSongsById(QStringList() << QString::number(id), db);
|
SongList list = GetSongsById(QStringList() << QString::number(id), db);
|
||||||
if (list.isEmpty()) return Song();
|
if (list.isEmpty()) return Song();
|
||||||
return list.first();
|
return list.first();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SongList CollectionBackend::GetSongsById(const QStringList &ids, QSqlDatabase &db) {
|
SongList CollectionBackend::GetSongsById(const QStringList &ids, QSqlDatabase &db) {
|
||||||
|
@ -897,13 +919,15 @@ CollectionBackend::AlbumList CollectionBackend::GetCompilationAlbums(const Query
|
||||||
|
|
||||||
SongList CollectionBackend::GetCompilationSongs(const QString &album, const QueryOptions &opt) {
|
SongList CollectionBackend::GetCompilationSongs(const QString &album, const QueryOptions &opt) {
|
||||||
|
|
||||||
CollectionQuery query(opt);
|
QMutexLocker l(db_->Mutex());
|
||||||
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
|
CollectionQuery query(db, songs_table_, fts_table_, opt);
|
||||||
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
||||||
query.AddCompilationRequirement(true);
|
query.AddCompilationRequirement(true);
|
||||||
query.AddWhere("album", album);
|
query.AddWhere("album", album);
|
||||||
|
|
||||||
QMutexLocker l(db_->Mutex());
|
if (!query.Exec()) return SongList();
|
||||||
if (!ExecQuery(&query)) return SongList();
|
|
||||||
|
|
||||||
SongList ret;
|
SongList ret;
|
||||||
while (query.Next()) {
|
while (query.Next()) {
|
||||||
|
@ -1022,7 +1046,10 @@ void CollectionBackend::UpdateCompilations(QSqlQuery &find_song, QSqlQuery &upda
|
||||||
|
|
||||||
CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist, const bool compilation_required, const QueryOptions &opt) {
|
CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist, const bool compilation_required, const QueryOptions &opt) {
|
||||||
|
|
||||||
CollectionQuery query(opt);
|
QMutexLocker l(db_->Mutex());
|
||||||
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
|
CollectionQuery query(db, songs_table_, fts_table_, opt);
|
||||||
query.SetColumnSpec("url, effective_albumartist, album, compilation_effective, art_automatic, art_manual, filetype, cue_path");
|
query.SetColumnSpec("url, effective_albumartist, album, compilation_effective, art_automatic, art_manual, filetype, cue_path");
|
||||||
query.SetOrderBy("effective_albumartist, album, url");
|
query.SetOrderBy("effective_albumartist, album, url");
|
||||||
|
|
||||||
|
@ -1034,10 +1061,7 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist,
|
||||||
query.AddWhere("effective_albumartist", artist);
|
query.AddWhere("effective_albumartist", artist);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (!query.Exec()) return AlbumList();
|
||||||
QMutexLocker l(db_->Mutex());
|
|
||||||
if (!ExecQuery(&query)) return AlbumList();
|
|
||||||
}
|
|
||||||
|
|
||||||
QMap<QString, Album> albums;
|
QMap<QString, Album> albums;
|
||||||
while (query.Next()) {
|
while (query.Next()) {
|
||||||
|
@ -1100,19 +1124,21 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist,
|
||||||
|
|
||||||
CollectionBackend::Album CollectionBackend::GetAlbumArt(const QString &effective_albumartist, const QString &album) {
|
CollectionBackend::Album CollectionBackend::GetAlbumArt(const QString &effective_albumartist, const QString &album) {
|
||||||
|
|
||||||
|
QMutexLocker l(db_->Mutex());
|
||||||
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
Album ret;
|
Album ret;
|
||||||
ret.album = album;
|
ret.album = album;
|
||||||
ret.album_artist = effective_albumartist;
|
ret.album_artist = effective_albumartist;
|
||||||
|
|
||||||
CollectionQuery query = CollectionQuery(QueryOptions());
|
CollectionQuery query(db, songs_table_, fts_table_, QueryOptions());
|
||||||
query.SetColumnSpec("art_automatic, art_manual, url");
|
query.SetColumnSpec("art_automatic, art_manual, url");
|
||||||
if (!effective_albumartist.isEmpty()) {
|
if (!effective_albumartist.isEmpty()) {
|
||||||
query.AddWhere("effective_albumartist", effective_albumartist);
|
query.AddWhere("effective_albumartist", effective_albumartist);
|
||||||
}
|
}
|
||||||
query.AddWhere("album", album);
|
query.AddWhere("album", album);
|
||||||
|
|
||||||
QMutexLocker l(db_->Mutex());
|
if (!query.Exec()) return ret;
|
||||||
if (!ExecQuery(&query)) return ret;
|
|
||||||
|
|
||||||
if (query.Next()) {
|
if (query.Next()) {
|
||||||
ret.art_automatic = QUrl::fromEncoded(query.Value(0).toByteArray());
|
ret.art_automatic = QUrl::fromEncoded(query.Value(0).toByteArray());
|
||||||
|
@ -1136,12 +1162,12 @@ void CollectionBackend::UpdateManualAlbumArt(const QString &effective_albumartis
|
||||||
QSqlDatabase db(db_->Connect());
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
// Get the songs before they're updated
|
// Get the songs before they're updated
|
||||||
CollectionQuery query;
|
CollectionQuery query(db, songs_table_, fts_table_);
|
||||||
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
||||||
query.AddWhere("effective_albumartist", effective_albumartist);
|
query.AddWhere("effective_albumartist", effective_albumartist);
|
||||||
query.AddWhere("album", album);
|
query.AddWhere("album", album);
|
||||||
|
|
||||||
if (!ExecQuery(&query)) return;
|
if (!query.Exec()) return;
|
||||||
|
|
||||||
SongList deleted_songs;
|
SongList deleted_songs;
|
||||||
while (query.Next()) {
|
while (query.Next()) {
|
||||||
|
@ -1167,7 +1193,7 @@ void CollectionBackend::UpdateManualAlbumArt(const QString &effective_albumartis
|
||||||
db_->CheckErrors(q);
|
db_->CheckErrors(q);
|
||||||
|
|
||||||
// Now get the updated songs
|
// Now get the updated songs
|
||||||
if (!ExecQuery(&query)) return;
|
if (!query.Exec()) return;
|
||||||
|
|
||||||
SongList added_songs;
|
SongList added_songs;
|
||||||
while (query.Next()) {
|
while (query.Next()) {
|
||||||
|
@ -1195,12 +1221,12 @@ void CollectionBackend::UpdateAutomaticAlbumArt(const QString &effective_albumar
|
||||||
QSqlDatabase db(db_->Connect());
|
QSqlDatabase db(db_->Connect());
|
||||||
|
|
||||||
// Get the songs before they're updated
|
// Get the songs before they're updated
|
||||||
CollectionQuery query;
|
CollectionQuery query(db, songs_table_, fts_table_);
|
||||||
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
||||||
query.AddWhere("effective_albumartist", effective_albumartist);
|
query.AddWhere("effective_albumartist", effective_albumartist);
|
||||||
query.AddWhere("album", album);
|
query.AddWhere("album", album);
|
||||||
|
|
||||||
if (!ExecQuery(&query)) return;
|
if (!query.Exec()) return;
|
||||||
|
|
||||||
SongList deleted_songs;
|
SongList deleted_songs;
|
||||||
while (query.Next()) {
|
while (query.Next()) {
|
||||||
|
@ -1222,7 +1248,7 @@ void CollectionBackend::UpdateAutomaticAlbumArt(const QString &effective_albumar
|
||||||
db_->CheckErrors(q);
|
db_->CheckErrors(q);
|
||||||
|
|
||||||
// Now get the updated songs
|
// Now get the updated songs
|
||||||
if (!ExecQuery(&query)) return;
|
if (!query.Exec()) return;
|
||||||
|
|
||||||
SongList added_songs;
|
SongList added_songs;
|
||||||
while (query.Next()) {
|
while (query.Next()) {
|
||||||
|
@ -1246,12 +1272,12 @@ void CollectionBackend::ForceCompilation(const QString &album, const QList<QStri
|
||||||
|
|
||||||
for (const QString &artist : artists) {
|
for (const QString &artist : artists) {
|
||||||
// Get the songs before they're updated
|
// Get the songs before they're updated
|
||||||
CollectionQuery query;
|
CollectionQuery query(db, songs_table_, fts_table_);
|
||||||
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
||||||
query.AddWhere("album", album);
|
query.AddWhere("album", album);
|
||||||
if (!artist.isEmpty()) query.AddWhere("artist", artist);
|
if (!artist.isEmpty()) query.AddWhere("artist", artist);
|
||||||
|
|
||||||
if (!ExecQuery(&query)) return;
|
if (!query.Exec()) return;
|
||||||
|
|
||||||
while (query.Next()) {
|
while (query.Next()) {
|
||||||
Song song(source_);
|
Song song(source_);
|
||||||
|
@ -1274,7 +1300,7 @@ void CollectionBackend::ForceCompilation(const QString &album, const QList<QStri
|
||||||
db_->CheckErrors(q);
|
db_->CheckErrors(q);
|
||||||
|
|
||||||
// Now get the updated songs
|
// Now get the updated songs
|
||||||
if (!ExecQuery(&query)) return;
|
if (!query.Exec()) return;
|
||||||
|
|
||||||
while (query.Next()) {
|
while (query.Next()) {
|
||||||
Song song(source_);
|
Song song(source_);
|
||||||
|
@ -1290,10 +1316,6 @@ void CollectionBackend::ForceCompilation(const QString &album, const QList<QStri
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CollectionBackend::ExecQuery(CollectionQuery *q) {
|
|
||||||
return !db_->CheckErrors(q->Exec(db_->Connect(), songs_table_, fts_table_));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CollectionBackend::IncrementPlayCount(const int id) {
|
void CollectionBackend::IncrementPlayCount(const int id) {
|
||||||
|
|
||||||
if (id == -1) return;
|
if (id == -1) return;
|
||||||
|
|
|
@ -71,6 +71,9 @@ class CollectionBackendInterface : public QObject {
|
||||||
typedef QList<Album> AlbumList;
|
typedef QList<Album> AlbumList;
|
||||||
|
|
||||||
virtual QString songs_table() const = 0;
|
virtual QString songs_table() const = 0;
|
||||||
|
virtual QString fts_table() const = 0;
|
||||||
|
|
||||||
|
virtual Database *db() const = 0;
|
||||||
|
|
||||||
// Get a list of directories in the collection. Emits DirectoriesDiscovered.
|
// Get a list of directories in the collection. Emits DirectoriesDiscovered.
|
||||||
virtual void LoadDirectoriesAsync() = 0;
|
virtual void LoadDirectoriesAsync() = 0;
|
||||||
|
@ -111,8 +114,6 @@ class CollectionBackendInterface : public QObject {
|
||||||
|
|
||||||
virtual void AddDirectory(const QString &path) = 0;
|
virtual void AddDirectory(const QString &path) = 0;
|
||||||
virtual void RemoveDirectory(const Directory &dir) = 0;
|
virtual void RemoveDirectory(const Directory &dir) = 0;
|
||||||
|
|
||||||
virtual bool ExecQuery(CollectionQuery *q) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CollectionBackend : public CollectionBackendInterface {
|
class CollectionBackend : public CollectionBackendInterface {
|
||||||
|
@ -127,9 +128,10 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||||
|
|
||||||
void ExitAsync();
|
void ExitAsync();
|
||||||
|
|
||||||
Database *db() const { return db_; }
|
Database *db() const override { return db_; }
|
||||||
|
|
||||||
QString songs_table() const override { return songs_table_; }
|
QString songs_table() const override { return songs_table_; }
|
||||||
|
QString fts_table() const override { return fts_table_; }
|
||||||
QString dirs_table() const { return dirs_table_; }
|
QString dirs_table() const { return dirs_table_; }
|
||||||
QString subdirs_table() const { return subdirs_table_; }
|
QString subdirs_table() const { return subdirs_table_; }
|
||||||
|
|
||||||
|
@ -174,7 +176,6 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||||
void AddDirectory(const QString &path) override;
|
void AddDirectory(const QString &path) override;
|
||||||
void RemoveDirectory(const Directory &dir) override;
|
void RemoveDirectory(const Directory &dir) override;
|
||||||
|
|
||||||
bool ExecQuery(CollectionQuery *q) override;
|
|
||||||
SongList ExecCollectionQuery(CollectionQuery *query);
|
SongList ExecCollectionQuery(CollectionQuery *query);
|
||||||
|
|
||||||
void IncrementPlayCountAsync(const int id);
|
void IncrementPlayCountAsync(const int id);
|
||||||
|
|
|
@ -815,14 +815,20 @@ QVariant CollectionModel::data(const CollectionItem *item, const int role) const
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CollectionModel::HasCompilations(const CollectionQuery &query) {
|
bool CollectionModel::HasCompilations(const QSqlDatabase &db, const CollectionQuery &query) {
|
||||||
|
|
||||||
CollectionQuery q = query;
|
CollectionQuery q(db, backend_->songs_table(), backend_->fts_table(), query_options_);
|
||||||
|
|
||||||
|
q.SetColumnSpec(query.column_spec());
|
||||||
|
q.SetOrderBy(query.order_by());
|
||||||
|
q.SetWhereClauses(query.where_clauses());
|
||||||
|
q.SetBoundValues(query.bound_values());
|
||||||
|
q.SetIncludeUnavailable(query.include_unavailable());
|
||||||
|
q.SetDuplicatesOnly(query.duplicates_only());
|
||||||
q.AddCompilationRequirement(true);
|
q.AddCompilationRequirement(true);
|
||||||
q.SetLimit(1);
|
q.SetLimit(1);
|
||||||
|
|
||||||
QMutexLocker l(backend_->db()->Mutex());
|
if (!q.Exec()) return false;
|
||||||
if (!backend_->ExecQuery(&q)) return false;
|
|
||||||
|
|
||||||
return q.Next();
|
return q.Next();
|
||||||
|
|
||||||
|
@ -837,7 +843,12 @@ CollectionModel::QueryResult CollectionModel::RunQuery(CollectionItem *parent) {
|
||||||
GroupBy child_type = child_level >= 3 ? GroupBy_None : group_by_[child_level];
|
GroupBy child_type = child_level >= 3 ? GroupBy_None : group_by_[child_level];
|
||||||
|
|
||||||
// Initialize the query. child_type says what type of thing we want (artists, songs, etc.)
|
// Initialize the query. child_type says what type of thing we want (artists, songs, etc.)
|
||||||
CollectionQuery q(query_options_);
|
|
||||||
|
{
|
||||||
|
QMutexLocker l(backend_->db()->Mutex());
|
||||||
|
QSqlDatabase db(backend_->db()->Connect());
|
||||||
|
|
||||||
|
CollectionQuery q(db, backend_->songs_table(), backend_->fts_table(), query_options_);
|
||||||
InitQuery(child_type, &q);
|
InitQuery(child_type, &q);
|
||||||
|
|
||||||
// Walk up through the item's parents adding filters as necessary
|
// Walk up through the item's parents adding filters as necessary
|
||||||
|
@ -850,7 +861,7 @@ CollectionModel::QueryResult CollectionModel::RunQuery(CollectionItem *parent) {
|
||||||
// Artists GroupBy is special - we don't want compilation albums appearing
|
// Artists GroupBy is special - we don't want compilation albums appearing
|
||||||
if (IsArtistGroupBy(child_type)) {
|
if (IsArtistGroupBy(child_type)) {
|
||||||
// Add the special Various artists node
|
// Add the special Various artists node
|
||||||
if (show_various_artists_ && HasCompilations(q)) {
|
if (show_various_artists_ && HasCompilations(db, q)) {
|
||||||
result.create_va = true;
|
result.create_va = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -859,13 +870,14 @@ CollectionModel::QueryResult CollectionModel::RunQuery(CollectionItem *parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the query
|
// Execute the query
|
||||||
QMutexLocker l(backend_->db()->Mutex());
|
if (q.Exec()) {
|
||||||
if (backend_->ExecQuery(&q)) {
|
|
||||||
while (q.Next()) {
|
while (q.Next()) {
|
||||||
result.rows << SqlRow(q);
|
result.rows << SqlRow(q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (QThread::currentThread() != thread() && QThread::currentThread() != backend_->thread()) {
|
if (QThread::currentThread() != thread() && QThread::currentThread() != backend_->thread()) {
|
||||||
backend_->Close();
|
backend_->Close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,7 +239,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
||||||
QueryResult RunQuery(CollectionItem *parent);
|
QueryResult RunQuery(CollectionItem *parent);
|
||||||
void PostQuery(CollectionItem *parent, const QueryResult &result, const bool signal);
|
void PostQuery(CollectionItem *parent, const QueryResult &result, const bool signal);
|
||||||
|
|
||||||
bool HasCompilations(const CollectionQuery &query);
|
bool HasCompilations(const QSqlDatabase &db, const CollectionQuery &query);
|
||||||
|
|
||||||
void BeginReset();
|
void BeginReset();
|
||||||
|
|
||||||
|
|
|
@ -31,14 +31,23 @@
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QSqlDatabase>
|
#include <QSqlDatabase>
|
||||||
#include <QSqlQuery>
|
#include <QSqlQuery>
|
||||||
|
#include <QSqlError>
|
||||||
|
|
||||||
|
#include "core/logging.h"
|
||||||
|
#include "core/song.h"
|
||||||
|
|
||||||
#include "collectionquery.h"
|
#include "collectionquery.h"
|
||||||
#include "core/song.h"
|
|
||||||
|
|
||||||
QueryOptions::QueryOptions() : max_age_(-1), query_mode_(QueryMode_All) {}
|
QueryOptions::QueryOptions() : max_age_(-1), query_mode_(QueryMode_All) {}
|
||||||
|
|
||||||
CollectionQuery::CollectionQuery(const QueryOptions &options)
|
CollectionQuery::CollectionQuery(const QSqlDatabase &db, const QString &songs_table, const QString &fts_table, const QueryOptions &options) :
|
||||||
: include_unavailable_(false), join_with_fts_(false), limit_(-1) {
|
QSqlQuery(db),
|
||||||
|
songs_table_(songs_table),
|
||||||
|
fts_table_(fts_table),
|
||||||
|
include_unavailable_(false),
|
||||||
|
join_with_fts_(false),
|
||||||
|
duplicates_only_(false),
|
||||||
|
limit_(-1) {
|
||||||
|
|
||||||
if (!options.filter().isEmpty()) {
|
if (!options.filter().isEmpty()) {
|
||||||
// We need to munge the filter text a little bit to get it to work as expected with sqlite's FTS5:
|
// We need to munge the filter text a little bit to get it to work as expected with sqlite's FTS5:
|
||||||
|
@ -98,7 +107,7 @@ CollectionQuery::CollectionQuery(const QueryOptions &options)
|
||||||
bound_values_ << cutoff;
|
bound_values_ << cutoff;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Currently you cannot use any QueryMode other than All and fts at the same time.
|
// TODO: Currently you cannot use any QueryMode other than All and FTS at the same time.
|
||||||
// Joining songs, duplicated_songs and songs_fts all together takes a huge amount of time.
|
// Joining songs, duplicated_songs and songs_fts all together takes a huge amount of time.
|
||||||
// The query takes about 20 seconds on my machine then. Why?
|
// The query takes about 20 seconds on my machine then. Why?
|
||||||
// Untagged mode could work with additional filtering but I'm disabling it just to be consistent
|
// Untagged mode could work with additional filtering but I'm disabling it just to be consistent
|
||||||
|
@ -123,7 +132,7 @@ QString CollectionQuery::GetInnerQuery() {
|
||||||
|
|
||||||
void CollectionQuery::AddWhere(const QString &column, const QVariant &value, const QString &op) {
|
void CollectionQuery::AddWhere(const QString &column, const QVariant &value, const QString &op) {
|
||||||
|
|
||||||
// ignore 'literal' for IN
|
// Ignore 'literal' for IN
|
||||||
if (!op.compare("IN", Qt::CaseInsensitive)) {
|
if (!op.compare("IN", Qt::CaseInsensitive)) {
|
||||||
QStringList final;
|
QStringList final;
|
||||||
for (const QString &single_value : value.toStringList()) {
|
for (const QString &single_value : value.toStringList()) {
|
||||||
|
@ -168,7 +177,7 @@ void CollectionQuery::AddWhereArtist(const QVariant &value) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionQuery::AddCompilationRequirement(bool compilation) {
|
void CollectionQuery::AddCompilationRequirement(const bool compilation) {
|
||||||
// The unary + is added to prevent sqlite from using the index idx_comp_artist.
|
// The unary + is added to prevent sqlite from using the index idx_comp_artist.
|
||||||
// When joining with fts, sqlite 3.8 has a tendency to use this index and thereby nesting the tables in an order which gives very poor performance
|
// When joining with fts, sqlite 3.8 has a tendency to use this index and thereby nesting the tables in an order which gives very poor performance
|
||||||
|
|
||||||
|
@ -176,15 +185,15 @@ void CollectionQuery::AddCompilationRequirement(bool compilation) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSqlQuery CollectionQuery::Exec(QSqlDatabase db, const QString &songs_table, const QString &fts_table) {
|
bool CollectionQuery::Exec() {
|
||||||
|
|
||||||
QString sql;
|
QString sql;
|
||||||
|
|
||||||
if (join_with_fts_) {
|
if (join_with_fts_) {
|
||||||
sql = QString("SELECT %1 FROM %2 INNER JOIN %3 AS fts ON %2.ROWID = fts.ROWID").arg(column_spec_, songs_table, fts_table);
|
sql = QString("SELECT %1 FROM %2 INNER JOIN %3 AS fts ON %2.ROWID = fts.ROWID").arg(column_spec_, songs_table_, fts_table_);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sql = QString("SELECT %1 FROM %2 %3").arg(column_spec_, songs_table, GetInnerQuery());
|
sql = QString("SELECT %1 FROM %2 %3").arg(column_spec_, songs_table_, GetInnerQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList where_clauses(where_clauses_);
|
QStringList where_clauses(where_clauses_);
|
||||||
|
@ -198,31 +207,40 @@ QSqlQuery CollectionQuery::Exec(QSqlDatabase db, const QString &songs_table, con
|
||||||
|
|
||||||
if (limit_ != -1) sql += " LIMIT " + QString::number(limit_);
|
if (limit_ != -1) sql += " LIMIT " + QString::number(limit_);
|
||||||
|
|
||||||
sql.replace("%songs_table", songs_table);
|
sql.replace("%songs_table", songs_table_);
|
||||||
sql.replace("%fts_table_noprefix", fts_table.section('.', -1, -1));
|
sql.replace("%fts_table_noprefix", fts_table_.section('.', -1, -1));
|
||||||
sql.replace("%fts_table", fts_table);
|
sql.replace("%fts_table", fts_table_);
|
||||||
|
|
||||||
query_ = QSqlQuery(db);
|
prepare(sql);
|
||||||
query_.prepare(sql);
|
|
||||||
|
|
||||||
// Bind values
|
// Bind values
|
||||||
for (const QVariant &value : bound_values_) {
|
for (const QVariant &value : bound_values_) {
|
||||||
query_.addBindValue(value);
|
addBindValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
query_.exec();
|
const bool result = exec();
|
||||||
return query_;
|
|
||||||
|
if (!result) {
|
||||||
|
QSqlError last_error = lastError();
|
||||||
|
if (last_error.isValid()) {
|
||||||
|
qLog(Error) << "DB error: " << last_error;
|
||||||
|
qLog(Error) << "Faulty query: " << lastQuery();
|
||||||
|
qLog(Error) << "Bound values: " << boundValues();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CollectionQuery::Next() { return query_.next(); }
|
bool CollectionQuery::Next() { return next(); }
|
||||||
|
|
||||||
QVariant CollectionQuery::Value(int column) const { return query_.value(column); }
|
QVariant CollectionQuery::Value(const int column) const { return value(column); }
|
||||||
|
|
||||||
bool QueryOptions::Matches(const Song &song) const {
|
bool QueryOptions::Matches(const Song &song) const {
|
||||||
|
|
||||||
if (max_age_ != -1) {
|
if (max_age_ != -1) {
|
||||||
const uint cutoff = QDateTime::currentDateTime().toSecsSinceEpoch() - max_age_;
|
const qint64 cutoff = QDateTime::currentDateTime().toSecsSinceEpoch() - max_age_;
|
||||||
if (song.ctime() <= cutoff) return false;
|
if (song.ctime() <= cutoff) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct QueryOptions {
|
||||||
// - use the all songs table
|
// - use the all songs table
|
||||||
// - use the duplicated songs view; by duplicated we mean those songs for which the (artist, album, title) tuple is found more than once in the songs table
|
// - use the duplicated songs view; by duplicated we mean those songs for which the (artist, album, title) tuple is found more than once in the songs table
|
||||||
// - use the untagged songs view; by untagged we mean those for which at least one of the (artist, album, title) tags is empty
|
// - use the untagged songs view; by untagged we mean those for which at least one of the (artist, album, title) tags is empty
|
||||||
// Please note that additional filtering based on fts table (the filter attribute) won't work in Duplicates and Untagged modes.
|
// Please note that additional filtering based on FTS table (the filter attribute) won't work in Duplicates and Untagged modes.
|
||||||
enum QueryMode {
|
enum QueryMode {
|
||||||
QueryMode_All,
|
QueryMode_All,
|
||||||
QueryMode_Duplicates,
|
QueryMode_Duplicates,
|
||||||
|
@ -71,12 +71,13 @@ struct QueryOptions {
|
||||||
QueryMode query_mode_;
|
QueryMode query_mode_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CollectionQuery {
|
class CollectionQuery : public QSqlQuery {
|
||||||
public:
|
public:
|
||||||
explicit CollectionQuery(const QueryOptions &options = QueryOptions());
|
explicit CollectionQuery(const QSqlDatabase &db, const QString &songs_table, const QString &fts_table, const QueryOptions &options = QueryOptions());
|
||||||
|
|
||||||
// Sets contents of SELECT clause on the query (list of columns to get).
|
// Sets contents of SELECT clause on the query (list of columns to get).
|
||||||
void SetColumnSpec(const QString &spec) { column_spec_ = spec; }
|
void SetColumnSpec(const QString &spec) { column_spec_ = spec; }
|
||||||
|
|
||||||
// Sets an ORDER BY clause on the query.
|
// Sets an ORDER BY clause on the query.
|
||||||
void SetOrderBy(const QString &order_by) { order_by_ = order_by; }
|
void SetOrderBy(const QString &order_by) { order_by_ = order_by; }
|
||||||
|
|
||||||
|
@ -85,29 +86,42 @@ class CollectionQuery {
|
||||||
void AddWhere(const QString &column, const QVariant &value, const QString &op = "=");
|
void AddWhere(const QString &column, const QVariant &value, const QString &op = "=");
|
||||||
void AddWhereArtist(const QVariant &value);
|
void AddWhereArtist(const QVariant &value);
|
||||||
|
|
||||||
void AddCompilationRequirement(bool compilation);
|
void SetWhereClauses(const QStringList &where_clauses) { where_clauses_ = where_clauses; }
|
||||||
void SetLimit(int limit) { limit_ = limit; }
|
void SetBoundValues(const QVariantList &bound_values) { bound_values_ = bound_values; }
|
||||||
void SetIncludeUnavailable(bool include_unavailable) { include_unavailable_ = include_unavailable; }
|
void SetDuplicatesOnly(const bool duplicates_only) { duplicates_only_ = duplicates_only; }
|
||||||
|
void SetIncludeUnavailable(const bool include_unavailable) { include_unavailable_ = include_unavailable; }
|
||||||
|
void SetLimit(const int limit) { limit_ = limit; }
|
||||||
|
void AddCompilationRequirement(const bool compilation);
|
||||||
|
|
||||||
QSqlQuery Exec(QSqlDatabase db, const QString &songs_table, const QString &fts_table);
|
bool Exec();
|
||||||
bool Next();
|
bool Next();
|
||||||
QVariant Value(int column) const;
|
QVariant Value(const int column) const;
|
||||||
|
|
||||||
operator const QSqlQuery &() const { return query_; }
|
QString column_spec() const { return column_spec_; }
|
||||||
|
QString order_by() const { return order_by_; }
|
||||||
|
QStringList where_clauses() const { return where_clauses_; }
|
||||||
|
QVariantList bound_values() const { return bound_values_; }
|
||||||
|
bool include_unavailable() const { return include_unavailable_; }
|
||||||
|
bool join_with_fts() const { return join_with_fts_; }
|
||||||
|
bool duplicates_only() const { return duplicates_only_; }
|
||||||
|
int limit() const { return limit_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString GetInnerQuery();
|
QString GetInnerQuery();
|
||||||
|
|
||||||
bool include_unavailable_;
|
QSqlDatabase db_;
|
||||||
bool join_with_fts_;
|
QString songs_table_;
|
||||||
|
QString fts_table_;
|
||||||
|
|
||||||
QString column_spec_;
|
QString column_spec_;
|
||||||
QString order_by_;
|
QString order_by_;
|
||||||
QStringList where_clauses_;
|
QStringList where_clauses_;
|
||||||
QVariantList bound_values_;
|
QVariantList bound_values_;
|
||||||
int limit_;
|
|
||||||
bool duplicates_only_;
|
|
||||||
|
|
||||||
QSqlQuery query_;
|
bool include_unavailable_;
|
||||||
|
bool join_with_fts_;
|
||||||
|
bool duplicates_only_;
|
||||||
|
int limit_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COLLECTIONQUERY_H
|
#endif // COLLECTIONQUERY_H
|
||||||
|
|
|
@ -30,8 +30,6 @@
|
||||||
|
|
||||||
SqlRow::SqlRow(const QSqlQuery &query) { Init(query); }
|
SqlRow::SqlRow(const QSqlQuery &query) { Init(query); }
|
||||||
|
|
||||||
SqlRow::SqlRow(const CollectionQuery &query) { Init(query); }
|
|
||||||
|
|
||||||
void SqlRow::Init(const QSqlQuery &query) {
|
void SqlRow::Init(const QSqlQuery &query) {
|
||||||
|
|
||||||
int rows = query.record().count();
|
int rows = query.record().count();
|
||||||
|
|
|
@ -32,9 +32,7 @@ class CollectionQuery;
|
||||||
class SqlRow {
|
class SqlRow {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// WARNING: Implicit construction from QSqlQuery and CollectionQuery.
|
|
||||||
SqlRow(const QSqlQuery &query);
|
SqlRow(const QSqlQuery &query);
|
||||||
SqlRow(const CollectionQuery &query);
|
|
||||||
|
|
||||||
const QVariant &value(int i) const { return columns_[i]; }
|
const QVariant &value(int i) const { return columns_[i]; }
|
||||||
|
|
||||||
|
|
|
@ -249,8 +249,11 @@ QVariant ContextAlbumsModel::data(const CollectionItem *item, int role) const {
|
||||||
|
|
||||||
ContextAlbumsModel::QueryResult ContextAlbumsModel::RunQuery(CollectionItem *parent) {
|
ContextAlbumsModel::QueryResult ContextAlbumsModel::RunQuery(CollectionItem *parent) {
|
||||||
|
|
||||||
|
QMutexLocker l(backend_->db()->Mutex());
|
||||||
|
QSqlDatabase db(backend_->db()->Connect());
|
||||||
|
|
||||||
QueryResult result;
|
QueryResult result;
|
||||||
CollectionQuery q(query_options_);
|
CollectionQuery q(db, backend_->songs_table(), backend_->fts_table(), query_options_);
|
||||||
q.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
q.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
||||||
|
|
||||||
// Walk up through the item's parents adding filters as necessary
|
// Walk up through the item's parents adding filters as necessary
|
||||||
|
@ -263,9 +266,7 @@ ContextAlbumsModel::QueryResult ContextAlbumsModel::RunQuery(CollectionItem *par
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the query
|
// Execute the query
|
||||||
QMutexLocker l(backend_->db()->Mutex());
|
if (!q.Exec()) return result;
|
||||||
|
|
||||||
if (!backend_->ExecQuery(&q)) return result;
|
|
||||||
|
|
||||||
while (q.Next()) {
|
while (q.Next()) {
|
||||||
result.rows << SqlRow(q);
|
result.rows << SqlRow(q);
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "song.h"
|
#include "song.h"
|
||||||
#include "songloader.h"
|
#include "songloader.h"
|
||||||
#include "tagreaderclient.h"
|
#include "tagreaderclient.h"
|
||||||
|
#include "database.h"
|
||||||
#include "engine/enginetype.h"
|
#include "engine/enginetype.h"
|
||||||
#include "engine/enginebase.h"
|
#include "engine/enginebase.h"
|
||||||
#include "collection/collectionbackend.h"
|
#include "collection/collectionbackend.h"
|
||||||
|
@ -222,11 +223,14 @@ SongLoader::Result SongLoader::LoadLocal(const QString &filename) {
|
||||||
// Search in the database.
|
// Search in the database.
|
||||||
QUrl url = QUrl::fromLocalFile(filename);
|
QUrl url = QUrl::fromLocalFile(filename);
|
||||||
|
|
||||||
CollectionQuery query;
|
QMutexLocker l(collection_->db()->Mutex());
|
||||||
|
QSqlDatabase db(collection_->db()->Connect());
|
||||||
|
|
||||||
|
CollectionQuery query(db, collection_->songs_table(), collection_->fts_table());
|
||||||
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
||||||
query.AddWhere("url", url.toEncoded());
|
query.AddWhere("url", url.toEncoded());
|
||||||
|
|
||||||
if (collection_->ExecQuery(&query) && query.Next()) {
|
if (query.Exec() && query.Next()) {
|
||||||
// We may have many results when the file has many sections
|
// We may have many results when the file has many sections
|
||||||
do {
|
do {
|
||||||
Song song(Song::Source_Collection);
|
Song song(Song::Source_Collection);
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
#include "core/utilities.h"
|
#include "core/utilities.h"
|
||||||
#include "core/imageutils.h"
|
#include "core/imageutils.h"
|
||||||
#include "core/tagreaderclient.h"
|
#include "core/tagreaderclient.h"
|
||||||
|
#include "core/database.h"
|
||||||
#include "widgets/forcescrollperpixel.h"
|
#include "widgets/forcescrollperpixel.h"
|
||||||
#include "widgets/qsearchfield.h"
|
#include "widgets/qsearchfield.h"
|
||||||
#include "collection/sqlrow.h"
|
#include "collection/sqlrow.h"
|
||||||
|
@ -888,7 +889,10 @@ SongList AlbumCoverManager::GetSongsInAlbum(const QModelIndex &idx) const {
|
||||||
|
|
||||||
SongList ret;
|
SongList ret;
|
||||||
|
|
||||||
CollectionQuery q;
|
QMutexLocker l(collection_backend_->db()->Mutex());
|
||||||
|
QSqlDatabase db(collection_backend_->db()->Connect());
|
||||||
|
|
||||||
|
CollectionQuery q(db, collection_backend_->songs_table(), collection_backend_->fts_table());
|
||||||
q.SetColumnSpec("ROWID," + Song::kColumnSpec);
|
q.SetColumnSpec("ROWID," + Song::kColumnSpec);
|
||||||
q.AddWhere("album", idx.data(Role_Album).toString());
|
q.AddWhere("album", idx.data(Role_Album).toString());
|
||||||
q.SetOrderBy("disc, track, title");
|
q.SetOrderBy("disc, track, title");
|
||||||
|
@ -900,7 +904,7 @@ SongList AlbumCoverManager::GetSongsInAlbum(const QModelIndex &idx) const {
|
||||||
|
|
||||||
q.AddCompilationRequirement(albumartist.isEmpty());
|
q.AddCompilationRequirement(albumartist.isEmpty());
|
||||||
|
|
||||||
if (!collection_backend_->ExecQuery(&q)) return ret;
|
if (!q.Exec()) return ret;
|
||||||
|
|
||||||
while (q.Next()) {
|
while (q.Next()) {
|
||||||
Song song;
|
Song song;
|
||||||
|
|
Loading…
Reference in New Issue