aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ManaTools/Shared/GUI/Event.pm
blob: c51a39fdb19e7966650cbcadecb4b2cbde39dfc5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# vim: set et ts=4 sw=4:
package ManaTools::Shared::GUI::Event;
#============================================================= -*-perl-*-

=head1 NAME

ManaTools::Shared::GUI::Event - Class to manage various events

=head1 SYNOPSIS

use ManaTools::Shared::GUI::Event;

my $event = ManaTools::Shared::GUI::Event->new(
    name => "Event1",
    parentDialog => $dialog,
    eventType => $yui::YEvent::YWidgetEvent,
    widget => $widget,
    backend => $backend,
    event => sub {
        my $self = shift;
        my $yevent = shift;
        my $backend = shift;
        my $dialog = $self->parentDialog();
        my $ydialog = $dialog->dialog();
        ...
        return 1;
    }
);


=head1 DESCRIPTION

This class wraps the most common dialog functionality


=head1 SUPPORT

You can find documentation for this module with the perldoc command:

perldoc ManaTools::Shared::GUI::Event

=head1 AUTHOR

Maarten Vanraes <alien@rmail.be>

=head1 COPYRIGHT and LICENSE

Copyright (C) 2015-2016, Maarten Vanraes.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2, as
published by the Free Software Foundation.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA

=head1 FUNCTIONS

=cut

use Moose;
use diagnostics;
use utf8;

with 'ManaTools::Shared::GUI::EventRole';

use yui;

#=============================================================

=head2 new

=head3 INPUT

    hash ref containing
        name:               a name to identify it
        parentDialog:       the parent Dialog
        eventType:          a yui::YEventType
        widget:             an optional widget
        item:               an optional item
        event:              an optional CodeRef that returns 0 if event is
                            not correctly processed
        backend:            an optional backend to be used in the event handler

=head3 DESCRIPTION

    new is inherited from Moose, to create an Event object

=cut

has 'widget' => (
    is => 'ro',
    isa => 'Maybe[yui::YWidget]',
    default => sub {
        return undef;
    }
);

has 'item' => (
    is => 'ro',
    isa => 'Maybe[yui::YItem]',
    default => sub {
        return undef;
    }
);

has 'event' => (
    is => 'rw',
    isa => 'Maybe[CodeRef]',
    lazy => 1,
    default => sub {
        return undef;
    }
);

has 'backend' => (
    is => 'rw',
    isa => 'Maybe[Ref]',
    lazy => 1,
    default => sub {
        return undef;
    }
);

#=============================================================

sub processEvent {
    my $self = shift;
    my $yevent = shift;
    return -1 if ($yevent->eventType != $self->eventType);
    return -1 if ($yevent->eventType == $yui::YEvent::WidgetEvent && !$self->equalsWidget($yevent->widget));
    return -1 if ($yevent->eventType == $yui::YEvent::MenuEvent && !$self->equalsItem($yevent->item));
    my $event = $self->event();
    return $event->($self, $yevent, $self->backend()) if defined($event);
    return -1;
}

sub equalsWidget {
    my $self = shift;
    my $widget = shift;
    return ($self->widget() == $widget);
}

sub equalsItem {
    my $self = shift;
    my $item = shift;
    return ($self->item() == $item);
}

#=============================================================

no Moose;
__PACKAGE__->meta->make_immutable;

1;
href='#n568'>568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
#!/usr/bin/perl
# vim: set et ts=4 sw=4:
#    Copyright 2012-2013 Angelo Naselli <anaselli@linux.it>
#
#    This file is part of AdminPanel
#
#    AdminPanel 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.
#
#    AdminPanel 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 AdminPanel.  If not, see <http://www.gnu.org/licenses/>.

package AdminPanel::Shared;

=head1 NAME

AdminPanel::Shared - AdminPanel::Shared contains all the shared routines 
                     needed by AdminPanel and modules

=head1 SYNOPSIS

    

=head1 DESCRIPTION

This module collects all the routines shared between AdminPanel and its modules.

=head1 EXPORT

    warningMsgBox
    msgBox
    infoMsgBox
    ask_YesOrNo
    ask_OkCancel
    AboutDialog
    trim


=head1 SUPPORT

You can find documentation for this module with the perldoc command:

    perldoc AdminPanel::Shared

=head1 AUTHOR

Angelo Naselli <anaselli@linux.it>

=head1 COPYRIGHT and LICENSE

