media library: preserve filters/selections on update

This commit is contained in:
Andrzej Rybczak
2012-10-03 19:58:48 +02:00
parent d3dc560602
commit 6e33c2ef0f
3 changed files with 104 additions and 58 deletions

View File

@@ -67,18 +67,18 @@ bool SongEntryMatcher(const Regex &rx, const MPD::Song &s);
void DisplayAlbums(NC::Menu<AlbumEntry> &menu);
void DisplayPrimaryTags(NC::Menu<MediaLibrary::PrimaryTag> &menu);
bool SortSongsByTrack(const MPD::Song &a, const MPD::Song &b);
struct SortAllTracks {
struct SortSongs {
static const std::array<MPD::Song::GetFunction, 3> GetFuns;
LocaleStringComparison m_cmp;
std::ptrdiff_t m_offset;
public:
SortAllTracks() : m_cmp(std::locale(), Config.ignore_leading_the) { }
SortSongs(bool disc_only)
: m_cmp(std::locale(), Config.ignore_leading_the), m_offset(disc_only ? 2 : 0) { }
bool operator()(const MPD::Song &a, const MPD::Song &b) {
for (auto get = GetFuns.begin(); get != GetFuns.end(); ++get) {
for (auto get = GetFuns.begin()+m_offset; get != GetFuns.end(); ++get) {
int ret = m_cmp(a.getTags(*get, Config.tags_separator),
b.getTags(*get, Config.tags_separator));
if (ret != 0)
@@ -88,7 +88,7 @@ public:
}
};
const std::array<MPD::Song::GetFunction, 3> SortAllTracks::GetFuns = {{
const std::array<MPD::Song::GetFunction, 3> SortSongs::GetFuns = {{
&MPD::Song::getDate,
&MPD::Song::getAlbum,
&MPD::Song::getDisc
@@ -242,9 +242,10 @@ void MediaLibrary::update()
if (hasTwoColumns)
{
if (Albums.reallyEmpty())
if (Albums.reallyEmpty() || m_albums_update_request)
{
Songs.clear();
Albums.clearSearchResults();
m_albums_update_request = false;
std::map<std::tuple<std::string, std::string, std::string>, time_t> albums;
Mpd.GetDirectoryRecursive("/", [&albums](MPD::Song &&s) {
unsigned idx = 0;
@@ -260,22 +261,33 @@ void MediaLibrary::update()
}
while (!(tag = s.get(Config.media_lib_primary_tag, ++idx)).empty());
});
for (auto it = albums.begin(); it != albums.end(); ++it)
Albums.addItem(AlbumEntry(Album(
std::move(std::get<0>(it->first)),
std::move(std::get<1>(it->first)),
std::move(std::get<2>(it->first)),
it->second)));
withUnfilteredMenuReapplyFilter(Albums, [this, &albums]() {
size_t idx = 0;
for (auto it = albums.begin(); it != albums.end(); ++it, ++idx)
{
auto &&entry = AlbumEntry(Album(
std::move(std::get<0>(it->first)),
std::move(std::get<1>(it->first)),
std::move(std::get<2>(it->first)),
it->second));
if (idx < Albums.size())
Albums[idx].value() = entry;
else
Albums.addItem(entry);
}
if (idx < Albums.size())
Albums.resizeList(idx);
std::sort(Albums.beginV(), Albums.endV(), SortAlbumEntries());
});
Albums.refresh();
}
}
else
{
if (Tags.reallyEmpty())
if (Tags.reallyEmpty() || m_tags_update_request)
{
Albums.clear();
Songs.clear();
Tags.clearSearchResults();
m_tags_update_request = false;
std::map<std::string, time_t> tags;
Mpd.GetDirectoryRecursive("/", [&tags](MPD::Song &&s) {
unsigned idx = 0;
@@ -290,13 +302,26 @@ void MediaLibrary::update()
}
while (!(tag = s.get(Config.media_lib_primary_tag, ++idx)).empty());
});
for (auto it = tags.begin(); it != tags.end(); ++it)
Tags.addItem(PrimaryTag(std::move(it->first), it->second));
withUnfilteredMenuReapplyFilter(Tags, [this, &tags]() {
size_t idx = 0;
for (auto it = tags.begin(); it != tags.end(); ++it, ++idx)
{
auto &&tag = PrimaryTag(std::move(it->first), it->second);
if (idx < Tags.size())
Tags[idx].value() = tag;
else
Tags.addItem(tag);
}
if (idx < Tags.size())
Tags.resizeList(idx);
});
Tags.refresh();
}
if (!Tags.empty() && Albums.reallyEmpty())
if ((!Tags.empty() && Albums.reallyEmpty()) || m_albums_update_request)
{
Albums.clearSearchResults();
m_albums_update_request = false;
auto &primary_tag = Tags.current().value().tag();
Mpd.StartSearch(true);
Mpd.AddSearch(Config.media_lib_primary_tag, primary_tag);
@@ -309,25 +334,40 @@ void MediaLibrary::update()
else
it->second = s.getMTime();
});
for (auto it = albums.begin(); it != albums.end(); ++it)
Albums.addItem(AlbumEntry(Album(
primary_tag,
std::move(std::get<0>(it->first)),
std::move(std::get<1>(it->first)),
it->second)));
std::sort(Albums.beginV(), Albums.endV(), SortAlbumEntries());
if (albums.size() > 1)
{
Albums.addSeparator();
Albums.addItem(AlbumEntry::mkAllTracksEntry(primary_tag));
}
withUnfilteredMenuReapplyFilter(Albums, [this, &albums, &primary_tag]() {
size_t idx = 0;
for (auto it = albums.begin(); it != albums.end(); ++it, ++idx)
{
auto &&entry = AlbumEntry(Album(
primary_tag,
std::move(std::get<0>(it->first)),
std::move(std::get<1>(it->first)),
it->second));
if (idx < Albums.size())
{
Albums[idx].value() = entry;
Albums[idx].setSeparator(false);
}
else
Albums.addItem(entry);
}
if (idx < Albums.size())
Albums.resizeList(idx);
std::sort(Albums.beginV(), Albums.endV(), SortAlbumEntries());
if (albums.size() > 1)
{
Albums.addSeparator();
Albums.addItem(AlbumEntry::mkAllTracksEntry(primary_tag));
}
});
Albums.refresh();
}
}
if (!Albums.empty() && Songs.reallyEmpty())
if ((!Albums.empty() && Songs.reallyEmpty()) || m_songs_update_request)
{
Songs.reset();
Songs.clearSearchResults();
m_songs_update_request = false;
auto &album = Albums.current().value();
Mpd.StartSearch(true);
Mpd.AddSearch(Config.media_lib_primary_tag, album.entry().tag());
@@ -336,15 +376,23 @@ void MediaLibrary::update()
Mpd.AddSearch(MPD_TAG_ALBUM, album.entry().album());
Mpd.AddSearch(MPD_TAG_DATE, album.entry().date());
}
Mpd.CommitSearchSongs([this](MPD::Song &&s) {
Songs.addItem(s, myPlaylist->checkForSong(s));
withUnfilteredMenuReapplyFilter(Songs, [this, &album]() {
size_t idx = 0;
Mpd.CommitSearchSongs([this, &idx](MPD::Song &&s) {
bool is_playlist = myPlaylist->checkForSong(s);
if (idx < Songs.size())
{
Songs[idx].value() = s;
Songs[idx].setBold(is_playlist);
}
else
Songs.addItem(s, is_playlist);
++idx;
});
if (idx < Songs.size())
Songs.resizeList(idx);
std::sort(Songs.beginV(), Songs.endV(), SortSongs(!album.isAllTracksEntry()));
});
if (album.isAllTracksEntry())
std::sort(Songs.beginV(), Songs.endV(), SortAllTracks());
else
std::sort(Songs.beginV(), Songs.endV(), SortSongsByTrack);
Songs.refresh();
}
@@ -640,7 +688,7 @@ MPD::SongList MediaLibrary::getSelectedSongs()
Mpd.CommitSearchSongs([&result](MPD::Song &&s) {
result.push_back(s);
});
std::sort(result.begin()+begin, result.end(), SortSongsByTrack);
std::sort(result.begin()+begin, result.end(), SortSongs(false));
}
}
// if no item is selected, add songs from right column
@@ -998,14 +1046,4 @@ void DisplayPrimaryTags(NC::Menu<MediaLibrary::PrimaryTag> &menu)
menu << tag;
}
/***********************************************************************/
bool SortSongsByTrack(const MPD::Song &a, const MPD::Song &b)
{
int cmp = a.getDisc().compare(b.getDisc());
if (cmp != 0)
return cmp < 0;
return a.getTrack() < b.getTrack();
}
}

