diff --git a/src/song.cpp b/src/song.cpp index 9565e0f17..2a207c421 100644 --- a/src/song.cpp +++ b/src/song.cpp @@ -415,7 +415,7 @@ QString Song::PrettyTitleWithArtist() const { if (title.isEmpty()) title = QFileInfo(d->filename_).baseName(); - if (d->compilation_ && !d->artist_.isEmpty()) + if (is_compilation() && !d->artist_.isEmpty() && !d->artist_.toLower().contains("various")) title = d->artist_ + " - " + title; return title; diff --git a/src/song.h b/src/song.h index 84415f449..04a5a6f68 100644 --- a/src/song.h +++ b/src/song.h @@ -162,6 +162,8 @@ class Song { void set_art_automatic(const QString& v) { d->art_automatic_ = v; } void set_art_manual(const QString& v) { d->art_manual_ = v; } void set_image(const QImage& i) { d->image_ = i; } + void set_forced_compilation_on(bool v) { d->forced_compilation_on_ = v; } + void set_forced_compilation_off(bool v) { d->forced_compilation_off_ = v; } // Setters that should only be used by tests void set_filename(const QString& v) { d->filename_ = v; } diff --git a/tests/library_test.cpp b/tests/library_test.cpp index 7126a079b..013287cad 100644 --- a/tests/library_test.cpp +++ b/tests/library_test.cpp @@ -177,5 +177,86 @@ TEST_F(LibraryTest, UnknownAlbums) { EXPECT_EQ("Album", real_album_index.data().toString()); } +TEST_F(LibraryTest, VariousArtistSongs) { + backend_->ExpectSetup(true); + library_->StartThreads(); + + LibraryBackendInterface::AlbumList albums; + albums << LibraryBackendInterface::Album("", "Album", "", ""); + + SongList songs; + songs << Song() << Song() << Song() << Song(); + songs[0].Init("Title 1", "Artist 1", "Album", 0); + songs[1].Init("Title 2", "Artist 2", "Album", 0); + songs[2].Init("Title 3", "Artist 3", "Album", 0); + songs[3].Init("Title 4", "Various Artists", "Album", 0); + + // Different ways of putting songs in "Various Artist". Make sure they all work + songs[0].set_sampler(true); + songs[1].set_compilation(true); + songs[2].set_forced_compilation_on(true); + songs[3].set_sampler(true); + + EXPECT_CALL(*backend_, GetCompilationAlbums(_)) + .WillOnce(Return(albums)); + EXPECT_CALL(*backend_, GetCompilationSongs(QString("Album"), _)) + .WillOnce(Return(songs)); + + QModelIndex artist_index = library_->index(0, 0, QModelIndex()); + ASSERT_EQ(1, library_->rowCount(artist_index)); + + QModelIndex album_index = library_->index(0, 0, artist_index); + ASSERT_EQ(4, library_->rowCount(album_index)); + + EXPECT_EQ("Artist 1 - Title 1", library_->index(0, 0, album_index).data().toString()); + EXPECT_EQ("Artist 2 - Title 2", library_->index(1, 0, album_index).data().toString()); + EXPECT_EQ("Artist 3 - Title 3", library_->index(2, 0, album_index).data().toString()); + EXPECT_EQ("Title 4", library_->index(3, 0, album_index).data().toString()); +} + +TEST_F(LibraryTest, RemoveSongsLazyLoaded) { + backend_->ExpectSetup(false, QStringList() << "Artist"); + library_->StartThreads(); + + LibraryBackendInterface::AlbumList albums; + albums << LibraryBackendInterface::Album("Artist", "Album", "", ""); + + SongList songs; + songs << Song() << Song() << Song(); + songs[0].Init("Title 1", "Artist", "Album", 0); songs[0].set_id(0); + songs[1].Init("Title 2", "Artist", "Album", 0); songs[1].set_id(1); + songs[2].Init("Title 3", "Artist", "Album", 0); songs[2].set_id(2); + + EXPECT_CALL(*backend_, GetAlbumsByArtist(QString("Artist"), _)) + .WillOnce(Return(albums)); + EXPECT_CALL(*backend_, GetSongs(QString("Artist"), QString("Album"), _)) + .WillOnce(Return(songs)); + + // Lazy load the items + QModelIndex artist_index = library_->index(0, 0, QModelIndex()); + ASSERT_EQ(1, library_->rowCount(artist_index)); + QModelIndex album_index = library_->index(0, 0, artist_index); + ASSERT_EQ(3, library_->rowCount(album_index)); + + // Remove the first two songs + QSignalSpy spy1(library_, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int))); + QSignalSpy spy2(library_, SIGNAL(rowsRemoved(QModelIndex,int,int))); + + SongList songs_to_delete = SongList() << songs[0] << songs[1]; + backend_->EmitSongsDeleted(songs_to_delete); + + ASSERT_EQ(2, spy1.count()); + ASSERT_EQ(2, spy2.count()); + for (int call=0 ; call<=1 ; ++call) { + for (int arg=1 ; arg<=2 ; ++arg) { + EXPECT_EQ(0, spy1[call][arg].toInt()) << "Call " << call << " arg " << arg; + EXPECT_EQ(0, spy2[call][arg].toInt()) << "Call " << call << " arg " << arg; + } + } + + ASSERT_EQ(1, library_->rowCount(album_index)); + EXPECT_EQ("Title 3", library_->index(0, 0, album_index).data().toString()); +} + } // namespace diff --git a/tests/metatypes_env.h b/tests/metatypes_env.h index 2c27d954b..634bf1761 100644 --- a/tests/metatypes_env.h +++ b/tests/metatypes_env.h @@ -20,6 +20,7 @@ #include #include +#include #include "directory.h" #include "song.h" @@ -29,6 +30,7 @@ public: void SetUp() { qRegisterMetaType("DirectoryList"); qRegisterMetaType("SongList"); + qRegisterMetaType("QModelIndex"); } }; diff --git a/tests/mock_librarybackend.h b/tests/mock_librarybackend.h index 6e558b94a..6ec343834 100644 --- a/tests/mock_librarybackend.h +++ b/tests/mock_librarybackend.h @@ -18,6 +18,7 @@ #define MOCK_LIBRARYBACKEND_H #include "librarybackend.h" +#include "test_utils.h" #include @@ -77,6 +78,14 @@ class MockLibraryBackend : public LibraryBackendInterface { void ExpectSetup(bool has_compilations = false, const QStringList& artists = QStringList()); + + EXPOSE_SIGNAL1(DirectoriesDiscovered, DirectoryList); + EXPOSE_SIGNAL1(DirectoriesDeleted, DirectoryList); + + EXPOSE_SIGNAL1(SongsDiscovered, SongList); + EXPOSE_SIGNAL1(SongsDeleted, SongList); + + EXPOSE_SIGNAL1(TotalSongCountUpdated, int); }; #endif diff --git a/tests/test_utils.h b/tests/test_utils.h index 4b78922c8..f0464e67c 100644 --- a/tests/test_utils.h +++ b/tests/test_utils.h @@ -27,4 +27,9 @@ std::ostream& operator <<(std::ostream& stream, const QString& str); std::ostream& operator <<(std::ostream& stream, const QUrl& url); std::ostream& operator <<(std::ostream& stream, const QNetworkRequest& req); +#define EXPOSE_SIGNAL0(n) \ + void Emit##n() { emit n(); } +#define EXPOSE_SIGNAL1(n, t1) \ + void Emit##n(const t1& a1) { emit n(a1); } + #endif // TEST_UTILS_H