Copyright (C) 2013, Angelo Naselli.

This file 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.

This file 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 this file.  If not, see <http://www.gnu.org/licenses/>.

=head1 FUNCTIONS

=cut

use strict;
use warnings;
use diagnostics;

use Digest::MD5;

use lib qw(/usr/lib/libDrakX);
use common qw(N 
              N_);
use yui;
use base qw(Exporter);

# TODO move GUI dialogs to Shared::GUI
our @EXPORT = qw(
                warningMsgBox
                msgBox
                infoMsgBox
                ask_YesOrNo
                ask_OkCancel
                ask_fromList
                AboutDialog
                trim 
                member
                md5sum
);


=head1 VERSION

Version 0.01

=cut

our $VERSION = '0.01';

=head1 License

GPL2 license content text, it can be used to be shown
in dialogs.

=cut

our $License = N_("This program 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, or (at your option)
any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
");


#=============================================================

=head2 warningMsgBox

=head3 INPUT

    $st: string to be swhon into the dialog

=head3 DESCRIPTION

This function creates an Warning dialog and show the message 
passed as input.

=cut

#=============================================================

sub warningMsgBox {
    my ($st) = @_;
    my $factory = yui::YUI::widgetFactory;
    my $msg_box = $factory->createPopupDialog($yui::YDialogWarnColor);
    my $layout = $factory->createVBox($msg_box);
    my $align = $factory->createAlignment($layout, 3, 0);
    $factory->createLabel( $align, $st, 1, 0);
    $align = $factory->createAlignment($layout, 3, 0);
    $factory->createPushButton($align, N("Ok"));
    $msg_box->waitForEvent();

    destroy $msg_box;
}

#=============================================================

=head2 infoMsgBox

=head3 INPUT

    $st: string to be swhon into the dialog

=head3 DESCRIPTION

This function creates an Info dialog and show the message 
passed as input.

=cut

#=============================================================

sub infoMsgBox {
    my ($st) = @_;
    my $factory = yui::YUI::widgetFactory;
    my $msg_box = $factory->createPopupDialog($yui::YDialogInfoColor);
    my $layout = $factory->createVBox($msg_box);
    my $align = $factory->createAlignment($layout, 3, 0);
    $factory->createLabel( $align, $st, 1, 0);
    $align = $factory->createAlignment($layout, 3, 0);
    $factory->createPushButton($align, N("Ok"));
    $msg_box->waitForEvent();

    destroy $msg_box;
}

#=============================================================

=head2 msgBox

=head3 INPUT

    $st: string to be swhon into the dialog

=head3 DESCRIPTION

This function creates a dialog and show the message passed as input.

=cut

#=============================================================

sub msgBox {
    my ($st) = @_;
    my $factory = yui::YUI::widgetFactory;
    my $msg_box = $factory->createPopupDialog($yui::YDialogNormalColor);
    my $layout = $factory->createVBox($msg_box);
    my $align = $factory->createAlignment($layout, 3, 0);
    $factory->createLabel( $align, $st, 1, 0);
    $align = $factory->createAlignment($layout, 3, 0);
    $factory->createPushButton($align, N("Ok"));
    $msg_box->waitForEvent();

    destroy $msg_box;
}

#=============================================================

=head2 ask_OkCancel

=head3 INPUT

    $title: Title shown as heading
    $text:  text to be shown into the dialog

=head3 OUTPUT

    0: Cancel button has been pressed
    1: Ok button has been pressed

=head3 DESCRIPTION

This function create an OK-Cancel dialog with a 'title' and a 
'text' passed as parameters.

=cut

#=============================================================

sub ask_OkCancel {
    my ($title, $text) = @_;
    my $retVal = 0;
    yui::YUI::widgetFactory;
    my $factory = yui::YExternalWidgets::externalWidgetFactory("mga");
    $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory);
    my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_TWO);
    $dlg->setTitle($title);
    $dlg->setText($text);
    $dlg->setButtonLabel(N("Ok"), $yui::YMGAMessageBox::B_ONE );
    $dlg->setButtonLabel(N("Cancel"), $yui::YMGAMessageBox::B_TWO);
    $dlg->setDefaultButton($yui::YMGAMessageBox::B_ONE);
    $dlg->setMinSize(50, 5);
    
    $retVal = $dlg->show() == $yui::YMGAMessageBox::B_ONE ? 1 : 0;
    
    $dlg = undef;
    
    return $retVal;
}

