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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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'],
                 # 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);

        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);

        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 $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);

        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);
    }
}

{
    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;
                        if ($idx == -1)
                        {
                            $self->{parent}->removeSearch(0);
                        }
                        else
                        {
                            $self->{parent}->removeSearch(1);
                            $self->{parent}->setSearchWithTypes(%{$self->{userFilters}->[$idx]});
                        }
                    });
                    
                    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
        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->{controls}->{quickEntry}->setValue('')
            if $self->{controls}->{quickEntry};
    }

}


{
    package GCToolbarOptionsDialog;
    use base 'GCDoubleListDialog';

    sub new
    {
        my ($proto, $parent) = @_;
        my $class = ref($proto) || $proto;
        my $self  = $class->SUPER::new($parent, 'Toolbar configuration', 1);

        bless($self, $class);

        $self->{separatorString} = $self->{parent}->{lang}->{ToolbarSeparator};
        $self->addToPermanent($self->{separatorString});

        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->{vboxUnused}->pack_start($defaultButton, 0, 0, 0);
        $self->{vboxUsed}->pack_start($clearButton, 0, 0, 0);

        $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 getUnusedLabel
    {
        my $self = shift;
        
        return $self->{parent}->{lang}->{ImportExportFieldsUnused};
    }
    sub getUsedLabel
    {
        my $self = shift;
        
        return $self->{parent}->{lang}->{ImportExportFieldsUsed};
    }

    sub preFill
    {
        my $self = shift;
        
        my @data;
        $self->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;
