summaryrefslogtreecommitdiff
path: root/lib/gcstar/GCMenu.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gcstar/GCMenu.pm')
-rw-r--r--lib/gcstar/GCMenu.pm1840
1 files changed, 1840 insertions, 0 deletions
diff --git a/lib/gcstar/GCMenu.pm b/lib/gcstar/GCMenu.pm
new file mode 100644
index 0000000..db6ebec
--- /dev/null
+++ b/lib/gcstar/GCMenu.pm
@@ -0,0 +1,1840 @@
+package GCMenu;
+
+###################################################
+#
+# 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 utf8;
+use Gtk2;
+
+use strict;
+{
+ package GCMenuBar;
+ use base 'Gtk2::MenuBar';
+
+ use GCExport;
+ use GCImport;
+ use GCStats;
+
+ sub addHistoryMenu
+ {
+ my ($self, $historyArray) = @_;
+ my $parent = $self->{parent};
+
+ my @tmpHistory;
+ if (! $historyArray)
+ {
+ my @tmpHistory = split(/\|/, $parent->{options}->history);
+ $historyArray = \@tmpHistory;
+ }
+ foreach my $filename(@$historyArray)
+ {
+ next if !$filename || ($filename eq 'none');
+ my $item = Gtk2::MenuItem->new_with_label($filename);
+ $item->signal_connect ('activate' => sub {
+ $parent->openFile($filename);
+ });
+ $self->{menuHistory}->append($item);
+ $item->show();
+ }
+ $self->{menuHistoryItem}->set_submenu($self->{menuHistory});
+ }
+
+ sub setBookmarks
+ {
+ my ($self, $bookmarks) = @_;
+ $self->{bookmarks} = $bookmarks;
+ $self->addBookmarksDir($self->{bookmarks}, undef);
+ $self->{menuBookmarks}->show_all;
+ }
+
+ sub clearBookmarks
+ {
+ my $self = shift;
+ my $i = 0;
+ foreach ($self->{menuBookmarks}->get_children)
+ {
+ $i++;
+ next if ($i < 4 + ($self->{parent}->{options}->tearoffMenus ? 1 : 0));
+ $self->{menuBookmarks}->remove($_);
+ $_->destroy;
+ }
+ }
+
+ sub addBookmarksDir
+ {
+ my ($self, $dir, $parent) = @_;
+ if ($parent)
+ {
+ my $subMenu = Gtk2::Menu->new();
+ my $item = Gtk2::MenuItem->new_with_mnemonic($dir->{name});
+ $item->set_submenu($subMenu);
+ $parent->append($item);
+ $parent = $subMenu;
+ $dir->{menu} = $subMenu;
+ }
+ else
+ {
+ $parent = $self->{menuBookmarks};
+ }
+ foreach my $sub(@{$dir->{dir}})
+ {
+ $self->addBookmarksDir($sub, $parent);
+ }
+ return if !$dir->{file};
+ foreach my $file(@{$dir->{file}})
+ {
+ $self->addBookmark($file, $parent);
+ }
+ }
+
+ sub addBookmark
+ {
+ my ($self, $bookmark, $parent) = @_;
+
+ my $item = Gtk2::MenuItem->new_with_mnemonic($bookmark->{name});
+ $item->signal_connect ('activate' => sub {
+ $self->{parent}->openFile($bookmark->{path});
+ });
+ $parent->append($item);
+
+ }
+
+ sub setModel
+ {
+ my ($self, $model) = @_;
+ $self->{model} = $model;
+ $self->createFilters($model,
+ $model->{fieldsInfo});
+ $self->initExportImportList($model);
+
+ # Update menu labels which are collection dependant
+ $self->updateMenus;
+
+ }
+
+ sub updateItem
+ {
+ my ($self, $item, $label) = @_;
+ foreach my $child($item->get_children)
+ {
+ if ($child->isa('Gtk2::Label'))
+ {
+ $child->set_label($self->{parent}->{lang}->{$label});
+ }
+ }
+ }
+
+ sub updateMenus
+ {
+ my ($self) = @_;
+
+ # Update labels which are collection dependant
+ # list for each item is: [parent, item name, label index in language]
+ foreach (
+ # Menu labels
+ [$self, 'viewAllItems', 'MenuViewAllItems'],
+ [$self, 'menuLend', 'MenuLend'],
+ [$self, 'duplicateItem', 'MenuDuplicate'],
+ [$self, 'newitem', 'MenuAddItem'],
+ [$self, 'deleteCurrentItem', 'MenuEditDeleteCurrent'],
+ [$self, 'selectAllItem', 'MenuEditSelectAllItems'],
+ [$self, 'defaultValues', 'MenuDefaultValues'],
+ # Context menu labels
+ [$self->{parent}, 'contextNewWindow', 'MenuNewWindow'],
+ [$self->{parent}, 'contextDuplicateItem', 'MenuDuplicate'],
+ [$self->{parent}, 'contextSelectAllItem', 'MenuEditSelectAllItems'],
+ [$self->{parent}, 'contextItemDelete', 'MenuEditDeleteCurrent'],
+ [$self->{parent}, 'contextViewAllItems', 'MenuViewAllItems'],
+ )
+ {
+ $self->updateItem($_->[0]->{$_->[1]}, $_->[2]);
+ }
+ }
+
+ sub initFilters
+ {
+ my ($self, $info) = @_;
+
+ $self->selectAll(1);
+ $self->block;
+ my $fieldsInfo = $self->{fieldsInfo};
+ foreach (keys %$info)
+ {
+ my $activeIdx = 0;
+ my $filtersInfo = $self->{filtersInfo}->{$_};
+ next if !$filtersInfo;
+
+ if ($fieldsInfo->{$_}->{type} eq 'options')
+ {
+ foreach my $valueInfo(@{$self->{model}->getValues($fieldsInfo->{$_}->{'values'})})
+ {
+ last if $valueInfo->{value} eq $info->{$_};
+ $activeIdx++;
+ }
+ $activeIdx++ if $activeIdx >= $fieldsInfo->{$_}->{separator};
+ }
+ elsif ($fieldsInfo->{$_}->{type} eq 'number')
+ {
+ #The value that means no check
+ my $boundary = $fieldsInfo->{$_}->{min};
+ $boundary = $fieldsInfo->{$_}->{max}
+ if ($filtersInfo->{type}->{comparison} =~ /^l/);
+ if ($info->{$_} != $boundary)
+ {
+ $activeIdx = 1;
+ $self->{numberValues}->{$_} = $info->{$_};
+ }
+ }
+ elsif ($fieldsInfo->{$_}->{type} eq 'date')
+ {
+ #The value that means no check
+ if ($info->{$_})
+ {
+ $activeIdx = 1;
+ $self->{dateValues}->{$_} = $info->{$_};
+ }
+ }
+ elsif (($fieldsInfo->{$_}->{type} eq 'history text')
+ || ($fieldsInfo->{$_}->{type} eq 'single list'))
+ {
+ my @values;
+ @values = @{$self->{parent}->{panel}->getValues($_)}
+ if ($fieldsInfo->{$_}->{type} eq 'history text');
+ @values = @{$self->{parent}->{panel}->getValues($_)->[0]}
+ if ($fieldsInfo->{$_}->{type} eq 'single list');
+ foreach my $value(@values)
+ {
+ last if $value eq $info->{$_};
+ $activeIdx++;
+ }
+ $activeIdx = 0 if $activeIdx >= $#values;
+ }
+ elsif ($fieldsInfo->{$_}->{type} eq 'yesno')
+ {
+ $activeIdx = 1;
+ $activeIdx = 0 if (($filtersInfo->{values} eq 'off') && ($info->{$_} == 1))
+ || (($filtersInfo->{values} eq 'on') && ($info->{$_} == 0));
+ $activeIdx = 2 if ($filtersInfo->{values} eq 'both') && ($info->{$_} == 0);
+ }
+
+ $self->{'menuFilter'.$_}->set_active($activeIdx);
+ $self->{'menuFilter'.$_}->get_active->set_active(1);
+ }
+
+ $self->unblock;
+ }
+
+ sub initExportImportList
+ {
+ my ($self, $model) = @_;
+
+ my $modelName = $model->getName;
+ #It will hide the export/import modules that don't support current model
+ # This code may be factorized.
+ foreach my $exporter(@GCExport::exportersArray)
+ {
+ my $item = $self->{exporters}->{$exporter->getName};
+ my @models = @{$exporter->getModels};
+ my $show = 0;
+ $show = 1 if !@models;
+ foreach (@models)
+ {
+ $show = 1 if $modelName eq $_;
+ last if $show;
+ }
+ $item->hide if !$show;
+ $item->show if $show;
+ }
+ foreach my $importer(@GCImport::importersArray)
+ {
+ my $item = $self->{importers}->{$importer->getName};
+ my @models = @{$importer->getModels};
+ my $show = 0;
+ $show = 1 if (!$importer->shouldBeHidden || !@models);
+ foreach (@models)
+ {
+ $show = 1 if $modelName eq $_;
+ last if $show;
+ }
+ $item->hide if !$show;
+ $item->show if $show;
+ }
+ }
+
+ sub createFilters
+ {
+ my ($self, $model, $fieldsInfo) = @_;
+ foreach (@{$self->{existingFilters}})
+ {
+ $self->{menuDisplay}->remove($_);
+ $_->destroy;
+ }
+
+ $self->{existingFilters} = [];
+ $self->{existingFiltersMenu} = [];
+ $self->{dynamicFilters} = {};
+ $self->{fieldsInfo} = $fieldsInfo;
+ $self->{filtersInfo} = {};
+ my $position = ($self->{parent}->{options}->tearoffMenus ? 1 : 0);
+ $self->createUserFilters($model, $position + 1);
+ foreach my $filter(@{$model->{filters}})
+ {
+ next if (!defined $filter->{quick}) || ($filter->{quick} ne 'true');
+ my $field = $filter->{field};
+ $self->{filtersInfo}->{$field} = $filter;
+ $self->{'menuFilter'.$field} = Gtk2::Menu->new;
+ $self->{'menuFilter'.$field}->set_accel_path("<main>/Filter/$field");
+ $self->{'menuFilter'.$field}->set_accel_group($self->{accel});
+
+ my $all = Gtk2::RadioMenuItem->new_with_mnemonic(undef,$self->{parent}->{lang}->{MenuNoFilter});
+ $self->{'group'.$field} = $all->get_group();
+ $self->{'menuFilter'.$field}->append($all);
+ $all->signal_connect('activate' => sub {
+ $self->changeFilter(shift, $field, '');
+ });
+
+ if (($fieldsInfo->{$field}->{type} eq 'history text') ||
+ ($fieldsInfo->{$field}->{type} eq 'single list'))
+ {
+ $self->{dynamicFilters}->{$field} = 1;
+ #$self->checkFilter($field);
+ }
+ elsif ($fieldsInfo->{$field}->{type} eq 'yesno')
+ {
+ $filter->{'values'} = 'both' if ! $filter->{'values'} ;
+ if (($filter->{'values'} eq 'on') || ($filter->{'values'} eq 'both'))
+ {
+ my $labelOn = $filter->{labelon} || 'CheckYes';
+ my $on = Gtk2::RadioMenuItem->new_with_mnemonic($self->{'group'.$field},
+ $model->getDisplayedText($labelOn));
+ $self->{'menuFilter'.$field}->append($on);
+ $on->signal_connect('activate' => sub {
+ $self->changeFilter(shift, $field, 1);
+ });
+ }
+ if (($filter->{'values'} eq 'off') || ($filter->{'values'} eq 'both'))
+ {
+ my $labelOff = $filter->{labeloff} || 'CheckNo';
+ my $off = Gtk2::RadioMenuItem->new_with_mnemonic($self->{'group'.$field},
+ $model->getDisplayedText($labelOff));
+ $self->{'menuFilter'.$field}->append($off);
+ $off->signal_connect('activate' => sub {
+ $self->changeFilter(shift, $field, 0);
+ });
+ }
+ }
+ elsif ($fieldsInfo->{$field}->{type} eq 'options')
+ {
+ $self->{dynamicFilters}->{$field} = 1
+ if $field eq $self->{parent}->{model}->{commonFields}->{borrower}->{name};
+ my $i = 0;
+ foreach my $valueInfo(@{$model->getValues($fieldsInfo->{$field}->{'values'})})
+ {
+ $self->{'menuFilter'.$field}->append(Gtk2::SeparatorMenuItem->new)
+ if (exists $fieldsInfo->{$field}->{separator})
+ && ($fieldsInfo->{$field}->{separator} == $i);
+ $i++;
+ next if $valueInfo->{displayed} eq '';
+ my $item = Gtk2::RadioMenuItem->new_with_mnemonic($self->{'group'.$field},
+ $valueInfo->{displayed});
+ $self->{'menuFilter'.$field}->append($item);
+ $item->signal_connect('activate' => sub {
+ $self->changeFilter(shift, $field, $valueInfo->{value});
+ });
+ }
+ }
+ elsif ($fieldsInfo->{$field}->{type} eq 'number')
+ {
+ my $item = Gtk2::RadioMenuItem->new_with_mnemonic($self->{'group'.$field},
+ $model->getDisplayedText($filter->{labelselect}));
+ $self->{'menuFilter'.$field}->append($item);
+ $item->signal_connect('activate' => sub {
+ my $widget = shift;
+ return if ! $widget->get_active;
+ return if $self->{deactivated};
+ my $title = $model->getDisplayedText($filter->{labelselect});
+ $title =~ s/_//g;
+ $title =~ s/\.\.\.//g;
+ my $dialog = new GCNumberEntryDialog($self->{parent},
+ $title,
+ $fieldsInfo->{$field}->{min},
+ $fieldsInfo->{$field}->{max},
+ $fieldsInfo->{$field}->{step});
+ $dialog->setValue($self->{numberValues}->{$field})
+ if $self->{numberValues} != undef;
+ my $value = $dialog->getUserValue;
+ if ($value >= 0)
+ {
+ $self->changeFilter($widget, $field, $value);
+ $self->{numberValues}->{$field} = $value;
+ }
+ });
+ }
+ elsif ($fieldsInfo->{$field}->{type} eq 'date')
+ {
+ my $item = Gtk2::RadioMenuItem->new_with_mnemonic($self->{'group'.$field},
+ $model->getDisplayedText($filter->{labelselect}));
+ $self->{'menuFilter'.$field}->append($item);
+ $item->signal_connect('activate' => sub {
+ my $widget = shift;
+ return if ! $widget->get_active;
+ return if $self->{deactivated};
+ my $title = $model->getDisplayedText($filter->{labelselect});
+ $title =~ s/_//g;
+ $title =~ s/\.\.\.//g;
+ my $dialog = new GCDateSelectionDialog($self->{parent});
+
+ $dialog->date(GCPreProcess::restoreDate($self->{dateValues}->{$field}))
+ if $self->{dateValues} != undef;
+ if ($dialog->show)
+ {
+ my $value = GCPreProcess::reverseDate($dialog->date);
+ $self->changeFilter($widget, $field, $value);
+ $self->{dateValues}->{$field} = $value;
+ }
+ });
+ }
+
+ my $label = $fieldsInfo->{$field}->{displayed};
+ $label = $model->getDisplayedText($filter->{label}) if $filter->{label};
+ $self->{'item'.$field} = Gtk2::MenuItem->new_with_mnemonic($label);
+ $self->{'item'.$field}->set_accel_path("<main>/Display/$field");
+ $self->{'item'.$field}->set_submenu($self->{'menuFilter'.$field});
+ $self->{menuDisplay}->insert($self->{'item'.$field}, $position);
+ $self->{'item'.$field}->show_all;
+
+ push @{$self->{existingFilters}}, $self->{'item'.$field};
+ push @{$self->{existingFiltersMenu}}, $self->{'menuFilter'.$field};
+
+ $position++;
+ }
+ }
+
+ sub createUserFilters
+ {
+ my ($self, $model, $position) = @_;
+ if (!defined $position)
+ {
+ # Here we need to find the correct position
+ $position = 0;
+ foreach ($self->{menuDisplay}->get_children)
+ {
+ $position++;
+ last if $_->isa('Gtk2::SeparatorMenuItem');
+ }
+ }
+ if ($self->{userFiltersMenu})
+ {
+ foreach ($self->{userFiltersMenu}->get_children)
+ {
+ $self->{userFiltersMenu}->remove($_);
+ $_->destroy;
+ }
+ $self->{menuDisplay}->remove($self->{userFiltersItem});
+ $self->{userFiltersMenu}->destroy;
+ $self->{userFiltersItem}->destroy;
+ $self->{userFiltersMenu} = 0;
+ }
+ return if !$model->getName;
+ my @userFilters = @{$model->getUserFilters};
+ $self->{userFiltersMenu} = new Gtk2::Menu;
+ # Setting the accel group to be able to use also shortcuts on user filters
+ $self->{userFiltersMenu}->set_accel_group($self->{accel});
+ $self->{userFiltersItem} = Gtk2::MenuItem->new_with_mnemonic($self->{parent}->{lang}->{MenuSavedSearches});
+ $self->{userFiltersItem}->set_accel_path('<main>/Display/SavedSearches');
+ $self->{userFiltersItem}->set_submenu($self->{userFiltersMenu});
+ $self->{menuDisplay}->insert($self->{userFiltersItem}, $position);
+ if (@userFilters)
+ {
+ foreach my $userFilter(@userFilters)
+ {
+ my $filter = Gtk2::MenuItem->new($userFilter->{name});
+ $filter->set_accel_path('<main>/Display/SavedSearches/'.$userFilter->{name});
+ $filter->signal_connect('activate' => sub {
+ my ($widget, $filter) = @_;
+ $self->selectAll(1);
+ $self->{parent}->setSearchWithTypes(info => $filter->{info},
+ mode => $filter->{mode},
+ regexp => $filter->{regexp},
+ case => $filter->{case},
+ ignoreDiacritics => $filter->{ignoreDiacritics});
+ }, $userFilter);
+ $self->{userFiltersMenu}->append($filter);
+ }
+ }
+ $self->{userFiltersMenu}->append(Gtk2::SeparatorMenuItem->new);
+ my $newUserFilter = Gtk2::MenuItem->new($self->{parent}->{lang}->{MenuSavedSearchesSave});
+ $newUserFilter->signal_connect('activate' => sub {
+ $self->{parent}->saveCurrentSearch;
+ });
+ $self->{userFiltersMenu}->append($newUserFilter);
+ my $editUserFilter = Gtk2::MenuItem->new($self->{parent}->{lang}->{MenuSavedSearchesEdit});
+ $editUserFilter->signal_connect('activate' => sub {
+ $self->{parent}->editSavedSearches;
+ });
+ $self->{userFiltersMenu}->append($editUserFilter);
+
+ $self->{userFiltersItem}->show_all;
+ $self->{menuDisplay}->show_all;
+ }
+
+ sub refreshFilters
+ {
+ my $self = shift;
+ foreach (keys %{$self->{dynamicFilters}})
+ {
+ $self->checkFilter($_);
+ }
+ }
+
+ sub checkFilter
+ {
+ my ($self, $field) = @_;
+ return if ! exists $self->{dynamicFilters}->{$field};
+ $self->{deactivated} = 1;
+ my $values = $self->{parent}->{panel}->getValues($field);
+ $values = $values->[0] if ref($values->[0]) eq 'ARRAY';
+ my $current = $self->{'menuFilter'.$field}->get_active->child->get_label;
+ my $first = 1;
+ foreach ($self->{'menuFilter'.$field}->get_children)
+ {
+ if ($first)
+ {
+ $first = 0;
+ $_->set_active(1);
+ }
+ else
+ {
+ $self->{'menuFilter'.$field}->remove($_);
+ }
+ }
+ my $active = 0;
+ my $i = 0;
+ foreach (@$values)
+ {
+ next if !$_;
+ my ($label, $value) = ($_, $_);
+ if (ref($_) eq 'HASH')
+ {
+ $label = $_->{displayed};
+ $value = $_->{value};
+ }
+ my $item = Gtk2::RadioMenuItem->new_with_mnemonic($self->{'group'.$field}, $label);
+ $self->{'menuFilter'.$field}->append($item);
+ $item->signal_connect('activate' => sub {
+ $self->changeFilter(shift, $field, $value);
+ });
+ if ($label eq $current)
+ {
+ $item->set_active(1);
+ $active = $i + 1;
+ }
+ $i++;
+ }
+ $self->{'menuFilter'.$field}->show_all;
+ $self->{'menuFilter'.$field}->set_active($active);
+
+ $self->{deactivated} = 0;
+ }
+
+ sub changeFilter
+ {
+ my ($self, $widget, $filter, $value) = @_;
+ return if $self->{deactivated};
+ return if ! $widget->get_active;
+ $self->{parent}->setFilter($filter, $value);
+ }
+
+ sub setSaveActive
+ {
+ my ($self, $value) = @_;
+ $self->{savedb}->set_sensitive($value);
+ }
+
+ sub setAddBookmarkActive
+ {
+ my ($self, $value) = @_;
+ $self->{addBookmark}->set_sensitive($value);
+ }
+
+ sub setCollectionLock
+ {
+ my ($self, $value) = @_;
+ $self->{menuEditLockItemsItem}->set_active(0);
+ }
+
+ sub new
+ {
+ my ($proto, $parent, $accelMapFile) = @_;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+ bless ($self, $class);
+
+ $self->{parent} = $parent;
+ $self->{accel} = Gtk2::AccelGroup->new();
+
+ ############################
+ # File Menu
+ ############################
+
+ $self->{menuFile} = Gtk2::Menu->new;
+ $self->{menuFile}->set_accel_path('<main>/File');
+ $self->{menuFile}->set_accel_group($self->{accel});
+
+ if ($parent->{options}->tearoffMenus)
+ {
+ my $fto = Gtk2::TearoffMenuItem->new();
+ $self->{menuFile}->append($fto);
+ }
+
+ my $newdb = Gtk2::ImageMenuItem->new_from_stock('gtk-new');
+ $newdb->set_accel_path('<main>/File/gtk-new');
+ $newdb->signal_connect ('activate' => sub {
+ $self->{parent}->newList;
+ });
+ $self->{menuFile}->append($newdb);
+
+ my $opendb = Gtk2::ImageMenuItem->new_from_stock('gtk-open');
+ $opendb->set_accel_path('<main>/File/gtk-open');
+ $opendb->signal_connect ('activate' => sub {
+ $self->{parent}->openList;
+ });
+ $self->{menuFile}->append($opendb);
+
+ $self->{menuFile}->append(Gtk2::SeparatorMenuItem->new);
+ ############################
+
+ $self->{savedb} = Gtk2::ImageMenuItem->new_from_stock('gtk-save');
+ $self->{savedb}->set_accel_path('<main>/File/gtk-save');
+ $self->{savedb}->signal_connect ('activate' => sub {
+ $self->{parent}->saveList;
+ });
+ $self->{menuFile}->append($self->{savedb});
+
+ my $saveasdb = Gtk2::ImageMenuItem->new_from_stock('gtk-save-as');
+ $saveasdb->set_accel_path('<main>/File/gtk-save-as');
+ $saveasdb->signal_connect ('activate' => sub {
+ $self->{parent}->saveAs;
+ });
+ $self->{menuFile}->append($saveasdb);
+
+
+ $self->{menuFile}->append(Gtk2::SeparatorMenuItem->new);
+ ############################
+
+ $self->{newitem} = Gtk2::ImageMenuItem->new_from_stock('gtk-add');
+ $self->{newitem}->set_accel_path('<main>/File/gtk-add');
+ $self->{newitem}->signal_connect ('activate' => sub {
+ $self->{parent}->newItem;
+ });
+ $self->{menuFile}->append($self->{newitem});
+
+ my $properties = Gtk2::ImageMenuItem->new_from_stock('gtk-properties');
+ $properties->set_accel_path('<main>/File/gtk-properties');
+ $properties->signal_connect ('activate' => sub {
+ $self->{parent}->properties;
+ });
+ $self->{menuFile}->append($properties);
+
+ if ($GCStats::statisticsActivated)
+ {
+ my $statistics = Gtk2::ImageMenuItem->new_with_mnemonic($parent->{lang}->{MenuStats});
+ $statistics->set_accel_path('<main>/File/Stats');
+ $statistics->signal_connect ('activate' => sub {
+ $self->{parent}->stats;
+ });
+ $self->{menuFile}->append($statistics);
+ }
+
+ $self->{menuLend} = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuLend});
+ $self->{menuLend}->set_accel_path('<main>/File/Borrowers');
+ $self->{menuLend}->signal_connect ('activate' => sub {
+ $self->{parent}->showBorrowed;
+ });
+ $self->{menuFile}->append($self->{menuLend});
+
+ $self->{menuFile}->append(Gtk2::SeparatorMenuItem->new);
+ ############################
+
+ $self->{menuHistoryItem} = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuHistory});
+ $self->{menuHistoryItem}->set_accel_path('<main>/File/History');
+ $self->{menuHistory} = Gtk2::Menu->new();
+ addHistoryMenu($self);
+ $self->{menuFile}->append($self->{menuHistoryItem});
+
+ $self->{menuFile}->append(Gtk2::SeparatorMenuItem->new);
+ ############################
+
+ my $importItem = Gtk2::ImageMenuItem->new_from_stock('gtk-convert');
+ $importItem->set_accel_path('<main>/File/gtk-convert');
+ $self->{menuImport} = Gtk2::Menu->new;
+ $self->{menuImport}->set_accel_path('<main>/Import');
+ $self->{menuImport}->set_accel_group($self->{accel});
+ $self->{importers} = {};
+ my $langName = $parent->{options}->lang;
+ foreach my $importer(@GCImport::importersArray)
+ {
+ $importer->setLangName($langName);
+ my $name = $importer->getName;
+ my $item = Gtk2::MenuItem->new_with_mnemonic($name);
+ $item->signal_connect ('activate' => sub {
+ $self->{parent}->import($importer);
+ });
+ $self->{importers}->{$name} = $item;
+ }
+ foreach my $importerName(sort keys %{$self->{importers}})
+ {
+ $self->{menuImport}->append($self->{importers}->{$importerName});
+ }
+ $importItem->set_submenu($self->{menuImport});
+ $self->{menuFile}->append($importItem);
+
+ my $exportItem = Gtk2::ImageMenuItem->new_from_stock('gtk-revert-to-saved');
+ $self->{menuExport} = Gtk2::Menu->new;
+ $self->{menuExport}->set_accel_path('<main>/Export');
+ $self->{menuExport}->set_accel_group($self->{accel});
+ $self->{exporters} = {};
+ foreach my $exporter(@GCExport::exportersArray)
+ {
+ $exporter->setLangName($langName);
+ my $item = Gtk2::MenuItem->new_with_mnemonic($exporter->getName);
+ $item->signal_connect ('activate' => sub {
+ $self->{parent}->export($exporter);
+ });
+ $self->{exporters}->{$exporter->getName} = $item;
+ }
+ foreach my $exportName(sort keys %{$self->{exporters}})
+ {
+ $self->{menuExport}->append($self->{exporters}->{$exportName});
+ }
+ $exportItem->set_submenu($self->{menuExport});
+ $self->{menuFile}->append($exportItem);
+
+ $self->{menuFile}->append(Gtk2::SeparatorMenuItem->new);
+ ############################
+
+ my $leave = Gtk2::ImageMenuItem->new_from_stock('gtk-quit');
+ $leave->set_accel_path('<main>/File/gtk-quit');
+ $self->{menuFile}->append($leave);
+ $leave->signal_connect('activate' ,sub {
+ $self->{parent}->leave;
+ });
+
+ my $fileitem = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuFile});
+ $fileitem->set_submenu($self->{menuFile});
+
+ $self->append($fileitem);
+
+ ############################
+ # Edit Menu
+ ############################
+ $self->{menuEdit} = Gtk2::Menu->new;
+ $self->{menuEdit}->set_accel_path('<main>/Edit');
+ $self->{menuEdit}->set_accel_group($self->{accel});
+
+ if ($parent->{options}->tearoffMenus)
+ {
+ my $eto = Gtk2::TearoffMenuItem->new();
+ $self->{menuEdit}->append($eto);
+ }
+
+ $self->{duplicateItem} = Gtk2::ImageMenuItem->new_from_stock('gtk-dnd');
+ $self->{duplicateItem}->set_accel_path('<main>/Edit/gtk-dnd');
+ $self->{duplicateItem}->signal_connect('activate' , sub {
+ $self->{parent}->duplicateItem;
+ });
+ $self->{menuEdit}->append($self->{duplicateItem});
+
+ $self->{selectAllItem} = Gtk2::ImageMenuItem->new_from_stock('gtk-select-all');
+ $self->{selectAllItem}->set_accel_path('<main>/Edit/gtk-select-all');
+ $self->{selectAllItem}->signal_connect('activate' , sub {
+ $self->{parent}->selectAll;
+ });
+ $self->{menuEdit}->append($self->{selectAllItem});
+
+ $self->{deleteCurrentItem} = Gtk2::ImageMenuItem->new_from_stock('gtk-delete');
+ $self->{deleteCurrentItem}->set_accel_path('<main>/Edit/gtk-delete');
+ $self->{deleteCurrentItem}->signal_connect('activate' , sub {
+ $self->{parent}->deleteCurrentItem;
+ });
+ $self->{menuEdit}->append($self->{deleteCurrentItem});
+
+ $self->{menuEdit}->append(Gtk2::SeparatorMenuItem->new);
+ ############################
+
+ $self->{editFieldsItem} = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuEditFields});
+ $self->{editFieldsItem}->set_accel_path('<main>/Edit/Collection');
+ $self->{editFieldsItem}->signal_connect('activate' , sub {
+ $self->{parent}->editModel;
+ });
+ $self->{menuEdit}->append($self->{editFieldsItem});
+
+ $self->{menuEdit}->append(Gtk2::SeparatorMenuItem->new);
+ ############################
+
+ my $queryReplaceItem = Gtk2::ImageMenuItem->new_from_stock('gtk-find-and-replace');
+ $queryReplaceItem->set_accel_path('<main>/Edit/gtk-find-and-replace');
+ $queryReplaceItem->signal_connect('activate' , sub {
+ $self->{parent}->queryReplace;
+ });
+ $self->{menuEdit}->append($queryReplaceItem);
+
+ $self->{menuEdit}->append(Gtk2::SeparatorMenuItem->new);
+ ############################
+
+ my $lockItemsItem = Gtk2::CheckMenuItem->new_with_mnemonic($parent->{lang}->{MenuEditLockItems});
+ $lockItemsItem->set_accel_path('<main>/Edit/Lock');
+ $self->{menuEdit}->append($lockItemsItem);
+ #$lockItemsItem->set_active($parent->{items}->getLock);
+ $lockItemsItem->signal_connect('activate' , sub {
+ my $parent = $self;
+ my $self = shift;
+ return if $parent->{deactivated};
+ $parent->{parent}->setLock($self->get_active);
+ $self->toggled();
+ },$lockItemsItem);
+ $self->{menuEditLockItemsItem}=$lockItemsItem;
+ $lockItemsItem->{parent}=$self->{menuEdit};
+
+ my $editItem = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuEdit});
+ $editItem->set_submenu($self->{menuEdit});
+ $self->append($editItem);
+
+ ############################
+ # Display Menu
+ ############################
+ $self->{menuDisplay} = Gtk2::Menu->new;
+ $self->{menuDisplay}->set_accel_path('<main>/Display');
+ $self->{menuDisplay}->set_accel_group($self->{accel});
+
+ if ($parent->{options}->tearoffMenus)
+ {
+ my $dto = Gtk2::TearoffMenuItem->new;
+ $self->{menuDisplay}->append($dto);
+ }
+ ############################
+
+ $self->{menuDisplay}->append(Gtk2::SeparatorMenuItem->new);
+
+ my $search = Gtk2::ImageMenuItem->new_from_stock('gtk-find');
+ $search->set_accel_path('<main>/Display/gtk-find');
+ $search->signal_connect('activate' , sub {
+ $self->{parent}->search('all');
+ });
+ $self->{menuDisplay}->append($search);
+
+ my $advancedSearch = Gtk2::ImageMenuItem->new_with_mnemonic($parent->{lang}->{MenuAdvancedSearch});
+ $advancedSearch->set_accel_path('<main>/Display/Advanced');
+ my $advancedImage = Gtk2::Image->new_from_stock('gtk-find', 'menu');
+ $advancedSearch->set_image($advancedImage);
+ $advancedSearch->signal_connect('activate' , sub {
+ $self->{parent}->advancedSearch;
+ });
+ $self->{menuDisplay}->append($advancedSearch);
+
+ my $random = Gtk2::ImageMenuItem->new_from_stock('gtk-execute');
+ $random->set_accel_path('<main>/Display/gtk-execute');
+ $random->signal_connect('activate' , sub {
+ $self->{parent}->randomItem;
+ });
+ $self->{menuDisplay}->append($random);
+
+ $self->{menuDisplay}->append(new Gtk2::SeparatorMenuItem);
+ ############################
+
+ $self->{'viewAllItems'} = Gtk2::ImageMenuItem->new_with_mnemonic($parent->{lang}->{MenuViewAllItems});
+ $self->{'viewAllItems'}->set_accel_path('<main>/Display/All');
+ my $refreshImage = Gtk2::Image->new_from_stock('gtk-refresh', 'menu');
+ $self->{'viewAllItems'}->set_image($refreshImage);
+ $self->{'viewAllItems'}->signal_connect('activate' , sub {
+ $self->selectAll
+ });
+ $self->{menuDisplay}->append($self->{'viewAllItems'});
+
+ $self->{displayItem} = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuDisplay});
+ $self->{displayItem}->set_submenu($self->{menuDisplay});
+
+ $self->append($self->{displayItem});
+
+ ############################
+ # Configuration Menu
+ ############################
+ $self->{menuConfig} = Gtk2::Menu->new;
+ $self->{menuConfig}->set_accel_path('<main>/Config');
+ $self->{menuConfig}->set_accel_group($self->{accel});
+
+ if ($parent->{options}->tearoffMenus)
+ {
+ my $cto = Gtk2::TearoffMenuItem->new;
+ $self->{menuConfig}->append($cto);
+ }
+
+ my $options = Gtk2::ImageMenuItem->new_from_stock('gtk-preferences');
+ $options->set_accel_path('<main>/Config/gtk-preferences');
+ $options->signal_connect('activate' , sub {
+ my ($widget, $window) = @_;
+ $window->options;
+ }, $self->{parent});
+ $self->{menuConfig}->append($options);
+
+ $self->{displayItem} = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuDisplayMenu});
+ $self->{displayItem}->set_accel_path('<main>/Config/DisplayItem');
+ #$self->{displayItem}->set_submenu($self->createDisplayMenu);
+ $self->attachDisplayMenu;
+ $self->{menuConfig}->append($self->{displayItem});
+
+ my $toolbarConfig = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuToolbarConfiguration});
+ $toolbarConfig->set_accel_path('<main>/Config/Toolbar');
+ $toolbarConfig->signal_connect ('activate' => sub {
+ $self->{parent}->toolbarOptions;
+ });
+ $self->{menuConfig}->append($toolbarConfig);
+
+ $self->{menuConfig}->append(new Gtk2::SeparatorMenuItem);
+
+ my $displayOptions = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuDisplayOptions});
+ $displayOptions->set_accel_path('<main>/Config/Display');
+ $displayOptions->signal_connect ('activate' => sub {
+ $self->{parent}->displayOptions;
+ });
+ $self->{menuConfig}->append($displayOptions);
+
+ $self->{defaultValues} = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuDefaultValues});
+ $self->{defaultValues}->set_accel_path('<main>/Config/DefaultValues');
+ $self->{defaultValues}->signal_connect ('activate' => sub {
+ $self->{parent}->setDefaultValues;
+ });
+ $self->{menuConfig}->append($self->{defaultValues});
+
+ my $borrowers = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuBorrowers});
+ $borrowers->set_accel_path('<main>/Config/Borrowers');
+ $borrowers->signal_connect ('activate' => sub {
+ $self->{parent}->borrowers;
+ });
+ $self->{menuConfig}->append($borrowers);
+
+ my $configitem = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuConfiguration});
+ $configitem->set_submenu($self->{menuConfig});
+ $self->append($configitem);
+
+ ############################
+ # Bookmarks Menu
+ ############################
+ $self->{menuBookmarks} = Gtk2::Menu->new;
+ $self->{menuBookmarks}->set_accel_path('<main>/Bookmarks');
+ $self->{menuBookmarks}->set_accel_group($self->{accel});
+
+ if ($parent->{options}->tearoffMenus)
+ {
+ my $bto = Gtk2::TearoffMenuItem->new;
+ $self->{menuBookmarks}->append($bto);
+ }
+
+ $self->{addBookmark} = Gtk2::ImageMenuItem->new_with_mnemonic($parent->{lang}->{MenuBookmarksAdd});
+ my $addBookmarkImage = Gtk2::Image->new_from_stock('gtk-add', 'menu');
+ $self->{addBookmark}->set_image($addBookmarkImage);
+ $self->{addBookmark}->set_accel_path('<main>/Bookmarks/Add');
+ $self->{addBookmark}->signal_connect('activate' , sub {
+ $self->{parent}->addBookmark;
+ });
+ $self->{menuBookmarks}->append($self->{addBookmark});
+
+ my $editBookmark = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuBookmarksEdit});
+ $editBookmark->set_accel_path('<main>/Bookmarks/Edit');
+ $editBookmark->signal_connect('activate' , sub {
+ $self->{parent}->editBookmark;
+ });
+ $self->{menuBookmarks}->append($editBookmark);
+
+ $self->{menuBookmarks}->append(new Gtk2::SeparatorMenuItem);
+
+ my $bookmarksitem = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuBookmarks});
+ $bookmarksitem->set_submenu($self->{menuBookmarks});
+ $self->append($bookmarksitem);
+
+ ############################
+ # Help Menu
+ ############################
+ $self->{menuHelp} = Gtk2::Menu->new;
+ $self->{menuHelp}->set_accel_path('<main>/Help');
+ $self->{menuHelp}->set_accel_group($self->{accel});
+
+ if ($parent->{options}->tearoffMenus)
+ {
+ my $hto = Gtk2::TearoffMenuItem->new;
+ $self->{menuHelp}->append($hto);
+ }
+
+ my $help = Gtk2::ImageMenuItem->new_from_stock('gtk-help');
+ $help->set_accel_path('<main>/Help/Content');
+ $help->signal_connect('activate' , sub {
+ my ($widget, $window) = @_;
+ $window->help;
+ }, $self->{parent});
+ $self->{menuHelp}->append($help);
+ my $plugins = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuAllPlugins});
+ $plugins->set_accel_path('<main>/Help/Plugins');
+ $plugins->signal_connect ('activate' => sub {
+ $self->{parent}->showAllPlugins;
+ });
+ $self->{menuHelp}->append($plugins);
+ my $depend = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{InstallDependencies});
+ $depend->set_accel_path('<main>/Help/Dependencies');
+ $depend->signal_connect ('activate' => sub {
+ $self->{parent}->showDependencies;
+ });
+ $self->{menuHelp}->append($depend);
+ my $bug = Gtk2::ImageMenuItem->new_with_mnemonic($parent->{lang}->{MenuBugReport});
+ $bug->set_accel_path('<main>/Help/Bug');
+ $bug->signal_connect('activate' , sub {
+ my ($widget, $window) = @_;
+ $window->reportBug;
+ }, $self->{parent});
+ $self->{menuHelp}->append($bug);
+ my $about = Gtk2::ImageMenuItem->new_from_stock('gtk-about');
+ $about->set_accel_path('<main>/Help/gtk-about');
+ $about->signal_connect('activate' , sub {
+ my ($widget, $window) = @_;
+ $window->about;
+ }, $self->{parent});
+ $self->{menuHelp}->append($about);
+
+ my $helpitem = Gtk2::MenuItem->new_with_mnemonic($parent->{lang}->{MenuHelp});
+ $helpitem->set_submenu($self->{menuHelp});
+ $self->append($helpitem);
+
+ $parent->add_accel_group($self->{accel});
+
+ $self->{deactivateFilters} = 0;
+ $self->{contextUpdating} = 0;
+
+ $self->setSaveActive(0);
+
+ $self->{AccelMapFile} = $accelMapFile;
+ if (-f $accelMapFile)
+ {
+ Gtk2::AccelMap->load($accelMapFile);
+ }
+ else
+ {
+ $self->restoreDefaultAccels;
+ }
+ $self->get_settings->set(gtk_can_change_accels => 1);
+
+ return $self;
+
+ }
+
+ sub save
+ {
+ my $self = shift;
+ Gtk2::AccelMap->save($self->{AccelMapFile});
+ }
+
+ sub restoreDefaultAccels
+ {
+ my $self = shift;
+
+ Gtk2::AccelMap->foreach(undef, sub {
+ my ($path, $key, $modifier, $changed) = @_;
+ if ($path =~ m|(gtk-.*?)$|)
+ {
+ my $stockItem = Gtk2::Stock->lookup($1);
+ Gtk2::AccelMap->change_entry($path,
+ $stockItem->{keyval},
+ $stockItem->{modifier},
+ 1);
+ }
+ else
+ {
+ Gtk2::AccelMap->change_entry($path,
+ undef,
+ [],
+ 1);
+ }
+ });
+
+ Gtk2::AccelMap->change_entry('<main>/Bookmarks/Add',
+ ord('d'),
+ 'control-mask',
+ 1);
+
+
+ return $self;
+ }
+
+ sub setLock
+ {
+ my ($self, $value) = @_;
+ $self->block;
+ $self->{menuEditLockItemsItem}->set_active($value);
+ $self->unblock;
+ }
+
+ sub selectAll
+ {
+ my ($self, $noRefresh) = @_;
+
+ $self->block;
+ $self->{parent}->removeSearch($noRefresh);
+
+ foreach (@{$self->{existingFiltersMenu}})
+ {
+ $_->set_active(0);
+ $_->get_active->set_active(1);
+ }
+ $self->unblock;
+ }
+
+ sub block
+ {
+ my $self = shift;
+
+ $self->{parent}->blockListUpdates(1);
+ $self->{deactivated} = 1;
+ }
+
+ sub unblock
+ {
+ my $self = shift;
+
+ $self->{deactivated} = 0;
+ $self->{parent}->blockListUpdates(0);
+ }
+
+ sub attachDisplayMenu
+ {
+ my ($self, $newParent) = @_;
+
+ $newParent = $self->{displayItem}
+ if !$newParent;
+
+ my $displayMenu;
+ if ($self->{displayMenu})
+ {
+ $displayMenu = $self->{displayMenu};
+ $displayMenu->detach;
+ }
+ else
+ {
+ $displayMenu = Gtk2::Menu->new;
+ $displayMenu->set_accel_path('<main>/Config/DisplayMenu');
+ $displayMenu->set_accel_group($self->{accel});
+
+ my $fullScreen = Gtk2::CheckMenuItem->new_with_mnemonic($self->{parent}->{lang}->{MenuDisplayFullScreen});
+ $fullScreen->set_accel_path('<main>/Config/DisplayMenu/Fullscreen');
+ $fullScreen->signal_connect ('activate' => sub {
+ my $parent = $self;
+ my $self = shift;
+ $parent->{parent}->setFullScreen($self->get_active);
+ $self->toggled();
+ }, $fullScreen);
+ $displayMenu->append($fullScreen);
+
+ $displayMenu->append(new Gtk2::SeparatorMenuItem);
+
+ my $menuBar = Gtk2::CheckMenuItem->new_with_mnemonic($self->{parent}->{lang}->{MenuDisplayMenuBar});
+ $menuBar->set_accel_path('<main>/Config/DisplayMenu/MenuBar');
+ $menuBar->set_active($self->{parent}->{options}->displayMenuBar);
+ $menuBar->signal_connect ('activate' => sub {
+ my $parent = $self;
+ my $self = shift;
+ $parent->{parent}->setDisplayMenuBar($self->get_active);
+ $self->toggled();
+ }, $menuBar);
+ $displayMenu->append($menuBar);
+
+ $self->{displayToolBar} = Gtk2::CheckMenuItem->new_with_mnemonic($self->{parent}->{lang}->{MenuDisplayToolBar});
+ $self->{displayToolBar}->set_accel_path('<main>/Config/DisplayMenu/ToolBar');
+ $self->{displayToolBar}->set_active($self->{parent}->{options}->toolbar);
+ $self->{displayToolBar}->signal_connect ('activate' => sub {
+ my $parent = $self;
+ my $self = shift;
+ return if !$self->{acceptEvents};
+ my $value = $self->get_active;
+ # If activated, we set it to the system setting
+ $value = 3
+ if $value;
+ $parent->{parent}->setDisplayToolBar($value);
+ $self->toggled();
+ }, $self->{displayToolBar});
+ $self->{displayToolBar}->{acceptEvents} = 1;
+ $displayMenu->append($self->{displayToolBar});
+
+ my $statusBar = Gtk2::CheckMenuItem->new_with_mnemonic($self->{parent}->{lang}->{MenuDisplayStatusBar});
+ $statusBar->set_accel_path('<main>/Config/DisplayMenu/StatusBar');
+ $statusBar->set_active($self->{parent}->{options}->status);
+ $statusBar->signal_connect ('activate' => sub {
+ my $parent = $self;
+ my $self = shift;
+ $parent->{parent}->setDisplayStatusBar($self->get_active);
+ $self->toggled();
+ }, $statusBar);
+ $displayMenu->append($statusBar);
+
+ $self->{displayMenu} = $displayMenu;
+ }
+
+ $newParent->set_submenu($displayMenu);
+ $newParent->show_all;
+ #return $self->{displayMenu};
+ }
+
+ sub setDisplayToolbarState
+ {
+ my ($self, $value) = @_;
+ #$self->{displayToolBar}->{acceptEvents} = 0;
+ $self->{displayToolBar}->set_active($value);
+ $self->{displayToolBar}->{acceptEvents} = 1;
+ }
+}
+
+{
+ package GCToolBar;
+ use base 'Gtk2::Toolbar';
+
+ our $CONFIGURATION_FILE = 'Toolbar';
+ our @DEFAULT_CONTROLS = (
+ 'gtk-add', 'gtk-save', 'gtk-preferences',
+ 'ToolbarSeparator',
+ 'gtk-find', 'gtk-refresh', 'gtk-execute', 'gtk-media-play',
+ 'ToolbarSeparator',
+ 'ToolbarGroupBy'
+ );
+
+ sub new
+ {
+ my ($proto, $parent) = @_;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+
+ bless($self, $class);
+
+ $self->{parent} = $parent;
+ $self->{lang} = $parent->{lang};
+
+ $self->set_name('GCToolbar');
+ $self->set_show_arrow (1);
+
+ $self->{configFile} = $ENV{GCS_CONFIG_HOME}.'/'.$GCToolBar::CONFIGURATION_FILE;
+
+ $self->{stockIdToWidget} = {
+ 'gtk-add' => {
+ tooltip => $self->{lang}->{NewItemTooltip},
+ callback => sub {$parent->newItem}
+ },
+ 'gtk-save' => {
+ tooltip => $self->{lang}->{SaveListTooltip},
+ callback => sub {$parent->saveList}
+ },
+ 'gtk-preferences' => {
+ tooltip => $self->{lang}->{PreferencesTooltip},
+ callback => sub {$parent->options}
+ },
+ 'gtk-find' => {
+ tooltip => $self->{lang}->{SearchTooltip},
+ callback => sub {$parent->search('all')}
+ },
+ 'gtk-refresh' => {
+ tooltip => $self->{lang}->{ToolbarAllTooltip},
+ callback => sub {$parent->viewAllItems}
+ },
+ 'gtk-execute' => {
+ tooltip => $self->{lang}->{RandomTooltip},
+ callback => sub {$parent->randomItem}
+ },
+ 'gtk-media-play' => {
+ tooltip => $self->{lang}->{PlayTooltip},
+ callback => sub {$parent->playItem}
+ },
+ 'gtk-new' => {
+ tooltip => undef,
+ callback => sub {$parent->newList}
+ },
+ 'gtk-open' => {
+ tooltip => undef,
+ callback => sub {$parent->openList}
+ },
+ 'gtk-properties' => {
+ tooltip => undef,
+ callback => sub {$parent->properties}
+ },
+ 'gtk-quit' => {
+ tooltip => undef,
+ callback => sub {$parent->leave}
+ },
+ 'gtk-dnd' => {
+ tooltip => undef,
+ callback => sub {$parent->duplicateItem}
+ },
+ 'gtk-delete' => {
+ tooltip => undef,
+ callback => sub {$parent->deleteCurrentItem}
+ },
+ 'gtk-find-and-replace' => {
+ tooltip => undef,
+ callback => sub {$parent->queryReplace}
+ },
+ 'gtk-help' => {
+ tooltip => undef,
+ callback => sub {$parent->help}
+ },
+ };
+
+ $self->loadControls;
+
+ $self->{blocked} = 1;
+ $self->setSaveActive(0);
+ $self->{showFieldsSelection} = 1;
+
+ return $self;
+ }
+
+ sub loadControls
+ {
+ my $self = shift;
+ my @controls;
+ if (! -f $self->{configFile})
+ {
+ @controls = @GCToolBar::DEFAULT_CONTROLS;
+ }
+ else
+ {
+ open CONFIG, $self->{configFile};
+ my @array;
+ foreach (<CONFIG>)
+ {
+ s/\s+$//;
+ push @controls, $_;
+ }
+ close CONFIG;
+ }
+ foreach (@controls)
+ {
+ if (/^gtk-/)
+ {
+ $self->{controls}->{$_} = Gtk2::ToolButton->new_from_stock($_);
+
+ # Set the important property on the add and save buttons
+ # (shows text in toolbar, depending on gtk settings)
+ if (/add|save/)
+ {
+ $self->{controls}->{$_}->set_is_important(1);
+ }
+
+ $self->{controls}->{$_}->signal_connect('clicked' => $self->{stockIdToWidget}->{$_}->{callback});
+ $self->{parent}->{tooltips}->set_tip($self->{controls}->{$_}, $self->{stockIdToWidget}->{$_}->{tooltip}, '')
+ if $self->{stockIdToWidget}->{$_}->{tooltip};
+ $self->insert($self->{controls}->{$_}, -1);
+
+ }
+ elsif ($_ eq 'ToolbarSeparator')
+ {
+ $self->insert(Gtk2::SeparatorToolItem->new, -1);
+ }
+ else
+ {
+ if ($_ eq 'ToolbarGroupBy')
+ {
+ $self->{controls}->{groupLabel} = new Gtk2::Label($self->{lang}->{ToolbarGroupBy});
+ $self->{controls}->{groupOption} = new GCFieldSelector(0, undef, 1);
+ $self->{controls}->{groupOption}->set_focus_on_click(0);
+ $self->{controls}->{groupOption}->signal_connect('changed' => sub {
+ return if $self->{blocked};
+ my $field = $self->{controls}->{groupOption}->getValue;
+ return if $self->{currentGroupField} eq $field;
+ $self->{parent}->setGrouping($field);
+ });
+ my $groupVBox = new Gtk2::VBox(0,0);
+ $groupVBox->set_border_width(0);
+ $groupVBox->pack_start($self->{controls}->{groupOption}, 1, 0, 0);
+ $self->{parent}->{tooltips}->set_tip($self->{controls}->{groupOption}, $self->{lang}->{ToolbarGroupByTooltip}, '');
+ my $groupBox = new Gtk2::HBox(0,0);
+ $groupBox->pack_start($self->{controls}->{groupLabel}, 0, 0, 0);
+ $groupBox->pack_start($groupVBox, 1, 1, $GCUtils::halfMargin);
+ my $groupItem = new Gtk2::ToolItem;
+ $groupItem->add($groupBox);
+ $self->insert($groupItem, -1);
+ }
+ elsif ($_ eq 'OptionsView')
+ {
+ my %views = %{$self->{lang}->{OptionsViews}};
+ $self->{controls}->{viewOption} = new GCMenuList;
+ my @viewsOptions = map {{value => $_, displayed => $views{$_}}}
+ (sort keys %views);
+ $self->{controls}->{viewOption}->setValues(\@viewsOptions);
+ $self->{controls}->{viewOption}->signal_connect('changed' => sub {
+ return if $self->{blocked};
+ $self->{parent}->{options}->view($self->{controls}->{viewOption}->getValue);
+ $self->{parent}->setItemsList(0, 1);
+ });
+ my $listViewBox = new Gtk2::VBox(0,0);
+ $listViewBox->set_border_width(0);
+ $listViewBox->pack_start($self->{controls}->{viewOption}, 1, 0, 0);
+ my $viewItem = new Gtk2::ToolItem;
+ $viewItem->add($listViewBox);
+ $self->insert($viewItem, -1);
+ }
+ elsif ($_ eq 'OptionsLayout')
+ {
+ $self->{controls}->{layoutOption} = new GCMenuList;
+ $self->{controls}->{layoutOption}->signal_connect('changed' => sub {
+ return if $self->{blocked};
+ $self->{model}->{preferences}->layout($self->{controls}->{layoutOption}->getValue);
+ $self->{parent}->changePanel(0, 0);
+ });
+ my $layoutBox = new Gtk2::VBox(0,0);
+ $layoutBox->set_border_width(0);
+ $layoutBox->pack_start($self->{controls}->{layoutOption}, 1, 0, 0);
+ my $layoutItem = new Gtk2::ToolItem;
+ $layoutItem->add($layoutBox);
+ $self->insert($layoutItem, -1);
+ }
+ elsif ($_ eq 'MenuSavedSearches')
+ {
+ $self->{controls}->{userFiltersOption} = new GCMenuList;
+ $self->{controls}->{userFiltersOption}->setTitle($self->{parent}->{lang}->{MenuSavedSearches});
+ $self->{controls}->{userFiltersOption}->signal_connect('changed' => sub {
+ return if $self->{blocked};
+ my $idx = $self->{controls}->{userFiltersOption}->getValue;
+ $self->{controls}->{userFiltersOption}->{changeInProgress} = 1;
+ if ($idx == -1)
+ {
+ $self->{parent}->removeSearch(0);
+ }
+ else
+ {
+ $self->{parent}->removeSearch(1);
+ $self->{parent}->setSearchWithTypes(%{$self->{userFilters}->[$idx]});
+ }
+ $self->{controls}->{userFiltersOption}->{changeInProgress} = 0;
+ });
+
+ my $filterBox = new Gtk2::VBox(0,0);
+ $filterBox->set_border_width(0);
+ $filterBox->pack_start($self->{controls}->{userFiltersOption}, 1, 0, 0);
+ my $filterItem = new Gtk2::ToolItem;
+ $filterItem->add($filterBox);
+ $self->insert($filterItem, -1);
+ }
+ elsif ($_ eq 'ToolbarQuickSearch')
+ {
+ my $quickBox = new Gtk2::HBox(0,0);
+ $self->{controls}->{quickLabel} = new Gtk2::Label($self->{lang}->{ToolbarQuickSearchLabel});
+ $quickBox->pack_start($self->{controls}->{quickLabel}, 0, 0, 0);
+
+ $self->{controls}->{quickEntry} = new GCShortText;
+ $self->{controls}->{quickEntry}->signal_connect('activate' => sub {
+ $self->{parent}->setQuickSearch($self->{controls}->{quickFields}->getValue,
+ $self->{controls}->{quickEntry}->getValue);
+ $self->{controls}->{quickEntry}->grab_focus;
+ });
+
+ $self->{controls}->{quickFields} = new GCFieldSelector(0, undef, 0, 1, 1);
+ $self->{controls}->{quickFields}->set_focus_on_click(0);
+
+ # Without 2 handlers below, the focus goes out of the toolbar when
+ # pressing Tab or Shift-Tab
+ $self->{controls}->{quickEntry}->signal_connect('key-press-event' => sub {
+ my ($widget, $event) = @_;
+ my $key = Gtk2::Gdk->keyval_name($event->keyval);
+ if ($key eq 'Tab')
+ {
+ $self->{controls}->{quickFields}->grab_focus;
+ return 1;
+ }
+ # Let key be managed by Gtk2
+ return 0;
+ });
+ $self->{controls}->{quickFields}->signal_connect('key-press-event' => sub {
+ my ($widget, $event) = @_;
+ my $key = Gtk2::Gdk->keyval_name($event->keyval);
+ my $state = $event->get_state;
+ if (($key =~ /Tab$/) && ($state =~ /shift-mask/))
+ {
+ $self->{controls}->{quickEntry}->grab_focus;
+ return 1;
+ }
+ # Let key be managed by Gtk2
+ return 0;
+ });
+ $quickBox->pack_start($self->{controls}->{quickEntry}, 0, 0, $GCUtils::halfMargin);
+ my $quickFieldsBox = new Gtk2::VBox(0,0);
+ $quickFieldsBox->set_border_width(0);
+ $quickFieldsBox->pack_start($self->{controls}->{quickFields}, 1, 0, 0);
+ $quickBox->pack_start($quickFieldsBox, 0, 0, 0);
+ $self->{parent}->{tooltips}->set_tip($self->{controls}->{quickEntry}, $self->{lang}->{ToolbarQuickSearchTooltip}, '');
+ $self->{parent}->{tooltips}->set_tip($self->{controls}->{quickFields}, $self->{lang}->{ToolbarQuickSearchTooltip}, '');
+ my $quickItem = new Gtk2::ToolItem;
+ $quickItem->add($quickBox);
+ $self->insert($quickItem, -1);
+ }
+ }
+ }
+ my $separator = Gtk2::SeparatorToolItem->new;
+ $separator->set_expand(1);
+ $separator->set_draw(0);
+
+ my $logoPixbuf = Gtk2::Gdk::Pixbuf->new_from_file($self->{parent}->{logosDir}.'/button.png');
+ my ($width, $height) = Gtk2::IconSize->lookup($self->get_icon_size);
+ $logoPixbuf = GCUtils::scaleMaxPixbuf($logoPixbuf, $width, $height);
+
+ my $logo = Gtk2::Image->new_from_pixbuf($logoPixbuf);
+ my $logoButton = new Gtk2::Button;
+ $logoButton->add($logo);
+ my $logoItem = new Gtk2::ToolItem;
+ $logoItem->add($logoButton);
+ $logoButton->set_relief('none');
+ $self->{parent}->{tooltips}->set_tip($logoButton,
+ $self->{lang}->{AboutTitle});
+ $logoButton->signal_connect('clicked' , sub {
+ $self->{parent}->about;
+ });
+
+ $self->insert($separator, -1);
+ $self->insert($logoItem, -1);
+ }
+
+ sub createUserFilters
+ {
+ my ($self, $model) = @_;
+ $self->{blocked} = 1;
+ if ($self->{controls}->{userFiltersOption})
+ {
+ $self->{userFilters} = $model->getUserFilters;
+ my $i = 0;
+ my @filters = map {{value => $i++,
+ displayed => $model->getDisplayedText($_->{name})}}
+ @{$self->{userFilters}};
+ $self->{controls}->{userFiltersOption}->setValues(\@filters);
+ }
+ $self->{blocked} = 0;
+ }
+
+ sub setShowFieldsSelection
+ {
+ my ($self, $value) = @_;
+ return;
+ return if ! $self->{controls}->{groupOption};
+ if ($value)
+ {
+ $self->{controls}->{groupLabel}->show;
+ $self->{groupBox}->show;
+ }
+ else
+ {
+ $self->{controls}->{groupLabel}->hide;
+ $self->{groupBox}->hide;
+ }
+ }
+
+ sub setSaveActive
+ {
+ my ($self, $value) = @_;
+ $self->{controls}->{'gtk-save'}->set_sensitive($value)
+ if $self->{controls}->{'gtk-save'};
+ }
+
+ sub setAddActive
+ {
+ my ($self, $value) = @_;
+ $self->{controls}->{'gtk-add'}->set_sensitive($value)
+ if $self->{controls}->{'gtk-add'};
+ }
+
+ sub setModel
+ {
+ my ($self, $model) = @_;
+ $self->{blocked} = 1;
+ $self->{model} = $model;
+ $self->{controls}->{groupOption}->setModel($model)
+ if $self->{controls}->{groupOption};
+ $self->setGroupField($model->{preferences}->groupBy, 1);
+
+ if ($self->{controls}->{quickFields})
+ {
+ $self->{controls}->{quickFields}->signal_handler_disconnect(
+ $self->{quickFieldsHandler}
+ ) if $self->{quickFieldsHandler};
+ $self->{controls}->{quickFields}->setModel($model);
+ $self->{controls}->{quickFields}->setValue($model->{preferences}->quickSearchField);
+ $self->{quickFieldsHandler} = $self->{controls}->{quickFields}->signal_connect(
+ 'changed' => sub {
+ my $value = $self->{controls}->{quickFields}->getValue;
+ $self->{model}->{preferences}->quickSearchField($value)
+ if $value;
+ });
+ }
+
+ if ($self->{controls}->{layoutOption})
+ {
+ my @panels = map {{value => $_,
+ displayed => $model->getDisplayedText($model->{panels}->{$_}->{label})}}
+ @{$model->{panelsNames}};
+ $self->{controls}->{layoutOption}->setValues(\@panels);
+ }
+
+ $self->createUserFilters($model);
+
+ # Update tooltip text
+ $self->{parent}->{tooltips}->set_tip($self->{controls}->{'gtk-add'},
+ $self->{lang}->{NewItemTooltip})
+ if $self->{controls}->{'gtk-add'};
+ $self->{parent}->{tooltips}->set_tip($self->{controls}->{'gtk-find'},
+ $self->{lang}->{SearchTooltip})
+ if $self->{controls}->{'gtk-find'};
+ $self->{parent}->{tooltips}->set_tip($self->{controls}->{'gtk-refresh'},
+ $self->{lang}->{ToolbarAllTooltip})
+ if $self->{controls}->{'gtk-refresh'};
+
+ # Update add button text
+ if ($self->{controls}->{'gtk-add'})
+ {
+ my $addText = $self->{lang}->{MenuAddItem};
+ $addText =~ s/\_//g;
+ my $widget = $self->{controls}->{'gtk-add'}->get_children;
+ while ($widget)
+ {
+ if ($widget->isa(Gtk2::Label::))
+ {
+ $widget->set_text($addText);
+ last;
+ }
+ elsif ($widget->isa(Gtk2::Image::))
+ {
+ last;
+ }
+ $widget = $widget->get_children;
+ }
+ }
+
+ # Hide tonight button if needed
+ if ($self->{controls}->{'gtk-execute'})
+ {
+ $self->{controls}->{'gtk-execute'}->show;
+ $self->{controls}->{'gtk-execute'}->hide if !$model->hasRandom;
+ }
+
+ # Hide play button if needed
+ if ($self->{controls}->{'gtk-media-play'})
+ {
+ $self->{controls}->{'gtk-media-play'}->show;
+ # Update button tooltip
+ $self->{parent}->{tooltips}->set_tip($self->{controls}->{'gtk-media-play'},
+ $self->{lang}->{PlayTooltip});
+ $self->{controls}->{'gtk-media-play'}->hide if !$model->hasPlay;
+ }
+
+ $self->{blocked} = 0;
+ }
+
+ sub setGroupField
+ {
+ my ($self, $field, $force) = @_;
+ my $i = 0;
+ return if (defined $self->{currentGroupField}) && ($self->{currentGroupField} eq $field) && !$force;
+ $self->{currentGroupField} = $field;
+ $self->{controls}->{groupOption}->setValue($field)
+ if $self->{controls}->{groupOption};
+ }
+
+ sub setItemsList
+ {
+ my ($self, $view) = @_;
+ return if ! $self->{controls}->{viewOption};
+ $self->{controls}->{viewOption}->setValue($view);
+ }
+
+ sub setLayout
+ {
+ my ($self, $layout) = @_;
+ return if ! $self->{controls}->{layoutOption};
+ $self->{controls}->{layoutOption}->setValue($layout);
+ }
+
+ sub setSize
+ {
+ my ($self, $size) = @_;
+
+ if ($size == 3)
+ {
+ $self->unset_icon_size;
+ }
+ else
+ {
+ $self->set_icon_size($size == 1 ? 'small-toolbar' : 'large-toolbar');
+ }
+ }
+
+ sub removeSearch
+ {
+ my $self = shift;
+ $self->{blocked} = 1;
+ $self->{controls}->{quickEntry}->setValue('')
+ if $self->{controls}->{quickEntry};
+ if ($self->{controls}->{userFiltersOption})
+ {
+ $self->{controls}->{userFiltersOption}->clear
+ if !$self->{controls}->{userFiltersOption}->{changeInProgress};
+ }
+ $self->{blocked} = 0;
+ }
+
+}
+
+
+{
+ package GCToolbarOptionsDialog;
+ use base 'GCDoubleListDialog';
+
+ sub new
+ {
+ my ($proto, $parent) = @_;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new($parent, 'Toolbar configuration', 1,
+ $parent->{lang}->{ImportExportFieldsUnused}, $parent->{lang}->{ImportExportFieldsUsed});
+
+ bless($self, $class);
+
+ $self->{separatorString} = $self->{parent}->{lang}->{ToolbarSeparator};
+
+ my $defaultButton = new GCButton->newFromStock('gtk-undo', 0, $parent->{lang}->{PanelRestoreDefault});
+ $defaultButton->set_border_width($GCUtils::margin);
+ $defaultButton->signal_connect('clicked' => sub {
+ $self->preFill;
+ });
+ my $clearButton = new GCButton->newFromStock('gtk-clear');
+ $clearButton->set_border_width($GCUtils::margin);
+ $clearButton->signal_connect('clicked' => sub {
+ $self->clearList;
+ });
+
+ $self->getDoubleList->addToPermanent($self->{separatorString});
+ $self->getDoubleList->setDataHandler($self);
+ $self->getDoubleList->addBottomButtons($defaultButton,$clearButton);
+
+ $self->{configFile} = $ENV{GCS_CONFIG_HOME}.'/'.$GCToolBar::CONFIGURATION_FILE;
+ $self->{conversionMap} = {};
+
+ my @separatorXpm = (
+ '16 16 3 1',
+ ' c None', '- c grey', '+ c black',
+ ' +- ', ' +- ', ' +- ', ' +- ',
+ ' +- ', ' +- ', ' +- ', ' +- ',
+ ' +- ', ' +- ', ' +- ', ' +- ',
+ ' +- ', ' +- ', ' +- ', ' +- ');
+ $self->{separatorPixbuf} = Gtk2::Gdk::Pixbuf->new_from_xpm_data(@separatorXpm);
+
+ return $self;
+ }
+
+ sub getInitData
+ {
+ my $self = shift;
+
+ return $self->getDataFromList([
+ 'ToolbarSeparator',
+ 'gtk-add', 'gtk-save', 'gtk-preferences',
+ 'gtk-find', 'gtk-refresh', 'gtk-execute', 'gtk-media-play',
+ 'gtk-new', 'gtk-open', 'gtk-properties', 'gtk-quit',
+ 'gtk-dnd', 'gtk-delete', 'gtk-find-and-replace',
+ 'gtk-help',
+ 'ToolbarGroupBy', 'ToolbarQuickSearch', 'OptionsView', 'OptionsLayout',
+ 'MenuSavedSearches'
+ ], 1);
+ }
+
+ sub getData
+ {
+ my $self = shift;
+ if (! -f $self->{configFile})
+ {
+ return $self->getDefaultData;
+ }
+ open CONFIG, $self->{configFile};
+ my @array;
+ foreach (<CONFIG>)
+ {
+ s/\s+$//;
+ push @array, $_;
+ }
+ close CONFIG;
+ return $self->getDataFromList(\@array);
+ }
+
+ sub getDefaultData
+ {
+ my $self = shift;
+ return $self->getDataFromList(\@GCToolBar::DEFAULT_CONTROLS);
+ }
+
+ sub saveList
+ {
+ my ($self, $list) = @_;
+
+ open CONFIG, '>',$self->{configFile};
+ foreach (@$list)
+ {
+ print CONFIG $self->{conversionMap}->{$_->[1]}, "\n";
+ }
+ close CONFIG;
+ }
+
+ sub preFill
+ {
+ my $self = shift;
+
+ my @data;
+ $self->getDoubleList->setListData($self->getDefaultData);
+ }
+
+ sub getDataFromList
+ {
+ my ($self, $list, $init) = @_;
+ my @data;
+ foreach my $id (@$list)
+ {
+ if ($id =~ /^gtk-/)
+ {
+ my $stockItem = Gtk2::Stock->lookup($id);
+ # Make sure string has model dependant parts translated:
+ (my $label = $self->{parent}->GCLang::getGenericModelString($stockItem->{label})) =~ s/_//g;
+ my $pixbuf = $self->{parent}->render_icon($id, 'menu');
+ push @data, [$pixbuf, $label];
+ $self->{conversionMap}->{$label} = $id if $init;
+ }
+ else
+ {
+ my $pixbuf = undef;
+ if ($id eq 'ToolbarSeparator')
+ {
+ $pixbuf = $self->{separatorPixbuf};
+ }
+ my $label = $self->{parent}->{lang}->{$id};
+ push @data, [$pixbuf, $label];
+ $self->{conversionMap}->{$label} = $id if $init;
+ }
+ }
+ return \@data;
+ }
+}
+
+1;