menu: implement custom iterator

This commit is contained in:
Andrzej Rybczak
2012-08-30 20:17:25 +02:00
parent 7297b8a9ad
commit 7e53654492
12 changed files with 207 additions and 151 deletions

View File

@@ -881,7 +881,7 @@ void Delete::Run()
for (std::vector<size_t>::reverse_iterator it = list.rbegin(); it != list.rend(); ++it) for (std::vector<size_t>::reverse_iterator it = list.rbegin(); it != list.rend(); ++it)
{ {
Mpd.Delete(playlist, *it); Mpd.Delete(playlist, *it);
myPlaylistEditor->Content->DeleteOption(*it); myPlaylistEditor->Content->DeleteItem(*it);
} }
Mpd.CommitCommandsList(); Mpd.CommitCommandsList();
ShowMessage("Selected items deleted from playlist \"%s\"", myPlaylistEditor->Playlists->Current().c_str()); ShowMessage("Selected items deleted from playlist \"%s\"", myPlaylistEditor->Playlists->Current().c_str());
@@ -889,7 +889,7 @@ void Delete::Run()
else else
{ {
if (Mpd.Delete(myPlaylistEditor->Playlists->Current(), myPlaylistEditor->Content->Choice())) if (Mpd.Delete(myPlaylistEditor->Playlists->Current(), myPlaylistEditor->Content->Choice()))
myPlaylistEditor->Content->DeleteOption(myPlaylistEditor->Content->Choice()); myPlaylistEditor->Content->DeleteItem(myPlaylistEditor->Content->Choice());
} }
} }
} }
@@ -2203,7 +2203,7 @@ void ToggleBrowserSortMode::Run()
ShowMessage("Sort songs by: Name"); ShowMessage("Sort songs by: Name");
break; break;
} }
myBrowser->Main()->Sort<CaseInsensitiveSorting>(myBrowser->CurrentDir() != "/"); std::sort(myBrowser->Main()->Begin()+(myBrowser->CurrentDir() != "/"), myBrowser->Main()->End(), CaseInsensitiveSorting());
} }
bool ToggleLibraryTagType::canBeRun() const bool ToggleLibraryTagType::canBeRun() const

View File

@@ -369,7 +369,7 @@ void Browser::GetDirectory(std::string dir, std::string subdir)
MPD::Item parent; MPD::Item parent;
parent.name = ".."; parent.name = "..";
parent.type = itDirectory; parent.type = itDirectory;
w->AddOption(parent); w->AddItem(parent);
} }
MPD::ItemList list; MPD::ItemList list;
@@ -397,7 +397,7 @@ void Browser::GetDirectory(std::string dir, std::string subdir)
case itPlaylist: case itPlaylist:
{ {
utf_to_locale(it->name); utf_to_locale(it->name);
w->AddOption(*it); w->AddItem(*it);
break; break;
} }
case itDirectory: case itDirectory:
@@ -405,7 +405,7 @@ void Browser::GetDirectory(std::string dir, std::string subdir)
utf_to_locale(it->name); utf_to_locale(it->name);
if (it->name == subdir) if (it->name == subdir)
highlightme = w->Size(); highlightme = w->Size();
w->AddOption(*it); w->AddItem(*it);
break; break;
} }
case itSong: case itSong:
@@ -419,7 +419,7 @@ void Browser::GetDirectory(std::string dir, std::string subdir)
break; break;
} }
} }
w->AddOption(*it, bold); w->AddItem(*it, bold);
break; break;
} }
} }

View File

@@ -207,7 +207,7 @@ void MediaLibrary::Update()
if (it->empty() && !Config.media_library_display_empty_tag) if (it->empty() && !Config.media_library_display_empty_tag)
continue; continue;
utf_to_locale(*it); utf_to_locale(*it);
Artists->AddOption(*it); Artists->AddItem(*it);
} }
Artists->Window::Clear(); Artists->Window::Clear();
Artists->Refresh(); Artists->Refresh();
@@ -237,22 +237,22 @@ void MediaLibrary::Update()
utf_to_locale(*album); utf_to_locale(*album);
Mpd.CommitSearchTags([this, &album](std::string &&date) { Mpd.CommitSearchTags([this, &album](std::string &&date) {
utf_to_locale(date); utf_to_locale(date);
Albums->AddOption(SearchConstraints(*album, date)); Albums->AddItem(SearchConstraints(*album, date));
}); });
} }
else else
{ {
utf_to_locale(*album); utf_to_locale(*album);
Albums->AddOption(SearchConstraints(*album, "")); Albums->AddItem(SearchConstraints(*album, ""));
} }
} }
utf_to_locale(Artists->Current()); utf_to_locale(Artists->Current());
if (!Albums->Empty()) if (!Albums->Empty())
Albums->Sort<SearchConstraintsSorting>(); std::sort(Albums->Begin(), Albums->End(), SearchConstraintsSorting());
if (Albums->Size() > 1) if (Albums->Size() > 1)
{ {
Albums->AddSeparator(); Albums->AddSeparator();
Albums->AddOption(SearchConstraints("", AllTracksMarker)); Albums->AddItem(SearchConstraints("", AllTracksMarker));
} }
Albums->Refresh(); Albums->Refresh();
Mpd.BlockIdle(0); Mpd.BlockIdle(0);
@@ -286,27 +286,27 @@ void MediaLibrary::Update()
utf_to_locale(*album); utf_to_locale(*album);
Mpd.CommitSearchTags([this, &artist, &album](std::string &&tag) { Mpd.CommitSearchTags([this, &artist, &album](std::string &&tag) {
utf_to_locale(tag); utf_to_locale(tag);
Albums->AddOption(SearchConstraints(*artist, *album, tag)); Albums->AddItem(SearchConstraints(*artist, *album, tag));
}); });
} }
else else
{ {
utf_to_locale(*artist); utf_to_locale(*artist);
utf_to_locale(*album); utf_to_locale(*album);
Albums->AddOption(SearchConstraints(*artist, *album, *artist)); Albums->AddItem(SearchConstraints(*artist, *album, *artist));
} }
} }
else else
{ {
utf_to_locale(*artist); utf_to_locale(*artist);
utf_to_locale(*album); utf_to_locale(*album);
Albums->AddOption(SearchConstraints(*artist, *album, "")); Albums->AddItem(SearchConstraints(*artist, *album, ""));
} }
} }
} }
Mpd.BlockIdle(0); Mpd.BlockIdle(0);
if (!Albums->Empty()) if (!Albums->Empty())
Albums->Sort<SearchConstraintsSorting>(); std::sort(Albums->Begin(), Albums->End(), SearchConstraintsSorting());
Albums->Refresh(); Albums->Refresh();
} }
@@ -320,7 +320,6 @@ void MediaLibrary::Update()
if (!(hasTwoColumns ? Albums->Empty() : Artists->Empty()) && Songs->ReallyEmpty()) if (!(hasTwoColumns ? Albums->Empty() : Artists->Empty()) && Songs->ReallyEmpty())
{ {
Songs->Reset(); Songs->Reset();
MPD::SongList list;
Mpd.StartSearch(1); Mpd.StartSearch(1);
Mpd.AddSearch(Config.media_lib_primary_tag, locale_to_utf_cpy(hasTwoColumns ? Albums->Current().PrimaryTag : Artists->Current())); Mpd.AddSearch(Config.media_lib_primary_tag, locale_to_utf_cpy(hasTwoColumns ? Albums->Current().PrimaryTag : Artists->Current()));
@@ -330,17 +329,15 @@ void MediaLibrary::Update()
if (Config.media_library_display_date) if (Config.media_library_display_date)
Mpd.AddSearch(MPD_TAG_DATE, locale_to_utf_cpy(Albums->Current().Date)); Mpd.AddSearch(MPD_TAG_DATE, locale_to_utf_cpy(Albums->Current().Date));
} }
Mpd.CommitSearchSongs([&list](MPD::Song &&s) { Mpd.CommitSearchSongs([this](MPD::Song &&s) {
list.push_back(s); Songs->AddItem(s, myPlaylist->checkForSong(s));
}); });
if (Albums->Current().Date == AllTracksMarker) if (Albums->Current().Date == AllTracksMarker)
std::sort(list.begin(), list.end(), SortAllTracks); std::sort(Songs->Begin(), Songs->End(), SortAllTracks);
else else
std::sort(list.begin(), list.end(), SortSongsByTrack); std::sort(Songs->Begin(), Songs->End(), SortSongsByTrack);
for (auto it = list.begin(); it != list.end(); ++it)
Songs->AddOption(*it, myPlaylist->checkForSong(*it));
Songs->Window::Clear(); Songs->Window::Clear();
Songs->Refresh(); Songs->Refresh();
} }

