diff options
Diffstat (limited to 'lib/gcstar/GCOptions.pm')
-rw-r--r-- | lib/gcstar/GCOptions.pm | 1670 |
1 files changed, 1670 insertions, 0 deletions
diff --git a/lib/gcstar/GCOptions.pm b/lib/gcstar/GCOptions.pm new file mode 100644 index 0000000..053b635 --- /dev/null +++ b/lib/gcstar/GCOptions.pm @@ -0,0 +1,1670 @@ +package GCOptions; + +################################################### +# +# 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 Gtk2; + +our $DEFAULT_IMG_DIR='./.%FILE_BASE%_pictures/'; + +{ + package GCOptionLoader; + + my $DEFAULT_LANG='EN'; + #my $DEFAULT_IMG_DIR=$ENV{GCS_DATA_HOME}.'/images/'; + + use XML::Simple; + use IO::File; + use POSIX (':errno_h'); + use GCLang; + + sub new + { + # fallbackOptions has been added in 1.7.0. Previous versions stored some collection + # specific settings at global level. This has been moved to collection level, but to + # let users keep their previous settings, it will try to find it at global level if not found + # at collection level. + + my ($proto, $file, $main, $fallbackOptions) = @_; + my $class = ref($proto) || $proto; + my $self = {created => 0, fallbackOptions => $fallbackOptions}; + + #GCLang::loadLangs; + + bless ($self, $class); + $self->load($file, $main) if $file; + return $self; + } + + sub newFromXmlString + { + my ($proto, $string) = @_; + my $class = ref($proto) || $proto; + my $self = {created => 0}; + bless ($self, $class); + if ($string) + { + my $xs = XML::Simple->new; + $self->{options} = $xs->XMLin($string, + SuppressEmpty => 1); + } + return $self; + } + + sub toXmlString + { + my $self = shift; + + my $result = '<collectionInlinePreferences> +'; + while (my ($key,$value) = each(%{$self->{options}})) + { + $result .= " <$key>".GCUtils::encodeEntities($value)."</$key>\n"; + } + $result .= '</collectionInlinePreferences>'; + return $result; + } + + sub error + { + my ($self, $type, $errmsg) = @_; + if ($self->{parent}) + { + $self->{parent}->optionsError($type, $errmsg); + } + else + { + print "Error performing $type for ".$self->{file}.": $errmsg\n"; + } + } + + sub setParent + { + my ($self, $parent) = @_; + $self->{parent} = $parent; + } + + + sub load + { + my ( $self, $file, $main ) = @_; + + my %defaults; + if ( $main ) + { + my $lang = $ENV{LANG}; + if ($lang) + { + $lang =~ s/(..)_?.*/\U$1\E/; + } + else + { + $lang = $DEFAULT_LANG; + }; # if + + %defaults = ( + images => $GCOptions::DEFAULT_IMG_DIR, + autosave => 1, + noautoload => 0, + programs => "system", + browser => "firefox", + player => "mplayer", + audio => "xmms", + imageEditor => "gimp", + file => "", + split => 300, + width => 920, + height => 640, + confirm => 1, + lang => $lang, + status => 1, + splash => 1, + tearoffMenus => 0, + toolbar => 3, + toolbarPosition => 0, + transform => 1, + articles => "le,la,les,l,un,une,des,a,the,der,die,das,ein,eine,el,los,una", + askImport => 0, + searchStop => 1, + alwaysOriginal => 0, + proxy => "", + cookieJar => "", + borrowers => "", + emails => "", + view => 0, + columns => 3, + resizeImgList => 1, + animateImgList => 1, + listBgPicture => 1, + useOverlays => 1, + mailer => "Sendmail", + from => "", + subject => "GCstar email", + smtp => "", + template => "Hello %1,<br/><br/>You have borrowed my %2 since %3. I\'d like to get it back shortly.", + history => "none|none|none|none|none", + historysize => "5", + useRelativePaths => 1, + useTitleForPics => 1, + expandersMode => 'cut', + dateFormat => '%d/%m/%Y', + spellCheck => 1, + cdDevice => '/dev/cd', + useStars => 1, + bigPics => 0, + listPaneSplit => 10000, # Big value to make sure it's hidden by default + displayMenuBar => 1 + ); + }; # if + + $self->{file} = $file; + $self->{options} = \%defaults; # Use default values for now. + my $handle = IO::File->new($file, "<:utf8"); + if (defined( $handle)) + { + # File opened succesfully, read it. + my $options = \%defaults; + while (my $line = $handle->getline()) + { + # Remove last character if white space + # This includes carriage return and fix an issue when using DOS-encoded file on Unix system + $line =~ s/\s$//; + if ($line =~ m{^(.*?)=(.*)$}) + { + $options->{$1} = $2; + } + else + { + # TODO: Report an error in config file. + } # if + } # while + # Close file, check errors. + my $rc = $handle->close(); + if ($rc) + { + # File was read successfully, update options. + $self->{options} = $options; + } + else + { + # File was not read, do not change default values and report error. + $self->error( 'read', $! ); + } #if + } + else + { + # File is not opened. Check the reason. + if ($! == ENOENT) + { + # File does not exist -- not a problem, just continue with defaults. + $self->{options} = \%defaults; + } + else + { + # It is a real error, report it. + # ???: Why report goes to stdout? + # TODO: Open a error window. + $self->error('read', $!); + } # if + } # if + + if (!GCLang::loadLangs($self->lang) && $main) + { + $self->lang($DEFAULT_LANG); + GCLang::loadLangs($self->lang); + } + } + + sub getFullLang + { + my $self = shift; + (my $lang = $self->lang) =~ s/(.*)/\L$1\E_$1/; + $lang =~ s/_EN/_US/; # Fix for english + $lang =~ s/_CS/_CZ/; # Fix for Czech + $lang =~ s/_cn_ZH//; # Fix for Simplified Chinese + $lang =~ s/_ZH/_TW/; # Fix for Traditional Chinese + $lang .= '.UTF-8'; + $lang = 'sr@Latn' if $lang =~ /^sr/; # Fix for serbian + return $lang; + } + + sub save + { + my $self = shift; + return if !$self->{file}; + my $handle = IO::File->new($self->{file}, ">:utf8"); + if (defined($handle)) + { + while ( my ( $key, $value ) = each( %{ $self->{options} } ) ) + { + if ($key) + { + $handle->print( "$key=$value\n" ); + } # if + } # while + $handle->close() or $self->error('save', $!); + } + else + { + $self->error( 'save', $! ); + }; # if + } + + sub exists + { + my ($self, $name) = @_; + + return exists $self->{options}->{$name}; + } + + sub AUTOLOAD + { + my $self = shift; + my $name = our $AUTOLOAD; + return if $name =~ /::DESTROY$/; + my @comp = split('::', $name); + $name = $comp[-1]; + if (@_) + { + $self->{options}->{$name} = shift; + } + else + { + if (!exists $self->{options}->{$name} && $self->{fallbackOptions}) + { + $self->{options}->{$name} = $self->{fallbackOptions}->$name; + } + return $self->{options}->{$name}; + } + } + + sub checkPreviousGCfilms + { + my ($self, $parent) = @_; + + $self->{modelsFactory} = $parent->{modelsFactory}; + my $gcfilmsconf = $ENV{XDG_CONFIG_HOME}.'/gcfilms/gcfilms.conf'; + + if ( -e $gcfilmsconf) + { + my $dialog = Gtk2::MessageDialog->new($parent, + [qw/modal destroy-with-parent/], + 'question', + 'ok-cancel', + $parent->{lang}->{GCfilmsImportQuestion}); + + my $withOptionsCb = new Gtk2::CheckButton($parent->{lang}->{GCfilmsImportOptions}); + my $withDataCb = new Gtk2::CheckButton($parent->{lang}->{GCfilmsImportData}); + $dialog->vbox->pack_start($withOptionsCb, 0, 0, 0); + $dialog->vbox->pack_start($withDataCb, 0, 0, 0); + $dialog->vbox->show_all; + #$parent->{splash}->hide if $parent->{splash}; + my $response = $dialog->run; + my $withOptions = $withOptionsCb->get_active; + my $withData = $withDataCb->get_active; + $dialog->destroy; + return if $response ne 'ok'; + my $gcfilmsOptions = GCOptionLoader->new($gcfilmsconf, 0); + $self->importGCfilmsOptions($gcfilmsOptions) if $withOptions; + $self->importGCfilmsData($gcfilmsOptions) if $withData; + } + } + + sub importGCfilmsOptions + { + my ($self, $options) = @_; + + my @commonOptions = ( + 'listImgSize', + 'historysize', + 'browser', + 'listBgColor', + 'listFgColor', + 'searchStop', + 'groupItems', + 'view', + 'split', + 'autosave', + 'articles', + 'lang', + 'template', + 'askImport', + 'subject', + 'toolbar', + 'listImgSkin', + 'columns', + 'proxy', + 'width', + 'mailer', + 'smtp', + 'status', + 'borrowers', + 'confirm', + 'itemWindowHeight', + 'from', + 'useRelativePaths', + 'toolbarPosition', + 'transform', + 'itemWindowWidth', + 'player', + 'height', + 'listBgPicture', + 'emails', + 'splash' + ); + + my @specificOptions = ( + 'sortOrder', + 'details', + 'sortField', + 'plugin', + 'multisite', + ); + + foreach (@commonOptions) + { + (my $gcfilmsOption = $_) =~ s/item/movie/; + my $value = $options->$gcfilmsOption; + $value =~ s|<br>|<br/>|gm; + $self->$_($value); + } + my $newOptions = $self->{modelsFactory}->getModel('GCfilms')->{preferences}; + foreach (@specificOptions) + { + $newOptions->$_($options->$_); + } + + # Special processing for order -> layout + my $layout = 'form'; + my $order = $options->order; + $layout = 'compact' if ($order == 1) || ($order == 2); + $layout = 'readonly' if ($order == 3) || ($order == 4); + $newOptions->layout($layout); + + $newOptions->save; + } + + sub importGCfilmsData + { + my ($self, $options) = @_; + $self->{parent}->importWithDetect($options->file, 1); + $self->{options}->{file} = $ENV{GCS_DATA_HOME}.'/films.gcs'; + $self->{parent}->{items}->save($self->{parent}); + #$self->{parent}->setFileName($self->{options}->{file}); + $self->{parent}->refreshTitle; + } +} + +{ + package GCOptionsDialog; + + use Glib::Object::Subclass + Gtk2::Dialog:: + ; + + @GCOptionsDialog::ISA = ('GCModalDialog'); + + use GCPlugins; + + use GCLang; + use GCStyle; + use GCMail; + + sub on_destroy + { + my ($widget, $self) = @_; + return 1; + } + + sub initValues + { + my $self = shift; + + $self->{viewChanged} = 0; + $self->{viewOptionsChanged} = 0; + $self->{expert}->set_active($self->{options}->expert); + + if ($self->{options}->programs eq 'system') + { + $self->{systemPrograms}->set_active(1); + } + else + { + $self->{userPrograms}->set_active(1); + } + $self->{defineProgramsButton}->lock($self->{systemPrograms}->get_active); + $self->{browser} = $self->{options}->browser; + $self->{player} = $self->{options}->player; + $self->{audio} = $self->{options}->audio; + $self->{imageEditor} = $self->{options}->imageEditor; + + $self->{cdDevice}->setValue($self->{options}->cdDevice); + $self->{images}->setValue($self->{options}->images); + $self->{confirm}->set_active($self->{options}->confirm); + $self->{autosave}->set_active($self->{options}->autosave); + $self->{autoload}->set_active(! $self->{options}->noautoload); + $self->{splash}->set_active($self->{options}->splash); + $self->{tearoffMenus}->set_active($self->{options}->tearoffMenus); + $self->{options}->spellCheck(1) if ! $self->{options}->exists('spellCheck'); + $self->{spellCheck}->set_active($self->{options}->spellCheck) + if $self->{spellCheck}; + $self->{useRelativePaths}->set_active($self->{options}->useRelativePaths); + $self->{useStars}->set_active($self->{options}->useStars); + $self->{proxycb}->set_active($self->{options}->proxy); + $self->{proxyurl}->set_text($self->{options}->proxy); + $self->{cookieJarcb}->set_active($self->{options}->cookieJar); + $self->{cookieJarPath}->setValue($self->{options}->cookieJar); + $self->{transform}->set_active($self->{options}->transform); + $self->{articles}->set_text($self->{options}->articles); + + if ($self->{options}->useTitleForPics) + { + $self->{picturesNameTitle}->set_active(1); + } + else + { + $self->{picturesNameAuto}->set_active(1); + } + + $self->{options}->columns(3) if ! $self->{options}->exists('columns'); + $self->{columns} = $self->{options}->columns; + + $self->{options}->resizeImgList(0) if ! $self->{options}->exists('resizeImgList'); + $self->{resizeImgList} = $self->{options}->resizeImgList; + + $self->{options}->animateImgList(1) if ! $self->{options}->exists('animateImgList'); + $self->{animateImgList} = $self->{options}->animateImgList; + + $self->{options}->toolbar(3) if ! $self->{options}->exists('toolbar'); + $self->{toolbarOption}->setValue($self->{options}->toolbar); + + $self->{options}->toolbarPosition(0) if ! $self->{options}->exists('toolbarPosition'); + $self->{toolbarPositionOption}->setValue($self->{options}->toolbarPosition); + + $self->{options}->expandersMode('cut') if ! $self->{options}->exists('expandersMode'); + $self->{expandersMode}->setValue($self->{options}->expandersMode); + + $self->{dateFormat}->setValue($self->{options}->dateFormat) + if $self->{dateFormat}; + + $self->{options}->view(0) if ! $self->{options}->exists('view'); + $self->{viewOption}->setValue($self->{options}->view); + + $self->{model}->{preferences}->plugin('ask') + if ! $self->{model}->{preferences}->exists('plugin'); + $self->{pluginOption}->setValue($self->{model}->{preferences}->plugin); + + $self->{askImport}->set_active($self->{options}->askImport); + $self->{searchStop}->set_active($self->{options}->searchStop); + $self->{bigPics}->set_active($self->{options}->bigPics); + + $self->{langOption}->setValue($self->{options}->lang); + $self->{styleOption}->setValue($self->{options}->style); + + $self->{layoutOption}->setValue($self->{model}->{preferences}->layout); + $self->{panelStyleOption}->setValue($self->{options}->panelStyle); + + $self->{options}->mailer('Sendmail') if ! $self->{options}->exists('mailer'); + $self->{mailerOption}->setValue($self->{options}->mailer); + + $self->{from}->set_text($self->{options}->from); + + # Picture size for image mode + $self->{options}->listImgSize(2) if ! $self->{options}->exists('listImgSize'); + $self->{listImgSize} = $self->{options}->listImgSize; + $self->{options}->listImgSkin($GCStyle::defaultList) if ! $self->{options}->exists('listImgSkin'); + $self->{listImgSkin} = $self->{options}->listImgSkin; + $self->{options}->listBgColor('65535,65535,65535') if ! $self->{options}->exists('listBgColor'); + $self->{options}->listFgColor('0,0,0') if ! $self->{options}->exists('listFgColor'); + $self->{mlbg} = $self->{options}->listBgColor; + $self->{mlfg} = $self->{options}->listFgColor; + $self->{useOverlays} = $self->{options}->useOverlays; + $self->{listBgPicture} = $self->{options}->listBgPicture; + + $self->{proxyurl}->set_editable(0) if ! $self->{proxycb}->get_active; + $self->{proxyurl}->set_editable(1) if $self->{proxycb}->get_active; + $self->{cookieJarPath}->lock(1) if ! $self->{cookieJarcb}->get_active; + $self->{cookieJarPath}->lock(0) if $self->{cookieJarcb}->get_active; + + $self->{historysize}->set_value($self->{options}->historysize); + + # Picture size for detailed mode + $self->{options}->detailImgSize($self->{options}->listImgSize) + if ! $self->{options}->exists('detailImgSize'); + + $self->{model}->{preferences}->details($self->{model}->{commonFields}->{title}) + if ! $self->{model}->{preferences}->exists('details'); + $self->{details} = $self->{model}->{preferences}->details; + + $self->{detailImgSize} = $self->{options}->detailImgSize; + $self->{groupBy} = $self->{model}->{preferences}->groupBy; + $self->{secondarySort} = $self->{model}->{preferences}->secondarySort; + $self->{groupedFirst} = $self->{model}->{preferences}->groupedFirst; + $self->{addCount} = $self->{model}->{preferences}->addCount; + } + + sub saveValues + { + my $self = shift; + + $self->{options}->expert(($self->{expert}->get_active) ? 1 : 0); + + $self->{options}->programs(($self->{systemPrograms}->get_active) ? 'system' : 'user'); + $self->{options}->browser($self->{browser}); + $self->{options}->player($self->{player}); + $self->{options}->audio($self->{audio}); + $self->{options}->imageEditor($self->{imageEditor}); + + $self->{options}->cdDevice($self->{cdDevice}->getValue); + $self->{options}->images($self->{images}->getValue); + $self->{options}->confirm(($self->{confirm}->get_active) ? 1 : 0); + $self->{options}->autosave(($self->{autosave}->get_active) ? 1 : 0); + $self->{options}->noautoload(($self->{autoload}->get_active) ? 0 : 1); + $self->{options}->splash(($self->{splash}->get_active) ? 1 : 0); + $self->{options}->tearoffMenus(($self->{tearoffMenus}->get_active) ? 1 : 0); + $self->{options}->spellCheck(($self->{spellCheck}->get_active) ? 1 : 0) + if $self->{spellCheck}; + $self->{options}->useStars(($self->{useStars}->get_active) ? 1 : 0); + $self->{options}->useRelativePaths(($self->{useRelativePaths}->get_active) ? 1 : 0); + $self->{options}->useTitleForPics(($self->{picturesNameTitle}->get_active) ? 1 : 0); + $self->{options}->transform(($self->{transform}->get_active) ? 1 : 0); + $self->{options}->articles($self->{articles}->get_text); + + if ($self->{proxycb}->get_active) + { + $self->{options}->proxy($self->{proxyurl}->get_text); + } + else + { + $self->{options}->proxy(''); + } + + if ($self->{cookieJarcb}->get_active) + { + $self->{options}->cookieJar($self->{cookieJarPath}->getValue); + } + else + { + $self->{options}->cookieJar(''); + } + + $self->{options}->lang($self->{langOption}->getValue); + $self->{options}->style($self->{styleOption}->getValue); + $self->{model}->{preferences}->layout($self->{layoutOption}->getValue); + $self->{options}->panelStyle($self->{panelStyleOption}->getValue); + $self->{options}->toolbar($self->{toolbarOption}->getValue); + $self->{options}->toolbarPosition($self->{toolbarPositionOption}->getValue); + $self->{options}->expandersMode($self->{expandersMode}->getValue); + $self->{options}->dateFormat($self->{dateFormat}->getValue) + if $self->{dateFormat}; + my $currentView = $self->{options}->view; + $self->{options}->view($self->{viewOption}->getValue); + + if (($currentView != $self->{options}->view) + || ($self->{viewOptionsChanged})) + { + $self->{parent}->setItemsList(0, 1); + $self->{viewChanged} = 1; + } + + $self->{model}->{preferences}->plugin($self->{pluginOption}->getValue); + + $self->{options}->askImport(($self->{askImport}->get_active) ? 1 : 0); + $self->{options}->searchStop(($self->{searchStop}->get_active) ? 1 : 0); + $self->{options}->bigPics(($self->{bigPics}->get_active) ? 1 : 0); + #$self->{options}->alwaysOriginal(($self->{alwaysOriginal}->get_active) ? 1 : 0); + + $self->{options}->mailer($self->{mailerOption}->getValue); + $self->{options}->smtp($self->{smtp}->get_text); + $self->{options}->from($self->{from}->get_text); + + $self->{parent}->checkImagesDirectory(1); + $self->{options}->historysize($self->{historysize}->get_value); + $self->{parent}->{menubar}->{menuHistoryItem}->remove_submenu(); + $self->{parent}->{menubar}->{menuHistory} = Gtk2::Menu->new(); + $self->{parent}->{menubar}->addHistoryMenu(); + + #$self->{model}->{preferences}->details($self->{details}); + + $self->{options}->save; + } + + sub checkValues + { + my $self = shift; + + return $self->{parent}->{lang}->{OptionsPicturesWorkingDirError} + if $self->{images}->getValue =~ /.%WORKING_DIR%/; + return undef; + } + + sub activateInternetOptions + { + my ($self, $value) = @_; + + $self->{dataGroupLabel}->set_sensitive($value); + $self->{pluginLabel}->set_sensitive($value); + $self->{pluginOption}->set_sensitive($value); + $self->{pluginList}->set_sensitive($value); + $self->{askImport}->set_sensitive($value); + $self->{searchStop}->set_sensitive($value); + $self->{bigPics}->set_sensitive($value); + } + + sub show_all + { + my $self = shift; + $self->SUPER::show_all; + $self->{hboxImages}->hide; + $self->{hboxDetails}->hide; + $self->{hboxSMTP}->hide if $self->{mailerOption}->getValue ne 'SMTP'; + if ($self->{expert}->get_active) + { + $self->{hboxImages}->show_all if ($self->{options}->view == 1); + $self->{hboxDetails}->show_all if ($self->{options}->view == 2); + } + else + { + # Toolbar and status bar + $self->{labelToolbar}->hide_all; + $self->{toolbarOption}->hide_all; + $self->{labelToolbarPosition}->hide_all; + $self->{toolbarPositionOption}->hide_all; + $self->{labelExpandersMode}->hide_all; + $self->{expandersMode}->hide_all; + if ($self->{dateFormat}) + { + $self->{labelDateFormat}->hide_all; + $self->{dateFormat}->hide_all; + } + $self->{useStars}->hide_all; + # CD Device + $self->{cdDeviceLabel}->hide_all; + $self->{cdDevice}->hide_all; + # Pictures + $self->{picturesNameFormat}->hide_all; + $self->{picturesNameAuto}->hide_all; + $self->{picturesNameTitle}->hide_all; + $self->{useRelativePaths}->hide_all; + # Internet searches + $self->{searchStop}->hide_all; + # Internet access + $self->{proxycb}->hide_all; + $self->{proxyurl}->hide_all; + $self->{cookieJarcb}->hide_all; + $self->{cookieJarPath}->hide_all; + $self->{mailerLabel}->hide_all; + $self->{mailerOption}->hide_all; + $self->{hboxSMTP}->hide_all; + $self->{hboxMua}->hide_all; + # Features + $self->{tearoffMenus}->hide_all; + $self->{autoload}->hide_all; + $self->{OptionsRestoreAccelerators}->hide_all; + # History + $self->{fileHistoryLabel}->hide_all; + $self->{labelHistorysize}->hide_all; + $self->{historysize}->hide_all; + $self->{buttonClearHistory}->hide_all; + } + $self->{allShown} = 1; + $self->{layoutOption}->signal_emit('changed'); + } + + sub show + { + my $self = shift; + my $tabToShow= shift; + + $self->initValues; + $self->show_all if !$self->{allShown}; + $self->{optionstabs}->set_current_page ($tabToShow) if $tabToShow; + $self->activateInternetOptions(! $self->{model}->isPersonal); + + $self->{hboxSMTP}->hide if $self->{options}->mailer ne 'SMTP'; + $self->{pluginList}->hide + if (($self->{model}->{preferences}->plugin ne 'multi') + && ($self->{model}->{preferences}->plugin ne 'multiperfield') + && ($self->{model}->{preferences}->plugin ne 'multiask')); + + while (1) + { + my $code = $self->run; + last if $code ne 'ok'; + my $errorMessage = $self->checkValues; + if (!$errorMessage) + { + $self->saveValues; + last; + } + else + { + my $dialog = Gtk2::MessageDialog->new_with_markup($self->{parent}, + [qw/modal destroy-with-parent/], + 'error', + 'ok', + $errorMessage); + $dialog->run; + $dialog->destroy; + next; + } + } + $self->hide; + } + + sub changeDetails + { + my $self = shift; + my $parent = $self->{parent}; + my @tmpOptionsArray = split m/\|/, $self->{details}; + + my $fieldsDialog = new GCDetailedOptionsDialog($self, + \@tmpOptionsArray); + + + $fieldsDialog->show; + $fieldsDialog->destroy; + } + + sub setModel + { + my ($self, $model) = @_; + + $self->{model} = $model; + my @plugins = map {{value => $_, + displayed => $_}} + @{$model->getPluginsNames}; + unshift @plugins, ( + {value => 'ask', displayed => $self->{parent}->{lang}->{OptionsAskPlugins}}, + {value => 'multiask', displayed => $self->{parent}->{lang}->{OptionsPluginsMultiAsk}}, + {value => 'multi', displayed => $self->{parent}->{lang}->{OptionsPluginsMulti}}, + {value => 'multiperfield', displayed => $self->{parent}->{lang}->{OptionsPluginsMultiPerField}}, + ); + $self->{pluginOption}->setValues(\@plugins); + + my @panels = map {{value => $_, + displayed => $model->getDisplayedText($model->{panels}->{$_}->{label})}} + @{$model->{panelsNames}}; + $self->{layoutOption}->setValues(\@panels); + } + + sub initMailerOption + { + my $self = shift; + use locale; + my @mailers = ({value => 'Sendmail', displayed => 'Sendmail'}, + {value => 'SMTP', displayed => 'SMTP'}); + my $mailPrograms = GCMail::getMailers; + foreach (sort keys %{$mailPrograms}) + { + push @mailers, {value => $_, displayed => $_}; + } + $self->{mailerOption}->setValues(\@mailers, 2); + } + + sub new + { + my ($proto, $parent, $options) = @_; + my $class = ref($proto) || $proto; + my $self = $class->SUPER::new($parent, + $parent->{lang}->{OptionsTitle}, + ); + bless ($self, $class); + + $self->{allShown} = 0; + $self->set_has_separator(0); + + $options = $parent->{options} if !$options; + $self->{options} = $options; + + $self->{parent} = $parent; + + $self->{lang} = $parent->{lang}; + $self->{tooltips} = $parent->{tooltips}; + + ################ + # Main options + ################ + my $tableMain = new Gtk2::Table(3,2,0); + $tableMain->set_row_spacings($GCUtils::halfMargin); + $tableMain->set_col_spacings($GCUtils::margin); + $tableMain->set_border_width($GCUtils::margin); + + my $labelLang = new GCLabel($parent->{lang}->{OptionsLang}); + $self->{langOption} = new GCMenuList; + my @langValues; + push @langValues, {value => $_, displayed => $GCLang::langs{$_}->{LangName}} + foreach (keys %GCLang::langs); + @langValues = sort {$a->{displayed} cmp $b->{displayed}} @langValues; + $self->{langOption}->setValues(\@langValues); + + $tableMain->attach($labelLang, 0, 1, 1, 2, 'fill', 'fill', 0, 0); + $tableMain->attach($self->{langOption}, 1, 2, 1, 2, 'fill', 'fill', 0, 0); + + my $labelStyle = new GCLabel($parent->{lang}->{OptionsStyle}); + $self->{styleOption} = new GCMenuList; + my @styleValues; + push @styleValues, {value => $_, displayed => $_} foreach (sort keys %GCStyle::styles); + $self->{styleOption}->setValues(\@styleValues); + $tableMain->attach($labelStyle, 0, 1, 2, 3, 'fill', 'fill', 0, 0); + $tableMain->attach($self->{styleOption}, 1, 2, 2, 3, 'fill', 'fill', 0, 0); + + $self->{tearoffMenus} = new Gtk2::CheckButton($parent->{lang}->{OptionsTearoffMenus}); + $self->{tearoffMenus}->set_active($options->tearoffMenus); + $self->{tearoffMenus}->set_active(1) if (! $options->exists('tearoffMenus')); + $tableMain->attach($self->{tearoffMenus}, 0, 2, 3, 4, 'fill', 'fill', 0, 0); + + my $labelWarning = new Gtk2::Label; + $labelWarning->set_markup('<b>'.$parent->{lang}->{OptionsWarning}.'</b>'); + $labelWarning->set_use_underline(1); + $labelWarning->set_line_wrap(1); + $labelWarning->set_justify('center'); + + my $vboxMain = new Gtk2::VBox(0,0); + $vboxMain->set_border_width(20); + $vboxMain->pack_start($tableMain,1,1,0); + #$vboxMain->pack_start(Gtk2::HSeparator->new,1,1,10); + $vboxMain->pack_start($labelWarning,1,1,0); + + ################## + # Display options + ################## + my $tableDisplay = new Gtk2::Table(10, 6, 0); + $tableDisplay->set_row_spacings($GCUtils::halfMargin); + $tableDisplay->set_col_spacings($GCUtils::margin); + $tableDisplay->set_border_width($GCUtils::margin); + + my $labelDisplayInformationGroup = new GCHeaderLabel($parent->{lang}->{OptionsDisplayInformationGroup}); + $tableDisplay->attach($labelDisplayInformationGroup, 0, 6, 0, 1, 'fill', 'fill', 0, 0); + + my $labelView = new GCLabel($parent->{lang}->{OptionsView}); + my %views = %{$parent->{lang}->{OptionsViews}}; + $self->{viewOption} = new GCMenuList; + my @viewsOptions = map {{value => $_, displayed => $views{$_}}} + (sort keys %views); + $self->{viewOption}->setValues(\@viewsOptions); + + + + $tableDisplay->attach($labelView, 2, 3, 1, 2, 'fill', 'fill', 0, 0); + $tableDisplay->attach($self->{viewOption}, 3, 4, 1, 2, 'fill', 'fill', 0, 0); + + $self->{hboxImages} = new Gtk2::HBox(0,0); + $self->{imagesButton} = new Gtk2::Button($parent->{lang}->{ImagesOptionsButton}); + $self->{imagesButton}->signal_connect('clicked', sub { + $self->{imagesOptionsDialog} = new GCImagesOptionsDialog($self) + if ! $self->{imagesOptionsDialog}; + $self->{imagesOptionsDialog}->show; + }); + $self->{hboxImages}->pack_start($self->{imagesButton}, 0, 0, 0); + + $self->{hboxDetails} = new Gtk2::HBox(0,0); + $self->{buttonDetails} = new Gtk2::Button($parent->{lang}->{ImagesOptionsButton}); + $self->{buttonDetails}->signal_connect('clicked' => sub { + $self->changeDetails; + }); + $self->{hboxDetails}->pack_start($self->{buttonDetails}, 0, 0, 0); + + $self->{viewOption}->signal_connect('changed' => sub { + my $i = $self->{viewOption}->getValue; + $self->{hboxImages}->hide; + $self->{hboxDetails}->hide; + if ($self->{expert}->get_active) + { + $self->{hboxImages}->show_all if ($i == 1); + $self->{hboxDetails}->show_all if ($i == 2); + } + }); + $tableDisplay->attach($self->{hboxImages}, 4, 6, 1, 2, 'fill', 'fill', 0, 0); + $tableDisplay->attach($self->{hboxDetails}, 4, 6, 1, 2, 'fill', 'fill', 0, 0); + + my $labelLayout = new GCLabel($parent->{lang}->{OptionsLayout}); + $self->{layoutOption} = new GCMenuList; + $self->{layoutOption}->signal_connect('changed' => sub { + my $panelName = $self->{layoutOption}->getValue; + my $readonly = ($self->{model}->{panels}->{$panelName}->{editable} eq 'false'); + if ($readonly) + { + $self->{labelPanelStyle}->show; + $self->{panelStyleOption}->show; + } + else + { + $self->{labelPanelStyle}->hide; + $self->{panelStyleOption}->hide; + } + }); + $tableDisplay->attach($labelLayout, 2, 3, 2, 3, 'fill', 'fill', 0, 0); + $tableDisplay->attach($self->{layoutOption}, 3, 4, 2, 3, 'fill', 'fill', 0, 0); + + $self->{labelPanelStyle} = new GCLabel($parent->{lang}->{OptionsStyle}); + $self->{panelStyleOption} = new GCMenuList; + my @panelStyles = map {{value => $_, displayed => $_}} + (sort @GCStyle::readOnlyStyles); + $self->{panelStyleOption}->setValues(\@panelStyles); + + $tableDisplay->attach($self->{labelPanelStyle}, 4, 5, 2, 3, 'fill', 'fill', 0, 0); + $tableDisplay->attach($self->{panelStyleOption}, 5, 6, 2, 3, ['fill', 'expand'], 'fill', 0, 0); + + $self->{labelToolbar} = new GCLabel($parent->{lang}->{OptionsToolbar}); + $self->{toolbarOption} = new GCMenuList; + my %toolbars = %{$parent->{lang}->{OptionsToolbars}}; + my @toolbarValues = map {{value => $_, displayed => $toolbars{$_}}} + (sort keys %toolbars); + $self->{toolbarOption}->setValues(\@toolbarValues); + + $tableDisplay->attach($self->{labelToolbar}, 2, 3, 3, 4, 'fill', 'fill', 0, 0); + $tableDisplay->attach($self->{toolbarOption}, 3, 4, 3, 4, 'fill', 'fill', 0, 0); + + $self->{labelToolbarPosition} = new GCLabel($parent->{lang}->{OptionsToolbarPosition}); + $self->{toolbarPositionOption} = new GCMenuList; + my %toolbarPositions = %{$parent->{lang}->{OptionsToolbarPositions}}; + my @positionValues = map {{value => $_, displayed => $toolbarPositions{$_}}} + (sort keys %toolbarPositions); + $self->{toolbarPositionOption}->setValues(\@positionValues); + + $tableDisplay->attach($self->{labelToolbarPosition}, 4, 5, 3, 4, 'fill', 'fill', 0, 0); + $tableDisplay->attach($self->{toolbarPositionOption}, 5, 6, 3, 4, ['fill', 'expand'], 'fill', 0, 0); + + $self->{labelExpandersMode} = new GCLabel($parent->{lang}->{OptionsExpandersMode}); + $self->{expandersMode} = new GCMenuList; + my %expandersModes = %{$parent->{lang}->{OptionsExpandersModes}}; + my @ExpandersModeValues = map {{value => $_, displayed => $expandersModes{$_}}} + (sort keys %expandersModes); + $self->{expandersMode}->setValues(\@ExpandersModeValues); + + $tableDisplay->attach($self->{labelExpandersMode}, 2, 3, 4, 5, 'fill', 'fill', 0, 0); + $tableDisplay->attach($self->{expandersMode}, 3, 4, 4, 5, 'fill', 'fill', 0, 0); + + $self->{useStars} = new Gtk2::CheckButton($parent->{lang}->{OptionsUseStars}); + $tableDisplay->attach($self->{useStars}, 4, 6, 4, 5, ['expand', 'fill'], 'fill', 0, 0); + + if ($GCUtils::hasTimeConversion) + { + $self->{labelDateFormat} = new GCLabel($parent->{lang}->{OptionsDateFormat}); + $self->{dateFormat} = new GCShortText; + $self->{dateFormat}->set_width_chars(10); + $self->{tooltips}->set_tip($self->{dateFormat}, + $parent->{lang}->{OptionsDateFormatTooltip}); + $tableDisplay->attach($self->{labelDateFormat}, 2, 3, 5, 6, 'fill', 'fill', 0, 0); + $tableDisplay->attach($self->{dateFormat}, 3, 6, 5, 6, 'fill', 'fill', 0, 0); + } + + my $labelDisplayArticlesGroup = new GCHeaderLabel($parent->{lang}->{OptionsDisplayArticlesGroup}); + $tableDisplay->attach($labelDisplayArticlesGroup, 0, 6, 7, 8, 'fill', 'fill', 0, 0); + + $self->{transform} = new Gtk2::CheckButton($parent->{lang}->{OptionsTransform}); + $tableDisplay->attach($self->{transform}, 2, 6, 8, 9, 'fill', 'fill', 0, 0); + my $labelArticles = new GCLabel($parent->{lang}->{OptionsArticles}); + $tableDisplay->attach($labelArticles, 2, 4, 9, 10, 'fill', 'fill', 0, 0); + $self->{articles} = new Gtk2::Entry; + $self->{articles}->set_width_chars(10); + $tableDisplay->attach($self->{articles}, 4, 6, 9, 10, ['expand', 'fill'], 'fill', 0, 0); + $options->articles('le,la,les,l,un,une,des,a,the') if (! $options->exists('articles')); + + my $vboxDisplay = new Gtk2::VBox(0,0); + $vboxDisplay->set_border_width(0); + $vboxDisplay->pack_start($tableDisplay, 0, 0, 0); + + ################# + # Paths options + ################# + my $vboxPath = new Gtk2::VBox(0,0); + + my $tablePath = new Gtk2::Table(14, 4, 0); + my $pathRow = -1; + $tablePath->set_row_spacings($GCUtils::halfMargin); + $tablePath->set_col_spacings($GCUtils::margin); + $tablePath->set_border_width($GCUtils::margin); + + my $labelProgramsGroup = new GCHeaderLabel($parent->{lang}->{OptionsPathProgramsGroup}); + $pathRow++; + $tablePath->attach($labelProgramsGroup, 0, 4, $pathRow, $pathRow + 1, 'fill', 'fill', 0, 0); + + $self->{systemPrograms} = new Gtk2::RadioButton(undef, $parent->{lang}->{OptionsProgramsSystem}); + $pathRow++; + $tablePath->attach($self->{systemPrograms}, 2, 4, $pathRow, $pathRow + 1, 'fill', 'fill', 0, 0); + $self->{programTypeGroup} = $self->{systemPrograms}->get_group; + $self->{userPrograms} = new Gtk2::RadioButton($self->{programTypeGroup}, $parent->{lang}->{OptionsProgramsUser}); + $self->{defineProgramsButton} = new GCButton($parent->{lang}->{OptionsProgramsSet}); + $self->{defineProgramsButton}->signal_connect('clicked' => sub { + $self->{programsDialog} = new GCProgramsOptionsDialog($self) + if ! $self->{programsDialog}; + $self->{programsDialog}->show; + }); + my $hboxDefinePrograms = new Gtk2::HBox(0,0); + $hboxDefinePrograms->pack_start($self->{userPrograms}, 0, 0, 0); + $hboxDefinePrograms->pack_start($self->{defineProgramsButton}, 0, 0, 2*$GCUtils::margin); + $pathRow++; + $tablePath->attach($hboxDefinePrograms, 2, 4, $pathRow, $pathRow + 1, 'fill', [], 0, 0); + $self->{userPrograms}->signal_connect('toggled' => sub { + $self->{defineProgramsButton}->lock(! $self->{userPrograms}->get_active); + }); + + $self->{cdDeviceLabel} = new GCLabel($parent->{lang}->{OptionsCdDevice}); + $self->{cdDevice} = new GCFile($self, + $self->{parent}->{lang}->{FileChooserOpenDirectory}, + 'select-folder'); + $pathRow++; + $tablePath->attach($self->{cdDeviceLabel}, 2, 3, $pathRow, $pathRow + 1, 'fill', 'fill', 0, 0); + $tablePath->attach($self->{cdDevice}, 3, 4, $pathRow, $pathRow + 1, 'fill', 'fill', 0, 0); + + $self->{labelImagesGroup} = new GCHeaderLabel($parent->{lang}->{OptionsPathImagesGroup}); + $pathRow += 2; + $tablePath->attach($self->{labelImagesGroup}, 0, 4, $pathRow, $pathRow + 1, 'fill', 'fill', 0, 0); + $self->{labelImages} = new GCLabel($parent->{lang}->{OptionsImages}); + $pathRow++; + $tablePath->attach($self->{labelImages}, 2, 3, $pathRow, $pathRow + 1, 'fill', 'fill', 0, 0); + $self->{images} = new GCFile($self, + $self->{parent}->{lang}->{FileChooserOpenDirectory}, + 'select-folder', + 0, + $GCOptions::DEFAULT_IMG_DIR); + $self->{images}->setWidth(40); + $tablePath->attach($self->{images}, 3, 4, $pathRow, $pathRow + 1, ['expand', 'fill'], 'fill', 0, 0); + + $self->{labelPicturesWorkingDir} = new GCLabel($parent->{lang}->{OptionsPicturesWorkingDir}); + $pathRow++; + $tablePath->attach($self->{labelPicturesWorkingDir}, 2, 4, $pathRow, $pathRow + 1, 'fill', 'fill', 2*$GCUtils::margin, 0); + $self->{labelPicturesFileBase} = new GCLabel($parent->{lang}->{OptionsPicturesFileBase}); + $pathRow++; + $tablePath->attach($self->{labelPicturesFileBase}, 2, 4, $pathRow, $pathRow + 1, 'fill', 'fill', 2*$GCUtils::margin, 0); + + $self->{picturesNameFormat} = new GCLabel($parent->{lang}->{OptionsPicturesFormat}); + $pathRow += 2; + $tablePath->attach($self->{picturesNameFormat}, 2, 4, $pathRow, $pathRow + 1, 'fill', 'fill', 0, 0); + $self->{picturesNameAuto} = new Gtk2::RadioButton(undef, $parent->{lang}->{OptionsPicturesFormatInternal}); + $pathRow++; + $tablePath->attach($self->{picturesNameAuto}, 2, 4, $pathRow, $pathRow + 1, 'fill', 'fill', 2*$GCUtils::margin, 0); + $self->{picturesNameGroup} = $self->{picturesNameAuto}->get_group; + $self->{picturesNameTitle} = new Gtk2::RadioButton($self->{picturesNameGroup}, $parent->{lang}->{OptionsPicturesFormatTitle}); + $pathRow++; + $tablePath->attach($self->{picturesNameTitle}, 2, 4, $pathRow, $pathRow + 1, 'fill', 'fill', 2*$GCUtils::margin, 0); + + $self->{useRelativePaths} = new Gtk2::CheckButton($parent->{lang}->{OptionsUseRelativePaths}); + $self->{useRelativePaths}->set_active($options->useRelativePaths); + $self->{useRelativePaths}->set_active(0) if (! $options->exists('useRelativePaths')); + $pathRow++; + $tablePath->attach($self->{useRelativePaths}, 2, 4, $pathRow, $pathRow + 1, 'fill', 'fill', 0, 0); + + $vboxPath->pack_start($tablePath, 0, 0, 0); + + ################### + # Internet options + ################### + my $tableInternet = new Gtk2::Table(12, 5, 0); + $tableInternet->set_row_spacings($GCUtils::halfMargin); + $tableInternet->set_col_spacings($GCUtils::margin); + $tableInternet->set_border_width($GCUtils::margin); + + $self->{dataGroupLabel} = new GCHeaderLabel($parent->{lang}->{OptionsInternetDataGroup}); + $tableInternet->attach($self->{dataGroupLabel}, 0, 5, 0, 1, 'fill', 'fill', 0, 0); + + $self->{pluginLabel} = new GCLabel($parent->{lang}->{OptionsPlugins}); + $self->{pluginOption} = new GCMenuList; + $self->{pluginList} = new Gtk2::Button($parent->{lang}->{OptionsPluginsList}); + $self->{pluginList}->signal_connect('clicked' => sub { + $parent->getDialog('MultiSite')->show if (($self->{pluginOption}->getValue eq 'multi') + || ($self->{pluginOption}->getValue eq 'multiask')); + $parent->getDialog('MultiSitePerField')->show if (($self->{pluginOption}->getValue eq 'multiperfield')); + }); + $self->{pluginOption}->signal_connect('changed' => sub { + if (($self->{pluginOption}->getValue eq 'multi') + || ($self->{pluginOption}->getValue eq 'multiask') + || ($self->{pluginOption}->getValue eq 'multiperfield')) + { + $self->{pluginList}->show; + } + else + { + $self->{pluginList}->hide; + } + }); + $self->{askImport} = new Gtk2::CheckButton($parent->{lang}->{OptionsAskImport}); + $tableInternet->attach($self->{pluginLabel}, 2, 3, 1, 2, 'fill', 'fill', 0, 0); + $tableInternet->attach($self->{pluginOption}, 3, 4, 1, 2, 'fill', 'fill', 0, 0); + $tableInternet->attach($self->{pluginList}, 4, 5, 1, 2, 'fill', 'fill', 20, 0); + $tableInternet->attach($self->{askImport}, 2, 5, 2, 3, 'fill', 'fill', 0, 0); + $self->{bigPics} = new Gtk2::CheckButton($parent->{lang}->{OptionsBigPics}); + $tableInternet->attach($self->{bigPics}, 2, 5, 3, 4, 'fill', 'fill', 0, 0); + $self->{searchStop} = new Gtk2::CheckButton($parent->{lang}->{OptionsSearchStop}); + $tableInternet->attach($self->{searchStop}, 2, 5, 4, 5, 'fill', 'fill', 0, 0) if ($^O !~ /win32/i); + + my $settingsGroupLabel = new GCHeaderLabel($parent->{lang}->{OptionsInternetSettingsGroup}); + $tableInternet->attach($settingsGroupLabel, 0, 5, 6, 7, 'fill', 'fill', 0, 0); + + $self->{proxycb} = new Gtk2::CheckButton($parent->{lang}->{OptionsProxy}); + $self->{proxycb}->set_active($options->proxy); + $self->{proxyurl} = new Gtk2::Entry; + $self->{proxyurl}->set_text($options->proxy); + $self->{proxycb}->signal_connect('clicked' => sub { + if ($self->{proxycb}->get_active) + { + $self->{proxyurl}->set_editable(1); + } + else + { + $self->{proxyurl}->set_editable(0); + } + }); + $tableInternet->attach($self->{proxycb}, 2, 3, 7, 8, 'fill', 'fill', 0, 0); + $tableInternet->attach($self->{proxyurl}, 3, 4, 7, 8, 'fill', 'shrink', 0, 0); + + $self->{cookieJarcb} = new Gtk2::CheckButton($parent->{lang}->{OptionsCookieJar}); + $self->{cookieJarcb}->set_active($options->cookieJar); + $self->{cookieJarcb}->signal_connect('clicked' => sub { + if ($self->{cookieJarcb}->get_active) + { + $self->{cookieJarPath}->lock(0); + } + else + { + $self->{cookieJarPath}->lock(1); + } + }); + $tableInternet->attach($self->{cookieJarcb}, 2, 3, 8, 9, 'fill', 'fill', 0, 0); + $self->{cookieJarPath} = new GCFile($self, + $self->{parent}->{lang}->{OptionsCookieJar}, + 'open', + 0 ); + $tableInternet->attach($self->{cookieJarPath}, 3, 4, 8, 9, 'fill', 'fill', 0, 0); + + my $labelFrom = new GCLabel($self->{parent}->{lang}->{OptionsFrom}); + $self->{from} = new Gtk2::Entry; + $tableInternet->attach($labelFrom, 2, 3, 9, 10, 'fill', 'fill', 0, 0); + $tableInternet->attach($self->{from}, 3, 4, 9, 10, 'fill', 'fill', 0, 0); + + $self->{mailerLabel} = new GCLabel($parent->{lang}->{OptionsMailer}); + $self->{mailerOption} = new GCMenuList; + $self->initMailerOption; + $tableInternet->attach($self->{mailerLabel}, 2, 3, 10, 11, 'fill', 'fill', 0, 0); + $tableInternet->attach($self->{mailerOption}, 3, 4, 10, 11, 'fill', 'fill', 0, 0); + + $self->{hboxSMTP} = new Gtk2::HBox(0,0); + my $SMTPLabel = new GCLabel($parent->{lang}->{OptionsSMTP}); + $self->{smtp} = new Gtk2::Entry; + $self->{smtp}->set_text($options->smtp); + $self->{smtp}->set_width_chars(20); + $self->{hboxSMTP}->pack_start($SMTPLabel,0,0,0); + $self->{hboxSMTP}->pack_start($self->{smtp},0,0,5); + $tableInternet->attach($self->{hboxSMTP}, 4, 5, 10, 11, 'fill', 'fill', 0, 0); + + $self->{mailerOption}->signal_connect('changed' => sub { + if ('SMTP' eq $self->{mailerOption}->getValue) + { + $self->{hboxSMTP}->show; + } + else + { + $self->{hboxSMTP}->hide; + } + }); + + my $mailersButton = new GCButton($parent->{lang}->{OptionsConfigureMailers}); + $self->{hboxMua} = new Gtk2::HBox(0,0); + $self->{hboxMua}->pack_start($mailersButton,0,0,0); + $tableInternet->attach($self->{hboxMua}, 2, 4, 11, 12, 'fill', 'fill', 0, 0); + $mailersButton->signal_connect('clicked' => sub { + my $dialog = $self->{parent}->getDialog('MailPrograms'); + $self->initMailerOption if $dialog->show; + }); + + my $vboxInternet = new Gtk2::VBox(0,0); + $vboxInternet->set_border_width(0); + $vboxInternet->pack_start($tableInternet,0,0,0); + + ################### + # Features options + ################### + my $vboxConvenience = new Gtk2::VBox(0,0); + my $tableFeature = new Gtk2::Table(11, 5, 0); + $tableFeature->set_row_spacings($GCUtils::halfMargin); + $tableFeature->set_col_spacings($GCUtils::margin); + $tableFeature->set_border_width($GCUtils::margin); + + $self->{confirm} = new Gtk2::CheckButton($parent->{lang}->{OptionsRemoveConfirm}); + $self->{confirm}->set_active($options->confirm); + $self->{autosave} = new Gtk2::CheckButton($parent->{lang}->{OptionsAutoSave}); + $self->{autosave}->set_active($options->autosave); + $self->{autoload} = new Gtk2::CheckButton($parent->{lang}->{OptionsAutoLoad}); + $self->{autoload}->set_active(! $options->noautoload); + $self->{splash} = new Gtk2::CheckButton($parent->{lang}->{OptionsSplash}); + $self->{splash}->set_active($options->splash); + $self->{splash}->set_active(1) if (! $options->exists('splash')); + $self->{spellCheck} = 0; + my $restoreAccelOffset = 0; + if ($GCBaseWidgets::hasSpellChecker) + { + $self->{spellCheck} = new Gtk2::CheckButton($parent->{lang}->{OptionsSpellCheck}); + $self->{spellCheck}->set_active($options->spellCheck); + $restoreAccelOffset = 1; + } + $self->{OptionsRestoreAccelerators} = new Gtk2::Button($parent->{lang}->{OptionsRestoreAccelerators}); + $self->{OptionsRestoreAccelerators}->signal_connect('clicked' => sub { + $self->{parent}->{menubar}->restoreDefaultAccels; + }); + + + my $conveniencesLabel = new GCHeaderLabel($parent->{lang}->{OptionsFeaturesConveniencesGroup}); + $tableFeature->attach($conveniencesLabel, 0, 4, 0, 1, 'fill', 'fill', 0, 0); + $tableFeature->attach($self->{splash}, 2, 4, 1, 2, 'fill', 'fill', 0, 0); + $tableFeature->attach($self->{confirm}, 2, 4, 2, 3, 'fill', 'fill', 0, 0); + $tableFeature->attach($self->{autosave}, 2, 4, 3, 4, 'fill', 'fill', 0, 0); + $tableFeature->attach($self->{autoload}, 2, 4, 4, 5, 'fill', 'fill', 0, 0); + $tableFeature->attach($self->{spellCheck}, 2, 4, 5, 6, 'fill', 'fill', 0, 0) + if $self->{spellCheck}; + $tableFeature->attach($self->{OptionsRestoreAccelerators}, 2, 3, + 5 + $restoreAccelOffset, 6 + $restoreAccelOffset, + 'fill', 'fill', 0, 0); + + my $fileHistoryLabelText = $parent->{lang}->{MenuHistory}; + $fileHistoryLabelText =~ s/_//g; + $self->{fileHistoryLabel} = new GCHeaderLabel($fileHistoryLabelText); + $tableFeature->attach($self->{fileHistoryLabel}, 0, 4, 9, 10, 'fill', 'fill', 0, 0); + + $self->{labelHistorysize} = new GCLabel($parent->{lang}->{OptionsHistory}); + my $adjHistory = Gtk2::Adjustment->new(0, 1, 20, 1, 1, 0) ; + $self->{historysize} = Gtk2::SpinButton->new($adjHistory, 0, 0); + $self->{buttonClearHistory} = new Gtk2::Button($parent->{lang}->{OptionsClearHistory}); + $self->{buttonClearHistory}->signal_connect('clicked' => sub { + $self->{options}->history(''); + }); + $tableFeature->attach($self->{labelHistorysize}, 2, 3, 10, 11, 'fill', 'fill', 0, 0); + $tableFeature->attach($self->{historysize}, 3, 4, 10, 11, 'fill', 'fill', 0, 0); + $tableFeature->attach($self->{buttonClearHistory}, 2, 3, 11, 12, 'fill', 'fill', 0, 0); + + $vboxConvenience->pack_start($tableFeature,0,0,0); + + ################### + # Tab Gesture Stuff + ################### + + my $tabs = Gtk2::Notebook->new(); + $tabs->set_name('GCOptionsTabs'); + $tabs->set_tab_pos('left'); + $tabs->set_show_border(0); + + my ($mainButton, $displayButton, $pathButton, $internetButton, $conveniencesButton); + + $mainButton = GCImageBox->new_from_stock('gtk-home', + $parent->{lang}->{OptionsMain}); + $displayButton = GCImageBox->new_from_stock('gtk-select-color', + $parent->{lang}->{OptionsDisplay}); + $pathButton = GCImageBox->new_from_stock('gtk-directory', + $parent->{lang}->{OptionsPaths}); + $internetButton = GCImageBox->new_from_stock('gtk-network', + $parent->{lang}->{OptionsInternet}); + $conveniencesButton = GCImageBox->new_from_stock('gtk-properties', + $parent->{lang}->{OptionsConveniences}); + + $tabs->append_page_menu($vboxMain, $mainButton, Gtk2::Label->new($parent->{lang}->{OptionsMain})); + $tabs->append_page_menu($vboxDisplay, $displayButton, Gtk2::Label->new($parent->{lang}->{OptionsDisplay})); + $tabs->append_page_menu($vboxPath, $pathButton, Gtk2::Label->new($parent->{lang}->{OptionsPaths})); + $tabs->append_page_menu($vboxInternet, $internetButton, Gtk2::Label->new($parent->{lang}->{OptionsInternet})); + $tabs->append_page_menu($vboxConvenience, $conveniencesButton, Gtk2::Label->new($parent->{lang}->{OptionsConveniences})); + + $tabs->set_tab_label_packing ($vboxMain, 1, 0, 'start'); + $tabs->set_tab_label_packing ($vboxDisplay, 1, 0, 'start'); + $tabs->set_tab_label_packing ($vboxPath, 1, 0, 'start'); + $tabs->set_tab_label_packing ($vboxInternet, 1, 0, 'start'); + $tabs->set_tab_label_packing ($vboxConvenience, 1, 0, 'start'); + + $self->vbox->pack_start($tabs, 1, 1, 0); + $self->{optionstabs}=$tabs; + $self->{expert} = new Gtk2::CheckButton($parent->{lang}->{OptionsExpertMode}); + $self->{expert}->signal_connect('toggled' => sub { + $self->show_all; + }); + $self->{expert}->set_border_width($GCUtils::margin); + $self->vbox->pack_start($self->{expert}, 0, 1, 0); + + $self->{lang} = $parent->{lang}; + + return $self; + } + +} + +{ + # Class used to let user select images options + package GCImagesOptionsDialog; + use base "GCModalDialog"; + use GCItemsLists::GCListOptions; + + sub show + { + my $self = shift; + + $self->{panel}->initValues; + + $self->show_all; + my $code = $self->run; + if ($code eq 'ok') + { + $self->{panel}->saveValues; + $self->{parent}->{viewOptionsChanged} = 1; + } + $self->hide; + } + + sub new + { + my ($proto, $parent) = @_; + my $class = ref($proto) || $proto; + + my $self = $class->SUPER::new($parent, + $parent->{lang}->{ImagesOptionsTitle}, + ); + + $self->{panel} = new GCImagesOptionsPanel($parent->{model}->{preferences}, $parent->{parent}); + $self->{parent} = $parent; + + $self->vbox->pack_start($self->{panel},1,1,0); + + bless ($self, $class); + return $self; + } +} + +{ + # Class used to let user select detailed options + package GCDetailedOptionsDialog; + use base "GCModalDialog"; + use GCItemsLists::GCListOptions; + + sub show + { + my $self = shift; + + $self->{panel}->initValues; + + $self->show_all; + my $code = $self->run; + if ($code eq 'ok') + { + $self->{panel}->saveValues; + $self->{parent}->{viewOptionsChanged} = 1; + } + $self->hide; + } + + sub new + { + my ($proto, $parent) = @_; + my $class = ref($proto) || $proto; + + my $self = $class->SUPER::new($parent, + $parent->{lang}->{DetailedOptionsTitle}, + ); + + $self->{panel} = new GCDetailedOptionsPanel($parent->{model}->{preferences}, $parent->{parent}); + $self->{parent} = $parent; + + $self->vbox->pack_start($self->{panel},1,1,0); + + bless ($self, $class); + return $self; + } +} + + +{ + # Class used to let user select program to run + package GCProgramsOptionsDialog; + use base "GCModalDialog"; + + sub initValues + { + my $self = shift; + + foreach (@{$self->{programs}}) + { + $self->{paths}->{$_}->setValue($self->{parent}->{$_}); + } + } + + sub saveValues + { + my $self = shift; + + foreach (@{$self->{programs}}) + { + $self->{parent}->{$_} = $self->{paths}->{$_}->getValue; + } + } + + sub show + { + my $self = shift; + + $self->initValues; + + $self->show_all; + my $code = $self->run; + if ($code eq 'ok') + { + $self->saveValues; + } + $self->hide; + } + + sub new + { + my ($proto, $parent) = @_; + my $class = ref($proto) || $proto; + + my $self = $class->SUPER::new($parent, + $parent->{lang}->{OptionsProgramsSet}, + ); + + $self->{programs} = ['browser', 'player', 'audio', 'imageEditor']; + + my $tablePath = new Gtk2::Table(scalar @{$self->{programs}} + 1, 4); + $tablePath->set_row_spacings($GCUtils::halfMargin); + $tablePath->set_col_spacings($GCUtils::margin); + $tablePath->set_border_width($GCUtils::margin); + + $self->{labelPrograms} = new GCHeaderLabel($parent->{lang}->{OptionsPrograms}); + $tablePath->attach($self->{labelPrograms}, 0, 4, 0, 1, 'fill', 'fill', 0, $GCUtils::halfMargin); + + my $line = 1; + foreach my $program(@{$self->{programs}}) + { + my $label = new GCLabel($parent->{lang}->{'Options'.ucfirst($program)}); + $tablePath->attach($label, 2, 3, $line, $line + 1, 'fill', 'fill', 0, 0); + $self->{paths}->{$program} = new GCFile($parent, $parent->{lang}->{OptionsProgramTitle}); + $self->{paths}->{$program}->setWidth(40); + $tablePath->attach($self->{paths}->{$program}, 3, 4, $line, $line + 1, ['expand', 'fill'], 'fill', 0, 0); + $line++; + } + + $tablePath->show_all; + + $self->vbox->pack_start($tablePath,1,1,0); + + bless ($self, $class); + return $self; + } +} + +{ + # Class used to let user select information to be displayed + package GCDisplayOptionsDialog; + use base "Gtk2::Dialog"; + + sub show + { + my $self = shift; + + $self->initValues; + + $self->show_all; + my $code = $self->run; + if ($code eq 'ok') + { + $self->saveValues; + } + $self->hide; + } + + sub new + { + my ($proto, $parent) = @_; + my $class = ref($proto) || $proto; + + my $self = $class->SUPER::new($parent->{lang}->{DisplayOptionsTitle}, + $parent, + [qw/modal destroy-with-parent/], + @GCDialogs::okCancelButtons + ); + + bless($self, $class); + + $self->{show} = {}; + $self->{options} = $parent->{model}->{preferences}; + $self->{parent} = $parent; + + $self->{lang} = $parent->{lang}; + $self->set_default_size(-1,480); + return $self; + } + + sub createContent + { + my ($self, $model) = @_; + + $self->{options} = $model->{preferences}; + if ($self->{tabs}) + { + $self->vbox->remove($self->{hboxActions}); + $self->{hboxActions}->destroy; + $self->vbox->remove($self->{tabs}); + $self->{tabs}->destroy; + } + + $self->{fieldsInfo} = $model->getDisplayedInfo; + $self->{fields} = $model->getFieldsCopy; + + #Add special items + if (! $model->isPersonal) + { + unshift @{$self->{fields}}, 'searchButton'; + unshift @{$self->{fieldsInfo}->[0]->{items}}, + {id => 'searchButton', + label => $model->getDisplayedText('PanelSearchButton')}; + } + $self->createComponents; + $self->initValues; + } + + sub initValues + { + my $self = shift; + $self->{show} = {}; + + foreach (@{$self->{fields}}) + { + my $isShown = 1; + $isShown = 0 if ($self->{options}->hidden =~ m/\|$_\|/); + $self->{show}->{$_} = $isShown; + # Only set active if field exists. Works around problems caused trying + # to open corrupted collections + $self->{$_}->set_active($isShown) + if exists $self->{$_}; + } + } + + sub saveValues + { + my $self = shift; + $self->{show} = {}; + + my $hidden = '|'; + foreach (@{$self->{fields}}) + { + my $isShown = 0; + $isShown = 1 if $self->{$_}->get_active; + $self->{show}->{$_} = $isShown; + $hidden .= $_.'|' if !$isShown; + } + $self->{options}->hidden($hidden); + $self->{options}->save; + } + + sub selectAll + { + my $self = shift; + + foreach (@{$self->{fields}}) + { + $self->{$_}->set_active(1); + } + } + + sub initBox + { + my ($self, $box, $values) = @_; + $box->set_border_width(2); + foreach (@$values) + { + $self->{$_->{id}} = new Gtk2::CheckButton($_->{label}); + $box->pack_start($self->{$_->{id}}, 0,0,5); + } + } + + sub createComponents + { + my $self = shift; + + $self->{tabs} = Gtk2::Notebook->new(); + $self->{tabs}->set_border_width(12); + foreach (@{$self->{fieldsInfo}}) + { + my $frame = new Gtk2::Frame(); + $frame->set_shadow_type('none'); + $frame->set_border_width($GCUtils::margin); + $frame->set_label_align(1.0, 0.0); + my $vbox = new Gtk2::VBox(0,0); + $self->initBox($vbox, $_->{items}); + my $scroll = new Gtk2::ScrolledWindow; + $scroll->set_policy ('automatic', 'automatic'); + $frame->add($scroll); + $scroll->add_with_viewport($vbox); + $scroll->set_shadow_type('none'); + $scroll->child->set_shadow_type('none'); + $self->{tabs}->append_page($frame, $_->{title}); + } + + $self->{hboxActions} = new Gtk2::HBox(0,0); + my $allButton = new Gtk2::Button($self->{lang}->{DisplayOptionsAll}); + $allButton->signal_connect( clicked => sub { + $self->selectAll; + }); + $self->{hboxActions}->pack_end($allButton,1,0,20); + + $self->vbox->pack_start($self->{tabs}, 1, 1, 2); + $self->vbox->pack_start($self->{hboxActions}, 0, 0, 10); + } +} + +1; |