implement ProxySongList for handling general operations on lists

This commit is contained in:
Andrzej Rybczak
2012-09-02 20:51:20 +02:00
parent 0cfe5d8f01
commit 5e8d1673e0
22 changed files with 297 additions and 220 deletions

View File

@@ -72,6 +72,7 @@ noinst_HEADERS = \
mutable_song.h \ mutable_song.h \
outputs.h \ outputs.h \
playlist_editor.h \ playlist_editor.h \
proxy_song_list.h \
regex_filter.h \ regex_filter.h \
regexes.h \ regexes.h \
screen.h \ screen.h \

View File

@@ -508,84 +508,96 @@ void ScrollDown::Run()
ListsChangeFinisher(); ListsChangeFinisher();
} }
bool ScrollUpArtist::canBeRun() const
{
return proxySongList(myScreen).get();
}
void ScrollUpArtist::Run() void ScrollUpArtist::Run()
{ {
// FIXME auto pl = proxySongList(myScreen);
/*List *mList = myScreen->GetList(); assert(pl);
if (!mList || mList->Empty()) size_t pos = pl->choice();
return; if (MPD::Song *s = pl->getSong(pos))
size_t pos = mList->Choice();
if (MPD::Song *s = myScreen->GetSong(pos))
{ {
std::string artist = s->getArtist(); std::string artist = s->getArtist();
while (pos > 0) while (pos > 0)
{ {
s = myScreen->GetSong(--pos); s = pl->getSong(--pos);
myScreen->Scroll(wUp);
if (!s || s->getArtist() != artist) if (!s || s->getArtist() != artist)
break; break;
} }
}*/ pl->highlight(pos);
}
}
bool ScrollUpAlbum::canBeRun() const
{
return proxySongList(myScreen).get();
} }
void ScrollUpAlbum::Run() void ScrollUpAlbum::Run()
{ {
// FIXME auto pl = proxySongList(myScreen);
/*List *mList = myScreen->GetList(); assert(pl);
if (!mList || mList->Empty()) size_t pos = pl->choice();
return; if (MPD::Song *s = pl->getSong(pos))
size_t pos = mList->Choice();
if (MPD::Song *s = myScreen->GetSong(pos))
{ {
std::string album = s->getAlbum(); std::string album = s->getAlbum();
while (pos > 0) while (pos > 0)
{ {
s = myScreen->GetSong(--pos); s = pl->getSong(--pos);
myScreen->Scroll(wUp);
if (!s || s->getAlbum() != album) if (!s || s->getAlbum() != album)
break; break;
} }
}*/ pl->highlight(pos);
}
}
bool ScrollDownArtist::canBeRun() const
{
return proxySongList(myScreen).get();
} }
void ScrollDownArtist::Run() void ScrollDownArtist::Run()
{ {
// FIXME auto pl = proxySongList(myScreen);
/*List *mList = myScreen->GetList(); assert(pl);
if (!mList || mList->Empty()) size_t pos = pl->choice();
return; if (MPD::Song *s = pl->getSong(pos))
size_t pos = mList->Choice();
if (MPD::Song *s = myScreen->GetSong(pos))
{ {
std::string artist = s->getArtist(); std::string artist = s->getArtist();
while (pos < mList->Size() - 1) while (pos < pl->size() - 1)
{ {
s = myScreen->GetSong(++pos); s = pl->getSong(++pos);
myScreen->Scroll(wDown);
if (!s || s->getArtist() != artist) if (!s || s->getArtist() != artist)
break; break;
} }
}*/ pl->highlight(pos);
}
}
bool ScrollDownAlbum::canBeRun() const
{
return proxySongList(myScreen).get();
} }
void ScrollDownAlbum::Run() void ScrollDownAlbum::Run()
{ {
// FIXME auto pl = proxySongList(myScreen);
/*List *mList = myScreen->GetList(); assert(pl);
if (!mList || mList->Empty()) size_t pos = pl->choice();
return; if (MPD::Song *s = pl->getSong(pos))
size_t pos = mList->Choice();
if (MPD::Song *s = myScreen->GetSong(pos))
{ {
std::string album = s->getAlbum(); std::string album = s->getAlbum();
while (pos < mList->Size() - 1) while (pos < pl->size() - 1)
{ {
s = myScreen->GetSong(++pos); s = pl->getSong(++pos);
myScreen->Scroll(wDown);
if (!s || s->getAlbum() != album) if (!s || s->getAlbum() != album)
break; break;
} }
}*/ pl->highlight(pos);
}
} }
void PageUp::Run() void PageUp::Run()
@@ -1384,8 +1396,7 @@ void SetCrossfade::Run()
bool EditSong::canBeRun() const bool EditSong::canBeRun() const
{ {
# ifdef HAVE_TAGLIB_H # ifdef HAVE_TAGLIB_H
auto w = dynamic_cast<HasSongs *>(myScreen); return currentSong(myScreen);
return w && w->currentSong();
# else # else
return false; return false;
# endif // HAVE_TAGLIB_H # endif // HAVE_TAGLIB_H
@@ -1396,9 +1407,7 @@ void EditSong::Run()
# ifdef HAVE_TAGLIB_H # ifdef HAVE_TAGLIB_H
if (!isMPDMusicDirSet()) if (!isMPDMusicDirSet())
return; return;
auto w = dynamic_cast<HasSongs *>(myScreen); auto s = currentSong(myScreen);
assert(w);
auto s = w->currentSong();
assert(s); assert(s);
myTinyTagEditor->SetEdited(*s); myTinyTagEditor->SetEdited(*s);
myTinyTagEditor->SwitchTo(); myTinyTagEditor->SwitchTo();
@@ -1641,29 +1650,24 @@ void EditLyrics::Run()
bool JumpToBrowser::canBeRun() const bool JumpToBrowser::canBeRun() const
{ {
auto w = dynamic_cast<HasSongs *>(myScreen); return currentSong(myScreen);
return w && w->currentSong();
} }
void JumpToBrowser::Run() void JumpToBrowser::Run()
{ {
auto w = dynamic_cast<HasSongs *>(myScreen); auto s = currentSong(myScreen);
auto s = w->currentSong();
assert(s); assert(s);
myBrowser->LocateSong(*s); myBrowser->LocateSong(*s);
} }
bool JumpToMediaLibrary::canBeRun() const bool JumpToMediaLibrary::canBeRun() const
{ {
auto w = dynamic_cast<HasSongs *>(myScreen); return currentSong(myScreen);
return w && w->currentSong();
} }
void JumpToMediaLibrary::Run() void JumpToMediaLibrary::Run()
{ {
auto w = dynamic_cast<HasSongs *>(myScreen); auto s = currentSong(myScreen);
assert(w);
auto s = w->currentSong();
assert(s); assert(s);
myLibrary->LocateSong(*s); myLibrary->LocateSong(*s);
} }
@@ -1719,8 +1723,7 @@ void ToggleScreenLock::Run()
bool JumpToTagEditor::canBeRun() const bool JumpToTagEditor::canBeRun() const
{ {
# ifdef HAVE_TAGLIB_H # ifdef HAVE_TAGLIB_H
auto w = dynamic_cast<HasSongs *>(myScreen); return currentSong(myScreen);
return w && w->currentSong();
# else # else
return false; return false;
# endif // HAVE_TAGLIB_H # endif // HAVE_TAGLIB_H
@@ -1731,9 +1734,7 @@ void JumpToTagEditor::Run()
# ifdef HAVE_TAGLIB_H # ifdef HAVE_TAGLIB_H
if (!isMPDMusicDirSet()) if (!isMPDMusicDirSet())
return; return;
auto w = dynamic_cast<HasSongs *>(myScreen); auto s = currentSong(myScreen);
assert(w);
auto s = w->currentSong();
assert(s); assert(s);
myTagEditor->LocateSong(*s); myTagEditor->LocateSong(*s);
# endif // HAVE_TAGLIB_H # endif // HAVE_TAGLIB_H
@@ -1794,13 +1795,13 @@ void JumpToPositionInSong::Run()
bool ReverseSelection::canBeRun() const bool ReverseSelection::canBeRun() const
{ {
auto w = dynamic_cast<HasSongs *>(myScreen); auto w = hasSongs(myScreen);
return w && w->allowsSelection(); return w && w->allowsSelection();
} }
void ReverseSelection::Run() void ReverseSelection::Run()
{ {
auto w = dynamic_cast<HasSongs *>(myScreen); auto w = hasSongs(myScreen);
assert(w); assert(w);
w->reverseSelection(); w->reverseSelection();
ShowMessage("Selection reversed"); ShowMessage("Selection reversed");
@@ -1808,58 +1809,54 @@ void ReverseSelection::Run()
bool DeselectItems::canBeRun() const bool DeselectItems::canBeRun() const
{ {
auto w = dynamic_cast<HasSongs *>(myScreen); return proxySongList(myScreen).get();
return w && w->allowsSelection();
} }
void DeselectItems::Run() void DeselectItems::Run()
{ {
auto w = dynamic_cast<HasSongs *>(myScreen); auto pl = proxySongList(myScreen);
assert(w); assert(pl);
w->removeSelection(); for (size_t i = 0; i < pl->size(); ++i)
pl->setSelected(i, false);
} }
bool SelectAlbum::canBeRun() const bool SelectAlbum::canBeRun() const
{ {
auto w = dynamic_cast<HasSongs *>(myScreen); auto w = hasSongs(myScreen);
return w && w->allowsSelection() return w && w->allowsSelection() && w->getProxySongList().get();
&& myScreen->GetList();
} }
void SelectAlbum::Run() void SelectAlbum::Run()
{ {
// FIXME auto pl = proxySongList(myScreen);
/*List *mList = myScreen->GetList(); assert(pl);
assert(mList); size_t pos = pl->choice();
size_t pos = mList->Choice(); if (MPD::Song *s = pl->getSong(pos))
if (MPD::Song *s = myScreen->GetSong(pos))
{ {
std::string album = s->getAlbum(); std::string album = s->getAlbum();
// select song under cursor // select song under cursor
mList->Select(pos, 1); pl->setSelected(pos, true);
// go up // go up
while (pos > 0) while (pos > 0)
{ {
s = myScreen->GetSong(--pos); s = pl->getSong(--pos);
if (!s || s->getAlbum() != album) if (!s || s->getAlbum() != album)
break; break;
else else
mList->Select(pos, 1); pl->setSelected(pos, true);
} }
// go down // go down
pos = mList->Choice(); pos = pl->choice();
while (pos < mList->Size() - 1) while (pos < pl->size() - 1)
{ {
s = myScreen->GetSong(++pos); s = pl->getSong(++pos);
if (!s || s->getAlbum() != album) if (!s || s->getAlbum() != album)
break; break;
else else
mList->Select(pos, 1); pl->setSelected(pos, true);
} }
ShowMessage("Album around cursor position selected"); ShowMessage("Album around cursor position selected");
} }
*/
} }
void AddSelectedItems::Run() void AddSelectedItems::Run()
@@ -2354,7 +2351,11 @@ void ShowSongInfo::Run()
bool ShowArtistInfo::canBeRun() const bool ShowArtistInfo::canBeRun() const
{ {
#ifdef HAVE_CURL_CURL_H #ifdef HAVE_CURL_CURL_H
return myScreen == myLastfm || dynamic_cast<HasSongs *>(myScreen); return myScreen == myLastfm
|| (myScreen->ActiveWindow() == myLibrary->Tags
&& !myLibrary->Tags->Empty()
&& Config.media_lib_primary_tag == MPD_TAG_ARTIST)
|| currentSong(myScreen);
# else # else
return false; return false;
# endif // NOT HAVE_CURL_CURL_H # endif // NOT HAVE_CURL_CURL_H
@@ -2370,14 +2371,18 @@ void ShowArtistInfo::Run()
} }
std::string artist; std::string artist;
auto hs = dynamic_cast<HasSongs *>(myScreen); if (myScreen->ActiveWindow() == myLibrary->Tags)
assert(hs); {
auto s = hs->currentSong(); assert(!myLibrary->Tags->Empty());
assert(Config.media_lib_primary_tag == MPD_TAG_ARTIST);
if (s)
artist = s->getArtist();
else if (myScreen == myLibrary && myLibrary->Main() == myLibrary->Tags && !myLibrary->Tags->Empty())
artist = myLibrary->Tags->Current().value(); 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)) if (!artist.empty() && myLastfm->SetArtistInfoArgs(artist, Config.lastfm_preferred_language))
myLastfm->SwitchTo(); myLastfm->SwitchTo();

View File

@@ -168,24 +168,28 @@ struct ScrollDown : public Action
struct ScrollUpArtist : public Action struct ScrollUpArtist : public Action
{ {
ScrollUpArtist() : Action(aScrollUpArtist, "scroll_up_artist") { } ScrollUpArtist() : Action(aScrollUpArtist, "scroll_up_artist") { }
virtual bool canBeRun() const;
virtual void Run(); virtual void Run();
}; };
struct ScrollUpAlbum : public Action struct ScrollUpAlbum : public Action
{ {
ScrollUpAlbum() : Action(aScrollUpAlbum, "scroll_up_album") { } ScrollUpAlbum() : Action(aScrollUpAlbum, "scroll_up_album") { }
virtual bool canBeRun() const;
virtual void Run(); virtual void Run();
}; };
struct ScrollDownArtist : public Action struct ScrollDownArtist : public Action
{ {
ScrollDownArtist() : Action(aScrollDownArtist, "scroll_down_artist") { } ScrollDownArtist() : Action(aScrollDownArtist, "scroll_down_artist") { }
virtual bool canBeRun() const;
virtual void Run(); virtual void Run();
}; };
struct ScrollDownAlbum : public Action struct ScrollDownAlbum : public Action
{ {
ScrollDownAlbum() : Action(aScrollDownAlbum, "scroll_down_album") { } ScrollDownAlbum() : Action(aScrollDownAlbum, "scroll_down_album") { }
virtual bool canBeRun() const;
virtual void Run(); virtual void Run();
}; };

View File

@@ -301,6 +301,16 @@ void Browser::prevFound(bool wrap)
/***********************************************************************/ /***********************************************************************/
std::shared_ptr<ProxySongList> Browser::getProxySongList()
{
return mkProxySongList(*w, [](NC::Menu<MPD::Item>::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 *Browser::getSong(size_t pos)
{ {
MPD::Song *ptr = 0; MPD::Song *ptr = 0;
@@ -322,11 +332,6 @@ bool Browser::allowsSelection()
return true; return true;
} }
void Browser::removeSelection()
{
removeSelectionHelper(w->Begin(), w->End());
}
void Browser::reverseSelection() void Browser::reverseSelection()
{ {
reverseSelectionHelper(w->Begin()+(itsBrowsedDir == "/" ? 0 : 1), w->End()); reverseSelectionHelper(w->Begin()+(itsBrowsedDir == "/" ? 0 : 1), w->End());

View File

@@ -22,6 +22,7 @@
#define _BROWSER_H #define _BROWSER_H
#include "interfaces.h" #include "interfaces.h"
#include "mpdpp.h"
#include "screen.h" #include "screen.h"
class Browser : public Screen< NC::Menu<MPD::Item> >, public Filterable, public HasSongs, public Searchable class Browser : public Screen< NC::Menu<MPD::Item> >, public Filterable, public HasSongs, public Searchable
@@ -51,10 +52,10 @@ class Browser : public Screen< NC::Menu<MPD::Item> >, public Filterable, public
/// HasSongs implementation /// HasSongs implementation
virtual MPD::Song *getSong(size_t pos); virtual MPD::Song *getSong(size_t pos);
virtual MPD::Song *currentSong(); virtual MPD::Song *currentSong();
virtual std::shared_ptr<ProxySongList> getProxySongList();
virtual bool allowsSelection(); virtual bool allowsSelection();
virtual void reverseSelection(); virtual void reverseSelection();
virtual void removeSelection();
virtual MPD::SongList getSelectedSongs(); virtual MPD::SongList getSelectedSongs();
virtual NC::List *GetList() { return w; } virtual NC::List *GetList() { return w; }

View File

@@ -79,7 +79,9 @@ void setProperties(NC::Menu<T> &menu, const MPD::Song &s, HasSongs &screen, bool
separate_albums = false; separate_albums = false;
if (Config.playlist_separate_albums) 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()) if (next && next->getAlbum() != s.getAlbum())
separate_albums = true; separate_albums = true;
} }

View File

@@ -32,10 +32,22 @@ inline HasSongs *hasSongs(BasicScreen *screen)
return dynamic_cast<HasSongs *>(screen); return dynamic_cast<HasSongs *>(screen);
} }
template <typename Iterator> void removeSelectionHelper(Iterator first, Iterator last) inline std::shared_ptr<ProxySongList> proxySongList(BasicScreen *screen)
{ {
for (; first != last; ++first) auto ptr = nullProxySongList();
first->setSelected(false); 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 <typename Iterator> void reverseSelectionHelper(Iterator first, Iterator last) template <typename Iterator> void reverseSelectionHelper(Iterator first, Iterator last)

View File

@@ -22,8 +22,9 @@
#define _INTERFACES_H #define _INTERFACES_H
#include <string> #include <string>
#include "mpdpp.h"
#include "gcc.h" #include "gcc.h"
#include "song.h"
#include "proxy_song_list.h"
struct Filterable struct Filterable
{ {
@@ -40,12 +41,10 @@ struct Searchable
struct HasSongs struct HasSongs
{ {
virtual MPD::Song *getSong(size_t pos) = 0; virtual std::shared_ptr<ProxySongList> getProxySongList() = 0;
virtual MPD::Song *currentSong() = 0;
virtual bool allowsSelection() = 0; virtual bool allowsSelection() = 0;
virtual void reverseSelection() = 0; virtual void reverseSelection() = 0;
virtual void removeSelection() = 0;
virtual MPD::SongList getSelectedSongs() = 0; virtual MPD::SongList getSelectedSongs() = 0;
}; };

View File

@@ -117,28 +117,26 @@ void Lyrics::SwitchTo()
} }
# endif // HAVE_CURL_CURL_H # endif // HAVE_CURL_CURL_H
auto hs = dynamic_cast<HasSongs *>(myScreen); const MPD::Song *s = currentSong(myScreen);
if (!hs) if (!s)
return; 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;
myOldScreen = myScreen;
myScreen = this; itsSong = *s;
Load();
itsSong = *s;
Load(); Global::RedrawHeader = true;
Global::RedrawHeader = true;
}
else
{
ShowMessage("Song must have both artist and title tag set");
return;
}
} }
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 // 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 // fetching lyrics may fail (eg. if tags are missing) and we don't want
// to adjust screen size then. // to adjust screen size then.

View File

@@ -531,37 +531,21 @@ void MediaLibrary::prevFound(bool wrap)
/***********************************************************************/ /***********************************************************************/
MPD::Song *MediaLibrary::getSong(size_t pos) std::shared_ptr<ProxySongList> MediaLibrary::getProxySongList()
{ {
MPD::Song *ptr = 0; auto ptr = nullProxySongList();
if (w == Songs) if (w == Songs)
ptr = &(*Songs)[pos].value(); ptr = mkProxySongList(*Songs, [](NC::Menu<MPD::Song>::Item &item) {
return &item.value();
});
return ptr; return ptr;
} }
MPD::Song *MediaLibrary::currentSong()
{
if (w == Songs && !Songs->Empty())
return getSong(Songs->Choice());
else
return 0;
}
bool MediaLibrary::allowsSelection() bool MediaLibrary::allowsSelection()
{ {
return true; 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() void MediaLibrary::reverseSelection()
{ {
if (w == Tags) if (w == Tags)

View File

@@ -50,12 +50,10 @@ class MediaLibrary : public Screen<NC::Window>, public Filterable, public HasSon
virtual void prevFound(bool wrap); virtual void prevFound(bool wrap);
/// HasSongs implementation /// HasSongs implementation
virtual MPD::Song *getSong(size_t pos); virtual std::shared_ptr<ProxySongList> getProxySongList();
virtual MPD::Song *currentSong();
virtual bool allowsSelection(); virtual bool allowsSelection();
virtual void reverseSelection(); virtual void reverseSelection();
virtual void removeSelection();
virtual MPD::SongList getSelectedSongs(); virtual MPD::SongList getSelectedSongs();
virtual NC::List *GetList(); virtual NC::List *GetList();

View File

@@ -1193,7 +1193,7 @@ MPD::ItemList MPD::Connection::GetDirectory(const std::string &path)
it.type = itDirectory; it.type = itDirectory;
break; break;
case MPD_ENTITY_TYPE_SONG: case MPD_ENTITY_TYPE_SONG:
it.song = std::shared_ptr<Song>(new Song(mpd_song_dup(mpd_entity_get_song(item)))); it.song = std::make_shared<Song>(Song(mpd_song_dup(mpd_entity_get_song(item))));
it.type = itSong; it.type = itSong;
break; break;
case MPD_ENTITY_TYPE_PLAYLIST: case MPD_ENTITY_TYPE_PLAYLIST:

View File

@@ -318,6 +318,16 @@ void Playlist::prevFound(bool wrap)
/***********************************************************************/ /***********************************************************************/
std::shared_ptr<ProxySongList> Playlist::getProxySongList()
{
auto ptr = nullProxySongList();
if (w == Items)
ptr = mkProxySongList(*Items, [](NC::Menu<MPD::Song>::Item &item) {
return &item.value();
});
return ptr;
}
MPD::Song *Playlist::getSong(size_t pos) MPD::Song *Playlist::getSong(size_t pos)
{ {
MPD::Song *ptr = 0; MPD::Song *ptr = 0;
@@ -339,11 +349,6 @@ bool Playlist::allowsSelection()
return w == Items; return w == Items;
} }
void Playlist::removeSelection()
{
removeSelectionHelper(Items->Begin(), Items->End());
}
void Playlist::reverseSelection() void Playlist::reverseSelection()
{ {
reverseSelectionHelper(Items->Begin(), Items->End()); reverseSelectionHelper(Items->Begin(), Items->End());

View File

@@ -55,10 +55,10 @@ class Playlist : public Screen<NC::Window>, public Filterable, public HasSongs,
/// HasSongs implementation /// HasSongs implementation
virtual MPD::Song *getSong(size_t pos); virtual MPD::Song *getSong(size_t pos);
virtual MPD::Song *currentSong(); virtual MPD::Song *currentSong();
virtual std::shared_ptr<ProxySongList> getProxySongList();
virtual bool allowsSelection(); virtual bool allowsSelection();
virtual void reverseSelection(); virtual void reverseSelection();
virtual void removeSelection();
virtual MPD::SongList getSelectedSongs(); virtual MPD::SongList getSelectedSongs();
virtual NC::List *GetList() { return w == Items ? Items : 0; } virtual NC::List *GetList() { return w == Items ? Items : 0; }

View File

@@ -486,35 +486,21 @@ void PlaylistEditor::prevFound(bool wrap)
/***********************************************************************/ /***********************************************************************/
MPD::Song *PlaylistEditor::getSong(size_t pos) std::shared_ptr<ProxySongList> PlaylistEditor::getProxySongList()
{ {
MPD::Song *ptr = 0; auto ptr = nullProxySongList();
if (w == Content) if (w == Content)
ptr = &(*Content)[pos].value(); ptr = mkProxySongList(*Content, [](NC::Menu<MPD::Song>::Item &item) {
return &item.value();
});
return ptr; return ptr;
} }
MPD::Song *PlaylistEditor::currentSong()
{
if (w == Content && !Content->Empty())
return getSong(Content->Choice());
else
return 0;
}
bool PlaylistEditor::allowsSelection() bool PlaylistEditor::allowsSelection()
{ {
return true; 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() void PlaylistEditor::reverseSelection()
{ {
if (w == Playlists) if (w == Playlists)

View File

@@ -49,12 +49,10 @@ class PlaylistEditor : public Screen<NC::Window>, public Filterable, public HasS
virtual void prevFound(bool wrap); virtual void prevFound(bool wrap);
/// HasSongs implementation /// HasSongs implementation
virtual MPD::Song *getSong(size_t pos); virtual std::shared_ptr<ProxySongList> getProxySongList();
virtual MPD::Song *currentSong();
virtual bool allowsSelection(); virtual bool allowsSelection();
virtual void reverseSelection(); virtual void reverseSelection();
virtual void removeSelection();
virtual MPD::SongList getSelectedSongs(); virtual MPD::SongList getSelectedSongs();
virtual void Locate(const std::string &); virtual void Locate(const std::string &);

110
src/proxy_song_list.h Normal file
View File

@@ -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 <typename T, typename F> struct Impl : Interface
{
typedef typename NC::Menu<T> 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<Interface> m_impl;
public:
template <typename T, typename F>
ProxySongList(typename NC::Menu<T> &menu, F f) : m_impl(new Impl<T, F>(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 <typename T, typename F>
std::shared_ptr<ProxySongList> mkProxySongList(typename NC::Menu<T> &menu, F f)
{
return std::make_shared<ProxySongList>(ProxySongList(menu, f));
}
inline std::shared_ptr<ProxySongList> nullProxySongList()
{
return std::shared_ptr<ProxySongList>();
}
#endif

View File

@@ -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; return mkProxySongList(*w, [](NC::Menu<SEItem>::Item &item) {
auto &item = (*w)[pos]; MPD::Song *ptr = 0;
if (!item.isSeparator() && item.value().isSong()) if (!item.isSeparator() && item.value().isSong())
ptr = &item.value().song(); ptr = &item.value().song();
return ptr; return ptr;
} });
MPD::Song *SearchEngine::currentSong()
{
if (w->Empty())
return 0;
else
return getSong(w->Choice());
} }
bool SearchEngine::allowsSelection() bool SearchEngine::allowsSelection()
@@ -336,11 +329,6 @@ bool SearchEngine::allowsSelection()
return w->Current().value().isSong(); return w->Current().value().isSong();
} }
void SearchEngine::removeSelection()
{
removeSelectionHelper(w->Begin(), w->End());
}
void SearchEngine::reverseSelection() void SearchEngine::reverseSelection()
{ {
reverseSelectionHelper(w->Begin()+std::min(StaticOptions, w->Size()), w->End()); reverseSelectionHelper(w->Begin()+std::min(StaticOptions, w->Size()), w->End());

View File

@@ -96,12 +96,10 @@ class SearchEngine : public Screen< NC::Menu<SEItem> >, public Filterable, publi
virtual void prevFound(bool wrap); virtual void prevFound(bool wrap);
/// HasSongs implementation /// HasSongs implementation
virtual MPD::Song *getSong(size_t pos); virtual std::shared_ptr<ProxySongList> getProxySongList();
virtual MPD::Song *currentSong();
virtual bool allowsSelection(); virtual bool allowsSelection();
virtual void reverseSelection(); virtual void reverseSelection();
virtual void removeSelection();
virtual MPD::SongList getSelectedSongs(); virtual MPD::SongList getSelectedSongs();
virtual NC::List *GetList() { return w->Size() >= StaticOptions ? w : 0; } virtual NC::List *GetList() { return w->Size() >= StaticOptions ? w : 0; }

View File

@@ -84,10 +84,7 @@ void SongInfo::SwitchTo()
if (myLockedScreen) if (myLockedScreen)
UpdateInactiveScreen(this); UpdateInactiveScreen(this);
auto hs = dynamic_cast<HasSongs *>(myScreen); auto s = currentSong(myScreen);
if (!hs)
return;
auto s = hs->currentSong();
if (!s) if (!s)
return; return;

View File

@@ -854,33 +854,21 @@ void TagEditor::prevFound(bool wrap)
/***********************************************************************/ /***********************************************************************/
MPD::Song *TagEditor::getSong(size_t pos) std::shared_ptr<ProxySongList> TagEditor::getProxySongList()
{ {
MPD::Song *ptr = 0; auto ptr = nullProxySongList();
if (w == Tags) if (w == Tags)
ptr = &(*Tags)[pos].value(); ptr = mkProxySongList(*Tags, [](NC::Menu<MPD::MutableSong>::Item &item) {
return &item.value();
});
return ptr; return ptr;
} }
MPD::Song *TagEditor::currentSong()
{
if (w == Tags && !Tags->Empty())
return getSong(Tags->Choice());
else
return 0;
}
bool TagEditor::allowsSelection() bool TagEditor::allowsSelection()
{ {
return w == Tags; return w == Tags;
} }
void TagEditor::removeSelection()
{
if (w == Tags)
removeSelectionHelper(Tags->Begin(), Tags->End());
}
void TagEditor::reverseSelection() void TagEditor::reverseSelection()
{ {
if (w == Tags) if (w == Tags)

View File

@@ -61,12 +61,10 @@ class TagEditor : public Screen<NC::Window>, public Filterable, public HasSongs,
virtual void prevFound(bool wrap); virtual void prevFound(bool wrap);
/// HasSongs implementation /// HasSongs implementation
virtual MPD::Song *getSong(size_t pos); virtual std::shared_ptr<ProxySongList> getProxySongList();
virtual MPD::Song *currentSong();
virtual bool allowsSelection(); virtual bool allowsSelection();
virtual void reverseSelection(); virtual void reverseSelection();
virtual void removeSelection();
virtual MPD::SongList getSelectedSongs(); virtual MPD::SongList getSelectedSongs();
virtual NC::List *GetList(); virtual NC::List *GetList();