song list: get rid of boost::zip_iterator and improve {Const,}SongIterator
This commit is contained in:
@@ -59,6 +59,7 @@ ncmpcpp_LDFLAGS = $(all_libraries)
|
|||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
helpers/song_iterator_maker.h \
|
helpers/song_iterator_maker.h \
|
||||||
utility/comparators.h \
|
utility/comparators.h \
|
||||||
|
utility/const.h \
|
||||||
utility/conversion.h \
|
utility/conversion.h \
|
||||||
utility/functional.h \
|
utility/functional.h \
|
||||||
utility/html.h \
|
utility/html.h \
|
||||||
|
|||||||
@@ -80,9 +80,9 @@ std::vector<std::shared_ptr<Actions::BaseAction>> AvailableActions;
|
|||||||
|
|
||||||
void populateActions();
|
void populateActions();
|
||||||
|
|
||||||
bool scrollTagCanBeRun(NC::List *&list, SongList *&songs);
|
bool scrollTagCanBeRun(NC::List *&list, const SongList *&songs);
|
||||||
void scrollTagUpRun(NC::List *list, SongList *songs, MPD::Song::GetFunction get);
|
void scrollTagUpRun(NC::List *list, const SongList *songs, MPD::Song::GetFunction get);
|
||||||
void scrollTagDownRun(NC::List *list, SongList *songs, MPD::Song::GetFunction get);
|
void scrollTagDownRun(NC::List *list, const SongList *songs, MPD::Song::GetFunction get);
|
||||||
|
|
||||||
void seek();
|
void seek();
|
||||||
void findItem(const SearchDirection direction);
|
void findItem(const SearchDirection direction);
|
||||||
@@ -1783,28 +1783,25 @@ bool SelectAlbum::canBeRun()
|
|||||||
void SelectAlbum::run()
|
void SelectAlbum::run()
|
||||||
{
|
{
|
||||||
const auto front = m_songs->beginS(), current = m_songs->currentS(), end = m_songs->endS();
|
const auto front = m_songs->beginS(), current = m_songs->currentS(), end = m_songs->endS();
|
||||||
auto *s = current->get<Bit::Song>();
|
if (current->song() == nullptr)
|
||||||
if (s == nullptr)
|
|
||||||
return;
|
return;
|
||||||
auto get = &MPD::Song::getAlbum;
|
auto get = &MPD::Song::getAlbum;
|
||||||
const std::string tag = s->getTags(get);
|
const std::string tag = current->song()->getTags(get);
|
||||||
// go up
|
// go up
|
||||||
for (auto it = current; it != front;)
|
for (auto it = current; it != front;)
|
||||||
{
|
{
|
||||||
--it;
|
--it;
|
||||||
s = it->get<Bit::Song>();
|
if (it->song() == nullptr || it->song()->getTags(get) != tag)
|
||||||
if (s == nullptr || s->getTags(get) != tag)
|
|
||||||
break;
|
break;
|
||||||
it->get<Bit::Properties>().setSelected(true);
|
it->properties().setSelected(true);
|
||||||
}
|
}
|
||||||
// go down
|
// go down
|
||||||
for (auto it = current;;)
|
for (auto it = current;;)
|
||||||
{
|
{
|
||||||
it->get<Bit::Properties>().setSelected(true);
|
it->properties().setSelected(true);
|
||||||
if (++it == end)
|
if (++it == end)
|
||||||
break;
|
break;
|
||||||
s = it->get<Bit::Song>();
|
if (it->song() == nullptr || it->song()->getTags(get) != tag)
|
||||||
if (s == nullptr || s->getTags(get) != tag)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Statusbar::print("Album around cursor position selected");
|
Statusbar::print("Album around cursor position selected");
|
||||||
@@ -2809,7 +2806,7 @@ void populateActions()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scrollTagCanBeRun(NC::List *&list, SongList *&songs)
|
bool scrollTagCanBeRun(NC::List *&list, const SongList *&songs)
|
||||||
{
|
{
|
||||||
auto w = myScreen->activeWindow();
|
auto w = myScreen->activeWindow();
|
||||||
if (list != static_cast<void *>(w))
|
if (list != static_cast<void *>(w))
|
||||||
@@ -2820,36 +2817,34 @@ bool scrollTagCanBeRun(NC::List *&list, SongList *&songs)
|
|||||||
&& songs != nullptr;
|
&& songs != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scrollTagUpRun(NC::List *list, SongList *songs, MPD::Song::GetFunction get)
|
void scrollTagUpRun(NC::List *list, const SongList *songs, MPD::Song::GetFunction get)
|
||||||
{
|
{
|
||||||
const auto front = songs->beginS();
|
const auto front = songs->beginS();
|
||||||
auto it = songs->currentS();
|
auto it = songs->currentS();
|
||||||
if (auto *s = it->get<Bit::Song>())
|
if (it->song() != nullptr)
|
||||||
{
|
{
|
||||||
const std::string tag = s->getTags(get);
|
const std::string tag = it->song()->getTags(get);
|
||||||
while (it != front)
|
while (it != front)
|
||||||
{
|
{
|
||||||
--it;
|
--it;
|
||||||
s = it->get<Bit::Song>();
|
if (it->song() == nullptr || it->song()->getTags(get) != tag)
|
||||||
if (s == nullptr || s->getTags(get) != tag)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
list->highlight(it-front);
|
list->highlight(it-front);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scrollTagDownRun(NC::List *list, SongList *songs, MPD::Song::GetFunction get)
|
void scrollTagDownRun(NC::List *list, const SongList *songs, MPD::Song::GetFunction get)
|
||||||
{
|
{
|
||||||
const auto front = songs->beginS(), back = --songs->endS();
|
const auto front = songs->beginS(), back = --songs->endS();
|
||||||
auto it = songs->currentS();
|
auto it = songs->currentS();
|
||||||
if (auto *s = it->get<Bit::Song>())
|
if (it->song() != nullptr)
|
||||||
{
|
{
|
||||||
const std::string tag = s->getTags(get);
|
const std::string tag = it->song()->getTags(get);
|
||||||
while (it != back)
|
while (it != back)
|
||||||
{
|
{
|
||||||
++it;
|
++it;
|
||||||
s = it->get<Bit::Song>();
|
if (it->song() == nullptr || it->song()->getTags(get) != tag)
|
||||||
if (s == nullptr || s->getTags(get) != tag)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
list->highlight(it-front);
|
list->highlight(it-front);
|
||||||
@@ -2882,7 +2877,8 @@ void seek()
|
|||||||
// can be run and one of them is of the given type. This will still not work
|
// can be run and one of them is of the given type. This will still not work
|
||||||
// in some contrived cases, but allows for more flexibility than accepting
|
// in some contrived cases, but allows for more flexibility than accepting
|
||||||
// single actions only.
|
// single actions only.
|
||||||
auto hasRunnableAction = [](BindingsConfiguration::BindingIteratorPair &bindings, Actions::Type type) {
|
auto hasRunnableAction = [](BindingsConfiguration::BindingIteratorPair &bindings,
|
||||||
|
Actions::Type type) {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
for (auto binding = bindings.first; binding != bindings.second; ++binding)
|
for (auto binding = bindings.first; binding != bindings.second; ++binding)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ private:
|
|||||||
virtual void run() override;
|
virtual void run() override;
|
||||||
|
|
||||||
NC::List *m_list;
|
NC::List *m_list;
|
||||||
SongList *m_songs;
|
const SongList *m_songs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScrollUpAlbum: BaseAction
|
struct ScrollUpAlbum: BaseAction
|
||||||
@@ -292,7 +292,7 @@ private:
|
|||||||
virtual void run() override;
|
virtual void run() override;
|
||||||
|
|
||||||
NC::List *m_list;
|
NC::List *m_list;
|
||||||
SongList *m_songs;
|
const SongList *m_songs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScrollDownArtist: BaseAction
|
struct ScrollDownArtist: BaseAction
|
||||||
@@ -304,7 +304,7 @@ private:
|
|||||||
virtual void run() override;
|
virtual void run() override;
|
||||||
|
|
||||||
NC::List *m_list;
|
NC::List *m_list;
|
||||||
SongList *m_songs;
|
const SongList *m_songs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScrollDownAlbum: BaseAction
|
struct ScrollDownAlbum: BaseAction
|
||||||
@@ -316,7 +316,7 @@ private:
|
|||||||
virtual void run() override;
|
virtual void run() override;
|
||||||
|
|
||||||
NC::List *m_list;
|
NC::List *m_list;
|
||||||
SongList *m_songs;
|
const SongList *m_songs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PageUp: BaseAction
|
struct PageUp: BaseAction
|
||||||
|
|||||||
@@ -70,54 +70,53 @@ void clearDirectory(const std::string &directory);
|
|||||||
std::string itemToString(const MPD::Item &item);
|
std::string itemToString(const MPD::Item &item);
|
||||||
bool browserEntryMatcher(const Regex::Regex &rx, const MPD::Item &item, bool filter);
|
bool browserEntryMatcher(const Regex::Regex &rx, const MPD::Item &item, bool filter);
|
||||||
|
|
||||||
template <bool Const>
|
|
||||||
struct SongExtractor
|
|
||||||
{
|
|
||||||
typedef SongExtractor type;
|
|
||||||
|
|
||||||
typedef typename NC::Menu<MPD::Item>::Item MenuItem;
|
|
||||||
typedef typename std::conditional<Const, const MenuItem, MenuItem>::type Item;
|
|
||||||
typedef typename std::conditional<Const, const MPD::Song, MPD::Song>::type Song;
|
|
||||||
|
|
||||||
Song *operator()(Item &item) const
|
|
||||||
{
|
|
||||||
Song *ptr = nullptr;
|
|
||||||
if (item.value().type() == MPD::Item::Type::Song)
|
|
||||||
ptr = const_cast<Song *>(&item.value().song());
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct SongPropertiesExtractor<MPD::Item>
|
||||||
|
{
|
||||||
|
template <typename ItemT>
|
||||||
|
auto &operator()(ItemT &item) const
|
||||||
|
{
|
||||||
|
auto s = item.value().type() == MPD::Item::Type::Song
|
||||||
|
? &item.value().song()
|
||||||
|
: nullptr;
|
||||||
|
m_cache.assign(&item.properties(), s);
|
||||||
|
return m_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable SongProperties m_cache;
|
||||||
|
};
|
||||||
|
|
||||||
SongIterator BrowserWindow::currentS()
|
SongIterator BrowserWindow::currentS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<MPD::Item>(current(), SongExtractor<false>());
|
return makeSongIterator(current());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator BrowserWindow::currentS() const
|
ConstSongIterator BrowserWindow::currentS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<MPD::Item>(current(), SongExtractor<true>());
|
return makeConstSongIterator(current());
|
||||||
}
|
}
|
||||||
|
|
||||||
SongIterator BrowserWindow::beginS()
|
SongIterator BrowserWindow::beginS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<MPD::Item>(begin(), SongExtractor<false>());
|
return makeSongIterator(begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator BrowserWindow::beginS() const
|
ConstSongIterator BrowserWindow::beginS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<MPD::Item>(begin(), SongExtractor<true>());
|
return makeConstSongIterator(begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
SongIterator BrowserWindow::endS()
|
SongIterator BrowserWindow::endS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<MPD::Item>(end(), SongExtractor<false>());
|
return makeSongIterator(end());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator BrowserWindow::endS() const
|
ConstSongIterator BrowserWindow::endS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<MPD::Item>(end(), SongExtractor<true>());
|
return makeConstSongIterator(end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MPD::Song> BrowserWindow::getSelectedSongs()
|
std::vector<MPD::Song> BrowserWindow::getSelectedSongs()
|
||||||
|
|||||||
@@ -87,8 +87,7 @@ void setProperties(NC::Menu<T> &menu, const MPD::Song &s, const SongList &list,
|
|||||||
auto next = list.beginS() + drawn_pos + 1;
|
auto next = list.beginS() + drawn_pos + 1;
|
||||||
if (next != list.endS())
|
if (next != list.endS())
|
||||||
{
|
{
|
||||||
auto next_s = next->get<Bit::Song>();
|
if (next->song() != nullptr && next->song()->getAlbum() != s.getAlbum())
|
||||||
if (next_s != nullptr && next_s->getAlbum() != s.getAlbum())
|
|
||||||
separate_albums = true;
|
separate_albums = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const MPD::Song *currentSong(const BaseScreen *screen)
|
|||||||
{
|
{
|
||||||
const auto it = list->currentS();
|
const auto it = list->currentS();
|
||||||
if (it != list->endS())
|
if (it != list->endS())
|
||||||
ptr = it->get<Bit::Song>();
|
ptr = it->song();
|
||||||
}
|
}
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -387,12 +387,10 @@ template <typename ListT>
|
|||||||
void markSongsInPlaylist(ListT &list)
|
void markSongsInPlaylist(ListT &list)
|
||||||
{
|
{
|
||||||
ScopedUnfilteredMenu<typename ListT::Item::Type> sunfilter(ReapplyFilter::No, list);
|
ScopedUnfilteredMenu<typename ListT::Item::Type> sunfilter(ReapplyFilter::No, list);
|
||||||
MPD::Song *s;
|
|
||||||
for (auto &p : static_cast<SongList &>(list))
|
for (auto &p : static_cast<SongList &>(list))
|
||||||
{
|
{
|
||||||
s = p.get<Bit::Song>();
|
if (p.song() != nullptr)
|
||||||
if (s != nullptr)
|
p.properties().setBold(myPlaylist->checkForSong(*p.song()));
|
||||||
p.get<Bit::Properties>().setBold(myPlaylist->checkForSong(*s));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,26 +22,48 @@
|
|||||||
#define NCMPCPP_HELPERS_SONG_ITERATOR_MAKER_H
|
#define NCMPCPP_HELPERS_SONG_ITERATOR_MAKER_H
|
||||||
|
|
||||||
#include <boost/iterator/transform_iterator.hpp>
|
#include <boost/iterator/transform_iterator.hpp>
|
||||||
#include <boost/iterator/zip_iterator.hpp>
|
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "song_list.h"
|
#include "song_list.h"
|
||||||
|
|
||||||
template <typename ItemT, typename TransformT>
|
template <typename SongT>
|
||||||
SongIterator makeSongIterator_(typename NC::Menu<ItemT>::Iterator it, TransformT &&map)
|
struct SongPropertiesExtractor
|
||||||
{
|
{
|
||||||
return SongIterator(boost::make_zip_iterator(boost::make_tuple(
|
template <typename ItemT>
|
||||||
typename NC::Menu<ItemT>::PropertiesIterator(it),
|
auto &operator()(ItemT &item) const
|
||||||
boost::make_transform_iterator(it, std::forward<TransformT>(map))
|
{
|
||||||
)));
|
return m_cache.assign(&item.properties(), &item.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable SongProperties m_cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename IteratorT>
|
||||||
|
SongIterator makeSongIterator(IteratorT it)
|
||||||
|
{
|
||||||
|
typedef SongPropertiesExtractor<
|
||||||
|
typename IteratorT::value_type::Type
|
||||||
|
> Extractor;
|
||||||
|
static_assert(
|
||||||
|
std::is_convertible<
|
||||||
|
typename std::result_of<Extractor(typename IteratorT::reference)>::type,
|
||||||
|
SongProperties &
|
||||||
|
>::value, "invalid result type of SongPropertiesExtractor");
|
||||||
|
return SongIterator(boost::make_transform_iterator(it, Extractor{}));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ItemT, typename TransformT>
|
template <typename ConstIteratorT>
|
||||||
ConstSongIterator makeConstSongIterator_(typename NC::Menu<ItemT>::ConstIterator it, TransformT &&map)
|
ConstSongIterator makeConstSongIterator(ConstIteratorT it)
|
||||||
{
|
{
|
||||||
return ConstSongIterator(boost::make_zip_iterator(boost::make_tuple(
|
typedef SongPropertiesExtractor<
|
||||||
typename NC::Menu<ItemT>::ConstPropertiesIterator(it),
|
typename ConstIteratorT::value_type::Type
|
||||||
boost::make_transform_iterator(it, std::forward<TransformT>(map))
|
> Extractor;
|
||||||
)));
|
static_assert(
|
||||||
|
std::is_convertible<
|
||||||
|
typename std::result_of<Extractor(typename ConstIteratorT::reference)>::type,
|
||||||
|
const SongProperties &
|
||||||
|
>::value, "invalid result type of SongPropertiesExtractor");
|
||||||
|
return ConstSongIterator(boost::make_transform_iterator(it, Extractor{}));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NCMPCPP_HELPERS_SONG_ITERATOR_MAKER_H
|
#endif // NCMPCPP_HELPERS_SONG_ITERATOR_MAKER_H
|
||||||
|
|||||||
11
src/menu.h
11
src/menu.h
@@ -29,6 +29,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
#include "utility/const.h"
|
||||||
#include "strbuffer.h"
|
#include "strbuffer.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
@@ -197,8 +198,6 @@ struct Menu: Window, List
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Const { Yes, No };
|
|
||||||
|
|
||||||
template <Const const_>
|
template <Const const_>
|
||||||
struct ExtractProperties
|
struct ExtractProperties
|
||||||
{
|
{
|
||||||
@@ -254,19 +253,19 @@ struct Menu: Window, List
|
|||||||
typedef std::reverse_iterator<ConstIterator> ConstReverseIterator;
|
typedef std::reverse_iterator<ConstIterator> ConstReverseIterator;
|
||||||
|
|
||||||
typedef boost::transform_iterator<
|
typedef boost::transform_iterator<
|
||||||
typename Item::template ExtractValue<Item::Const::No>,
|
typename Item::template ExtractValue<Const::No>,
|
||||||
Iterator> ValueIterator;
|
Iterator> ValueIterator;
|
||||||
typedef boost::transform_iterator<
|
typedef boost::transform_iterator<
|
||||||
typename Item::template ExtractValue<Item::Const::Yes>,
|
typename Item::template ExtractValue<Const::Yes>,
|
||||||
ConstIterator> ConstValueIterator;
|
ConstIterator> ConstValueIterator;
|
||||||
typedef std::reverse_iterator<ValueIterator> ReverseValueIterator;
|
typedef std::reverse_iterator<ValueIterator> ReverseValueIterator;
|
||||||
typedef std::reverse_iterator<ConstValueIterator> ConstReverseValueIterator;
|
typedef std::reverse_iterator<ConstValueIterator> ConstReverseValueIterator;
|
||||||
|
|
||||||
typedef boost::transform_iterator<
|
typedef boost::transform_iterator<
|
||||||
typename Item::template ExtractProperties<Item::Const::No>,
|
typename Item::template ExtractProperties<Const::No>,
|
||||||
Iterator> PropertiesIterator;
|
Iterator> PropertiesIterator;
|
||||||
typedef boost::transform_iterator<
|
typedef boost::transform_iterator<
|
||||||
typename Item::template ExtractProperties<Item::Const::Yes>,
|
typename Item::template ExtractProperties<Const::Yes>,
|
||||||
ConstIterator> ConstPropertiesIterator;
|
ConstIterator> ConstPropertiesIterator;
|
||||||
|
|
||||||
/// Function helper prototype used to display each option on the screen.
|
/// Function helper prototype used to display each option on the screen.
|
||||||
|
|||||||
17
src/mpdpp.h
17
src/mpdpp.h
@@ -260,6 +260,23 @@ struct Item
|
|||||||
{
|
{
|
||||||
return m_type;
|
return m_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Directory &directory()
|
||||||
|
{
|
||||||
|
return const_cast<Directory &>(
|
||||||
|
static_cast<const Item &>(*this).directory());
|
||||||
|
}
|
||||||
|
Song &song()
|
||||||
|
{
|
||||||
|
return const_cast<Song &>(
|
||||||
|
static_cast<const Item &>(*this).song());
|
||||||
|
}
|
||||||
|
Playlist &playlist()
|
||||||
|
{
|
||||||
|
return const_cast<Playlist &>(
|
||||||
|
static_cast<const Item &>(*this).playlist());
|
||||||
|
}
|
||||||
|
|
||||||
const Directory &directory() const
|
const Directory &directory() const
|
||||||
{
|
{
|
||||||
assert(m_type == Type::Directory);
|
assert(m_type == Type::Directory);
|
||||||
|
|||||||
@@ -73,56 +73,56 @@ namespace pos {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
std::string SEItemToString(const SEItem &ei);
|
std::string SEItemToString(const SEItem &ei);
|
||||||
bool SEItemEntryMatcher(const Regex::Regex &rx, const NC::Menu<SEItem>::Item &item, bool filter);
|
bool SEItemEntryMatcher(const Regex::Regex &rx,
|
||||||
|
const NC::Menu<SEItem>::Item &item,
|
||||||
template <bool Const>
|
bool filter);
|
||||||
struct SongExtractor
|
|
||||||
{
|
|
||||||
typedef SongExtractor type;
|
|
||||||
|
|
||||||
typedef typename NC::Menu<SEItem>::Item MenuItem;
|
|
||||||
typedef typename std::conditional<Const, const MenuItem, MenuItem>::type Item;
|
|
||||||
typedef typename std::conditional<Const, const MPD::Song, MPD::Song>::type Song;
|
|
||||||
|
|
||||||
Song *operator()(Item &item) const
|
|
||||||
{
|
|
||||||
Song *ptr = nullptr;
|
|
||||||
if (!item.isSeparator() && item.value().isSong())
|
|
||||||
ptr = &item.value().song();
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct SongPropertiesExtractor<SEItem>
|
||||||
|
{
|
||||||
|
template <typename ItemT>
|
||||||
|
auto &operator()(ItemT &item) const
|
||||||
|
{
|
||||||
|
auto s = !item.isSeparator() && item.value().isSong()
|
||||||
|
? &item.value().song()
|
||||||
|
: nullptr;
|
||||||
|
return m_cache.assign(&item.properties(), s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable SongProperties m_cache;
|
||||||
|
};
|
||||||
|
|
||||||
SongIterator SearchEngineWindow::currentS()
|
SongIterator SearchEngineWindow::currentS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<SEItem>(current(), SongExtractor<false>());
|
return makeSongIterator(current());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator SearchEngineWindow::currentS() const
|
ConstSongIterator SearchEngineWindow::currentS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<SEItem>(current(), SongExtractor<true>());
|
return makeConstSongIterator(current());
|
||||||
}
|
}
|
||||||
|
|
||||||
SongIterator SearchEngineWindow::beginS()
|
SongIterator SearchEngineWindow::beginS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<SEItem>(begin(), SongExtractor<false>());
|
return makeSongIterator(begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator SearchEngineWindow::beginS() const
|
ConstSongIterator SearchEngineWindow::beginS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<SEItem>(begin(), SongExtractor<true>());
|
return makeConstSongIterator(begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
SongIterator SearchEngineWindow::endS()
|
SongIterator SearchEngineWindow::endS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<SEItem>(end(), SongExtractor<false>());
|
return makeSongIterator(end());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator SearchEngineWindow::endS() const
|
ConstSongIterator SearchEngineWindow::endS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<SEItem>(end(), SongExtractor<true>());
|
return makeConstSongIterator(end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MPD::Song> SearchEngineWindow::getSelectedSongs()
|
std::vector<MPD::Song> SearchEngineWindow::getSelectedSongs()
|
||||||
|
|||||||
@@ -22,53 +22,34 @@
|
|||||||
#include "song_info.h"
|
#include "song_info.h"
|
||||||
#include "utility/functional.h"
|
#include "utility/functional.h"
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
template <bool Const>
|
|
||||||
struct SongExtractor
|
|
||||||
{
|
|
||||||
typedef SongExtractor type;
|
|
||||||
|
|
||||||
typedef typename NC::Menu<MPD::Song>::Item MenuItem;
|
|
||||||
typedef typename std::conditional<Const, const MenuItem, MenuItem>::type Item;
|
|
||||||
typedef typename std::conditional<Const, const MPD::Song, MPD::Song>::type Song;
|
|
||||||
|
|
||||||
Song *operator()(Item &item) const
|
|
||||||
{
|
|
||||||
return &item.value();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
SongIterator SongMenu::currentS()
|
SongIterator SongMenu::currentS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<MPD::Song>(current(), SongExtractor<false>());
|
return makeSongIterator(current());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator SongMenu::currentS() const
|
ConstSongIterator SongMenu::currentS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<MPD::Song>(current(), SongExtractor<true>());
|
return makeConstSongIterator(current());
|
||||||
}
|
}
|
||||||
|
|
||||||
SongIterator SongMenu::beginS()
|
SongIterator SongMenu::beginS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<MPD::Song>(begin(), SongExtractor<false>());
|
return makeSongIterator(begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator SongMenu::beginS() const
|
ConstSongIterator SongMenu::beginS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<MPD::Song>(begin(), SongExtractor<true>());
|
return makeConstSongIterator(begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
SongIterator SongMenu::endS()
|
SongIterator SongMenu::endS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<MPD::Song>(end(), SongExtractor<false>());
|
return makeSongIterator(end());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator SongMenu::endS() const
|
ConstSongIterator SongMenu::endS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<MPD::Song>(end(), SongExtractor<true>());
|
return makeConstSongIterator(end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MPD::Song> SongMenu::getSelectedSongs()
|
std::vector<MPD::Song> SongMenu::getSelectedSongs()
|
||||||
|
|||||||
@@ -22,25 +22,85 @@
|
|||||||
#define NCMPCPP_SONG_LIST_H
|
#define NCMPCPP_SONG_LIST_H
|
||||||
|
|
||||||
#include <boost/range/detail/any_iterator.hpp>
|
#include <boost/range/detail/any_iterator.hpp>
|
||||||
#include <boost/tuple/tuple.hpp>
|
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "song.h"
|
#include "song.h"
|
||||||
|
#include "utility/const.h"
|
||||||
|
|
||||||
template <typename ValueT>
|
struct SongProperties
|
||||||
|
{
|
||||||
|
enum class State { Undefined, Const, Mutable };
|
||||||
|
|
||||||
|
SongProperties()
|
||||||
|
: m_state(State::Undefined)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
SongProperties &assign(NC::List::Properties *properties_, MPD::Song *song_)
|
||||||
|
{
|
||||||
|
m_state = State::Mutable;
|
||||||
|
m_properties = properties_;
|
||||||
|
m_song = song_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SongProperties &assign(const NC::List::Properties *properties_, const MPD::Song *song_)
|
||||||
|
{
|
||||||
|
m_state = State::Const;
|
||||||
|
m_const_properties = properties_;
|
||||||
|
m_const_song = song_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NC::List::Properties &properties() const
|
||||||
|
{
|
||||||
|
assert(m_state != State::Undefined);
|
||||||
|
return *m_const_properties;
|
||||||
|
}
|
||||||
|
const MPD::Song *song() const
|
||||||
|
{
|
||||||
|
assert(m_state != State::Undefined);
|
||||||
|
return m_const_song;
|
||||||
|
}
|
||||||
|
|
||||||
|
NC::List::Properties &properties()
|
||||||
|
{
|
||||||
|
assert(m_state == State::Mutable);
|
||||||
|
return *m_properties;
|
||||||
|
}
|
||||||
|
MPD::Song *song()
|
||||||
|
{
|
||||||
|
assert(m_state == State::Mutable);
|
||||||
|
return m_song;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
State m_state;
|
||||||
|
|
||||||
|
union {
|
||||||
|
NC::List::Properties *m_properties;
|
||||||
|
const NC::List::Properties *m_const_properties;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
MPD::Song *m_song;
|
||||||
|
const MPD::Song *m_const_song;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <Const const_>
|
||||||
using SongIteratorT = boost::range_detail::any_iterator<
|
using SongIteratorT = boost::range_detail::any_iterator<
|
||||||
ValueT,
|
typename std::conditional<
|
||||||
|
const_ == Const::Yes,
|
||||||
|
const SongProperties,
|
||||||
|
SongProperties>::type,
|
||||||
boost::random_access_traversal_tag,
|
boost::random_access_traversal_tag,
|
||||||
const ValueT, // const needed, see https://svn.boost.org/trac/boost/ticket/10493
|
typename std::conditional<
|
||||||
|
const_ == Const::Yes,
|
||||||
|
const SongProperties &,
|
||||||
|
SongProperties &>::type,
|
||||||
std::ptrdiff_t
|
std::ptrdiff_t
|
||||||
>;
|
>;
|
||||||
|
|
||||||
typedef SongIteratorT<boost::tuple<NC::List::Properties &, MPD::Song *>> SongIterator;
|
typedef SongIteratorT<Const::No> SongIterator;
|
||||||
typedef SongIteratorT<boost::tuple<const NC::List::Properties &, const MPD::Song *>> ConstSongIterator;
|
typedef SongIteratorT<Const::Yes> ConstSongIterator;
|
||||||
|
|
||||||
namespace Bit {
|
|
||||||
const size_t Properties = 0;
|
|
||||||
const size_t Song = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SongList
|
struct SongList
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -87,51 +87,36 @@ std::string SongToString(const MPD::MutableSong &s);
|
|||||||
bool DirEntryMatcher(const Regex::Regex &rx, const std::pair<std::string, std::string> &dir, bool filter);
|
bool DirEntryMatcher(const Regex::Regex &rx, const std::pair<std::string, std::string> &dir, bool filter);
|
||||||
bool SongEntryMatcher(const Regex::Regex &rx, const MPD::MutableSong &s);
|
bool SongEntryMatcher(const Regex::Regex &rx, const MPD::MutableSong &s);
|
||||||
|
|
||||||
template <bool Const>
|
|
||||||
struct SongExtractor
|
|
||||||
{
|
|
||||||
typedef SongExtractor type;
|
|
||||||
|
|
||||||
typedef typename NC::Menu<MPD::MutableSong>::Item MenuItem;
|
|
||||||
typedef typename std::conditional<Const, const MenuItem, MenuItem>::type Item;
|
|
||||||
typedef typename std::conditional<Const, const MPD::Song, MPD::Song>::type Song;
|
|
||||||
|
|
||||||
Song *operator()(Item &item) const
|
|
||||||
{
|
|
||||||
return &item.value();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SongIterator TagsWindow::currentS()
|
SongIterator TagsWindow::currentS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<MPD::MutableSong>(current(), SongExtractor<false>());
|
return makeSongIterator(current());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator TagsWindow::currentS() const
|
ConstSongIterator TagsWindow::currentS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<MPD::MutableSong>(current(), SongExtractor<true>());
|
return makeConstSongIterator(current());
|
||||||
}
|
}
|
||||||
|
|
||||||
SongIterator TagsWindow::beginS()
|
SongIterator TagsWindow::beginS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<MPD::MutableSong>(begin(), SongExtractor<false>());
|
return makeSongIterator(begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator TagsWindow::beginS() const
|
ConstSongIterator TagsWindow::beginS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<MPD::MutableSong>(begin(), SongExtractor<true>());
|
return makeConstSongIterator(begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
SongIterator TagsWindow::endS()
|
SongIterator TagsWindow::endS()
|
||||||
{
|
{
|
||||||
return makeSongIterator_<MPD::MutableSong>(end(), SongExtractor<false>());
|
return makeSongIterator(end());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstSongIterator TagsWindow::endS() const
|
ConstSongIterator TagsWindow::endS() const
|
||||||
{
|
{
|
||||||
return makeConstSongIterator_<MPD::MutableSong>(end(), SongExtractor<true>());
|
return makeConstSongIterator(end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<MPD::Song> TagsWindow::getSelectedSongs()
|
std::vector<MPD::Song> TagsWindow::getSelectedSongs()
|
||||||
|
|||||||
26
src/utility/const.h
Normal file
26
src/utility/const.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2008-2016 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 NCMPCPP_UTILITY_CONST_H
|
||||||
|
#define NCMPCPP_UTILITY_CONST_H
|
||||||
|
|
||||||
|
enum class Const { Yes, No };
|
||||||
|
|
||||||
|
#endif // NCMPCPP_UTILITY_CONST_H
|
||||||
Reference in New Issue
Block a user