new feature: support for multiple tag types in one column

This commit is contained in:
Andrzej Rybczak
2010-05-17 22:49:26 +02:00
parent 53dfda0f98
commit 3d41a1585c
6 changed files with 165 additions and 139 deletions

View File

@@ -208,12 +208,21 @@
## - r - column will be right aligned ## - r - column will be right aligned
## - E - if tag is empty, empty tag marker won't be displayed ## - E - if tag is empty, empty tag marker won't be displayed
## ##
## You can also give a column custom name by putting it after ## You can also:
## attributes, separated with character ':', e.g. {lr:Length} ##
## gives you right aligned column of lengths named "Length". ## - give a column custom name by putting it after attributes,
## separated with character ':', e.g. {lr:Length} gives you
## right aligned column of lengths named "Length".
##
## - define sequence of tags, that have to be displayed in case
## predecessor is empty in a way similar to the one in classic
## song format, i.e. using '|' character, e.g. {a|c|p:Owner}
## creates column named "Owner" that tries to display artist
## tag and then composer and performer if previous ones are
## not available.
## ##
# #
#song_columns_list_format = "(7f)[green]{l} (25)[cyan]{a} (40)[]{t} (30)[red]{b}" #song_columns_list_format = "(7f)[green]{l} (25)[cyan]{a} (40)[]{t|f} (30)[red]{b}"
# #
##### various settings ##### ##### various settings #####
# #

View File