#=============================================================

=head2 ask_YesOrNo

=head3 INPUT

    $title: Title shown as heading
    $text:  question text to be shown into the dialog

=head3 OUTPUT

    0: "No" button has been pressed
    1: "Yes" button has been pressed

=head3 DESCRIPTION

This function create a Yes-No dialog with a 'title' and a 
question 'text' passed as parameters.

=cut

#=============================================================

sub ask_YesOrNo {
    my ($title, $text) = @_;
    my $retVal = 0;
    my $factory = yui::YUI::widgetFactory;

    my $msg_box = $factory->createPopupDialog($yui::YDialogNormalColor);
    my $layout = $factory->createVBox($msg_box);

    my $align = $factory->createAlignment($layout, 3, 0);
    ## title with headings true
    $factory->createLabel( $align, $title, 1, 0);
    $align = $factory->createLeft($layout);
    $factory->createLabel( $align, $text, 0, 0);

    $align = $factory->createRight($layout);
    my $hbox = $factory->createHBox($align);
    my $yesButton = $factory->createPushButton($hbox, N("Yes"));
    my $noButton  = $factory->createPushButton($hbox, N("No"));

    my $event = $msg_box->waitForEvent();

    my $eventType = $event->eventType();

    if ($eventType == $yui::YEvent::WidgetEvent) {
        # widget selected
        my $widget      = $event->widget();
        $retVal = ($widget == $yesButton) ? 1 : 0;
    }

    destroy $msg_box;

    return $retVal;
}


#=============================================================

=head2 ask_fromList

=head3 INPUT

    $title: dialog title
    $text:  combobox heading
    $list:  item list 

=head3 OUTPUT

    undef:          if Cancel button has been pressed
    selected item:  if Ok button has been pressed

=head3 DESCRIPTION

This function create a dialog with a combobox in which to 
choose an item from a given list.

=cut

#=============================================================

sub ask_fromList {
    my ($title, $text, $list) = @_;
    
    die "Title is mandatory"   if (! $title);
    die "Heading is mandatory" if (! $text);
    die "List is mandatory"   if (! $list );
    die "At least one element is mandatory into list"   if (scalar(@$list) < 1);

    my $choice  = undef;
    my $factory = yui::YUI::widgetFactory;

    ## push application title
    my $appTitle = yui::YUI::app()->applicationTitle();
    ## set new title to get it in dialog
    yui::YUI::app()->setApplicationTitle($title);

    my $dlg = $factory->createPopupDialog($yui::YDialogNormalColor);
    my $layout = $factory->createVBox($dlg);

    my $combo   = $factory->createComboBox($layout, $text, 0);
    my $itemColl = new yui::YItemCollection;
    foreach (@$list) {
            my $item = new yui::YItem ($_, 0);
            $itemColl->push($item);
            $item->DISOWN();
    }
    $combo->addItems($itemColl);

    my $align = $factory->createRight($layout);
    my $hbox = $factory->createHBox($align);
    my $okButton = $factory->createPushButton($hbox, N("Ok"));
    my $cancelButton = $factory->createPushButton($hbox, N("Cancel"));

    while (1) {
        my $event = $dlg->waitForEvent();

        my $eventType = $event->eventType();
        #event type checking
        if ($eventType == $yui::YEvent::CancelEvent) {
            last;
        }
        elsif ($eventType == $yui::YEvent::WidgetEvent) {
            # widget selected
            my $widget = $event->widget();

            if ($widget == $cancelButton) {
                last;
            }
            elsif ($widget == $okButton) {
                my $item = $combo->selectedItem();
                $choice = $item->label() if ($item);
                last;
            }
        }
    }

    destroy $dlg;

    #restore old application title
    yui::YUI::app()->setApplicationTitle($appTitle);
    
    return $choice;
}


#=============================================================

=head2 AboutDialog

=head3 INPUT

    $opts: optional options needed to get info for dialog.
           name          => Application Name,
           version       => Application Version,
           copyright     => Copyright ususally like "Copyright (C) copyright-holder Year",
           license       => License text, 
           comments      => A comment related to application to be shown,
           website       => Web site URL,
           website_label => Label to hide previous link,
           authors       => Application authors,
           translator_credits => Application translators 
           documenters   => Application documenters 
           artists       => Graphic applicaton designers
           logo          => picture path to be shown as application logo

