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 are not widely used are not provided with a graphical
23 interface for inspection and/or modification.
25 Users wanting to edit such preferences had to face raw editing 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 A running Claws Mail cannot be detected if using the --clawsrc option because
47 the directory is not assumed to be a Claws Mail configuration dir. If that is
48 the case use the --alternate-config-dir option instead.
52 Ricardo Mones E<lt>ricardo@mones.orgE<gt>
56 Copyright (c) 2007 by Ricardo Mones
58 This program is free software: you can redistribute it and/or modify
59 it under the terms of the GNU General Public License as published by
60 the Free Software Foundation, either version 3 of the License, or
61 (at your option) any later version.
63 This program is distributed in the hope that it will be useful,
64 but WITHOUT ANY WARRANTY; without even the implied warranty of
65 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66 GNU General Public License for more details.
68 You should have received a copy of the GNU General Public License
69 along with this program. If not, see E<lt>http://www.gnu.org/licenses/E<gt>.
74 use POSIX qw(setlocale);
76 use Glib qw(TRUE FALSE);
79 my $NAME = 'clawsker';
80 my $PREFIX = '@PREFIX@';
81 my $LIBDIR = '@LIBDIR@';
82 my $VERSION = '@VERSION@';
84 my $locale = (defined($ENV{LC_MESSAGES}) ? $ENV{LC_MESSAGES} : $ENV{LANG});
85 setlocale (LC_ALL, $locale);
86 bindtextdomain ($NAME, sprintf ('%s/share/locale', $PREFIX));
92 my $xla = gettext ($str);
93 if (scalar(keys(%par)) > 0) {
94 foreach my $key (keys %par) {
95 $xla =~ s/\{$key\}/$par{$key}/g;
103 win_title => _('Claws Mail Hidden Preferences'),
104 about => _('About...'),
105 about_title => _('Clawsker :: A Claws Mail Tweaker'),
106 about_license => _('License:'),
107 about_version => _('Version:'),
109 tab_colours => _('Colours'),
110 tab_behaviour => _('Behaviour'),
112 tab_other => _('Other'),
114 ab_frame => _('Addressbook'),
115 mem_frame => _('Memory'),
116 msgview_frame => _('Message view'),
117 log_frame => _('Log window'),
118 dnd_frame => _('Drag \'n\' drop'),
119 ssl_frame => _('Secure Sockets Layer'),
120 msgs_frame => _('Messages'),
121 stripes_frame => _('Coloured stripes'),
122 sbar_frame => _('Scroll bars'),
123 mlist_frame => _('Message list'),
125 l_oth_use_dlg => _('Use detached address book edit dialogue'),
126 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.'),
127 l_oth_max_use => _('Maximum memory for message cache (Kb)'),
128 h_oth_max_use => _('The maximum amount of memory to use to cache messages, in kB.'),
129 l_oth_min_time => _('Minimun time for cache elements (minutes)'),
130 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.'),
132 l_gui_b_unread => _('Show unread messages with bold font'),
133 h_gui_b_unread => _('Show unread messages in the Message List using a bold font.'),
134 l_gui_no_markup => _('Don\'t use markup in compose window'),
135 h_gui_no_markup => _('Don\'t use bold and italic text in Compose dialogue\'s account selector.'),
136 l_gui_dot_lines => _('Use dotted lines in tree views'),
137 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.'),
138 l_gui_h_scroll => _('Enable horizontal scrollbar'),
139 h_gui_h_scroll => _('Enable the horizontal scrollbar in the Message List.'),
140 l_gui_swp_from => _('Dislay To header in From field in Sent folder'),
141 h_gui_swp_from => _('Display the sender\'s email address in the To column of the Sent folder instead of the recipient\'s.'),
142 l_gui_v_scroll => _('Folder list scrollbar behaviour'),
143 h_gui_v_scroll => _('Specify the policy of vertical scrollbar of Folder List: show always, automatic or hide always.'),
144 l_gui_v_scroll_show => _('Show always'),
145 l_gui_v_scroll_auto => _('Automatic'),
146 l_gui_v_scroll_hide => _('Hide always'),
147 l_gui_strip_off => _('Striped lines contrast'),
148 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.'),
149 l_gui_cursor_v => _('Show Cursor in message view'),
150 h_gui_cursor_v => _('Display the cursor in the message view.'),
151 l_gui_toolbar_d => _('Detachable toolbars'),
152 h_gui_toolbar_d => _('Show handles in the toolbars.'),
153 l_gui_strip_all => _('Use stripes in all tree view components'),
154 h_gui_strip_all => _('Enable alternately coloured lines in all tree view components.'),
155 l_gui_strip_sum => _('Use stripes in Folder List and Message List'),
156 h_gui_strip_sum => _('Enable alternately coloured lines in message list and folder list'),
158 l_beh_hover_t => _('Drag \'n\' drop hover timeout (ms)'),
159 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.'),
160 l_beh_dangerous => _('Don\'t confirm deletions (dangerous!)'),
161 h_beh_dangerous => _('Don\'t ask for confirmation before definitive deletion of emails.'),
162 l_beh_flowed => _('Respect format=flowed in messages'),
163 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.'),
164 l_beh_parts_rw => _('Allow writable temporary files'),
165 h_beh_parts_rw => _('Saves temporary files when opening attachment with write bit set.'),
166 l_beh_skip_ssl => _('Don\'t check SSL certificates'),
167 h_beh_skip_ssl => _('Disables the verification of SSL certificates.'),
168 l_beh_up_step => _('Progress bar update step (items)'),
169 h_beh_up_step => _('Update stepping in progress bars.'),
170 l_beh_thread_a => _('Maximum age when threading by subject (days)'),
171 h_beh_thread_a => _('Number of days to include a message in a thread when using "Thread using subject in addition to standard headers".'),
172 l_beh_unsafe_ssl => _('Allow unsafe SSL certificates'),
173 h_beh_unsafe_ssl => _('Allows Claws Mail to remember multiple SSL certificates for a given server/port.'),
174 l_beh_use_utf8 => _('Force UTF-8 for broken mails'),
175 h_beh_use_utf8 => _('Use UTF-8 encoding for broken mails instead of current locale.'),
176 l_beh_warn_dnd => _('Warn on drag \'n\' drop'),
177 h_beh_warn_dnd => _('Display a confirmation dialogue on drag \'n\' drop of folders.'),
179 l_col_emphasis => _('X-Mailer header'),
180 h_col_emphasis => _('The colour used for the X-Mailer line when its value is Claws Mail.'),
181 l_col_log_err => _('Error messages'),
182 h_col_log_err => _('Colour for error messages in log window.'),
183 l_col_log_in => _('Server messages'),
184 h_col_log_in => _('Colour for input messages in log window.'),
185 l_col_log_msg => _('Standard messages'),
186 h_col_log_msg => _('Colour for messages in log window.'),
187 l_col_log_out => _('Client messages'),
188 h_col_log_out => _('Colour for output messages in log window.'),
189 l_col_log_warn => _('Warnings'),
190 h_col_log_warn => _('Colour for warning messages in log window.'),
192 e_error => _('Error: '),
193 e_noclawsrc => _('resource file for Claws Mail was not found.'),
194 e_running => _('seems Claws Mail is currently running, close it first.'),
195 e_requireddir => _('option requires a directory name.'),
196 e_requiredfile => _('option requires a file name.'),
197 e_notadir => _('specified name is not a directory or does not exist.'),
198 e_notafile => _('specified name is not a file or does not exist.'),
201 # all preferences read by load_preferences
203 # values of all preferences handled by clawsker
205 # default config dir and file name
206 my $ALTCONFIGDIR = FALSE;
207 my $CONFIGDIR = $ENV{HOME} . '/.claws-mail/';
208 my $CONFIGRC = 'clawsrc';
210 # index constants for preference arrays
211 use constant NAME => 0; # the name on the rc file
212 use constant LABEL => 1; # the label on the GUI
213 use constant DESC => 2; # the description for the hint/help
214 use constant TYPE => 3; # data type: bool, int, float, string, color
215 use constant GUI => 4; # GUI element
217 # constants for GUI spacing
218 use constant HBOX_SPC => 5;
219 use constant FRAME_SPC => 2;
220 use constant PAGE_SPC => 5;
222 # data handlers and auxiliar functions
224 sub handle_bool_value {
225 my ($widget, $event, $dataref) = @_;
226 $$dataref = ($widget->get_active ())? '1': '0';
229 sub handle_int_value {
230 my ($widget, $event, $dataref) = @_;
231 $_ = $widget->get_text ();
236 $widget->set_text ($_);
239 $widget->set_text ($$dataref);
243 sub handle_string_value {
244 my ($widget, $event, $dataref) = @_;
245 $$dataref = $widget->get_text ();
248 sub gdk_color_from_str {
250 my ($rr, $gg, $bb) = (0, 0 ,0);
252 if (/\#([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])([A-F0-9][A-F0-9])/) {
257 my $color = Gtk2::Gdk::Color->new ($rr, $gg, $bb);
261 sub str_from_gdk_color {
263 my $rr = $color->red / 256;
264 my $gg = $color->green / 256;
265 my $bb = $color->blue / 256;
266 my $str = sprintf ("#%.2x%.2x%.2x", $rr, $gg, $bb);
270 sub handle_color_value {
271 my ($widget, $event, $dataref) = @_;
272 my $newcol = $widget->get_color;
273 $$dataref = &str_from_gdk_color ($newcol);
276 sub handle_selection_value {
277 my ($widget, $event, $dataref) = @_;
278 $$dataref = $widget->get_active;
281 sub get_rc_filename {
282 return $CONFIGDIR . $CONFIGRC;
285 sub set_rc_filename {
287 my @parts = split ('/', $fullname);
288 $CONFIGRC = $parts[$#parts];
289 $parts[$#parts] = '';
290 $CONFIGDIR = join ('/', @parts);
293 sub check_claws_not_running() {
295 my $socket = (not $ALTCONFIGDIR)? "/tmp/": $CONFIGDIR;
296 $socket .= "claws-mail-$<";
298 my $emsg = "$xl::s{e_error}$xl::s{e_running}";
299 die "$emsg\n" unless defined($parent);
300 my $errordlg = Gtk2::MessageDialog->new ($parent, 'modal', 'error', 'cancel', $emsg);
301 $errordlg->set_title (_('Error'));
310 # graphic element creation
312 sub new_check_button_for {
313 my ($hash, $key) = @_;
314 my $name = $$hash{$key}[NAME];
315 my $label = $$hash{$key}[LABEL];
317 my $hbox = Gtk2::HBox->new (FALSE, 5);
318 my $cb = Gtk2::CheckButton->new ($label);
319 $$hash{$key}[GUI] = $cb;
320 $cb->set_active ($HPVALUE{$name} eq '1');
321 $cb->signal_connect (clicked => sub {
323 &handle_bool_value($w, $e, \$HPVALUE{$name});
325 $hbox->pack_start ($cb, FALSE, FALSE, HBOX_SPC);
330 sub new_text_box_for {
331 my ($hash, $key) = @_;
332 my $name = $$hash{$key}[NAME];
333 my $label = $$hash{$key}[LABEL];
335 my $hbox = Gtk2::HBox->new (FALSE, 5);
336 my $glabel = Gtk2::Label->new ($label);
337 my $gentry = Gtk2::Entry->new;
338 $gentry->set_width_chars (8);
339 $$hash{$key}[GUI] = $gentry;
340 $gentry->set_text($HPVALUE{$name});
341 $gentry->signal_connect(changed => sub {
343 &handle_int_value($w, $e, \$HPVALUE{$name}); # FIXME int only
345 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
346 $hbox->pack_start ($gentry, FALSE, FALSE, HBOX_SPC);
351 sub new_color_button_for {
352 my ($hash, $key) = @_;
353 my $name = $$hash{$key}[NAME];
354 my $label = $$hash{$key}[LABEL];
356 my $col = &gdk_color_from_str ($HPVALUE{$name});
357 my $hbox = Gtk2::HBox->new (FALSE, 5);
358 my $glabel = Gtk2::Label->new ($label);
359 my $button = Gtk2::ColorButton->new_with_color ($col);
360 $$hash{$key}[GUI] = $button;
361 $button->set_title ($label);
362 $button->set_relief ('none');
363 $button->signal_connect ('color-set' => sub {
365 &handle_color_value($w, $e, \$HPVALUE{$name});
367 $hbox->pack_start ($button, FALSE, FALSE, HBOX_SPC);
368 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
373 sub new_selection_box_for {
374 my ($hash, $key) = @_;
375 my $name = $$hash{$key}[NAME];
376 my $label = $$hash{$key}[LABEL];
378 my $hbox = Gtk2::HBox->new (FALSE, 5);
379 my $glabel = Gtk2::Label->new ($label);
380 my $combo = Gtk2::ComboBox->new_text;
381 $$hash{$key}[GUI] = $combo;
382 my @options = split (';', $$hash{$key}[TYPE]);
383 foreach my $opt (@options) {
384 my ($index, $textkey) = split ('=', $opt);
385 $combo->insert_text ($index, $xl::s{$textkey});
387 $combo->signal_connect ('changed' => sub {
389 &handle_selection_value($w, $e, \$HPVALUE{$name});
391 $combo->set_active ($HPVALUE{$name});
392 $hbox->pack_start ($glabel, FALSE, FALSE, HBOX_SPC);
393 $hbox->pack_start ($combo, FALSE, FALSE, HBOX_SPC);
398 # preference maps and corresponding page creation subs
400 %pr::oth = ( # other preferences
402 'addressbook_use_editaddress_dialog',
403 $xl::s{l_oth_use_dlg},
404 $xl::s{h_oth_use_dlg},
409 'cache_max_mem_usage',
410 $xl::s{l_oth_max_use},
411 $xl::s{h_oth_max_use},
416 'cache_min_keep_time',
417 $xl::s{l_oth_min_time},
418 $xl::s{h_oth_min_time},
424 sub new_other_page() {
425 my $of = Gtk2::VBox->new (FALSE, 5);
426 $of->set_border_width (PAGE_SPC);
428 my $ab_frame = Gtk2::Frame->new ($xl::s{ab_frame});
429 my $cb_use_dlg = &new_check_button_for(\%pr::oth, 'use_dlg');
430 my $vb1 = Gtk2::VBox->new (FALSE, 5);
431 $vb1->set_border_width (PAGE_SPC);
432 $vb1->pack_start ($cb_use_dlg, FALSE, FALSE, 0);
433 $ab_frame->add ($vb1);
435 my $mem_frame = Gtk2::Frame->new ($xl::s{mem_frame});
436 my $tb_max_use = &new_text_box_for(\%pr::oth, 'max_use');
437 my $tb_min_time = &new_text_box_for(\%pr::oth, 'min_time');
438 my $vb2 = Gtk2::VBox->new (FALSE, 5);
439 $vb2->set_border_width (PAGE_SPC);
440 $vb2->pack_start ($tb_max_use, FALSE, FALSE, 0);
441 $vb2->pack_start ($tb_min_time, FALSE, FALSE, 0);
442 $mem_frame->add ($vb2);
444 $of->pack_start ($ab_frame, FALSE, FALSE, FRAME_SPC);
445 $of->pack_start ($mem_frame, FALSE, FALSE, FRAME_SPC);
450 %pr::gui = ( # gui bells and whistles
453 $xl::s{l_gui_b_unread},
454 $xl::s{h_gui_b_unread},
460 $xl::s{l_gui_no_markup},
461 $xl::s{h_gui_no_markup},
466 'enable_dotted_lines',
467 $xl::s{l_gui_dot_lines},
468 $xl::s{h_gui_dot_lines},
474 $xl::s{l_gui_h_scroll},
475 $xl::s{h_gui_h_scroll},
481 $xl::s{l_gui_swp_from},
482 $xl::s{h_gui_swp_from},
487 'folderview_vscrollbar_policy',
488 $xl::s{l_gui_v_scroll},
489 $xl::s{h_gui_v_scroll},
490 '0=l_gui_v_scroll_show;1=l_gui_v_scroll_auto;2=l_gui_v_scroll_hide',
494 'stripes_color_offset',
495 $xl::s{l_gui_strip_off},
496 $xl::s{h_gui_strip_off},
501 'textview_cursor_visible',
502 $xl::s{l_gui_cursor_v},
503 $xl::s{h_gui_cursor_v},
508 'toolbar_detachable',
509 $xl::s{l_gui_toolbar_d},
510 $xl::s{h_gui_toolbar_d},
515 'use_stripes_everywhere',
516 $xl::s{l_gui_strip_all},
517 $xl::s{h_gui_strip_all},
522 'use_stripes_in_summaries',
523 $xl::s{l_gui_strip_sum},
524 $xl::s{h_gui_strip_sum},
531 my $gf = Gtk2::VBox->new (FALSE, 5);
532 $gf->set_border_width (PAGE_SPC);
534 my $stripes_frame = Gtk2::Frame->new ($xl::s{stripes_frame});
535 my $cb_strip_all = &new_check_button_for (\%pr::gui, 'strip_all');
536 my $cb_strip_sum = &new_check_button_for (\%pr::gui, 'strip_sum');
537 my $tb_strip_off = &new_text_box_for (\%pr::gui, 'strip_off');
538 my $vb1 = Gtk2::VBox->new (FALSE, 5);
539 $vb1->set_border_width (PAGE_SPC);
540 $vb1->pack_start ($cb_strip_all, FALSE, FALSE, 0);
541 $vb1->pack_start ($cb_strip_sum, FALSE, FALSE, 0);
542 $vb1->pack_start ($tb_strip_off, FALSE, FALSE, 0);
543 $stripes_frame->add ($vb1);
545 my $mlist_frame = Gtk2::Frame->new ($xl::s{mlist_frame});
546 my $cb_b_unread = &new_check_button_for (\%pr::gui, 'b_unread');
547 my $cb_swp_from = &new_check_button_for (\%pr::gui, 'swp_from');
548 my $vb3 = Gtk2::VBox->new (FALSE, 5);
549 $vb3->set_border_width (PAGE_SPC);
550 $vb3->pack_start ($cb_b_unread, FALSE, FALSE, 0);
551 $vb3->pack_start ($cb_swp_from, FALSE, FALSE, 0);
552 $mlist_frame->add ($vb3);
554 my $sbar_frame = Gtk2::Frame->new ($xl::s{sbar_frame});
555 my $cb_h_scroll = &new_check_button_for (\%pr::gui, 'h_scroll');
556 my $sb_v_scroll = &new_selection_box_for (\%pr::gui, 'v_scroll');
557 my $vb2 = Gtk2::VBox->new (FALSE, 5);
558 $vb2->set_border_width (PAGE_SPC);
559 $vb2->pack_start ($cb_h_scroll, FALSE, FALSE, 0);
560 $vb2->pack_start ($sb_v_scroll, FALSE, FALSE, 0);
561 $sbar_frame->add ($vb2);
563 my $cb_no_markup = &new_check_button_for (\%pr::gui, 'no_markup');
564 my $cb_dot_lines = &new_check_button_for (\%pr::gui, 'dot_lines');
565 my $cb_cursor_v = &new_check_button_for (\%pr::gui, 'cursor_v');
566 my $cb_toolbar_d = &new_check_button_for (\%pr::gui, 'toolbar_d');
568 $gf->pack_start ($stripes_frame, FALSE, FALSE, FRAME_SPC);
569 $gf->pack_start ($mlist_frame, FALSE, FALSE, FRAME_SPC);
570 $gf->pack_start ($cb_no_markup, FALSE, FALSE, 0);
571 $gf->pack_start ($cb_dot_lines, FALSE, FALSE, 0);
572 $gf->pack_start ($cb_cursor_v, FALSE, FALSE, 0);
573 $gf->pack_start ($cb_toolbar_d, FALSE, FALSE, 0);
574 $gf->pack_start ($sbar_frame, FALSE, FALSE, FRAME_SPC);
579 %pr::beh = ( # tweak some behaviour
582 $xl::s{l_beh_hover_t},
583 $xl::s{h_beh_hover_t},
589 $xl::s{l_beh_dangerous},
590 $xl::s{h_beh_dangerous},
595 'respect_flowed_format',
596 $xl::s{l_beh_flowed},
597 $xl::s{h_beh_flowed},
602 'save_parts_readwrite',
603 $xl::s{l_beh_parts_rw},
604 $xl::s{h_beh_parts_rw},
609 'skip_ssl_cert_check',
610 $xl::s{l_beh_skip_ssl},
611 $xl::s{h_beh_skip_ssl},
616 'statusbar_update_step',
617 $xl::s{l_beh_up_step},
618 $xl::s{h_beh_up_step},
623 'thread_by_subject_max_age',
624 $xl::s{l_beh_thread_a},
625 $xl::s{h_beh_thread_a},
631 $xl::s{l_beh_unsafe_ssl},
632 $xl::s{h_beh_unsafe_ssl},
637 'utf8_instead_of_locale_for_broken_mail',
638 $xl::s{l_beh_use_utf8},
639 $xl::s{h_beh_use_utf8},
645 $xl::s{l_beh_warn_dnd},
646 $xl::s{h_beh_warn_dnd},
652 sub new_behaviour_page() {
653 my $bf = Gtk2::VBox->new (FALSE, 5);
654 $bf->set_border_width (PAGE_SPC);
656 my $dnd_frame = Gtk2::Frame->new ($xl::s{dnd_frame});
657 my $tb_hoover_t = &new_text_box_for (\%pr::beh, 'hover_t');
658 my $cb_warn_dnd = &new_check_button_for (\%pr::beh, 'warn_dnd');
659 my $vb1 = Gtk2::VBox->new (FALSE, 5);
660 $vb1->set_border_width (PAGE_SPC);
661 $vb1->pack_start ($cb_warn_dnd, FALSE, FALSE, 0);
662 $vb1->pack_start ($tb_hoover_t, FALSE, FALSE, 0);
663 $dnd_frame->add ($vb1);
665 my $ssl_frame = Gtk2::Frame->new ($xl::s{ssl_frame});
666 my $cb_skip_ssl = &new_check_button_for (\%pr::beh, 'skip_ssl');
667 my $cb_unsafe_ssl = &new_check_button_for (\%pr::beh, 'unsafe_ssl');
668 my $hb1 = Gtk2::HBox->new (FALSE, 5);
669 $hb1->set_border_width (PAGE_SPC);
670 $hb1->pack_start ($cb_skip_ssl, FALSE, FALSE, 0);
671 $hb1->pack_start ($cb_unsafe_ssl, FALSE, FALSE, 0);
672 $ssl_frame->add ($hb1);
674 my $tb_up_step = &new_text_box_for (\%pr::beh, 'up_step');
675 my $tb_thread_a = &new_text_box_for (\%pr::beh, 'thread_a');
677 my $msgs_frame = Gtk2::Frame->new ($xl::s{msgs_frame});
678 my $cb_flowed = &new_check_button_for (\%pr::beh, 'flowed');
679 my $cb_parts_rw = &new_check_button_for (\%pr::beh, 'parts_rw');
680 my $cb_use_utf8 = &new_check_button_for (\%pr::beh, 'use_utf8');
681 my $cb_dangerous = &new_check_button_for (\%pr::beh, 'dangerous');
682 my $vb2 = Gtk2::VBox->new (FALSE, 5);
683 $vb2->set_border_width (PAGE_SPC);
684 $vb2->pack_start ($cb_flowed, FALSE, FALSE, 0);
685 $vb2->pack_start ($cb_parts_rw, FALSE, FALSE, 0);
686 $vb2->pack_start ($cb_use_utf8, FALSE, FALSE, 0);
687 $vb2->pack_start ($cb_dangerous, FALSE, FALSE, 0);
688 $msgs_frame->add ($vb2);
690 $bf->pack_start ($dnd_frame, FALSE, FALSE, FRAME_SPC);
691 $bf->pack_start ($ssl_frame, FALSE, FALSE, FRAME_SPC);
692 $bf->pack_start ($tb_up_step, FALSE, FALSE, 0);
693 $bf->pack_start ($tb_thread_a, FALSE, FALSE, 0);
694 $bf->pack_start ($msgs_frame, FALSE, FALSE, FRAME_SPC);
699 %pr::col = ( # a variety of colours
702 $xl::s{l_col_emphasis},
703 $xl::s{h_col_emphasis},
709 $xl::s{l_col_log_err},
710 $xl::s{h_col_log_err},
716 $xl::s{l_col_log_in},
717 $xl::s{h_col_log_in},
723 $xl::s{l_col_log_msg},
724 $xl::s{h_col_log_msg},
730 $xl::s{l_col_log_out},
731 $xl::s{h_col_log_out},
737 $xl::s{l_col_log_warn},
738 $xl::s{h_col_log_warn},
744 sub new_colours_page() {
745 my $cf = Gtk2::VBox->new (FALSE, 5);
746 $cf->set_border_width (PAGE_SPC);
748 my $msgview_frame = Gtk2::Frame->new ($xl::s{msgview_frame});
749 my $cb_emphasis = &new_color_button_for (\%pr::col, 'emphasis');
750 my $vb1 = Gtk2::VBox->new (FALSE, 5);
751 $vb1->set_border_width (PAGE_SPC);
752 $vb1->pack_start ($cb_emphasis, FALSE, FALSE, 0);
753 $msgview_frame->add ($vb1);
755 my $log_frame = Gtk2::Frame->new ($xl::s{log_frame});
756 my $cb_log_err = &new_color_button_for (\%pr::col, 'log_err');
757 my $cb_log_in = &new_color_button_for (\%pr::col, 'log_in');
758 my $cb_log_msg = &new_color_button_for (\%pr::col, 'log_msg');
759 my $cb_log_out = &new_color_button_for (\%pr::col, 'log_out');
760 my $cb_log_warn = &new_color_button_for (\%pr::col, 'log_warn');
761 my $vb2 = Gtk2::VBox->new (FALSE, 5);
762 $vb2->set_border_width (PAGE_SPC);
763 $vb2->pack_start ($cb_log_err, FALSE, FALSE, 0);
764 $vb2->pack_start ($cb_log_in, FALSE, FALSE, 0);
765 $vb2->pack_start ($cb_log_msg, FALSE, FALSE, 0);
766 $vb2->pack_start ($cb_log_out, FALSE, FALSE, 0);
767 $vb2->pack_start ($cb_log_warn, FALSE, FALSE, 0);
768 $log_frame->add ($vb2);
770 $cf->pack_start ($msgview_frame, FALSE, FALSE, 0);
771 $cf->pack_start ($log_frame, FALSE, FALSE, 0);
776 # the command line help
778 my $line = '-' x length ($xl::s{about_title}) . "\n";
780 print $xl::s{about_title} . "\n";
781 print $xl::s{about_version} . " $VERSION\n";
783 print _("Syntax:\n");
784 print _(" clawsker [options]\n");
785 print _("Options:\n");
786 print _(" --help Prints this help screen.\n");
787 print _(" --alternate-config-dir <dir> Uses <dir> as Claws Mail config dir.\n");
788 print _(" --clawsrc <file> Uses <file> as full resource name.\n");
791 # parse the command line
792 sub parse_command_line() {
794 while (defined($ARGV[$arg])) {
800 /--alternate-config-dir/ && do {
802 die "$xl::s{e_error}$xl::s{e_requireddir}\n"
803 unless defined($ARGV[$arg]);
804 die "$xl::s{e_error}$xl::s{e_notadir}\n"
805 unless -d $ARGV[$arg];
806 $CONFIGDIR = $ARGV[$arg];
807 $ALTCONFIGDIR = TRUE;
812 die "$xl::s{e_error}$xl::s{e_requiredfile}\n"
813 unless defined($ARGV[$arg]);
814 die "$xl::s{e_error}$xl::s{e_notafile}\n"
815 unless -f $ARGV[$arg];
816 &set_rc_filename ($ARGV[$arg]);
819 /.*/ && die $xl::s{e_error}
820 . _("unknown option '{opt}'.\n", opt => $ARGV[$arg]);
826 # update the hidden preferences status from loaded values
827 sub init_hidden_preferences() {
828 foreach my $hash (\%pr::beh, \%pr::col, \%pr::gui, \%pr::oth) {
829 foreach my $key (keys %$hash) {
830 $HPVALUE{${$hash}{$key}[NAME]} = $PREFS{${$hash}{$key}[NAME]};
835 # load current status from disc
836 sub load_preferences() {
837 my $rc = &get_rc_filename;
838 -f $rc or die "$xl::s{e_error}$xl::s{e_noclawsrc}\n";
839 &check_claws_not_running ();
843 if (/^([8a-z_]+)=(.*)$/) {
850 # save current preferences to disc
851 sub save_preferences() {
853 my $rc = &get_rc_filename;
854 -f $rc or die "$xl::s{e_error}$xl::s{e_noclawsrc}\n";
855 &check_claws_not_running ($parent) or return;
856 my $rcbak = "$rc.backup";
857 rename ($rc, $rcbak);
859 open (RCB, "<$rcbak");
862 if (/^([8a-z_]+)=(.*)$/) {
863 if (defined($HPVALUE{$1})) {
864 print RCF $1 . "=" . $HPVALUE{$1} . "\n";
880 my $nb = Gtk2::Notebook->new;
882 $nb->append_page (&new_behaviour_page, $xl::s{tab_behaviour});
883 $nb->append_page (&new_colours_page, $xl::s{tab_colours});
884 $nb->append_page (&new_gui_page, $xl::s{tab_gui});
885 $nb->append_page (&new_other_page, $xl::s{tab_other});
890 # create an about dialog
891 sub new_about_dialog() {
893 my $title = $xl::s{about_title};
894 my $lic = $xl::s{about_license};
895 my $vers = $xl::s{about_version} . " $VERSION";
897 "This program is free software: you can redistribute it and/or modify
898 it under the terms of the GNU General Public License as published by
899 the Free Software Foundation, either version 3 of the License, or
900 (at your option) any later version.
902 This program is distributed in the hope that it will be useful,
903 but WITHOUT ANY WARRANTY; without even the implied warranty of
904 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
905 GNU General Public License for more details.
907 You should have received a copy of the GNU General Public License
908 along with this program. If not, see <http://www.gnu.org/licenses/>.";
910 my $holder = "Ricardo Mones <ricardo\@mones.org>";
912 my $dialog = Gtk2::MessageDialog->new_with_markup ($parent,
913 [qw/modal destroy-with-parent/],
915 "<span size=\"x-large\" weight=\"bold\">$title</span>\n"
916 . "<span size=\"large\">$vers</span>\n"
917 . "<span>Copyright $year by $holder</span>\n\n"
918 . "<span size=\"large\">$lic</span>\n\n"
919 . "<span size=\"small\">$license</span>");
920 $dialog->set_title ($xl::s{about});
926 sub new_button_box() {
927 my ($parent, $adlg) = @_;
928 my $b_about = Gtk2::Button->new_from_stock ('gtk-about');
929 my $b_exit = Gtk2::Button->new_from_stock ('gtk-quit');
930 my $b_apply = Gtk2::Button->new_from_stock ('gtk-apply');
931 # disable button until is really implemented
932 # my $b_undo = Gtk2::Button->new_from_stock ('gtk-undo');
933 my $hbox = Gtk2::HBox->new (FALSE, 5);
935 $b_exit->signal_connect (clicked => sub { Gtk2->main_quit });
936 $b_apply->signal_connect (clicked => sub { &save_preferences ($parent) });
937 # $b_undo->signal_connect (clicked => sub { &undo_current_changes });
938 $b_about->signal_connect (clicked => sub { $adlg->run; $adlg->hide });
940 $hbox->pack_end ($b_exit, FALSE, FALSE, 0);
941 $hbox->pack_end ($b_apply, FALSE, FALSE, 0);
942 # $hbox->pack_end ($b_undo, FALSE, FALSE, 0);
943 $hbox->pack_start ($b_about, FALSE, FALSE, 0);
951 &init_hidden_preferences;
953 my $window = Gtk2::Window->new ('toplevel');
954 my $box = Gtk2::VBox->new (FALSE, 5);
955 $box->set_border_width(3);
956 my $about = &new_about_dialog;
957 $box->pack_start (&new_notebook, FALSE, FALSE, 0);
958 $box->pack_end (&new_button_box ($window, $about), FALSE, FALSE, 0);
959 $window->signal_connect (delete_event => sub { Gtk2->main_quit });
960 $window->set_title ($xl::s{win_title});