From c20d8694aeb6a9bc39a3523327b37ab3389c647c Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Fri, 10 Jul 2009 19:17:12 +0200 Subject: [PATCH] new feature: allow for fixed size columns --- doc/config | 10 +++++-- src/browser.cpp | 4 +-- src/display.cpp | 62 ++++++++++++++++++++++++++++--------------- src/display.h | 2 +- src/ncmpcpp.cpp | 10 +++---- src/playlist.cpp | 17 ++++++------ src/search_engine.cpp | 4 +-- src/settings.cpp | 20 +++++++++----- src/settings.h | 13 ++++++++- 9 files changed, 89 insertions(+), 53 deletions(-) diff --git a/doc/config b/doc/config index 55b3011d..8c434ce8 100644 --- a/doc/config +++ b/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 ##### # diff --git a/src/browser.cpp b/src/browser.cpp index bf3fc44d..ebcde5ae 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -51,7 +51,7 @@ const char *Browser::SupportedExtensions[] = void Browser::Init() { - w = new Menu(0, MainStartY, COLS, MainHeight, Config.columns_in_browser ? Display::Columns(Config.song_columns_list_format) : "", Config.main_color, brNone); + w = new Menu(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: { diff --git a/src/display.cpp b/src/display.cpp index 41182f75..74e39a9d 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -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; + + std::vector::const_iterator next2last; + bool last_fixed = Config.columns.back().fixed; + if (Config.columns.size() > 1) + next2last = Config.columns.end()-2; - for (int width = StrToInt(GetLineValue(st, '(', ')', 1)); width; width = StrToInt(GetLineValue(st, '(', ')', 1))) + for (std::vector::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 *menu) +void Display::SongsInColumns(const MPD::Song &s, void *, Menu *menu) { if (!s.Localized()) const_cast(&s)->Localize(); - std::string st = s_template ? *static_cast(s_template) : ""; + if (Config.columns.empty()) + return; + + std::vector::const_iterator next2last, it; size_t where = 0; - Color color = clDefault; + int width; - for (int width = StrToInt(GetLineValue(st, '(', ')', 1)); width; width = StrToInt(GetLineValue(st, '(', ')', 1))) + 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, Menucolor != 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 *menu) if (!Config.columns_in_browser) Display::Songs(*item.song, &Config.song_list_format, reinterpret_cast *>(menu)); else - Display::SongsInColumns(*item.song, &Config.song_columns_list_format, reinterpret_cast *>(menu)); + Display::SongsInColumns(*item.song, 0, reinterpret_cast *>(menu)); return; case MPD::itPlaylist: *menu << Config.browser_playlist_prefix << item.name; @@ -478,7 +496,7 @@ void Display::SearchEngine(const std::pair &pair, void *, if (!Config.columns_in_search_engine) Display::Songs(*pair.second, &Config.song_list_format, reinterpret_cast *>(menu)); else - Display::SongsInColumns(*pair.second, &Config.song_columns_list_format, reinterpret_cast *>(menu)); + Display::SongsInColumns(*pair.second, 0, reinterpret_cast *>(menu)); } else diff --git a/src/display.h b/src/display.h index 3069a078..43343173 100644 --- a/src/display.h +++ b/src/display.h @@ -27,7 +27,7 @@ namespace Display { - std::string Columns(std::string); + std::string Columns(); template void Generic(const T &t, void *, Menu *menu) { diff --git a/src/ncmpcpp.cpp b/src/ncmpcpp.cpp index aba2e8c6..cd123536 100644 --- a/src/ncmpcpp.cpp +++ b/src/ncmpcpp.cpp @@ -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 diff --git a/src/playlist.cpp b/src/playlist.cpp index bc73f9ef..1f7e7bb3 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -47,16 +47,16 @@ size_t Playlist::SortDialogHeight; void Playlist::Init() { - w = new Menu(0, MainStartY, COLS, MainHeight, Config.columns_in_playlist ? Display::Columns(Config.song_columns_list_format) : "", Config.main_color, brNone); + w = new Menu(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(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(data); - for (std::string i = GetLineValue(fmt, '{', '}', 1); !i.empty(); i = GetLineValue(fmt, '{', '}', 1)) + for (std::vector::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 += " "; } diff --git a/src/search_engine.cpp b/src/search_engine.cpp index 805a2b92..06ccef89 100644 --- a/src/search_engine.cpp +++ b/src/search_engine.cpp @@ -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::pairtoString(Config.song_list_format); else - return Playlist::SongInColumnsToString(*pair.second, &Config.song_columns_list_format); + return Playlist::SongInColumnsToString(*pair.second, 0); } diff --git a/src/settings.cpp b/src/settings.cpp index 195e1d65..c43e4524 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -230,8 +230,8 @@ void DefaultConfiguration(ncmpcpp_config &conf) { conf.mpd_host = "localhost"; conf.empty_tag = ""; + 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); + } } - diff --git a/src/settings.h b/src/settings.h index 0d7896b3..b7d534a3 100644 --- a/src/settings.h +++ b/src/settings.h @@ -22,6 +22,7 @@ #define _SETTINGS_H #include +#include #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::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 columns; + Buffer browser_playlist_prefix; Buffer selected_item_prefix; Buffer selected_item_suffix;