{
package GCPlugins;
###################################################
#
# 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 File::Basename;
use GCUtils 'glob';
use GCDialogs;
use base 'Exporter';
our @EXPORT = qw(%pluginsMap %pluginsNameArrays);
our %pluginsMap;
our %pluginsNameArrays;
sub loadPlugins
{
my $model = shift;
return if $pluginsNameArrays{$model};
my $dir = $ENV{GCS_LIB_DIR}.'/GCPlugins/'.$model;
foreach (glob "$dir/*.pm")
{
my $plugin = basename($_, '.pm')."\n";
next if $plugin =~ /Common/;
(my $class = $plugin) =~ s/^GC/GCPlugin/;
my $obj;
eval "use GCPlugins::".$model."::$plugin; \$obj = new GCPlugins::".$model."::$class;";
die "Fatal error with plugin $plugin : $@" if $@;
$pluginsMap{$model}->{$obj->getName} = $obj;
}
my @names = sort keys %{$pluginsMap{$model}};
$pluginsNameArrays{$model} = \@names;
}
sub loadAllPlugins
{
foreach my $dir(glob $ENV{GCS_LIB_DIR}.'/GCPlugins/*')
{
next if $dir =~ /PluginsBase/;
my $model = basename($dir);
next if ($model !~ /^GC/) || ($model eq 'GCstar');
loadPlugins($model);
}
}
{
package GCPluginJob;
use Storable qw(store_fd fd_retrieve);
use IO::Handle;
use GCPlugins::GCPluginsBase;
sub new
{
my ($proto, $command, $data) = @_;
my $class = ref($proto) || $proto;
my $self = {command => $command, data => $data};
$command->autoflush(1);
$data->autoflush(1);
#GCPlugins::loadPlugins if ! $ENV{GCS_PROFILING};
bless ($self, $class);
return $self;
}
sub run
{
my $self = shift;
my $command = $self->{command};
my $info;
while (1)
{
local $Storable::forgive_me = 1;
$info = fd_retrieve($command);
eval {$self->beginSearch($info)};
}
}
sub quit
{
my $self = shift;
close $self->{command};
close $self->{data};
wait;
exit;
}
sub beginSearch
{
my ($self, $info) = @_;
my $pid;
GCPlugins::loadPlugins($info->{model}) if $info->{model};
if ($pid = fork)
{
my $command = $self->{command};
$command->autoflush(1);
my $cmd = readline($command);
chomp $cmd;
kill 9,$pid if ($cmd eq 'STOP');
$self->quit if $cmd eq 'EXIT';
wait;
}
else
{
#$info could be a simple hash or the plugin itself depending on the phase
if ($info->{type} eq 'load')
{
# Here we create the plugin
my $plugin = $pluginsMap{$info->{model}}->{$info->{name}};
$plugin->setProxy($info->{proxy});
$plugin->setCookieJar($info->{cookieJar});
$plugin->{type} = $info->{type};
$plugin->{urlField} = $info->{urlField};
$plugin->{bigPics} = $info->{bigPics};
$self->{currentPlugin} = $plugin;
$plugin->{title} = $info->{query};
$plugin->{searchField} = $info->{field};
$plugin->{pass} = $info->{pass};
$plugin->{nextUrl} = $info->{nextUrl};
$plugin->load;
# Remove the user agent part of the data, otherwise the Storable lib complains
# about not being able to store the sub's stored in it.
undef($plugin->{ua});
local $Storable::forgive_me = 1;
store_fd $plugin, $self->{data};
}
elsif ($info->{type} ne 'exit')
{
# Here we re-use it
my $plugin = $info;
store_fd $plugin->getItemInfo, $self->{data};
}
exit;
}
}
}
use Gtk2;
{
package GCPluginsDialog;
use base 'GCModalDialog';
sub show
{
my $self = shift;
$self->{useThisSite}->set_active(0);
$self->SUPER::show();
$self->show_all;
$self->{fieldsList}->hide if $self->{hideFieldsList};
my $path = $self->{pluginsList}->get_selection->get_selected_rows;
$self->{pluginsList}->scroll_to_cell($path) if $path;
my $response = $self->run;
$self->{plugin} = undef;
if ($response eq 'ok')
{
my $pluginName = '';
my $idx = ($self->{pluginsList}->get_selected_indices)[0];
$pluginName = $self->{pluginsList}->{data}->[$idx]->[0];
$self->{plugin} = $self->{model}->getPlugin($pluginName);
if ($self->{useThisSite}->get_active)
{
$self->{parent}->{model}->{preferences}->plugin($pluginName);
$self->{parent}->checkPlugin;
}
}
$self->hide;
}
sub new
{
my ($proto, $parent) = @_;
my $class = ref($proto) || $proto;
my $self = $class->SUPER::new($parent,
$parent->{lang}->{PluginsTitle},
'gtk-jump-to'
);
bless ($self, $class);
$self->{parent} = $parent;
$self->{titleGroup} = new GCGroup($parent->{lang}->{PluginsQuery});
my $queryHbox = new Gtk2::HBox(0,0);
$self->{query} = new GCShortText;
$self->{query}->signal_connect(activate => sub {
$self->response('ok');
});
$self->{fieldsList} = new GCMenuList;
$queryHbox->pack_start($self->{query}, 1, 1, 0);
$queryHbox->pack_start($self->{fieldsList}, 0, 0, $GCUtils::halfMargin);
$self->{titleGroup}->addWidget($queryHbox);
$self->vbox->pack_start($self->{titleGroup}, 0, 0, 0);
my $pluginGroup = undef;
my $pluginsFrame = new GCGroup($parent->{lang}->{PluginsFrame});
$self->{pluginsList} = new Gtk2::SimpleList($parent->{lang}->{PluginsName} => "text",
$parent->{lang}->{PluginsLang} => "text",
$parent->{lang}->{PluginsSearchFields} => "text",
$parent->{lang}->{PluginsAuthor} => "text",
$parent->{lang}->{PluginsPreferred} => "pixbuf",);
$self->{pluginsList}->set_border_width(5);
$self->{pluginsList}->set_rules_hint(1);
$self->{pluginsList}->get_column(0)->set_min_width(150);
for my $i (0..2)
{
$self->{pluginsList}->get_column($i)->set_resizable(1);
}
$self->{pluginsList}->signal_connect(row_activated => sub {
$self->response('ok');
});
# Setup tooltips for list control
$self->{pluginsList}->set_has_tooltip(1);
$self->{pluginsList}->signal_connect (query_tooltip => sub {
my ($widget, $x, $y, $keyboard_mode, $tooltip) = @_;
# Place the tooltip in the right position
my $path = $self->{pluginsList}->get_path_at_pos ($x, $y);
return 0 unless $path;
$self->{pluginsList}->set_tooltip_row($tooltip, $path);
# If row is for a preferred plugin, set the tooltip
my $index = ($path->get_indices)[0];
if (${ $self->{pluginsList}->{data} }[$index][4] == $self->{starPixbuf})
{
$tooltip->set_text($parent->{lang}->{PluginsPreferredTooltip});
return 1;
}
else
{
return 0;
}
});
# Pixbufs for preferred and standard plugins
$self->{starPixbuf} = Gtk2::Gdk::Pixbuf->new_from_file($ENV{GCS_SHARE_DIR}.'/icons/star.png');
$self->{blankPixbuf} = Gtk2::Gdk::Pixbuf->new ('rgb', 1, 8, 1, 1);
$self->{blankPixbuf}->fill(0x00000000);
$self->{currentPluginList} = undef;
#$self->setModel;
my $scrollPanelList = new Gtk2::ScrolledWindow;
$scrollPanelList->set_border_width(5);
$scrollPanelList->set_policy ('never', 'automatic');
$scrollPanelList->set_shadow_type('etched-in');
$scrollPanelList->add($self->{pluginsList});
$self->{useThisSite} = Gtk2::CheckButton->new($parent->{lang}->{PluginsUseSite});
my $pluginBox = new Gtk2::VBox(0,0);
$pluginBox->pack_start($scrollPanelList, 1, 1, 0);
$pluginBox->pack_start(Gtk2::VBox->new, 0, 0, $GCUtils::halfMargin);
$pluginBox->pack_start($self->{useThisSite}, 0, 0, 0);
$pluginsFrame->addWidget($pluginBox);
$self->vbox->pack_start($pluginsFrame, 1, 1, 0);
$self->set_default_size(1,550);
return $self;
}
sub query
{
my $self = shift;
if (@_)
{
my ($query, $field, $queries) = @_;
$self->{fieldsList}->setValue($field);
$self->{query}->setValue($query);
$self->{queries} = $queries;
$self->{fieldsList}->signal_connect('changed' => sub {
# Only change the search query if it's not empty, otherwise keep existing value
if ($self->{queries}->{$self->{fieldsList}->getValue})
{
$self->{query}->setValue(
$self->{queries}->{$self->{fieldsList}->getValue}
);
}
});
#$self->{fieldsList}->setDefaultValues(shift);
#$self->{searchField} = shift;
}
return ($self->{query}->getValue, $self->{fieldsList}->getValue);
}
sub plugin
{
my $self = shift;
return $self->{plugin};
}
sub setModel
{
my ($self, $model, $list) = @_;
$model ||= $self->{parent}->{model};
my @plugins_array = sort split (",", $list) if $list;
my @fields = @{$model->getSearchFields};
if ($#fields < 1)
{
$self->{hideFieldsList} = 1;
}
else
{
$self->{hideFieldsList} = 0;
my @values;
foreach (@fields)
{
push @values, {value => $_,
displayed => $model->getDisplayedText($model->{fieldsInfo}->{$_}->{label})};
}
$self->{fieldsList}->setValues(\@values);
}
# if ($model)
# {
# my $titleField = $model->{commonFields}->{title};
# my $titleInfo = $self->{parent}->{model}->{fieldsInfo}->{$titleField};
# my $titleText = $model->getDisplayedText($titleInfo->{label});
# $self->{titleGroup}->setLabel($titleText);
# }
return if $list && ($self->{currentPluginList} eq $list);
$self->{currentPluginList} = $list;
my $pluginGroup = undef;
my $i = 0;
my @newData;
$self->{model} = $model;
if ($model)
{
foreach (sort keys %{$model->getAllPlugins})
{
my $plugin = $model->getPlugin($_);
if ((!$list) || ($plugin->getName eq $plugins_array[$i]))
{
# Add plugin to list
# Plugin should be marked as a default if it's both preferred, and for the user's language,
# or if isPreferred is 2 (not language dependant)
push @newData, [$plugin->getName, "\n".$plugin->getLang."\n",
$plugin->getSearchFields($model), $plugin->getAuthor,
((($plugin->isPreferred == 1)
&& ($self->{parent}->{options}->lang eq $plugin->getLang))
|| ($plugin->isPreferred == 2))
? $self->{starPixbuf} : $self->{blankPixbuf}];
$i++;
}
}
}
# Sort list with preferred plugins first
@{$self->{pluginsList}->{data}} = sort {
if (($a->[4] == $self->{starPixbuf}) && ($b->[4] == $self->{starPixbuf}))
{ return lc($a->[0]) cmp lc($b->[0]); }
elsif ($a->[4] == $self->{starPixbuf}) { return -1; }
elsif ($b->[4] == $self->{starPixbuf}) { return 1; }
else { return lc($a->[0]) cmp lc($b->[0]); }
} @newData;
$self->{pluginsList}->select(0);
}
}
{
package GCAllPluginsDialog;
use base 'GCModalDialog';
sub show
{
my $self = shift;
$self->SUPER::show();
$self->show_all;
($self->action_area->get_children)[1]->hide_all;
my $response = $self->run;
$self->hide;
}
sub new
{
my ($proto, $parent) = @_;
my $class = ref($proto) || $proto;
my $self = $class->SUPER::new($parent,
$parent->{lang}->{PluginsFrame},
'gtk-close'
);
bless ($self, $class);
$self->{parent} = $parent;
$self->{factory} = $parent->{modelsFactory};
my @columnsNames = ('Name', 'Lang', 'SearchFields', 'Author', 'Preferred');
$self->{pluginsModel} = new Gtk2::TreeStore(map {'Glib::String'} @columnsNames);
$self->{pluginsList} = Gtk2::TreeView->new_with_model($self->{pluginsModel});
my @columns;
my $i = 0;
for my $col(@columnsNames)
{
my $column = Gtk2::TreeViewColumn->new_with_attributes($parent->{lang}->{'Plugins'.$col},
Gtk2::CellRendererText->new,
'text' => $i);
$column->set_resizable(1);
$self->{pluginsList}->append_column($column);
$i++;
}
$self->{pluginsList}->set_border_width(5);
$self->{pluginsList}->set_rules_hint(1);
my $scrollPanelList = new Gtk2::ScrolledWindow;
$scrollPanelList->set_border_width(5);
$scrollPanelList->set_policy ('never', 'automatic');
$scrollPanelList->set_shadow_type('etched-in');
$scrollPanelList->add($self->{pluginsList});
$self->{useThisSite} = Gtk2::CheckButton->new($parent->{lang}->{PluginsUseSite});
my $pluginBox = new Gtk2::VBox(0,0);
$pluginBox->pack_start($scrollPanelList, 1, 1, 0);
for my $modelInfo (@{$self->{factory}->getDefaultModels})
{
my $modelIter = $self->{pluginsModel}->append(undef);
$self->{pluginsModel}->set($modelIter,
(0 => $modelInfo->{description})
);
my $model = $self->{factory}->getModel($modelInfo->{name});
for my $pluginName (sort keys %{$model->getAllPlugins})
{
my $plugin = $model->getPlugin($pluginName);
my $pluginIter = $self->{pluginsModel}->append($modelIter);
my %data;
$i = 0;
my $method;
($method = 'get'.$_, $data{$i++} = $plugin->$method($model))
foreach (@columnsNames);
$self->{pluginsModel}->set($pluginIter, %data);
# (
# 0 => $plugin->getName,
# 1 => $plugin->getLang,
# 2 => $plugin->getSearchFieldsAsString($model),
# 4 => $plugin->getAuthor
# )
# );
}
}
$self->vbox->pack_start($pluginBox, 1, 1, 0);
$self->set_default_size(1,550);
return $self;
}
sub setModel
{
my ($self, $model, $list) = @_;
$model ||= $self->{parent}->{model};
my @plugins_array = sort split (",", $list) if $list;
my @fields = @{$model->getSearchFields};
if ($#fields < 1)
{
$self->{hideFieldsList} = 1;
}
else
{
$self->{hideFieldsList} = 0;
my @values;
foreach (@fields)
{
push @values, {value => $_,
displayed => $model->getDisplayedText($model->{fieldsInfo}->{$_}->{label})};
}
$self->{fieldsList}->setValues(\@values);
}
return if $list && ($self->{currentPluginList} eq $list);
$self->{currentPluginList} = $list;
my $pluginGroup = undef;
my $i = 0;
my @newData;
$self->{model} = $model;
if ($model)
{
foreach (sort keys %{$model->getAllPlugins})
{
my $plugin = $model->getPlugin($_);
if ((!$list) || ($plugin->getName eq $plugins_array[$i]))
{
push @newData, [$plugin->getName, "\n".$plugin->getLang."\n", $plugin->getAuthor,
$plugin->isPreferred ? $self->{starPixbuf} : $self->{blankPixbuf}];
$i++;
}
}
}
# Sort list with preferred plugins first
@{$self->{pluginsList}->{data}} = sort {
if (($a->[4] == $self->{starPixbuf}) && ($b->[4] == $self->{starPixbuf}))
{ return lc($a->[0]) cmp lc($b->[0]); }
elsif ($a->[4] == $self->{starPixbuf}) { return -1; }
elsif ($b->[4] == $self->{starPixbuf}) { return 1; }
else { return lc($a->[0]) cmp lc($b->[0]); }
} @newData;
$self->{pluginsList}->select(0);
}
}
{
#Class that is used to let user select
#plugins he wants to use in a multi-site search.
package GCMultiSiteDialog;
use base 'GCDoubleListDialog';
sub getInitData
{
my $self = shift;
return $self->{model}->getPluginsNames;
}
sub getData
{
my $self = shift;
my @array = split m/,/, $self->{model}->{preferences}->multisite;
return \@array;
}
sub saveList
{
my ($self, $list) = @_;
my $value = join ',', @$list;
$self->{model}->{preferences}->multisite($value);
}
sub getPlugin
{
my ($self, $idx) = @_;
$self->init;
return $self->{usedArray}->[$idx];
}
sub getPluginsNumber
{
my $self = shift;
$self->init;
return scalar @{$self->{usedArray}};
}
sub preFill
{
my $self = shift;
my @data;
my $langName = $self->{options}->lang;
foreach (@{$self->{model}->getPluginsNames})
{
push @data, $_ if $self->{model}->getPlugin($_)->getLang eq $langName;
}
$self->getDoubleList->setListData(\@data);
}
sub setModel
{
my ($self, $model) = @_;
$self->{model} = $model;
}
sub new
{
my ($proto, $parent, $model) = @_;
my $class = ref($proto) || $proto;
my $self = $class->SUPER::new(
$parent,
$parent->{lang}->{MultiSiteTitle},
0,
$parent->{lang}->{MultiSiteUnused},
$parent->{lang}->{MultiSiteUsed}
);
bless ($self, $class);
$self->setModel($model);
if (! $self->{model}->{preferences}->exists('multisite'))
{
$self->preFill;
$self->saveList(\@{$self->{usedArray}});
$self->{initialized} = 1;
}
my $langButton = new Gtk2::Button($parent->{lang}->{MultiSiteLang});
$langButton->set_border_width($GCUtils::margin);
$langButton->signal_connect('clicked' => sub {
$self->preFill;
});
my $clearButton = new Gtk2::Button($parent->{lang}->{MultiSiteClear});
$clearButton->set_border_width($GCUtils::margin);
$clearButton->signal_connect('clicked' => sub {
$self->clearList;
});
$self->getDoubleList->setDataHandler($self);
$self->getDoubleList->addBottomButtons($langButton,$clearButton);
return $self;
}
}
{
#Class that is used to let user select
#plugin order he wants to use for each imported fields
package GCMultiSitePerFieldDialog;
use base 'GCModalDialog';
our $removeValue = 'GCListRemove';
my $startColMenus=1;
my $pluginListOrderPerField;
my $fieldsToFetch;
my $remainingSourcesOrderPerField;
sub show
{
my $self = shift;
$self->SUPER::show();
$self->show_all;
my $response = $self->run;
$self->hide;
$self->cleanListOrder;
$self->savePrefOrderListFromForm if ($response eq 'ok');
$self->loadPrefOrderListInForm if ($response ne 'ok');
return ($response eq 'ok');
}
sub getSourcesListMenu
{
my ($self,$withRemoveItem) = @_;
return new GCMenuList($self->{sourcesList}) if !$withRemoveItem;
return new GCMenuList($self->{sourcesListWithRemoveItem}) if $withRemoveItem;
}
sub createRowForField
{
my ($self, $field, $row, $mandatory) = @_;
my $fieldsInfo = $self->{parent}->{model}->{fieldsInfo};
$self->{fields}->{$field}->{row}=$row;
$self->{fields}->{$field}->{'Cb'} = new GCCheckBox($self->{parent}->{model}->getDisplayedText($fieldsInfo->{$field}->{label}));
if ($mandatory)
{
$self->{fields}->{$field}->{'Cb'}->lock(1);
$self->{fields}->{$field}->{'Cb'}->setValue(1);
$self->{fields}->{$field}->{'Cb'}->{mandatory} = 1;
}
$self->{table}->attach($self->{fields}->{$field}->{'Cb'}, 0, 1, $row, $row + 1, 'fill', ['fill', 'expand'], 0, 0);
my $curNbSite=0;
$self->{fields}->{$field}->{'SiteListMenus'}=[];
$self->{fields}->{$field}->{'SiteListAddLast'}=new Gtk2::Button("+");
$self->{fields}->{$field}->{'SiteListAddLast'}->signal_connect('clicked' => sub {
$self->addSiteListToField($field,-1);
});
$self->{fields}->{$field}->{'SiteListAddLast'}->set_no_show_all(1);
$self->{fields}->{$field}->{'SiteListAddFirst'}=new Gtk2::Button("+");
$self->{fields}->{$field}->{'SiteListAddFirst'}->signal_connect('clicked' => sub {
$self->addSiteListToField($field,0);
});
$self->{table}->attach($self->{fields}->{$field}->{'SiteListAddFirst'}, $startColMenus, 1+$startColMenus, $row, $row + 1, 'fill', 'fill', 0, 0);
my $Align = new Gtk2::Alignment(0.0, 0.5, 0.0, 0.0);
my $Hbox = new Gtk2::HBox();
$self->{fields}->{$field}->{'Hbox'}=$Hbox;
$Hbox->pack_start($self->{fields}->{$field}->{'SiteListAddLast'},1,0,0);
$Align->add($Hbox);
$self->{table}->attach($Align, 1+$startColMenus, 2+$startColMenus, $row, $row + 1, ['expand','fill'], 'fill', 0, 0);
}
sub addSiteListToField
{
my ($self, $field, $position,$value) = @_;
my $curListMenus=$self->{fields}->{$field}->{'SiteListMenus'};
my $curNbSite=scalar @{$curListMenus};
$curNbSite++;
$position=$curNbSite-1 if $position==-1;
my $Hbox = $self->{fields}->{$field}-> {'Hbox'};
my $newSiteList = $self->getSourcesListMenu(1);
$value=$self->{bottomline}->{siteAddToAll}->getValue(1) if !$value;
$newSiteList->setValue($value);
$newSiteList->{orderInList}=$position;
$newSiteList->signal_connect('changed' => sub {
if ($newSiteList->getValue eq $removeValue)
{
$self->removeSiteListFromField($field, $newSiteList->{orderInList})
}
});
#insert the new siteList
splice @{$curListMenus}, $position, 0, $newSiteList;
$Hbox->pack_start($newSiteList,0,0,0);
$Hbox->reorder_child($newSiteList,$position);
$newSiteList->show;
#move other siteList on this row to the right
for (my $idx=$position;$idx<$curNbSite;$idx++)
{
$curListMenus->[$idx]->{orderInList}=$idx;
}
if($curNbSite==1)
{
$self->{fields}->{$field}->{'SiteListAddLast'}->set_no_show_all(0);
$self->{fields}->{$field}->{'SiteListAddLast'}->show;
}
}
sub removeSiteListFromField
{
my ($self, $field, $position) = @_;
my $curListMenus=$self->{fields}->{$field}->{'SiteListMenus'};
my $curNbSite=scalar @{$curListMenus};
$position=$curNbSite-1 if $position==-1;
my $oldSiteList=splice @{$curListMenus}, $position, 1;
my $Hbox = $self->{fields}->{$field}-> {'Hbox'};
$Hbox->remove($oldSiteList);
$curNbSite--;
#move other siteList on this row to the left
for (my $idx=$position;$idx<$curNbSite;$idx++)
{
$curListMenus->[$idx]->{orderInList}=$idx;
}
if($curNbSite==0)
{
$self->{fields}->{$field}->{'SiteListAddLast'}->set_no_show_all(1);
$self->{fields}->{$field}->{'SiteListAddLast'}->hide;
}
}
sub removeAllSourceListFromField
{
my ($self, $field) = @_;
my $curNbSite=scalar @{$self->{fields}->{$field}->{'SiteListMenus'}};
for (my $i=0;$i<$curNbSite;$i++)
{
$self->removeSiteListFromField($field,-1);
}
}
sub new
{
my ($proto, $parent, $model,$usePlugins,$otherSources) = @_;
my $class = ref($proto) || $proto;
my $self = $class->SUPER::new($parent,
$parent->{lang}->{OptionsPluginsMultiPerFieldWindowTitle}
);
bless ($self, $class);
$model=$parent->{model} if !$model;
$self->{parent} = $parent;
$self->set_modal(1);
$self->set_position('center');
$self->set_default_size(1,500);
my $layoutHbox = new Gtk2::HBox(0,0);
$self->{layoutVBox} = new Gtk2::VBox(0,0);
$self->vbox->pack_start($layoutHbox, 1,1,0);
$layoutHbox->pack_start($self->{layoutVBox},0,0,$GCUtils::margin);
$self->{table} = new Gtk2::Table(1, 3, 0);
$self->{table}->set_row_spacings($GCUtils::halfMargin);
$self->{table}->set_col_spacings($GCUtils::margin);
$self->{table}->set_border_width($GCUtils::margin);
$self->{scrollPanelList} = new Gtk2::ScrolledWindow;
$self->{scrollPanelList}->set_policy ('never', 'automatic');
$self->{scrollPanelList}->set_shadow_type('none');
$self->{scrollPanelList}->add_with_viewport($self->{table});
$self->{descriptionLabel}=new GCLabel($parent->{lang}->{OptionsPluginsMultiPerFieldDesc});
$self->{layoutVBox}->pack_start($self->{descriptionLabel},0,0,$GCUtils::margin);
$self->{layoutVBox}->pack_start($self->{scrollPanelList},1,1,$GCUtils::margin);
$self->setModel($model);
$self->setSourceList($usePlugins,$otherSources);
$self->initForm;
if (! $self->{model}->{preferences}->exists('multisiteperfield'))
{
$self->savePrefOrderListFromForm;
}
else
{
$self->loadPrefOrderListInForm;
}
return $self;
}
sub setSourceList
{
my ($self,$usePlugins,$otherSourcesList) = @_;
$#{$self->{sourcesList}}=-1;
$#{$self->{sourcesListWithRemoveItem}}=-1;
if ($usePlugins)
{
foreach (@{$self->{model}->getPluginsNames})
{
push @{$self->{sourcesList}},{value=>$_,
displayed=>$_};
}
}
if ($otherSourcesList && scalar (@$otherSourcesList))
{
foreach (@{$otherSourcesList})
{
push @{$self->{sourcesList}},Storable::dclone($_);
}
}
$self->{sourcesListWithRemoveItem}=Storable::dclone($self->{sourcesList});
unshift @{$self->{sourcesListWithRemoveItem}}, {value=>$removeValue,displayed=>$self->{parent}->{lang}->{OptionsPluginsMultiPerFieldRemove}};
}
sub setModel
{
my ($self, $model) = @_;
my $parent = $self->{parent};
return if $self->{model} == $model;
$self->{model} = $model;
}
sub initForm
{
my ($self) = @_;
my $parent = $self->{parent};
my $fieldsInfo = $self->{model}->{fieldsInfo};
$self->{urlField} = $self->{parent}->{model}->{commonFields}->{url};
foreach ($self->{table}->get_children)
{
$self->{table}->remove($_);
$_->destroy;
}
my $row = 0;
my $field;
foreach $field(@{$self->{model}->{fieldsNames}})
{
next if $fieldsInfo->{$field}->{imported} ne 'true';
next if ($field eq $self->{urlField});
$self->createRowForField($field, $row);
$row++;
}
$row++;
if($self->{bottomline})
{
foreach($self->{bottomline}->get_children)
{
$self->{bottomline}->remove($_);
$_->destroy;
}
$self->{bottomline}->destroy;
undef $self->{bottomline};
}
$self->{bottomline}=new Gtk2::HBox;
$self->{bottomline}->{selectAll}=new Gtk2::Button($parent->{lang}->{ImportSelectAll});
$self->{bottomline}->{selectAll}->signal_connect('clicked' => sub {
while ( my ($field, $row) = each(%{$self->{fields}}) ) {
$row->{'Cb'}->setValue(1);
}
});
$self->{bottomline}->pack_start($self->{bottomline}->{selectAll},0,0,0);
$self->{bottomline}->{selectNone}=new Gtk2::Button($parent->{lang}->{ImportSelectNone});
$self->{bottomline}->{selectNone}->signal_connect('clicked' => sub {
while ( my ($field, $row) = each(%{$self->{fields}}) ) {
$row->{'Cb'}->setValue(0);
}
});
$self->{bottomline}->pack_start($self->{bottomline}->{selectNone},0,0,0);
$self->{bottomline}->{clear}=new Gtk2::Button($parent->{lang}->{OptionsPluginsMultiPerFieldClearSelected});
$self->{bottomline}->{clear}->signal_connect('clicked' => sub {
while ( my ($field, $row) = each(%{$self->{fields}}) ) {
$self->removeAllSourceListFromField($field) if $row->{'Cb'}->getValue;
}
});
$self->{bottomline}->pack_start($self->{bottomline}->{clear},0,0,0);
$self->{bottomline}->{positionAddToAll} = new GCMenuList([{value=>'First',displayed=>$parent->{lang}->{OptionsPluginsMultiPerFieldFirst}},
{value=>'Last',displayed=>$parent->{lang}->{OptionsPluginsMultiPerFieldLast}}]);
$self->{bottomline}->pack_end($self->{bottomline}->{positionAddToAll},0,0,0);
$self->{bottomline}->{siteAddToAll} = $self->getSourcesListMenu;
$self->{bottomline}->pack_end($self->{bottomline}->{siteAddToAll},0,0,0);
$self->{bottomline}->{addToAll} = GCButton->newFromStock('gtk-add', 0);
$self->{bottomline}->{addToAll}->signal_connect('clicked' => sub {
my $positionAdd=$self->{bottomline}->{positionAddToAll}->getValue(0) eq 'First' ? 0:-1;
foreach $field(keys %{$self->{fields}})
{
$self->addSiteListToField($field,$positionAdd,$self->{bottomline}->{siteAddToAll}->getValue(0));
}
});
$self->{bottomline}->pack_end($self->{bottomline}->{addToAll},0,0,0);
$self->{layoutVBox}->pack_start($self->{bottomline},0,0,$GCUtils::margin);
}
sub loadPrefOrderListInForm
{
my $self = shift;
# load from preference string
undef $pluginListOrderPerField;
undef $fieldsToFetch;
my $valueStr = $self->{model}->{preferences}->multisiteperfield;
my @arrValues= split ';', $valueStr;
foreach (@arrValues)
{
my @line=split ',',$_;
my $field=shift @line;
$fieldsToFetch->{$field}=shift @line;
$pluginListOrderPerField->{$field}=\@line if scalar(@line);
}
# add values in form
while ( my ($field, $row) = each(%{$self->{fields}}) ) {
$self->removeAllSourceListFromField($field);
$self->addSiteListToField($field,-1,$_) foreach (@{$pluginListOrderPerField->{$field}});
$self->{fields}->{$field}->{Cb}->setValue($fieldsToFetch->{$field});
}
$self->cleanListOrder;
}
sub savePrefOrderListFromForm
{
my $self = shift;
undef $pluginListOrderPerField;
undef $fieldsToFetch;
# load from form
$self->cleanListOrder;
while ( my ($field, $row) = each(%{$self->{fields}}) ) {
$fieldsToFetch->{$field}= $row->{'Cb'}->getValue;
push @{$pluginListOrderPerField->{$field}},$_->getValue foreach (@{$row->{'SiteListMenus'}});
}
# save to preference string
my $valueStrArr = [];
while ( my ($field, $row) = each(%{$self->{fields}}) ) {
my $value=$field.','.$fieldsToFetch->{$field};
$value=$value.','.join ',',@{$pluginListOrderPerField->{$field}} if $pluginListOrderPerField->{$field};
push @$valueStrArr,$value;
}
$self->{model}->{preferences}->multisiteperfield(join ';',@$valueStrArr);
}
sub cleanListOrder
{
my $self = shift;
# remove double sitename for each fields, keep the first one
for my $field (keys %{$self->{fields}} ) {
my $sites={};
my $row=$self->{fields}->{$field}->{SiteListMenus};
for (my $i = 0; $i <= $#$row; ++$i)
{
if ($sites->{$row->[$i]->getValue})
{
$self->removeSiteListFromField($field,$i);
$i--;
}
else
{
$sites->{$row->[$i]->getValue}=1;
}
}
undef $sites;
}
}
sub resetCurrentFetchingStatus
{
undef $remainingSourcesOrderPerField;
foreach (keys %$fieldsToFetch)
{
$remainingSourcesOrderPerField->{$_}=Storable::dclone($pluginListOrderPerField->{$_}) if $fieldsToFetch->{$_} ;
}
}
sub getNextSourceNeeded
{
my $self = shift;
foreach my $field(keys %$remainingSourcesOrderPerField)
{
if (scalar(@{$remainingSourcesOrderPerField->{$field}})>0)
{
return $remainingSourcesOrderPerField->{$field}->[0];
}
}
return undef;
}
sub getPlugin
{
my ($self,$pluginName) = @_;
return $self->{model}->getPlugin($pluginName);
}
sub getNonEmptyFields
{
my ($self,$info)=@_;
my $nonEmptyFields=[];
foreach my $field(keys %$info)
{
push @$nonEmptyFields,$field if $self->isFieldNonEmpty($info->{$field});
}
return $nonEmptyFields;
}
sub isFieldNonEmpty
{
my ($self,$var)=@_;
return 0 if !defined $var;
my $reftype=ref $var;
if (!$reftype)
{
return $var ne '';
}
elsif ($reftype eq 'SCALAR')
{
return $$var ne '' && $var!=undef;
}
elsif ($reftype eq 'ARRAY')
{
return scalar($var)>0;
}
elsif ($reftype eq 'HASH')
{
return scalar(keys(%{$var}))>0;
}
}
sub doneWithSourceName
{
my ($self,$pluginName,$info) = @_;
foreach my $field(keys %$remainingSourcesOrderPerField)
{
foreach my $pluginIdx (0..$#{$remainingSourcesOrderPerField->{$field}})
{
if ($remainingSourcesOrderPerField->{$field}->[$pluginIdx] eq $pluginName)
{
if ($self->isFieldNonEmpty($info->{$field}))
{
# if we have the field, so we wont need other info
$#{$remainingSourcesOrderPerField->{$field}}=$pluginIdx-1;
last;
}
else
{
# else we will still need the next one
splice @{$remainingSourcesOrderPerField->{$field}},$pluginIdx,1;
last;
}
}
}
}
}
sub joinInfo
{
my ($self,$infoPerPlugin) = @_;
my $info={};
my $fetchedSources=Storable::dclone($pluginListOrderPerField);
my %urls;
my $urlField=$self->{parent}->{model}->{commonFields}->{url};
foreach my $field(keys %$pluginListOrderPerField)
{
shift @{$fetchedSources->{$field}} while (scalar(@{$fetchedSources->{$field}}) && !$self->isFieldNonEmpty($infoPerPlugin->{$fetchedSources->{$field}->[0]}->{$field}));
if (scalar(@{$fetchedSources->{$field}})>0)
{
$info->{$field}=$infoPerPlugin->{$fetchedSources->{$field}->[0]}->{$field} ;
$urls{$fetchedSources->{$field}->[0]}=$infoPerPlugin->{$fetchedSources->{$field}->[0]}->{$urlField};
}
}
$info->{$urlField}=join ';',values %urls;
return $info;
}
}
}
{
package GCResultsDialog;
use base 'GCModalDialog';
sub show
{
my $self = shift;
for my $i (0..$self->{nbCols} - 1)
{
$self->{results}->get_column($i)->set_sort_indicator(0);
}
$self->{order} = 1;
$self->{sort} = '';
$self->{validated} = 0;
$self->SUPER::show();
$self->show_all;
$self->{nextButton}->hide if !$self->{withNext};
$self->{multipleSelectionLabel}->hide if ! $self->{multipleSelection};
my $ended = 0;
my $code;
while (!$ended)
{
$code = $self->run;
if ($code eq 'ok')
{
$self->{validated} = 1;
$self->{itemsIndexes} = [];
my @idxs = $self->{results}->get_selected_indices;
foreach my $idx(@idxs)
{
push @{$self->{itemsIndexes}}, $self->{items}->[$idx]->{'#'};
}
}
elsif ($code eq 'yes')
{
my @idx = $self->{results}->get_selected_indices;
my $itemIndex = $self->{items}->[$idx[0]]->{'#'};
$self->{parent}->downloadItemInfoFromPlugin($self->{plugin}, $itemIndex, 1);
}
$ended = 1 if ($code eq 'ok') || ($code eq 'cancel') || ($code eq 'delete-event') || ($code eq 'no');
}
$self->hideTooltip;
$self->hide;
return ($code eq 'no');
}
sub getItemsIndexes
{
my $self = shift;
return $self->{itemsIndexes};
}
sub setMultipleSelection
{
my ($self, $activate) = @_;
return if !$self->{results};
$self->{results}->get_selection->set_mode ($activate ? 'multiple' : 'single');
$self->{multipleSelection} = $activate;
}
sub setWithNext
{
my ($self, $value) = @_;
$self->{withNext} = $value;
}
sub setSearchPlugin
{
my ($self, $plugin) = @_;
$self->{plugin} = $plugin;
$self->set_title($self->{parent}->{lang}->{ResultsTitle}.' ('.$plugin->getName.')');
for my $i (0..$self->{nbCols} - 2)
{
# If plugin is a multi-pass plugin, then update the column headers for this pass
$plugin->getReturnedFields() if $plugin->getNumberPasses > 1;
$self->{results}->get_column($i)->set_visible($plugin->hasField($self->{fields}->[$i]));
}
if ($plugin->getExtra)
{
$self->{results}->get_column($self->{nbCols} - 1)->set_visible(1);
$self->{results}->get_column($self->{nbCols} - 1)->set_title($plugin->getExtra);
$self->{withExtra} = 1;
}
else
{
$self->{results}->get_column($self->{nbCols} - 1)->set_visible(0);
$self->{withExtra} = 0;
}
}
sub new
{
my ($proto, $parent) = @_;
my $class = ref($proto) || $proto;
my $self = $class->SUPER::new($parent,
$parent->{lang}->{ResultsTitle},
undef, 0,
'gtk-zoom-in' => 'yes'
);
bless ($self, $class);
$self->{results} = 0;
$self->{withExtra} = 0;
$self->{withNext} = 0;
$self->{multipleSelection} = 0;
$self->{nextButton} = Gtk2::Button->new_from_stock('gtk-go-forward');
$parent->{tooltips}->set_tip($self->{nextButton},
$parent->{lang}->{ResultsNextTip});
$self->add_action_widget($self->{nextButton}, 'no');
$self->{parent} = $parent;
$self->set_modal(1);
$self->set_position('center');
$self->{scrollPanelList} = new Gtk2::ScrolledWindow;
$self->{scrollPanelList}->set_policy ('never', 'automatic');
$self->{scrollPanelList}->set_shadow_type('etched-in');
$self->vbox->pack_start($self->{scrollPanelList}, 1, 1, 0);
$self->vbox->pack_start(Gtk2::HSeparator->new, 0, 0, 0);
my $fillBox = new Gtk2::HBox(0,0);
$self->{multipleSelectionLabel} = GCLabel->new(''.$parent->{lang}->{ResultsInfo}.'');
$self->{multipleSelectionLabel}->set_line_wrap(1);
$self->{multipleSelectionLabel}->set_justify('center');
$self->{multipleSelectionLabel}->set_padding($GCUtils::margin, 0);
$fillBox->pack_start(Gtk2::HBox->new(0,0),1,1,0);
$fillBox->pack_start($self->{multipleSelectionLabel}, 0, 0, $GCUtils::margin);
$fillBox->pack_start(Gtk2::HBox->new(0,0),1,1,0);
$self->vbox->pack_start($fillBox, 0 , 0, $GCUtils::margin);
# To create a tooltip as it is not implemented directly in Gtk2
$self->{tooltipLabel} = Gtk2::Label->new;
$self->{tooltipLabel}->set_line_wrap(1);
$self->{tooltipLabel}->set_padding($GCUtils::margin, $GCUtils::margin);
$self->{tooltip} = Gtk2::Window->new('popup');
$self->{tooltip}->set_decorated(0);
$self->{tooltip}->set_sensitive(1);
$self->{tooltip}->modify_fg('normal', Gtk2::Gdk::Color->parse('#000000'));
$self->{tooltip}->modify_bg('normal', Gtk2::Gdk::Color->parse('#ffffbf'));
$self->{tooltip}->set_position('mouse');
$self->{tooltip}->add($self->{tooltipLabel});
$self->{tooltip}->signal_connect('button_press_event' => sub {
$self->hideTooltip;
if ($self->{results})
{
shift;
$self->{results}->signal_emit('button_press_event', @_);
}
});
$self->{tooltip}->signal_connect('motion-notify-event' => sub {
my ($widget, $event) = @_;
my ($x, $y) = ($event->x_root, $event->y_root);
my ($xoffset, $yoffset) = $widget->window->get_root_origin;
my $allocation = $widget->allocation();
my $x1 = $xoffset + 2 * $allocation->x;
my $y1 = $yoffset + 2 * $allocation->y;
my $x2 = $x1 + $allocation->width;
my $y2 = $y1 + $allocation->height;
my $isInWidget = ($x > $x1 && $x < $x2 && $y > $y1 && $y < $y2);
return if $isInWidget;
if ($self->{results})
{
shift;
$self->{results}->signal_emit('motion-notify-event', @_);
}
});
$self->{tooltipDisplayed} = 0;
return $self;
}
sub setModel
{
my ($self, $model, $fieldsInfo) = @_;
if ($self->{results})
{
$self->{scrollPanelList}->remove($self->{results});
$self->{results}->destroy;
}
$self->{fields} = [];
my @cols;
foreach my $field(@{$model->{resultsFields}})
{
push @cols, ($fieldsInfo->{$field}->{displayed} => 'text');
push @{$self->{fields}}, $field;
}
# Extra column
push @cols, ('' => 'text');
push @{$self->{fields}}, 'extra';
$self->{nbCols} = scalar @{$self->{fields}};
$self->{results} = Gtk2::SimpleList->new(@cols);
$self->{results}->set_rules_hint(1);
$self->{results}->set_headers_clickable(1);
$self->{order} = 1;
$self->{sort} = '';
for my $i (0..$self->{nbCols} - 1)
{
$self->{results}->get_column($i)->set_sort_indicator(0);
$self->{results}->get_column($i)->set_resizable(1);
$self->{results}->get_column($i)->signal_connect('clicked' => sub {
$self->sort($self->{fields}->[$i]);
});
$self->{results}->get_column($i)->{column_number} = $i;
}
$self->{scrollPanelList}->add($self->{results});
$self->{results}->signal_connect(row_activated => sub {
my ($sl, $path, $column) = @_;
$self->response('ok');
});
$self->{results}->signal_connect('motion-notify-event' => sub {
my ($widget, $event) = @_;
$self->displayTooltip($event);
});
$self->{results}->signal_connect('leave-notify-event' => sub {
my ($widget, $event) = @_;
# It corresponds to a leave of the whole widget not from a single cell
$self->hideTooltip if $event->detail eq 'ancestor';
});
$self->{multipleSelectionLabel}->set_markup(''.$self->{parent}->{lang}->{ResultsInfo}.'');
}
sub sort
{
my ($self, $type) = @_;
my $col = 0;
for my $i (0..$self->{nbCols} - 1)
{
$self->{results}->get_column($i)->set_sort_indicator(0);
$col = $i if $self->{fields}->[$i] eq $type;
}
my @items = @{$self->{items}};
if ($self->{sort} eq $type)
{
$self->{order} = 1 - $self->{order}
}
else
{
$self->{order} = 1;
}
@items = sort {$a->{$type} cmp $b->{$type}} @items;
@items = reverse @items if ! $self->{order};
$self->{results}->get_column($col)->set_sort_indicator(1);
$self->{results}->get_column($col)->set_sort_order($self->{order} ? 'ascending' : 'descending');
$self->setList('',@items);
$self->{sort} = $type;
}
sub setList
{
my ($self, $title, @items) = @_;
$self->set_title($self->get_title . ' - '.$title) if $title;
$self->{items} = \@items;
@{$self->{results}->{data}} = ();
$self->{tooltipsStrings} = {};
my $idx = 0;
my $col = 0;
foreach my $item (@items)
{
my $infos = [];
$col = 0;
foreach my $field(@{$self->{fields}})
{
my $value = '';
$value = $item->{$field} if exists $item->{$field};
(my $shortField = $value) =~ s/(.{40}).*/$1.../;
push @$infos, $shortField."\n";
# We store a tooltip is the text has been truncated
$self->{tooltipsStrings}->{$idx}->{$col} = $value
if $value ne $shortField;
$col++;
}
$item->{'#'} = $idx if ! exists $item->{'#'};
push @{$self->{results}->{data}}, $infos;
#push @{$self->{tooltipsStrings}}, $item->{$self->{fields}->[0]};
$idx++;
}
$self->{results}->select(0);
$self->{results}->columns_autosize;
$self->set_default_size(-1,400);
}
sub displayTooltip
{
my ($self, $event) = @_;
my ($path, $column, $cell_x, $cell_y) = $self->{results}->get_path_at_pos ($event->x, $event->y);
if ($path)
{
my $model = $self->{results}->get_model;
my $col = $column->{column_number};
my $row = $path->to_string();
# If a new cell is selected, then hide the tooltip
# It'll be re-shown as required by the code down under
if ($self->{selectedRow} ne $row or $self->{selectedCol} != $col)
{
$self->hideTooltip;
$self->{selectedRow} = $row;
$self->{selectedCol} = $col;
}
else
{
return;
}
if ($row ne '')
{
# Pick that popup string from our hash
#my $str = $popup_hash->{$row}->{$i};
my $str = $self->{tooltipsStrings}->{$row}->{$col};
if ($str)
{
$self->{tooltipLabel}->set_label($str);
if (!$self->{tooltipDisplayed})
{
$self->{tooltip}->show_all;
Gtk2->grab_add($self->{tooltip});
Gtk2::Gdk->pointer_grab(
$self->{tooltip}->window, 1,
[qw/button-press-mask button-release-mask pointer-motion-mask/],
undef, undef, 0);
Gtk2::Gdk->keyboard_grab ($self->{tooltip}->window, 0, 0);
$self->{tooltip}->grab_focus;
my ($thisx, $thisy) = $self->{tooltip}->window->get_origin;
# The window to be a bit away from the mouse pointer.
$self->{tooltip}->move($thisx, $thisy-20);
$self->{tooltipDisplayed} = 1;
}
}
}
return 0;
}
}
sub hideTooltip
{
my $self = shift;
if ($self->{tooltipDisplayed})
{
Gtk2->grab_remove($self->{tooltip});
$self->{tooltip}->hide;
$self->{tooltipDisplayed} = 0;
}
}
}
{
package GCImportFieldsDialog;
use base 'GCModalDialog';
sub setReadOnly
{
my ($self, $value) = @_;
$self->{readOnly} = $value;
my @children = $self->{table}->get_children;
foreach (@children)
{
$_->set_sensitive(!$value) if ($_->get_name eq 'GtkCheckButton')
&& (!$_->{mandatory});
}
$self->set_title($value ? $self->{parent}->{lang}->{ResultsPreview}
: $self->{parent}->{lang}->{ImportWindowTitle});
}
sub info
{
my $self = shift;
my $fieldsInfo = $self->{parent}->{model}->{fieldsInfo};
if (@_)
{
my $info = shift;
$self->{info} = $info;
my @children = $self->{table}->get_children;
foreach (@children)
{
$_->set_text('') if $_->get_name eq 'GtkEntry';
}
my $fieldsInfo = $self->{parent}->{model}->{fieldsInfo};
foreach (keys %{$info})
{
my $tmp = $info->{$_};
if ($fieldsInfo->{$_}->{type} =~ /list/)
{
$tmp = GCPreProcess::multipleList($tmp, $fieldsInfo->{$_}->{type});
}
if ($fieldsInfo->{$_}->{values})
{
$tmp = $self->{parent}->{model}->getDisplayedValue($fieldsInfo->{$_}->{values},
$tmp);
}
if ($_ ne $self->{urlField})
{
$tmp =~ s/\n/ /g;
$tmp =~ s/(.{50}).*/$1.../m;
}
$self->{$_}->set_text($tmp)
if $self->{$_};
}
}
else
{
my $ignore = $self->{parent}->{ignoreString};
foreach my $field(@{$self->{parent}->{model}->{fieldsNames}})
{
next if $fieldsInfo->{$field}->{imported} ne 'true';
next if ($fieldsInfo->{$field}->{type} eq 'url');
if (! $self->{$field.'Cb'}->get_active)
{
unlink $self->{info}->{$field}
if ($fieldsInfo->{$field}->{type} eq 'image')
&& ($self->{info}->{$field} !~ m|^http://|);
$self->{info}->{$field} = $ignore;
}
}
return $self->{info};
}
}
sub showImage
{
use File::Temp qw/ :POSIX /;
my ($self, $field) = @_;
my $location = $self->{info}->{$field};
if ($location =~ m|^http://|)
{
my ($name,$path,$suffix) = File::Basename::fileparse($location, "\.gif", "\.jpg", "\.jpeg", "\.png");
$self->window->set_cursor(Gtk2::Gdk::Cursor->new('watch'));
GCUtils::updateUI;
(my $tmpFile = tmpnam) .= $suffix;
GCUtils::downloadFile($location, $tmpFile, $self->{parent});
$self->window->set_cursor(Gtk2::Gdk::Cursor->new('left_ptr'));
$self->{parent}->launch($tmpFile, 'image', 0, $self);
$self->{info}->{$field} = $tmpFile;
}
else
{
$self->{parent}->launch($location, 'image', 0, $self);
}
}
sub show
{
my $self = shift;
$self->SUPER::show();
$self->show_all;
if ($self->{readOnly})
{
$self->{selectAll}->hide;
$self->{selectNone}->hide;
($self->action_area->get_children)[1]->hide;
}
foreach (keys %{$self->{imagesButton}})
{
$self->{$_}->hide if $self->{info}->{$_};
$self->{imagesButton}->{$_}->hide if ! $self->{info}->{$_};
}
my $response = $self->run;
$self->hide;
return ($response eq 'ok');
}
sub createItem
{
my ($self, $field, $row, $mandatory) = @_;
my $fieldsInfo = $self->{parent}->{model}->{fieldsInfo};
$self->{$field.'Cb'} = new Gtk2::CheckButton($self->{parent}->{model}->getDisplayedText($fieldsInfo->{$field}->{label}));
if ($mandatory)
{
$self->{$field.'Cb'}->set_sensitive(0);
$self->{$field.'Cb'}->set_active(1);
$self->{$field.'Cb'}->{mandatory} = 1;
}
$self->{$field} = new Gtk2::Entry;
$self->{$field}->set_editable(0);
$self->{table}->attach($self->{$field.'Cb'}, 0, 1, $row, $row + 1, 'fill', ['fill', 'expand'], 0, 0);
$self->{table}->attach($self->{$field}, 1, 2, $row, $row + 1, ['fill', 'expand'], 'fill', 0, 0);
}
sub new
{
my ($proto, $parent) = @_;
my $class = ref($proto) || $proto;
my $self = $class->SUPER::new($parent,
$parent->{lang}->{ImportWindowTitle}
);
bless ($self, $class);
$self->{parent} = $parent;
$self->set_modal(1);
$self->set_position('center');
$self->set_default_size(1,500);
$self->{table} = new Gtk2::Table(1, 2, 0);
$self->{table}->set_row_spacings($GCUtils::halfMargin);
$self->{table}->set_col_spacings($GCUtils::margin);
$self->{table}->set_border_width($GCUtils::margin);
$self->{scrollPanelList} = new Gtk2::ScrolledWindow;
$self->{scrollPanelList}->set_policy ('never', 'automatic');
$self->{scrollPanelList}->set_shadow_type('none');
$self->{scrollPanelList}->add_with_viewport($self->{table});
$self->vbox->pack_start($self->{scrollPanelList},1,1,$GCUtils::margin);
$self->setModel($parent->{model});
return $self;
}
sub setModel
{
my ($self, $model) = @_;
my $parent = $self->{parent};
$self->{model} = $model;
my $fieldsInfo = $model->{fieldsInfo};
$self->{urlField} = $self->{parent}->{model}->{commonFields}->{url};
foreach ($self->{table}->get_children)
{
$self->{table}->remove($_);
$_->destroy;
}
my $row = 0;
my @picFields;
my $field;
foreach $field(@{$model->{fieldsNames}})
{
next if $fieldsInfo->{$field}->{imported} ne 'true';
next if ($field eq $self->{urlField});
if ($fieldsInfo->{$field}->{type} eq 'image')
{
push @picFields, $field;
next;
}
$self->createItem($field, $row);
$row++;
}
foreach $field(@picFields)
{
$self->createItem($field, $row);
$self->{imagesButton}->{$field} = new Gtk2::Button($parent->{lang}->{ImportViewPicture});
$self->{imagesButton}->{$field}->signal_connect('clicked' => sub {
$self->showImage($field);
});
$self->{table}->attach($self->{imagesButton}->{$field}, 1, 2, $row, $row + 1, 'fill', 'fill', 0, 0);
$row++;
}
if ($self->{urlField})
{
$self->createItem($self->{urlField}, $row, 1);
$row++;
}
$row++;
$self->{selectAll} = new Gtk2::Button($parent->{lang}->{ImportSelectAll});
$self->{selectAll}->signal_connect('clicked' => sub {
my @children = $self->{table}->get_children;
foreach (@children)
{
$_->set_active(1) if $_->get_name eq 'GtkCheckButton';
}
});
$self->{table}->attach($self->{selectAll}, 0, 1, $row, $row + 1, 'fill', 'fill', 0, 0);
$row++;
$self->{selectNone} = new Gtk2::Button($parent->{lang}->{ImportSelectNone});
$self->{selectNone}->signal_connect('clicked' => sub {
my @children = $self->{table}->get_children;
# Remove 2 items corresponding to website to keep it checked
splice @children, 2, 2;
foreach (@children)
{
$_->set_active(0) if $_->get_name eq 'GtkCheckButton';
}
});
$self->{table}->attach($self->{selectNone}, 0, 1, $row, $row + 1, 'fill', 'fill', 0, 0);
}
}
1;