5 Email-Reminder-Editor - edit special occasion reminders
9 Simple editor for modifying special occasion email reminders.
13 Email-reminder allows users to define events that they want to be
14 reminded of by email. Possible events include birthdays,
15 anniversaries and yearly events. Reminders can be sent on the day of
16 the event and a few days beforehand.
18 This is a simple editor that allows users to add/modify their
19 reminders. It saves changes automatically when the program is closed.
27 Displays basic usage message.
31 Does not actually save any changes.
35 Prints out information about what the program is doing.
39 Displays the version number.
49 Francois Marier <francois@fmarier.org>
53 collect-reminders, send-reminders
57 Copyright (C) 2004-2014 by Francois Marier
59 Email-Reminder is free software; you can redistribute it and/or
60 modify it under the terms of the GNU General Public License as
61 published by the Free Software Foundation; either version 3 of the
62 License, or (at your option) any later version.
64 Email-Reminder is distributed in the hope that it will be useful,
65 but WITHOUT ANY WARRANTY; without even the implied warranty of
66 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
67 General Public License for more details.
69 You should have received a copy of the GNU General Public License
70 along with Email-Reminder; if not, write to the Free Software
71 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
86 use constant TRUE
=> 1;
87 use constant FALSE
=> 0;
89 use EmailReminder
::Event
;
90 use EmailReminder
::EventList
;
92 # Command-line parameters
98 GetOptions
("verbose" => \
$verbose,
100 "simulate" => \
$simulate,
101 "version" => \
$version,
106 my $ANNIVERSARY_TAB = 'Anniversaries';
107 my $BIRTHDAY_TAB = 'Birthdays';
108 my $MONTHLY_TAB = 'Monthly Events';
109 my $WEEKLY_TAB = 'Weekly Events';
110 my $YEARLY_TAB = 'Yearly Events';
112 my $EMAIL_PREF_LABEL = 'Email:';
113 my $NAME_PREF_LABEL = 'Name:';
115 my $NEW_EVENT_NAME = '<new event>';
116 my $WINDOW_TITLE = 'Email-Reminder Editor';
118 my $DEFAULT_WIDTH = 600;
119 my $DEFAULT_HEIGHT = 400;
121 my $SEND_REMINDERS_EXECUTABLE = '/usr/bin/send-reminders';
130 $events = EmailReminder
::EventList
->new(glob("~/" . $EmailReminder::Utils
::USER_CONFIG_FILE
), TRUE
);
131 print "Events loaded.\n" if $verbose;
137 $events->save($verbose) unless $simulate;
138 print "Events saved.\n" if $verbose;
144 my ($cell_renderer, $text_path, $new_text, $model) = @_;
145 my $path = Gtk2
::TreePath
->new_from_string($text_path);
146 $model->set_value($path, $cell_renderer->{column
}, $new_text);
158 my @columns = ('ID', @_);
160 # TODO: make listbox sortable by clicking on column headers
161 my $model = $events->get_model($type);
162 #my $sort_model = Gtk2::TreeModelSort->new_with_model($model);
163 #$sort_model->set_default_sort_func(\&_sort_by_column);
164 #$sort_model->set_sort_column_id(1, 'ascending');
165 my $list = Gtk2
::TreeView
->new($model);
166 $list->{type
} = $type;
169 foreach my $title (@columns) {
170 my $renderer = Gtk2
::CellRendererText
->new();
171 $renderer->set(editable
=> TRUE
);
172 $renderer->{column
} = $col_num;
173 $renderer->signal_connect (edited
=> \
&text_cell_edited
, $model);
175 my $col = Gtk2
::TreeViewColumn
->new_with_attributes($title, $renderer, 'text' => $col_num);
176 $col->set_resizable(TRUE
);
177 #$col->set_clickable(FALSE);
178 #$col->set_sort_column_id($col_num);
179 $list->append_column($col);
184 $list->get_column(0)->set_visible(FALSE
) unless $debug; # hide the ID column
186 my $scrolled = Gtk2
::ScrolledWindow
->new;
187 $scrolled->set_policy('automatic', 'automatic');
188 $scrolled->add($list);
197 item_type
=> '<Branch>',
199 '_Test configuration' => {
200 callback
=> \
&test_callback
,
201 callback_action
=> 0,
204 item_type
=> '<Separator>',
207 item_type
=> '<StockItem>',
208 callback
=> \
&window_close
,
209 extra_data
=> 'gtk-quit',
214 item_type
=> '<Branch>',
217 item_type
=> '<StockItem>',
218 extra_data
=> 'gtk-new',
219 callback
=> \
&new_callback
,
222 item_type
=> '<StockItem>',
223 extra_data
=> 'gtk-delete',
224 accelerator
=> '<ctrl>D',
225 callback
=> \
&delete_callback
,
227 '_Edit reminders' => {
228 callback
=> \
&edit_callback
,
231 item_type
=> '<Separator>',
233 '_Preferences...' => {
234 item_type
=> '<StockItem>',
235 extra_data
=> 'gtk-preferences',
236 callback
=> \
&prefs_callback
,
242 return Gtk2
::SimpleMenu
->new(menu_tree
=> $menu_tree);
247 unless (-x
$SEND_REMINDERS_EXECUTABLE) {
248 my $error = Gtk2
::MessageDialog
->new($window, ['modal'], 'error', 'ok', "Cannot run '$SEND_REMINDERS_EXECUTABLE'. Check your installation.");
255 my $errorOutput = `$SEND_REMINDERS_EXECUTABLE`;
257 my $error = Gtk2
::MessageDialog
->new($window, ['modal'], 'error', 'ok', $errorOutput);
267 my (undef, $listbox) = get_selected_index
();
269 my $event_type = $listbox->{type
};
270 $events->add_event($event_type);
272 my $event_index = $listbox->get_model()->get_nb_events() - 1;
273 $listbox->get_selection()->select_path(Gtk2
::TreePath
->new_from_string($event_index));
279 my ($path, $listbox) = get_selected_index
();
280 return unless defined($path);
282 $listbox->get_model()->delete_event($path);
288 my $selected = get_selected_event
();
289 return unless defined($selected);
291 my $dialog = create_reminder_dialog
($selected);
298 my $dialog = create_prefs_dialog
();
304 sub create_reminder_dialog
308 my $name = $event->get_name();
309 my $reminders = $event->get_reminders();
311 my $dialog = Gtk2
::Dialog
->new_with_buttons('Edit reminders', $window,
312 'destroy-with-parent',
313 'gtk-close' => 'close' );
315 my $reminder_label = Gtk2
::Label
->new("Current reminders for '$name':");
316 my $cb_sameday = Gtk2
::CheckButton
->new("Same day");
317 my $cb_advance = Gtk2
::CheckButton
->new("Days in advance:");
318 my $adj = Gtk2
::Adjustment
->new(1.0, 1.0, 364, 1.0, 10.0, 0.0);
319 my $spin_days = Gtk2
::SpinButton
->new($adj, 0, 0);
321 # Disable spin button unless the option is checked
322 $spin_days->set_sensitive(FALSE
);
323 $cb_advance->signal_connect(toggled
=> sub {
324 $spin_days->set_sensitive($cb_advance->get_active());
327 my $hbox = Gtk2
::HBox
->new();
328 $hbox->add($cb_advance);
329 $hbox->add($spin_days);
331 my $checkboxes = Gtk2
::VBox
->new(FALSE
, 6);
332 $checkboxes->set_border_width(6);
333 $checkboxes->add($reminder_label);
334 $checkboxes->add($cb_sameday);
335 $checkboxes->add($hbox);
337 foreach my $reminder (@
$reminders)
341 $cb_sameday->set_active(TRUE
);
343 elsif ($reminder > 0)
345 $cb_advance->set_active(TRUE
);
346 $spin_days->set_value($reminder);
350 $checkboxes->show_all;
351 $dialog->vbox->add($checkboxes);
353 $dialog->signal_connect(response
=> sub {
354 # Update values inside EventList
355 my @new_reminders = ();
356 push(@new_reminders, 0) if $cb_sameday->get_active();
357 push(@new_reminders, $spin_days->get_value())
358 if $cb_advance->get_active();
359 $event->set_reminders(\
@new_reminders);
367 sub create_prefs_dialog
369 my $dialog = Gtk2
::Dialog
->new_with_buttons('Preferences', $window,
371 'gtk-close' => 'close' );
373 my $info_label = Gtk2
::Label
->new("Set the default recipient for the reminder emails:");
374 my $name_label = Gtk2
::Label
->new($NAME_PREF_LABEL);
375 my $email_label = Gtk2
::Label
->new($EMAIL_PREF_LABEL);
377 my $fname = Gtk2
::Entry
->new();
378 my $lname = Gtk2
::Entry
->new();
379 my $email = Gtk2
::Entry
->new();
380 my @fullname = $events->get_user_name();
381 $fname->set_text($fullname[0]);
382 $lname->set_text($fullname[1]);
383 $email->set_text($events->get_user_email());
385 my $name = Gtk2
::HBox
->new();
386 $name->pack_start($fname, TRUE
, TRUE
, 0);
387 $name->pack_start($lname, TRUE
, TRUE
, 0);
389 my $options = Gtk2
::Table
->new(3, 2, FALSE
);
390 $options->set_row_spacings(3);
391 $options->attach_defaults($name_label, 0, 1, 0, 1);
392 $options->attach_defaults($name, 1, 2, 0, 1);
393 $options->attach_defaults($email_label, 0, 1, 1, 2);
394 $options->attach_defaults($email, 1, 2, 1, 2);
396 $options->show_all();
398 $dialog->vbox->set_spacing(6);
399 $dialog->vbox->add($info_label);
400 $dialog->vbox->add($options);
402 $dialog->signal_connect(response
=> sub {
404 $events->set_user_fname($fname->get_text());
405 $events->set_user_lname($lname->get_text());
406 unless ($events->set_user_email($email->get_text())) {
407 my $warning = Gtk2
::MessageDialog
->new($dialog, ['modal'], 'warning', 'ok', "The email address you entered is invalid; it has not been changed.");
418 unless ($events->get_user_email())
420 my $warning = Gtk2
::MessageDialog
->new($window, ['modal'], 'warning', 'none', "You will not receive any reminders since you have not set your email address. \n\nWould you like to set your email address in the preferences now or quit?");
421 $warning->add_buttons('gtk-preferences' => 'no', 'gtk-quit' => 'yes');
423 my $response = $warning->run();
426 if ('no' eq $response)
439 $window = Gtk2
::Window
->new;
440 $window->set_title($WINDOW_TITLE);
441 $window->set_default_size($DEFAULT_WIDTH, $DEFAULT_HEIGHT);
442 $window->set_resizable(TRUE
);
444 $window->signal_connect(destroy
=> sub { Gtk2
->main_quit; });
445 $window->signal_connect(delete_event
=> \
&window_close
);
447 my $vbox = Gtk2
::VBox
->new(FALSE
, 0);
451 my $menu = create_menu
();
452 $window->add_accel_group($menu->{accel_group
});
453 $vbox->pack_start($menu->{widget
}, FALSE
, FALSE
, 0);
456 my $toolbar = Gtk2
::Toolbar
->new() ;
457 $toolbar->set_style('both-horiz');
458 $toolbar->insert_stock('gtk-new', "Add a new event", undef, \
&new_callback
, undef, -1);
459 $toolbar->insert_stock('gtk-delete', "Delete the selected event", undef, \
&delete_callback
, undef, -1);
460 $toolbar->append_space();
461 $toolbar->insert_item("Edit reminders", "Edit reminders for the selected event", undef, undef, \
&edit_callback
, undef, -1);
462 $vbox->pack_start($toolbar, FALSE
, FALSE
, 0);
465 # TODO: make the accel Ctrl+PageDown/Up work everywhere
466 # (not just when focus is on the tabs)
467 $notebook = Gtk2
::Notebook
->new();
468 $notebook->set_tab_pos('top');
469 $vbox->pack_start($notebook, TRUE
, TRUE
, 0);
472 my $listbox1 = create_listbox
("birthday", 'Name', 'Birth date', 'Email');
473 my $listbox2 = create_listbox
("anniversary", 'Person 1', 'Wedding date', 'Email 1', 'Person 2', 'Email 2');
474 my $listbox3 = create_listbox
("yearly", 'Event name', 'Event date');
475 my $listbox4 = create_listbox
("monthly", 'Event name', 'Event day');
476 my $listbox5 = create_listbox
("weekly", 'Event name', 'Event day');
477 $notebook->append_page($listbox1, $BIRTHDAY_TAB);
478 $notebook->append_page($listbox2, $ANNIVERSARY_TAB);
479 $notebook->append_page($listbox3, $YEARLY_TAB);
480 $notebook->append_page($listbox4, $MONTHLY_TAB);
481 $notebook->append_page($listbox5, $WEEKLY_TAB);
486 sub get_selected_index
488 my $scrolled = $notebook->get_nth_page($notebook->get_current_page());
489 my $listbox = $scrolled->get_child();
491 my $path = $listbox->get_selection()->get_selected_rows();
492 return ($path, $listbox);
495 sub get_selected_event
497 my ($path, $listbox) = get_selected_index
();
498 return unless defined($path);
500 my $event = $listbox->get_model()->get_event($path);
513 print "Version: $EmailReminder::Utils::VERSION\n" if $verbose;
521 if ($help || $version) {
522 print "$WINDOW_TITLE $EmailReminder::Utils::VERSION\n";