class Menu is template now / bunch of code clean-ups.

This commit is contained in:
unK
2008-09-03 01:16:26 +02:00
parent 451f2e112e
commit 723de0687e
10 changed files with 1021 additions and 954 deletions

View File

@@ -25,18 +25,14 @@ extern MPDConnection *Mpd;
extern ncmpcpp_config Config;
extern Menu *mPlaylist;
extern Menu *mBrowser;
extern Menu *mTagEditor;
extern Menu *mSearcher;
extern Menu *mPlaylistEditor;
extern Menu<Song> *mPlaylist;
extern Menu<Item> *mBrowser;
extern Menu<string> *mTagEditor;
extern Menu<string> *mSearcher;
extern Menu<Song> *mPlaylistEditor;
extern Window *wFooter;
extern SongList vPlaylist;
extern SongList vPlaylistContent;
extern ItemList vBrowser;
extern NcmpcppScreen current_screen;
extern Song edited_song;
@@ -64,36 +60,56 @@ extern string UNKNOWN_ARTIST;
extern string UNKNOWN_TITLE;
extern string UNKNOWN_ALBUM;
void UpdateItemList(const ItemList &v, Menu *menu, int i)
void UpdateItemList(Menu<Item> *menu)
{
bool bold = 0;
for (ItemList::const_iterator it = v.begin(); it != v.end(); it++, i++)
for (int i = 0; i < menu->Size(); i++)
{
if (it->type == itSong)
if (menu->at(i).type == itSong)
{
for (SongList::const_iterator j = vPlaylist.begin(); j != vPlaylist.end(); j++)
for (int j = 0; j < mPlaylist->Size(); j++)
{
if ((*j)->GetHash() == it->song->GetHash())
if (mPlaylist->at(j).GetHash() == menu->at(i).song->GetHash())
{
bold = 1;
break;
}
}
menu->BoldOption(i, bold);
menu->BoldOption(i+1, bold);
bold = 0;
}
}
menu->Refresh();
}
void UpdateSongList(const SongList &v, Menu *menu, int i)
void UpdateSongList(Menu<Song> *menu)
{
bool bold = 0;
for (int i = 0; i < menu->Size(); i++)
{
for (int j = 0; j < mPlaylist->Size(); j++)
{
if (mPlaylist->at(j).GetHash() == menu->at(i).GetHash())
{
bold = 1;
break;
}
}
menu->BoldOption(i+1, bold);
bold = 0;
}
menu->Refresh();
}
void UpdateFoundList(const SongList &v, Menu<string> *menu)
{
int i = search_engine_static_option+1;
bool bold = 0;
for (SongList::const_iterator it = v.begin(); it != v.end(); it++, i++)
{
for (SongList::const_iterator j = vPlaylist.begin(); j != vPlaylist.end(); j++)
for (int j = 0; j < mPlaylist->Size(); j++)
{
if ((*j)->GetHash() == (*it)->GetHash())
if (mPlaylist->at(j).GetHash() == (*it)->GetHash())
{
bold = 1;
break;
@@ -108,16 +124,12 @@ void UpdateSongList(const SongList &v, Menu *menu, int i)
void DeleteSong(int id)
{
Mpd->QueueDeleteSong(id);
delete vPlaylist[id];
vPlaylist.erase(vPlaylist.begin()+id);
mPlaylist->DeleteOption(id+1);
}
void PlaylistDeleteSong(const string &path, int id)
{
Mpd->QueueDeleteFromPlaylist(path, id);
delete vPlaylistContent[id];
vPlaylistContent.erase(vPlaylistContent.begin()+id);
mPlaylistEditor->DeleteOption(id+1);
}
@@ -125,7 +137,6 @@ bool MoveSongUp(int pos)
{
if (pos > 0 && !mPlaylist->Empty() && current_screen == csPlaylist)
{
std::swap<Song *>(vPlaylist[pos], vPlaylist[pos-1]);
mPlaylist->Swap(pos, pos-1);
Mpd->Move(pos, pos-1);
return true;
@@ -136,9 +147,8 @@ bool MoveSongUp(int pos)
bool MoveSongDown(int pos)
{
if (pos+1 < vPlaylist.size() && !mPlaylist->Empty() && current_screen == csPlaylist)
if (pos+1 < mPlaylist->Size() && !mPlaylist->Empty() && current_screen == csPlaylist)
{
std::swap<Song *>(vPlaylist[pos+1], vPlaylist[pos]);
mPlaylist->Swap(pos+1, pos);
Mpd->Move(pos, pos+1);
return true;
@@ -161,7 +171,7 @@ bool PlaylistMoveSongUp(const string &path, int pos)
bool PlaylistMoveSongDown(const string &path, int pos)
{
if (pos+1 < mPlaylistEditor->MaxChoice() && !mPlaylistEditor->Empty() && current_screen == csPlaylistEditor)
if (pos+1 < mPlaylistEditor->Size() && !mPlaylistEditor->Empty() && current_screen == csPlaylistEditor)
{
mPlaylistEditor->Swap(pos+1, pos);
Mpd->Move(path, pos, pos+1);
@@ -260,8 +270,8 @@ string TotalPlaylistLength()
const int YEAR = 365*DAY;
string result;
int length = 0;
for (SongList::const_iterator it = vPlaylist.begin(); it != vPlaylist.end(); it++)
length += (*it)->GetTotalLength();
for (int i = 0; i < mPlaylist->Size(); i++)
length += mPlaylist->at(i).GetTotalLength();
if (!length)
return result;
@@ -305,8 +315,22 @@ string TotalPlaylistLength()
return result;
}
string DisplaySong(const Song &s, const string &song_template)
string DisplayItem(const Item &item, void *)
{
switch (item.type)
{
case itDirectory:
return "[" + item.name + "]";
case itSong:
return DisplaySong(*item.song);
case itPlaylist:
return Config.browser_playlist_prefix + item.name;
}
}
string DisplaySong(const Song &s, void *s_template)
{
const string &song_template = s_template ? *static_cast<string *>(s_template) : "";
string result;
bool link_tags = 0;
bool tags_present = 0;
@@ -801,26 +825,26 @@ void GetDirectory(string dir)
if (browsed_dir != dir)
mBrowser->Reset();
browsed_dir = dir;
vBrowser.clear();
mBrowser->Clear(0);
if (dir != "/")
{
mBrowser->AddOption("[..]");
Item parent;
parent.name = "..";
parent.type = itDirectory;
vBrowser.push_back(parent);
mBrowser->AddOption(parent);
}
Mpd->GetDirectory(dir, vBrowser);
sort(vBrowser.begin(), vBrowser.end(), SortDirectory);
ItemList list;
Mpd->GetDirectory(dir, list);
sort(list.begin(), list.end(), SortDirectory);
for (ItemList::iterator it = vBrowser.begin()+(dir != "/" ? 1 : 0); it != vBrowser.end(); it++)
for (ItemList::iterator it = list.begin(); it != list.end(); it++)
{
switch (it->type)
{
case itPlaylist:
{
mBrowser->AddOption(Config.browser_playlist_prefix + string(it->name));
mBrowser->AddOption(*it);
break;
}
case itDirectory:
@@ -831,25 +855,24 @@ void GetDirectory(string dir)
directory = subdir.substr(browsed_dir.size()-1,subdir.size()-browsed_dir.size()+1);
else
directory = subdir.substr(browsed_dir.size()+1,subdir.size()-browsed_dir.size()-1);
mBrowser->AddOption("[" + directory + "]");
if (directory == browsed_subdir)
highlightme = mBrowser->MaxChoice();
highlightme = mBrowser->Size()+1;
it->name = directory;
mBrowser->AddOption(*it);
break;
}
case itSong:
{
Song *s = it->song;
bool bold = 0;
for (SongList::const_iterator it = vPlaylist.begin(); it != vPlaylist.end(); it++)
for (int i = 0; i < mPlaylist->Size(); i++)
{
if ((*it)->GetHash() == s->GetHash())
if (mPlaylist->at(i).GetHash() == it->song->GetHash())
{
bold = 1;
break;
}
}
bold ? mBrowser->AddBoldOption(DisplaySong(*s)) : mBrowser->AddOption(DisplaySong(*s));
bold ? mBrowser->AddBoldOption(*it) : mBrowser->AddOption(*it);
break;
}
}

View File

@@ -30,8 +30,9 @@
extern ncmpcpp_config Config;
void UpdateItemList(const ItemList &, Menu *, int = 1);
void UpdateSongList(const SongList &, Menu *, int = 1);
void UpdateItemList(Menu<Item> *);
void UpdateSongList(Menu<Song> *);
void UpdateFoundList(const SongList &, Menu<string> *);
void DeleteSong(int);
void PlaylistDeleteSong(const string &, int);
@@ -46,7 +47,8 @@ bool SortSongsByTrack(Song *, Song *);
bool CaseInsensitiveComparison(string, string);
void WindowTitle(const string &);
string TotalPlaylistLength();
string DisplaySong(const Song &, const string & = Config.song_list_format);
string DisplayItem(const Item &, void * = NULL);
string DisplaySong(const Song &, void * = &Config.song_list_format);
void ShowMessage(const string &, int = Config.message_delay_time);
bool SortDirectory(const Item &a, const Item &b);
void GetDirectory(string);

View File

@@ -19,635 +19,10 @@
***************************************************************************/
#include "menu.h"
#include "misc.h"
Menu::Menu(const Menu &m) : Window(m)
template <>
string Menu<string>::DisplayOption(const string &str) const
{
for (vector<Option *>::const_iterator it = m.itsOptions.begin(); it != m.itsOptions.end(); it++)
{
Option *new_option = new Option(**it);
itsOptions.push_back(new_option);
}
NeedsRedraw = m.NeedsRedraw;
itsSelectedPrefix = m.itsSelectedPrefix;
itsSelectedSuffix = m.itsSelectedSuffix;
itsStaticsNumber = m.itsStaticsNumber;
itsBeginning = m.itsBeginning;
itsHighlight = m.itsHighlight;
itsHighlightColor = m.itsHighlightColor;
itsHighlightEnabled = m.itsHighlightEnabled;
return str;
}
Menu::~Menu()
{
for (vector<Option *>::iterator it = itsOptions.begin(); it != itsOptions.end(); it++)
delete *it;
}
int Menu::count_length(string str)
{
if (str.empty())
return 0;
bool collect = false;
int length = 0;
#ifdef UTF8_ENABLED
wstring str2 = ToWString(str);
wstring tmp;
#else
string &str2 = str;
string tmp;
#endif
for (int i = 0; i < str2.length(); i++, length++)
{
if (str2[i] == '[')
collect = 1;
if (collect)
tmp += str2[i];
if (str2[i] == ']')
collect = 0;
if (!collect && !tmp.empty())
{
if (is_valid_color(TO_STRING(tmp)))
length -= tmp.length();
tmp.clear();
}
}
return length;
}
void Menu::AddOption(const string &str, Location location, bool separator)
{
Option *new_option = new Option;
new_option->content = str;
new_option->location = location;
new_option->have_separator = separator;
itsOptions.push_back(new_option);
if (itsOptions.size() > itsBeginning && itsOptions.size() <= itsBeginning+itsHeight)
NeedsRedraw.push_back(itsOptions.size()-1);
}
void Menu::AddBoldOption(const string &str, Location location, bool separator)
{
Option *new_option = new Option;
new_option->content = str;
new_option->location = location;
new_option->have_separator = separator;
new_option->is_bold = 1;
itsOptions.push_back(new_option);
if (itsOptions.size() > itsBeginning && itsOptions.size() <= itsBeginning+itsHeight)
NeedsRedraw.push_back(itsOptions.size()-1);
}
void Menu::AddStaticOption(const string &str, Location location, bool separator)
{
Option *new_option = new Option;
new_option->content = str;
new_option->location = location;
new_option->have_separator = separator;
new_option->is_static = 1;
itsOptions.push_back(new_option);
itsStaticsNumber++;
if (itsOptions.size() > itsBeginning && itsOptions.size() <= itsBeginning+itsHeight)
NeedsRedraw.push_back(itsOptions.size()-1);
}
void Menu::AddStaticBoldOption(const string &str, Location location, bool separator)
{
Option *new_option = new Option;
new_option->content = str;
new_option->location = location;
new_option->have_separator = separator;
new_option->is_static = 1;
new_option->is_bold = 1;
itsOptions.push_back(new_option);
itsStaticsNumber++;
if (itsOptions.size() > itsBeginning && itsOptions.size() <= itsBeginning+itsHeight)
NeedsRedraw.push_back(itsOptions.size()-1);
}
void Menu::AddSeparator()
{
AddStaticOption("", lLeft, 1);
}
void Menu::UpdateOption(int index, string str, Location location, bool separator)
{
index--;
try
{
itsOptions.at(index)->location = location;
itsOptions.at(index)->content = str;
itsOptions.at(index)->have_separator = separator;
if (index >= itsBeginning && index < itsBeginning+itsHeight)
NeedsRedraw.push_back(index);
}
catch (std::out_of_range)
{
}
}
void Menu::BoldOption(int index, bool bold)
{
index--;
try
{
itsOptions.at(index)->is_bold = bold;
if (index >= itsBeginning && index < itsBeginning+itsHeight)
NeedsRedraw.push_back(index);
}
catch (std::out_of_range)
{
}
}
void Menu::MakeStatic(int index, bool stat)
{
index--;
try
{
if (stat && !itsOptions.at(index)->is_static)
itsStaticsNumber++;
if (!stat && itsOptions.at(index)->is_static)
itsStaticsNumber--;
itsOptions.at(index)->is_static = stat;
}
catch (std::out_of_range)
{
}
}
string Menu::GetCurrentOption() const
{
try
{
return itsOptions.at(itsHighlight)->content;
}
catch (std::out_of_range)
{
return "";
}
}
string Menu::GetOption(int i) const
{
try
{
return itsOptions.at(i-1)->content;
}
catch (std::out_of_range)
{
return "";
}
}
void Menu::DeleteOption(int no)
{
no--;
try
{
if (itsOptions.at(no)->is_static)
itsStaticsNumber--;
}
catch (std::out_of_range)
{
return;
}
delete itsOptions[no];
itsOptions.erase(itsOptions.begin()+no);
if (itsHighlight > itsOptions.size()-1)
itsHighlight = itsOptions.size()-1;
idlok(itsWindow, 1);
scrollok(itsWindow, 1);
int MaxBeginning = itsOptions.size() < itsHeight ? 0 : itsOptions.size()-itsHeight;
if (itsBeginning > MaxBeginning)
{
itsBeginning = MaxBeginning;
wmove(itsWindow, no-itsBeginning, 0);
wdeleteln(itsWindow);
wscrl(itsWindow, -1);
NeedsRedraw.push_back(itsBeginning);
}
else
{
wmove(itsWindow, no-itsBeginning, 0);
wdeleteln(itsWindow);
}
NeedsRedraw.push_back(itsHighlight);
NeedsRedraw.push_back(itsBeginning+itsHeight-1);
scrollok(itsWindow, 0);
idlok(itsWindow, 0);
}
void Menu::Swap(int one, int two)
{
try
{
std::swap<Option *>(itsOptions.at(one), itsOptions.at(two));
NeedsRedraw.push_back(one);
NeedsRedraw.push_back(two);
}
catch (std::out_of_range)
{
}
}
void Menu::redraw_screen()
{
NeedsRedraw.clear();
vector<Option *>::const_iterator it = itsOptions.begin()+itsBeginning;
NeedsRedraw.reserve(itsHeight);
for (int i = itsBeginning; i < itsBeginning+itsHeight && it != itsOptions.end(); i++, it++)
NeedsRedraw.push_back(i);
}
void Menu::Display(bool redraw_whole_window)
{
Window::show_border();
Refresh(redraw_whole_window);
}
void Menu::Refresh(bool redraw_whole_window)
{
if (!itsOptions.empty() && is_static())
itsHighlight == 0 ? Go(wDown) : Go(wUp);
int MaxBeginning = itsOptions.size() < itsHeight ? 0 : itsOptions.size()-itsHeight;
if (itsBeginning > MaxBeginning)
itsBeginning = MaxBeginning;
if (itsHighlight >= itsOptions.size()-1)
Highlight(itsOptions.size());
if (redraw_whole_window)
{
Window::Clear();
redraw_screen();
}
for (vector<int>::const_iterator it = NeedsRedraw.begin(); it != NeedsRedraw.end(); it++)
{
try
{
itsOptions.at(*it);
}
catch (std::out_of_range)
{
break;
}
int line = *it-itsBeginning;
if (line < 0 || line+1 > itsHeight) // do not draw if line should be invisible anyway
continue;
Color old_basecolor = itsBaseColor;
if (*it == itsHighlight && itsHighlightEnabled)
{
Reverse(1);
SetBaseColor(itsHighlightColor);
SetColor(itsHighlightColor);
}
if (itsOptions[*it]->is_bold)
Bold(1);
int ch = itsOptions[*it]->have_separator ? 0 : 32;
mvwhline(itsWindow,line, 0, ch, itsWidth);
int strlength = itsOptions[*it]->location != lLeft && BBEnabled ? count_length(itsOptions[*it]->content) : itsOptions[*it]->content.length();
if (strlength)
{
int x = 0;
if (itsOptions[*it]->location == lCenter)
{
for (; x < (itsWidth-strlength-(!ch ? 4 : 0))/2; x++);
if (!ch)
{
AltCharset(1);
mvwaddstr(itsWindow, line, x, "u ");
AltCharset(0);
x += 2;
}
}
if (itsOptions[*it]->location == lRight)
{
for (; x < (itsWidth-strlength); x++)
if (!ch)
{
AltCharset(1);
mvwaddstr(itsWindow, line, x, "u ");
AltCharset(0);
x += 2;
}
}
# ifdef UTF8_ENABLED
if (itsOptions[*it]->selected)
WriteXY(x, line, itsWidth, ToWString(itsSelectedPrefix + itsOptions[*it]->content + itsSelectedSuffix), 0);
else
WriteXY(x, line, itsWidth, ToWString(itsOptions[*it]->content), 0);
# else
if (itsOptions[*it]->selected)
WriteXY(x, line, itsWidth, itsSelectedPrefix + itsOptions[*it]->content + itsSelectedSuffix, 0);
else
WriteXY(x, line, itsWidth, itsOptions[*it]->content, 0);
# endif
if (!ch && (itsOptions[*it]->location == lCenter || itsOptions[*it]->location == lLeft))
{
x += strlength;
AltCharset(1);
mvwaddstr(itsWindow, line, x, " t");
AltCharset(0);
}
}
SetBaseColor(old_basecolor);
SetColor(old_basecolor);
while (!itsColors.empty()) // clear color stack and disable bold and reverse as
itsColors.pop(); // some items are too long to close all tags properly
Reverse(0);
Bold(0);
}
NeedsRedraw.clear();
wrefresh(itsWindow);
}
void Menu::Go(Where where)
{
if (Empty()) return;
int MaxHighlight = itsOptions.size()-1;
int MaxBeginning = itsOptions.size() < itsHeight ? 0 : itsOptions.size()-itsHeight;
int MaxCurrentHighlight = itsBeginning+itsHeight-1;
idlok(itsWindow, 1);
scrollok(itsWindow, 1);
switch (where)
{
case wUp:
{
if (itsHighlight <= itsBeginning && itsHighlight > 0)
{
itsBeginning--; // for scrolling
wscrl(itsWindow, -1);
}
if (itsHighlight == 0)
break;
else
{
NeedsRedraw.push_back(itsHighlight--);
NeedsRedraw.push_back(itsHighlight);
}
if (is_static())
{
if (itsHighlight == 0)
Go(wDown);
else
Go(wUp);
}
break;
}
case wDown:
{
if (itsHighlight >= MaxCurrentHighlight && itsHighlight < MaxHighlight)
{
itsBeginning++; // scroll
wscrl(itsWindow, 1);
}
if (itsHighlight == MaxHighlight)
break;
else
{
NeedsRedraw.push_back(itsHighlight++);
NeedsRedraw.push_back(itsHighlight);
}
if (is_static())
{
if (itsHighlight == MaxHighlight)
Go(wUp);
else
Go(wDown);
}
break;
}
case wPageUp:
{
itsHighlight -= itsHeight;
itsBeginning -= itsHeight;
if (itsBeginning < 0)
{
itsBeginning = 0;
if (itsHighlight < 0) itsHighlight = 0;
}
if (is_static())
{
if (itsHighlight == 0)
Go(wDown);
else
Go(wUp);
}
redraw_screen();
break;
}
case wPageDown:
{
itsHighlight += itsHeight;
itsBeginning += itsHeight;
if (itsBeginning > MaxBeginning)
{
itsBeginning = MaxBeginning;
if (itsHighlight > MaxHighlight) itsHighlight = MaxHighlight;
}
if (is_static())
{
if (itsHighlight == MaxHighlight)
Go(wUp);
else
Go(wDown);
}
redraw_screen();
break;
}
case wHome:
{
itsHighlight = 0;
itsBeginning = 0;
if (is_static())
{
if (itsHighlight == 0)
Go(wDown);
else
Go(wUp);
}
redraw_screen();
break;
}
case wEnd:
{
itsHighlight = MaxHighlight;
itsBeginning = MaxBeginning;
if (is_static())
{
if (itsHighlight == MaxHighlight)
Go(wUp);
else
Go(wDown);
}
redraw_screen();
break;
}
}
idlok(itsWindow, 0);
scrollok(itsWindow, 0);
}
void Menu::Highlight(int which)
{
which--;
int old_highlight = itsHighlight;
int old_beginning = itsBeginning;
if (which < itsOptions.size())
itsHighlight = which;
else
return;
if (which >= itsHeight/2 && itsOptions.size() > itsHeight)
{
itsBeginning = itsHighlight-itsHeight/2;
if (itsBeginning > itsOptions.size()-itsHeight)
itsBeginning = itsOptions.size()-itsHeight;
}
else
itsBeginning = 0;
int howmuch = itsBeginning-old_beginning;
if (Abs(howmuch) > itsHeight)
redraw_screen();
else
{
idlok(itsWindow, 1);
scrollok(itsWindow, 1);
if (old_highlight >= itsBeginning && old_highlight < itsBeginning+itsHeight)
NeedsRedraw.push_back(old_highlight);
wscrl(itsWindow, howmuch);
if (howmuch < 0)
for (int i = 0; i < Abs(howmuch); i++)
NeedsRedraw.push_back(itsBeginning+i);
else
for (int i = 0; i < Abs(howmuch); i++)
NeedsRedraw.push_back(itsBeginning+itsHeight-1-i);
NeedsRedraw.push_back(itsHighlight);
scrollok(itsWindow, 0);
idlok(itsWindow, 0);
}
}
void Menu::Reset()
{
NeedsRedraw.clear();
itsHighlight = 0;
itsBeginning = 0;
}
void Menu::Clear(bool clear_screen)
{
for (vector<Option *>::iterator it = itsOptions.begin(); it != itsOptions.end(); it++)
delete *it;
itsOptions.clear();
NeedsRedraw.clear();
itsStaticsNumber = 0;
if (clear_screen)
Window::Clear();
}
void Menu::Select(int option, bool selected)
{
option--;
try
{
if (itsOptions.at(option)->selected != selected)
NeedsRedraw.push_back(option);
itsOptions.at(option)->selected = selected;
}
catch (std::out_of_range)
{
}
}
bool Menu::Selected(int option)
{
option--;
try
{
return itsOptions.at(option)->selected;
}
catch (std::out_of_range)
{
return false;
}
}
bool Menu::IsAnySelected()
{
bool result = 0;
for (vector<Option *>::const_iterator it = itsOptions.begin(); it != itsOptions.end(); it++)
{
if ((*it)->selected)
{
result = 1;
break;
}
}
return result;
}
void Menu::GetSelectedList(vector<int> &v)
{
int i = 1;
for (vector<Option *>::const_iterator it = itsOptions.begin(); it != itsOptions.end(); it++, i++)
if ((*it)->selected)
v.push_back(i);
}
int Menu::GetRealChoice() const
{
int real_choice = 0;
vector<Option *>::const_iterator it = itsOptions.begin();
for (int i = 0; i < itsHighlight; it++, i++)
if (!(*it)->is_static) real_choice++;
return real_choice+1;
}
bool Menu::IsStatic(int option)
{
try
{
return itsOptions.at(option-1)->is_static;
}
catch (std::out_of_range)
{
return 1;
}
}
Window * Menu::EmptyClone()
{
return new Menu(GetStartX(),GetStartY(),GetWidth(),GetHeight(),itsTitle,itsBaseColor,itsBorder);
}

View File

@@ -22,15 +22,17 @@
#define HAVE_MENU_H
#include "window.h"
#include "misc.h"
#include <stdexcept>
enum Location { lLeft, lCenter, lRight };
template <class T>
struct Option
{
Option() : is_static(0), is_bold(0), selected(0), have_separator(0) { }
string content;
T item;
bool is_static;
bool is_bold;
bool selected;
@@ -38,56 +40,73 @@ struct Option
Location location;
};
template <class T>
class Menu : public Window
{
typedef typename vector<Option<T> *>::iterator T_iterator;
typedef typename vector<Option<T> *>::const_iterator T_const_iterator;
typedef string (*ItemDisplayer) (const T &, void *);
public:
Menu(int startx, int starty, int width, int height, string title, Color color, Border border) : Window(startx, starty, width, height, title, color, border), itsSelectedPrefix("[r]"), itsSelectedSuffix("[/r]"), itsStaticsNumber(0), itsBeginning(0), itsHighlight(0), itsHighlightColor(itsBaseColor), itsHighlightEnabled(1) { SetColor(color); }
Menu(int startx, int starty, int width, int height, string title, Color color, Border border) : itsItemDisplayer(0), itsUserdata(0), Window(startx, starty, width, height, title, color, border), itsSelectedPrefix("[r]"), itsSelectedSuffix("[/r]"), itsStaticsNumber(0), itsBeginning(0), itsHighlight(0), itsHighlightColor(itsBaseColor), itsHighlightEnabled(1) { SetColor(color); }
Menu(const Menu &);
virtual ~Menu();
virtual void Add(string str) { AddOption(str); }
void AddOption(const string &, Location = lLeft, bool separator = 0);
void AddBoldOption(const string &str, Location location = lLeft, bool separator = 0);
void AddStaticOption(const string &str, Location location = lLeft, bool separator = 0);
void AddStaticBoldOption(const string &str, Location location = lLeft, bool separator = 0);
void SetItemDisplayer(ItemDisplayer ptr) { itsItemDisplayer = ptr; }
void SetItemDisplayerUserData(void *data) { itsUserdata = data; }
void AddOption(const T &, Location = lLeft, bool separator = 0);
void AddBoldOption(const T &item, Location location = lLeft, bool separator = 0);
void AddStaticOption(const T &item, Location location = lLeft, bool separator = 0);
void AddStaticBoldOption(const T &item, Location location = lLeft, bool separator = 0);
void AddSeparator();
void UpdateOption(int, string, Location = lLeft, bool separator = 0);
void UpdateOption(int, const T &, Location = lLeft, bool separator = 0);
void BoldOption(int, bool);
void MakeStatic(int, bool);
void DeleteOption(int);
void Swap(int, int);
string GetCurrentOption() const;
string GetOption(int i) const;
virtual string GetOption(int i) const;
virtual void Display(bool redraw_whole_window = 0);
virtual void Refresh(bool redraw_whole_window = 0);
virtual void Go(Where);
void Highlight(int);
virtual void Highlight(int);
virtual void Reset();
virtual void Clear(bool clear_screen = 1);
void Select(int, bool);
bool Selected(int);
bool IsAnySelected();
virtual void Select(int, bool);
virtual bool Selected(int);
virtual bool IsAnySelected();
virtual void GetSelectedList(vector<int> &);
void SetSelectPrefix(string str) { itsSelectedPrefix = str; }
void SetSelectSuffix(string str) { itsSelectedSuffix = str; }
void GetSelectedList(vector<int> &);
void HighlightColor(Color col) { itsHighlightColor = col; NeedsRedraw.push_back(itsHighlight); }
void Highlighting(bool hl) { itsHighlightEnabled = hl; NeedsRedraw.push_back(itsHighlight); Refresh(); }
virtual void Highlighting(bool hl) { itsHighlightEnabled = hl; NeedsRedraw.push_back(itsHighlight); Refresh(); }
int GetRealChoice() const;
virtual int GetChoice() const { return itsHighlight+1; }
int MaxChoice() const { return itsOptions.size(); }
virtual int Size() const { return itsOptions.size(); }
int MaxRealChoice() const { return itsOptions.size()-itsStaticsNumber; }
bool Empty() { return itsOptions.empty(); }
bool IsStatic(int);
virtual bool IsStatic(int);
virtual Window * Clone() { return new Menu(*this); }
virtual Window * EmptyClone();
T & at(int i) { return itsOptions.at(i)->item; }
const T & at(int i) const { return itsOptions.at(i)->item; }
const T & operator[](int i) const { return itsOptions[i]->item; }
T & operator[](int i) { return itsOptions[i]->item; }
protected:
vector<Option *> itsOptions;
string DisplayOption(const T &t) const;
ItemDisplayer itsItemDisplayer;
void *itsUserdata;
vector<Option<T> *> itsOptions;
vector<int> NeedsRedraw;
string itsSelectedPrefix;
@@ -107,5 +126,677 @@ class Menu : public Window
bool itsHighlightEnabled;
};
template <class T>
Menu<T>::Menu(const Menu &m) : Window(m)
{
for (T_const_iterator it = m.itsOptions.begin(); it != m.itsOptions.end(); it++)
{
Option<T> *new_option = new Option<T>(**it);
itsOptions.push_back(new_option);
}
itsItemDisplayer = m.itsItemDisplayer;
itsUserdata = m.itsUserdata;
NeedsRedraw = m.NeedsRedraw;
itsSelectedPrefix = m.itsSelectedPrefix;
itsSelectedSuffix = m.itsSelectedSuffix;
itsStaticsNumber = m.itsStaticsNumber;
itsBeginning = m.itsBeginning;
itsHighlight = m.itsHighlight;
itsHighlightColor = m.itsHighlightColor;
itsHighlightEnabled = m.itsHighlightEnabled;
}
template <class T>
Menu<T>::~Menu()
{
for (T_iterator it = itsOptions.begin(); it != itsOptions.end(); it++)
delete *it;
}
template <class T>
int Menu<T>::count_length(string str)
{
if (str.empty())
return 0;
bool collect = false;
int length = 0;
#ifdef UTF8_ENABLED
wstring str2 = ToWString(str);
wstring tmp;
#else
string &str2 = str;
string tmp;
#endif
for (int i = 0; i < str2.length(); i++, length++)
{
if (str2[i] == '[')
collect = 1;
if (collect)
tmp += str2[i];
if (str2[i] == ']')
collect = 0;
if (!collect && !tmp.empty())
{
if (is_valid_color(TO_STRING(tmp)))
length -= tmp.length();
tmp.clear();
}
}
return length;
}
template <class T>
void Menu<T>::AddOption(const T &item, Location location, bool separator)
{
Option<T> *new_option = new Option<T>;
new_option->item = item;
new_option->location = location;
new_option->have_separator = separator;
itsOptions.push_back(new_option);
if (itsOptions.size() > itsBeginning && itsOptions.size() <= itsBeginning+itsHeight)
NeedsRedraw.push_back(itsOptions.size()-1);
}
template <class T>
void Menu<T>::AddBoldOption(const T &item, Location location, bool separator)
{
Option<T> *new_option = new Option<T>;
new_option->item = item;
new_option->location = location;
new_option->have_separator = separator;
new_option->is_bold = 1;
itsOptions.push_back(new_option);
if (itsOptions.size() > itsBeginning && itsOptions.size() <= itsBeginning+itsHeight)
NeedsRedraw.push_back(itsOptions.size()-1);
}
template <class T>
void Menu<T>::AddStaticOption(const T &item, Location location, bool separator)
{
Option<T> *new_option = new Option<T>;
new_option->item = item;
new_option->location = location;
new_option->have_separator = separator;
new_option->is_static = 1;
itsOptions.push_back(new_option);
itsStaticsNumber++;
if (itsOptions.size() > itsBeginning && itsOptions.size() <= itsBeginning+itsHeight)
NeedsRedraw.push_back(itsOptions.size()-1);
}
template <class T>
void Menu<T>::AddStaticBoldOption(const T &item, Location location, bool separator)
{
Option<T> *new_option = new Option<T>;
new_option->item = item;
new_option->location = location;
new_option->have_separator = separator;
new_option->is_static = 1;
new_option->is_bold = 1;
itsOptions.push_back(new_option);
itsStaticsNumber++;
if (itsOptions.size() > itsBeginning && itsOptions.size() <= itsBeginning+itsHeight)
NeedsRedraw.push_back(itsOptions.size()-1);
}
template <class T>
void Menu<T>::AddSeparator()
{
AddStaticOption("", lLeft, 1);
}
template <class T>
void Menu<T>::UpdateOption(int index, const T &item, Location location, bool separator)
{
index--;
try
{
itsOptions.at(index)->location = location;
itsOptions.at(index)->item = item;
itsOptions.at(index)->have_separator = separator;
if (index >= itsBeginning && index < itsBeginning+itsHeight)
NeedsRedraw.push_back(index);
}
catch (std::out_of_range)
{
}
}
template <class T>
void Menu<T>::BoldOption(int index, bool bold)
{
index--;
try
{
itsOptions.at(index)->is_bold = bold;
if (index >= itsBeginning && index < itsBeginning+itsHeight)
NeedsRedraw.push_back(index);
}
catch (std::out_of_range)
{
}
}
template <class T>
void Menu<T>::MakeStatic(int index, bool stat)
{
index--;
try
{
if (stat && !itsOptions.at(index)->is_static)
itsStaticsNumber++;
if (!stat && itsOptions.at(index)->is_static)
itsStaticsNumber--;
itsOptions.at(index)->is_static = stat;
}
catch (std::out_of_range)
{
}
}
template <class T>
string Menu<T>::GetCurrentOption() const
{
try
{
return OmitBBCodes(DisplayOption(itsOptions.at(itsHighlight)->item));
}
catch (std::out_of_range)
{
return "";
}
}
template <class T>
string Menu<T>::GetOption(int i) const
{
try
{
return OmitBBCodes(DisplayOption(itsOptions.at(i-1)->item));
}
catch (std::out_of_range)
{
return "";
}
}
template <class T>
void Menu<T>::DeleteOption(int no)
{
no--;
try
{
if (itsOptions.at(no)->is_static)
itsStaticsNumber--;
}
catch (std::out_of_range)
{
return;
}
delete itsOptions[no];
itsOptions.erase(itsOptions.begin()+no);
if (itsHighlight > itsOptions.size()-1)
itsHighlight = itsOptions.size()-1;
idlok(itsWindow, 1);
scrollok(itsWindow, 1);
int MaxBeginning = itsOptions.size() < itsHeight ? 0 : itsOptions.size()-itsHeight;
if (itsBeginning > MaxBeginning)
{
itsBeginning = MaxBeginning;
wmove(itsWindow, no-itsBeginning, 0);
wdeleteln(itsWindow);
wscrl(itsWindow, -1);
NeedsRedraw.push_back(itsBeginning);
}
else
{
wmove(itsWindow, no-itsBeginning, 0);
wdeleteln(itsWindow);
}
NeedsRedraw.push_back(itsHighlight);
NeedsRedraw.push_back(itsBeginning+itsHeight-1);
scrollok(itsWindow, 0);
idlok(itsWindow, 0);
}
template <class T>
void Menu<T>::Swap(int one, int two)
{
try
{
std::swap<Option<T> *>(itsOptions.at(one), itsOptions.at(two));
NeedsRedraw.push_back(one);
NeedsRedraw.push_back(two);
}
catch (std::out_of_range)
{
}
}
template <class T>
void Menu<T>::redraw_screen()
{
NeedsRedraw.clear();
T_const_iterator it = itsOptions.begin()+itsBeginning;
NeedsRedraw.reserve(itsHeight);
for (int i = itsBeginning; i < itsBeginning+itsHeight && it != itsOptions.end(); i++, it++)
NeedsRedraw.push_back(i);
}
template <class T>
void Menu<T>::Display(bool redraw_whole_window)
{
Window::show_border();
Refresh(redraw_whole_window);
}
template <class T>
void Menu<T>::Refresh(bool redraw_whole_window)
{
if (!itsOptions.empty() && is_static())
itsHighlight == 0 ? Go(wDown) : Go(wUp);
int MaxBeginning = itsOptions.size() < itsHeight ? 0 : itsOptions.size()-itsHeight;
if (itsBeginning > MaxBeginning)
itsBeginning = MaxBeginning;
if (itsHighlight >= itsOptions.size()-1)
Highlight(itsOptions.size());
if (redraw_whole_window)
{
Window::Clear();
redraw_screen();
}
for (vector<int>::const_iterator it = NeedsRedraw.begin(); it != NeedsRedraw.end(); it++)
{
try
{
itsOptions.at(*it);
}
catch (std::out_of_range)
{
break;
}
int line = *it-itsBeginning;
if (line < 0 || line+1 > itsHeight) // do not draw if line should be invisible anyway
continue;
Color old_basecolor = itsBaseColor;
if (*it == itsHighlight && itsHighlightEnabled)
{
Reverse(1);
SetBaseColor(itsHighlightColor);
SetColor(itsHighlightColor);
}
if (itsOptions[*it]->is_bold)
Bold(1);
int ch = itsOptions[*it]->have_separator ? 0 : 32;
mvwhline(itsWindow,line, 0, ch, itsWidth);
string option = DisplayOption(itsOptions[*it]->item);
int strlength = itsOptions[*it]->location != lLeft && BBEnabled ? count_length(option) : option.length();
if (strlength)
{
int x = 0;
if (itsOptions[*it]->location == lCenter)
{
for (; x < (itsWidth-strlength-(!ch ? 4 : 0))/2; x++);
if (!ch)
{
AltCharset(1);
mvwaddstr(itsWindow, line, x, "u ");
AltCharset(0);
x += 2;
}
}
if (itsOptions[*it]->location == lRight)
{
for (; x < (itsWidth-strlength); x++)
if (!ch)
{
AltCharset(1);
mvwaddstr(itsWindow, line, x, "u ");
AltCharset(0);
x += 2;
}
}
# ifdef UTF8_ENABLED
if (itsOptions[*it]->selected)
WriteXY(x, line, itsWidth, ToWString(itsSelectedPrefix + option + itsSelectedSuffix), 0);
else
WriteXY(x, line, itsWidth, ToWString(option), 0);
# else
if (itsOptions[*it]->selected)
WriteXY(x, line, itsWidth, itsSelectedPrefix + option + itsSelectedSuffix, 0);
else
WriteXY(x, line, itsWidth, option, 0);
# endif
if (!ch && (itsOptions[*it]->location == lCenter || itsOptions[*it]->location == lLeft))
{
x += strlength;
AltCharset(1);
mvwaddstr(itsWindow, line, x, " t");
AltCharset(0);
}
}
SetBaseColor(old_basecolor);
SetColor(old_basecolor);
while (!itsColors.empty()) // clear color stack and disable bold and reverse as
itsColors.pop(); // some items are too long to close all tags properly
AltCharset(0);
Reverse(0);
Bold(0);
}
NeedsRedraw.clear();
wrefresh(itsWindow);
}
template <class T>
void Menu<T>::Go(Where where)
{
if (Empty()) return;
int MaxHighlight = itsOptions.size()-1;
int MaxBeginning = itsOptions.size() < itsHeight ? 0 : itsOptions.size()-itsHeight;
int MaxCurrentHighlight = itsBeginning+itsHeight-1;
idlok(itsWindow, 1);
scrollok(itsWindow, 1);
switch (where)
{
case wUp:
{
if (itsHighlight <= itsBeginning && itsHighlight > 0)
{
itsBeginning--; // for scrolling
wscrl(itsWindow, -1);
}
if (itsHighlight == 0)
break;
else
{
NeedsRedraw.push_back(itsHighlight--);
NeedsRedraw.push_back(itsHighlight);
}
if (is_static())
{
if (itsHighlight == 0)
Go(wDown);
else
Go(wUp);
}
break;
}
case wDown:
{
if (itsHighlight >= MaxCurrentHighlight && itsHighlight < MaxHighlight)
{
itsBeginning++; // scroll
wscrl(itsWindow, 1);
}
if (itsHighlight == MaxHighlight)
break;
else
{
NeedsRedraw.push_back(itsHighlight++);
NeedsRedraw.push_back(itsHighlight);
}
if (is_static())
{
if (itsHighlight == MaxHighlight)
Go(wUp);
else
Go(wDown);
}
break;
}
case wPageUp:
{
itsHighlight -= itsHeight;
itsBeginning -= itsHeight;
if (itsBeginning < 0)
{
itsBeginning = 0;
if (itsHighlight < 0) itsHighlight = 0;
}
if (is_static())
{
if (itsHighlight == 0)
Go(wDown);
else
Go(wUp);
}
redraw_screen();
break;
}
case wPageDown:
{
itsHighlight += itsHeight;
itsBeginning += itsHeight;
if (itsBeginning > MaxBeginning)
{
itsBeginning = MaxBeginning;
if (itsHighlight > MaxHighlight) itsHighlight = MaxHighlight;
}
if (is_static())
{
if (itsHighlight == MaxHighlight)
Go(wUp);
else
Go(wDown);
}
redraw_screen();
break;
}
case wHome:
{
itsHighlight = 0;
itsBeginning = 0;
if (is_static())
{
if (itsHighlight == 0)
Go(wDown);
else
Go(wUp);
}
redraw_screen();
break;
}
case wEnd:
{
itsHighlight = MaxHighlight;
itsBeginning = MaxBeginning;
if (is_static())
{
if (itsHighlight == MaxHighlight)
Go(wUp);
else
Go(wDown);
}
redraw_screen();
break;
}
}
idlok(itsWindow, 0);
scrollok(itsWindow, 0);
}
template <class T>
void Menu<T>::Highlight(int which)
{
which--;
int old_highlight = itsHighlight;
int old_beginning = itsBeginning;
if (which < itsOptions.size())
itsHighlight = which;
else
return;
if (which >= itsHeight/2 && itsOptions.size() > itsHeight)
{
itsBeginning = itsHighlight-itsHeight/2;
if (itsBeginning > itsOptions.size()-itsHeight)
itsBeginning = itsOptions.size()-itsHeight;
}
else
itsBeginning = 0;
int howmuch = itsBeginning-old_beginning;
if (Abs(howmuch) > itsHeight)
redraw_screen();
else
{
idlok(itsWindow, 1);
scrollok(itsWindow, 1);
if (old_highlight >= itsBeginning && old_highlight < itsBeginning+itsHeight)
NeedsRedraw.push_back(old_highlight);
wscrl(itsWindow, howmuch);
if (howmuch < 0)
for (int i = 0; i < Abs(howmuch); i++)
NeedsRedraw.push_back(itsBeginning+i);
else
for (int i = 0; i < Abs(howmuch); i++)
NeedsRedraw.push_back(itsBeginning+itsHeight-1-i);
NeedsRedraw.push_back(itsHighlight);
scrollok(itsWindow, 0);
idlok(itsWindow, 0);
}
}
template <class T>
void Menu<T>::Reset()
{
NeedsRedraw.clear();
itsHighlight = 0;
itsBeginning = 0;
}
template <class T>
void Menu<T>::Clear(bool clear_screen)
{
for (T_iterator it = itsOptions.begin(); it != itsOptions.end(); it++)
delete *it;
itsOptions.clear();
NeedsRedraw.clear();
itsStaticsNumber = 0;
if (clear_screen)
Window::Clear();
}
template <class T>
void Menu<T>::Select(int option, bool selected)
{
option--;
try
{
if (itsOptions.at(option)->selected != selected)
NeedsRedraw.push_back(option);
itsOptions.at(option)->selected = selected;
}
catch (std::out_of_range)
{
}
}
template <class T>
bool Menu<T>::Selected(int option)
{
option--;
try
{
return itsOptions.at(option)->selected;
}
catch (std::out_of_range)
{
return false;
}
}
template <class T>
bool Menu<T>::IsAnySelected()
{
bool result = 0;
for (T_const_iterator it = itsOptions.begin(); it != itsOptions.end(); it++)
{
if ((*it)->selected)
{
result = 1;
break;
}
}
return result;
}
template <class T>
void Menu<T>::GetSelectedList(vector<int> &v)
{
int i = 1;
for (T_const_iterator it = itsOptions.begin(); it != itsOptions.end(); it++, i++)
if ((*it)->selected)
v.push_back(i);
}
template <class T>
int Menu<T>::GetRealChoice() const
{
int real_choice = 0;
T_const_iterator it = itsOptions.begin();
for (int i = 0; i < itsHighlight; it++, i++)
if (!(*it)->is_static) real_choice++;
return real_choice+1;
}
template <class T>
bool Menu<T>::IsStatic(int option)
{
try
{
return itsOptions.at(option-1)->is_static;
}
catch (std::out_of_range)
{
return 1;
}
}
template <class T>
Window * Menu<T>::EmptyClone()
{
return new Menu(GetStartX(),GetStartY(),GetWidth(),GetHeight(),itsTitle,itsBaseColor,itsBorder);
}
template <class T>
string Menu<T>::DisplayOption(const T &t) const
{
return itsItemDisplayer ? itsItemDisplayer(t, itsUserdata) : "";
}
#endif

View File

@@ -66,29 +66,22 @@
ncmpcpp_config Config;
ncmpcpp_keys Key;
SongList vPlaylist;
SongList vSearched;
SongList vLibSongs;
SongList vPlaylistContent;
ItemList vBrowser;
TagList vArtists;
vector<int> vFoundPositions;
int found_pos = 0;
Window *wCurrent = 0;
Window *wPrev = 0;
Menu *mPlaylist;
Menu *mBrowser;
Menu *mTagEditor;
Menu *mSearcher;
Menu *mLibArtists;
Menu *mLibAlbums;
Menu *mLibSongs;
Menu *mPlaylistList;
Menu *mPlaylistEditor;
Menu<Song> *mPlaylist;
Menu<Item> *mBrowser;
Menu<string> *mTagEditor;
Menu<string> *mSearcher;
Menu<string> *mLibArtists;
Menu<string> *mLibAlbums;
Menu<Song> *mLibSongs;
Menu<string> *mPlaylistList;
Menu<Song> *mPlaylistEditor;
Scrollpad *sHelp;
Scrollpad *sLyrics;
@@ -197,13 +190,19 @@ int main(int argc, char *argv[])
if (!Config.statusbar_visibility)
main_height++;
mPlaylist = new Menu(0, main_start_y, COLS, main_height, "", Config.main_color, brNone);
mPlaylist = new Menu<Song>(0, main_start_y, COLS, main_height, "", Config.main_color, brNone);
mPlaylist->SetSelectPrefix(Config.selected_item_prefix);
mPlaylist->SetSelectSuffix(Config.selected_item_suffix);
mPlaylist->SetItemDisplayer(DisplaySong);
mPlaylist->SetItemDisplayerUserData(&Config.song_list_format);
mBrowser = static_cast<Menu *>(mPlaylist->Clone());
mTagEditor = static_cast<Menu *>(mPlaylist->Clone());
mSearcher = static_cast<Menu *>(mPlaylist->Clone());
mBrowser = new Menu<Item>(0, main_start_y, COLS, main_height, "", Config.main_color, brNone);
mBrowser->SetSelectPrefix(Config.selected_item_prefix);
mBrowser->SetSelectSuffix(Config.selected_item_suffix);
mBrowser->SetItemDisplayer(DisplayItem);
mTagEditor = new Menu<string>(0, main_start_y, COLS, main_height, "", Config.main_color, brNone);
mSearcher = static_cast<Menu<string> *>(mTagEditor->Clone());
int lib_artist_width = COLS/3-1;
int lib_albums_width = COLS/3;
@@ -211,16 +210,20 @@ int main(int argc, char *argv[])
int lib_songs_width = COLS-COLS/3*2-1;
int lib_songs_start_x = lib_artist_width+lib_albums_width+2;
mLibArtists = new Menu(0, main_start_y, lib_artist_width, main_height, "Artists", Config.main_color, brNone);
mLibAlbums = new Menu(lib_albums_start_x, main_start_y, lib_albums_width, main_height, "Albums", Config.main_color, brNone);
mLibSongs = new Menu(lib_songs_start_x, main_start_y, lib_songs_width, main_height, "Songs", Config.main_color, brNone);
mLibArtists = new Menu<string>(0, main_start_y, lib_artist_width, main_height, "Artists", Config.main_color, brNone);
mLibAlbums = new Menu<string>(lib_albums_start_x, main_start_y, lib_albums_width, main_height, "Albums", Config.main_color, brNone);
mLibSongs = new Menu<Song>(lib_songs_start_x, main_start_y, lib_songs_width, main_height, "Songs", Config.main_color, brNone);
mLibSongs->SetSelectPrefix(Config.selected_item_prefix);
mLibSongs->SetSelectSuffix(Config.selected_item_suffix);
mLibSongs->SetItemDisplayer(DisplaySong);
mLibSongs->SetItemDisplayerUserData(&Config.song_library_format);
mPlaylistList = new Menu(0, main_start_y, lib_artist_width, main_height, "Playlists", Config.main_color, brNone);
mPlaylistEditor = new Menu(lib_albums_start_x, main_start_y, lib_albums_width+lib_songs_width+1, main_height, "Playlist's content", Config.main_color, brNone);
mPlaylistList = new Menu<string>(0, main_start_y, lib_artist_width, main_height, "Playlists", Config.main_color, brNone);
mPlaylistEditor = new Menu<Song>(lib_albums_start_x, main_start_y, lib_albums_width+lib_songs_width+1, main_height, "Playlist's content", Config.main_color, brNone);
mPlaylistEditor->SetSelectPrefix(Config.selected_item_prefix);
mPlaylistEditor->SetSelectSuffix(Config.selected_item_suffix);
mPlaylistEditor->SetItemDisplayer(DisplaySong);
mPlaylistEditor->SetItemDisplayerUserData(&Config.song_list_format);
sHelp = new Scrollpad(0, main_start_y, COLS, main_height, "", Config.main_color, brNone);
sLyrics = static_cast<Scrollpad *>(sHelp->EmptyClone());
@@ -465,11 +468,13 @@ int main(int argc, char *argv[])
{
if (mLibArtists->Empty())
{
found_pos = 0;
vFoundPositions.clear();
TagList list;
mLibAlbums->Clear(0);
vArtists.clear();
Mpd->GetArtists(vArtists);
sort(vArtists.begin(), vArtists.end(), CaseInsensitiveComparison);
for (TagList::const_iterator it = vArtists.begin(); it != vArtists.end(); it++)
Mpd->GetArtists(list);
sort(list.begin(), list.end(), CaseInsensitiveComparison);
for (TagList::const_iterator it = list.begin(); it != list.end(); it++)
mLibArtists->AddOption(*it);
mLibArtists->Window::Clear();
mLibArtists->Refresh();
@@ -477,6 +482,7 @@ int main(int argc, char *argv[])
if (mLibAlbums->Empty())
{
mLibAlbums->Reset();
mLibSongs->Clear(0);
TagList list;
Mpd->GetAlbums(mLibArtists->GetCurrentOption(), list);
@@ -513,14 +519,15 @@ int main(int argc, char *argv[])
if (mLibSongs->Empty())
{
FreeSongList(vLibSongs);
mLibSongs->Reset();
SongList list;
if (mLibAlbums->Empty())
{
mLibAlbums->WriteXY(0, 0, "No albums found.");
mLibSongs->Clear(0);
Mpd->StartSearch(1);
Mpd->AddSearch(MPD_TAG_ITEM_ARTIST, mLibArtists->GetCurrentOption());
Mpd->CommitSearch(vLibSongs);
Mpd->CommitSearch(list);
}
else
{
@@ -528,32 +535,33 @@ int main(int argc, char *argv[])
Mpd->StartSearch(1);
Mpd->AddSearch(MPD_TAG_ITEM_ARTIST, mLibArtists->GetCurrentOption());
Mpd->AddSearch(MPD_TAG_ITEM_ALBUM, mLibAlbums->GetCurrentOption());
Mpd->CommitSearch(vLibSongs);
if (vLibSongs.empty())
Mpd->CommitSearch(list);
if (list.empty())
{
const string &album = mLibAlbums->GetCurrentOption();
Mpd->StartSearch(1);
Mpd->AddSearch(MPD_TAG_ITEM_ARTIST, mLibArtists->GetCurrentOption());
Mpd->AddSearch(MPD_TAG_ITEM_ALBUM, album.substr(7, album.length()-7));
Mpd->CommitSearch(vLibSongs);
Mpd->CommitSearch(list);
}
}
sort(vLibSongs.begin(), vLibSongs.end(), SortSongsByTrack);
sort(list.begin(), list.end(), SortSongsByTrack);
bool bold = 0;
for (SongList::const_iterator it = vLibSongs.begin(); it != vLibSongs.end(); it++)
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
{
for (SongList::const_iterator j = vPlaylist.begin(); j != vPlaylist.end(); j++)
for (int j = 0; j < mPlaylist->Size(); j++)
{
if ((*it)->GetHash() == (*j)->GetHash())
if ((*it)->GetHash() == mPlaylist->at(j).GetHash())
{
bold = 1;
break;
}
}
bold ? mLibSongs->AddBoldOption(DisplaySong(**it, Config.song_library_format)) : mLibSongs->AddOption(DisplaySong(**it, Config.song_library_format));
bold ? mLibSongs->AddBoldOption(**it) : mLibSongs->AddOption(**it);
bold = 0;
}
FreeSongList(list);
mLibSongs->Window::Clear();
mLibSongs->Refresh();
}
@@ -578,28 +586,31 @@ int main(int argc, char *argv[])
if (mPlaylistEditor->Empty())
{
FreeSongList(vPlaylistContent);
Mpd->GetPlaylistContent(mPlaylistList->GetCurrentOption(), vPlaylistContent);
mPlaylistEditor->Reset();
SongList list;
Mpd->GetPlaylistContent(mPlaylistList->GetCurrentOption(), list);
bool bold = 0;
for (SongList::const_iterator it = vPlaylistContent.begin(); it != vPlaylistContent.end(); it++)
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
{
for (SongList::const_iterator j = vPlaylist.begin(); j != vPlaylist.end(); j++)
for (int j = 0; j < mPlaylist->Size(); j++)
{
if ((*it)->GetHash() == (*j)->GetHash())
if ((*it)->GetHash() == mPlaylist->at(j).GetHash())
{
bold = 1;
break;
}
}
bold ? mPlaylistEditor->AddBoldOption(DisplaySong(**it)) : mPlaylistEditor->AddOption(DisplaySong(**it));
bold ? mPlaylistEditor->AddBoldOption(**it) : mPlaylistEditor->AddOption(**it);
bold = 0;
}
FreeSongList(list);
mPlaylistEditor->Window::Clear();
mPlaylistEditor->Refresh();
}
if (wCurrent == mPlaylistEditor && mPlaylistEditor->Empty())
{
mPlaylistEditor->HighlightColor(Config.main_highlight_color);
mPlaylistList->HighlightColor(Config.active_column_color);
wCurrent = mPlaylistList;
@@ -653,37 +664,11 @@ int main(int argc, char *argv[])
if (Keypressed(input, Key.Up))
{
if (wCurrent == mLibArtists)
{
wCurrent->Timeout(50);
while (Keypressed(input, Key.Up))
{
TraceMpdStatus();
wCurrent->Go(wUp);
wCurrent->Refresh();
wCurrent->ReadKey(input);
}
wCurrent->Timeout(ncmpcpp_window_timeout);
}
else
wCurrent->Go(wUp);
wCurrent->Go(wUp);
}
else if (Keypressed(input, Key.Down))
{
if (wCurrent == mLibArtists)
{
wCurrent->Timeout(50);
while (Keypressed(input, Key.Down))
{
TraceMpdStatus();
wCurrent->Go(wDown);
wCurrent->Refresh();
wCurrent->ReadKey(input);
}
wCurrent->Timeout(ncmpcpp_window_timeout);
}
else
wCurrent->Go(wDown);
wCurrent->Go(wDown);
}
else if (Keypressed(input, Key.PageUp))
{
@@ -764,8 +749,8 @@ int main(int argc, char *argv[])
wFooter->Resize(COLS, wFooter->GetHeight());
if (wCurrent != sHelp)
wCurrent->Hide();
wCurrent->Display(redraw_me);
wCurrent->Window::Clear();
wCurrent->Refresh(1);
if (current_screen == csLibrary)
{
REFRESH_MEDIA_LIBRARY_SCREEN;
@@ -799,21 +784,21 @@ int main(int argc, char *argv[])
case csPlaylist:
{
if (!mPlaylist->Empty())
Mpd->PlayID(vPlaylist[mPlaylist->GetChoice()-1]->GetID());
Mpd->PlayID(mPlaylist->at(mPlaylist->GetChoice()-1).GetID());
break;
}
case csBrowser:
{
GO_TO_PARENT_DIR:
int ci = mBrowser->GetChoice()-1;
switch (vBrowser[ci].type)
const Item &item = mBrowser->at(mBrowser->GetChoice()-1);
switch (item.type)
{
case itDirectory:
{
found_pos = 0;
vFoundPositions.clear();
if (browsed_dir != "/" && ci == 0)
if (item.name == "..")
{
int i = browsed_dir.size();
while (browsed_dir[--i] != '/');
@@ -832,15 +817,15 @@ int main(int argc, char *argv[])
else
{
if (browsed_dir != "/")
GetDirectory(browsed_dir + "/" + vBrowser[ci].name);
GetDirectory(browsed_dir + "/" + item.name);
else
GetDirectory(vBrowser[ci].name);
GetDirectory(item.name);
}
break;
}
case itSong:
{
Song &s = *vBrowser[ci].song;
Song &s = *item.song;
int id = Mpd->AddSong(s);
if (id >= 0)
{
@@ -853,13 +838,13 @@ int main(int argc, char *argv[])
case itPlaylist:
{
SongList list;
Mpd->GetPlaylistContent(vBrowser[ci].name, list);
Mpd->GetPlaylistContent(item.name, list);
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
Mpd->QueueAddSong(**it);
if (Mpd->CommitQueue())
{
ShowMessage("Loading and playing playlist " + vBrowser[ci].name + "...");
Song *s = vPlaylist[vPlaylist.size()-list.size()];
ShowMessage("Loading and playing playlist " + item.name + "...");
Song *s = &mPlaylist->at(mPlaylist->Size()-list.size());
if (s->GetHash() == list[0]->GetHash())
Mpd->PlayID(s->GetID());
else
@@ -972,8 +957,7 @@ int main(int argc, char *argv[])
Mpd->UpdateDirectory(s.GetDirectory());
if (prev_screen == csSearcher)
{
int upid = mSearcher->GetChoice()-search_engine_static_option-1;
*vSearched[upid] = s;
*vSearched[mSearcher->GetRealChoice()-2] = s;
mSearcher->UpdateOption(mSearcher->GetChoice(), DisplaySong(s));
}
}
@@ -989,20 +973,12 @@ int main(int argc, char *argv[])
redraw_me = 1;
if (current_screen == csLibrary)
{
# ifdef HAVE_TAGLIB_H
if (id == 8)
{
mLibSongs->HighlightColor(Config.main_highlight_color);
mLibArtists->HighlightColor(Config.active_column_color);
wCurrent = mLibArtists;
}
else
wCurrent = wPrev;
# else
wCurrent = wPrev;
# endif
REFRESH_MEDIA_LIBRARY_SCREEN;
}
else if (current_screen == csPlaylistEditor)
{
REFRESH_PLAYLIST_EDITOR_SCREEN;
}
# ifdef HAVE_TAGLIB_H
break;
}
@@ -1128,9 +1104,9 @@ int main(int argc, char *argv[])
for (SongList::const_iterator it = vSearched.begin(); it != vSearched.end(); it++)
{
for (SongList::const_iterator j = vPlaylist.begin(); j != vPlaylist.end(); j++)
for (int j = 0; j < mPlaylist->Size(); j++)
{
if ((*j)->GetHash() == (*it)->GetHash())
if (mPlaylist->at(j).GetHash() == (*it)->GetHash())
{
bold = 1;
break;
@@ -1190,7 +1166,7 @@ int main(int argc, char *argv[])
if (Mpd->CommitQueue())
{
ShowMessage("Adding all songs artist's: " + artist);
Song *s = vPlaylist[vPlaylist.size()-list.size()];
Song *s = &mPlaylist->at(mPlaylist->GetChoice()-list.size());
if (s->GetHash() == list[0]->GetHash())
{
if (Keypressed(input, Key.Enter))
@@ -1202,13 +1178,13 @@ int main(int argc, char *argv[])
}
else if (wCurrent == mLibAlbums)
{
for (SongList::const_iterator it = vLibSongs.begin(); it != vLibSongs.end(); it++)
Mpd->QueueAddSong(**it);
for (int i = 0; i < mLibSongs->Size(); i++)
Mpd->QueueAddSong(mLibSongs->at(i));
if (Mpd->CommitQueue())
{
ShowMessage("Adding songs from: " + mLibArtists->GetCurrentOption() + " \"" + mLibAlbums->GetCurrentOption() + "\"");
Song *s = vPlaylist[vPlaylist.size()-vLibSongs.size()];
if (s->GetHash() == vLibSongs[0]->GetHash())
Song *s = &mPlaylist->at(mPlaylist->Size()-mLibSongs->Size());
if (s->GetHash() == mLibSongs->at(0).GetHash())
{
if (Keypressed(input, Key.Enter))
Mpd->PlayID(s->GetID());
@@ -1219,9 +1195,9 @@ int main(int argc, char *argv[])
}
else if (wCurrent == mLibSongs)
{
if (!vLibSongs.empty())
if (!mLibSongs->Empty())
{
Song &s = *vLibSongs[mLibSongs->GetChoice()-1];
Song &s = mLibSongs->at(mLibSongs->GetChoice()-1);
int id = Mpd->AddSong(s);
if (id >= 0)
{
@@ -1251,11 +1227,11 @@ int main(int argc, char *argv[])
if (Mpd->CommitQueue())
{
ShowMessage("Loading playlist " + playlist + "...");
Song *s = vPlaylist[vPlaylist.size()-list.size()];
if (s->GetHash() == list[0]->GetHash())
Song &s = mPlaylist->at(mPlaylist->Size()-list.size());
if (s.GetHash() == list[0]->GetHash())
{
if (Keypressed(input, Key.Enter))
Mpd->PlayID(s->GetID());
Mpd->PlayID(s.GetID());
}
else
ShowMessage(message_part_of_songs_added);
@@ -1263,9 +1239,9 @@ int main(int argc, char *argv[])
}
else if (wCurrent == mPlaylistEditor)
{
if (!vPlaylistContent.empty())
if (!mPlaylistEditor->Empty())
{
Song &s = *vPlaylistContent[mPlaylistEditor->GetChoice()-1];
Song &s = mPlaylistEditor->at(mPlaylistEditor->GetChoice()-1);
int id = Mpd->AddSong(s);
if (id >= 0)
{
@@ -1290,22 +1266,21 @@ int main(int argc, char *argv[])
{
if (wCurrent == mPlaylist || (wCurrent == mBrowser && wCurrent->GetChoice() > (browsed_dir != "/" ? 1 : 0)) || (wCurrent == mSearcher && !vSearched.empty() && wCurrent->GetChoice() > search_engine_static_option) || wCurrent == mLibSongs || wCurrent == mPlaylistEditor)
{
Menu *mCurrent = static_cast<Menu *>(wCurrent);
int i = mCurrent->GetChoice();
mCurrent->Select(i, !mCurrent->Selected(i));
mCurrent->Go(wDown);
int i = wCurrent->GetChoice();
wCurrent->Select(i, !wCurrent->Selected(i));
wCurrent->Go(wDown);
}
}
else
{
if (current_screen == csBrowser)
{
int ci = mBrowser->GetChoice()-1;
switch (vBrowser[ci].type)
const Item &item = mBrowser->at(mBrowser->GetChoice()-1);
switch (item.type)
{
case itDirectory:
{
string getdir = browsed_dir == "/" ? vBrowser[ci].name : browsed_dir + "/" + vBrowser[ci].name;
string getdir = browsed_dir == "/" ? item.name : browsed_dir + "/" + item.name;
SongList list;
Mpd->GetDirectoryRecursive(getdir, list);
@@ -1315,8 +1290,8 @@ int main(int argc, char *argv[])
if (Mpd->CommitQueue())
{
ShowMessage("Added folder: " + getdir);
Song *s = vPlaylist[vPlaylist.size()-list.size()];
if (s->GetHash() != list[0]->GetHash())
Song &s = mPlaylist->at(mPlaylist->Size()-list.size());
if (s.GetHash() != list[0]->GetHash())
ShowMessage(message_part_of_songs_added);
}
FreeSongList(list);
@@ -1324,7 +1299,7 @@ int main(int argc, char *argv[])
}
case itSong:
{
Song &s = *vBrowser[ci].song;
Song &s = *item.song;
if (Mpd->AddSong(s) != -1)
ShowMessage("Added to playlist: " + OmitBBCodes(DisplaySong(s)));
break;
@@ -1332,14 +1307,14 @@ int main(int argc, char *argv[])
case itPlaylist:
{
SongList list;
Mpd->GetPlaylistContent(vBrowser[ci].name, list);
Mpd->GetPlaylistContent(item.name, list);
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
Mpd->QueueAddSong(**it);
if (Mpd->CommitQueue())
{
ShowMessage("Loading playlist " + vBrowser[ci].name + "...");
Song *s = vPlaylist[vPlaylist.size()-list.size()];
if (s->GetHash() != list[0]->GetHash())
ShowMessage("Loading playlist " + item.name + "...");
Song &s = mPlaylist->at(mPlaylist->Size()-list.size());
if (s.GetHash() != list[0]->GetHash())
ShowMessage(message_part_of_songs_added);
}
FreeSongList(list);
@@ -1453,7 +1428,7 @@ int main(int argc, char *argv[])
block_playlist_update = 1;
dont_change_now_playing = 1;
mPlaylist->Timeout(50);
while (!vPlaylist.empty() && Keypressed(input, Key.Delete))
while (!mPlaylist->Empty() && Keypressed(input, Key.Delete))
{
TraceMpdStatus();
timer = time(NULL);
@@ -1469,10 +1444,9 @@ int main(int argc, char *argv[])
else if (current_screen == csBrowser || wCurrent == mPlaylistList)
{
LOCK_STATUSBAR;
Menu *mCurrent = static_cast<Menu *>(wCurrent);
int id = mCurrent->GetChoice()-1;
const string &name = wCurrent == mBrowser ? vBrowser[id].name : mPlaylistList->GetCurrentOption();
if (current_screen != csBrowser || vBrowser[id].type == itPlaylist)
int id = wCurrent->GetChoice()-1;
const string &name = wCurrent == mBrowser ? mBrowser->at(id).name : mPlaylistList->at(id);
if (current_screen != csBrowser || mBrowser->at(id).type == itPlaylist)
{
wFooter->WriteXY(0, Config.statusbar_visibility, "Delete playlist " + name + " ? [y/n] ", 1);
curs_set(1);
@@ -1510,7 +1484,7 @@ int main(int argc, char *argv[])
else
{
mPlaylistEditor->Timeout(50);
while (!vPlaylistContent.empty() && Keypressed(input, Key.Delete))
while (!mPlaylistEditor->Empty() && Keypressed(input, Key.Delete))
{
TraceMpdStatus();
timer = time(NULL);
@@ -1580,7 +1554,7 @@ int main(int argc, char *argv[])
UNLOCK_STATUSBAR;
}
}
if (browsed_dir == "/" && !vBrowser.empty())
if (browsed_dir == "/" && !mBrowser->Empty())
GetDirectory(browsed_dir);
}
else if (Keypressed(input, Key.Stop))
@@ -1691,8 +1665,8 @@ int main(int argc, char *argv[])
Mpd->QueueAddSong(**it);
if (Mpd->CommitQueue())
{
Song *s = vPlaylist[vPlaylist.size()-list.size()];
if (s->GetHash() != list[0]->GetHash())
Song &s = mPlaylist->at(mPlaylist->Size()-list.size());
if (s.GetHash() != list[0]->GetHash())
ShowMessage(message_part_of_songs_added);
}
}
@@ -1705,7 +1679,7 @@ int main(int argc, char *argv[])
{
if (now_playing < 0)
continue;
if (!vPlaylist[now_playing]->GetTotalLength())
if (!mPlaylist->at(now_playing).GetTotalLength())
{
ShowMessage("Unknown item length!");
continue;
@@ -1716,7 +1690,7 @@ int main(int argc, char *argv[])
int songpos, in;
songpos = Mpd->GetElapsedTime();
Song &s = *vPlaylist[now_playing];
Song &s = mPlaylist->at(now_playing);
while (1)
{
@@ -1805,26 +1779,30 @@ int main(int argc, char *argv[])
}
else if (Keypressed(input, Key.EditTags))
{
if ((wCurrent == mPlaylist && !vPlaylist.empty())
|| (wCurrent == mBrowser && vBrowser[mBrowser->GetChoice()-1].type == itSong)
if ((wCurrent == mPlaylist && !mPlaylist->Empty())
|| (wCurrent == mBrowser && mBrowser->at(mBrowser->GetChoice()-1).type == itSong)
|| (wCurrent == mSearcher && !vSearched.empty() && mSearcher->GetChoice() > search_engine_static_option)
|| (wCurrent == mLibSongs && !vLibSongs.empty()))
|| (wCurrent == mLibSongs && !mLibSongs->Empty())
|| (wCurrent == mPlaylistEditor && !mPlaylistEditor->Empty()))
{
int id = wCurrent->GetChoice()-1;
Song *s;
switch (current_screen)
{
case csPlaylist:
s = vPlaylist[id];
s = &mPlaylist->at(id);
break;
case csBrowser:
s = vBrowser[id].song;
s = mBrowser->at(id).song;
break;
case csSearcher:
s = vSearched[id-search_engine_static_option];
break;
case csLibrary:
s = vLibSongs[id];
s = &mLibSongs->at(id);
break;
case csPlaylistEditor:
s = &mPlaylistEditor->at(id);
break;
default:
break;
@@ -1845,7 +1823,7 @@ int main(int argc, char *argv[])
if (wCurrent == mSearcher && !vSearched.empty() && mSearcher->GetChoice() > search_engine_static_option)
{
GetDirectory(vSearched[mSearcher->GetChoice()-search_engine_static_option-1]->GetDirectory());
for (int i = 1; i < mBrowser->MaxChoice(); i++)
for (int i = 1; i < mBrowser->Size(); i++)
{
if (mSearcher->GetCurrentOption() == mBrowser->GetOption(i))
{
@@ -1860,7 +1838,7 @@ int main(int argc, char *argv[])
{
if (wCurrent == mSearcher)
{
mSearcher->Highlight(13);
mSearcher->Highlight(13); // highlight 'search' button
goto ENTER_SEARCH_ENGINE_SCREEN;
}
}
@@ -1868,7 +1846,7 @@ int main(int argc, char *argv[])
{
if (now_playing < 0)
continue;
if (!vPlaylist[now_playing]->GetTotalLength())
if (!mPlaylist->at(now_playing).GetTotalLength())
{
ShowMessage("Unknown item length!");
continue;
@@ -1876,23 +1854,22 @@ int main(int argc, char *argv[])
LOCK_STATUSBAR;
wFooter->WriteXY(0, Config.statusbar_visibility, "Position to go (in %): ", 1);
string position = wFooter->GetString(3);
int newpos = atoi(position.c_str());
int newpos = StrToInt(position);
if (newpos > 0 && newpos < 100 && !position.empty())
Mpd->Seek(vPlaylist[now_playing]->GetTotalLength()*newpos/100.0);
Mpd->Seek(mPlaylist->at(now_playing).GetTotalLength()*newpos/100.0);
UNLOCK_STATUSBAR;
}
else if (Keypressed(input, Key.ReverseSelection))
{
if (wCurrent == mPlaylist || wCurrent == mBrowser || (wCurrent == mSearcher && !vSearched.empty()) || wCurrent == mLibSongs || wCurrent == mPlaylistEditor)
{
Menu *mCurrent = static_cast<Menu *>(wCurrent);
for (int i = 1; i <= mCurrent->MaxChoice(); i++)
mCurrent->Select(i, !mCurrent->Selected(i) && !mCurrent->IsStatic(i));
for (int i = 1; i <= wCurrent->Size(); i++)
wCurrent->Select(i, !wCurrent->Selected(i) && !wCurrent->IsStatic(i));
// hackish shit begins
if (mCurrent == mBrowser && browsed_dir != "/")
mCurrent->Select(1, 0); // [..] cannot be selected, uhm.
if (mCurrent == mSearcher)
mCurrent->Select(14, 0); // 'Reset' cannot be selected, omgplz.
if (wCurrent == mBrowser && browsed_dir != "/")
wCurrent->Select(1, 0); // [..] cannot be selected, uhm.
if (wCurrent == mSearcher)
wCurrent->Select(14, 0); // 'Reset' cannot be selected, omgplz.
// hacking shit ends. need better solution :/
ShowMessage("Selection reversed!");
}
@@ -1901,11 +1878,10 @@ int main(int argc, char *argv[])
{
if (wCurrent == mPlaylist || wCurrent == mBrowser || wCurrent == mSearcher || wCurrent == mLibSongs || wCurrent == mPlaylistEditor)
{
Menu *mCurrent = static_cast<Menu *>(wCurrent);
if (mCurrent->IsAnySelected())
if (wCurrent->IsAnySelected())
{
for (int i = 1; i <= mCurrent->MaxChoice(); i++)
mCurrent->Select(i, 0);
for (int i = 1; i <= wCurrent->Size(); i++)
wCurrent->Select(i, 0);
ShowMessage("Items deselected!");
}
}
@@ -1914,11 +1890,10 @@ int main(int argc, char *argv[])
{
if (wCurrent == mPlaylist || wCurrent == mBrowser || wCurrent == mSearcher || wCurrent == mLibSongs || wCurrent == mPlaylistEditor)
{
Menu *mCurrent = static_cast<Menu *>(wCurrent);
if (mCurrent->IsAnySelected())
if (wCurrent->IsAnySelected())
{
vector<int> list;
mCurrent->GetSelectedList(list);
wCurrent->GetSelectedList(list);
SongList result;
for (vector<int>::const_iterator it = list.begin(); it != list.end(); it++)
{
@@ -1926,31 +1901,32 @@ int main(int argc, char *argv[])
{
case csPlaylist:
{
Song *s = new Song(*vPlaylist[*it-1]);
Song *s = new Song(mPlaylist->at(*it-1));
result.push_back(s);
break;
}
case csBrowser:
{
switch (vBrowser[*it-1].type)
const Item &item = mBrowser->at(*it-1);
switch (item.type)
{
case itDirectory:
{
if (browsed_dir != "/")
Mpd->GetDirectoryRecursive(browsed_dir + "/" + vBrowser[*it-1].name, result);
Mpd->GetDirectoryRecursive(browsed_dir + "/" + item.name, result);
else
Mpd->GetDirectoryRecursive(vBrowser[*it-1].name, result);
Mpd->GetDirectoryRecursive(item.name, result);
break;
}
case itSong:
{
Song *s = new Song(*vBrowser[*it-1].song);
Song *s = new Song(*item.song);
result.push_back(s);
break;
}
case itPlaylist:
{
Mpd->GetPlaylistContent(vBrowser[*it-1].name, result);
Mpd->GetPlaylistContent(item.name, result);
break;
}
}
@@ -1964,13 +1940,13 @@ int main(int argc, char *argv[])
}
case csLibrary:
{
Song *s = new Song(*vLibSongs[*it-1]);
Song *s = new Song(mLibSongs->at(*it-1));
result.push_back(s);
break;
}
case csPlaylistEditor:
{
Song *s = new Song(*vPlaylistContent[*it-1]);
Song *s = new Song(mPlaylistEditor->at(*it-1));
result.push_back(s);
break;
}
@@ -1981,11 +1957,11 @@ int main(int argc, char *argv[])
const int dialog_width = COLS*0.8;
const int dialog_height = LINES*0.6;
Menu *mDialog = new Menu((COLS-dialog_width)/2, (LINES-dialog_height)/2, dialog_width, dialog_height, "Add selected items to...", clYellow, brGreen);
Menu<string> *mDialog = new Menu<string>((COLS-dialog_width)/2, (LINES-dialog_height)/2, dialog_width, dialog_height, "Add selected items to...", clYellow, brGreen);
mDialog->Timeout(ncmpcpp_window_timeout);
mDialog->AddOption("Current MPD playlist");
mDialog->AddOption("New playlist (m3u file)");
mDialog->AddOption("Create new playlist (m3u file)");
mDialog->AddSeparator();
TagList playlists;
Mpd->GetPlaylists(playlists);
@@ -2036,8 +2012,8 @@ int main(int argc, char *argv[])
if (Mpd->CommitQueue())
{
ShowMessage("Selected items added!");
Song *s = vPlaylist[vPlaylist.size()-result.size()];
if (s->GetHash() != result[0]->GetHash())
Song &s = mPlaylist->at(mPlaylist->Size()-result.size());
if (s.GetHash() != result[0]->GetHash())
ShowMessage(message_part_of_songs_added);
}
}
@@ -2056,7 +2032,7 @@ int main(int argc, char *argv[])
}
}
else if (id > 2 && id < mDialog->MaxChoice())
else if (id > 2 && id < mDialog->Size())
{
for (SongList::const_iterator it = result.begin(); it != result.end(); it++)
Mpd->QueueAddToPlaylist(playlists[id-4], **it);
@@ -2064,7 +2040,7 @@ int main(int argc, char *argv[])
ShowMessage("Selected items added to playlist '" + playlists[id-4] + "'!");
}
if (id != mDialog->MaxChoice())
if (id != mDialog->Size())
{
// refresh playlist's lists
if (browsed_dir == "/")
@@ -2082,15 +2058,15 @@ int main(int argc, char *argv[])
{
if (mPlaylist->IsAnySelected())
{
for (int i = 0; i < mPlaylist->MaxChoice(); i++)
for (int i = 0; i < mPlaylist->Size(); i++)
{
if (!mPlaylist->Selected(i+1) && i != now_playing)
Mpd->QueueDeleteSongId(vPlaylist[i]->GetID());
Mpd->QueueDeleteSongId(mPlaylist->at(i).GetID());
}
// if mpd deletes now playing song deletion will be sluggishly slow
// then so we have to assure it will be deleted at the very end.
if (!mPlaylist->Selected(now_playing+1))
Mpd->QueueDeleteSongId(vPlaylist[now_playing]->GetID());
Mpd->QueueDeleteSongId(mPlaylist->at(now_playing).GetID());
ShowMessage("Deleting all items but selected...");
Mpd->CommitQueue();
@@ -2103,10 +2079,10 @@ int main(int argc, char *argv[])
ShowMessage("Nothing is playing now!");
continue;
}
for (SongList::iterator it = vPlaylist.begin(); it != vPlaylist.begin()+now_playing; it++)
Mpd->QueueDeleteSongId((*it)->GetID());
for (SongList::iterator it = vPlaylist.begin()+now_playing+1; it != vPlaylist.end(); it++)
Mpd->QueueDeleteSongId((*it)->GetID());
for (int i = 0; i < now_playing; i++)
Mpd->QueueDeleteSongId(mPlaylist->at(i).GetID());
for (int i = now_playing+1; i < mPlaylist->Size(); i++)
Mpd->QueueDeleteSongId(mPlaylist->at(i).GetID());
ShowMessage("Deleting all items except now playing one...");
Mpd->CommitQueue();
ShowMessage("Items deleted!");
@@ -2126,7 +2102,6 @@ int main(int argc, char *argv[])
string how = Keypressed(input, Key.FindForward) ? "forward" : "backward";
found_pos = -1;
vFoundPositions.clear();
Menu *mCurrent = static_cast<Menu *>(wCurrent);
LOCK_STATUSBAR;
wFooter->WriteXY(0, Config.statusbar_visibility, "Find " + how + ": ", 1);
string findme = wFooter->GetString();
@@ -2136,7 +2111,9 @@ int main(int argc, char *argv[])
continue;
transform(findme.begin(), findme.end(), findme.begin(), tolower);
for (int i = 1; i <= mCurrent->MaxChoice(); i++)
Menu<Song> *mCurrent = static_cast<Menu<Song> *>(wCurrent);
for (int i = (wCurrent == mBrowser ? search_engine_static_option : 1); i <= mCurrent->Size(); i++)
{
string name = mCurrent->GetOption(i);
transform(name.begin(), name.end(), name.begin(), tolower);
@@ -2160,8 +2137,9 @@ int main(int argc, char *argv[])
ShowMessage("Unable to find \"" + findme + "\"");
else
{
mCurrent->Highlight(vFoundPositions[found_pos < 0 ? 0 : found_pos]);
mCurrent->Highlighting(1);
wCurrent->Highlight(vFoundPositions[found_pos < 0 ? 0 : found_pos]);
if (wCurrent == mPlaylist)
mPlaylist->Highlighting(1);
}
}
}
@@ -2169,10 +2147,9 @@ int main(int argc, char *argv[])
{
if (!vFoundPositions.empty())
{
Menu *mCurrent = static_cast<Menu *>(wCurrent);
try
{
mCurrent->Highlight(vFoundPositions.at(Keypressed(input, Key.NextFoundPosition) ? ++found_pos : --found_pos));
wCurrent->Highlight(vFoundPositions.at(Keypressed(input, Key.NextFoundPosition) ? ++found_pos : --found_pos));
}
catch (std::out_of_range)
{
@@ -2180,12 +2157,12 @@ int main(int argc, char *argv[])
{
if (Keypressed(input, Key.NextFoundPosition))
{
mCurrent->Highlight(vFoundPositions.front());
wCurrent->Highlight(vFoundPositions.front());
found_pos = 0;
}
else
{
mCurrent->Highlight(vFoundPositions.back());
wCurrent->Highlight(vFoundPositions.back());
found_pos = vFoundPositions.size()-1;
}
}
@@ -2208,7 +2185,7 @@ int main(int argc, char *argv[])
{
if (wCurrent == sLyrics)
{
wCurrent->Hide();
wCurrent->Window::Clear();
current_screen = prev_screen;
wCurrent = wPrev;
redraw_me = 1;
@@ -2216,38 +2193,45 @@ int main(int argc, char *argv[])
{
REFRESH_MEDIA_LIBRARY_SCREEN;
}
continue;
else if (current_screen == csPlaylistEditor)
{
REFRESH_PLAYLIST_EDITOR_SCREEN;
}
}
if ((wCurrent == mPlaylist && !vPlaylist.empty())
|| (wCurrent == mBrowser && vBrowser[mBrowser->GetChoice()-1].type == itSong)
else if (
(wCurrent == mPlaylist && !mPlaylist->Empty())
|| (wCurrent == mBrowser && mBrowser->at(mBrowser->GetChoice()-1).type == itSong)
|| (wCurrent == mSearcher && !vSearched.empty() && mSearcher->GetChoice() > search_engine_static_option)
|| (wCurrent == mLibSongs && !vLibSongs.empty()))
|| (wCurrent == mLibSongs && !mLibSongs->Empty())
|| (wCurrent == mPlaylistEditor && !mPlaylistEditor->Empty()))
{
Song *s;
int id = wCurrent->GetChoice()-1;
switch (current_screen)
{
case csPlaylist:
s = vPlaylist[mPlaylist->GetChoice()-1];
s = &mPlaylist->at(id);
break;
case csBrowser:
s = vBrowser[mBrowser->GetChoice()-1].song;
s = mBrowser->at(id).song;
break;
case csSearcher:
s = vSearched[mSearcher->GetRealChoice()-2]; // first one is 'Reset'
s = vSearched[id-search_engine_static_option]; // first one is 'Reset'
break;
case csLibrary:
s = vLibSongs[mLibSongs->GetChoice()-1];
s = &mLibSongs->at(id);
break;
case csPlaylistEditor:
s = &mPlaylistEditor->at(id);
break;
default:
break;
}
if (s->GetArtist() != UNKNOWN_ARTIST && s->GetTitle() != UNKNOWN_TITLE)
{
wPrev = wCurrent;
prev_screen = current_screen;
wCurrent = sLyrics;
wCurrent->Hide();
wCurrent->Clear();
current_screen = csLyrics;
song_lyrics = "Lyrics: " + s->GetArtist() + " - " + s->GetTitle();
@@ -2293,7 +2277,7 @@ int main(int argc, char *argv[])
if (browsed_dir.empty())
browsed_dir = "/";
mBrowser->Empty() ? GetDirectory(browsed_dir) : UpdateItemList(vBrowser, mBrowser);
mBrowser->Empty() ? GetDirectory(browsed_dir) : UpdateItemList(mBrowser);
if (wCurrent != mBrowser && current_screen != csTagEditor)
{
@@ -2320,7 +2304,7 @@ int main(int argc, char *argv[])
if (!vSearched.empty())
{
wCurrent->WriteXY(0, 0, "Updating list...");
UpdateSongList(vSearched, mSearcher, search_engine_static_option+1);
UpdateFoundList(vSearched, mSearcher);
}
}
}
@@ -2343,7 +2327,7 @@ int main(int argc, char *argv[])
wCurrent = mLibArtists;
current_screen = csLibrary;
UpdateSongList(vLibSongs, mLibSongs);
UpdateSongList(mLibSongs);
}
}
else if (Keypressed(input, Key.PlaylistEditor))
@@ -2364,7 +2348,7 @@ int main(int argc, char *argv[])
wCurrent = mPlaylistList;
current_screen = csPlaylistEditor;
UpdateSongList(vPlaylistContent, mPlaylistEditor);
UpdateSongList(mPlaylistEditor);
}
}
else if (Keypressed(input, Key.Quit))

View File

@@ -211,17 +211,19 @@ void Scrollpad::SetTitle(string newtitle)
itsTitle = newtitle;
}
void Scrollpad::Clear()
void Scrollpad::Clear(bool clear_screen)
{
itsBeginning = 0;
itsRealHeight = 1;
itsXPos = 0;
itsContent.clear();
itsRawContent.clear();
wclear(itsWindow);
delwin(itsWindow);
itsWindow = newpad(itsRealHeight, itsWidth);
itsWindow = newpad(itsHeight, itsWidth);
SetColor(itsColor, itsBgColor);
Window::Clear();
if (clear_screen)
Window::Clear();
}
Window * Scrollpad::EmptyClone()

View File

@@ -37,7 +37,7 @@ class Scrollpad: public Window
virtual void Resize(int, int);
virtual void SetBorder(Border);
virtual void SetTitle(string);
virtual void Clear();
virtual void Clear(bool clear_screen = 1);
virtual Window * Clone() { return new Scrollpad(*this); }
virtual Window * EmptyClone();
protected:

View File

@@ -26,24 +26,19 @@ extern MPDConnection *Mpd;
extern ncmpcpp_config Config;
extern Menu *mPlaylist;
extern Menu *mBrowser;
extern Menu *wCurrent;
extern Menu *mSearcher;
extern Menu *mLibArtists;
extern Menu *mLibAlbums;
extern Menu *mLibSongs;
extern Menu *mPlaylistEditor;
extern Menu<Song> *mPlaylist;
extern Menu<Item> *mBrowser;
extern Menu<string> *mSearcher;
extern Menu<string> *mLibArtists;
extern Menu<string> *mLibAlbums;
extern Menu<Song> *mLibSongs;
extern Menu<Song> *mPlaylistEditor;
extern Window *wCurrent;
extern Window *wHeader;
extern Window *wFooter;
extern SongList vPlaylist;
extern SongList vSearched;
extern SongList vLibSongs;
extern SongList vPlaylistContent;
extern ItemList vBrowser;
extern TagList vArtists;
extern time_t block_delay;
extern time_t timer;
@@ -160,92 +155,79 @@ void NcmpcppStatusChanged(MPDConnection *Mpd, MPDStatusChanges changed, void *da
if (!block_playlist_update)
{
SongList list;
int playlist_length = Mpd->GetPlaylistLength();
if (playlist_length != vPlaylist.size())
if (playlist_length != mPlaylist->Size())
{
if (playlist_length < vPlaylist.size())
if (playlist_length < mPlaylist->Size())
{
mPlaylist->Clear(playlist_length < mPlaylist->GetHeight() && current_screen == csPlaylist);
FreeSongList(vPlaylist);
Mpd->GetPlaylistChanges(-1, list);
}
else
Mpd->GetPlaylistChanges(playlist_old_id, list);
vPlaylist.reserve(playlist_length);
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
{
vPlaylist.push_back(*it);
if (now_playing != (*it)->GetPosition())
mPlaylist->AddOption(DisplaySong(**it));
mPlaylist->AddOption(**it);
else
mPlaylist->AddBoldOption(DisplaySong(**it));
mPlaylist->AddBoldOption(**it);
}
if (current_screen == csPlaylist)
{
if (!playlist_length || mPlaylist->MaxChoice() < mPlaylist->GetHeight())
mPlaylist->Hide();
if (!playlist_length || mPlaylist->Size() < mPlaylist->GetHeight())
mPlaylist->Window::Clear();
mPlaylist->Refresh(1);
}
}
else
{
int i = 1;
mPlaylist->BoldOption(old_playing+1, 0);
mPlaylist->BoldOption(now_playing+1, 1);
// mPlaylist->BoldOption(old_playing+1, 0);
// mPlaylist->BoldOption(now_playing+1, 1);
Mpd->GetPlaylistChanges(-1, list);
SongList::iterator j = list.begin();
for (SongList::iterator it = vPlaylist.begin(); it != vPlaylist.end(); it++, i++)
for (int i = 0; i < mPlaylist->Size(); i++)
{
if (**it != **j)
{
**it = **j;
mPlaylist->UpdateOption(i, DisplaySong(**it));
}
j++;
if (*list[i] != mPlaylist->at(i))
mPlaylist->UpdateOption(i+1, *list[i]);
}
FreeSongList(list);
}
FreeSongList(list);
}
if (vPlaylist.empty())
if (mPlaylist->Empty())
{
playlist_stats.clear();
mPlaylist->Reset();
ShowMessage("Cleared playlist!");
}
else
playlist_stats = "(" + IntoStr(vPlaylist.size()) + (vPlaylist.size() == 1 ? " item" : " items") + TotalPlaylistLength() + ")";
playlist_stats = "(" + IntoStr(mPlaylist->Size()) + (mPlaylist->Size() == 1 ? " item" : " items") + TotalPlaylistLength() + ")";
if (current_screen == csBrowser)
{
UpdateItemList(vBrowser, mBrowser);
UpdateItemList(mBrowser);
}
else if (current_screen == csSearcher)
{
UpdateSongList(vSearched, mSearcher, search_engine_static_option+1);
UpdateFoundList(vSearched, mSearcher);
}
else if (current_screen == csLibrary)
{
UpdateSongList(vLibSongs, mLibSongs);
UpdateSongList(mLibSongs);
}
else if (current_screen == csPlaylistEditor)
{
UpdateSongList(vPlaylistContent, mPlaylistEditor);
UpdateSongList(mPlaylistEditor);
}
}
if (changed.Database)
{
GetDirectory(browsed_dir);
mLibArtists->Clear(0);
mPlaylistEditor->Clear(0);
}
if (changed.PlayerState)
{
@@ -286,7 +268,7 @@ void NcmpcppStatusChanged(MPDConnection *Mpd, MPDStatusChanges changed, void *da
}
if (changed.SongID)
{
if (!vPlaylist.empty() && now_playing >= 0)
if (!mPlaylist->Empty() && now_playing >= 0)
{
if (!mPlaylist->Empty())
{
@@ -315,7 +297,7 @@ void NcmpcppStatusChanged(MPDConnection *Mpd, MPDStatusChanges changed, void *da
Song s = Mpd->GetCurrentSong();
if (!player_state.empty() && !s.Empty())
{
WindowTitle(DisplaySong(s, Config.song_window_title_format));
WindowTitle(DisplaySong(s, &Config.song_window_title_format));
int elapsed = Mpd->GetElapsedTime();
@@ -330,7 +312,7 @@ void NcmpcppStatusChanged(MPDConnection *Mpd, MPDStatusChanges changed, void *da
tracklength = " [" + ShowTime(elapsed) + "/" + s.GetLength() + "]";
else
tracklength = " [" + ShowTime(elapsed) + "]";
ncmpcpp_string_t playing_song = NCMPCPP_TO_WSTRING(OmitBBCodes(DisplaySong(s, Config.song_status_format)));
ncmpcpp_string_t playing_song = NCMPCPP_TO_WSTRING(OmitBBCodes(DisplaySong(s, &Config.song_status_format)));
int max_length_without_scroll = wFooter->GetWidth()-player_state.length()-tracklength.length();
@@ -352,7 +334,7 @@ void NcmpcppStatusChanged(MPDConnection *Mpd, MPDStatusChanges changed, void *da
playing_song_scroll_begin = 0;
}
else
wFooter->WriteXY(player_state.length(), 1, OmitBBCodes(DisplaySong(s, Config.song_status_format)), 1);
wFooter->WriteXY(player_state.length(), 1, OmitBBCodes(DisplaySong(s, &Config.song_status_format)), 1);
wFooter->Bold(1);
wFooter->WriteXY(wFooter->GetWidth()-tracklength.length(), 1, tracklength);

View File

@@ -231,7 +231,7 @@ void Window::Refresh(bool stub)
wrefresh(itsWindow);
}
void Window::Clear()
void Window::Clear(bool stub)
{
for (int i = 0; i < GetHeight(); i++)
mvwhline(itsWindow, i, 0, 32, GetWidth());

View File

@@ -74,7 +74,7 @@ class Window
virtual void Resize(int, int);
virtual void Display(bool = 0);
virtual void Refresh(bool = 0);
virtual void Clear();
virtual void Clear(bool stub = 1);
virtual void Hide(char = 32) const;
virtual void Bold(bool) const;
virtual void Reverse(bool) const;
@@ -110,6 +110,14 @@ class Window
virtual Window * Clone() { return new Window(*this); }
virtual Window * EmptyClone();
// stubs for inherits, ugly shit, needs improvement
virtual void Select(int, bool) { }
virtual bool Selected(int) { return 0; }
virtual int Size() const { return 0; }
virtual bool IsAnySelected() { return 0; }
virtual void GetSelectedList(vector<int> &) { }
virtual bool IsStatic(int) { return 0; }
virtual void Highlight(int) { }
virtual void Go(Where) { } // for Menu and Scrollpad class
virtual int GetChoice() const { return -1; } // for Menu class
virtual void Add(string str) { Write(str); } // for Scrollpad class