Permalink
Browse files

add option to ignore articles when sorting

  • Loading branch information...
squentin committed Aug 23, 2015
1 parent f2b44c8 commit 851d146dc21bddca692992a7722e1aa642b8fadd
Showing with 59 additions and 15 deletions.
  1. +23 −10 gmusicbrowser.pl
  2. +36 −5 gmusicbrowser_songs.pm
@@ -1165,6 +1165,7 @@ sub ConvertSize
DateFormat_history => ['%c 604800 %A %X 86400 Today %X 60 now'],
AlwaysInPlaylist => 1,
PixCacheSize => 60, # in MB
Articles => 'the a an',
SavedSTGroupings=>
{ _"None" => '',
@@ -4117,17 +4118,20 @@ sub PopupAA
if (!@keys) {@keys=@keys_minor; undef @keys_minor;}
}

Songs::sort_gid_by_name($field,\@keys) unless $nosort;
my @names=@{Songs::Gid_to_Display($field,\@keys)}; #convert @keys to list of names
my $rm_articles= !$nosort && $::Options{Remove_articles} && Songs::CanRemoveArticles($field);
@keys= @{AA::SortKeys($field,\@keys)} unless $nosort;
my $displaynames= Songs::Gid_to_Display($field,\@keys); #convert @keys to list of names
my $names= $rm_articles ? [map Songs::remove_articles($_), @$displaynames] : $displaynames;

my @common_args= (widget=>$widget, makemenu=>$createAAMenu, cols=>3, height=>32+2);
my $menu=Breakdown_List(\@names, keys=>\@keys, @common_args);
my $menu=Breakdown_List($names, keys=>\@keys, displaynames=>$displaynames, @common_args);
return undef unless $menu;
if (@keys_minor)
{ Songs::sort_gid_by_name($field,\@keys_minor) unless $nosort;
my @names=@{Songs::Gid_to_Display($field,\@keys)};
my $displaynames= @{AA::SortKeys($field,\@keys_minor)};
my $names= $rm_articles ? [map Songs::remove_articles($_), @$displaynames] : $displaynames;
my $item=Gtk2::MenuItem->new('minor'); #FIXME
my $submenu=Breakdown_List(\@names, keys=>\@keys_minor, @common_args);
my $submenu=Breakdown_List($names, keys=>\@keys_minor, displaynames=>$displaynames, @common_args);
$item->set_submenu($submenu);
$menu->append($item);
}
@@ -4139,7 +4143,8 @@ sub PopupAA

sub Breakdown_List
{ my ($names,%options)=@_;
my ($min,$opt,$max,$makemenu,$keys,$widget)=@options{qw/min opt max makemenu keys widget/};
my ($min,$opt,$max,$makemenu,$keys,$widget,$displaynames)=@options{qw/min opt max makemenu keys widget displaynames/};
$displaynames||=$names;
$widget ||= Gtk2->get_current_event; #used to find current screen
my $screen= $widget ? $widget->get_screen : Gtk2::Gdk::Screen->get_default; # FIXME is that ok for multi-monitors ?
my $maxheight= $screen->get_height;
@@ -4157,7 +4162,7 @@ sub Breakdown_List
}

