From 126bb8cb6b93240bb4d3a2b816b74c286c3d422b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 6 Jul 2014 15:20:38 +0200 Subject: Imported Upstream version 1.7.0 --- lib/gcstar/GCExportImport.pm | 526 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 526 insertions(+) create mode 100644 lib/gcstar/GCExportImport.pm (limited to 'lib/gcstar/GCExportImport.pm') diff --git a/lib/gcstar/GCExportImport.pm b/lib/gcstar/GCExportImport.pm new file mode 100644 index 0000000..b73cdd3 --- /dev/null +++ b/lib/gcstar/GCExportImport.pm @@ -0,0 +1,526 @@ +package GCExportImport; + +################################################### +# +# 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; + +{ + package GCExportImportBase; + + sub setLangName + { + my ($self, $langName) = @_; + + $self->{langName} = $langName; + } + + sub getLang + { + my ($self) = @_; + if (! $self->{langContainer}) + { + my $langFile = $self->{moduleName}; + my %tmpLang; + eval "use GCLang::".$self->{langName}."::$langFile\n"; + eval "%tmpLang = %GCLang::".$self->{langName}."::".$langFile."::lang"; + $self->{langContainer} = \%tmpLang; + } + return $self->{langContainer}; + } + + sub getName + { + my $self = shift; + + return $self->getLang->{Name}; + } + + sub setModel + { + my ($self, $model) = @_; + $self->{model} = $model; + } + + sub checkModule + { + my ($self, $module, $version) = @_; + + eval "use $module"; + ($self->{errors} .= "$module\n", return 0) if $@; + return 1 if !defined $version; + no strict 'refs'; + ($self->{errors} .= "$module\n", return 0) + if (${$module.'::VERSION'} < $version); + return 1; + } + + sub checkOptionalModule + { + my ($self, $module, $version) = @_; + # Save errors + my $errors = $self->{errors}; + my $code = $self->checkModule($module, $version); + # And restore them so it won't impact detecting if the module is broken + $self->{errors} = $errors; + return $code; + } + + sub hideFileSelection + { + return 0; + } + + sub new + { + my ($proto) = @_; + my $class = ref($proto) || $proto; + + (my $moduleName = $class) =~ s/(GC..port)er/$1/; + + my $self = {moduleName => $moduleName, + errors => ''}; + bless($self, $class); + return $self; + } +} + +use GCDialogs; + +{ + package GCExportImportDialog; + use base 'GCModalDialog'; + + sub show + { + my $self = shift; + $self->SUPER::show(); + $self->show_all; + + $self->{optionsFrame}->hide if ! $self->{nbOptions}; + if (($self->{type} eq 'export') && (! $self->{module}->wantsSort)) + { + $self->{sorter}->hide; + $self->{sortLabel}->hide; + $self->{order}->hide; + $self->{orderLabel}->hide; + } + + if ($self->{module}->hideFileSelection) + { + $self->{file}->hide; + $self->{labelFile}->hide; + } + + $self->resize(1,1); + my $ok = 0; + while (!$ok) + { + my $response = $self->run; + if ($response eq 'ok') + { + if (($self->{module}->wantsFieldsSelection) + && (scalar @{$self->{fields}} == 0)) + { + my $dialog = Gtk2::MessageDialog->new($self, + [qw/modal destroy-with-parent/], + 'error', + 'ok', + $self->{parent}->{lang}->{ImportExportFieldsEmpty}); + + $dialog->set_position('center-on-parent'); + $dialog->run(); + $dialog->destroy; + next; + } + my $file = $self->{file}->getValue; + if ($file || ! $self->{module}->wantsFileSelection) + { + my %options = $self->getOptions; + $self->addOptions(\%options); + $options{model} = $self->{parent}->{model}; + $options{file} = $file; + $options{lang} = $self->{parent}->{lang}; + $options{fields} = $self->{fields}; + $options{fieldsInfo} = $self->{parent}->{model}->{fieldsInfo}; + $options{originalList} = $self->{parent}->{items}; + $options{parent} = $self->{parent}; + + my ($info, $type) = $self->{module}->process(\%options); + $type ||= 'info'; + if ($info) + { + my $dialog = Gtk2::MessageDialog->new($self, + [qw/modal destroy-with-parent/], + $type, + 'ok', + $info); + + $dialog->set_position('center-on-parent'); + $dialog->run(); + $dialog->destroy ; + } + $self->{parent}->setNbItems; + } + else + { + 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; + } + } + $ok = 1; + } + $self->hide; + } + + sub setModule + { + my ($self, $module) = @_; + $self->set_title($self->{title}." [".$module->getName."]"); + if ($module->wantsDirectorySelection) + { + $self->{labelFile}->set_label($self->{parent}->{lang}->{FileChooserDirectory}); + $self->{file}->setTitle($self->{parent}->{lang}->{FileChooserOpenDirectory}); + $self->{file}->setType('select-folder', 0); + } + else + { + $self->{labelFile}->set_label($self->{parent}->{lang}->{ImportExportFile}); + $self->{file}->setTitle($self->{parent}->{lang}->{FileChooserOpenFile}); + $self->{file}->setType($self->{fileType}, $self->{withFilter}); + } + $self->{file}->setPatternFilter($module->getFilePatterns) + if ($self->{type} eq 'import'); + + $module->setModel($self->{parent}->{model}); + # sorter will only be created for export modules. + # It's initialized with the title field + if ($self->{sorter}) + { + $self->{sorter}->setModel($self->{parent}->{model}); + $self->{sorter}->setValue($self->{parent}->{model}->{commonFields}->{title}); + $self->{sorter}->setValue($module->{options}->{sorter}) + if exists $module->{options}; + } + if ($self->{order}) + { + $self->{order}->setValue(0); + $self->{order}->setValue($module->{options}->{order}) + if exists $module->{options}; + } + foreach ($self->{optionsTable}->get_children) + { + $self->{optionsTable}->remove($_); + $_->destroy; + } + my @optionsList = @{$module->getOptions}; + $self->{optionsTable}->resize($#optionsList + 1, 3) + if $#optionsList >= 0; + + $self->{module} = $module; + my %options; + my $option; + my $row = 0; + my @widgetSignals; + foreach $option (@optionsList) + { + my $label = $module->getLang->{$option->{label}}; + if (!$label) + { + if ($self->{parent}->{model}) + { + $label = $self->{parent}->{model}->getDisplayedText($option->{label}); + } + else + { + $label = $self->{parent}->{lang}->{$option->{label}}; + } + } + my $widget; + my @vExpand = ('fill'); + my $type = $option->{type}; + my $value = ((exists $module->{options}) ? $module->{options}->{$option->{name}} : $option->{default}); + if ($type eq 'yesno') + { + $widget = new GCCheckBox($label); + $self->{optionsTable}->attach($widget, 0, 2, $row, $row + 1, 'fill', 'fill', 0, 0); + if ($option->{changedCallback}) + { + $widget->signal_connect('toggled' => $option->{changedCallback}, [$self,$widget]); + push @widgetSignals, [$widget, 'toggled']; + } + } + elsif ( ($type eq 'short text') || + ($type eq 'long text') || + ($type eq 'number') || + ($type eq 'options') || + ($type eq 'file') || + ($type eq 'history text')) + { + my $labelWidget = GCLabel->new($label); + $self->{optionsTable}->attach($labelWidget, 0, 1, $row, $row + 1, 'fill', 'fill', 0, 0); + + if ($type eq 'short text') + { + $widget = new GCShortText; + } + elsif ($type eq 'long text') + { + $widget = new GCLongText; + $widget->set_size_request(-1,$option->{height}); + push @vExpand, 'expand'; + } + elsif ($type eq 'number') + { + $widget = new GCNumeric($value, $option->{min}, $option->{max}, $option->{step}); + + } + elsif ($type eq 'file') + { + $widget = new GCFile($self, $label, 'open'); + } + elsif ($type eq 'options') + { + $widget = new GCMenuList; + my @valuesList; + if (UNIVERSAL::isa( $option->{valuesList}, "HASH" )) + { + foreach $value(keys %{$option->{valuesList}}) + { + my $item = { + value => $value, + displayed => $option->{valuesList}->{$value} + }; + $item->{displayed} = $module->getLang->{$item->{displayed}} + if ($module->getLang->{$item->{displayed}}); + push @valuesList, $item; + } + } + else + { + my @values; + @values=split m/,/,$option->{valuesList} if(scalar($option->{valuesList})); + @values=@{$option->{valuesList}} if (UNIVERSAL::isa( $option->{valuesList}, "ARRAY" )); + foreach $value(@values) + { + my $item = { + value => $value, + displayed => $value + }; + $item->{displayed} = $module->getLang->{$item->{displayed}} + if ($module->getLang->{$item->{displayed}}); + push @valuesList, $item; + } + } + $widget->setValues(\@valuesList); + if ($option->{changedCallback}) + { + $widget->signal_connect('changed' => $option->{changedCallback}, [$self,$widget]); + push @widgetSignals, [$widget, 'changed']; + } + } + elsif ($type eq 'history text') + { + $widget = new GCHistoryText; + my @initValues = @{$option->{initValues}} if $option->{initValues}; + $widget->setValues(\@initValues); + } + if ($option->{changedCallback}) + { + $widget->signal_connect('changed' => $option->{changedCallback}, [$self,$widget]); + push @widgetSignals, [$widget, 'changed']; + } + if ($option->{buttonLabel}) + { + my $button = Gtk2::Button->new($module->getLang->{$option->{buttonLabel}}); + $button->signal_connect('clicked' => $option->{buttonCallback}, [$self,$widget]); + $self->{optionsTable}->attach($button, 2, 3, $row, $row + 1, 'fill', 'fill', 0, 0); + } + $self->{optionsTable}->attach($widget, 1, 2, $row, $row + 1, ['expand', 'fill'], \@vExpand, 0, 0); + } +# elsif ($type eq 'colorSelection') +# { +# $widget = new Gtk2::HBox(0,0); +# $widget->pack_start(new Gtk2::Label($label), 0,0,0); +# my $entry = new Gtk2::Entry; +# $entry->set_text($value); +# $widget->pack_start($entry, 1,1,5); +# +# my $button = Gtk2::Button->new_from_stock('gtk-select-color'); +# $button->signal_connect('clicked' => sub { +# my $dialog = new Gtk2::ColorSelectionDialog($label); +# my $previous = Gtk2::Gdk::Color->parse($entry->get_text); +# $dialog->colorsel->set_current_color($previous) if $previous; +# my $response = $dialog->run; +# if ($response eq 'ok') +# { +# my $color = $dialog->colorsel->get_current_color; +# my $red = $color->red / 257; +# my $blue = $color->blue / 257; +# my $green = $color->green / 257; +# my $colorString = sprintf ("#%X%X%X", $red, $blue, $green); +# $entry->set_text($colorString); +# } +# $dialog->destroy; +# }); +# $widget->pack_start($button, 0,0,0); +# } + $widget->set_sensitive(0) if $option->{insensitive}; + $widget->setValue($value); + $self->{parent}->{tooltips}->set_tip($widget, + $module->getLang->{$option->{tooltip}}) + if $option->{tooltip}; + $options{$option->{name}} = $widget; + $row++; + } + + $options{withPictures} = new GCCheckBox($self->{parent}->{lang}->{ExportWithPictures}); + if ($module->wantsImagesSelection) + { + $self->{optionsTable}->resize($row, 3); + my $value = ((exists $module->{options}) ? $module->{options}->{withPictures} : 1); + $options{withPictures}->set_active($value); + $self->{optionsTable}->attach($options{withPictures}, 0, 2, $row, $row + 1, 'fill', 'fill', 0, 0); + $row++; + $options{withPictures}->show; + } + else + { + $options{withPictures}->set_active(0); + } + + if ($module->wantsFieldsSelection) + { + $self->{optionsTable}->resize($row, 3); + $self->{fieldsSelection} = new Gtk2::Button($self->{fieldsButtonLabel}); + $self->{parent}->{tooltips}->set_tip($self->{fieldsSelection}, + $self->{fieldsTip}); + $self->{optionsTable}->attach($self->{fieldsSelection}, + 0, 1, $row, $row + 1, 'fill', 'fill', 0, 0); + $self->{fieldsSelection}->signal_connect('clicked' => sub { + $self->{fields} = $self->{fieldsDialog}->getSelectedIds + if $self->{fieldsDialog}->show; + }); + $row++; + } + + $self->{nbOptions} = $row; + $self->{options} = \%options; + $self->{optionsFrame}->show_all; + foreach my $pair(@widgetSignals) + { + $pair->[0]->signal_emit($pair->[1]) + } + + } + + sub getOptions + { + my $self = shift; + my %result; + + foreach (keys %{$self->{options}}) + { + my $value; + my $widget = $self->{options}->{$_}; + $result{$_} = $widget->getValue; + } + + return %result; + } + + sub new + { + my ($proto, $parent, $title, $type) = @_; + my $class = ref($proto) || $proto; + + my $okLabel; + #$okLabel = $parent->{lang}->{'Menu'.ucfirst($type)}; + $okLabel = ($type eq 'import') ? 'gtk-convert' : 'gtk-revert-to-saved'; + $okLabel =~ s/_//g; + + my $self = $class->SUPER::new($parent, + $title, + $okLabel + ); + + $self->{parent} = $parent; + $self->{title} = $title; + $self->{lang} = $parent->{lang}; + $self->{fields} = []; + $self->{type} = $type; + + $self->{optionsFrame} = new GCGroup($parent->{lang}->{OptionsTitle}); + $self->{optionsTable} = new Gtk2::Table(0,3); + $self->{optionsTable}->set_border_width($GCUtils::halfMargin); + $self->{optionsTable}->set_col_spacings($GCUtils::margin); + $self->{optionsTable}->set_row_spacings($GCUtils::halfMargin); + $self->{optionsFrame}->addWidget($self->{optionsTable}); + + #$self->{fileVbox} = new Gtk2::VBox(0,0); + + #my $sep = new Gtk2::HSeparator; + #my $hbox = new Gtk2::HBox(0,0); + + $self->{dataFrame} = new GCGroup($parent->{lang}->{ImportExportData}); + $self->{dataTable} = new Gtk2::Table(1,2); + $self->{dataTable}->set_border_width($GCUtils::halfMargin); + $self->{dataTable}->set_col_spacings($GCUtils::margin); + $self->{dataTable}->set_row_spacings($GCUtils::halfMargin); + $self->{dataFrame}->addWidget($self->{dataTable}); + + $self->{labelFile} = new GCLabel($parent->{lang}->{ImportExportFile}); + #$hbox->pack_start($labelFile,0,0,5); + + $self->{fileType} = ($type eq 'import') ? 'open' : 'save'; + $self->{withFilter} = ($self->{type} eq 'import') ? 1 : 0; + $self->{file} = new GCFile($self, + $parent->{lang}->{FileChooserOpenFile}, + $self->{fileType}, + $self->{withFilter}); + + #$hbox->pack_start($self->{file},1,1,5); + + #$self->{fileVbox}->pack_start($sep, 0, 0, 2); + #$self->{fileVbox}->pack_start($hbox, 0, 0, 10); + + $self->vbox->set_homogeneous(0); + $self->vbox->pack_start($self->{optionsFrame},1,1,0); + $self->vbox->pack_start($self->{dataFrame},0,0,0); + #$self->vbox->pack_start($self->{fileVbox}, 0, 0, 0); + + bless ($self, $class); + return $self; + } + +} + +1; -- cgit v1.2.3