new feature: allow for fixed size columns
This commit is contained in:
10
doc/config
10
doc/config
@@ -101,12 +101,18 @@
|
||||
##
|
||||
## - syntax for each column is:
|
||||
##
|
||||
## (width of column in %)[column's color]{displayed tag}
|
||||
## (width of column)[column's color]{displayed tag}
|
||||
##
|
||||
## Note: Width is by default in %, if you want a column to
|
||||
## have fixed size, add 'f' after the value, e.g. (10)[white]{a}
|
||||
## will be the column that take 10% of screen (so the real column's
|
||||
## width will depend on actual screen size), whereas (10f)[white]{a}
|
||||
## will take 10 terminal cells, no matter how wide the screen is.
|
||||
##
|
||||
## - color is optional (if you want the default one, type [])
|
||||
##
|
||||
#
|
||||
#song_columns_list_format = "(7)[green]{l} (28)[cyan]{a} (28)[]{b} (50)[red]{t}"
|
||||
#song_columns_list_format = "(7f)[green]{l} (25)[cyan]{a} (40)[]{t} (30)[red]{b}"
|
||||
#
|
||||
##### various settings #####
|
||||
#
|
||||
|
||||
@@ -51,7 +51,7 @@ const char *Browser::SupportedExtensions[] =
|
||||
|
||||
void Browser::Init()
|
||||
{
|
||||
w = new Menu<Item>(0, MainStartY, COLS, MainHeight, Config.columns_in_browser ? Display::Columns(Config.song_columns_list_format) : "", Config.main_color, brNone);
|
||||
w = new Menu<Item>(0, MainStartY, COLS, MainHeight, Config.columns_in_browser ? Display::Columns() : "", Config.main_color, brNone);
|
||||
w->HighlightColor(Config.main_highlight_color);
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
w->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
@@ -626,7 +626,7 @@ std::string Browser::ItemToString(const MPD::Item &item, void *)
|
||||
if (!Config.columns_in_browser)
|
||||
return item.song->toString(Config.song_list_format);
|
||||
else
|
||||
return Playlist::SongInColumnsToString(*item.song, &Config.song_columns_list_format);
|
||||
return Playlist::SongInColumnsToString(*item.song, 0);
|
||||
}
|
||||
case MPD::itPlaylist:
|
||||
{
|
||||
|
||||
@@ -23,17 +23,25 @@
|
||||
#include "helpers.h"
|
||||
#include "playlist.h"
|
||||
|
||||
std::string Display::Columns(std::string st)
|
||||
std::string Display::Columns()
|
||||
{
|
||||
if (Config.columns.empty())
|
||||
return "";
|
||||
|
||||
std::string result;
|
||||
size_t where = 0;
|
||||
int width;
|
||||
|
||||
for (int width = StrToInt(GetLineValue(st, '(', ')', 1)); width; width = StrToInt(GetLineValue(st, '(', ')', 1)))
|
||||
std::vector<Column>::const_iterator next2last;
|
||||
bool last_fixed = Config.columns.back().fixed;
|
||||
if (Config.columns.size() > 1)
|
||||
next2last = Config.columns.end()-2;
|
||||
|
||||
for (std::vector<Column>::const_iterator it = Config.columns.begin(); it != Config.columns.end(); ++it)
|
||||
{
|
||||
width *= COLS/100.0;
|
||||
char type = GetLineValue(st, '{', '}', 1)[0];
|
||||
width = it->width*(it->fixed ? 1 : COLS/100.0);
|
||||
|
||||
switch (type)
|
||||
switch (it->type)
|
||||
{
|
||||
case 'l':
|
||||
result += "Time";
|
||||
@@ -77,7 +85,10 @@ std::string Display::Columns(std::string st)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
where += width;
|
||||
if (last_fixed && it == next2last)
|
||||
where = COLS-(++next2last)->width;
|
||||
else
|
||||
where += width;
|
||||
|
||||
if (result.length() > where)
|
||||
result = result.substr(0, where);
|
||||
@@ -87,32 +98,36 @@ std::string Display::Columns(std::string st)
|
||||
return result;
|
||||
}
|
||||
|
||||
void Display::SongsInColumns(const MPD::Song &s, void *s_template, Menu<MPD::Song> *menu)
|
||||
void Display::SongsInColumns(const MPD::Song &s, void *, Menu<MPD::Song> *menu)
|
||||
{
|
||||
if (!s.Localized())
|
||||
const_cast<MPD::Song *>(&s)->Localize();
|
||||
|
||||
std::string st = s_template ? *static_cast<std::string *>(s_template) : "";
|
||||
size_t where = 0;
|
||||
Color color = clDefault;
|
||||
if (Config.columns.empty())
|
||||
return;
|
||||
|
||||
for (int width = StrToInt(GetLineValue(st, '(', ')', 1)); width; width = StrToInt(GetLineValue(st, '(', ')', 1)))
|
||||
std::vector<Column>::const_iterator next2last, it;
|
||||
size_t where = 0;
|
||||
int width;
|
||||
|
||||
bool last_fixed = Config.columns.back().fixed;
|
||||
if (Config.columns.size() > 1)
|
||||
next2last = Config.columns.end()-2;
|
||||
|
||||
for (it = Config.columns.begin(); it != Config.columns.end(); ++it)
|
||||
{
|
||||
if (where)
|
||||
{
|
||||
menu->GotoXY(where, menu->Y());
|
||||
*menu << ' ';
|
||||
if (color != clDefault)
|
||||
if ((it-1)->color != clDefault)
|
||||
*menu << clEnd;
|
||||
}
|
||||
|
||||
width *= COLS/100.0;
|
||||
color = IntoColor(GetLineValue(st, '[', ']', 1));
|
||||
char type = GetLineValue(st, '{', '}', 1)[0];
|
||||
|
||||
width = it->width*(it->fixed ? 1 : COLS/100.0);
|
||||
MPD::Song::GetFunction get = 0;
|
||||
|
||||
switch (type)
|
||||
switch (it->type)
|
||||
{
|
||||
case 'l':
|
||||
get = &MPD::Song::GetLength;
|
||||
@@ -159,17 +174,20 @@ void Display::SongsInColumns(const MPD::Song &s, void *s_template, Menu<MPD::Son
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (color != clDefault)
|
||||
*menu << color;
|
||||
if (it->color != clDefault)
|
||||
*menu << it->color;
|
||||
whline(menu->Raw(), 32, menu->GetWidth()-where);
|
||||
std::string tag = (s.*get)();
|
||||
if (!tag.empty())
|
||||
*menu << tag;
|
||||
else
|
||||
*menu << Config.empty_tag;
|
||||
where += width;
|
||||
if (last_fixed && it == next2last)
|
||||
where = COLS-(++next2last)->width;
|
||||
else
|
||||
where += width;
|
||||
}
|
||||
if (color != clDefault)
|
||||
if ((--it)->color != clDefault)
|
||||
*menu << clEnd;
|
||||
}
|
||||
|
||||
@@ -461,7 +479,7 @@ void Display::Items(const MPD::Item &item, void *, Menu<MPD::Item> *menu)
|
||||
if (!Config.columns_in_browser)
|
||||
Display::Songs(*item.song, &Config.song_list_format, reinterpret_cast<Menu<MPD::Song> *>(menu));
|
||||
else
|
||||
Display::SongsInColumns(*item.song, &Config.song_columns_list_format, reinterpret_cast<Menu<MPD::Song> *>(menu));
|
||||
Display::SongsInColumns(*item.song, 0, reinterpret_cast<Menu<MPD::Song> *>(menu));
|
||||
return;
|
||||
case MPD::itPlaylist:
|
||||
*menu << Config.browser_playlist_prefix << item.name;
|
||||
@@ -478,7 +496,7 @@ void Display::SearchEngine(const std::pair<Buffer *, MPD::Song *> &pair, void *,
|
||||
if (!Config.columns_in_search_engine)
|
||||
Display::Songs(*pair.second, &Config.song_list_format, reinterpret_cast<Menu<MPD::Song> *>(menu));
|
||||
else
|
||||
Display::SongsInColumns(*pair.second, &Config.song_columns_list_format, reinterpret_cast<Menu<MPD::Song> *>(menu));
|
||||
Display::SongsInColumns(*pair.second, 0, reinterpret_cast<Menu<MPD::Song> *>(menu));
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
namespace Display
|
||||
{
|
||||
std::string Columns(std::string);
|
||||
std::string Columns();
|
||||
|
||||
template <typename T> void Generic(const T &t, void *, Menu<T> *menu)
|
||||
{
|
||||
|
||||
@@ -1100,25 +1100,21 @@ int main(int argc, char *argv[])
|
||||
if (Config.columns_in_playlist)
|
||||
{
|
||||
myPlaylist->Main()->SetItemDisplayer(Display::SongsInColumns);
|
||||
myPlaylist->Main()->SetItemDisplayerUserData(&Config.song_columns_list_format);
|
||||
myPlaylist->Main()->SetTitle(Display::Columns(Config.song_columns_list_format));
|
||||
myPlaylist->Main()->SetTitle(Display::Columns());
|
||||
myPlaylist->Main()->SetGetStringFunction(Playlist::SongInColumnsToString);
|
||||
myPlaylist->Main()->SetGetStringFunctionUserData(&Config.song_columns_list_format);
|
||||
}
|
||||
else
|
||||
{
|
||||
myPlaylist->Main()->SetItemDisplayer(Display::Songs);
|
||||
myPlaylist->Main()->SetItemDisplayerUserData(&Config.song_list_format);
|
||||
myPlaylist->Main()->SetTitle("");
|
||||
myPlaylist->Main()->SetGetStringFunction(Playlist::SongToString);
|
||||
myPlaylist->Main()->SetGetStringFunctionUserData(&Config.song_list_format);
|
||||
}
|
||||
}
|
||||
else if (myScreen == myBrowser)
|
||||
{
|
||||
Config.columns_in_browser = !Config.columns_in_browser;
|
||||
ShowMessage("Browser display mode: %s", Config.columns_in_browser ? "Columns" : "Classic");
|
||||
myBrowser->Main()->SetTitle(Config.columns_in_browser ? Display::Columns(Config.song_columns_list_format) : "");
|
||||
myBrowser->Main()->SetTitle(Config.columns_in_browser ? Display::Columns() : "");
|
||||
|
||||
}
|
||||
else if (myScreen == mySearcher)
|
||||
@@ -1126,7 +1122,7 @@ int main(int argc, char *argv[])
|
||||
Config.columns_in_search_engine = !Config.columns_in_search_engine;
|
||||
ShowMessage("Search engine display mode: %s", Config.columns_in_search_engine ? "Columns" : "Classic");
|
||||
if (mySearcher->Main()->Size() > SearchEngine::StaticOptions)
|
||||
mySearcher->Main()->SetTitle(Config.columns_in_search_engine ? Display::Columns(Config.song_columns_list_format) : "");
|
||||
mySearcher->Main()->SetTitle(Config.columns_in_search_engine ? Display::Columns() : "");
|
||||
}
|
||||
}
|
||||
# ifdef HAVE_CURL_CURL_H
|
||||
|
||||
@@ -47,16 +47,16 @@ size_t Playlist::SortDialogHeight;
|
||||
|
||||
void Playlist::Init()
|
||||
{
|
||||
w = new Menu<MPD::Song>(0, MainStartY, COLS, MainHeight, Config.columns_in_playlist ? Display::Columns(Config.song_columns_list_format) : "", Config.main_color, brNone);
|
||||
w = new Menu<MPD::Song>(0, MainStartY, COLS, MainHeight, Config.columns_in_playlist ? Display::Columns() : "", Config.main_color, brNone);
|
||||
w->SetTimeout(ncmpcpp_window_timeout);
|
||||
w->CyclicScrolling(Config.use_cyclic_scrolling);
|
||||
w->HighlightColor(Config.main_highlight_color);
|
||||
w->SetSelectPrefix(&Config.selected_item_prefix);
|
||||
w->SetSelectSuffix(&Config.selected_item_suffix);
|
||||
w->SetItemDisplayer(Config.columns_in_playlist ? Display::SongsInColumns : Display::Songs);
|
||||
w->SetItemDisplayerUserData(Config.columns_in_playlist ? &Config.song_columns_list_format : &Config.song_list_format);
|
||||
w->SetItemDisplayerUserData(&Config.song_list_format);
|
||||
w->SetGetStringFunction(Config.columns_in_playlist ? SongInColumnsToString : SongToString);
|
||||
w->SetGetStringFunctionUserData(Config.columns_in_playlist ? &Config.song_columns_list_format : &Config.song_list_format);
|
||||
w->SetGetStringFunctionUserData(&Config.song_list_format);
|
||||
|
||||
SortDialogHeight = std::min(int(MainHeight-2), 18);
|
||||
|
||||
@@ -105,7 +105,7 @@ void Playlist::SwitchTo()
|
||||
void Playlist::Resize()
|
||||
{
|
||||
w->Resize(COLS, MainHeight);
|
||||
w->SetTitle(Config.columns_in_playlist ? Display::Columns(Config.song_columns_list_format) : "");
|
||||
w->SetTitle(Config.columns_in_playlist ? Display::Columns() : "");
|
||||
SortDialogHeight = std::min(int(MainHeight-2), 18);
|
||||
if (MainHeight > 6)
|
||||
SortDialog->Resize(SortDialogWidth, SortDialogHeight);
|
||||
@@ -448,20 +448,19 @@ std::string Playlist::SongToString(const MPD::Song &s, void *data)
|
||||
return s.toString(*static_cast<std::string *>(data));
|
||||
}
|
||||
|
||||
std::string Playlist::SongInColumnsToString(const MPD::Song &s, void *data)
|
||||
std::string Playlist::SongInColumnsToString(const MPD::Song &s, void *)
|
||||
{
|
||||
std::string result;
|
||||
std::string fmt = *static_cast<std::string *>(data);
|
||||
for (std::string i = GetLineValue(fmt, '{', '}', 1); !i.empty(); i = GetLineValue(fmt, '{', '}', 1))
|
||||
for (std::vector<Column>::const_iterator it = Config.columns.begin(); it != Config.columns.end(); ++it)
|
||||
{
|
||||
if (i == "t")
|
||||
if (it->type == 't')
|
||||
{
|
||||
result += "{%t}|{%f}";
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "%";
|
||||
result += i;
|
||||
result += it->type;
|
||||
}
|
||||
result += " ";
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ void SearchEngine::EnterPressed()
|
||||
if (!w->Back().first)
|
||||
{
|
||||
if (Config.columns_in_search_engine)
|
||||
w->SetTitle(Display::Columns(Config.song_columns_list_format));
|
||||
w->SetTitle(Display::Columns());
|
||||
size_t found = w->Size()-SearchEngine::StaticOptions;
|
||||
found += 3; // don't count options inserted below
|
||||
w->InsertSeparator(ResetButton+1);
|
||||
@@ -645,6 +645,6 @@ std::string SearchEngine::SearchEngineOptionToString(const std::pair<Buffer *, M
|
||||
if (!Config.columns_in_search_engine)
|
||||
return pair.second->toString(Config.song_list_format);
|
||||
else
|
||||
return Playlist::SongInColumnsToString(*pair.second, &Config.song_columns_list_format);
|
||||
return Playlist::SongInColumnsToString(*pair.second, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -230,8 +230,8 @@ void DefaultConfiguration(ncmpcpp_config &conf)
|
||||
{
|
||||
conf.mpd_host = "localhost";
|
||||
conf.empty_tag = "<empty>";
|
||||
conf.song_list_columns_format = "(7f)[green]{l} (25)[cyan]{a} (40)[]{t} (30)[red]{b}";
|
||||
conf.song_list_format = "{%a - }{%t}|{$8%f$9}%r{$3(%l)$9}";
|
||||
conf.song_columns_list_format = "(7)[green]{l} (25)[cyan]{a} (40)[]{t} (30)[red]{b}";
|
||||
conf.song_status_format = "{(%l) }{%a - }{%t}|{%f}";
|
||||
conf.song_window_title_format = "{%a - }{%t}|{%f}";
|
||||
conf.song_library_format = "{%n - }{%t}|{%f}";
|
||||
@@ -453,10 +453,7 @@ void ReadConfiguration(ncmpcpp_config &conf)
|
||||
std::ifstream f(config_file.c_str());
|
||||
std::string cl, v;
|
||||
|
||||
if (!f.is_open())
|
||||
return;
|
||||
|
||||
while (!f.eof())
|
||||
while (f.is_open() && !f.eof())
|
||||
{
|
||||
getline(f, cl);
|
||||
if (!cl.empty() && cl[0] != '#')
|
||||
@@ -515,7 +512,7 @@ void ReadConfiguration(ncmpcpp_config &conf)
|
||||
else if (cl.find("song_columns_list_format") != std::string::npos)
|
||||
{
|
||||
if (!v.empty())
|
||||
conf.song_columns_list_format = v;
|
||||
conf.song_list_columns_format = v;
|
||||
}
|
||||
else if (cl.find("song_status_format") != std::string::npos)
|
||||
{
|
||||
@@ -784,6 +781,15 @@ void ReadConfiguration(ncmpcpp_config &conf)
|
||||
}
|
||||
}
|
||||
f.close();
|
||||
|
||||
for (std::string width = GetLineValue(conf.song_list_columns_format, '(', ')', 1); !width.empty(); width = GetLineValue(conf.song_list_columns_format, '(', ')', 1))
|
||||
{
|
||||
Column col;
|
||||
col.color = IntoColor(GetLineValue(conf.song_list_columns_format, '[', ']', 1));
|
||||
col.type = GetLineValue(conf.song_list_columns_format, '{', '}', 1)[0];
|
||||
col.fixed = *width.rbegin() == 'f';
|
||||
col.width = StrToInt(width);
|
||||
conf.columns.push_back(col);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define _SETTINGS_H
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "home.h"
|
||||
#include "libmpdclient.h"
|
||||
@@ -36,6 +37,14 @@
|
||||
const std::string config_dir = home_path + HOME_FOLDER;
|
||||
const int null_key = std::numeric_limits<int>::max();
|
||||
|
||||
struct Column
|
||||
{
|
||||
unsigned width;
|
||||
Color color;
|
||||
char type;
|
||||
bool fixed;
|
||||
};
|
||||
|
||||
struct ncmpcpp_keys
|
||||
{
|
||||
int Up[2];
|
||||
@@ -113,8 +122,8 @@ struct ncmpcpp_config
|
||||
std::string mpd_host;
|
||||
std::string mpd_music_dir;
|
||||
std::string empty_tag;
|
||||
std::string song_list_columns_format;
|
||||
std::string song_list_format;
|
||||
std::string song_columns_list_format;
|
||||
std::string song_status_format;
|
||||
std::string song_window_title_format;
|
||||
std::string song_library_format;
|
||||
@@ -125,6 +134,8 @@ struct ncmpcpp_config
|
||||
|
||||
std::string pattern;
|
||||
|
||||
std::vector<Column> columns;
|
||||
|
||||
Buffer browser_playlist_prefix;
|
||||
Buffer selected_item_prefix;
|
||||
Buffer selected_item_suffix;
|
||||
|
||||
Reference in New Issue
Block a user