From 6177d49f9fdb32c27265ba879195617182454de7 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Sun, 3 May 2009 19:02:31 +0200 Subject: [PATCH] new feature: two columns view in media library (albums and songs) --- src/help.cpp | 1 + src/media_library.cpp | 106 +++++++++++++++++++++++++++++++++++------- src/media_library.h | 4 ++ src/ncmpcpp.cpp | 18 +++++-- src/status.cpp | 8 +++- 5 files changed, 115 insertions(+), 22 deletions(-) diff --git a/src/help.cpp b/src/help.cpp index 9d32b02f..5582ab8e 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -232,6 +232,7 @@ void Help::GetKeybindings() *w << " " << fmtBold << "Keys - Media library\n -----------------------------------------\n" << fmtBoldEnd; + *w << DisplayKeys(Key.MediaLibrary) << "Switch between two/three columns\n"; *w << DisplayKeys(&Key.VolumeDown[0], 1) << "Previous column\n"; *w << DisplayKeys(&Key.VolumeUp[0], 1) << "Next column\n"; *w << DisplayKeys(Key.Enter) << "Add to playlist and play song/album/artist's songs\n"; diff --git a/src/media_library.cpp b/src/media_library.cpp index 54ac1a6a..795688c5 100644 --- a/src/media_library.cpp +++ b/src/media_library.cpp @@ -35,6 +35,7 @@ using std::string; MediaLibrary *myLibrary = new MediaLibrary; +bool MediaLibrary::hasTwoColumns; size_t MediaLibrary::itsLeftColWidth; size_t MediaLibrary::itsMiddleColWidth; size_t MediaLibrary::itsMiddleColStartX; @@ -43,6 +44,7 @@ size_t MediaLibrary::itsRightColStartX; void MediaLibrary::Init() { + hasTwoColumns = 0; itsLeftColWidth = COLS/3-1; itsMiddleColWidth = COLS/3; itsMiddleColStartX = itsLeftColWidth+1; @@ -77,11 +79,21 @@ void MediaLibrary::Init() void MediaLibrary::Resize() { - itsLeftColWidth = COLS/3-1; - itsMiddleColStartX = itsLeftColWidth+1; - itsMiddleColWidth = COLS/3; - itsRightColStartX = itsLeftColWidth+itsMiddleColWidth+2; - itsRightColWidth = COLS-COLS/3*2-1; + if (!hasTwoColumns) + { + itsLeftColWidth = COLS/3-1; + itsMiddleColStartX = itsLeftColWidth+1; + itsMiddleColWidth = COLS/3; + itsRightColStartX = itsLeftColWidth+itsMiddleColWidth+2; + itsRightColWidth = COLS-COLS/3*2-1; + } + else + { + itsMiddleColStartX = 0; + itsMiddleColWidth = COLS/2; + itsRightColStartX = itsMiddleColWidth+1; + itsRightColWidth = COLS-itsMiddleColWidth-1; + } Artists->Resize(itsLeftColWidth, MainHeight); Albums->Resize(itsMiddleColWidth, MainHeight); @@ -110,7 +122,24 @@ void MediaLibrary::Refresh() void MediaLibrary::SwitchTo() { if (myScreen == this) - return; + { + hasTwoColumns = !hasTwoColumns; + hasToBeResized = 1; + Artists->Clear(0); + Albums->Clear(0); + Albums->Reset(); + Songs->Clear(0); + if (hasTwoColumns) + { + if (w == Artists) + NextColumn(); + string item_type = IntoStr(Config.media_lib_primary_tag); + ToLower(item_type); + Albums->SetTitle("Albums (sorted by " + item_type + ")"); + } + else + Albums->SetTitle("Albums"); + } if (hasToBeResized) Resize(); @@ -128,7 +157,7 @@ std::string MediaLibrary::Title() void MediaLibrary::Update() { - if (Artists->Empty()) + if (!hasTwoColumns && Artists->Empty()) { TagList list; Albums->Clear(0); @@ -147,7 +176,7 @@ void MediaLibrary::Update() Artists->Refresh(); } - if (!Artists->Empty() && Albums->Empty() && Songs->Empty()) + if (!hasTwoColumns && !Artists->Empty() && Albums->Empty() && Songs->Empty()) { Albums->Reset(); TagList list; @@ -173,14 +202,13 @@ void MediaLibrary::Update() Albums->AddOption(std::make_pair("", SearchConstraints("", ""))); } - for (TagList::iterator it = list.begin(); it != list.end(); it++) + for (TagList::const_iterator it = list.begin(); it != list.end(); it++) { TagList l; Mpd->StartFieldSearch(MPD_TAG_ITEM_DATE); Mpd->AddSearch(Config.media_lib_primary_tag, Artists->Current()); Mpd->AddSearch(MPD_TAG_ITEM_ALBUM, *it); Mpd->CommitSearch(l); - utf_to_locale(*it); if (l.empty()) { Albums->AddOption(std::make_pair(*it, SearchConstraints(*it, ""))); @@ -190,27 +218,69 @@ void MediaLibrary::Update() Albums->AddOption(std::make_pair("(" + *j + ") " + *it, SearchConstraints(*it, *j))); } utf_to_locale(Artists->Current()); + for (size_t i = 0; i < Albums->Size(); i++) + utf_to_locale((*Albums)[i].first); if (!Albums->Empty()) Albums->Sort((*Albums)[0].first == ""); - Albums->Window::Clear(); + Albums->Refresh(); + } + else if (hasTwoColumns && Albums->Empty() && Songs->Empty()) + { + TagList artists; + *Albums << XY(0, 0) << "Fetching albums' list..."; + Albums->Window::Refresh(); + Mpd->GetList(artists, Config.media_lib_primary_tag); + for (TagList::const_iterator i = artists.begin(); i != artists.end(); i++) + { + TagList albums; + Mpd->StartFieldSearch(MPD_TAG_ITEM_ALBUM); + Mpd->AddSearch(Config.media_lib_primary_tag, *i); + Mpd->CommitSearch(albums); + for (TagList::const_iterator j = albums.begin(); j != albums.end(); j++) + { + if (Config.media_lib_primary_tag != MPD_TAG_ITEM_DATE) + { + TagList years; + Mpd->StartFieldSearch(MPD_TAG_ITEM_DATE); + Mpd->AddSearch(Config.media_lib_primary_tag, *i); + Mpd->AddSearch(MPD_TAG_ITEM_ALBUM, *j); + Mpd->CommitSearch(years); + if (!years.empty()) + { + for (TagList::const_iterator k = years.begin(); k != years.end(); k++) + { + Albums->AddOption(std::make_pair(*i + " - (" + *k + ") " + *j, SearchConstraints(*i, *j, *k))); + } + } + else + Albums->AddOption(std::make_pair(*i + " - " + *j, SearchConstraints(*i, *j, ""))); + } + else + Albums->AddOption(std::make_pair(*i + " - " + *j, SearchConstraints(*i, *j, *i))); + } + } + for (size_t i = 0; i < Albums->Size(); i++) + utf_to_locale((*Albums)[i].first); + if (!Albums->Empty()) + Albums->Sort(); Albums->Refresh(); } - if (!Artists->Empty() && w == Albums && Albums->Empty()) + if (!hasTwoColumns && !Artists->Empty() && w == Albums && Albums->Empty()) { Albums->HighlightColor(Config.main_highlight_color); Artists->HighlightColor(Config.active_column_color); w = Artists; } - if (!Artists->Empty() && Songs->Empty()) + if ((hasTwoColumns || !Artists->Empty()) && Songs->Empty()) { Songs->Reset(); SongList list; Songs->Clear(0); Mpd->StartSearch(1); - Mpd->AddSearch(Config.media_lib_primary_tag, locale_to_utf_cpy(Artists->Current())); + Mpd->AddSearch(Config.media_lib_primary_tag, hasTwoColumns ? Albums->Current().second.Artist : locale_to_utf_cpy(Artists->Current())); if (Albums->Empty()) // left for compatibility with AddSearch(MPD_TAG_ITEM_ALBUM, locale_to_utf_cpy(Albums->Current().second.Album)); + Mpd->AddSearch(MPD_TAG_ITEM_ALBUM, Albums->Current().second.Album); if (!Albums->Current().second.Album.empty()) // for - Mpd->AddSearch(MPD_TAG_ITEM_DATE, locale_to_utf_cpy(Albums->Current().second.Year)); + Mpd->AddSearch(MPD_TAG_ITEM_DATE, Albums->Current().second.Year); } Mpd->CommitSearch(list); @@ -293,7 +363,7 @@ void MediaLibrary::NextColumn() { if (w == Artists) { - if (Songs->Empty()) + if (!hasTwoColumns && Songs->Empty()) return; Artists->HighlightColor(Config.main_highlight_color); w->Refresh(); @@ -322,7 +392,7 @@ void MediaLibrary::PrevColumn() if (!Albums->Empty()) return; } - if (w == Albums) + if (w == Albums && !hasTwoColumns) { Albums->HighlightColor(Config.main_highlight_color); w->Refresh(); diff --git a/src/media_library.h b/src/media_library.h index 5d75f648..a7ed973d 100644 --- a/src/media_library.h +++ b/src/media_library.h @@ -28,8 +28,10 @@ class MediaLibrary : public Screen { struct SearchConstraints { + SearchConstraints(const std::string &artist, const std::string &album, const std::string &year) : Artist(artist), Album(album), Year(year) { } SearchConstraints(const std::string &album, const std::string &year) : Album(album), Year(year) { } + std::string Artist; std::string Album; std::string Year; }; @@ -57,6 +59,7 @@ class MediaLibrary : public Screen virtual List *GetList(); + int Columns() { return hasTwoColumns ? 2 : 3; } void NextColumn(); void PrevColumn(); @@ -72,6 +75,7 @@ class MediaLibrary : public Screen static bool SortSongsByTrack(MPD::Song *, MPD::Song *); static bool SortSongsByYear(MPD::Song *, MPD::Song *); + static bool hasTwoColumns; static size_t itsLeftColWidth; static size_t itsMiddleColWidth; static size_t itsMiddleColStartX; diff --git a/src/ncmpcpp.cpp b/src/ncmpcpp.cpp index 7373fffe..2daf8bcd 100644 --- a/src/ncmpcpp.cpp +++ b/src/ncmpcpp.cpp @@ -1664,7 +1664,8 @@ int main(int argc, char *argv[]) { myBrowser->ChangeBrowseMode(); } - else if (myScreen->ActiveWindow() == myLibrary->Artists) + else if (myScreen->ActiveWindow() == myLibrary->Artists + || (myLibrary->Columns() == 2 && myScreen->ActiveWindow() == myLibrary->Albums)) { LockStatusbar(); Statusbar() << "Tag type ? [" << fmtBold << 'a' << fmtBoldEnd << "rtist/" << fmtBold << 'y' << fmtBoldEnd << "ear/" << fmtBold << 'g' << fmtBoldEnd << "enre/" << fmtBold << 'c' << fmtBoldEnd << "omposer/" << fmtBold << 'p' << fmtBoldEnd << "erformer] "; @@ -1685,9 +1686,20 @@ int main(int argc, char *argv[]) string item_type = IntoStr(Config.media_lib_primary_tag); myLibrary->Artists->SetTitle(item_type + "s"); myLibrary->Artists->Reset(); - myLibrary->Artists->Clear(0); - myLibrary->Artists->Display(); ToLower(item_type); + if (myLibrary->Columns() == 2) + { + myLibrary->Songs->Clear(0); + myLibrary->Albums->Reset(); + myLibrary->Albums->Clear(); + myLibrary->Albums->SetTitle("Albums (sorted by " + item_type + ")"); + myLibrary->Albums->Display(); + } + else + { + myLibrary->Artists->Clear(0); + myLibrary->Artists->Display(); + } ShowMessage("Switched to list of %s tag", item_type.c_str()); } } diff --git a/src/status.cpp b/src/status.cpp index cc65a023..a07d90b8 100644 --- a/src/status.cpp +++ b/src/status.cpp @@ -287,7 +287,13 @@ void NcmpcppStatusChanged(Connection *Mpd, StatusChanges changed, void *) myTagEditor->Albums->Clear(0); myTagEditor->Dirs->Clear(0); # endif // HAVE_TAGLIB_H - myLibrary->Artists->Clear(0); + if (myLibrary->Columns() == 2) + { + myLibrary->Albums->Clear(); + myLibrary->Songs->Clear(0); + } + else + myLibrary->Artists->Clear(0); myPlaylistEditor->Content->Clear(0); } if (changed.PlayerState)