mirror of
https://github.com/clementine-player/Clementine
synced 2025-01-18 20:40:43 +01:00
When album cover art changes, update songs matching those albums in the playlist
This commit is contained in:
parent
b7a8e43a53
commit
8dd0b9902b
@ -29,6 +29,7 @@ class LibraryPlaylistItem : public PlaylistItem {
|
||||
void Reload();
|
||||
|
||||
Song Metadata() const { return song_; }
|
||||
void SetMetadata(const Song& song) { song_ = song; }
|
||||
|
||||
QUrl Url() const;
|
||||
|
||||
|
@ -72,6 +72,7 @@ Playlist::Playlist(PlaylistBackend* backend, int id, QObject *parent)
|
||||
|
||||
Playlist::~Playlist() {
|
||||
items_.clear();
|
||||
library_items_by_id_.clear();
|
||||
}
|
||||
|
||||
QVariant Playlist::headerData(int section, Qt::Orientation, int role) const {
|
||||
@ -603,6 +604,13 @@ QModelIndex Playlist::InsertItemsWithoutUndo(const PlaylistItemList& items,
|
||||
items_.insert(i, item);
|
||||
virtual_items_ << virtual_items_.count();
|
||||
|
||||
if (item->type() == "Library") {
|
||||
int id = item->Metadata().id();
|
||||
if (id != -1) {
|
||||
library_items_by_id_.insertMulti(id, item);
|
||||
}
|
||||
}
|
||||
|
||||
if (item == current_item_) {
|
||||
// It's one we removed before that got re-added through an undo
|
||||
current_item_index_ = index(i, 0);
|
||||
@ -820,6 +828,7 @@ void Playlist::Restore() {
|
||||
|
||||
items_.clear();
|
||||
virtual_items_.clear();
|
||||
library_items_by_id_.clear();
|
||||
|
||||
items_ = backend_->GetPlaylistItems(id_);
|
||||
|
||||
@ -827,7 +836,14 @@ void Playlist::Restore() {
|
||||
|
||||
for (int i=0 ; i<items_.count() ; ++i) {
|
||||
virtual_items_ << i;
|
||||
};
|
||||
|
||||
if (items_[i]->type() == "Library") {
|
||||
int id = items_[i]->Metadata().id();
|
||||
if (id != -1) {
|
||||
library_items_by_id_.insertMulti(id, items_[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
@ -852,8 +868,17 @@ PlaylistItemList Playlist::RemoveItemsWithoutUndo(int row, int count) {
|
||||
|
||||
// Remove items
|
||||
PlaylistItemList ret;
|
||||
for (int i=0 ; i<count ; ++i)
|
||||
ret << items_.takeAt(row);
|
||||
for (int i=0 ; i<count ; ++i) {
|
||||
boost::shared_ptr<PlaylistItem> item(items_.takeAt(row));
|
||||
ret << item;
|
||||
|
||||
if (item->type() == "Library") {
|
||||
int id = item->Metadata().id();
|
||||
if (id != -1) {
|
||||
library_items_by_id_.remove(id, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
endRemoveRows();
|
||||
|
||||
@ -1029,3 +1054,7 @@ quint64 Playlist::GetTotalLength() const {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
PlaylistItemList Playlist::library_items_by_id(int id) const {
|
||||
return library_items_by_id_.values(id);
|
||||
}
|
||||
|
@ -112,6 +112,8 @@ class Playlist : public QAbstractListModel {
|
||||
PlaylistItem::Options current_item_options() const;
|
||||
Song current_item_metadata() const;
|
||||
|
||||
PlaylistItemList library_items_by_id(int id) const;
|
||||
|
||||
SongList GetAllSongs() const;
|
||||
quint64 GetTotalLength() const; // in seconds
|
||||
|
||||
@ -200,6 +202,9 @@ class Playlist : public QAbstractListModel {
|
||||
PlaylistItemList items_;
|
||||
QList<int> virtual_items_; // Contains the indices into items_ in the order
|
||||
// that they will be played.
|
||||
// A map of library ID to playlist item - for fast lookups when library
|
||||
// items change.
|
||||
QMultiMap<int, boost::shared_ptr<PlaylistItem> > library_items_by_id_;
|
||||
|
||||
QPersistentModelIndex current_item_index_;
|
||||
QPersistentModelIndex last_played_item_index_;
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "playlistbackend.h"
|
||||
#include "playlistmanager.h"
|
||||
#include "core/utilities.h"
|
||||
#include "library/librarybackend.h"
|
||||
#include "library/libraryplaylistitem.h"
|
||||
#include "playlistparsers/playlistparser.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
@ -47,6 +49,8 @@ void PlaylistManager::Init(LibraryBackend* library_backend,
|
||||
playlist_backend_ = playlist_backend;
|
||||
sequence_ = sequence;
|
||||
|
||||
connect(library_backend_, SIGNAL(SongsDiscovered(SongList)), SLOT(SongsDiscovered(SongList)));
|
||||
|
||||
foreach (const PlaylistBackend::Playlist& p, playlist_backend->GetAllPlaylists()) {
|
||||
AddPlaylist(p.id, p.name);
|
||||
}
|
||||
@ -225,3 +229,17 @@ void PlaylistManager::SelectionChanged(const QItemSelection &selection) {
|
||||
current_selection_ = selection;
|
||||
UpdateSummaryText();
|
||||
}
|
||||
|
||||
void PlaylistManager::SongsDiscovered(const SongList& songs) {
|
||||
// Some songs might've changed in the library, let's update any playlist
|
||||
// items we have that match those songs
|
||||
|
||||
foreach (const Song& song, songs) {
|
||||
foreach (const Data& data, playlists_) {
|
||||
PlaylistItemList items = data.p->library_items_by_id(song.id());
|
||||
foreach (boost::shared_ptr<PlaylistItem> item, items) {
|
||||
static_cast<LibraryPlaylistItem*>(item.get())->SetMetadata(song);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ signals:
|
||||
|
||||
private slots:
|
||||
void UpdateSummaryText();
|
||||
void SongsDiscovered(const SongList& songs);
|
||||
|
||||
private:
|
||||
Playlist* AddPlaylist(int id, const QString& name);
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "test_utils.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "library/libraryplaylistitem.h"
|
||||
#include "playlist/playlist.h"
|
||||
#include "mock_settingsprovider.h"
|
||||
#include "mock_playlistitem.h"
|
||||
@ -434,6 +435,69 @@ TEST_F(PlaylistTest, ShuffleThenNext) {
|
||||
EXPECT_EQ(index-1, playlist_.previous_index());
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, LibraryIdMapSingle) {
|
||||
Song song;
|
||||
song.Init("title", "artist", "album", 123);
|
||||
song.set_id(1);
|
||||
|
||||
boost::shared_ptr<PlaylistItem> item(new LibraryPlaylistItem(song));
|
||||
playlist_.InsertItems(PlaylistItemList() << item);
|
||||
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(-1).count());
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(0).count());
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(2).count());
|
||||
ASSERT_EQ(1, playlist_.library_items_by_id(1).count());
|
||||
EXPECT_EQ(song.title(), playlist_.library_items_by_id(1)[0]->Metadata().title());
|
||||
|
||||
playlist_.Clear();
|
||||
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(1).count());
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, LibraryIdMapInvalid) {
|
||||
Song invalid;
|
||||
invalid.Init("title", "artist", "album", 123);
|
||||
ASSERT_EQ(-1, invalid.id());
|
||||
|
||||
boost::shared_ptr<PlaylistItem> item(new LibraryPlaylistItem(invalid));
|
||||
playlist_.InsertItems(PlaylistItemList() << item);
|
||||
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(-1).count());
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(0).count());
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(1).count());
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(2).count());
|
||||
}
|
||||
|
||||
TEST_F(PlaylistTest, LibraryIdMapMulti) {
|
||||
Song one;
|
||||
one.Init("title", "artist", "album", 123);
|
||||
one.set_id(1);
|
||||
|
||||
Song two;
|
||||
two.Init("title 2", "artist 2", "album 2", 123);
|
||||
two.set_id(2);
|
||||
|
||||
boost::shared_ptr<PlaylistItem> item_one(new LibraryPlaylistItem(one));
|
||||
boost::shared_ptr<PlaylistItem> item_two(new LibraryPlaylistItem(two));
|
||||
boost::shared_ptr<PlaylistItem> item_three(new LibraryPlaylistItem(one));
|
||||
playlist_.InsertItems(PlaylistItemList() << item_one << item_two << item_three);
|
||||
|
||||
EXPECT_EQ(2, playlist_.library_items_by_id(1).count());
|
||||
EXPECT_EQ(1, playlist_.library_items_by_id(2).count());
|
||||
|
||||
playlist_.removeRow(1); // item_two
|
||||
EXPECT_EQ(2, playlist_.library_items_by_id(1).count());
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(2).count());
|
||||
|
||||
playlist_.removeRow(1); // item_three
|
||||
EXPECT_EQ(1, playlist_.library_items_by_id(1).count());
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(2).count());
|
||||
|
||||
playlist_.removeRow(0); // item_one
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(1).count());
|
||||
EXPECT_EQ(0, playlist_.library_items_by_id(2).count());
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user