summaryrefslogtreecommitdiff
path: root/lib/gcstar/GCBorrowings.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gcstar/GCBorrowings.pm')
-rw-r--r--lib/gcstar/GCBorrowings.pm662
1 files changed, 662 insertions, 0 deletions
diff --git a/lib/gcstar/GCBorrowings.pm b/lib/gcstar/GCBorrowings.pm
new file mode 100644
index 0000000..d93c444
--- /dev/null
+++ b/lib/gcstar/GCBorrowings.pm
@@ -0,0 +1,662 @@
+package GCBorrowings;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use GCDialogs;
+use GCUtils;
+
+{
+ package GCImportBorrowersDialog;
+ use base 'GCModalDialog';
+
+ use XML::Simple;
+
+ sub importClaws
+ {
+ my ($self, $file) = @_;
+ my @result;
+ open XML, $file;
+ my $xmlString = do {local $/; <XML>};
+ close XML;
+ my $xs = XML::Simple->new;
+ my $addressBook = $xs->XMLin($xmlString,
+ ForceArray => ['address', 'person']
+ );
+ foreach (@{$addressBook->{person}})
+ {
+ push @result, [$_->{cn}, $_->{'address-list'}->{address}->[0]->{email}];
+ }
+ return \@result;
+ }
+
+ sub importLdif
+ {
+ my ($self, $file) = @_;
+ my @result;
+ open DATA, $file;
+ my %current;
+ while (<DATA>)
+ {
+ if (/^dn/)
+ {
+ push @result, [$current{name}, $current{email}] if %current;
+ %current = {};
+ }
+ $current{name} = $1 if (/^cn:\s*(.*)$/);
+ $current{email} = $1 if (/^mail:\s*(.*)$/);
+ }
+ close DATA;
+ push @result, [$current{name}, $current{email}] if %current;
+ return \@result;
+ }
+
+ sub importVcard
+ {
+ my ($self, $file) = @_;
+ my @result;
+ open DATA, $file;
+ my %current;
+ while (<DATA>)
+ {
+ push @result, [$current{name}, $current{email}] if /^END:VCARD/i;
+ $current{name} = $1 if (/^FN:(.*)$/i);
+ $current{email} = $1 if (/^EMAIL;INTERNET:(.*)$/);
+ }
+ close DATA;
+ return \@result;
+ }
+
+ sub show
+ {
+ my $self = shift;
+ $self->SUPER::show();
+ $self->show_all;
+ $self->set_position('center');
+ my $done = 0;
+ my $code;
+ while (!$done)
+ {
+ $code = $self->run;
+ if ($code ne 'ok')
+ {
+ $done = 1;
+ }
+ else
+ {
+ my $type = $self->{type}->getValue;
+ my $file = $self->{file}->getValue;
+ if (!$file)
+ {
+ my $dialog = Gtk2::MessageDialog->new($self,
+ [qw/modal destroy-with-parent/],
+ 'error',
+ 'ok',
+ $self->{parent}->{lang}->{ImportExportFileEmpty});
+
+ $dialog->set_position('center-on-parent');
+ $dialog->run();
+ $dialog->destroy;
+ next;
+ }
+ if ($type eq 'claws')
+ {
+ $self->{borrowers} = $self->importClaws($file);
+ }
+ elsif ($type eq 'ldif')
+ {
+ $self->{borrowers} = $self->importLdif($file);
+ }
+ elsif ($type eq 'vcard')
+ {
+ $self->{borrowers} = $self->importVcard($file);
+ }
+ $done = 1;
+ }
+ }
+ $self->hide;
+ return ($code eq 'ok');
+ }
+
+ sub getBorrowers
+ {
+ my $self = shift;
+ return $self->{borrowers};
+ }
+
+ sub new
+ {
+ my ($proto, $parent) = @_;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new($parent,
+ $parent->{lang}->{BorrowersImportTitle},
+ 'gtk-convert'
+ );
+ bless ($self, $class);
+ $self->{parent} = $parent;
+ $self->{lang} = $parent->{lang};
+
+ my $table = new Gtk2::Table(2,2,0);
+ $table->set_row_spacings($GCUtils::halfMargin);
+ $table->set_col_spacings($GCUtils::halfMargin);
+ $table->set_border_width($GCUtils::margin);
+
+ my $typeLabel = new GCLabel($parent->{lang}->{BorrowersImportType});
+ $self->{type} = new GCMenuList;
+ $self->{type}->setValues([
+ {value => 'ldif', displayed => 'LDIF'},
+ {value => 'claws', displayed => 'Claws Mail'},
+ {value => 'vcard', displayed => 'VCARD'},
+ ]);
+ my $fileLabel = new GCLabel($parent->{lang}->{BorrowersImportFile});
+ $self->{file} = new GCFile($self);
+
+ $table->attach($typeLabel, 0, 1, 0, 1, 'fill', 'fill', 0, 0);
+ $table->attach($self->{type}, 1, 2, 0, 1, ['expand', 'fill'], 'fill', 0, 0);
+ $table->attach($fileLabel, 0, 1, 1, 2, 'fill', 'fill', 0, 0);
+ $table->attach($self->{file}, 1, 2, 1, 2, ['expand', 'fill'], 'fill', 0, 0);
+
+ $self->vbox->pack_start($table, 1, 1, 0);
+
+ return $self;
+ }
+}
+
+{
+ package GCBorrowersDialog;
+ use base 'GCModalDialog';
+
+ sub initValues
+ {
+ use locale;
+
+ my $self = shift;
+ my $keepPrevious = shift;
+
+ my @borrowers;
+ my @emails;
+
+ if ($keepPrevious)
+ {
+ foreach my $line(@{$self->{people}->{data}})
+ {
+ push @borrowers, $line->[0];
+ push @emails, $line->[1];
+ }
+ }
+ else
+ {
+ @borrowers = split m/\|/, $self->{options}->borrowers;
+ @emails = split m/\|/, $self->{options}->emails;
+ }
+
+ @{$self->{people}->{data}} = ();
+ my %directory;
+
+ for (my $i = 0; $i < scalar(@borrowers); $i++)
+ {
+ $directory{$borrowers[$i]} = $emails[$i];
+ }
+
+ my @keys = sort keys %directory;
+ @keys = reverse @keys if $self->{reverse};
+ foreach (@keys)
+ {
+ my @infos = [$_, $directory{$_}];
+ push @{$self->{people}->{data}}, @infos;
+ }
+ $self->{people}->select(0);
+
+ (my $template = $self->{options}->template) =~ s|<br/>|\n|g;
+ $self->{mailTemplate}->setValue($template);
+
+ $self->{subject}->set_text($self->{options}->subject);
+ }
+
+ sub saveValues
+ {
+ my $self = shift;
+
+ my $borrowers = '';
+ my $emails = '';
+ foreach (@{$self->{people}->{data}})
+ {
+ $borrowers .= $_->[0].'|';
+ $emails .= $_->[1].'|';
+ }
+ $borrowers =~ s/.$//;
+ $emails =~ s/.$//;
+ $self->{options}->borrowers($borrowers);
+ $self->{options}->emails($emails);
+
+ (my $template = $self->{mailTemplate}->getValue) =~ s/\n/<br\/>/g;
+ $self->{options}->template($template);
+
+ $self->{options}->subject($self->{subject}->get_text);
+
+ $self->{options}->save;
+ }
+
+ sub show
+ {
+ my $self = shift;
+
+ $self->initValues;
+
+ $self->SUPER::show();
+ $self->show_all;
+
+ if ($self->run eq 'ok')
+ {
+ $self->saveValues;
+ }
+ $self->hide;
+ }
+
+ sub importBorrowers
+ {
+ my $self = shift;
+
+ $self->{importDialog} = new GCImportBorrowersDialog($self)
+ if ! $self->{importDialog};
+
+ if ($self->{importDialog}->show)
+ {
+ unshift @{$self->{people}->{data}}, @{$self->{importDialog}->getBorrowers};
+ }
+ }
+
+ sub removeCurrent
+ {
+ my $self = shift;
+ my @idx = $self->{people}->get_selected_indices;
+
+ if ($^O =~ /win32/i)
+ {
+ my @newData;
+ my $i = 0;
+ foreach (@{$self->{people}->{data}})
+ {
+ push @newData, [$_->[0], $_->[1]] if $i != $idx[0];
+ $i++;
+ }
+ @{$self->{people}->{data}} = @newData;
+ }
+ else
+ {
+ splice @{$self->{people}->{data}}, $idx[0], 1;
+ }
+ }
+
+ sub add
+ {
+ my $self = shift;
+
+ my $dialog = new Gtk2::Dialog($self->{parent}->{lang}->{BorrowersAdd},
+ $self,
+ [qw/modal destroy-with-parent/],
+ @GCDialogs::okCancelButtons
+ );
+
+ my $table = new Gtk2::Table(2,2,0);
+
+ my $labelName = new Gtk2::Label($self->{parent}->{lang}->{BorrowersName});
+ $table->attach($labelName, 0, 1, 0, 1, 'expand', 'fill', 5, 5);
+ my $name = new Gtk2::Entry;
+ $name->signal_connect('activate' => sub {$dialog->response('ok')});
+ $table->attach($name, 1, 2, 0, 1, 'expand', 'fill', 5, 5);
+
+ my $labelEmail = new Gtk2::Label($self->{parent}->{lang}->{BorrowersEmail});
+ $table->attach($labelEmail, 0, 1, 1, 2, 'expand', 'fill', 5, 5);
+ my $email = new Gtk2::Entry;
+ $email->signal_connect('activate' => sub {$dialog->response('ok')});
+ $table->attach($email, 1, 2, 1, 2, 'expand', 'fill', 5, 5);
+
+ $dialog->vbox->pack_start($table,1,1,0);
+ $dialog->vbox->show_all;
+
+ if ($dialog->run eq 'ok')
+ {
+ unshift @{$self->{people}->{data}}, [$name->get_text, $email->get_text];
+ }
+
+ $dialog->destroy;
+ }
+
+ sub new
+ {
+ my ($proto, $parent) = @_;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new($parent,
+ $parent->{lang}->{BorrowersTitle},
+ );
+
+ bless ($self, $class);
+
+ #$self->set_modal(1);
+ $self->set_position('center');
+ $self->set_default_size(400,400);
+
+ $self->{reverse} = 0;
+
+ $self->{parent} = $parent;
+ $self->{lang} = $parent->{lang};
+ $self->{options} = $parent->{options};
+
+ my $borrowersFrame = new GCGroup($self->{parent}->{lang}->{BorrowersList});
+ my $hbox = new Gtk2::HBox(0,0);
+
+ $self->{people} = new Gtk2::SimpleList($parent->{lang}->{BorrowersName} => "text",
+ $parent->{lang}->{BorrowersEmail} => "text");
+ $self->{people}->set_column_editable(1, 1);
+ $self->{people}->set_rules_hint(1);
+
+ $self->{people}->get_column(0)->set_sort_column_id(0);
+ $self->{people}->get_model->set_sort_column_id(0, 'ascending');
+
+ for my $i (0..1)
+ {
+ $self->{people}->get_column($i)->set_resizable(1);
+ }
+ $self->{order} = 1;
+ $self->{sort} = -1;
+
+ my $scrollPanelList = new Gtk2::ScrolledWindow;
+ $scrollPanelList->set_policy ('never', 'automatic');
+ $scrollPanelList->set_shadow_type('etched-in');
+ $scrollPanelList->set_border_width(0);
+ $scrollPanelList->add($self->{people});
+
+ my $vboxButtons = new Gtk2::VBox(0,0);
+ my $addButton = Gtk2::Button->new_from_stock('gtk-add');
+ $addButton->signal_connect('clicked' => sub {
+ $self->add;
+ });
+ my $removeButton = Gtk2::Button->new_from_stock('gtk-remove');
+ $removeButton->signal_connect('clicked' => sub {
+ $self->removeCurrent;
+ });
+
+ my $importButton = Gtk2::Button->new_from_stock('gtk-convert');
+ $importButton->signal_connect('clicked' => sub {
+ $self->importBorrowers;
+ });
+
+ #my $editButton = new Gtk2::Button($parent->{lang}->{BorrowersEdit});
+ $vboxButtons->pack_start($addButton,0,0,$GCUtils::halfMargin);
+ $vboxButtons->pack_start($removeButton,0,0,$GCUtils::halfMargin);
+ $vboxButtons->pack_start($importButton,0,0,$GCUtils::halfMargin);
+ #$vboxButtons->pack_start($editButton,0,0,0);
+
+ $hbox->pack_start($scrollPanelList,1,1,0);
+ $hbox->pack_start($vboxButtons,0,0,$GCUtils::margin);
+ $hbox->set_border_width(0);
+ $borrowersFrame->addWidget($hbox);
+ $self->vbox->pack_start($borrowersFrame,1,1,0);
+
+ my $templateFrame = new GCGroup($self->{parent}->{lang}->{BorrowersTemplate});
+ my $templateBox = new Gtk2::VBox(0,0);
+ $templateFrame->addWidget($templateBox);
+
+ $self->{mailTemplate} = new GCLongText;
+ $self->{mailTemplate}->set_size_request(-1,80);
+
+ my $hboxSubject = new Gtk2::HBox(0,0);
+ my $labelSubject = new Gtk2::Label($self->{parent}->{lang}->{BorrowersSubject});
+ $self->{subject} = new Gtk2::Entry;
+ $hboxSubject->pack_start($labelSubject,0,0,0);
+ $hboxSubject->pack_start($self->{subject},0,0,$GCUtils::halfMargin);
+
+
+# $templateBox->pack_start($labelTemplate,0,0,$GCUtils::halfMargin);
+ $templateBox->pack_start($hboxSubject,0,0,0);
+ $templateBox->pack_start($self->{mailTemplate},1,1,$GCUtils::halfMargin);
+
+ my $label1 = new Gtk2::Label($self->{parent}->{lang}->{BorrowersNotice1});
+ $label1->set_alignment(0,0);
+ my $label2 = new Gtk2::Label($self->{parent}->{lang}->{BorrowersNotice2});
+ $label2->set_alignment(0,0);
+ my $label3 = new Gtk2::Label($self->{parent}->{lang}->{BorrowersNotice3});
+ $label3->set_alignment(0,0);
+ $templateBox->pack_start($label1,0,0,0);
+ $templateBox->pack_start($label2,0,0,0);
+ $templateBox->pack_start($label3,0,0,0);
+
+ $self->vbox->pack_start($templateFrame, 1, 1, 0);
+
+ return $self;
+ }
+
+}
+
+{
+ package GCBorrowedDialog;
+ use base "Gtk2::Dialog";
+
+ sub setList
+ {
+ my ($self, $data, $model) = @_;
+
+ $self->setModel($model);
+ my $items = $data->getItemsListFiltered;
+ $self->{data} = $data;
+
+ $self->{itemsList} = [];
+ $self->{listModel}->clear;
+ my ($listId, $dataId) = (-1, -1);
+ foreach (@{$items})
+ {
+ $dataId++;
+ next if (!$_->{$self->{borrowerField}}) || ($_->{$self->{borrowerField}} eq 'none');
+ $listId++;
+ my $borrower = $_->{$self->{borrowerField}};
+ $borrower = $self->{parent}->{model}->getDisplayedText('PanelUnknown')
+ if $borrower eq 'unknown';
+ my $lendDate = GCUtils::timeToStr($_->{$self->{lendDateField}},
+ $self->{parent}->{options}->dateFormat);
+ push @{$self->{itemsList}}, {
+ $self->{titleField} => $_->{$self->{titleField}},
+ $self->{borrowerField} => $borrower,
+ $self->{lendDateField} => $_->{$self->{lendDateField}}
+ };
+ $self->{listModel}->set($self->{listModel}->append,
+ 0 => $_->{$self->{titleField}},
+ 1 => $borrower,
+ 2 => $lendDate,
+ 3 => $listId,
+ 4 => $dataId);
+ }
+
+ $self->{listView}->columns_autosize;
+ return if $listId == -1;
+ $self->{listView}->get_selection->select_iter($self->{listModel}->get_iter_first);
+ }
+
+ sub show
+ {
+ my $self = shift;
+
+ $self->SUPER::show();
+ $self->show_all;
+ $self->run;
+ $self->hide;
+ }
+
+ sub setModel
+ {
+ my ($self, $model) = @_;
+ $self->{titleField} = $model->{commonFields}->{title};
+ $self->{borrowerField} = $model->{commonFields}->{borrower}->{name};
+ $self->{lendDateField} = $model->{commonFields}->{borrower}->{date};
+ $self->{historyField} = $model->{commonFields}->{borrower}->{history};
+
+ $self->{titleColumn}->set_title($model->getDisplayedItems);
+ }
+
+ sub displayItem
+ {
+ my ($self, $idx) = @_;
+ $self->{data}->display($idx);
+ $self->{data}->select($idx);
+ }
+
+ sub returnItem
+ {
+ my $self = shift;
+ my $current = $self->{data}->getCurrent;
+ my $iter = $self->{listView}->get_selection->get_selected;
+ my $idx = $self->{listModel}->get($iter, 4);
+ $self->displayItem($idx);
+ if ($self->{data}->{panel}->itemBack)
+ {
+ $self->{listModel}->remove($iter);
+ }
+ $self->displayItem($current);
+ return;
+ }
+
+ sub showHistory
+ {
+ my $self = shift;
+ my $iter = $self->{listView}->get_selection->get_selected;
+ return if !$iter;
+ my $idx = $self->{listModel}->get($iter, 4);
+ $self->{history}->setValue(
+ $self->{data}->getValue($idx, $self->{historyField})
+ );
+ }
+
+ sub new
+ {
+ my ($proto, $parent) = @_;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new($parent->{lang}->{BorrowedTitle},
+ $parent,
+ [qw/modal destroy-with-parent/],
+ 'gtk-ok' => 'ok'
+ );
+
+ bless ($self, $class);
+
+ $self->{parent} = $parent;
+
+ $self->set_modal(1);
+ $self->set_position('center');
+ $self->set_default_size(400,400);
+
+ $self->{parent} = $parent;
+ $self->{options} = $parent->{options};
+
+ my $hbox = new Gtk2::HBox(0,0);
+
+ $self->{listModel} = new Gtk2::ListStore('Glib::String', 'Glib::String', 'Glib::String',
+ 'Glib::Int', 'Glib::Int');
+ $self->{listView} = Gtk2::TreeView->new_with_model($self->{listModel});
+ $self->{listView}->set_rules_hint(1);
+ $self->{listView}->set_headers_clickable(1);
+
+ my @columns;
+ push @columns, Gtk2::TreeViewColumn->new_with_attributes('',
+ Gtk2::CellRendererText->new,
+ 'text' => 0);
+ push @columns, Gtk2::TreeViewColumn->new_with_attributes($parent->{lang}->{PanelBorrower},
+ Gtk2::CellRendererText->new,
+ 'text' => 1);
+ push @columns, Gtk2::TreeViewColumn->new_with_attributes($parent->{lang}->{BorrowedDate},
+ Gtk2::CellRendererText->new,
+ 'text' => 2);
+ $self->{titleColumn} = $columns[0];
+ for my $i (0..2)
+ {
+ $columns[$i]->set_resizable(1);
+ $columns[$i]->set_sort_column_id($i);
+ $columns[$i]->set_reorderable(1);
+ $self->{listView}->append_column($columns[$i]);
+ }
+ $self->{listModel}->set_sort_func(2, sub {
+ my ($model, $a, $b) = @_;
+ my ($day, $month, $year) = split m/\//,
+ $self->{itemsList}->[$model->get($a, 3)]->{$self->{lendDateField}};
+ my $dateA = join "_", $year, $month, $day;
+ ($day, $month, $year) = split m/\//,
+ $self->{itemsList}->[$model->get($b, 3)]->{$self->{lendDateField}};
+ my $dateB = join "_", $year, $month, $day;
+ return $dateA cmp $dateB;
+
+ });
+
+ $self->{listView}->get_selection->signal_connect ('changed' => sub {
+ $self->showHistory;
+ });
+
+ my $scrollPanelList = new Gtk2::ScrolledWindow;
+ $scrollPanelList->set_policy ('never', 'automatic');
+ $scrollPanelList->set_shadow_type('etched-in');
+ $scrollPanelList->set_border_width($GCUtils::margin);
+ $scrollPanelList->add($self->{listView});
+
+ $self->{context} = new Gtk2::Menu;
+ $self->{returned} = Gtk2::MenuItem->new($parent->{lang}->{PanelReturned});
+ $self->{returned}->signal_connect('activate', sub {
+ $self->returnItem;
+ });
+ $self->{context}->append($self->{returned});
+ $self->{display} = Gtk2::MenuItem->new($parent->{lang}->{BorrowedDisplayInPanel});
+ $self->{display}->signal_connect('activate', sub {
+ my $iter = $self->{listView}->get_selection->get_selected;
+ my $idx = $self->{listModel}->get($iter, 4);
+ $self->displayItem($idx);
+ });
+ $self->{context}->append($self->{display});
+ $self->{context}->show_all;
+
+ $self->{listView}->signal_connect('button_press_event' => sub {
+ my ($widget, $event) = @_;
+ return 0 if $event->button ne 3;
+ $self->{context}->popup(undef, undef, undef, undef, $event->button, $event->time);
+ return 0;
+ });
+
+ my $historyExpander = new GCExpander($parent->{lang}->{PanelHistory});
+ $historyExpander->setValue($parent->{lang}->{PanelHistory});
+
+ my @labels = ($parent->{lang}->{PanelBorrower},
+ $parent->{lang}->{PanelLendDate},
+ $parent->{lang}->{PanelReturnDate});
+ $self->{history} = new GCMultipleList($self, 3, \@labels, 0, 2);
+
+ my $historyBox = new Gtk2::VBox(0,0);
+ $historyBox->set_border_width($GCUtils::margin);
+ $historyBox->pack_start($self->{history}, 1, 1, 0);
+
+ $historyExpander->add($historyBox);
+ $historyExpander->show_all;
+
+ $self->vbox->pack_start($scrollPanelList,1,1,0);
+ $self->vbox->pack_start($historyExpander,0,0, $GCUtils::halfMargin);
+
+ return $self;
+ }
+}
+
+1;