@@ -28,7 +28,7 @@ std::string Display::Columns()
if (Config.columns.empty()) if (Config.columns.empty())
return ""; return "";
std::basic_string<my_char_t> result, tag; std::basic_string<my_char_t> result;
size_t where = 0; size_t where = 0;
int width; int width;
@@ -46,57 +46,63 @@ std::string Display::Columns()
else else
width = it->width*(it->fixed ? 1 : COLS/100.0); width = it->width*(it->fixed ? 1 : COLS/100.0);
if (it->name.empty()) std::basic_string<my_char_t> tag;
if (it->type.length() >= 1 && it->name.empty())
{ {
switch (it->type) for (size_t j = 0; j < it->type.length(); ++j)
{ {
case 'l': switch (it->type[j])
tag = U("Time"); {
break; case 'l':
case 'f': tag += U("Time");
tag = U("Filename"); break;
break; case 'f':
case 'D': tag += U("Filename");
tag = U("Directory"); break;
break; case 'D':
case 'a': tag += U("Directory");
tag = U("Artist"); break;
break; case 'a':
case 'A': tag += U("Artist");
tag = U("Album Artist"); break;
break; case 'A':
case 't': tag += U("Album Artist");
tag = U("Title"); break;
break; case 't':
case 'b': tag += U("Title");
tag = U("Album"); break;
break; case 'b':
case 'y': tag += U("Album");
tag = U("Year"); break;
break; case 'y':
case 'n': tag += U("Year");
case 'N': break;
tag = U("Track"); case 'n':
break; case 'N':
case 'g': tag += U("Track");
tag = U("Genre"); break;
break; case 'g':
case 'c': tag += U("Genre");
tag = U("Composer"); break;
break; case 'c':
case 'p': tag += U("Composer");
tag = U("Performer"); break;
break; case 'p':
case 'd': tag += U("Performer");
tag = U("Disc"); break;
break; case 'd':
case 'C': tag += U("Disc");
tag = U("Comment"); break;
break; case 'C':
default: tag += U("Comment");
tag.clear(); break;
break; default:
tag += U("?");
break;
}
tag += '/';
} }
tag.resize(tag.length()-1);
} }
else else
tag = it->name; tag = it->name;
@@ -169,63 +175,66 @@ void Display::SongsInColumns(const MPD::Song &s, void *, Menu<MPD::Song> *menu)
MPD::Song::GetFunction get = 0; MPD::Song::GetFunction get = 0;
switch (it->type) std::string tag;
for (size_t i = 0; i < it->type.length(); ++i)
{ {
case 'l': switch (it->type[i])
get = &MPD::Song::GetLength; {
break; case 'l':
case 'D': get = &MPD::Song::GetLength;
get = &MPD::Song::GetDirectory; break;
break; case 'D':
case 'f': get = &MPD::Song::GetDirectory;
get = &MPD::Song::GetName; break;
break; case 'f':
case 'a':
get = &MPD::Song::GetArtist;
break;
case 'A':
get = &MPD::Song::GetAlbumArtist;
break;
case 'b':
get = &MPD::Song::GetAlbum;
break;
case 'y':
get = &MPD::Song::GetDate;
break;
case 'n':
get = &MPD::Song::GetTrackNumber;
break;
case 'N':
get = &MPD::Song::GetTrack;
break;
case 'g':
get = &MPD::Song::GetGenre;
break;
case 'c':
get = &MPD::Song::GetComposer;
break;
case 'p':
get = &MPD::Song::GetPerformer;
break;
case 'd':
get = &MPD::Song::GetDisc;
break;
case 'C':
get = &MPD::Song::GetComment;
break;
case 't':
if (!s.GetTitle().empty())
get = &MPD::Song::GetTitle;
else
get = &MPD::Song::GetName; get = &MPD::Song::GetName;
break; break;
default: case 'a':
get = &MPD::Song::GetArtist;
break;
case 'A':
get = &MPD::Song::GetAlbumArtist;
break;
case 'b':
get = &MPD::Song::GetAlbum;
break;
case 'y':
get = &MPD::Song::GetDate;
break;
case 'n':
get = &MPD::Song::GetTrackNumber;
break;
case 'N':
get = &MPD::Song::GetTrack;
break;
case 'g':
get = &MPD::Song::GetGenre;
break;
case 'c':
get = &MPD::Song::GetComposer;
break;
case 'p':
get = &MPD::Song::GetPerformer;
break;
case 'd':
get = &MPD::Song::GetDisc;
break;
case 'C':
get = &MPD::Song::GetComment;
break;
case 't':
get = &MPD::Song::GetTitle;
break;
default:
break;
}
tag = get ? s.GetTags(get) : "";
if (!tag.empty())
break; break;
} }
if (!discard_colors && it->color != clDefault) if (!discard_colors && it->color != clDefault)
*menu << it->color; *menu << it->color;
whline(menu->Raw(), 32, menu->GetWidth()-where); whline(menu->Raw(), 32, menu->GetWidth()-where);
std::string tag = get ? s.GetTags(get) : "";
// last column might need to be shrinked to make space for np/sel suffixes // last column might need to be shrinked to make space for np/sel suffixes
if (it == last) if (it == last)

View File

@@ -356,7 +356,7 @@ std::string GetLineValue(std::string &line, char a, char b, bool once)
++pos[0]; ++pos[0];
std::string result = pos[0] >= 0 && pos[1] >= 0 ? line.substr(pos[0], pos[1]-pos[0]) : ""; std::string result = pos[0] >= 0 && pos[1] >= 0 ? line.substr(pos[0], pos[1]-pos[0]) : "";
// replace \a and \b to a and b respectively // replace \a and \b with a and b respectively
char r1[] = "\\ ", r2[] = " "; char r1[] = "\\ ", r2[] = " ";
r1[1] = r2[0] = a; r1[1] = r2[0] = a;
Replace(result, r1, r2); Replace(result, r1, r2);

View File