# short-cut if no need to create sub-menus
if ($#$names<=$max) { return $makemenu ? $makemenu->(0,$#$names,$names,$keys) : [0,$#$names] }
if ($#$names<=$max) { return $makemenu ? $makemenu->(0,$#$names,$displaynames,$keys) : [0,$#$names] }

# check if needs more than 1 level of submenus
if ($makemenu && !$options{norecurse})
@@ -4171,9 +4176,10 @@ sub Breakdown_List
$makemenu= sub
{ my ($start,$end,$names,$keys)=@_;
my @names2=@$names[$start..$end];
my @displaynames2=@$displaynames[$start..$end];
my $keys2;
@$keys2= @$keys[$start..$end] if $keys && @$keys;
Breakdown_List(\@names2,@childarg,keys=>$keys2);
Breakdown_List(\@names2,@childarg,keys=>$keys2,displaynames=>\@displaynames2);
};
}
}
@@ -4308,7 +4314,7 @@ sub Breakdown_List
my $item=Gtk2::MenuItem->new_with_label($c1);
$item->{start}= substr $c1,0,1;
$item->{end}= substr $c2,0,1;
$item->{menuargs}= [$start,$end,$names,$keys];
$item->{menuargs}= [$start,$end,$displaynames,$keys];
# only build submenu when the item is selected
$item->signal_connect(activate => sub
{ my $args=delete $_[0]{menuargs};
@@ -4323,7 +4329,7 @@ sub Breakdown_List
$menu->append($item);
}
}
elsif (@menus==1) { $menu= $makemenu->(0,$#$names,$names,$keys); }
elsif (@menus==1) { $menu= $makemenu->(0,$#$names,$displaynames,$keys); }
else {return undef}

return $menu;
@@ -6696,6 +6702,12 @@ sub PrefMisc
text=>_"Extract guest artist from title :", tip=>_"Used for the Artists field", separator=> ' ',
empty=>_"ignore title", cb=>\&Songs::UpdateArtistsRE );

#articles
my $articles= NewPrefEntry('Articles',undef,cb=> sub { Delayed('UpdateArticleRE',1000,\&Songs::UpdateArticleRE); });
my $articles_check= NewPrefCheckButton(Remove_articles=>_"Ignore these words when sorting :",
widget=>$articles, cb=> \&Songs::UpdateArticleRE, horizontal=>1,
tip=>_"If one of these words is at the start of the string, it will be ignored when sorting most fields" );

#date format
my $dateex= mktime(5,4,3,2,0,(localtime)[5]);
my $datetip= join "\n", _"use standard strftime variables", _"examples :",
@@ -6728,6 +6740,7 @@ sub PrefMisc
my $foldercmd= NewPrefEntry(OpenFolder => _"Command to open folders :", tip => _"Will use system's default if blank", history=> 'OpenFolder_history');

my $vbox= Vpack( $checkR1,$checkR2,$checkR4, $DefRating,$ProxyCheck, $asplit, $atitle,
$articles_check,
[0,$datealign,$preview], $screensaver,$shutentry, $always_in_pl,
$recent_include_not_played, $volstep, $pixcache,
[ $playedpercent, $playedseconds ],
@@ -13,7 +13,7 @@ package Songs;

#our %Songs;
our ($IDFromFile,$MissingHash); my $KeepIDFromFile;
our ($Artists_split_re,$Artists_title_re);
our ($Artists_split_re,$Artists_title_re,$Articles_re);
my @MissingKeyFields;
our (%Def,%Types,%Categories,%FieldTemplates,@Fields,%HSort,%Aliases);
my %FuncCache;
@@ -841,6 +841,7 @@ our %timespan_menu=
edit_order=> 10, letter => 't',
category=>'basic',
alias_trans=> ::_p('Field_aliases',"title"), #TRANSLATION: comma-separated list of field aliases for title, these are in addition to english aliases
articles=>1,
},
artist =>
{ name => _"Artist", width => 200, flags => 'fgarwescpi',
@@ -856,6 +857,7 @@ our %timespan_menu=
category=>'basic',
alias=> 'by',
alias_trans=> ::_p('Field_aliases',"artist,by"), #TRANSLATION: comma-separated list of field aliases for artist, these are in addition to english aliases
articles=>1,
},
first_artist =>
{ flags => 'fig',
@@ -864,12 +866,14 @@ our %timespan_menu=
picture_field => 'artist_picture',
sortgroup=>'artist',
can_group=>1,
articles=>1,
},
artists =>
{ flags => 'gfil', type => 'artists', depend => 'artist title', name => _"Artists",
all_count=> _"All artists",
FilterList => {search=>1,drag=>::DRAG_ARTIST},
picture_field => 'artist_picture',
articles=>1,
},
album =>
{ name => _"Album", width => 200, flags => 'fgarwescpi', type => 'album',
@@ -885,6 +889,7 @@ our %timespan_menu=
category=>'basic',
alias=> 'on',
alias_trans=> ::_p('Field_aliases',"album,on"), #TRANSLATION: comma-separated list of field aliases for album, these are in addition to english aliases
articles=>1,
},
# genre_picture =>
# { name => "Genre picture",
@@ -929,6 +934,7 @@ our %timespan_menu=
letter => 'A',
depend => 'album_artist_raw artist album',
category=>'basic',
articles=>1,
},
album_has_picture=>
{ name => _"Album has picture", width => 20, flags => 'fgcs', type => 'boolean',
@@ -964,6 +970,7 @@ our %timespan_menu=
edit_order=> 55, edit_many=>1,
id3v2 => 'TIT1', vorbis => 'grouping', ape => 'Grouping', ilst => "\xA9grp",
category=>'extra',
articles=>1,
},
year =>
{ name => _"Year", width => 40, flags => 'fgarwescp', type => 'integer', bits => 16,
@@ -1180,6 +1187,7 @@ our %timespan_menu=
edit_many=>1,
disable=>1, options => 'disable',
category=>'extra',
articles=>1,
},
lyricist =>
{ name => _"Lyricist", width => 100, flags => 'fgarwescpi', type => 'artist',
@@ -1190,6 +1198,7 @@ our %timespan_menu=
edit_many=>1,
disable=>1, options => 'disable',
category=>'extra',
articles=>1,
},
conductor =>
{ name => _"Conductor", width => 100, flags => 'fgarwescpi', type => 'artist',
@@ -1200,6 +1209,7 @@ our %timespan_menu=
edit_many=>1,
disable=>1, options => 'disable',
category=>'extra',
articles=>1,
},
remixer =>
{ name => _"Remixer", width => 100, flags => 'fgarwescpi', type => 'artist',
@@ -1209,6 +1219,7 @@ our %timespan_menu=
edit_many=>1,
disable=>1, options => 'disable',
category=>'extra',
articles=>1,
},
version=> #subtitle ?
{ name => _"Version", width => 150, flags => 'fgarwescpi', type => 'fewstring',
@@ -1354,6 +1365,7 @@ our %timespan_menu=
name=> _"Title or filename",
depend => 'file title', letter => 'S', #why letter S ? :)
options => 'show_ext', show_ext=>0,
articles=>1,
},

missing => { flags => 'gan', type => 'integer', bits => 32, }, #FIXME store it using a 8-bit relative number to $::DAYNB
@@ -1397,13 +1409,13 @@ our %timespan_menu=
);

our %FieldTemplates=
( string => { type=>'string', editname=>_"string", flags=>'fgaescp', width=> 200, edit_many =>1, options=> 'customfield', },
( string => { type=>'string', editname=>_"string", flags=>'fgaescp', width=> 200, edit_many =>1, options=> 'customfield', articles=>1, },
text => { type=>'text', editname=>_"multi-lines string",flags=>'fgaescp', width=> 200, edit_many =>1, options=> 'customfield', },
float => { type=>'float', editname=>_"float", flags=>'fgaescp', width=> 100, edit_many =>1, options=> 'customfield', desc => _"For decimal numbers", },
boolean => { type=>'boolean', editname=>_"boolean", flags=>'fgaescp', width=> 20, edit_many =>1, options=> 'customfield', },
flags => { type=>'flags', editname=>_"flags", flags=>'fgaescpil', width=> 180, edit_many =>1, can_group=>1, options=> 'customfield persistent_values editsubmenu', FilterList=> {search=>1}, desc=>_"Same type as labels", editsubmenu => 1, },
artist => { type=>'artist', editname=>_"artist", flags=>'fgaescpi', width=> 200, edit_many =>1, can_group=>1, options=> 'customfield', FilterList=> {search=>1,drag=>::DRAG_ARTIST}, picture_field => 'artist_picture', },
fewstring=>{ type=>'fewstring', editname=>_"common string", flags=>'fgaescpi',width=> 200, edit_many =>1, can_group=>1, options=> 'customfield', FilterList=> {search=>1}, desc=>_"For when values are likely to be repeated" },
artist => { type=>'artist', editname=>_"artist", flags=>'fgaescpi', width=> 200, edit_many =>1, can_group=>1, options=> 'customfield', FilterList=> {search=>1,drag=>::DRAG_ARTIST}, picture_field => 'artist_picture', articles=>1, },
fewstring=>{ type=>'fewstring', editname=>_"common string", flags=>'fgaescpi',width=> 200, edit_many =>1, can_group=>1, options=> 'customfield', FilterList=> {search=>1}, desc=>_"For when values are likely to be repeated", articles=>1, },
fewnumber=>{ type=>'fewnumber', editname=>_"common number", flags=>'fgaescp', width=> 100, edit_many =>1, can_group=>1, options=> 'customfield', FilterList=> {}, desc=>_"For when values are likely to be repeated" },
integer => { type=>'integer', editname=>_"integer", flags=>'fgaescp', width=> 100, edit_many =>1, can_group=>1, options=> 'customfield', FilterList=> {}, desc => _"For integer numbers", },
rating => { type=>'rating', editname=>_"rating", flags=>'fgaescp_', width=> 80, edit_many =>1, can_group=>1, options=> 'customfield rw_ useridwarn userid editsubmenu stars', FilterList=> {},
@@ -1610,6 +1622,7 @@ sub SortCode
{ $op='cmp';
if (!$insensitive) { $code=$scode}
else { $code= $sicode || "::superlc($scode)"; }
if ($::Options{Remove_articles} && CanRemoveArticles($field)) { $code="remove_articles($code)"; }
}
my $init='';
$init=$1 if $code=~s/^(.+) +---- +//;
@@ -1619,6 +1632,23 @@ sub SortCode
$code= $inv ? "$code2 $op $code" : "$code $op $code2";
return $init,$code;
}
sub CompileArticleRE
{ my @art= split /\s+/, $::Options{Articles};
s/_/ /g for @art; #replace _ by spaces to allow multi-word "articles", not sure if it could be useful
@art= map quotemeta($_).(m/'$/ ? "" : "\\s+"), @art;
my $re= '^(?:' .join('|',@art). ')';
$Articles_re= qr/$re/i;
}
sub UpdateArticleRE
{ delete $::Delayed{'UpdateArticleRE'};
Songs::CompileArticleRE();
%FuncCache=();#FIXME find a better way
Songs::Changed(undef,FieldList(true=>'articles'));
}
sub CanRemoveArticles { $Def{$_[0]}{articles}; }
sub remove_articles
{ my $s=$_[0]; $s=~s/$Articles_re//; $s;
}

sub Compile #currently return value of the code must be a scalar
{ my ($name,$code)=@_;
@@ -1639,6 +1669,7 @@ sub UpdateFuncs

Field_Apply_options();
CompileArtistsRE();
CompileArticleRE();

my @todo=grep !$Def{$_}{disable}, sort keys %Def;
while (@todo)
@@ -3319,7 +3350,7 @@ sub GrepKeys

sub SortKeys
{ my ($field,$list,$mode,$hsongs)=@_;
my $invert= $mode=~s/^-//;
my $invert= $mode && $mode=~s/^-//;
my $h=my $pre=0;
$mode||='';
if ($mode eq 'songs')

0 comments on commit 851d146

Please sign in to comment.