View File

@@ -22,15 +22,15 @@
using namespace NCurses; using namespace NCurses;
template <> std::string Menu<std::string>::GetOption(size_t pos) template <> std::string Menu<std::string>::GetItem(size_t pos)
{ {
std::string result; std::string result;
if (m_options_ptr->at(pos)) if (m_options_ptr->at(pos))
{ {
if (m_get_string_helper) if (m_get_string_helper)
result = m_get_string_helper((*m_options_ptr)[pos]->Item); result = m_get_string_helper((*m_options_ptr)[pos]->Value);
else else
result = (*m_options_ptr)[pos]->Item; result = (*m_options_ptr)[pos]->Value;
} }
return result; return result;
} }

View File

@@ -22,8 +22,8 @@
#define _MENU_H #define _MENU_H
#include <regex.h> #include <regex.h>
#include <algorithm>
#include <functional> #include <functional>
#include <iterator>
#include <set> #include <set>
#include "error.h" #include "error.h"
@@ -102,7 +102,7 @@ namespace NCurses
/// This template class is generic menu capable of /// This template class is generic menu capable of
/// holding any std::vector compatible values. /// holding any std::vector compatible values.
/// ///
template <typename T> class Menu : public Window, public List template <typename T> struct Menu : public Window, public List
{ {
/// Function helper prototype used to display each option on the screen. /// Function helper prototype used to display each option on the screen.
/// If not set by setItemDisplayer(), menu won't display anything. /// If not set by setItemDisplayer(), menu won't display anything.
@@ -119,36 +119,94 @@ namespace NCurses
/// Struct that holds each item in the list and its attributes /// Struct that holds each item in the list and its attributes
/// ///
struct Option struct Item
{ {
Option() : isBold(0), isSelected(0), isStatic(0) { } Item() : isBold(0), isSelected(0), isStatic(0) { }
Option(const T &t, bool is_bold, bool is_static) : Item(const T &t, bool is_bold, bool is_static) :
Item(t), isBold(is_bold), isSelected(0), isStatic(is_static) { } Value(t), isBold(is_bold), isSelected(0), isStatic(is_static) { }
T Item; T Value;
bool isBold; bool isBold;
bool isSelected; bool isSelected;
bool isStatic; bool isStatic;
}; };
/// Functor that wraps around the functor passed to Sort() template <typename ValueT, typename BaseIterator> class ItemIterator
/// to fit to internal container structure : public std::iterator<std::random_access_iterator_tag, ValueT>
///
template <typename Comparison> class InternalSorting
{ {
Comparison cmp; friend class Menu<T>;
public: BaseIterator m_it;
bool operator()(Option *a, Option *b) explicit ItemIterator(BaseIterator it) : m_it(it) { }
{
return cmp(a->Item, b->Item); static const bool referenceValue = !std::is_same<
} ValueT, typename std::remove_pointer<
typename BaseIterator::value_type
>::type
>::value;
template <typename Result, bool referenceValue> struct getObject { };
template <typename Result> struct getObject<Result, true> {
static Result &apply(BaseIterator it) { return (*it)->Value; }
};
template <typename Result> struct getObject<Result, false> {
static Result &apply(BaseIterator it) { return **it; }
};
public:
ItemIterator() { }
ValueT &operator*() const { return getObject<ValueT, referenceValue>::apply(m_it); }
typename BaseIterator::value_type operator->() { return *m_it; }
ItemIterator &operator++() { ++m_it; return *this; }
ItemIterator operator++(int) { return ItemIterator(m_it++); }
ItemIterator &operator--() { --m_it; return *this; }
ItemIterator operator--(int) { return ItemIterator(m_it--); }
ValueT &operator[](ptrdiff_t n) const {
return getObject<ValueT, referenceValue>::apply(&m_it[n]);
}
ItemIterator &operator+=(ptrdiff_t n) { m_it += n; return *this; }
ItemIterator operator+(ptrdiff_t n) const { return ItemIterator(m_it + n); }
ItemIterator &operator-=(ptrdiff_t n) { m_it -= n; return *this; }
ItemIterator operator-(ptrdiff_t n) const { return ItemIterator(m_it - n); }
ptrdiff_t operator-(const ItemIterator &rhs) const { return m_it - rhs.m_it; }
template <typename Iterator>
bool operator==(const Iterator &rhs) const { return m_it == rhs.m_it; }
template <typename Iterator>
bool operator!=(const Iterator &rhs) const { return m_it != rhs.m_it; }
template <typename Iterator>
bool operator<(const Iterator &rhs) const { return m_it < rhs.m_it; }
template <typename Iterator>
bool operator<=(const Iterator &rhs) const { return m_it <= rhs.m_it; }
template <typename Iterator>
bool operator>(const Iterator &rhs) const { return m_it > rhs.m_it; }
template <typename Iterator>
bool operator>=(const Iterator &rhs) const { return m_it >= rhs.m_it; }
/// non-const to const conversion
template <typename Iterator> operator ItemIterator<
typename std::add_const<ValueT>::type, Iterator
>() { return ItemIterator(m_it); }
const BaseIterator &base() { return m_it; }
}; };
typedef typename std::vector<Option *>::iterator option_iterator; typedef ItemIterator<
typedef typename std::vector<Option *>::const_iterator option_const_iterator; T, typename std::vector<Item *>::iterator
> Iterator;
public:
typedef ItemIterator<
typename std::add_const<T>::type, typename std::vector<Item *>::const_iterator
> ConstIterator;
typedef std::reverse_iterator<Iterator> ReverseIterator;
typedef std::reverse_iterator<ConstIterator> ConstReverseIterator;
/// Constructs an empty menu with given parameters /// Constructs an empty menu with given parameters
/// @param startx X position of left upper corner of constructed menu /// @param startx X position of left upper corner of constructed menu
@@ -196,7 +254,7 @@ namespace NCurses
/// @param is_bold defines the initial state of bold attribute /// @param is_bold defines the initial state of bold attribute
/// @param is_static defines the initial state of static attribute /// @param is_static defines the initial state of static attribute
/// ///
void AddOption(const T &item, bool is_bold = 0, bool is_static = 0); void AddItem(const T &item, bool is_bold = 0, bool is_static = 0);
/// Adds separator to list /// Adds separator to list
/// ///
@@ -208,7 +266,7 @@ namespace NCurses
/// @param is_bold defines the initial state of bold attribute /// @param is_bold defines the initial state of bold attribute
/// @param is_static defines the initial state of static attribute /// @param is_static defines the initial state of static attribute
/// ///
void InsertOption(size_t pos, const T &Item, bool is_bold = 0, bool is_static = 0); void InsertItem(size_t pos, const T &Item, bool is_bold = 0, bool is_static = 0);
/// Inserts separator to list at given position /// Inserts separator to list at given position
/// @param pos initial position of inserted separator /// @param pos initial position of inserted separator
@@ -218,7 +276,7 @@ namespace NCurses
/// Deletes item from given position /// Deletes item from given position
/// @param pos given position of item to be deleted /// @param pos given position of item to be deleted
/// ///
void DeleteOption(size_t pos); void DeleteItem(size_t pos);
/// Converts the option into separator /// Converts the option into separator
/// @param pos position of item to be converted /// @param pos position of item to be converted
@@ -371,7 +429,7 @@ namespace NCurses
/// @return item converted to string /// @return item converted to string
/// @see setItemDisplayer() /// @see setItemDisplayer()
/// ///
std::string GetOption(size_t pos); std::string GetItem(size_t pos);
/// Refreshes the menu window /// Refreshes the menu window
/// @see Window::Refresh() /// @see Window::Refresh()
@@ -393,18 +451,6 @@ namespace NCurses
/// ///
void Reset(); void Reset();
/// Sorts all items using Comparison object with defined operator()
/// @param beginning beginning of range that has to be sorted
///
template <typename Comparison> void Sort(size_t beginning = 0, size_t end = -1)
{
if (m_options.empty())
return;
sort(m_options.begin()+beginning, end == size_t(-1) ? m_options.end() : m_options.begin()+end, InternalSorting<Comparison>());
if (isFiltered())
ApplyFilter(m_filter);
}
/// Sets prefix, that is put before each selected item to indicate its selection /// Sets prefix, that is put before each selected item to indicate its selection
/// Note that the passed variable is not deleted along with menu object. /// Note that the passed variable is not deleted along with menu object.
/// @param b pointer to buffer that contains the prefix /// @param b pointer to buffer that contains the prefix
@@ -509,7 +555,19 @@ namespace NCurses
/// @throw List::InvalidItem if requested item is separator /// @throw List::InvalidItem if requested item is separator
/// ///
T &operator[](size_t pos); T &operator[](size_t pos);
Iterator Begin() { return Iterator(m_options_ptr->begin()); }
ConstIterator Begin() const { return ConstIterator(m_options_ptr->begin()); }
Iterator End() { return Iterator(m_options_ptr->end()); }
ConstIterator End() const { return ConstIterator(m_options_ptr->end()); }
ReverseIterator Rbegin() { return ReverseIterator(End()); }
ConstReverseIterator Rbegin() const { return ConstReverseIterator(End()); }
ReverseIterator Rend() { return ReverseIterator(Begin()); }
ConstReverseIterator Rend() const { return ConstReverseIterator(Begin()); }
protected: protected:
/// Clears filter, filtered data etc. /// Clears filter, filtered data etc.
/// ///
@@ -521,9 +579,9 @@ namespace NCurses
std::string m_filter; std::string m_filter;
std::string m_search_constraint; std::string m_search_constraint;
std::vector<Option *> *m_options_ptr; std::vector<Item *> *m_options_ptr;
std::vector<Option *> m_options; std::vector<Item *> m_options;
std::vector<Option *> m_filtered_options; std::vector<Item *> m_filtered_options;
std::vector<size_t> m_filtered_positions; std::vector<size_t> m_filtered_positions;
std::set<size_t> m_found_positions; std::set<size_t> m_found_positions;
@@ -542,10 +600,10 @@ namespace NCurses
Buffer *m_selected_suffix; Buffer *m_selected_suffix;
}; };
/// Specialization of Menu<T>::GetOption for T = std::string, it's obvious /// Specialization of Menu<T>::GetItem for T = std::string, it's obvious
/// that if strings are stored, we don't need extra function to convert /// that if strings are stored, we don't need extra function to convert
/// them to strings by default /// them to strings by default
template <> std::string Menu<std::string>::GetOption(size_t pos); template <> std::string Menu<std::string>::GetItem(size_t pos);
} }
template <typename T> NCurses::Menu<T>::Menu(size_t startx, template <typename T> NCurses::Menu<T>::Menu(size_t startx,
@@ -584,13 +642,13 @@ template <typename T> NCurses::Menu<T>::Menu(const Menu &m) : Window(m),
m_selected_suffix(m.m_selected_suffix) m_selected_suffix(m.m_selected_suffix)
{ {
m_options.reserve(m.m_options.size()); m_options.reserve(m.m_options.size());
for (option_const_iterator it = m.m_options.begin(); it != m.m_options.end(); ++it) for (auto it = m.m_options.begin(); it != m.m_options.end(); ++it)
m_options.push_back(new Option(**it)); m_options.push_back(new Item(**it));
} }
template <typename T> NCurses::Menu<T>::~Menu() template <typename T> NCurses::Menu<T>::~Menu()
{ {
for (option_iterator it = m_options.begin(); it != m_options.end(); ++it) for (auto it = m_options.begin(); it != m_options.end(); ++it)
delete *it; delete *it;
} }
@@ -606,7 +664,7 @@ template <typename T> void NCurses::Menu<T>::ResizeList(size_t size)
m_options.resize(size); m_options.resize(size);
for (size_t i = 0; i < size; ++i) for (size_t i = 0; i < size; ++i)
if (!m_options[i]) if (!m_options[i])
m_options[i] = new Option(); m_options[i] = new Item();
} }
else if (size < m_options.size()) else if (size < m_options.size())
{ {
@@ -616,19 +674,19 @@ template <typename T> void NCurses::Menu<T>::ResizeList(size_t size)
} }
} }
template <typename T> void NCurses::Menu<T>::AddOption(const T &item, bool is_bold, bool is_static) template <typename T> void NCurses::Menu<T>::AddItem(const T &item, bool is_bold, bool is_static)
{ {
m_options.push_back(new Option(item, is_bold, is_static)); m_options.push_back(new Item(item, is_bold, is_static));
} }
template <typename T> void NCurses::Menu<T>::AddSeparator() template <typename T> void NCurses::Menu<T>::AddSeparator()
{ {
m_options.push_back(static_cast<Option *>(0)); m_options.push_back(static_cast<Item *>(0));
} }
template <typename T> void NCurses::Menu<T>::InsertOption(size_t pos, const T &item, bool is_bold, bool is_static) template <typename T> void NCurses::Menu<T>::InsertItem(size_t pos, const T &item, bool is_bold, bool is_static)
{ {
m_options.insert(m_options.begin()+pos, new Option(item, is_bold, is_static)); m_options.insert(m_options.begin()+pos, new Item(item, is_bold, is_static));
} }
template <typename T> void NCurses::Menu<T>::InsertSeparator(size_t pos) template <typename T> void NCurses::Menu<T>::InsertSeparator(size_t pos)
@@ -636,7 +694,7 @@ template <typename T> void NCurses::Menu<T>::InsertSeparator(size_t pos)
m_options.insert(m_options.begin()+pos, 0); m_options.insert(m_options.begin()+pos, 0);
} }
template <typename T> void NCurses::Menu<T>::DeleteOption(size_t pos) template <typename T> void NCurses::Menu<T>::DeleteItem(size_t pos)
{ {
if (m_options_ptr->empty()) if (m_options_ptr->empty())
return; return;
@@ -753,7 +811,7 @@ template <typename T> void NCurses::Menu<T>::Refresh()
if ((*m_options_ptr)[i]->isSelected && m_selected_prefix) if ((*m_options_ptr)[i]->isSelected && m_selected_prefix)
*this << *m_selected_prefix; *this << *m_selected_prefix;
if (m_item_displayer) if (m_item_displayer)
m_item_displayer(*this, (*m_options_ptr)[i]->Item); m_item_displayer(*this, (*m_options_ptr)[i]->Value);
if ((*m_options_ptr)[i]->isSelected && m_selected_suffix) if ((*m_options_ptr)[i]->isSelected && m_selected_suffix)
*this << *m_selected_suffix; *this << *m_selected_suffix;
if (m_highlight_enabled && int(i) == itsHighlight) if (m_highlight_enabled && int(i) == itsHighlight)
@@ -897,7 +955,7 @@ template <typename T> void NCurses::Menu<T>::ClearFiltered()
template <typename T> void NCurses::Menu<T>::Clear() template <typename T> void NCurses::Menu<T>::Clear()
{ {
for (option_iterator it = m_options.begin(); it != m_options.end(); ++it) for (auto it = m_options.begin(); it != m_options.end(); ++it)
delete *it; delete *it;
m_options.clear(); m_options.clear();
m_found_positions.clear(); m_found_positions.clear();
@@ -953,7 +1011,7 @@ template <typename T> bool NCurses::Menu<T>::isSeparator(int pos) const
template <typename T> bool NCurses::Menu<T>::hasSelected() const template <typename T> bool NCurses::Menu<T>::hasSelected() const
{ {
for (option_const_iterator it = m_options_ptr->begin(); it != m_options_ptr->end(); ++it) for (auto it = m_options_ptr->begin(); it != m_options_ptr->end(); ++it)
if (*it && (*it)->isSelected) if (*it && (*it)->isSelected)
return true; return true;
return false; return false;
@@ -985,7 +1043,7 @@ template <typename T> size_t NCurses::Menu<T>::Choice() const
template <typename T> size_t NCurses::Menu<T>::RealChoice() const template <typename T> size_t NCurses::Menu<T>::RealChoice() const
{ {
size_t result = 0; size_t result = 0;
for (option_const_iterator it = m_options_ptr->begin(); it != m_options_ptr->begin()+itsHighlight; ++it) for (auto it = m_options_ptr->begin(); it != m_options_ptr->begin()+itsHighlight; ++it)
if (*it && !(*it)->isStatic) if (*it && !(*it)->isStatic)
result++; result++;
return result; return result;
@@ -993,7 +1051,7 @@ template <typename T> size_t NCurses::Menu<T>::RealChoice() const
template <typename T> void NCurses::Menu<T>::ReverseSelection(size_t beginning) template <typename T> void NCurses::Menu<T>::ReverseSelection(size_t beginning)
{ {
option_iterator it = m_options_ptr->begin()+beginning; auto it = m_options_ptr->begin()+beginning;
for (size_t i = beginning; i < Size(); ++i, ++it) for (size_t i = beginning; i < Size(); ++i, ++it)
if (*it) if (*it)
(*it)->isSelected = !(*it)->isSelected && !(*it)->isStatic; (*it)->isSelected = !(*it)->isSelected && !(*it)->isStatic;
@@ -1011,7 +1069,7 @@ template <typename T> bool NCurses::Menu<T>::Search(const std::string &constrain
{ {
for (size_t i = beginning; i < m_options_ptr->size(); ++i) for (size_t i = beginning; i < m_options_ptr->size(); ++i)
{ {
if (regexec(&rx, GetOption(i).c_str(), 0, 0, 0) == 0) if (regexec(&rx, GetItem(i).c_str(), 0, 0, 0) == 0)
m_found_positions.insert(i); m_found_positions.insert(i);
} }
} }
@@ -1058,7 +1116,7 @@ template <typename T> void NCurses::Menu<T>::ApplyFilter(const std::string &filt
{ {
for (size_t i = beginning; i < m_options.size(); ++i) for (size_t i = beginning; i < m_options.size(); ++i)
{ {
if (regexec(&rx, GetOption(i).c_str(), 0, 0, 0) == 0) if (regexec(&rx, GetItem(i).c_str(), 0, 0, 0) == 0)
{ {
m_filtered_positions.push_back(i); m_filtered_positions.push_back(i);
m_filtered_options.push_back(m_options[i]); m_filtered_options.push_back(m_options[i]);
@@ -1076,10 +1134,10 @@ template <typename T> const std::string &NCurses::Menu<T>::GetFilter()
return m_filter; return m_filter;
} }
template <typename T> std::string NCurses::Menu<T>::GetOption(size_t pos) template <typename T> std::string NCurses::Menu<T>::GetItem(size_t pos)
{ {
if (m_options_ptr->at(pos) && m_get_string_helper) if (m_options_ptr->at(pos) && m_get_string_helper)
return m_get_string_helper((*m_options_ptr)[pos]->Item); return m_get_string_helper((*m_options_ptr)[pos]->Value);
else else
return ""; return "";
} }
@@ -1088,56 +1146,56 @@ template <typename T> T &NCurses::Menu<T>::Back()
{ {
if (!m_options_ptr->back()) if (!m_options_ptr->back())
FatalError("Menu::Back() has requested separator!"); FatalError("Menu::Back() has requested separator!");
return m_options_ptr->back()->Item; return m_options_ptr->back()->Value;
} }
template <typename T> const T &NCurses::Menu<T>::Back() const template <typename T> const T &NCurses::Menu<T>::Back() const
{ {
if (!m_options_ptr->back()) if (!m_options_ptr->back())
FatalError("Menu::Back() has requested separator!"); FatalError("Menu::Back() has requested separator!");
return m_options_ptr->back()->Item; return m_options_ptr->back()->Value;
} }
template <typename T> T &NCurses::Menu<T>::Current() template <typename T> T &NCurses::Menu<T>::Current()
{ {
if (!m_options_ptr->at(itsHighlight)) if (!m_options_ptr->at(itsHighlight))
FatalError("Menu::Current() has requested separator!"); FatalError("Menu::Current() has requested separator!");
return (*m_options_ptr)[itsHighlight]->Item; return (*m_options_ptr)[itsHighlight]->Value;
} }
template <typename T> const T &NCurses::Menu<T>::Current() const template <typename T> const T &NCurses::Menu<T>::Current() const
{ {
if (!m_options_ptr->at(itsHighlight)) if (!m_options_ptr->at(itsHighlight))
FatalError("Menu::Current() const has requested separator!"); FatalError("Menu::Current() const has requested separator!");
return (*m_options_ptr)[itsHighlight]->Item; return (*m_options_ptr)[itsHighlight]->Value;
} }
template <typename T> T &NCurses::Menu<T>::at(size_t pos) template <typename T> T &NCurses::Menu<T>::at(size_t pos)
{ {
if (!m_options_ptr->at(pos)) if (!m_options_ptr->at(pos))
FatalError("Menu::at() has requested separator!"); FatalError("Menu::at() has requested separator!");
return (*m_options_ptr)[pos]->Item; return (*m_options_ptr)[pos]->Value;
} }
template <typename T> const T &NCurses::Menu<T>::at(size_t pos) const template <typename T> const T &NCurses::Menu<T>::at(size_t pos) const
{ {
if (!m_options->at(pos)) if (!m_options->at(pos))
FatalError("Menu::at() const has requested separator!"); FatalError("Menu::at() const has requested separator!");
return (*m_options_ptr)[pos]->Item; return (*m_options_ptr)[pos]->Value;
} }
template <typename T> const T &NCurses::Menu<T>::operator[](size_t pos) const template <typename T> const T &NCurses::Menu<T>::operator[](size_t pos) const
{ {
if (!(*m_options_ptr)[pos]) if (!(*m_options_ptr)[pos])
FatalError("Menu::operator[] const has requested separator!"); FatalError("Menu::operator[] const has requested separator!");
return (*m_options_ptr)[pos]->Item; return (*m_options_ptr)[pos]->Value;
} }
template <typename T> T &NCurses::Menu<T>::operator[](size_t pos) template <typename T> T &NCurses::Menu<T>::operator[](size_t pos)
{ {
if (!(*m_options_ptr)[pos]) if (!(*m_options_ptr)[pos])
FatalError("Menu::operator[] has requested separator!"); FatalError("Menu::operator[] has requested separator!");
return (*m_options_ptr)[pos]->Item; return (*m_options_ptr)[pos]->Value;
} }
#endif #endif

View File

@@ -117,7 +117,7 @@ void Outputs::FetchList()
return; return;
w->Clear(); w->Clear();
Mpd.GetOutputs([this](MPD::Output &&o) { Mpd.GetOutputs([this](MPD::Output &&o) {
w->AddOption(o, o.isEnabled()); w->AddItem(o, o.isEnabled());
}); });
if (myScreen == this) if (myScreen == this)
w->Refresh(); w->Refresh();

View File

@@ -71,19 +71,19 @@ void Playlist::Init()
SortDialog->CenteredCursor(Config.centered_cursor); SortDialog->CenteredCursor(Config.centered_cursor);
SortDialog->setItemDisplayer(Display::Pair<std::string, MPD::Song::GetFunction>); SortDialog->setItemDisplayer(Display::Pair<std::string, MPD::Song::GetFunction>);
SortDialog->AddOption(std::make_pair("Artist", &MPD::Song::getArtist)); SortDialog->AddItem(std::make_pair("Artist", &MPD::Song::getArtist));
SortDialog->AddOption(std::make_pair("Album", &MPD::Song::getAlbum)); SortDialog->AddItem(std::make_pair("Album", &MPD::Song::getAlbum));
SortDialog->AddOption(std::make_pair("Disc", &MPD::Song::getDisc)); SortDialog->AddItem(std::make_pair("Disc", &MPD::Song::getDisc));
SortDialog->AddOption(std::make_pair("Track", &MPD::Song::getTrack)); SortDialog->AddItem(std::make_pair("Track", &MPD::Song::getTrack));
SortDialog->AddOption(std::make_pair("Genre", &MPD::Song::getGenre)); SortDialog->AddItem(std::make_pair("Genre", &MPD::Song::getGenre));
SortDialog->AddOption(std::make_pair("Date", &MPD::Song::getDate)); SortDialog->AddItem(std::make_pair("Date", &MPD::Song::getDate));
SortDialog->AddOption(std::make_pair("Composer", &MPD::Song::getComposer)); SortDialog->AddItem(std::make_pair("Composer", &MPD::Song::getComposer));
SortDialog->AddOption(std::make_pair("Performer", &MPD::Song::getPerformer)); SortDialog->AddItem(std::make_pair("Performer", &MPD::Song::getPerformer));
SortDialog->AddOption(std::make_pair("Title", &MPD::Song::getTitle)); SortDialog->AddItem(std::make_pair("Title", &MPD::Song::getTitle));
SortDialog->AddOption(std::make_pair("Filename", &MPD::Song::getURI)); SortDialog->AddItem(std::make_pair("Filename", &MPD::Song::getURI));
SortDialog->AddSeparator(); SortDialog->AddSeparator();
SortDialog->AddOption(std::make_pair("Sort", static_cast<MPD::Song::GetFunction>(0))); SortDialog->AddItem(std::make_pair("Sort", static_cast<MPD::Song::GetFunction>(0)));
SortDialog->AddOption(std::make_pair("Cancel", static_cast<MPD::Song::GetFunction>(0))); SortDialog->AddItem(std::make_pair("Cancel", static_cast<MPD::Song::GetFunction>(0)));
} }
w = Items; w = Items;
@@ -538,7 +538,7 @@ bool Playlist::Add(const MPD::Song &s, bool in_playlist, bool play, int position
if ((*Items)[i].getHash() == hash) if ((*Items)[i].getHash() == hash)
{ {
Mpd.Delete(i); Mpd.Delete(i);
Items->DeleteOption(i); Items->DeleteItem(i);
i--; i--;
} }
} }

View File

@@ -142,7 +142,7 @@ void PlaylistEditor::Update()
for (MPD::TagList::iterator it = list.begin(); it != list.end(); ++it) for (MPD::TagList::iterator it = list.begin(); it != list.end(); ++it)
{ {
utf_to_locale(*it); utf_to_locale(*it);
Playlists->AddOption(*it); Playlists->AddItem(*it);
} }
Playlists->Window::Clear(); Playlists->Window::Clear();
Playlists->Refresh(); Playlists->Refresh();
@@ -153,7 +153,7 @@ void PlaylistEditor::Update()
Content->Reset(); Content->Reset();
size_t plsize = 0; size_t plsize = 0;
Mpd.GetPlaylistContent(locale_to_utf_cpy(Playlists->Current()), [this, &plsize](MPD::Song &&s) { Mpd.GetPlaylistContent(locale_to_utf_cpy(Playlists->Current()), [this, &plsize](MPD::Song &&s) {
Content->AddOption(s, myPlaylist->checkForSong(s)); Content->AddItem(s, myPlaylist->checkForSong(s));
++plsize; ++plsize;
}); });
if (plsize > 0) if (plsize > 0)

View File

@@ -167,7 +167,7 @@ void SearchEngine::EnterPressed()
size_t found = w->Size()-SearchEngine::StaticOptions; size_t found = w->Size()-SearchEngine::StaticOptions;
found += 3; // don't count options inserted below found += 3; // don't count options inserted below
w->InsertSeparator(ResetButton+1); w->InsertSeparator(ResetButton+1);
w->InsertOption(ResetButton+2, SEItem(), 1, 1); w->InsertItem(ResetButton+2, SEItem(), 1, 1);
w->at(ResetButton+2).mkBuffer() << Config.color1 << "Search results: " << Config.color2 << "Found " << found << (found > 1 ? " songs" : " song") << clDefault; w->at(ResetButton+2).mkBuffer() << Config.color1 << "Search results: " << Config.color2 << "Found " << found << (found > 1 ? " songs" : " song") << clDefault;
w->InsertSeparator(ResetButton+3); w->InsertSeparator(ResetButton+3);
UpdateFoundList(); UpdateFoundList();
@@ -386,7 +386,7 @@ void SearchEngine::Search()
if (!itsConstraints[10].empty()) if (!itsConstraints[10].empty())
Mpd.AddSearch(MPD_TAG_COMMENT, itsConstraints[10]); Mpd.AddSearch(MPD_TAG_COMMENT, itsConstraints[10]);
Mpd.CommitSearchSongs([this](MPD::Song &&s) { Mpd.CommitSearchSongs([this](MPD::Song &&s) {
w->AddOption(s); w->AddItem(s);
}); });
return; return;
} }
@@ -534,7 +534,7 @@ void SearchEngine::Search()
if (found && any_found) if (found && any_found)
{ {
w->AddOption(*it); w->AddItem(*it);
list[it-list.begin()] = 0; list[it-list.begin()] = 0;
} }
found = 1; found = 1;

View File

@@ -18,6 +18,7 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/ ***************************************************************************/
#include <algorithm>
#include "charset.h" #include "charset.h"
#include "browser.h" #include "browser.h"
#include "display.h" #include "display.h"
@@ -49,13 +50,13 @@ void SelectedItemsAdder::Init()
itsPositionSelector->CenteredCursor(Config.centered_cursor); itsPositionSelector->CenteredCursor(Config.centered_cursor);
itsPositionSelector->HighlightColor(Config.main_highlight_color); itsPositionSelector->HighlightColor(Config.main_highlight_color);
itsPositionSelector->setItemDisplayer(Display::Default<std::string>); itsPositionSelector->setItemDisplayer(Display::Default<std::string>);
itsPositionSelector->AddOption("At the end of playlist"); itsPositionSelector->AddItem("At the end of playlist");
itsPositionSelector->AddOption("At the beginning of playlist"); itsPositionSelector->AddItem("At the beginning of playlist");
itsPositionSelector->AddOption("After current track"); itsPositionSelector->AddItem("After current track");
itsPositionSelector->AddOption("After current album"); itsPositionSelector->AddItem("After current album");
itsPositionSelector->AddOption("After highlighted item"); itsPositionSelector->AddItem("After highlighted item");
itsPositionSelector->AddSeparator(); itsPositionSelector->AddSeparator();
itsPositionSelector->AddOption("Cancel"); itsPositionSelector->AddItem("Cancel");
w = itsPlaylistSelector; w = itsPlaylistSelector;
isInitialized = 1; isInitialized = 1;
@@ -96,20 +97,20 @@ void SelectedItemsAdder::SwitchTo()
w->Clear(); w->Clear();
w->Reset(); w->Reset();
if (myOldScreen != myPlaylist) if (myOldScreen != myPlaylist)
w->AddOption("Current MPD playlist", 0, 0); w->AddItem("Current MPD playlist", 0, 0);
w->AddOption("New playlist", 0, playlists_not_active); w->AddItem("New playlist", 0, playlists_not_active);
w->AddSeparator(); w->AddSeparator();
MPD::TagList playlists; MPD::TagList playlists;
Mpd.GetPlaylists(playlists); Mpd.GetPlaylists(playlists);
sort(playlists.begin(), playlists.end(), CaseInsensitiveSorting()); std::sort(playlists.begin(), playlists.end(), CaseInsensitiveSorting());
for (MPD::TagList::iterator it = playlists.begin(); it != playlists.end(); ++it) for (MPD::TagList::iterator it = playlists.begin(); it != playlists.end(); ++it)
{ {
utf_to_locale(*it); utf_to_locale(*it);
w->AddOption(*it, 0, playlists_not_active); w->AddItem(*it, 0, playlists_not_active);
} }
w->AddSeparator(); w->AddSeparator();
w->AddOption("Cancel"); w->AddItem("Cancel");
myScreen = this; myScreen = this;
w->Window::Clear(); w->Window::Clear();

View File

@@ -243,7 +243,7 @@ void NcmpcppStatusChanged(MPD::Connection *, MPD::StatusChanges changed, void *)
else else
{ {
// otherwise just add it to playlist // otherwise just add it to playlist
myPlaylist->Items->AddOption(s); myPlaylist->Items->AddItem(s);
} }
}); });

View File

@@ -91,18 +91,18 @@ void TagEditor::Init()
TagTypes->setItemDisplayer(Display::Default<std::string>); TagTypes->setItemDisplayer(Display::Default<std::string>);
for (const SongInfo::Metadata *m = SongInfo::Tags; m->Name; ++m) for (const SongInfo::Metadata *m = SongInfo::Tags; m->Name; ++m)
TagTypes->AddOption(m->Name); TagTypes->AddItem(m->Name);
TagTypes->AddSeparator(); TagTypes->AddSeparator();
TagTypes->AddOption("Filename"); TagTypes->AddItem("Filename");
TagTypes->AddSeparator(); TagTypes->AddSeparator();
if (Config.titles_visibility) if (Config.titles_visibility)
TagTypes->AddOption("Options", 1, 1); TagTypes->AddItem("Options", 1, 1);
TagTypes->AddSeparator(); TagTypes->AddSeparator();
TagTypes->AddOption("Capitalize First Letters"); TagTypes->AddItem("Capitalize First Letters");
TagTypes->AddOption("lower all letters"); TagTypes->AddItem("lower all letters");
TagTypes->AddSeparator(); TagTypes->AddSeparator();
TagTypes->AddOption("Reset"); TagTypes->AddItem("Reset");
TagTypes->AddOption("Save"); TagTypes->AddItem("Save");
Tags = new Menu<MPD::MutableSong>(RightColumnStartX, MainStartY, RightColumnWidth, MainHeight, Config.titles_visibility ? "Tags" : "", Config.main_color, brNone); Tags = new Menu<MPD::MutableSong>(RightColumnStartX, MainStartY, RightColumnWidth, MainHeight, Config.titles_visibility ? "Tags" : "", Config.main_color, brNone);
Tags->HighlightColor(Config.main_highlight_color); Tags->HighlightColor(Config.main_highlight_color);
@@ -117,10 +117,10 @@ void TagEditor::Init()
FParserDialog->CyclicScrolling(Config.use_cyclic_scrolling); FParserDialog->CyclicScrolling(Config.use_cyclic_scrolling);
FParserDialog->CenteredCursor(Config.centered_cursor); FParserDialog->CenteredCursor(Config.centered_cursor);
FParserDialog->setItemDisplayer(Display::Default<std::string>); FParserDialog->setItemDisplayer(Display::Default<std::string>);
FParserDialog->AddOption("Get tags from filename"); FParserDialog->AddItem("Get tags from filename");
FParserDialog->AddOption("Rename files"); FParserDialog->AddItem("Rename files");
FParserDialog->AddSeparator(); FParserDialog->AddSeparator();
FParserDialog->AddOption("Cancel"); FParserDialog->AddItem("Cancel");
FParser = new Menu<std::string>((COLS-FParserWidth)/2, (MainHeight-FParserHeight)/2+MainStartY, FParserWidthOne, FParserHeight, "_", Config.main_color, Config.active_window_border); FParser = new Menu<std::string>((COLS-FParserWidth)/2, (MainHeight-FParserHeight)/2+MainStartY, FParserWidthOne, FParserHeight, "_", Config.main_color, Config.active_window_border);
FParser->CyclicScrolling(Config.use_cyclic_scrolling); FParser->CyclicScrolling(Config.use_cyclic_scrolling);
@@ -252,10 +252,10 @@ void TagEditor::Update()
l.push_back(s); l.push_back(s);
}); });
if (!l.empty()) if (!l.empty())
Albums->AddOption(std::make_pair(l[0].toString(Config.tag_editor_album_format), *it)); Albums->AddItem(std::make_pair(l[0].toString(Config.tag_editor_album_format), *it));
} }
Mpd.BlockIdle(0); Mpd.BlockIdle(0);
Albums->Sort<CaseInsensitiveSorting>(); std::sort(Albums->Begin(), Albums->End(), CaseInsensitiveSorting());
} }
else else
{ {
@@ -266,18 +266,18 @@ void TagEditor::Update()
{ {
size_t slash = itsBrowsedDir.rfind("/"); size_t slash = itsBrowsedDir.rfind("/");
std::string parent = slash != std::string::npos ? itsBrowsedDir.substr(0, slash) : "/"; std::string parent = slash != std::string::npos ? itsBrowsedDir.substr(0, slash) : "/";
Dirs->AddOption(make_pair("[..]", parent)); Dirs->AddItem(make_pair("[..]", parent));
} }
else else
{ {
Dirs->AddOption(std::make_pair(".", "/")); Dirs->AddItem(std::make_pair(".", "/"));
} }
for (MPD::TagList::const_iterator it = list.begin(); it != list.end(); ++it) for (MPD::TagList::const_iterator it = list.begin(); it != list.end(); ++it)
{ {
size_t slash = it->rfind("/"); size_t slash = it->rfind("/");
std::string to_display = slash != std::string::npos ? it->substr(slash+1) : *it; std::string to_display = slash != std::string::npos ? it->substr(slash+1) : *it;
utf_to_locale(to_display); utf_to_locale(to_display);
Dirs->AddOption(make_pair(to_display, *it)); Dirs->AddItem(make_pair(to_display, *it));
if (*it == itsHighlightedDir) if (*it == itsHighlightedDir)
highlightme = Dirs->Size()-1; highlightme = Dirs->Size()-1;
} }
@@ -303,7 +303,7 @@ void TagEditor::Update()
}); });
std::sort(list.begin(), list.end(), CaseInsensitiveSorting()); std::sort(list.begin(), list.end(), CaseInsensitiveSorting());
for (auto it = list.begin(); it != list.end(); ++it) for (auto it = list.begin(); it != list.end(); ++it)
Tags->AddOption(*it); Tags->AddItem(*it);
} }
} }
else else
@@ -311,7 +311,7 @@ void TagEditor::Update()
Mpd.GetSongs(Dirs->Current().second, list); Mpd.GetSongs(Dirs->Current().second, list);
std::sort(list.begin(), list.end(), CaseInsensitiveSorting()); std::sort(list.begin(), list.end(), CaseInsensitiveSorting());
for (auto it = list.begin(); it != list.end(); ++it) for (auto it = list.begin(); it != list.end(); ++it)
Tags->AddOption(*it); Tags->AddItem(*it);
} }
Tags->Window::Clear(); Tags->Window::Clear();
Tags->Refresh(); Tags->Refresh();
@@ -380,19 +380,19 @@ void TagEditor::EnterPressed()
Config.pattern = Patterns.front(); Config.pattern = Patterns.front();
FParser->Clear(); FParser->Clear();
FParser->Reset(); FParser->Reset();
FParser->AddOption("Pattern: " + Config.pattern); FParser->AddItem("Pattern: " + Config.pattern);
FParser->AddOption("Preview"); FParser->AddItem("Preview");
FParser->AddOption("Legend"); FParser->AddItem("Legend");
FParser->AddSeparator(); FParser->AddSeparator();
FParser->AddOption("Proceed"); FParser->AddItem("Proceed");
FParser->AddOption("Cancel"); FParser->AddItem("Cancel");
if (!Patterns.empty()) if (!Patterns.empty())
{ {
FParser->AddSeparator(); FParser->AddSeparator();
FParser->AddOption("Recent patterns", 1, 1); FParser->AddItem("Recent patterns", 1, 1);
FParser->AddSeparator(); FParser->AddSeparator();
for (std::list<std::string>::const_iterator it = Patterns.begin(); it != Patterns.end(); ++it) for (std::list<std::string>::const_iterator it = Patterns.begin(); it != Patterns.end(); ++it)
FParser->AddOption(*it); FParser->AddItem(*it);
} }
FParser->SetTitle(choice == 0 ? "Get tags from filename" : "Rename files"); FParser->SetTitle(choice == 0 ? "Get tags from filename" : "Rename files");