Keep original order in menurc
[clawsker.git] / clawsker
index 35a2646c989d37ac19b9b00d143c5fe50e1a77dd..91e4d73a109c438ab9bf6f2e55b84ac3eba3954f 100755 (executable)
--- a/clawsker
+++ b/clawsker
@@ -1,7 +1,7 @@
 #!/usr/bin/perl -w
 #
 # Clawsker :: A Claws Mail Tweaker
-# Copyright 2007-2016 Ricardo Mones <ricardo@mones.org>
+# Copyright 2007-2017 Ricardo Mones <ricardo@mones.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -95,9 +95,11 @@ sub _ {
 
     l_oth_use_dlg => _('Use detached address book edit dialogue'),
     h_oth_use_dlg => _('If true use a separate dialogue to edit a person\'s details. Otherwise will use a form embedded in the address book\'s main window.'),
-    l_oth_max_use => _('Maximum memory for message cache (kB)'),
+    l_oth_max_use => _('Maximum memory for message cache'),
+    l_oth_max_use_units => _('kilobytes'),
     h_oth_max_use => _('The maximum amount of memory to use to cache messages, in kilobytes.'),
-    l_oth_min_time => _('Minimun time for cache elements (minutes)'),
+    l_oth_min_time => _('Minimun time for cache elements'),
+    l_oth_min_time_units => _('minutes'),
     h_oth_min_time => _('The minimum time in minutes to keep a cache in memory. Caches more recent than this time will not be freed, even if the memory usage is too high.'),
     l_oth_use_netm => _('Use NetworkManager'),
     h_oth_use_netm => _('Use NetworkManager to switch offline automatically.'),