=head3 OUTPUT

    Output_Parameter: out_par_description

=head3 DESCRIPTION

About dialog implementation, this dialog can be used by
modules, to show authors, license, credits, etc.

=cut

#=============================================================

sub AboutDialog {
    my ($opts) = @_;
    
    # Credits dialog
    sub _Credits {
        my ($opts) = @_;
        
        my $factory  = yui::YUI::widgetFactory;
        my $optional = yui::YUI::optionalWidgetFactory;
        
        my $creditsdlg = $factory->createPopupDialog();
        my $layout = $factory->createVBox($creditsdlg);
        
        # header
        $factory->createHBox($layout);
        my $hbox  = $factory->createHBox($layout);
        my $align = $factory->createHVCenter($hbox);
        $hbox     = $factory->createHBox($align);
        $factory->createHeading($hbox, N("Credits"));
        
        # Credits tab widget
        if ($optional->hasDumbTab()) {
            $hbox = $factory->createHBox($layout);
            $align = $factory->createAlignment($hbox, 3, 0);
            my $dumptab = $optional->createDumbTab($align);
            my $item = new yui::YItem(N("Written by"));
            $item->setSelected();
            $dumptab->addItem( $item );
            $item->DISOWN();
            if (exists $opts->{documenters}) {
                $item = new yui::YItem(N("Documented by"));
                $dumptab->addItem( $item );
                $item->DISOWN();
            }
            if (exists $opts->{translator_credits}) {
                $item = new yui::YItem(N("Translated by"));
                $dumptab->addItem( $item );
                $item->DISOWN();
            }
            if (exists $opts->{artists}) {
                $item = new yui::YItem(N("Artwork by"));
                $dumptab->addItem( $item );
                $item->DISOWN();
            }
            my $vbox = $factory->createVBox($dumptab);
            $align = $factory->createLeft($vbox);
            $factory->createVSpacing($vbox, 1.0);
            my $label = $factory->createLabel( $align, "***", 0);
            $factory->createVSpacing($vbox, 1.0);
       
            # start value for first Item
            $label->setValue($opts->{authors}) if exists $opts->{authors};
        
            # Close button
            $align = $factory->createRight($layout);
            my $closeButton = $factory->createPushButton($align, N("Close"));
            
            # manage Credits dialog events
            while(1) {
                my $event     = $creditsdlg->waitForEvent();
                my $eventType = $event->eventType();
                
                #event type checking
                if ($eventType == $yui::YEvent::CancelEvent) {
                    last;
                }
                elsif ($eventType == $yui::YEvent::WidgetEvent) {
                    # widget selected
                    my $widget = $event->widget();

                    if ($widget == $closeButton) {
                        last;
                    }                  
                }
                elsif ($event->item() ) {
                    # $eventType MenuEvent!!!
                    my $itemLabel = $event->item()->label();
                    $itemLabel =~ s/&//; #remove shortcut from label
                    if ($itemLabel eq N("Written by")) {
                        $label->setValue($opts->{authors}) if exists $opts->{authors};
                    }
                    elsif ($itemLabel eq N("Documented by")) {
                        $label->setValue($opts->{documenters}) if exists $opts->{documenters};
                    }
                    elsif ($itemLabel eq N("Translated by")) {
                        $label->setValue($opts->{translator_credits}) if exists $opts->{translator_credits};
                    }
                    elsif ($itemLabel eq N("Artwork by")) {
                        $label->setValue($opts->{artists}) if exists $opts->{artists};
                    }  
                }
            }
        }
        else {
            print "No tab widgets available!\n";
        }
        destroy $creditsdlg;
    }
    
    # License dialog
    sub _License {
        my ($license) = @_;
        
        my $factory = yui::YUI::widgetFactory;
        my $licensedlg = $factory->createPopupDialog();
        my $layout = $factory->createVBox($licensedlg);
        
        # header
        $factory->createHBox($layout);
        my $hbox  = $factory->createHBox($layout);
        my $align = $factory->createHVCenter($hbox);
        $hbox     = $factory->createHBox($align);
        $factory->createHeading($hbox, N("License"));
        
        # license
        $hbox = $factory->createHBox($layout);
        $align = $factory->createAlignment($hbox, 3, 0);
        $factory->createLabel( $align, $license);
            
        $align = $factory->createRight($layout);
        my $closeButton = $factory->createPushButton($align, N("Close"));
        
        $licensedlg->waitForEvent();
        
        destroy $licensedlg;
    }
    
    my $website = "http://www.mageia.org";
    my $website_label = "Mageia";
    my $factory = yui::YUI::widgetFactory;
    my $aboutdlg = $factory->createPopupDialog();
    my $layout = $factory->createVBox($aboutdlg);

    # header
    $factory->createHBox($layout);
    my $hbox_iconbar  = $factory->createHBox($layout);
    my $align  = $factory->createHVCenter($hbox_iconbar);
    $hbox_iconbar     = $factory->createHBox($align);
    $factory->createImage($hbox_iconbar, $opts->{logo}) if exists $opts->{logo};
    my $header = $opts->{name} . " " . $opts->{version};
    $factory->createHeading($hbox_iconbar, $header);

    # comments
    my $hbox = $factory->createHBox($layout);
    $align = $factory->createAlignment($hbox, 3, 0);
    $factory->createLabel( $align, $opts->{comments}, 0, 0) if exists $opts->{comments};
    
    # copyright
    $hbox = $factory->createHBox($layout);
    $align = $factory->createHVCenter($hbox);
    $factory->createLabel( $align, $opts->{copyright}, 0, 0) if exists $opts->{copyright};

    # website / website_label
    $hbox = $factory->createHBox($layout);
    $align = $factory->createHVCenter($hbox);
    $website = $opts->{website} if exists $opts->{website};
    $website_label = $opts->{website_label} if exists $opts->{website_label};
    my $webref = "<a href=\"". $website ."\">". $website_label ."</a>";
    $factory->createRichText( $align, $webref);
    
    # Credits, License and Close buttons
    $hbox = $factory->createHBox($layout);
    $align = $factory->createLeft($hbox);
    my $hbox1 = $factory->createHBox($align);
    my $creditsButton = $factory->createPushButton($hbox1, N("Credits"));
    my $licenseButton = $factory->createPushButton($hbox1, N("License"));
    $factory->createHSpacing($hbox, 2.0);
    $align = $factory->createRight($hbox);
    my $closeButton = $factory->createPushButton($align, N("Close"));
    
    # AboutDialog Events
    while(1) {
        my $event     = $aboutdlg->waitForEvent();
        my $eventType = $event->eventType();
        
        #event type checking
        if ($eventType == $yui::YEvent::CancelEvent) {
            last;
        }
        elsif ($eventType == $yui::YEvent::WidgetEvent) {
            # widget selected
            my $widget = $event->widget();

            if($widget == $licenseButton) {
                _License($opts->{license}) if exists $opts->{license};
            }
            elsif ($widget == $creditsButton) {
                _Credits($opts);
            }
            elsif ($widget == $closeButton) {
                last;
            }
        }
        elsif ($eventType == $yui::YEvent::MenuEvent) {
            my  $menuEvent = yui::YMGAWidgetFactory::getYMenuEvent($event);
            #TODO check why is not working
            run_program::raw({ detach => 1 }, 'www-browser', $menuEvent->id());
        }
    }
    
    destroy $aboutdlg;
}

