Improve album cover searching and cover manager, use HttpStatusCodeAttribute and QSslError for services
- Improve album cover manager - Change art_automatic and art_manual to QUrl - Refresh collection album covers when new album covers are fetched - Fix automatic album cover searching for local files outside of the collection - Make all Json services check HttpStatusCodeAttribute - Show detailed SSL errors for Subsonic, Tidal and Qobuz
This commit is contained in:
@@ -976,8 +976,8 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist,
|
||||
info.artist = compilation ? QString() : query.Value(1).toString();
|
||||
info.album_artist = compilation ? QString() : query.Value(2).toString();
|
||||
info.album_name = query.Value(0).toString();
|
||||
info.art_automatic = query.Value(5).toString();
|
||||
info.art_manual = query.Value(6).toString();
|
||||
info.art_automatic = query.Value(5).toUrl();
|
||||
info.art_manual = query.Value(6).toUrl();
|
||||
info.first_url = QUrl::fromEncoded(query.Value(7).toByteArray());
|
||||
|
||||
if ((info.artist == last_artist || info.album_artist == last_album_artist) && info.album_name == last_album)
|
||||
@@ -1015,8 +1015,8 @@ CollectionBackend::Album CollectionBackend::GetAlbumArt(const QString &artist, c
|
||||
if (!ExecQuery(&query)) return ret;
|
||||
|
||||
if (query.Next()) {
|
||||
ret.art_automatic = query.Value(0).toString();
|
||||
ret.art_manual = query.Value(1).toString();
|
||||
ret.art_automatic = query.Value(0).toUrl();
|
||||
ret.art_manual = query.Value(1).toUrl();
|
||||
ret.first_url = QUrl::fromEncoded(query.Value(2).toByteArray());
|
||||
}
|
||||
|
||||
@@ -1024,13 +1024,13 @@ CollectionBackend::Album CollectionBackend::GetAlbumArt(const QString &artist, c
|
||||
|
||||
}
|
||||
|
||||
void CollectionBackend::UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QString &art) {
|
||||
void CollectionBackend::UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url) {
|
||||
|
||||
metaObject()->invokeMethod(this, "UpdateManualAlbumArt", Qt::QueuedConnection, Q_ARG(QString, artist), Q_ARG(QString, albumartist), Q_ARG(QString, album), Q_ARG(QString, art));
|
||||
metaObject()->invokeMethod(this, "UpdateManualAlbumArt", Qt::QueuedConnection, Q_ARG(QString, artist), Q_ARG(QString, albumartist), Q_ARG(QString, album), Q_ARG(QUrl, cover_url));
|
||||
|
||||
}
|
||||
|
||||
void CollectionBackend::UpdateManualAlbumArt(const QString &artist, const QString &albumartist, const QString &album, const QString &art) {
|
||||
void CollectionBackend::UpdateManualAlbumArt(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url) {
|
||||
|
||||
QMutexLocker l(db_->Mutex());
|
||||
QSqlDatabase db(db_->Connect());
|
||||
@@ -1040,10 +1040,10 @@ void CollectionBackend::UpdateManualAlbumArt(const QString &artist, const QStrin
|
||||
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
||||
query.AddWhere("album", album);
|
||||
|
||||
if (!albumartist.isNull() && !albumartist.isEmpty()) {
|
||||
if (!albumartist.isEmpty()) {
|
||||
query.AddWhere("albumartist", albumartist);
|
||||
}
|
||||
else if (!artist.isNull()) {
|
||||
else if (!artist.isEmpty()) {
|
||||
query.AddWhere("artist", artist);
|
||||
}
|
||||
|
||||
@@ -1057,7 +1057,7 @@ void CollectionBackend::UpdateManualAlbumArt(const QString &artist, const QStrin
|
||||
}
|
||||
|
||||
// Update the songs
|
||||
QString sql(QString("UPDATE %1 SET art_manual = :art WHERE album = :album AND unavailable = 0").arg(songs_table_));
|
||||
QString sql(QString("UPDATE %1 SET art_manual = :cover WHERE album = :album AND unavailable = 0").arg(songs_table_));
|
||||
|
||||
if (!albumartist.isNull() && !albumartist.isEmpty()) {
|
||||
sql += " AND albumartist = :albumartist";
|
||||
@@ -1068,12 +1068,12 @@ void CollectionBackend::UpdateManualAlbumArt(const QString &artist, const QStrin
|
||||
|
||||
QSqlQuery q(db);
|
||||
q.prepare(sql);
|
||||
q.bindValue(":art", art);
|
||||
q.bindValue(":cover", cover_url);
|
||||
q.bindValue(":album", album);
|
||||
if (!albumartist.isNull() && !albumartist.isEmpty()) {
|
||||
if (!albumartist.isEmpty()) {
|
||||
q.bindValue(":albumartist", albumartist);
|
||||
}
|
||||
else if (!artist.isNull()) {
|
||||
else if (!artist.isEmpty()) {
|
||||
q.bindValue(":artist", artist);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class CollectionBackendInterface : public QObject {
|
||||
|
||||
struct Album {
|
||||
Album() {}
|
||||
Album(const QString &_artist, const QString &_album_artist, const QString &_album_name, const QString &_art_automatic, const QString &_art_manual, const QUrl &_first_url) :
|
||||
Album(const QString &_artist, const QString &_album_artist, const QString &_album_name, const QUrl &_art_automatic, const QUrl &_art_manual, const QUrl &_first_url) :
|
||||
artist(_artist),
|
||||
album_artist(_album_artist),
|
||||
album_name(_album_name),
|
||||
@@ -68,8 +68,8 @@ class CollectionBackendInterface : public QObject {
|
||||
QString album_artist;
|
||||
QString album_name;
|
||||
|
||||
QString art_automatic;
|
||||
QString art_manual;
|
||||
QUrl art_automatic;
|
||||
QUrl art_manual;
|
||||
QUrl first_url;
|
||||
};
|
||||
typedef QList<Album> AlbumList;
|
||||
@@ -99,7 +99,7 @@ class CollectionBackendInterface : public QObject {
|
||||
virtual AlbumList GetAlbumsByArtist(const QString &artist, const QueryOptions &opt = QueryOptions()) = 0;
|
||||
virtual AlbumList GetCompilationAlbums(const QueryOptions &opt = QueryOptions()) = 0;
|
||||
|
||||
virtual void UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QString &art) = 0;
|
||||
virtual void UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url) = 0;
|
||||
virtual Album GetAlbumArt(const QString &artist, const QString &albumartist, const QString &album) = 0;
|
||||
|
||||
virtual Song GetSongById(int id) = 0;
|
||||
@@ -155,7 +155,7 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||
AlbumList GetCompilationAlbums(const QueryOptions &opt = QueryOptions());
|
||||
AlbumList GetAlbumsByArtist(const QString &artist, const QueryOptions &opt = QueryOptions());
|
||||
|
||||
void UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QString &art);
|
||||
void UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url);
|
||||
Album GetAlbumArt(const QString &artist, const QString &albumartist, const QString &album);
|
||||
|
||||
Song GetSongById(int id);
|
||||
@@ -193,7 +193,7 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||
void MarkSongsUnavailable(const SongList &songs, bool unavailable = true);
|
||||
void AddOrUpdateSubdirs(const SubdirectoryList &subdirs);
|
||||
void UpdateCompilations();
|
||||
void UpdateManualAlbumArt(const QString &artist, const QString &albumartist, const QString &album, const QString &art);
|
||||
void UpdateManualAlbumArt(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url);
|
||||
void ForceCompilation(const QString &album, const QList<QString> &artists, bool on);
|
||||
void IncrementPlayCount(int id);
|
||||
void IncrementSkipCount(int id, float progress);
|
||||
|
||||
@@ -107,10 +107,7 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
|
||||
cover_loader_options_.scale_output_image_ = true;
|
||||
|
||||
if (app_)
|
||||
connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QImage)), SLOT(AlbumArtLoaded(quint64, QImage)));
|
||||
|
||||
//icon_cache_->setCacheDirectory(Utilities::GetConfigPath(Utilities::Path_CacheRoot) + "/pixmapcache");
|
||||
//icon_cache_->setMaximumCacheSize(CollectionModel::kIconCacheSize);
|
||||
connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QUrl, QImage)), SLOT(AlbumCoverLoaded(quint64, QUrl, QImage)));
|
||||
|
||||
QIcon nocover = IconLoader::Load("cdcase");
|
||||
no_cover_icon_ = nocover.pixmap(nocover.availableSizes().last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
@@ -422,7 +419,11 @@ void CollectionModel::SongsDeleted(const SongList &songs) {
|
||||
|
||||
if (node->parent != root_) parents << node->parent;
|
||||
|
||||
beginRemoveRows(ItemToIndex(node->parent), node->row, node->row);
|
||||
QModelIndex idx = ItemToIndex(node->parent);
|
||||
const QString cache_key = AlbumIconPixmapCacheKey(idx);
|
||||
QPixmapCache::remove(cache_key);
|
||||
|
||||
beginRemoveRows(idx, node->row, node->row);
|
||||
node->parent->Delete(node->row);
|
||||
song_nodes_.remove(song.id());
|
||||
endRemoveRows();
|
||||
@@ -491,51 +492,47 @@ void CollectionModel::SongsDeleted(const SongList &songs) {
|
||||
|
||||
}
|
||||
|
||||
QString CollectionModel::AlbumIconPixmapCacheKey(const QModelIndex &index) const {
|
||||
QString CollectionModel::AlbumIconPixmapCacheKey(const QModelIndex &idx) const {
|
||||
|
||||
QStringList path;
|
||||
QModelIndex index_copy(index);
|
||||
while (index_copy.isValid()) {
|
||||
path.prepend(index_copy.data().toString());
|
||||
index_copy = index_copy.parent();
|
||||
QModelIndex idx_copy(idx);
|
||||
while (idx_copy.isValid()) {
|
||||
//const CollectionItem *item = IndexToItem(idx_copy);
|
||||
//if (item && group_by_[item->container_level] == GroupBy_Album) {
|
||||
// QString album = idx_copy.data().toString();
|
||||
// album.remove(Song::kAlbumRemoveDisc);
|
||||
// path.prepend(album);
|
||||
//}
|
||||
//else {
|
||||
path.prepend(idx_copy.data().toString());
|
||||
//}
|
||||
idx_copy = idx_copy.parent();
|
||||
}
|
||||
|
||||
return "collectionart:" + path.join("/");
|
||||
|
||||
}
|
||||
|
||||
QVariant CollectionModel::AlbumIcon(const QModelIndex &index) {
|
||||
QVariant CollectionModel::AlbumIcon(const QModelIndex &idx) {
|
||||
|
||||
CollectionItem *item = IndexToItem(index);
|
||||
CollectionItem *item = IndexToItem(idx);
|
||||
if (!item) return no_cover_icon_;
|
||||
|
||||
// Check the cache for a pixmap we already loaded.
|
||||
const QString cache_key = AlbumIconPixmapCacheKey(index);
|
||||
const QString cache_key = AlbumIconPixmapCacheKey(idx);
|
||||
|
||||
QPixmap cached_pixmap;
|
||||
if (QPixmapCache::find(cache_key, &cached_pixmap)) {
|
||||
return cached_pixmap;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Try to load it from the disk cache
|
||||
std::unique_ptr<QIODevice> cache(icon_cache_->data(QUrl(cache_key)));
|
||||
if (cache) {
|
||||
QImage cached_image;
|
||||
if (cached_image.load(cache.get(), "XPM")) {
|
||||
QPixmapCache::insert(cache_key, QPixmap::fromImage(cached_image));
|
||||
return QPixmap::fromImage(cached_image);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Maybe we're loading a pixmap already?
|
||||
if (pending_cache_keys_.contains(cache_key)) {
|
||||
return no_cover_icon_;
|
||||
}
|
||||
|
||||
// No art is cached and we're not loading it already. Load art for the first song in the album.
|
||||
SongList songs = GetChildSongs(index);
|
||||
SongList songs = GetChildSongs(idx);
|
||||
if (!songs.isEmpty()) {
|
||||
const quint64 id = app_->album_cover_loader()->LoadImageAsync(cover_loader_options_, songs.first());
|
||||
pending_art_[id] = ItemAndCacheKey(item, cache_key);
|
||||
@@ -546,14 +543,16 @@ QVariant CollectionModel::AlbumIcon(const QModelIndex &index) {
|
||||
|
||||
}
|
||||
|
||||
void CollectionModel::AlbumArtLoaded(quint64 id, const QImage &image) {
|
||||
void CollectionModel::AlbumCoverLoaded(const quint64 id, const QUrl &cover_url, const QImage &image) {
|
||||
|
||||
if (!pending_art_.contains(id)) return;
|
||||
|
||||
ItemAndCacheKey item_and_cache_key = pending_art_.take(id);
|
||||
CollectionItem *item = item_and_cache_key.first;
|
||||
const QString &cache_key = item_and_cache_key.second;
|
||||
|
||||
if (!item) return;
|
||||
|
||||
const QString &cache_key = item_and_cache_key.second;
|
||||
|
||||
pending_cache_keys_.remove(cache_key);
|
||||
|
||||
// Insert this image in the cache.
|
||||
@@ -562,35 +561,19 @@ void CollectionModel::AlbumArtLoaded(quint64 id, const QImage &image) {
|
||||
QPixmapCache::insert(cache_key, no_cover_icon_);
|
||||
}
|
||||
else {
|
||||
//qLog(Debug) << cache_key;
|
||||
QPixmap image_pixmap;
|
||||
image_pixmap = QPixmap::fromImage(image);
|
||||
QPixmapCache::insert(cache_key, image_pixmap);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// if not already in the disk cache
|
||||
std::unique_ptr<QIODevice> cached_img(icon_cache_->data(QUrl(cache_key)));
|
||||
if (!cached_img && !image.isNull()) {
|
||||
QNetworkCacheMetaData item_metadata;
|
||||
item_metadata.setSaveToDisk(true);
|
||||
item_metadata.setUrl(QUrl(cache_key));
|
||||
QIODevice *cache = icon_cache_->prepare(item_metadata);
|
||||
if (cache) {
|
||||
image.save(cache, "XPM");
|
||||
icon_cache_->insert(cache);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const QModelIndex index = ItemToIndex(item);
|
||||
emit dataChanged(index, index);
|
||||
const QModelIndex idx = ItemToIndex(item);
|
||||
emit dataChanged(idx, idx);
|
||||
|
||||
}
|
||||
|
||||
QVariant CollectionModel::data(const QModelIndex &index, int role) const {
|
||||
QVariant CollectionModel::data(const QModelIndex &idx, int role) const {
|
||||
|
||||
const CollectionItem *item = IndexToItem(index);
|
||||
const CollectionItem *item = IndexToItem(idx);
|
||||
|
||||
// Handle a special case for returning album artwork instead of a generic CD icon.
|
||||
// this is here instead of in the other data() function to let us use the
|
||||
@@ -604,7 +587,7 @@ QVariant CollectionModel::data(const QModelIndex &index, int role) const {
|
||||
}
|
||||
if (is_album_node) {
|
||||
// It has const behaviour some of the time - that's ok right?
|
||||
return const_cast<CollectionModel*>(this)->AlbumIcon(index);
|
||||
return const_cast<CollectionModel*>(this)->AlbumIcon(idx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1326,9 +1309,9 @@ QString CollectionModel::SortTextForSong(const Song &song) {
|
||||
|
||||
}
|
||||
|
||||
Qt::ItemFlags CollectionModel::flags(const QModelIndex &index) const {
|
||||
Qt::ItemFlags CollectionModel::flags(const QModelIndex &idx) const {
|
||||
|
||||
switch (IndexToItem(index)->type) {
|
||||
switch (IndexToItem(idx)->type) {
|
||||
case CollectionItem::Type_Song:
|
||||
case CollectionItem::Type_Container:
|
||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled;
|
||||
@@ -1355,8 +1338,8 @@ QMimeData *CollectionModel::mimeData(const QModelIndexList &indexes) const {
|
||||
|
||||
data->backend = backend_;
|
||||
|
||||
for (const QModelIndex &index : indexes) {
|
||||
GetChildSongs(IndexToItem(index), &urls, &data->songs, &song_ids);
|
||||
for (const QModelIndex &idx : indexes) {
|
||||
GetChildSongs(IndexToItem(idx), &urls, &data->songs, &song_ids);
|
||||
}
|
||||
|
||||
data->setUrls(urls);
|
||||
@@ -1410,15 +1393,15 @@ SongList CollectionModel::GetChildSongs(const QModelIndexList &indexes) const {
|
||||
SongList ret;
|
||||
QSet<int> song_ids;
|
||||
|
||||
for (const QModelIndex &index : indexes) {
|
||||
GetChildSongs(IndexToItem(index), &dontcare, &ret, &song_ids);
|
||||
for (const QModelIndex &idx : indexes) {
|
||||
GetChildSongs(IndexToItem(idx), &dontcare, &ret, &song_ids);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
SongList CollectionModel::GetChildSongs(const QModelIndex &index) const {
|
||||
return GetChildSongs(QModelIndexList() << index);
|
||||
SongList CollectionModel::GetChildSongs(const QModelIndex &idx) const {
|
||||
return GetChildSongs(QModelIndexList() << idx);
|
||||
}
|
||||
|
||||
void CollectionModel::SetFilterAge(int age) {
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
#include <QImage>
|
||||
#include <QIcon>
|
||||
#include <QPixmap>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QSettings>
|
||||
|
||||
#include "core/simpletreemodel.h"
|
||||
@@ -135,7 +134,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
||||
|
||||
// Get information about the collection
|
||||
void GetChildSongs(CollectionItem *item, QList<QUrl> *urls, SongList *songs, QSet<int> *song_ids) const;
|
||||
SongList GetChildSongs(const QModelIndex &index) const;
|
||||
SongList GetChildSongs(const QModelIndex &idx) const;
|
||||
SongList GetChildSongs(const QModelIndexList &indexes) const;
|
||||
|
||||
// Might be accurate
|
||||
@@ -144,8 +143,8 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
||||
int total_album_count() const { return total_album_count_; }
|
||||
|
||||
// QAbstractItemModel
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &idx) const;
|
||||
QStringList mimeTypes() const;
|
||||
QMimeData *mimeData(const QModelIndexList &indexes) const;
|
||||
bool canFetchMore(const QModelIndex &parent) const;
|
||||
@@ -203,7 +202,7 @@ signals:
|
||||
// Called after ResetAsync
|
||||
void ResetAsyncQueryFinished(QFuture<CollectionModel::QueryResult> future);
|
||||
|
||||
void AlbumArtLoaded(quint64 id, const QImage &image);
|
||||
void AlbumCoverLoaded(const quint64 id, const QUrl &cover_url, const QImage &image);
|
||||
|
||||
private:
|
||||
// Provides some optimisations for loading the list of items in the root.
|
||||
@@ -236,8 +235,8 @@ signals:
|
||||
QString DividerDisplayText(GroupBy type, const QString &key) const;
|
||||
|
||||
// Helpers
|
||||
QString AlbumIconPixmapCacheKey(const QModelIndex &index) const;
|
||||
QVariant AlbumIcon(const QModelIndex &index);
|
||||
QString AlbumIconPixmapCacheKey(const QModelIndex &idx) const;
|
||||
QVariant AlbumIcon(const QModelIndex &idx);
|
||||
QVariant data(const CollectionItem *item, int role) const;
|
||||
bool CompareItems(const CollectionItem *a, const CollectionItem *b) const;
|
||||
|
||||
@@ -270,8 +269,6 @@ signals:
|
||||
QIcon playlists_dir_icon_;
|
||||
QIcon playlist_icon_;
|
||||
|
||||
QNetworkDiskCache *icon_cache_;
|
||||
|
||||
int init_task_id_;
|
||||
|
||||
bool use_pretty_covers_;
|
||||
|
||||
@@ -382,8 +382,8 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
||||
bool changed = (matching_song.mtime() != qMax(file_info.lastModified().toTime_t(), song_cue_mtime)) || cue_deleted || cue_added;
|
||||
|
||||
// Also want to look to see whether the album art has changed
|
||||
QString image = ImageForSong(file, album_art);
|
||||
if ((matching_song.art_automatic().isEmpty() && !image.isEmpty()) || (!matching_song.art_automatic().isEmpty() && !matching_song.has_embedded_cover() && !QFile::exists(matching_song.art_automatic()))) {
|
||||
QUrl image = ImageForSong(file, album_art);
|
||||
if ((matching_song.art_automatic().isEmpty() && !image.isEmpty()) || (!matching_song.art_automatic().isEmpty() && !matching_song.has_embedded_cover() && !QFile::exists(matching_song.art_automatic().toLocalFile()))) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
@@ -415,7 +415,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
||||
|
||||
qLog(Debug) << file << "created";
|
||||
// choose an image for the song(s)
|
||||
QString image = ImageForSong(file, album_art);
|
||||
QUrl image = ImageForSong(file, album_art);
|
||||
|
||||
for (Song song : song_list) {
|
||||
song.set_directory_id(t->dir());
|
||||
@@ -457,7 +457,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
||||
|
||||
}
|
||||
|
||||
void CollectionWatcher::UpdateCueAssociatedSongs(const QString &file, const QString &path, const QString &matching_cue, const QString &image, ScanTransaction *t) {
|
||||
void CollectionWatcher::UpdateCueAssociatedSongs(const QString &file, const QString &path, const QString &matching_cue, const QUrl &image, ScanTransaction *t) {
|
||||
|
||||
QFile cue(matching_cue);
|
||||
cue.open(QIODevice::ReadOnly);
|
||||
@@ -497,7 +497,7 @@ void CollectionWatcher::UpdateCueAssociatedSongs(const QString &file, const QStr
|
||||
|
||||
}
|
||||
|
||||
void CollectionWatcher::UpdateNonCueAssociatedSong(const QString &file, const Song &matching_song, const QString &image, bool cue_deleted, ScanTransaction *t) {
|
||||
void CollectionWatcher::UpdateNonCueAssociatedSong(const QString &file, const Song &matching_song, const QUrl &image, bool cue_deleted, ScanTransaction *t) {
|
||||
|
||||
// If a cue got deleted, we turn it's first section into the new 'raw' (cueless) song and we just remove the rest of the sections from the collection
|
||||
if (cue_deleted) {
|
||||
@@ -562,7 +562,7 @@ SongList CollectionWatcher::ScanNewFile(const QString &file, const QString &path
|
||||
|
||||
}
|
||||
|
||||
void CollectionWatcher::PreserveUserSetData(const QString &file, const QString &image, const Song &matching_song, Song *out, ScanTransaction *t) {
|
||||
void CollectionWatcher::PreserveUserSetData(const QString &file, const QUrl &image, const Song &matching_song, Song *out, ScanTransaction *t) {
|
||||
|
||||
out->set_id(matching_song.id());
|
||||
|
||||
@@ -731,20 +731,27 @@ QString CollectionWatcher::PickBestImage(const QStringList &images) {
|
||||
|
||||
}
|
||||
|
||||
QString CollectionWatcher::ImageForSong(const QString &path, QMap<QString, QStringList> &album_art) {
|
||||
QUrl CollectionWatcher::ImageForSong(const QString &path, QMap<QString, QStringList> &album_art) {
|
||||
|
||||
QString dir(DirectoryPart(path));
|
||||
|
||||
if (album_art.contains(dir)) {
|
||||
if (album_art[dir].count() == 1)
|
||||
return album_art[dir][0];
|
||||
if (album_art[dir].count() == 1) {
|
||||
QUrl url;
|
||||
url.setScheme("file");
|
||||
url.setPath(album_art[dir][0]);
|
||||
return url;
|
||||
}
|
||||
else {
|
||||
QString best_image = PickBestImage(album_art[dir]);
|
||||
album_art[dir] = QStringList() << best_image;
|
||||
return best_image;
|
||||
QUrl url;
|
||||
url.setScheme("file");
|
||||
url.setPath(best_image);
|
||||
return url;
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
return QUrl();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -155,17 +155,17 @@ signals:
|
||||
inline static QString ExtensionPart(const QString &fileName);
|
||||
inline static QString DirectoryPart(const QString &fileName);
|
||||
QString PickBestImage(const QStringList &images);
|
||||
QString ImageForSong(const QString &path, QMap<QString, QStringList> &album_art);
|
||||
QUrl ImageForSong(const QString &path, QMap<QString, QStringList> &album_art);
|
||||
void AddWatch(const Directory &dir, const QString &path);
|
||||
uint GetMtimeForCue(const QString &cue_path);
|
||||
void PerformScan(bool incremental, bool ignore_mtimes);
|
||||
|
||||
// Updates the sections of a cue associated and altered (according to mtime) media file during a scan.
|
||||
void UpdateCueAssociatedSongs(const QString &file, const QString &path, const QString &matching_cue, const QString &image, ScanTransaction *t);
|
||||
void UpdateCueAssociatedSongs(const QString &file, const QString &path, const QString &matching_cue, const QUrl &image, ScanTransaction *t);
|
||||
// Updates a single non-cue associated and altered (according to mtime) song during a scan.
|
||||
void UpdateNonCueAssociatedSong(const QString &file, const Song &matching_song, const QString &image, bool cue_deleted, ScanTransaction *t);
|
||||
void UpdateNonCueAssociatedSong(const QString &file, const Song &matching_song, const QUrl &image, bool cue_deleted, ScanTransaction *t);
|
||||
// Updates a new song with some metadata taken from it's equivalent old song (for example rating and score).
|
||||
void PreserveUserSetData(const QString &file, const QString &image, const Song &matching_song, Song *out, ScanTransaction *t);
|
||||
void PreserveUserSetData(const QString &file, const QUrl &image, const Song &matching_song, Song *out, ScanTransaction *t);
|
||||
// Scans a single media file that's present on the disk but not yet in the collection.
|
||||
// It may result in a multiple files added to the collection when the media file has many sections (like a CUE related media file).
|
||||
SongList ScanNewFile(const QString &file, const QString &path, const QString &matching_cue, QSet<QString> *cues_processed);
|
||||
|
||||
Reference in New Issue
Block a user