10 Clawsker - A Claws Mail Tweaker
18 Clawsker is an applet to edit the so called Claws Mail hidden preferences.
20 Claws Mail is a fast, lightweight and feature-rich MUA with a high number
21 of configurable options. To keep the binary small and fast some of these
22 preferences which not widely used are not provided with a graphical interface
23 for inspection and/or modification.
25 Users wanting to edit such preferences had to face raw edition of their
26 configuration files, now you can do it with a convenient GTK2 interface
32 Shows a brief help screen.
34 --alternate-config-dir <dir>
35 Uses <dir> as Claws Mail configuration dir.
38 Uses <file> as Claws Mail resource configuration file. This sets
39 the full file name overriding any previous setting.
41 Multiple options are allowed, although only the last one has effect. Weird
42 option specifications may produce weird results (but otherwise correct).
46 Alternate configuration directories are not (yet) supported.
50 Ricardo Mones E<lt>ricardo@mones.orgE<gt>
54 Copyright (c) 2007 by Ricardo Mones
56 This program is free software: you can redistribute it and/or modify
57 it under the terms of the GNU General Public License as published by
58 the Free Software Foundation, either version 3 of the License, or
59 (at your option) any later version.
61 This program is distributed in the hope that it will be useful,
62 but WITHOUT ANY WARRANTY; without even the implied warranty of
63 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
64 GNU General Public License for more details.
66 You should have received a copy of the GNU General Public License
67 along with this program. If not, see E<lt>http://www.gnu.org/licenses/E<gt>.
72 use POSIX qw(setlocale);
74 use Glib qw(TRUE FALSE);
77 my $NAME = 'clawsker';
78 my $PREFIX = '@PREFIX@';
79 my $LIBDIR = '@LIBDIR@';
80 my $VERSION = '@VERSION@';
82 my $locale = (defined($ENV{LC_MESSAGES}) ? $ENV{LC_MESSAGES} : $ENV{LANG});
83 setlocale (LC_ALL, $locale);
84 bindtextdomain ($NAME, sprintf ('%s/share/locale', $PREFIX));
90 my $xla = gettext ($str);
91 if (scalar(keys(%par)) > 0) {
92 foreach my $key (keys %par) {
93 $xla =~ s/\{$key\}/$par{$key}/g;
101 win_title => _('Claws Mail Hidden Preferences'),
102 about => _('About...'),
103 about_title => _('Clawsker :: A Claws Mail Tweaker'),
104 about_license => _('License:'),
105 about_version => _('Version:'),
107 tab_colours => _('Colours'),
108 tab_behaviour => _('Behaviour'),
110 tab_other => _('Other'),
112 ab_frame => _('Addressbook'),
113 mem_frame => _('Memory'),
114 msgview_frame => _('Message view'),
115 log_frame => _('Log window'),
116 dnd_frame => _('Drag and drop'),
117 ssl_frame => _('Secure Sockets Layer'),
118 msgs_frame => _('Messages'),
119 stripes_frame => _('Coloured stripes'),
120 sbar_frame => _('Scroll bars'),
121 mlist_frame => _('Message list'),
123 l_oth_use_dlg => _('Use address book dialog'),
124 h_oth_use_dlg => _('If true use a separate dialogue to edit a person\'s details. Otherwise will use a form embedded in the addressbook\'s main window.'),
125 l_oth_max_use => _('Maximum memory for message cache (Kb)'),
126 h_oth_max_use => _('The maximum amount of memory to use to cache messages, in kB.'),
127 l_oth_min_time => _('Minimun time for cache elements (minutes)'),
128 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.'),
130 l_gui_b_unread => _('Show unread messages with bold font'),
131 h_gui_b_unread => _('Show unread messages in the Message List using a bold font.'),
132 l_gui_no_markup => _('Don\'t use markup in compose window'),
133 h_gui_no_markup => _('Don\'t use bold and italic text in Compose dialogue\'s account selector.'),
134 l_gui_dot_lines => _('Use dotted lines in tree views'),
135 h_gui_dot_lines => _('Use the old dotted line look in the main window tree views (folder and message lists) instead of the modern lineless look.'),
136 l_gui_h_scroll => _('Enable horizontal scrollbar'),
137 h_gui_h_scroll => _('Enable the horizontal scrollbar in the Message List.'),
138 l_gui_swp_from => _('Swap From field in Sent folder'),
139 h_gui_swp_from => _('Display the sender\'s email address in the To column of the Sent folder instead of the recipient\'s.'),
140 l_gui_v_scroll => _('Folder list scrollbar behaviour'),
141 h_gui_v_scroll => _('Specify the policy of vertical scrollbar of Folder List: show always, automatic or hide always.'),
142 l_gui_v_scroll_show => _('Show always'),
143 l_gui_v_scroll_auto => _('Automatic'),
144 l_gui_v_scroll_hide => _('Hide always'),
145 l_gui_strip_off => _('Striped lines contrast'),
146 h_gui_strip_off => _('Specify the value to use when creating alternately coloured lines in tree view components. The smaller the value, the less visible the difference in the alternating colours of the lines.'),
147 l_gui_cursor_v => _('Cursor visible in message view'),
148 h_gui_cursor_v => _('Display the cursor in the message view.'),
149 l_gui_toolbar_d => _('Detachable toolbars'),
150 h_gui_toolbar_d => _('Show handles in the toolbars.'),
151 l_gui_strip_all => _('Use stripes in tree view components'),
152 h_gui_strip_all => _('Enable alternately coloured lines in all tree view components.'),
153 l_gui_strip_sum => _('Use stripes in summary view'),
154 h_gui_strip_sum => _('Enable alternately coloured lines in summary view and folder list'),
156 l_beh_hover_t => _('Drag and drop hover timeout (ms)'),
157 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.'),
158 l_beh_dangerous => _('Don\'t confirm deletions (dangerous!)'),
159 h_beh_dangerous => _('Don\'t ask for confirmation before definitive deletion of emails.'),
160 l_beh_flowed => _('Respect flowed format in messages'),
161 h_beh_flowed => _('Respect format=flowed on text/plain message parts. This will cause some mails to have long lines, but will fix some URLs that would otherwise be wrapped.'),
162 l_beh_parts_rw => _('Allow writable temporary files'),
163 h_beh_parts_rw => _('Saves temporary files when opening attachment with write bit set.'),
164 l_beh_skip_ssl => _('Don\'t check SSL certificates'),
165 h_beh_skip_ssl => _('Disables the verification of SSL certificates.'),
166 l_beh_up_step => _('Progress update step (items)'),
167 h_beh_up_step => _('Update stepping in progress bars.'),
168 l_beh_thread_a => _('Maximum age in threading by subject (days)'),
169 h_beh_thread_a => _('Number of days to include a message in a thread when using "Thread using subject in addition to standard headers".'),
170 l_beh_unsafe_ssl => _('Allow unsafe SSL certificates'),
171 h_beh_unsafe_ssl => _('Allows Claws Mail to remember multiple SSL certificates for a given server/port.'),
172 l_beh_use_utf8 => _('Use UTF-8 in broken mails'),
173 h_beh_use_utf8 => _('Use UTF-8 encoding for broken mails instead of current locale.'),
174 l_beh_warn_dnd => _('Warning on drag and drop'),
175 h_beh_warn_dnd => _('Display a confirmation dialogue on drag \'n\' drop of folders.'),
177 l_col_emphasis => _('Emphasised X-Mailer colour'),
178 h_col_emphasis => _('The colour used for the X-Mailer line when its value is Claws Mail.'),
179 l_col_log_err => _('Errors colour'),
180 h_col_log_err => _('Colour for error messages in log window.'),
181 l_col_log_in => _('Input colour'),
182 h_col_log_in => _('Colour for input messages in log window.'),
183 l_col_log_msg => _('Messages colour'),
184 h_col_log_msg => _('Colour for messages in log window.'),
185 l_col_log_out => _('Output colour'),
186 h_col_log_out => _('Colour for output messages in log window.'),
187 l_col_log_warn => _('Warnings colour'),
188 h_col_log_warn => _('Colour for warning messages in log window.'),
190 e_error => _('Error: '),
191 e_noclawsrc => _('resource file for Claws Mail was not found.'),
192 e_running => _('seems Claws Mail is currently running, close it first.'),
193 e_requireddir => _('option requires a directory name.'),
194 e_requiredfile => _('option requires a file name.'),
195 e_notadir => _('specified name is not a directory or does not exist.'),
196 e_notafile => _('specified name is not a file or does not exist.'),
199 # all preferences read by load_preferences
201 # values of all preferences handled by clawsker
203 # default config dir and file name
204 my $CONFIGDIR = $ENV{HOME} . '/.claws-mail/';
205 my $CONFIGRC = 'clawsrc';
207 # index constants for preference arrays
208 use constant NAME => 0; # the name on the rc file
209 use constant LABEL => 1; # the label on the GUI
210 use constant DESC => 2; # the description for the hint/help
211 use constant TYPE => 3; # data type: bool, int, float, string, color
212 use constant GUI => 4; # GUI element
214 # constants for GUI spacing
215 use constant HBOX_SPC => 5;
216 use constant FRAME_SPC => 2;
217 use constant PAGE_SPC => 5;
219 # data handlers and auxiliar functions
221 sub handle_bool_value {
222 my ($widget, $event, $dataref) = @_;
223 $$dataref = ($widget->get_active ())? '1': '0';
226 sub handle_int_value {
227 my ($widget, $event, $dataref) = @_;
228 $_ = $widget->get_text ();
233 $widget->set_text ($_);
236 $widget->set_text ($$dataref);
240 sub handle_string_value {
241 my ($widget, $event, $dataref) = @_;
242 $$dataref = $widget->get_text ();
245 sub gdk_color_from_str {
247 my ($rr, $gg, $bb) = (0, 0 ,0);
249 if (/\#([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])/) {
254 my $color = Gtk2::Gdk::Color->new ($rr, $gg, $bb);
258 sub str_from_gdk_color {
260 my $rr = $color->red / 256;
261 my $gg = $color->green / 256;
262 my $bb = $color->blue / 256;
263 my $str = sprintf ("#%.2x%.2x%.2x", $rr, $gg, $bb);
267 sub handle_color_value {
268 my ($widget, $event, $dataref) = @_;
269 my $newcol = $widget->get_color;
270 $$dataref = &str_from_gdk_color ($newcol);
273 sub handle_selection_value {
274 my ($widget, $event, $dataref) = @_;
275 $$dataref = $widget->get_active;
278 sub get_rc_filename {
279 return $CONFIGDIR . $CONFIGRC;
282 sub set_rc_filename {
284 my @parts = split ('/', $fullname);
285 $CONFIGRC = $parts[$#parts];
286 $parts[$#parts] = '';
287 $CONFIGDIR = join ('/', @parts);
290 sub check_claws_not_running() {
291 my $socket = "/tmp/claws-mail-$<";
292 -S $socket and die "$xl::s{e_error}$xl::s{e_running}\n";
295 # graphic element creation
297 sub new_check_button_for {
298 my ($hash, $key) = @_;
299 my $name = $$hash{$key}[NAME];
300 my $label = $$hash{$key}[LABEL];
302 my $hbox = Gtk2::HBox->new (FALSE, 5);
303 my $cb = Gtk2::CheckButton->new ($label);
304 $$hash{$key}[GUI] = $cb;
305 $cb->set_active ($HPVALUE{$name} eq '1');
306 $cb->signal_connect (clicked => sub {
308 &handle_bool_value($w, $e, \$HPVALUE{$name});
310 $hbox->pack_start ($cb, FALSE, FALSE, HBOX_SPC);
315 sub new_text_box_for {
316 my ($hash, $key) = @_;
317 my $name = $$hash{$key}[NAME];
318 my $label = $$hash{$key}[LABEL];
320 my $hbox = Gtk2::HBox->new (FALSE, 5);
321 my $glabel = Gtk2::Label->new ($label);
322 my $gentry = Gtk2::Entry->new;
323 $gentry->set_width_chars (8);
324 $$hash{$key}[GUI] = $gentry;
325 $gentry->set_text($HPVALUE{$name});
326 $gentry->signal_connect(changed => sub {
328 &handle_int_value($w, $e, \$HPVALUE{$name}); # FIXME int only
330 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
331 $hbox->pack_start ($gentry, FALSE, FALSE, HBOX_SPC);
336 sub new_color_button_for {
337 my ($hash, $key) = @_;
338 my $name = $$hash{$key}[NAME];
339 my $label = $$hash{$key}[LABEL];
341 my $col = &gdk_color_from_str ($HPVALUE{$name});
342 my $hbox = Gtk2::HBox->new (FALSE, 5);
343 my $glabel = Gtk2::Label->new ($label);
344 my $button = Gtk2::ColorButton->new_with_color ($col);
345 $$hash{$key}[GUI] = $button;
346 $button->set_title ($label);
347 $button->set_relief ('none');
348 $button->signal_connect ('color-set' => sub {
350 &handle_color_value($w, $e, \$HPVALUE{$name});
352 $hbox->pack_start ($button, FALSE, FALSE, HBOX_SPC);
353 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
358 sub new_selection_box_for {
359 my ($hash, $key) = @_;
360 my $name = $$hash{$key}[NAME];
361 my $label = $$hash{$key}[LABEL];
363 my $hbox = Gtk2::HBox->new (FALSE, 5);
364 my $glabel = Gtk2::Label->new ($label);
365 my $combo = Gtk2::ComboBox->new_text;
366 $$hash{$key}[GUI] = $combo;
367 my @options = split (';', $$hash{$key}[TYPE]);
368 foreach my $opt (@options) {
369 my ($index, $textkey) = split ('=', $opt);
370 $combo->insert_text ($index, $xl::s{$textkey});
372 $combo->signal_connect ('changed' => sub {
374 &handle_selection_value($w, $e, \$HPVALUE{$name});
376 $combo->set_active ($HPVALUE{$name});
377 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
378 $hbox->pack_start ($combo, FALSE, FALSE, HBOX_SPC);
383 # preference maps and corresponding page creation subs
385 %pr::oth = ( # other preferences
387 'addressbook_use_editaddress_dialog',
388 $xl::s{l_oth_use_dlg},
389 $xl::s{h_oth_use_dlg},
394 'cache_max_mem_usage',
395 $xl::s{l_oth_max_use},
396 $xl::s{h_oth_max_use},
401 'cache_min_keep_time',
402 $xl::s{l_oth_min_time},
403 $xl::s{h_oth_min_time},
409 sub new_other_page() {
410 my $of = Gtk2::VBox->new (FALSE, 5);
411 $of->set_border_width (PAGE_SPC);
413 my $ab_frame = Gtk2::Frame->new ($xl::s{ab_frame});
414 my $cb_use_dlg = &new_check_button_for(\%pr::oth, 'use_dlg');
415 my $vb1 = Gtk2::VBox->new (FALSE, 5);
416 $vb1->set_border_width (PAGE_SPC);
417 $vb1->pack_start ($cb_use_dlg, FALSE, FALSE, 0);
418 $ab_frame->add ($vb1);
420 my $mem_frame = Gtk2::Frame->new ($xl::s{mem_frame});
421 my $tb_max_use = &new_text_box_for(\%pr::oth, 'max_use');
422 my $tb_min_time = &new_text_box_for(\%pr::oth, 'min_time');
423 my $vb2 = Gtk2::VBox->new (FALSE, 5);
424 $vb2->set_border_width (PAGE_SPC);
425 $vb2->pack_start ($tb_max_use, FALSE, FALSE, 0);
426 $vb2->pack_start ($tb_min_time, FALSE, FALSE, 0);
427 $mem_frame->add ($vb2);
429 $of->pack_start ($ab_frame, FALSE, FALSE, FRAME_SPC);
430 $of->pack_start ($mem_frame, FALSE, FALSE, FRAME_SPC);
435 %pr::gui = ( # gui bells and whistles
438 $xl::s{l_gui_b_unread},
439 $xl::s{h_gui_b_unread},
445 $xl::s{l_gui_no_markup},
446 $xl::s{h_gui_no_markup},
451 'enable_dotted_lines',
452 $xl::s{l_gui_dot_lines},
453 $xl::s{h_gui_dot_lines},
459 $xl::s{l_gui_h_scroll},
460 $xl::s{h_gui_h_scroll},
466 $xl::s{l_gui_swp_from},
467 $xl::s{h_gui_swp_from},
472 'folderview_vscrollbar_policy',
473 $xl::s{l_gui_v_scroll},
474 $xl::s{h_gui_v_scroll},
475 '0=l_gui_v_scroll_show;1=l_gui_v_scroll_auto;2=l_gui_v_scroll_hide',
479 'stripes_color_offset',
480 $xl::s{l_gui_strip_off},
481 $xl::s{h_gui_strip_off},
486 'textview_cursor_visible',
487 $xl::s{l_gui_cursor_v},
488 $xl::s{h_gui_cursor_v},
493 'toolbar_detachable',
494 $xl::s{l_gui_toolbar_d},
495 $xl::s{h_gui_toolbar_d},
500 'use_stripes_everywhere',
501 $xl::s{l_gui_strip_all},
502 $xl::s{h_gui_strip_all},
507 'use_stripes_in_summaries',
508 $xl::s{l_gui_strip_sum},
509 $xl::s{h_gui_strip_sum},
516 my $gf = Gtk2::VBox->new (FALSE, 5);
517 $gf->set_border_width (PAGE_SPC);
519 my $stripes_frame = Gtk2::Frame->new ($xl::s{stripes_frame});
520 my $cb_strip_all = &new_check_button_for (\%pr::gui, 'strip_all');
521 my $cb_strip_sum = &new_check_button_for (\%pr::gui, 'strip_sum');
522 my $tb_strip_off = &new_text_box_for (\%pr::gui, 'strip_off');
523 my $vb1 = Gtk2::VBox->new (FALSE, 5);
524 $vb1->set_border_width (PAGE_SPC);
525 $vb1->pack_start ($cb_strip_all, FALSE, FALSE, 0);
526 $vb1->pack_start ($cb_strip_sum, FALSE, FALSE, 0);
527 $vb1->pack_start ($tb_strip_off, FALSE, FALSE, 0);
528 $stripes_frame->add ($vb1);
530 my $mlist_frame = Gtk2::Frame->new ($xl::s{mlist_frame});
531 my $cb_b_unread = &new_check_button_for (\%pr::gui, 'b_unread');
532 my $cb_swp_from = &new_check_button_for (\%pr::gui, 'swp_from');
533 my $vb3 = Gtk2::VBox->new (FALSE, 5);
534 $vb3->set_border_width (PAGE_SPC);
535 $vb3->pack_start ($cb_b_unread, FALSE, FALSE, 0);
536 $vb3->pack_start ($cb_swp_from, FALSE, FALSE, 0);
537 $mlist_frame->add ($vb3);
539 my $sbar_frame = Gtk2::Frame->new ($xl::s{sbar_frame});
540 my $cb_h_scroll = &new_check_button_for (\%pr::gui, 'h_scroll');
541 my $sb_v_scroll = &new_selection_box_for (\%pr::gui, 'v_scroll');
542 my $vb2 = Gtk2::VBox->new (FALSE, 5);
543 $vb2->set_border_width (PAGE_SPC);
544 $vb2->pack_start ($cb_h_scroll, FALSE, FALSE, 0);
545 $vb2->pack_start ($sb_v_scroll, FALSE, FALSE, 0);
546 $sbar_frame->add ($vb2);
548 my $cb_no_markup = &new_check_button_for (\%pr::gui, 'no_markup');
549 my $cb_dot_lines = &new_check_button_for (\%pr::gui, 'dot_lines');
550 my $cb_cursor_v = &new_check_button_for (\%pr::gui, 'cursor_v');
551 my $cb_toolbar_d = &new_check_button_for (\%pr::gui, 'toolbar_d');
553 $gf->pack_start ($stripes_frame, FALSE, FALSE, FRAME_SPC);
554 $gf->pack_start ($mlist_frame, FALSE, FALSE, FRAME_SPC);
555 $gf->pack_start ($cb_no_markup, FALSE, FALSE, 0);
556 $gf->pack_start ($cb_dot_lines, FALSE, FALSE, 0);
557 $gf->pack_start ($cb_cursor_v, FALSE, FALSE, 0);
558 $gf->pack_start ($cb_toolbar_d, FALSE, FALSE, 0);
559 $gf->pack_start ($sbar_frame, FALSE, FALSE, FRAME_SPC);
564 %pr::beh = ( # tweak some behaviour
567 $xl::s{l_beh_hover_t},
568 $xl::s{h_beh_hover_t},
574 $xl::s{l_beh_dangerous},
575 $xl::s{h_beh_dangerous},
580 'respect_flowed_format',
581 $xl::s{l_beh_flowed},
582 $xl::s{h_beh_flowed},
587 'save_parts_readwrite',
588 $xl::s{l_beh_parts_rw},
589 $xl::s{h_beh_parts_rw},
594 'skip_ssl_cert_check',
595 $xl::s{l_beh_skip_ssl},
596 $xl::s{h_beh_skip_ssl},
601 'statusbar_update_step',
602 $xl::s{l_beh_up_step},
603 $xl::s{h_beh_up_step},
608 'thread_by_subject_max_age',
609 $xl::s{l_beh_thread_a},
610 $xl::s{h_beh_thread_a},
616 $xl::s{l_beh_unsafe_ssl},
617 $xl::s{h_beh_unsafe_ssl},
622 'utf8_instead_of_locale_for_broken_mail',
623 $xl::s{l_beh_use_utf8},
624 $xl::s{h_beh_use_utf8},
630 $xl::s{l_beh_warn_dnd},
631 $xl::s{h_beh_warn_dnd},
637 sub new_behaviour_page() {
638 my $bf = Gtk2::VBox->new (FALSE, 5);
639 $bf->set_border_width (PAGE_SPC);
641 my $dnd_frame = Gtk2::Frame->new ($xl::s{dnd_frame});
642 my $tb_hoover_t = &new_text_box_for (\%pr::beh, 'hover_t');
643 my $cb_warn_dnd = &new_check_button_for (\%pr::beh, 'warn_dnd');
644 my $vb1 = Gtk2::VBox->new (FALSE, 5);
645 $vb1->set_border_width (PAGE_SPC);
646 $vb1->pack_start ($cb_warn_dnd, FALSE, FALSE, 0);
647 $vb1->pack_start ($tb_hoover_t, FALSE, FALSE, 0);
648 $dnd_frame->add ($vb1);
650 my $ssl_frame = Gtk2::Frame->new ($xl::s{ssl_frame});
651 my $cb_skip_ssl = &new_check_button_for (\%pr::beh, 'skip_ssl');
652 my $cb_unsafe_ssl = &new_check_button_for (\%pr::beh, 'unsafe_ssl');
653 my $hb1 = Gtk2::HBox->new (FALSE, 5);
654 $hb1->set_border_width (PAGE_SPC);
655 $hb1->pack_start ($cb_skip_ssl, FALSE, FALSE, 0);
656 $hb1->pack_start ($cb_unsafe_ssl, FALSE, FALSE, 0);
657 $ssl_frame->add ($hb1);
659 my $tb_up_step = &new_text_box_for (\%pr::beh, 'up_step');
660 my $tb_thread_a = &new_text_box_for (\%pr::beh, 'thread_a');
662 my $msgs_frame = Gtk2::Frame->new ($xl::s{msgs_frame});
663 my $cb_flowed = &new_check_button_for (\%pr::beh, 'flowed');
664 my $cb_parts_rw = &new_check_button_for (\%pr::beh, 'parts_rw');
665 my $cb_use_utf8 = &new_check_button_for (\%pr::beh, 'use_utf8');
666 my $cb_dangerous = &new_check_button_for (\%pr::beh, 'dangerous');
667 my $vb2 = Gtk2::VBox->new (FALSE, 5);
668 $vb2->set_border_width (PAGE_SPC);
669 $vb2->pack_start ($cb_flowed, FALSE, FALSE, 0);
670 $vb2->pack_start ($cb_parts_rw, FALSE, FALSE, 0);
671 $vb2->pack_start ($cb_use_utf8, FALSE, FALSE, 0);
672 $vb2->pack_start ($cb_dangerous, FALSE, FALSE, 0);
673 $msgs_frame->add ($vb2);
675 $bf->pack_start ($dnd_frame, FALSE, FALSE, FRAME_SPC);
676 $bf->pack_start ($ssl_frame, FALSE, FALSE, FRAME_SPC);
677 $bf->pack_start ($tb_up_step, FALSE, FALSE, 0);
678 $bf->pack_start ($tb_thread_a, FALSE, FALSE, 0);
679 $bf->pack_start ($msgs_frame, FALSE, FALSE, FRAME_SPC);
684 %pr::col = ( # a variety of colours
687 $xl::s{l_col_emphasis},
688 $xl::s{h_col_emphasis},
694 $xl::s{l_col_log_err},
695 $xl::s{h_col_log_err},
701 $xl::s{l_col_log_in},
702 $xl::s{h_col_log_in},
708 $xl::s{l_col_log_msg},
709 $xl::s{h_col_log_msg},
715 $xl::s{l_col_log_out},
716 $xl::s{h_col_log_out},
722 $xl::s{l_col_log_warn},
723 $xl::s{h_col_log_warn},
729 sub new_colours_page() {
730 my $cf = Gtk2::VBox->new (FALSE, 5);
731 $cf->set_border_width (PAGE_SPC);
733 my $msgview_frame = Gtk2::Frame->new ($xl::s{msgview_frame});
734 my $cb_emphasis = &new_color_button_for (\%pr::col, 'emphasis');
735 my $vb1 = Gtk2::VBox->new (FALSE, 5);
736 $vb1->set_border_width (PAGE_SPC);
737 $vb1->pack_start ($cb_emphasis, FALSE, FALSE, 0);
738 $msgview_frame->add ($vb1);
740 my $log_frame = Gtk2::Frame->new ($xl::s{log_frame});
741 my $cb_log_err = &new_color_button_for (\%pr::col, 'log_err');
742 my $cb_log_in = &new_color_button_for (\%pr::col, 'log_in');
743 my $cb_log_msg = &new_color_button_for (\%pr::col, 'log_msg');
744 my $cb_log_out = &new_color_button_for (\%pr::col, 'log_out');
745 my $cb_log_warn = &new_color_button_for (\%pr::col, 'log_warn');
746 my $vb2 = Gtk2::VBox->new (FALSE, 5);
747 $vb2->set_border_width (PAGE_SPC);
748 $vb2->pack_start ($cb_log_err, FALSE, FALSE, 0);
749 $vb2->pack_start ($cb_log_in, FALSE, FALSE, 0);
750 $vb2->pack_start ($cb_log_msg, FALSE, FALSE, 0);
751 $vb2->pack_start ($cb_log_out, FALSE, FALSE, 0);
752 $vb2->pack_start ($cb_log_warn, FALSE, FALSE, 0);
753 $log_frame->add ($vb2);
755 $cf->pack_start ($msgview_frame, FALSE, FALSE, 0);
756 $cf->pack_start ($log_frame, FALSE, FALSE, 0);
761 # the command line help
763 my $line = '-' x length ($xl::s{about_title}) . "\n";
765 print $xl::s{about_title} . "\n";
766 print $xl::s{about_version} . " $VERSION\n";
768 print _("Syntax:\n");
769 print _(" clawsker [options]\n");
770 print _("Options:\n");
771 print _(" --help Prints this help screen.\n");
772 print _(" --alternate-config-dir <dir> Uses <dir> as Claws Mail config dir.\n");
773 print _(" --clawsrc <file> Uses <file> as full resource name.\n");
776 # parse the command line
777 sub parse_command_line() {
779 while (defined($ARGV[$arg])) {
785 /--alternate-config-dir/ && do {
787 die "$xl::s{e_error}$xl::s{e_requireddir}\n"
788 unless defined($ARGV[$arg]);
789 die "$xl::s{e_error}$xl::s{e_notadir}\n"
790 unless -d $ARGV[$arg];
791 $CONFIGDIR = $ARGV[$arg];
796 die "$xl::s{e_error}$xl::s{e_requiredfile}\n"
797 unless defined($ARGV[$arg]);
798 die "$xl::s{e_error}$xl::s{e_notafile}\n"
799 unless -f $ARGV[$arg];
800 &set_rc_filename ($ARGV[$arg]);
803 /.*/ && die $xl::s{e_error}
804 . _("unknown option '{opt}'.\n", opt => $ARGV[$arg]);
810 # update the hidden preferences status from loaded values
811 sub init_hidden_preferences() {
812 foreach my $hash (\%pr::beh, \%pr::col, \%pr::gui, \%pr::oth) {
813 foreach my $key (keys %$hash) {
814 $HPVALUE{${$hash}{$key}[NAME]} = $PREFS{${$hash}{$key}[NAME]};
819 # load current status from disc
820 sub load_preferences() {
821 my $rc = &get_rc_filename;
822 -f $rc or die "$xl::s{e_error}$xl::s{e_noclawsrc}\n";
823 &check_claws_not_running;
827 if (/^([8a-z_]+)=(.*)$/) {
834 # save current preferences to disc
835 sub save_preferences() {
836 my $rc = &get_rc_filename;
837 -f $rc or die "$xl::s{e_error}$xl::s{e_noclawsrc}\n";
838 &check_claws_not_running;
839 my $rcbak = "$rc.backup";
840 rename ($rc, $rcbak);
842 open (RCB, "<$rcbak");
845 if (/^([8a-z_]+)=(.*)$/) {
846 if (defined($HPVALUE{$1})) {
847 print RCF $1 . "=" . $HPVALUE{$1} . "\n";
863 my $nb = Gtk2::Notebook->new;
865 $nb->append_page (&new_behaviour_page, $xl::s{tab_behaviour});
866 $nb->append_page (&new_colours_page, $xl::s{tab_colours});
867 $nb->append_page (&new_gui_page, $xl::s{tab_gui});
868 $nb->append_page (&new_other_page, $xl::s{tab_other});
873 # create an about dialog
874 sub new_about_dialog() {
876 my $title = $xl::s{about_title};
877 my $lic = $xl::s{about_license};
878 my $vers = $xl::s{about_version} . " $VERSION";
880 "This program is free software: you can redistribute it and/or modify
881 it under the terms of the GNU General Public License as published by
882 the Free Software Foundation, either version 3 of the License, or
883 (at your option) any later version.
885 This program is distributed in the hope that it will be useful,
886 but WITHOUT ANY WARRANTY; without even the implied warranty of
887 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
888 GNU General Public License for more details.
890 You should have received a copy of the GNU General Public License
891 along with this program. If not, see <http://www.gnu.org/licenses/>.";
893 my $holder = "Ricardo Mones <ricardo\@mones.org>";
895 my $dialog = Gtk2::MessageDialog->new_with_markup ($parent,
896 [qw/modal destroy-with-parent/],
898 "<span size=\"x-large\" weight=\"bold\">$title</span>\n"
899 . "<span size=\"large\">$vers</span>\n"
900 . "<span>Copyright $year by $holder</span>\n\n"
901 . "<span size=\"large\">$lic</span>\n\n"
902 . "<span size=\"small\">$license</span>");
903 $dialog->set_title ($xl::s{about});
909 sub new_button_box() {
911 my $b_about = Gtk2::Button->new_from_stock ('gtk-about');
912 my $b_exit = Gtk2::Button->new_from_stock ('gtk-quit');
913 my $b_apply = Gtk2::Button->new_from_stock ('gtk-apply');
914 # disable button until is really implemented
915 # my $b_undo = Gtk2::Button->new_from_stock ('gtk-undo');
916 my $hbox = Gtk2::HBox->new (FALSE, 5);
918 $b_exit->signal_connect (clicked => sub { Gtk2->main_quit });
919 $b_apply->signal_connect (clicked => sub { &save_preferences });
920 # $b_undo->signal_connect (clicked => sub { &undo_current_changes });
921 $b_about->signal_connect (clicked => sub { $adlg->run; $adlg->hide });
923 $hbox->pack_end ($b_exit, FALSE, FALSE, 0);
924 $hbox->pack_end ($b_apply, FALSE, FALSE, 0);
925 # $hbox->pack_end ($b_undo, FALSE, FALSE, 0);
926 $hbox->pack_start ($b_about, FALSE, FALSE, 0);
934 &init_hidden_preferences;
936 my $window = Gtk2::Window->new ('toplevel');
937 my $box = Gtk2::VBox->new (FALSE, 5);
938 $box->set_border_width(3);
939 my $about = &new_about_dialog;
940 $box->pack_start (&new_notebook, FALSE, FALSE, 0);
941 $box->pack_end (&new_button_box ($about), FALSE, FALSE, 0);
942 $window->signal_connect (delete_event => sub { Gtk2->main_quit });
943 $window->set_title ($xl::s{win_title});