#=============================================================

=head2 trim

=head3 INPUT

    $st: String to be trimmed

=head3 OUTPUT

    $st: trimmed string

=head3 DESCRIPTION

This function trim the given string.

=cut

#=============================================================

sub trim {
    my ($st) = shift;
    $st =~s /^\s+//g;
    $st =~s /\s+$//g;
    return $st;
}

#=============================================================

=head2 member

=head3 INPUT

    $e: Array element to be found into array
    @_: any array

=head3 OUTPUT

    1 or 0: if $e is a member of the given array

=head3 DESCRIPTION

This function look for an element into an array

=cut

#=============================================================
sub member { 
    my $e = shift; 
    foreach (@_) { 
        $e eq $_ and return 1;
    } 
    0; 
}

#=============================================================

=head2 md5sum

=head3 INPUT

$filename: file for md5 calculation

=head3 OUTPUT

md5 sum

=head3 DESCRIPTION

 compute MD5 for the given file

=cut

#=============================================================

sub md5sum {
    my @files = @_;

    my @md5 = map {
        my $sum;
        if (open(my $FILE, $_)) {
            binmode($FILE);
            $sum = Digest::MD5->new->addfile($FILE)->hexdigest;
            close($FILE);
        }
        $sum;
    } @files;
    return wantarray() ? @md5 : $md5[0];
}

1; # End of AdminPanel::Shared