View File

@@ -74,9 +74,14 @@ struct MediaLibrary: Screen<NC::Window *>, Filterable, HasColumns, HasSongs, Sea
void LocateSong(const MPD::Song &);
ProxySongList songsProxyList();
void toggleSortMode();
void requestTagsUpdate() { m_tags_update_request = true; }
void requestAlbumsUpdate() { m_albums_update_request = true; }
void requestSongsUpdate() { m_songs_update_request = true; }
struct PrimaryTag
{
PrimaryTag() : m_mtime(0) { }
PrimaryTag(std::string tag_, time_t mtime_)
: m_tag(std::move(tag_)), m_mtime(mtime_) { }
@@ -134,6 +139,10 @@ protected:
private:
void AddToPlaylist(bool);
bool m_tags_update_request;
bool m_albums_update_request;
bool m_songs_update_request;
};
extern MediaLibrary *myLibrary;

View File

@@ -193,10 +193,9 @@ void Status::Changes::database()
# ifdef HAVE_TAGLIB_H
myTagEditor->Dirs->clear();
# endif // HAVE_TAGLIB_H
if (myLibrary->Columns() == 2)
myLibrary->Albums.clear();
else
myLibrary->Tags.clear();
myLibrary->requestTagsUpdate();
myLibrary->requestAlbumsUpdate();
myLibrary->requestSongsUpdate();
}
void Status::Changes::playerState()