package GCImport::GCImportList; ################################################### # # 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 GCImport::GCImportBase; { package GCScannerDialog; use base 'GCModalDialog'; use XML::Simple; sub new { my ($proto, $parent, $lang, $model, $serverSocket) = @_; my $class = ref($proto) || $proto; my $self = $class->SUPER::new($parent, $lang->{Waiting}); bless($self, $class); $self->{lang} = $lang; $self->{model} = $model; $self->{accepted} = 0; if ($serverSocket) { $self->{network} = 1; $self->{serverSocket} = $serverSocket; } my $table = new Gtk2::Table(2, 2); $table->set_row_spacings($GCUtils::halfMargin); $table->set_col_spacings($GCUtils::margin); $table->set_border_width($GCUtils::margin); $self->{previousLabel} = new GCLabel(''); $self->{promptLabel} = new GCLabel($lang->{ScanPrompt}); $table->attach($self->{previousLabel}, 0, 1, 0, 1, 'fill', 'fill', 0, 0); $table->attach($self->{promptLabel}, 0, 1, 1, 2, 'fill', 'fill', 0, 0); my $eanLabel = new GCLabel($lang->{EAN}); $self->{ean} = new GCShortText; $self->{ean}->signal_connect('activate' => sub {$self->response('ok')} ); if (!$self->{network}) { $table->attach($eanLabel, 0, 1, 2, 3, 'fill', 'fill', 0, 0); $table->attach($self->{ean}, 1, 2, 2, 3, ['fill', 'expand'], 'fill', 0, 0); } $self->vbox->pack_start($table, 1, 1, 0); $table->show_all; $self->setCancelLabel($lang->{Terminate}); $self->action_area->remove(($self->action_area->get_children)[$self->{okPosition}]); return $self; } sub setPrevious { my ($self, $previous) = @_; if (!$self->{first}) { $self->{first} = 1; return; } my $label; if ($previous) { ($label = $self->{lang}->{Previous}) =~ s|%s|$previous|; } else { my $previous = $self->{previousCode}; ($label = $self->{lang}->{NothingFound}) =~ s|%s|$previous|; } $self->{previousLabel}->set_markup($label); $self->{promptLabel}->set_label($self->{lang}->{ScanOtherPrompt}); } sub readSocket { my ($self) = @_; Glib::Source->remove($self->{socketWatch}); my $socket = $self->{socket}; my $line = <$socket>; $self->response('cancel') if !$line; my $xs = XML::Simple->new; my $scan = $xs->XMLin($line); my $code = $scan->{scan}->{content}; $code = $self->eanToIsbn($code) if $self->{model} eq 'GCbooks'; $self->{ean}->setValue($code); $self->{previousCode} = $code; $self->response('ok'); } sub waitForCode { my $self = shift; $self->{socketWatch} = Glib::IO->add_watch($self->{socket}->fileno, 'in', sub { $self->readSocket; }); } sub eanToIsbn { my ($self, $code) = @_; return $code if $code !~ /978(\d{9})/; my $sub = $1; my $multiplier = 1; my $checkSum = 0; foreach (split(//, $sub)) { $checkSum += $_ * $multiplier++; } $checkSum %= 11; $checkSum = 'X' if $checkSum == 10; return $sub.$checkSum; } sub show { my $self = shift; $self->SUPER::show(); $self->show_all; $self->showMe; if ($self->{network}) { if (!$self->{accepted}) { $self->{serverWatch} = Glib::IO->add_watch($self->{serverSocket}->fileno, 'in', sub { $self->{socket} = $self->{serverSocket}->accept; $self->{accepted} = 1; $self->waitForCode; }); } else { $self->waitForCode; } } else { $self->{ean}->setValue(''); $self->{ean}->grab_focus; } my $code = $self->run; $self->hide; return $self->{ean}->getValue if $code eq 'ok'; $self->{socket}->close; return undef; } } { package GCImport::GCImporterScanner; use base qw(GCImport::GCImportBaseClass); use IO::Socket; use GCPlugins; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = $class->SUPER::new(); bless ($self, $class); return $self; } sub wantsFieldsSelection { return 0; } sub wantsFileSelection { return 0; } sub hideFileSelection { return 1; } sub getFilePatterns { return (); } sub checkPortField { my ($self, $data) = @_; my ($parent, $list) = @{$data}; my $model = $list->getValue ; $parent->{options}->{port}->set_sensitive($model eq 'Network'); } sub getOptions { my $self = shift; my $pluginsList = ''; foreach (@{$self->{model}->getPluginsNames}) { my $plugin = $GCPlugins::pluginsMap{$self->{model}->getName}->{$_}; $pluginsList .= $plugin->getName . ',' if $plugin->getEanField; } return [ { name => 'type', type => 'options', label => 'Type', valuesList => 'Local,Network', default => 'Local', changedCallback => sub {shift; $self->checkPortField(@_)}, }, { name => 'port', type => 'number', label => 'Port', default => 50007, min => 1024, max => 65536, }, { name => 'plugin', type => 'options', label => 'Plugin', valuesList => $pluginsList }, { name => 'first', type => 'yesno', label => 'UseFirst', default => '1' }, ]; } sub getModelName { my $self = shift; return $self->{model}->getName; } sub getBarCode { my ($self, $previous) = @_; #my $dialog = new $self->{dialog}->setPrevious($previous); return $self->{dialog}->show; } sub getItemsArray { my ($self, $file) = @_; my @result; #First we try to get the correct plugin my $plugin = $GCPlugins::pluginsMap{$self->{model}->getName}->{$self->{options}->{plugin}}; $plugin->{bigPics} = $self->{options}->{parent}->{options}->bigPics; my $titleField = $self->{model}->{commonFields}->{title}; my $searchField = $plugin->getEanField; my $i = 0; my $resultsDialog; if (!$self->{options}->{first}) { $resultsDialog = $self->{options}->{parent}->getDialog('Results'); $resultsDialog->setModel($self->{model}, $self->{model}->{fieldsInfo}); $resultsDialog->setMultipleSelection(0); } my $search; my $socket; if ($self->{options}->{type} eq 'Network') { $socket = new IO::Socket::INET( LocalPort => $self->{options}->{port}, Proto => 'tcp', Listen => 1, Reuse => 1 ); } $self->{dialog} = new GCScannerDialog($self->{options}->{parent}, $self->getLang, $self->{model}->getName, $socket); my $previous = ''; while ($search = $self->getBarCode($previous)) { chomp $search; next if ! $search; # $_ contains the title to search $plugin->{title} = $search; $plugin->{type} = 'load'; $plugin->{urlField} = $self->{model}->{commonFields}->{url}; $plugin->{searchField} = $searchField; #Initialize what will be pushed in the array my $info = {$searchField => $search}; $self->{options}->{parent}->setWaitCursor($self->{options}->{lang}->{StatusSearch}.' ('.$search.')'); $plugin->load; my $itemNumber = $plugin->getItemsNumber; if ($itemNumber != 0) { $plugin->{type} = 'info'; if (($itemNumber == 1) || ($self->{options}->{first})) { $plugin->{wantedIdx} = 0; } else { my $withNext = 0; my @items = $plugin->getItems; $resultsDialog->setWithNext(0); $resultsDialog->setSearchPlugin($plugin); $resultsDialog->setList($search); $resultsDialog->show; if ($resultsDialog->{validated}) { $plugin->{wantedIdx} = $resultsDialog->getItemsIndexes->[0]; } } $info = $plugin->getItemInfo; my $title = $info->{$titleField}; $self->{options}->{parent}->{defaultPictureSuffix} = $plugin->getDefaultPictureSuffix; foreach my $field(@{$self->{model}->{managedImages}}) { $info->{$field} = '' if $info->{$field} eq 'empty'; next if !$info->{$field}; ($info->{$field}) = $self->{options}->{parent}->downloadPicture($info->{$field}, $title); } # Add the default value my $defaultInfo = $self->{model}->getDefaultValues; foreach my $field(keys %$defaultInfo) { next if exists $info->{$field}; $info->{$field} = $defaultInfo->{$field}; } } $previous = $info->{$titleField}; push @result, $info; $self->{options}->{parent}->restoreCursor; } $socket->close if $socket; return \@result; } sub getEndInfo { my $self = shift; my $message; return $message; } } 1;