From 5e8d1673e014e5d9af4c5538ae938d7c414a2ed3 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Sun, 2 Sep 2012 20:51:20 +0200 Subject: [PATCH] implement ProxySongList for handling general operations on lists --- src/Makefile.am | 1 + src/actions.cpp | 183 +++++++++++++++++++++++++----------------------- src/actions.h | 4 ++ src/browser.cpp | 15 ++-- src/browser.h | 3 +- src/display.cpp | 4 +- src/helpers.h | 18 ++++- src/interfaces.h | 7 +- src/lyrics.cpp | 34 +++++---- src/media_library.cpp | 26 ++----- src/media_library.h | 4 +- src/mpdpp.cpp | 2 +- src/playlist.cpp | 15 ++-- src/playlist.h | 2 +- src/playlist_editor.cpp | 24 ++----- src/playlist_editor.h | 4 +- src/proxy_song_list.h | 110 +++++++++++++++++++++++++++++ src/search_engine.cpp | 26 ++----- src/search_engine.h | 4 +- src/song_info.cpp | 5 +- src/tag_editor.cpp | 22 ++---- src/tag_editor.h | 4 +- 22 files changed, 297 insertions(+), 220 deletions(-) create mode 100644 src/proxy_song_list.h diff --git a/src/Makefile.am b/src/Makefile.am index 43b1235..46caf2d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,6 +72,7 @@ noinst_HEADERS = \ mutable_song.h \ outputs.h \ playlist_editor.h \ + proxy_song_list.h \ regex_filter.h \ regexes.h \ screen.h \ diff --git a/src/actions.cpp b/src/actions.cpp index 0562202..a1ef162 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -508,84 +508,96 @@ void ScrollDown::Run() ListsChangeFinisher(); } +bool ScrollUpArtist::canBeRun() const +{ + return proxySongList(myScreen).get(); +} + void ScrollUpArtist::Run() { - // FIXME - /*List *mList = myScreen->GetList(); - if (!mList || mList->Empty()) - return; - size_t pos = mList->Choice(); - if (MPD::Song *s = myScreen->GetSong(pos)) + auto pl = proxySongList(myScreen); + assert(pl); + size_t pos = pl->choice(); + if (MPD::Song *s = pl->getSong(pos)) { std::string artist = s->getArtist(); while (pos > 0) { - s = myScreen->GetSong(--pos); - myScreen->Scroll(wUp); + s = pl->getSong(--pos); if (!s || s->getArtist() != artist) break; } - }*/ + pl->highlight(pos); + } +} + +bool ScrollUpAlbum::canBeRun() const +{ + return proxySongList(myScreen).get(); } void ScrollUpAlbum::Run() { - // FIXME - /*List *mList = myScreen->GetList(); - if (!mList || mList->Empty()) - return; - size_t pos = mList->Choice(); - if (MPD::Song *s = myScreen->GetSong(pos)) + auto pl = proxySongList(myScreen); + assert(pl); + size_t pos = pl->choice(); + if (MPD::Song *s = pl->getSong(pos)) { std::string album = s->getAlbum(); while (pos > 0) { - s = myScreen->GetSong(--pos); - myScreen->Scroll(wUp); + s = pl->getSong(--pos); if (!s || s->getAlbum() != album) break; } - }*/ + pl->highlight(pos); + } +} + +bool ScrollDownArtist::canBeRun() const +{ + return proxySongList(myScreen).get(); } void ScrollDownArtist::Run() { - // FIXME - /*List *mList = myScreen->GetList(); - if (!mList || mList->Empty()) - return; - size_t pos = mList->Choice(); - if (MPD::Song *s = myScreen->GetSong(pos)) + auto pl = proxySongList(myScreen); + assert(pl); + size_t pos = pl->choice(); + if (MPD::Song *s = pl->getSong(pos)) { std::string artist = s->getArtist(); - while (pos < mList->Size() - 1) + while (pos < pl->size() - 1) { - s = myScreen->GetSong(++pos); - myScreen->Scroll(wDown); + s = pl->getSong(++pos); if (!s || s->getArtist() != artist) break; } - }*/ + pl->highlight(pos); + } +} + +bool ScrollDownAlbum::canBeRun() const +{ + return proxySongList(myScreen).get(); } void ScrollDownAlbum::Run() { - // FIXME - /*List *mList = myScreen->GetList(); - if (!mList || mList->Empty()) - return; - size_t pos = mList->Choice(); - if (MPD::Song *s = myScreen->GetSong(pos)) + auto pl = proxySongList(myScreen); + assert(pl); + size_t pos = pl->choice(); + if (MPD::Song *s = pl->getSong(pos)) { std::string album = s->getAlbum(); - while (pos < mList->Size() - 1) + while (pos < pl->size() - 1) { - s = myScreen->GetSong(++pos); - myScreen->Scroll(wDown); + s = pl->getSong(++pos); if (!s || s->getAlbum() != album) break; } - }*/ + pl->highlight(pos); + } } void PageUp::Run() @@ -1384,8 +1396,7 @@ void SetCrossfade::Run() bool EditSong::canBeRun() const { # ifdef HAVE_TAGLIB_H - auto w = dynamic_cast(myScreen); - return w && w->currentSong(); + return currentSong(myScreen); # else return false; # endif // HAVE_TAGLIB_H @@ -1396,9 +1407,7 @@ void EditSong::Run() # ifdef HAVE_TAGLIB_H if (!isMPDMusicDirSet()) return; - auto w = dynamic_cast(myScreen); - assert(w); - auto s = w->currentSong(); + auto s = currentSong(myScreen); assert(s); myTinyTagEditor->SetEdited(*s); myTinyTagEditor->SwitchTo(); @@ -1641,29 +1650,24 @@ void EditLyrics::Run() bool JumpToBrowser::canBeRun() const { - auto w = dynamic_cast(myScreen); - return w && w->currentSong(); + return currentSong(myScreen); } void JumpToBrowser::Run() { - auto w = dynamic_cast(myScreen); - auto s = w->currentSong(); + auto s = currentSong(myScreen); assert(s); myBrowser->LocateSong(*s); } bool JumpToMediaLibrary::canBeRun() const { - auto w = dynamic_cast(myScreen); - return w && w->currentSong(); + return currentSong(myScreen); } void JumpToMediaLibrary::Run() { - auto w = dynamic_cast(myScreen); - assert(w); - auto s = w->currentSong(); + auto s = currentSong(myScreen); assert(s); myLibrary->LocateSong(*s); } @@ -1719,8 +1723,7 @@ void ToggleScreenLock::Run() bool JumpToTagEditor::canBeRun() const { # ifdef HAVE_TAGLIB_H - auto w = dynamic_cast(myScreen); - return w && w->currentSong(); + return currentSong(myScreen); # else return false; # endif // HAVE_TAGLIB_H @@ -1731,9 +1734,7 @@ void JumpToTagEditor::Run() # ifdef HAVE_TAGLIB_H if (!isMPDMusicDirSet()) return; - auto w = dynamic_cast(myScreen); - assert(w); - auto s = w->currentSong(); + auto s = currentSong(myScreen); assert(s); myTagEditor->LocateSong(*s); # endif // HAVE_TAGLIB_H @@ -1794,13 +1795,13 @@ void JumpToPositionInSong::Run() bool ReverseSelection::canBeRun() const { - auto w = dynamic_cast(myScreen); + auto w = hasSongs(myScreen); return w && w->allowsSelection(); } void ReverseSelection::Run() { - auto w = dynamic_cast(myScreen); + auto w = hasSongs(myScreen); assert(w); w->reverseSelection(); ShowMessage("Selection reversed"); @@ -1808,58 +1809,54 @@ void ReverseSelection::Run() bool DeselectItems::canBeRun() const { - auto w = dynamic_cast(myScreen); - return w && w->allowsSelection(); + return proxySongList(myScreen).get(); } void DeselectItems::Run() { - auto w = dynamic_cast(myScreen); - assert(w); - w->removeSelection(); + auto pl = proxySongList(myScreen); + assert(pl); + for (size_t i = 0; i < pl->size(); ++i) + pl->setSelected(i, false); } bool SelectAlbum::canBeRun() const { - auto w = dynamic_cast(myScreen); - return w && w->allowsSelection() - && myScreen->GetList(); + auto w = hasSongs(myScreen); + return w && w->allowsSelection() && w->getProxySongList().get(); } void SelectAlbum::Run() { - // FIXME - /*List *mList = myScreen->GetList(); - assert(mList); - size_t pos = mList->Choice(); - if (MPD::Song *s = myScreen->GetSong(pos)) + auto pl = proxySongList(myScreen); + assert(pl); + size_t pos = pl->choice(); + if (MPD::Song *s = pl->getSong(pos)) { std::string album = s->getAlbum(); - // select song under cursor - mList->Select(pos, 1); + pl->setSelected(pos, true); // go up while (pos > 0) { - s = myScreen->GetSong(--pos); + s = pl->getSong(--pos); if (!s || s->getAlbum() != album) break; else - mList->Select(pos, 1); + pl->setSelected(pos, true); } // go down - pos = mList->Choice(); - while (pos < mList->Size() - 1) + pos = pl->choice(); + while (pos < pl->size() - 1) { - s = myScreen->GetSong(++pos); + s = pl->getSong(++pos); if (!s || s->getAlbum() != album) break; else - mList->Select(pos, 1); + pl->setSelected(pos, true); } ShowMessage("Album around cursor position selected"); } - */ } void AddSelectedItems::Run() @@ -2354,7 +2351,11 @@ void ShowSongInfo::Run() bool ShowArtistInfo::canBeRun() const { #ifdef HAVE_CURL_CURL_H - return myScreen == myLastfm || dynamic_cast(myScreen); + return myScreen == myLastfm + || (myScreen->ActiveWindow() == myLibrary->Tags + && !myLibrary->Tags->Empty() + && Config.media_lib_primary_tag == MPD_TAG_ARTIST) + || currentSong(myScreen); # else return false; # endif // NOT HAVE_CURL_CURL_H @@ -2370,14 +2371,18 @@ void ShowArtistInfo::Run() } std::string artist; - auto hs = dynamic_cast(myScreen); - assert(hs); - auto s = hs->currentSong(); - - if (s) - artist = s->getArtist(); - else if (myScreen == myLibrary && myLibrary->Main() == myLibrary->Tags && !myLibrary->Tags->Empty()) + if (myScreen->ActiveWindow() == myLibrary->Tags) + { + assert(!myLibrary->Tags->Empty()); + assert(Config.media_lib_primary_tag == MPD_TAG_ARTIST); artist = myLibrary->Tags->Current().value(); + } + else + { + auto s = currentSong(myScreen); + assert(s); + artist = s->getArtist(); + } if (!artist.empty() && myLastfm->SetArtistInfoArgs(artist, Config.lastfm_preferred_language)) myLastfm->SwitchTo(); diff --git a/src/actions.h b/src/actions.h index fe46444..2b6118f 100644 --- a/src/actions.h +++ b/src/actions.h @@ -168,24 +168,28 @@ struct ScrollDown : public Action struct ScrollUpArtist : public Action { ScrollUpArtist() : Action(aScrollUpArtist, "scroll_up_artist") { } + virtual bool canBeRun() const; virtual void Run(); }; struct ScrollUpAlbum : public Action { ScrollUpAlbum() : Action(aScrollUpAlbum, "scroll_up_album") { } + virtual bool canBeRun() const; virtual void Run(); }; struct ScrollDownArtist : public Action { ScrollDownArtist() : Action(aScrollDownArtist, "scroll_down_artist") { } + virtual bool canBeRun() const; virtual void Run(); }; struct ScrollDownAlbum : public Action { ScrollDownAlbum() : Action(aScrollDownAlbum, "scroll_down_album") { } + virtual bool canBeRun() const; virtual void Run(); }; diff --git a/src/browser.cpp b/src/browser.cpp index 5722446..f17a536 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -301,6 +301,16 @@ void Browser::prevFound(bool wrap) /***********************************************************************/ +std::shared_ptr Browser::getProxySongList() +{ + return mkProxySongList(*w, [](NC::Menu::Item &item) { + MPD::Song *ptr = 0; + if (item.value().type == itSong) + ptr = item.value().song.get(); + return ptr; + }); +} + MPD::Song *Browser::getSong(size_t pos) { MPD::Song *ptr = 0; @@ -322,11 +332,6 @@ bool Browser::allowsSelection() return true; } -void Browser::removeSelection() -{ - removeSelectionHelper(w->Begin(), w->End()); -} - void Browser::reverseSelection() { reverseSelectionHelper(w->Begin()+(itsBrowsedDir == "/" ? 0 : 1), w->End()); diff --git a/src/browser.h b/src/browser.h index 6926218..9affe26 100644 --- a/src/browser.h +++ b/src/browser.h @@ -22,6 +22,7 @@ #define _BROWSER_H #include "interfaces.h" +#include "mpdpp.h" #include "screen.h" class Browser : public Screen< NC::Menu >, public Filterable, public HasSongs, public Searchable @@ -51,10 +52,10 @@ class Browser : public Screen< NC::Menu >, public Filterable, public /// HasSongs implementation virtual MPD::Song *getSong(size_t pos); virtual MPD::Song *currentSong(); + virtual std::shared_ptr getProxySongList(); virtual bool allowsSelection(); virtual void reverseSelection(); - virtual void removeSelection(); virtual MPD::SongList getSelectedSongs(); virtual NC::List *GetList() { return w; } diff --git a/src/display.cpp b/src/display.cpp index f60fe8a..e2329a9 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -79,7 +79,9 @@ void setProperties(NC::Menu &menu, const MPD::Song &s, HasSongs &screen, bool separate_albums = false; if (Config.playlist_separate_albums) { - auto next = screen.getSong(menu.DrawnPosition()+1); + auto pl = screen.getProxySongList(); + assert(pl); + auto next = pl->getSong(menu.DrawnPosition()+1); if (next && next->getAlbum() != s.getAlbum()) separate_albums = true; } diff --git a/src/helpers.h b/src/helpers.h index be3be6e..02f6330 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -32,10 +32,22 @@ inline HasSongs *hasSongs(BasicScreen *screen) return dynamic_cast(screen); } -template void removeSelectionHelper(Iterator first, Iterator last) +inline std::shared_ptr proxySongList(BasicScreen *screen) { - for (; first != last; ++first) - first->setSelected(false); + auto ptr = nullProxySongList(); + auto hs = hasSongs(screen); + if (hs) + ptr = hs->getProxySongList(); + return ptr; +} + +inline MPD::Song *currentSong(BasicScreen *screen) +{ + MPD::Song *ptr = 0; + auto pl = proxySongList(screen); + if (pl) + ptr = pl->currentSong(); + return ptr; } template void reverseSelectionHelper(Iterator first, Iterator last) diff --git a/src/interfaces.h b/src/interfaces.h index 2aa9c44..eb7c301 100644 --- a/src/interfaces.h +++ b/src/interfaces.h @@ -22,8 +22,9 @@ #define _INTERFACES_H #include -#include "mpdpp.h" #include "gcc.h" +#include "song.h" +#include "proxy_song_list.h" struct Filterable { @@ -40,12 +41,10 @@ struct Searchable struct HasSongs { - virtual MPD::Song *getSong(size_t pos) = 0; - virtual MPD::Song *currentSong() = 0; + virtual std::shared_ptr getProxySongList() = 0; virtual bool allowsSelection() = 0; virtual void reverseSelection() = 0; - virtual void removeSelection() = 0; virtual MPD::SongList getSelectedSongs() = 0; }; diff --git a/src/lyrics.cpp b/src/lyrics.cpp index aa88e61..5d85bb1 100644 --- a/src/lyrics.cpp +++ b/src/lyrics.cpp @@ -117,28 +117,26 @@ void Lyrics::SwitchTo() } # endif // HAVE_CURL_CURL_H - auto hs = dynamic_cast(myScreen); - if (!hs) + const MPD::Song *s = currentSong(myScreen); + if (!s) return; - if (const MPD::Song *s = hs->currentSong()) + if (!s->getArtist().empty() && !s->getTitle().empty()) { - if (!s->getArtist().empty() && !s->getTitle().empty()) - { - myOldScreen = myScreen; - myScreen = this; - - itsSong = *s; - Load(); - - Global::RedrawHeader = true; - } - else - { - ShowMessage("Song must have both artist and title tag set"); - return; - } + myOldScreen = myScreen; + myScreen = this; + + itsSong = *s; + Load(); + + Global::RedrawHeader = true; } + else + { + ShowMessage("Song must have both artist and title tag set"); + return; + } + // if we resize for locked screen, we have to do that in the end since // fetching lyrics may fail (eg. if tags are missing) and we don't want // to adjust screen size then. diff --git a/src/media_library.cpp b/src/media_library.cpp index 33c4405..9a0800c 100644 --- a/src/media_library.cpp +++ b/src/media_library.cpp @@ -531,37 +531,21 @@ void MediaLibrary::prevFound(bool wrap) /***********************************************************************/ -MPD::Song *MediaLibrary::getSong(size_t pos) +std::shared_ptr MediaLibrary::getProxySongList() { - MPD::Song *ptr = 0; + auto ptr = nullProxySongList(); if (w == Songs) - ptr = &(*Songs)[pos].value(); + ptr = mkProxySongList(*Songs, [](NC::Menu::Item &item) { + return &item.value(); + }); return ptr; } -MPD::Song *MediaLibrary::currentSong() -{ - if (w == Songs && !Songs->Empty()) - return getSong(Songs->Choice()); - else - return 0; -} - bool MediaLibrary::allowsSelection() { return true; } -void MediaLibrary::removeSelection() -{ - if (w == Tags) - removeSelectionHelper(Tags->Begin(), Tags->End()); - else if (w == Albums) - removeSelectionHelper(Albums->Begin(), Albums->End()); - else if (w == Songs) - removeSelectionHelper(Songs->Begin(), Songs->End()); -} - void MediaLibrary::reverseSelection() { if (w == Tags) diff --git a/src/media_library.h b/src/media_library.h index 1afd0b4..0401950 100644 --- a/src/media_library.h +++ b/src/media_library.h @@ -50,12 +50,10 @@ class MediaLibrary : public Screen, public Filterable, public HasSon virtual void prevFound(bool wrap); /// HasSongs implementation - virtual MPD::Song *getSong(size_t pos); - virtual MPD::Song *currentSong(); + virtual std::shared_ptr getProxySongList(); virtual bool allowsSelection(); virtual void reverseSelection(); - virtual void removeSelection(); virtual MPD::SongList getSelectedSongs(); virtual NC::List *GetList(); diff --git a/src/mpdpp.cpp b/src/mpdpp.cpp index a4340d5..e810400 100644 --- a/src/mpdpp.cpp +++ b/src/mpdpp.cpp @@ -1193,7 +1193,7 @@ MPD::ItemList MPD::Connection::GetDirectory(const std::string &path) it.type = itDirectory; break; case MPD_ENTITY_TYPE_SONG: - it.song = std::shared_ptr(new Song(mpd_song_dup(mpd_entity_get_song(item)))); + it.song = std::make_shared(Song(mpd_song_dup(mpd_entity_get_song(item)))); it.type = itSong; break; case MPD_ENTITY_TYPE_PLAYLIST: diff --git a/src/playlist.cpp b/src/playlist.cpp index cedace8..89b522b 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -318,6 +318,16 @@ void Playlist::prevFound(bool wrap) /***********************************************************************/ +std::shared_ptr Playlist::getProxySongList() +{ + auto ptr = nullProxySongList(); + if (w == Items) + ptr = mkProxySongList(*Items, [](NC::Menu::Item &item) { + return &item.value(); + }); + return ptr; +} + MPD::Song *Playlist::getSong(size_t pos) { MPD::Song *ptr = 0; @@ -339,11 +349,6 @@ bool Playlist::allowsSelection() return w == Items; } -void Playlist::removeSelection() -{ - removeSelectionHelper(Items->Begin(), Items->End()); -} - void Playlist::reverseSelection() { reverseSelectionHelper(Items->Begin(), Items->End()); diff --git a/src/playlist.h b/src/playlist.h index 4c65d3a..4702953 100644 --- a/src/playlist.h +++ b/src/playlist.h @@ -55,10 +55,10 @@ class Playlist : public Screen, public Filterable, public HasSongs, /// HasSongs implementation virtual MPD::Song *getSong(size_t pos); virtual MPD::Song *currentSong(); + virtual std::shared_ptr getProxySongList(); virtual bool allowsSelection(); virtual void reverseSelection(); - virtual void removeSelection(); virtual MPD::SongList getSelectedSongs(); virtual NC::List *GetList() { return w == Items ? Items : 0; } diff --git a/src/playlist_editor.cpp b/src/playlist_editor.cpp index e3aa4ef..f98ac26 100644 --- a/src/playlist_editor.cpp +++ b/src/playlist_editor.cpp @@ -486,35 +486,21 @@ void PlaylistEditor::prevFound(bool wrap) /***********************************************************************/ -MPD::Song *PlaylistEditor::getSong(size_t pos) +std::shared_ptr PlaylistEditor::getProxySongList() { - MPD::Song *ptr = 0; + auto ptr = nullProxySongList(); if (w == Content) - ptr = &(*Content)[pos].value(); + ptr = mkProxySongList(*Content, [](NC::Menu::Item &item) { + return &item.value(); + }); return ptr; } -MPD::Song *PlaylistEditor::currentSong() -{ - if (w == Content && !Content->Empty()) - return getSong(Content->Choice()); - else - return 0; -} - bool PlaylistEditor::allowsSelection() { return true; } -void PlaylistEditor::removeSelection() -{ - if (w == Playlists) - removeSelectionHelper(Playlists->Begin(), Playlists->End()); - else if (w == Content) - removeSelectionHelper(Content->Begin(), Content->End()); -} - void PlaylistEditor::reverseSelection() { if (w == Playlists) diff --git a/src/playlist_editor.h b/src/playlist_editor.h index 256c4f2..1afb62d 100644 --- a/src/playlist_editor.h +++ b/src/playlist_editor.h @@ -49,12 +49,10 @@ class PlaylistEditor : public Screen, public Filterable, public HasS virtual void prevFound(bool wrap); /// HasSongs implementation - virtual MPD::Song *getSong(size_t pos); - virtual MPD::Song *currentSong(); + virtual std::shared_ptr getProxySongList(); virtual bool allowsSelection(); virtual void reverseSelection(); - virtual void removeSelection(); virtual MPD::SongList getSelectedSongs(); virtual void Locate(const std::string &); diff --git a/src/proxy_song_list.h b/src/proxy_song_list.h new file mode 100644 index 0000000..3364427 --- /dev/null +++ b/src/proxy_song_list.h @@ -0,0 +1,110 @@ +/*************************************************************************** + * Copyright (C) 2008-2012 by Andrzej Rybczak * + * electricityispower@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef _PROXY_SONG_LIST +#define _PROXY_SONG_LIST + +#include "menu.h" +#include "song.h" + +class ProxySongList +{ + struct Interface + { + virtual ~Interface() { } + + virtual bool empty() = 0; + virtual size_t size() = 0; + virtual size_t choice() = 0; + virtual void highlight(size_t pos) = 0; + + virtual bool isSelected(size_t pos) = 0; + virtual void setSelected(size_t pos, bool selected) = 0; + + virtual MPD::Song *getSong(size_t pos) = 0; + virtual MPD::Song *currentSong() = 0; + }; + + template struct Impl : Interface + { + typedef typename NC::Menu Menu; + + Impl(Menu &menu, F f) : m_menu(menu), m_song_getter(f) { } + virtual ~Impl() { } + + virtual bool empty() { return m_menu.Empty(); } + virtual size_t size() { return m_menu.Size(); } + virtual size_t choice() { return m_menu.Choice(); } + virtual void highlight(size_t pos) { m_menu.Highlight(pos); } + + virtual bool isSelected(size_t pos) { + return m_menu[pos].isSelected(); + } + + virtual void setSelected(size_t pos, bool selected) { + m_menu[pos].setSelected(selected); + } + + virtual MPD::Song *getSong(size_t pos) { + return m_song_getter(m_menu[pos]); + } + + virtual MPD::Song *currentSong() { + if (!m_menu.Empty()) + return getSong(m_menu.Choice()); + else + return 0; + } + + private: + Menu &m_menu; + F m_song_getter; + }; + + std::shared_ptr m_impl; + +public: + template + ProxySongList(typename NC::Menu &menu, F f) : m_impl(new Impl(menu, f)) { } + + bool empty() { return m_impl->empty(); } + size_t size() { return m_impl->size(); } + size_t choice() { return m_impl->choice(); } + void highlight(size_t pos) { m_impl->highlight(pos); } + + bool isSelected(size_t pos) { return m_impl->isSelected(pos); } + void setSelected(size_t pos, bool selected) { m_impl->setSelected(pos, selected); } + + MPD::Song *getSong(size_t pos) { return m_impl->getSong(pos); } + MPD::Song *currentSong() { return m_impl->currentSong(); } +}; + +template +std::shared_ptr mkProxySongList(typename NC::Menu &menu, F f) +{ + return std::make_shared(ProxySongList(menu, f)); +} + +inline std::shared_ptr nullProxySongList() +{ + return std::shared_ptr(); +} + +#endif diff --git a/src/search_engine.cpp b/src/search_engine.cpp index 70146c1..4247b37 100644 --- a/src/search_engine.cpp +++ b/src/search_engine.cpp @@ -314,21 +314,14 @@ void SearchEngine::prevFound(bool wrap) /***********************************************************************/ -MPD::Song *SearchEngine::getSong(size_t pos) +std::shared_ptr< ProxySongList > SearchEngine::getProxySongList() { - MPD::Song *ptr = 0; - auto &item = (*w)[pos]; - if (!item.isSeparator() && item.value().isSong()) - ptr = &item.value().song(); - return ptr; -} - -MPD::Song *SearchEngine::currentSong() -{ - if (w->Empty()) - return 0; - else - return getSong(w->Choice()); + return mkProxySongList(*w, [](NC::Menu::Item &item) { + MPD::Song *ptr = 0; + if (!item.isSeparator() && item.value().isSong()) + ptr = &item.value().song(); + return ptr; + }); } bool SearchEngine::allowsSelection() @@ -336,11 +329,6 @@ bool SearchEngine::allowsSelection() return w->Current().value().isSong(); } -void SearchEngine::removeSelection() -{ - removeSelectionHelper(w->Begin(), w->End()); -} - void SearchEngine::reverseSelection() { reverseSelectionHelper(w->Begin()+std::min(StaticOptions, w->Size()), w->End()); diff --git a/src/search_engine.h b/src/search_engine.h index bdff33e..fae889a 100644 --- a/src/search_engine.h +++ b/src/search_engine.h @@ -96,12 +96,10 @@ class SearchEngine : public Screen< NC::Menu >, public Filterable, publi virtual void prevFound(bool wrap); /// HasSongs implementation - virtual MPD::Song *getSong(size_t pos); - virtual MPD::Song *currentSong(); + virtual std::shared_ptr getProxySongList(); virtual bool allowsSelection(); virtual void reverseSelection(); - virtual void removeSelection(); virtual MPD::SongList getSelectedSongs(); virtual NC::List *GetList() { return w->Size() >= StaticOptions ? w : 0; } diff --git a/src/song_info.cpp b/src/song_info.cpp index 6ff4909..3bd2726 100644 --- a/src/song_info.cpp +++ b/src/song_info.cpp @@ -84,10 +84,7 @@ void SongInfo::SwitchTo() if (myLockedScreen) UpdateInactiveScreen(this); - auto hs = dynamic_cast(myScreen); - if (!hs) - return; - auto s = hs->currentSong(); + auto s = currentSong(myScreen); if (!s) return; diff --git a/src/tag_editor.cpp b/src/tag_editor.cpp index 1450643..91a817f 100644 --- a/src/tag_editor.cpp +++ b/src/tag_editor.cpp @@ -854,33 +854,21 @@ void TagEditor::prevFound(bool wrap) /***********************************************************************/ -MPD::Song *TagEditor::getSong(size_t pos) +std::shared_ptr TagEditor::getProxySongList() { - MPD::Song *ptr = 0; + auto ptr = nullProxySongList(); if (w == Tags) - ptr = &(*Tags)[pos].value(); + ptr = mkProxySongList(*Tags, [](NC::Menu::Item &item) { + return &item.value(); + }); return ptr; } -MPD::Song *TagEditor::currentSong() -{ - if (w == Tags && !Tags->Empty()) - return getSong(Tags->Choice()); - else - return 0; -} - bool TagEditor::allowsSelection() { return w == Tags; } -void TagEditor::removeSelection() -{ - if (w == Tags) - removeSelectionHelper(Tags->Begin(), Tags->End()); -} - void TagEditor::reverseSelection() { if (w == Tags) diff --git a/src/tag_editor.h b/src/tag_editor.h index 56f0b66..a62c3e8 100644 --- a/src/tag_editor.h +++ b/src/tag_editor.h @@ -61,12 +61,10 @@ class TagEditor : public Screen, public Filterable, public HasSongs, virtual void prevFound(bool wrap); /// HasSongs implementation - virtual MPD::Song *getSong(size_t pos); - virtual MPD::Song *currentSong(); + virtual std::shared_ptr getProxySongList(); virtual bool allowsSelection(); virtual void reverseSelection(); - virtual void removeSelection(); virtual MPD::SongList getSelectedSongs(); virtual NC::List *GetList(); -- 2.11.4.GIT