#!/usr/bin/perl -w
#
# Clawsker :: A Claws Mail Tweaker
-# Copyright 2007-2017 Ricardo Mones <ricardo@mones.org>
+# Copyright 2007-2018 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
about_license => _('License:'),
about_version => _('Version:'),
+ exit_title => _('Clawsker warning'),
+ exit_fact => _('There are unapplied modifications.'),
+ exit_question => _('Do you really want to quit?'),
+
tab_colours => _('Colours'),
tab_behaviour => _('Behaviour'),
tab_gui => _('GUI'),
my $SELHOTKEY;
# loaded icons
my @APPICONS = ();
+# modification flag
+my $MODIFIED = 0;
# index constants for preference arrays
use constant NAME => 0; # the name on the rc file
use constant FRAME_SPC => 2;
use constant PAGE_SPC => 5;
+# for data references indexing
+use constant VALUE => 0;
+use constant IVALUE => 1;
+
# version functions
sub version_greater_or_equal {
sub handle_bool_value {
my ($widget, $event, $dataref) = @_;
- $$dataref = ($widget->get_active ())? '1': '0';
+ $$dataref->[VALUE] = ($widget->get_active ())? '1': '0';
+ $MODIFIED += $$dataref->[VALUE] != $$dataref->[IVALUE]? 1: -1
+ if $$dataref->[IVALUE];
}
sub handle_int_value {
s/^\s+//;
s/\s+$//;
if (/^[0-9]+$/) {
- $$dataref = $_;
+ $$dataref->[VALUE] = $_;
$widget->set_text ($_);
}
else {
- $widget->set_text ($$dataref);
+ $widget->set_text ($$dataref->[VALUE]);
}
+ $MODIFIED += $$dataref->[VALUE] != $$dataref->[IVALUE]? 1: -1
+ if $$dataref->[IVALUE];
}
sub handle_string_value {
my ($widget, $event, $dataref) = @_;
- $$dataref = $widget->get_text ();
+ $$dataref->[VALUE] = $widget->get_text ();
+ $MODIFIED += $$dataref->[VALUE] ne $$dataref->[IVALUE]? 1: -1
+ if $$dataref->[IVALUE];
}
sub handle_nchar_value {
my ($widget, $event, $dataref, $minlen, $maxlen) = @_;
$_ = substr ($widget->get_text (), 0, $maxlen);
$widget->set_text ($_);
- $$dataref = $_;
+ $$dataref->[VALUE] = $_;
+ $MODIFIED += $$dataref->[VALUE] ne $$dataref->[IVALUE]? 1: -1
+ if $$dataref->[IVALUE];
}
sub gdk_color_from_str {
sub handle_color_value {
my ($widget, $event, $dataref) = @_;
my $newcol = $widget->get_color;
- $$dataref = str_from_gdk_color ($newcol);
+ $$dataref->[VALUE] = str_from_gdk_color ($newcol);
+ $MODIFIED += $$dataref->[VALUE] ne $$dataref->[IVALUE]? 1: -1
+ if $$dataref->[IVALUE];
}
sub handle_selection_value {
my ($widget, $event, $dataref) = @_;
- $$dataref = $widget->get_active;
+ $$dataref->[VALUE] = $widget->get_active;
+ $MODIFIED += $$dataref->[VALUE] ne $$dataref->[IVALUE]? 1: -1
+ if $$dataref->[IVALUE];
}
sub get_rc_filename {
my $label = $$hash{$key}[LABEL];
#
my $cb = Gtk2::CheckButton->new ($label);
- my $value = $$vhash{$name};
+ my $value = $$vhash{$name}[VALUE];
$value //= $$hash{$key}[CMDEF];
$cb->set_active ($value eq '1');
$cb->signal_connect (clicked => sub {
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);
- my $value = $$vhash{$name};
+ my $value = $$vhash{$name}[VALUE];
$value //= $$hash{$key}[CMDEF];
$gentry->set_numeric (TRUE);
$gentry->set_value ($value);
my $width = $type[3];
$width //= $type[2];
$gentry->set_width_chars(int ($width) + 2) if defined ($width);
- my $value = $$vhash{$name};
+ my $value = $$vhash{$name}[VALUE];
$value //= $$hash{$key}[CMDEF];
$gentry->set_text ($value);
$gentry->signal_connect('key-release-event' => sub {
my $name = $$hash{$key}[NAME];
my $label = $$hash{$key}[LABEL];
#
- my $value = $$vhash{$name};
+ my $value = $$vhash{$name}[VALUE];
$value //= $$hash{$key}[CMDEF];
my $col = gdk_color_from_str ($value);
my $glabel = Gtk2::Label->new ($label);
my ($w, $e) = @_;
handle_selection_value ($w, $e, \$$vhash{$name});
});
- my $value = $$vhash{$name};
+ my $value = $$vhash{$name}[VALUE];
$value //= $$hash{$key}[CMDEF];
$combo->set_active ($value);
set_widget_hint ($combo, $$hash{$key}[DESC]);
my $renderer = Gtk2::CellRendererText->new ();
$renderer->set_property('alignment' => 'left');
$renderer->set_property('editable' => FALSE);
- $renderer->set_property('size-points' => 8);
- $renderer->set_property('size-set' => TRUE);
return $renderer;
}
sub {
my ($col, $renderer, $model, $iter, $data) = @_;
$renderer->set_property (
- 'text' => $model->get_value ($iter, C_LABEL));
+ 'markup' => '<span size="smaller">'
+ . $model->get_value ($iter, C_LABEL)
+ . '</span>');
$renderer->set_property (
'background' => $model->get_value ($iter, C_BCOLOR));
}
sub init_hidden_preferences {
foreach my $hash (\%pr::beh, \%pr::col, \%pr::gui, \%pr::oth, \%pr::win) {
foreach my $key (keys %$hash) {
- $HPVALUE{${$hash}{$key}[NAME]} = $PREFS{${$hash}{$key}[NAME]};
+ $HPVALUE{${$hash}{$key}[NAME]}[VALUE] = $PREFS{${$hash}{$key}[NAME]};
+ $HPVALUE{${$hash}{$key}[NAME]}[IVALUE] = $PREFS{${$hash}{$key}[NAME]};
}
}
foreach my $akey (keys %ACPREFS) {
foreach my $key (keys %pr::acc) {
my $pname = $pr::acc{$key}[NAME];
- $ACHPVALUE{$akey}{$pname} = $ACPREFS{$akey}{$pname};
+ $ACHPVALUE{$akey}{$pname}[VALUE] = $ACPREFS{$akey}{$pname};
+ $ACHPVALUE{$akey}{$pname}[IVALUE] = $ACPREFS{$akey}{$pname};
}
}
foreach my $key (keys %pr::plu) {
my $plugin = $pr::plu{$key}[PLUGIN];
my $pname = $pr::plu{$key}[NAME];
if (defined $PLPREFS{$plugin}) {
- $PLHPVALUE{$plugin}{$pname} = $PLPREFS{$plugin}{$pname};
+ $PLHPVALUE{$plugin}{$pname}[VALUE] = $PLPREFS{$plugin}{$pname};
+ $PLHPVALUE{$plugin}{$pname}[IVALUE] = $PLPREFS{$plugin}{$pname};
}
}
return TRUE;
close (RCF);
}
+sub backup_resource {
+ my $rc = shift;
+ my $rcbak = "$rc.backup";
+ do {
+ my $emsg = _("Unable to create backup file '{name}'\n", name => $rcbak);
+ log_message ($emsg);
+ error_dialog ($emsg);
+ return FALSE;
+ } unless rename ($rc, $rcbak);
+ return TRUE;
+}
+
# specific loaders
sub load_menurc {
my $rc = shift;
}
# save current preferences to disc
-sub save_preferences {
+sub save_rc_preferences {
my $rc = get_rc_filename ();
log_message ("Saving preferences to $rc\n");
return FALSE unless check_rc_file ($rc);
return FALSE unless check_claws_not_running ();
- my $rcbak = "$rc.backup";
- rename ($rc, $rcbak);
+ return FALSE unless backup_resource ($rc);
foreach (keys %PREFS) {
if (defined $HPVALUE{$_}) {
- $CONFIGDATA->{'Common'}{$_} = $HPVALUE{$_};
+ $CONFIGDATA->{'Common'}{$_} = $HPVALUE{$_}[VALUE];
}
}
foreach my $plugin (@AVPLUGINS) {
foreach (keys %{$CONFIGDATA->{$plugin}}) {
if (defined $PLHPVALUE{$plugin}{$_}) {
- $CONFIGDATA->{$plugin}{$_} = $PLHPVALUE{$plugin}{$_};
+ $CONFIGDATA->{$plugin}{$_} = $PLHPVALUE{$plugin}{$_}[VALUE];
}
}
}
log_message ("Saving account preferences to $rc\n");
return FALSE unless check_rc_file ($rc);
return FALSE unless check_claws_not_running ();
- my $rcbak = "$rc.backup";
- rename ($rc, $rcbak);
+ return FALSE unless backup_resource ($rc);
foreach my $asect (keys %$ACCOUNTDATA) {
if ($asect =~ /^Account: (\d+)$/) {
foreach (keys %{$ACCOUNTDATA->{$asect}}) {
if (defined $ACHPVALUE{$1}{$_}) {
- $ACCOUNTDATA->{$asect}{$_} = $ACHPVALUE{$1}{$_};
+ $ACCOUNTDATA->{$asect}{$_} = $ACHPVALUE{$1}{$_}[VALUE];
}
}
}
log_message ("Saving hotkey preferences to $rc\n");
return FALSE unless check_rc_file ($rc);
return FALSE unless check_claws_not_running ();
+ return FALSE unless backup_resource ($rc);
save_menurc ($rc, $HOTKEYS);
return TRUE;
}
+sub save_preferences {
+ my $result = save_rc_preferences ()
+ and save_ac_preferences ()
+ and save_hk_preferences ();
+ $MODIFIED = 0 if $result;
+ return $result;
+}
+
# create notebook
sub new_notebook {
my $nb = Gtk2::Notebook->new;
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.";
- my $year = "2007-2017";
+ my $year = "2007-2018";
my $holder = "Ricardo Mones <ricardo\@mones.org>";
my $url = "http://www.claws-mail.org/clawsker.php";
return $dialog;
}
+sub exit_handler {
+ my ($parent) = @_;
+ if ($MODIFIED != 0 and not $READONLY) {
+ my $fact = $xl::s{exit_fact};
+ my $question = $xl::s{exit_question};
+ my $dialog = Gtk2::MessageDialog->new_with_markup ($parent,
+ [qw/modal destroy-with-parent/],
+ 'warning', 'yes-no',
+ "<span>$fact</span>\n\n"
+ . "<span weight=\"bold\">$question</span>");
+ $dialog->set_title ($xl::s{exit_title});
+ my $resp = $dialog->run;
+ $dialog->hide;
+ return TRUE if ($resp eq 'no');
+ }
+ Gtk2->main_quit;
+}
+
# create buttons box
sub new_button_box {
my ($parent, $adlg) = @_;
# my $b_undo = Gtk2::Button->new_from_stock ('gtk-undo');
my $hbox = Gtk2::HBox->new (FALSE, 5);
# signal handlers
- $b_exit->signal_connect (clicked => sub { Gtk2->main_quit });
+ $b_exit->signal_connect (clicked => sub { exit_handler($parent) });
$b_apply->set_sensitive (not $READONLY);
- $b_apply->signal_connect (clicked => sub {
- save_preferences ($parent);
- save_ac_preferences ($parent);
- save_hk_preferences ($parent);
- });
+ $b_apply->signal_connect (clicked => sub { save_preferences($parent) });
# $b_undo->signal_connect (clicked => sub { undo_current_changes });
$b_about->signal_connect (clicked => sub { $adlg->run; $adlg->hide });
# package them
return @APPICONS;
}
+sub escape_key_handler {
+ my ($widget, $event) = @_;
+ if ($event->keyval == Gtk2::Gdk->keyval_from_name('Escape')) {
+ exit_handler($widget);
+ }
+}
+
# initialise
exit unless parse_command_line ();
Gtk2->init;
my $about = new_about_dialog ();
$box->pack_start (new_notebook (), TRUE, TRUE, 0);
$box->pack_end (new_button_box ($main_window, $about), FALSE, FALSE, 0);
-$main_window->signal_connect (delete_event => sub { Gtk2->main_quit });
+$main_window->signal_connect (delete_event => sub { exit_handler($main_window) });
+$main_window->signal_connect (key_press_event => \&escape_key_handler);
$main_window->set_title ($xl::s{win_title});
$main_window->set_icon_list (get_app_icons ());
$main_window->add ($box);