@@ -144,10 +146,14 @@ sub _ {
     h_gui_zero_char => _('Replaces \'0\' with the given character in Folder List.'),
     l_gui_type_any => _('Editable headers'),
     h_gui_type_any => _('Allows to manually type any value in Compose Window header entries or just select from the available choices in the associated dropdown list.'),
+    l_gui_warn_send_multi => _('Warn when sending to more than'),
+    l_gui_warn_send_multi_units => _('recipients'),
+    h_gui_warn_send_multi => _('Show a warning dialogue when sending to more recipients than specified. Use 0 to disable this check.'),
     l_gui_next_del => _('Select next message on delete'),
     h_gui_next_del => _('When deleting a message, toggles between selecting the next one (newer message) or the previous one (older message).'),
 
-    l_beh_hover_t => _('Drag \'n\' drop hover timeout (ms)'),
+    l_beh_hover_t => _('Drag \'n\' drop hover timeout'),
+    l_beh_hover_t_units => _('milliseconds'),
     h_beh_hover_t => _('Time in milliseconds that will cause a folder tree to expand when the mouse cursor is held over it during drag and drop.'),
     l_beh_dangerous => _('Don\'t confirm deletions (dangerous!)'),
     h_beh_dangerous => _('Don\'t ask for confirmation before definitive deletion of emails.'),
@@ -157,9 +163,11 @@ sub _ {
     h_beh_parts_rw => _('Saves temporary files when opening attachment with write bit set.'),
     l_beh_skip_ssl => _('Don\'t check SSL certificates'),
     h_beh_skip_ssl => _('Disables the verification of SSL certificates.'),
-    l_beh_up_step => _('Progress bar update step (items)'),
+    l_beh_up_step => _('Progress bar update step every'),
+    l_beh_up_step_units => _('items'),
     h_beh_up_step => _('Update stepping in progress bars.'),
-    l_beh_thread_a => _('Maximum age when threading by subject (days)'),
+    l_beh_thread_a => _('Maximum age when threading by subject'),
+    l_beh_thread_a_units => _('days'),
     h_beh_thread_a => _('Number of days to include a message in a thread when using "Thread using subject in addition to standard headers".'),
     l_beh_unsafe_ssl => _('Allow unsafe SSL certificates'),
     h_beh_unsafe_ssl => _('Allows Claws Mail to remember multiple SSL certificates for a given server/port.'),
@@ -217,7 +225,7 @@ sub _ {
     l_col_diff_del => _('Deleted lines'),
     h_col_diff_del => _('Colour for deleted lines in patches.'),
     l_col_diff_hunk => _('Hunk lines'),
-    h_col_diff_hunk => _('Color for hunk headers in patches.'),
+    h_col_diff_hunk => _('Colour for hunk headers in patches.'),
 
     l_win_x => _('X position'),
     h_win_x => _('X coordinate for window\'s top-left corner.'),
@@ -292,6 +300,8 @@ use constant PAGE_SPC => 5;
 
 sub version_greater_or_equal {
     my ($version, $refvers) = @_;
+    return TRUE if (length($version) == 0 and length($refvers) >= 0);
+    return FALSE if (length($version) >= 0 and length($refvers) == 0);
     return TRUE if (version->parse($version) >= version->parse($refvers));
     return FALSE;
 }
@@ -391,6 +401,10 @@ sub get_ac_rc_filename {
     return $CONFIGDIR . $ACCOUNTRC;
 }
 
+sub get_menurc_filename {
+    return $CONFIGDIR . "menurc";
+}
+
 sub set_rc_filename {
     my ($fullname) = @_;
     my @parts = split ('/', $fullname);
@@ -507,6 +521,11 @@ sub new_text_box_for_int($$$) {
     my @type = split (/,/, $$hash{$key}[TYPE]);
     push (@type, 0), push (@type, 10000) unless ($#type > 0);
     #
+    my $gunits = undef;
+    if (ref $label eq 'ARRAY') {
+        $gunits = Gtk2::Label->new ($label->[1]);
+        $label = $label->[0];
+    }
     my $glabel = Gtk2::Label->new ($label);
     my $pagei = int (($type[2] - $type[1]) / 10);
     my $gentry = Gtk2::SpinButton->new_with_range ($type[1], $type[2], $pagei);
@@ -521,7 +540,9 @@ sub new_text_box_for_int($$$) {
     set_widget_hint ($gentry, $$hash{$key}[DESC]);
     set_widget_sens ($gentry, $$hash{$key}[CMVER]);
     $glabel->set_sensitive ($gentry->sensitive);
+    $gunits->set_sensitive ($gentry->sensitive) if ($gunits);
     #
+    return new_hbox_spaced_pack ($glabel, $gentry, $gunits) if ($gunits);
     return new_hbox_spaced_pack ($glabel, $gentry);
 }
 
@@ -658,7 +679,7 @@ sub new_subpage_frame {
     ],
     max_use => [
         'cache_max_mem_usage',
-        $xl::s{l_oth_max_use},
+        [ $xl::s{l_oth_max_use}, $xl::s{l_oth_max_use_units} ],
         $xl::s{h_oth_max_use},
         'int,0,262144', # 0 Kb - 256 Mb
         '0.7.8.36',
@@ -666,7 +687,7 @@ sub new_subpage_frame {
     ],
     min_time => [
         'cache_min_keep_time',
-        $xl::s{l_oth_min_time},
+        [ $xl::s{l_oth_min_time}, $xl::s{l_oth_min_time_units} ],
         $xl::s{h_oth_min_time},
         'int,0,120', # 0 minutes - 2 hours
         '0.7.8.36',
@@ -849,6 +870,14 @@ sub new_other_page() {
         '3.12.0.44',
         '0',
     ],
+    warn_send_multi => [
+        'warn_sending_many_recipients_num',
+        [ $xl::s{l_gui_warn_send_multi}, $xl::s{l_gui_warn_send_multi_units} ],
+        $xl::s{h_gui_warn_send_multi},
+        'int,0,1000',
+        '3.14.1.125',
+        '0',
+    ],
     next_del => [
         'next_on_delete',
         $xl::s{l_gui_next_del},
@@ -890,10 +919,12 @@ sub new_gui_page() {
                          $xl::s{mview_frame}, 'not-packed'),
                      FALSE, FALSE, FRAME_SPC);
     $gf->pack_start (new_subpage_frame (
-                         new_hbox_pack (
-                             new_check_button_for (\%pr::gui, 'no_markup', \%HPVALUE),
-                             new_check_button_for (\%pr::gui, 'margin_co', \%HPVALUE),
-                             new_check_button_for (\%pr::gui, 'type_any', \%HPVALUE)),
+                         new_vbox_pack (
+                             new_hbox_pack_compact (
+                                 new_check_button_for (\%pr::gui, 'no_markup', \%HPVALUE),
+                                 new_check_button_for (\%pr::gui, 'margin_co', \%HPVALUE),
+                                 new_check_button_for (\%pr::gui, 'type_any', \%HPVALUE)),
+                             new_text_box_for_int (\%pr::gui, 'warn_send_multi', \%HPVALUE)),
                          $xl::s{compo_frame}, 'not-packed'),
                      FALSE, FALSE, FRAME_SPC);
     $gf->pack_start ($cb_dot_lines, FALSE, FALSE, 0);
@@ -912,7 +943,7 @@ sub new_gui_page() {
 %pr::beh = ( # tweak some behaviour
     hover_t => [
         'hover_timeout',
-        $xl::s{l_beh_hover_t},
+        [ $xl::s{l_beh_hover_t}, $xl::s{l_beh_hover_t_units} ],
         $xl::s{h_beh_hover_t},
         'int,100,3000', # 0.1 seconds - 3 seconds
         '0.0.0',
@@ -952,7 +983,7 @@ sub new_gui_page() {
     ],
     up_step => [
         'statusbar_update_step',
-        $xl::s{l_beh_up_step},
+        [ $xl::s{l_beh_up_step}, $xl::s{l_beh_up_step_units} ],
         $xl::s{h_beh_up_step},
         'int,1,200', # 1 item - 200 items
         '0.0.0',
@@ -960,7 +991,7 @@ sub new_gui_page() {
     ],
     thread_a => [
         'thread_by_subject_max_age',
-        $xl::s{l_beh_thread_a},
+        [ $xl::s{l_beh_thread_a}, $xl::s{l_beh_thread_a_units} ],
         $xl::s{h_beh_thread_a},
         'int,1,30', # 1 day - 30 days
         '0.0.0',
@@ -2335,6 +2366,53 @@ sub save_resource {
     close (RCF);
 }
 
+# specific loaders
+sub load_menurc {
+    my $rc = shift;
+    open (RCF, '<:encoding(utf8)', $rc)
+        or die _("Error: opening '{file}' for reading", file => $rc) . ": $!\n";
+    my %groups = ();
+    my $line = 0;
+    while (<RCF>) {
+        chomp;
+        if (/^; \(gtk_accel_path "<([A-Za-z]+)>([^"]+)" ([^\)]+)\)$/) {
+            my %data = ('key' => $3, 'enabled' => FALSE, 'line' => $line);
+            $groups{$1}{$2} = \%data;
+            # say "group -> $1 | path -> $2 | key -> $3";
+        } elsif (/^\(gtk_accel_path "<([A-Za-z]+)>([^"]+)" ([^\)]+)\)$/) {
+            my %data = ('key' => $3, 'enabled' => TRUE, 'line' => $line);
+            $groups{$1}{$2} = \%data;
+            # say "group -> $1 | path -> $2 | key -> $3";
+        }
+        ++$line;
+    }
+    close (RCF);
+    return \%groups;
+}
+
+sub save_menurc {
+    my ($rc, $groups) = @_;
+    my @lines = ();
+    foreach my $gkey (keys %$groups) {
+        my $group = $groups->{$gkey};
+        foreach my $akey (keys %$group) {
+            my $data = $group->{$akey};
+            my $key = $data->{'key'};
+            my $line = $data->{'line'};
+            $lines[$line] = ($data->{'enabled'})? '': '; ';
+            $lines[$line] .= '(gtk_accel_path "<'
+                    . $gkey . '>' . $akey . '" ' . $key . ')';
+        }
+    }
+    open (RCF, '>:utf8', $rc)
+        or die _("Error: opening '{file}' for writing", file => $rc) . ": $!\n";
+    say RCF '; claws-mail GtkAccelMap rc-file         -*- scheme -*-';
+    say RCF '; this file is an automated accelerator map dump';
+    say RCF ';';
+    foreach (@lines) { say RCF $_ if $_ }
+    close (RCF);
+}
+
 # load current status from disc
 sub load_rc_preferences {
     my $rc = get_rc_filename ();
@@ -2454,7 +2532,7 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.";
-    my $year = "2007-2016";
+    my $year = "2007-2017";
     my $holder = "Ricardo Mones &lt;ricardo\@mones.org&gt;";
     my $url = "http://www.claws-mail.org/clawsker.php";