@@ -415,25 +415,7 @@ std::string Playlist::SongToString(const MPD::Song &s, void *data)
std::string Playlist::SongInColumnsToString(const MPD::Song &s, void *) std::string Playlist::SongInColumnsToString(const MPD::Song &s, void *)
{ {
std::string result = "{"; return s.toString(Config.song_in_columns_to_string_format);
for (std::vector<Column>::const_iterator it = Config.columns.begin(); it != Config.columns.end(); ++it)
{
if (it->type == 't')
{
result += "{%t}|{%f}";
}
else
{
// tags should be put in additional braces as if they are not, the
// tag that is not present within 'main' braces discards them all.
result += "{%";
result += it->type;
result += "}";
}
result += " ";
}
result += "}";
return s.toString(result);
} }
bool Playlist::Add(const MPD::Song &s, bool in_playlist, bool play, int position) bool Playlist::Add(const MPD::Song &s, bool in_playlist, bool play, int position)

View File

@@ -1149,13 +1149,7 @@ void NcmpcppConfig::Read()
Column col; Column col;
col.color = IntoColor(GetLineValue(song_list_columns_format, '[', ']', 1)); col.color = IntoColor(GetLineValue(song_list_columns_format, '[', ']', 1));
std::string tag_type = GetLineValue(song_list_columns_format, '{', '}', 1); std::string tag_type = GetLineValue(song_list_columns_format, '{', '}', 1);
if (tag_type.length() > 0) // at least tag type was specified
col.type = tag_type[0];
else
{
col.type = 0;
col.display_empty_tag = 0;
}
col.fixed = *width.rbegin() == 'f'; col.fixed = *width.rbegin() == 'f';
// alternative name // alternative name
@@ -1166,20 +1160,51 @@ void NcmpcppConfig::Read()
tag_type.resize(tag_type_colon_pos); tag_type.resize(tag_type_colon_pos);
} }
for (std::string::const_iterator it = tag_type.begin()+(tag_type.length() > 0); it != tag_type.end(); ++it) if (!tag_type.empty())
{ {
switch (*it) size_t i = -1;
// extract tag types in format a|b|c etc.
do
col.type += tag_type[(++i)++]; // nice one.
while (tag_type[i] == '|');
// apply attributes
for (; i < tag_type.length(); ++i)
{ {
case 'r': switch (tag_type[i])
col.right_alignment = 1; {
break; case 'r':
case 'E': col.right_alignment = 1;
col.display_empty_tag = 0; break;
break; case 'E':
col.display_empty_tag = 0;
break;
}
} }
} }
else // empty column
col.display_empty_tag = 0;
col.width = StrToInt(width); col.width = StrToInt(width);
columns.push_back(col); columns.push_back(col);
} }
// generate format for converting tags in columns to string for Playlist::SongInColumnsToString()
char tag[] = "{% }|";
song_in_columns_to_string_format = "{";
for (std::vector<Column>::const_iterator it = columns.begin(); it != columns.end(); ++it)
{
for (std::string::const_iterator j = it->type.begin(); j != it->type.end(); ++j)
{
tag[2] = *j;
song_in_columns_to_string_format += tag;
}
*song_in_columns_to_string_format.rbegin() = ' ';
}
if (song_in_columns_to_string_format.length() == 1) // only '{'
song_in_columns_to_string_format += '}';
else
*song_in_columns_to_string_format.rbegin() = '}';
} }

View File

@@ -43,9 +43,9 @@ struct Column
Column() : right_alignment(0), display_empty_tag(1) { } Column() : right_alignment(0), display_empty_tag(1) { }
std::basic_string<my_char_t> name; std::basic_string<my_char_t> name;
std::string type;
unsigned width; unsigned width;
Color color; Color color;
char type;
bool fixed; bool fixed;
bool right_alignment; bool right_alignment;
bool display_empty_tag; bool display_empty_tag;
@@ -157,6 +157,7 @@ struct NcmpcppConfig
std::string song_window_title_format; std::string song_window_title_format;
std::string song_library_format; std::string song_library_format;
std::string tag_editor_album_format; std::string tag_editor_album_format;
std::string song_in_columns_to_string_format;
std::string external_editor; std::string external_editor;
std::string system_encoding; std::string system_encoding;
std::string execute_on_song_change; std::string execute_on_song_change;