source: extensions/pLoader/trunk/src/Uploader/GUI/wxApp.pm @ 4138

Revision 4138, 21.3 KB checked in by ronosman, 10 years ago (diff)

Bug 1216 fixed : panel captions remain in previous language after switch.

  • Property svn:eol-style set to LF
Line 
1# +-----------------------------------------------------------------------+
2# | pLoader - a Perl photo uploader for Piwigo                            |
3# +-----------------------------------------------------------------------+
4# | Copyright(C) 2008      Piwigo Team                  http://piwigo.org |
5# +-----------------------------------------------------------------------+
6# | This program is free software; you can redistribute it and/or modify  |
7# | it under the terms of the GNU General Public License as published by  |
8# | the Free Software Foundation                                          |
9# |                                                                       |
10# | This program is distributed in the hope that it will be useful, but   |
11# | WITHOUT ANY WARRANTY; without even the implied warranty of            |
12# | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
13# | General Public License for more details.                              |
14# |                                                                       |
15# | You should have received a copy of the GNU General Public License     |
16# | along with this program; if not, write to the Free Software           |
17# | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
18# | USA.                                                                  |
19# +-----------------------------------------------------------------------+
20package Uploader::GUI::wxApp;
21use strict;
22use base qw/Wx::App Class::Accessor::Fast/;   
23use Wx qw/
24             wxBITMAP_TYPE_GIF
25             wxBITMAP_TYPE_ICO
26             wxBITMAP_TYPE_BMP
27             wxBITMAP_TYPE_PNG
28             wxBITMAP_TYPE_JPEG
29             wxIMAGE_QUALITY_NORMAL
30             wxIMAGE_QUALITY_HIGH
31             wxSPLASH_CENTRE_ON_SCREEN
32             wxSPLASH_TIMEOUT
33             wxDefaultPosition
34             wxDefaultSize
35             wxSIMPLE_BORDER
36             wxFRAME_TOOL_WINDOW
37             wxFRAME_NO_TASKBAR wxSTAY_ON_TOP
38             wxWHITE
39             wxICON_EXCLAMATION
40             wxOK
41             wxLANGUAGE_CHINESE_SIMPLIFIED   
42             wxLANGUAGE_CZECH   
43             wxLANGUAGE_DANISH   
44             wxLANGUAGE_DUTCH   
45             wxLANGUAGE_ENGLISH   
46             wxLANGUAGE_FRENCH   
47             wxLANGUAGE_GERMAN   
48             wxLANGUAGE_HUNGARIAN
49             wxLANGUAGE_ITALIAN   
50             wxLANGUAGE_JAPANESE   
51             wxLANGUAGE_POLISH   
52             wxLANGUAGE_PORTUGUESE   
53             wxLANGUAGE_PORTUGUESE_BRAZILIAN   
54             wxLANGUAGE_RUSSIAN   
55             wxLANGUAGE_SLOVAK   
56             wxLANGUAGE_SPANISH   
57         /;
58use Uploader::GUI::wxFrameAUI;
59use File::Slurp ;
60use Data::Dumper;
61use Storable;
62use File::HomeDir;
63use File::Spec;
64use Uploader::PWG;
65use Uploader::ImageList;
66use Uploader::GUI::wxLoginDlg;
67use Wx::Locale qw/:default/;
68use utf8;
69
70$|=1;
71
72__PACKAGE__->mk_accessors( 
73    qw/
74          pwg
75          site_url
76          site_username
77          site_password
78          http_username
79          http_password
80          rejects
81          imagelist
82          storable_file
83          wx_thumb_dir
84          resized_dir
85          preview_dir
86          userdata_dir
87          resized_dir
88          thumb_dir
89          conf_file
90          layout_file
91          locale
92          current_language
93          languages
94          available_languages
95          version
96          imagelist_version
97          use_offline
98          login_dlg
99          branding
100          frame
101          perspective
102          imageviewerIndex
103          frameLayout
104          chunk_size
105          layout_clean
106      / 
107);
108
109sub FilterEvent {
110    my( $self, $event ) = @_;
111   
112    Wx::LogMessage "EventType %s", $event->GetEventType();
113   
114    return -1;
115}
116
117
118sub OnInit {
119    my( $self ) = @_;
120   
121    $self->version(
122        '2.0.5b'
123    );
124   
125    # to check if we can use stored cache
126    $self->imagelist_version(
127        '7'
128    );
129
130    $self->languages(
131      [
132             ["中文 (%s)", wxLANGUAGE_CHINESE_SIMPLIFIED, 'Chinese simplified'],   
133             ["Česky (%s)", wxLANGUAGE_CZECH, 'Czech'],   
134             ["Dansk (%s)", wxLANGUAGE_DANISH, 'Danish'],   
135             ["Deutsch (%s)", wxLANGUAGE_GERMAN, 'German'],   
136             ["English (%s)", wxLANGUAGE_ENGLISH, 'English'],   
137             ["Español (%s)", wxLANGUAGE_SPANISH, 'Spanish'],   
138             ["Français (%s)", wxLANGUAGE_FRENCH, 'French'],   
139             ["Italiano (%s)", wxLANGUAGE_ITALIAN, 'Italian'],   
140             ["日本語 (にほんご) (%s)", wxLANGUAGE_JAPANESE, 'Japanese'],   
141             ["Magyar (%s)", wxLANGUAGE_HUNGARIAN, 'Hungarian'],
142             ["Nederlands (%s)", wxLANGUAGE_DUTCH, 'Dutch'],   
143             ["Polski (%s)", wxLANGUAGE_POLISH, 'Polish'],   
144             ["Português Brasileiro (%s)", wxLANGUAGE_PORTUGUESE_BRAZILIAN, 'Portuguese Brazil'],   
145             ["Português Portugal (%s)", wxLANGUAGE_PORTUGUESE, 'Portuguese Portugal'],   
146             ["Русский (%s)", wxLANGUAGE_RUSSIAN, 'Russian'],
147             ["Slovenčina (%s)", wxLANGUAGE_SLOVAK, 'Slovak'],
148      ]
149    );
150    # some languages may be unavailable due to system configuration.
151    $self->_filter_available_languages;
152    Wx::InitAllImageHandlers();
153    my $applicationName = "pLoader" ;
154    $self->SetAppName( $applicationName );
155    $self->SetVendorName( "Piwigo Team" );
156
157    $self->{IMGTYPE} = {
158        'jpg' => wxBITMAP_TYPE_JPEG,
159        'gif' => wxBITMAP_TYPE_GIF,
160        'png' => wxBITMAP_TYPE_PNG,
161    };
162
163    $self->_init_userdir;
164
165    my $conf = retrieve $self->conf_file if -e $self->conf_file;       
166
167    if(defined $conf ){
168        $self->SetKeyValues($conf);
169    }
170    else {
171        $self->_readParams( 'pLoader.ini' ) unless defined $conf ;
172    }
173
174    # when language is switched, need a new layout
175    unlink $self->layout_file if $self->layout_clean;
176    $self->layout_clean(0);
177
178    my $layout = retrieve $self->layout_file if -e $self->layout_file; 
179    if(defined $layout ){
180        $self->SetKeyValues($layout);
181    }
182
183
184    $self->site_url(
185        $self->{site_url}
186    );
187   
188
189    $self->site_username(
190        $self->{site_username}
191    );
192    $self->site_password(
193        $self->{site_password}
194    );
195
196    $self->http_username(
197        $self->{http_username}
198    );
199    $self->http_password(
200        $self->{http_password}
201    );
202
203
204    $self->current_language(
205        $self->{current_language}||Wx::Locale::GetSystemLanguage()
206    );
207
208    $self->chunk_size(
209        $self->{chunk_size}||500_000
210    );
211   
212    $self->init_locale;
213
214    my $not_exit = $self->Login();
215    # user pressed OK
216    if($not_exit){
217        $self->StoreConnectionProperties;
218        if( !$self->use_offline ){
219            while( $not_exit and !$self->_is_connected ){
220                $not_exit = $self->Login();
221                last if $self->use_offline;
222            }
223        }
224        $self->_init_imagelist;
225        $self->_init_thumbimagelist;
226        $self->_init_frame;
227    }
228
229    $not_exit;
230}
231
232sub _filter_available_languages {
233    my ( $self ) = @_;
234
235    # check if the locale can be set and the translation catalog available
236    $self->available_languages(
237        [
238            grep {$_} 
239            map{
240                            #  a locale may be unavailable due to system limitations ( ex: chinese, japanese when language pack are not installed )
241                            if(Wx::Locale::IsAvailable($_->[1])){
242                            my $locale = Wx::Locale->new($_->[1]);
243                            $locale->AddCatalogLookupPathPrefix('../locale');
244                            $_ if $locale->AddCatalog('pLoader');
245                                }
246            }
247            @{$self->languages}
248        ]
249    );
250}
251
252sub _is_connected {
253    my ( $self ) = @_;
254
255    my $is_connected;
256
257    if($self->pwg->login_result->{stat} eq 'ok'){
258        $is_connected = 1;
259    }
260    else{
261        Wx::MessageBox( 
262            sprintf(
263                "%s\n\n%s %s %s",
264                $self->pwg->login_result->{message},
265                gettext("Connection to"),
266                $self->site_url,
267                gettext("failed"),
268            ),
269            gettext("Piwigo login error"),
270            wxOK | wxICON_EXCLAMATION, 
271        );
272    }
273   
274    $is_connected;
275}
276
277
278my $locale;
279sub init_locale {
280    my ( $self, $language ) = @_;
281   
282    $self->current_language(
283        $language
284    ) if defined $language;
285
286    undef $locale;
287    $locale = Wx::Locale->new(
288        $self->current_language
289    );
290    $locale->AddCatalogLookupPathPrefix( '../locale');
291    if(!$locale->AddCatalog( 'pLoader.mo' )){
292        Wx::LogMessage gettext("Cannot find translation catalog files for %s. Use default language"), $locale->GetCanonicalName();
293    }
294    $self->locale($locale);     
295}
296
297sub StoreConnectionProperties {
298    my ( $self ) = @_;
299
300    eval {   
301        store( 
302            {
303                map{
304                   $_ => $self->{$_},
305                }
306                qw/
307                    site_url
308                    site_username
309                    site_password
310                    http_username
311                    http_password
312                    current_language
313                    chunk_size
314                    layout_clean
315                /
316            },
317            $self->conf_file
318        );
319    };
320}
321
322sub StoreLayoutProperties {
323    my ( $self ) = @_;
324
325    eval {   
326        store( 
327            {
328                map{
329                   $_ => $self->{$_},
330                }
331                qw/
332                      perspective
333                      imageviewerIndex
334                      frameLayout
335                /
336            },
337            $self->layout_file
338        );
339    };
340}
341
342sub _init_imagelist {
343    my ( $self ) = @_; 
344
345    my $stored_imagelist;
346   
347    my $use_new_imagelist;
348   
349    if( -e $self->storable_file ){
350        eval {
351            $stored_imagelist = retrieve $self->storable_file;
352        };
353        if($@){
354            Wx::LogMessage(
355                gettext("An error has occured. Can not read %s\n%s"),
356                $self->storable_file,
357                $@
358            );
359            $use_new_imagelist = 1 ;
360        }
361        # should have a valid imagelist
362        else{
363            $use_new_imagelist = 1 unless $self->imagelist_version eq $stored_imagelist->{imagelist_version};
364            if($use_new_imagelist){
365                Wx::LogMessage(gettext("pLoader has to reset image cache."));
366            }
367        }
368    }
369    else{
370        $use_new_imagelist = 1 ;
371    }
372
373    if($use_new_imagelist){
374        $stored_imagelist = $self->_default_imagelist_params ;
375    }
376
377
378    $self->imagelist(
379        Uploader::ImageList->new(
380            $stored_imagelist
381        )
382    );
383
384    $self->imagelist->RescaleCallback(
385        sub { $self->RescaleImage(@_) }
386    );
387
388    $self->imagelist->ResizeCallback(
389        sub { $self->ResizeImage(@_) }
390    );
391
392    $self->imagelist->YieldCallback(
393        sub { Wx::Yield }
394    );
395}
396
397
398sub _default_imagelist_params {
399    my ( $self ) = @_ ;
400
401    my $params = {
402        new_files        => [],
403        thumb_size       => 120,
404        site_thumb_dir   => $self->thumb_dir,
405        wx_thumb_size    => 120,
406        wx_thumb_dir     => $self->wx_thumb_dir,
407        preview_ratio    => 25, 
408        preview_dir      => $self->preview_dir,
409        resize_w         => 800,
410        resize_h         => 600,
411        site_resized_dir => $self->resized_dir,
412        type             => 'jpg',
413        filter           => 'Lanczos',
414        blur             => 0.9,
415        quality          => 95,
416        wx_quality       => 80,
417        th_quality       => 90,
418        auto_rotate      => 1,
419        remove_uploaded_from_selection => 1,
420        interlace        => 'Line',
421        create_resized   => 1,
422        use_exif_preview => 1,
423        prefix           => 'TN',
424        count            => 0,
425        storable_file    => $self->storable_file,
426        userdata_dir     => $self->userdata_dir,
427        default_photo_name => gettext('File name'),
428        default_name_prefix => gettext('Photo '),
429        upload_rejects   =>  [],
430        image_sums       => {},
431        sums             => [],
432        version          => $self->version,
433        imagelist_version => $self->imagelist_version,
434        RescaleCallback  => sub { $self->RescaleImage(@_) },
435        ResizeCallback   => sub { $self->ResizeImage(@_) },
436        watermark_text => gettext("my watermark"),
437        watermark_text_size => 12,
438        watermark_position => gettext("Center"),
439        watermark_y => 10,
440        watermark_x => 10,
441        watermark_color => gettext("White"),
442    };
443
444    return $params;
445}
446
447sub Login {
448    my ( $self ) = @_; 
449
450    $self->login_dlg( 
451        Uploader::GUI::wxLoginDlg->new(
452            {
453                title         => gettext("Piwigo login"),
454                site_url      => sub { $self->site_url(@_) },
455                site_username => sub { $self->site_username(@_) },     
456                site_password => sub { $self->site_password(@_) },
457                use_offline   => sub { $self->use_offline(@_) },       
458            }
459        )
460    ) unless $self->login_dlg;
461
462    my $icon = Wx::Icon->new();
463    $icon->LoadFile('../res/favicon.ico', wxBITMAP_TYPE_ICO);
464    $self->login_dlg->SetIcon($icon);   
465
466   
467    my $rval = $self->login_dlg->ShowModal();
468    $self->login_dlg->Show(0);
469
470    $self->_init_branding;
471   
472    if ($self->site_url !~ /^http:/){
473        $self->site_url(
474            sprintf(
475                "http://%s",
476                $self->site_url
477            )
478        );     
479    }
480
481    $self->pwg(
482        # get these parameters from dialog or from file
483        Uploader::PWG->new(
484            {
485                site_url       => $self->site_url,
486                site_username  => $self->site_username,
487                site_password  => $self->site_password,
488                http_username  => $self->http_username,
489                http_password  => $self->http_password,
490                branding       => $self->branding,
491                chunk_size     => $self->chunk_size,
492                use_offline    => $self->use_offline,
493            }
494        )
495    );
496
497    $rval;
498}
499
500sub _init_userdir {
501    my ( $self ) = @_;
502   
503    my $applicationName = $self->GetAppName ;
504    my $userdatadir = File::Spec->canonpath(
505        File::Spec->catfile(
506            File::HomeDir->my_data(), 
507            "\.$applicationName"
508        )
509    );
510
511    if(! -d $userdatadir){
512        if(! mkdir $userdatadir){
513            Wx::MessageBox( 
514                sprintf(
515                    "%s directory creation failed",
516                    $userdatadir,
517                ),
518                "pLoader working directory creation error",
519                wxOK | wxICON_EXCLAMATION, 
520            );
521
522            $userdatadir = File::Spec->canonpath(
523                File::Spec->catfile(
524                    File::Spec->tmpdir(), 
525                    "\.$applicationName"
526                )
527            );
528            mkdir $userdatadir;
529        }       
530    }
531
532    $self->userdata_dir($userdatadir);
533   
534    $self->conf_file(
535        File::Spec->catfile(
536            $self->userdata_dir, 
537            ".$applicationName.conf"
538        )
539    );
540
541    $self->layout_file(
542        File::Spec->catfile(
543            $self->userdata_dir, 
544            ".$applicationName.layout"
545        )
546    );
547
548    $self->storable_file(
549        File::Spec->catfile($self->userdata_dir, 'pLoader.dat')
550    );
551   
552    my $thumbdir = File::Spec->catfile($self->userdata_dir, 'thumbnails');
553    mkdir $thumbdir unless -d $thumbdir ;
554    $self->thumb_dir($thumbdir);
555
556    my $wxthumbdir = File::Spec->catfile($self->userdata_dir, 'wxthumbnails');
557    mkdir $wxthumbdir unless -d $wxthumbdir ;
558    $self->wx_thumb_dir($wxthumbdir);
559
560
561    my $resizedir = File::Spec->catfile($self->userdata_dir, 'resize');
562    mkdir $resizedir unless -d $resizedir ;
563    $self->resized_dir($resizedir);
564
565    my $previewdir = File::Spec->catfile($self->userdata_dir, 'preview');
566    mkdir $previewdir unless -d $previewdir ;
567    $self->preview_dir($previewdir);
568
569       
570}
571
572sub _init_thumbimagelist {
573    my ( $self ) = @_;
574
575   
576    $self->imagelist->wx_thumb_imglist(
577        Wx::ImageList->new( 
578            $self->imagelist->wx_thumb_size, 
579            $self->imagelist->wx_thumb_size, 
580            1,
581            0
582        )
583    );
584   
585    # reload images
586    $self->_reload_thumb_images;
587}
588
589
590sub _reload_thumb_images {
591    my ( $self ) = @_;
592   
593    my $wximagelist = $self->imagelist->wx_thumb_imglist;
594    my $sums = $self->imagelist->sums;
595
596    map {
597        my $image = $self->imagelist->image_sums->{$_};
598
599        $wximagelist->Add(
600            Wx::Bitmap->new( 
601                $image->wx_thumb_file, 
602                $self->GetWxBitmapType($self->imagelist->type), 
603            )
604        );
605    }
606    @$sums ;
607
608}
609
610sub GetWxBitmapType {
611    my ( $self, $type ) = @_;
612   
613    $self->{IMGTYPE}->{$type};
614}
615
616
617sub RescaleImage {
618    my ( $self, $image_file, $image_file_out, $type, $ratio, $width, $height, $quality ) = @_;
619   
620
621    my $image = Wx::Image->new(
622            $image_file, 
623            $self->GetWxBitmapType($type),
624            0
625    );
626   
627    my $w;
628    my $h;
629
630    my $img_w = $image->GetWidth;
631    my $img_h = $image->GetHeight;
632   
633    # use a ratio ( 25% default ) if defined
634    # default ratio is used for preview.
635    if($ratio){
636        $w = $ratio*$img_w/100 ;
637        $h = $ratio*$img_h/100 ;
638    }
639    # use specified width and height
640    else{
641        # portrait
642        if( $img_w < $img_h ){
643            $w = $height;
644        }
645        else{
646            $w = $width;
647        }
648        # to respect aspect ratio
649        $h = sprintf(
650            "%.0f",
651            ($w*$img_h)/$img_w
652        );
653    }
654
655    $image->Rescale(
656        $w,
657        $h,
658        wxIMAGE_QUALITY_HIGH
659    );
660   
661    $quality ||= 90;
662   
663    $image->SetOption( 
664        "quality", 
665        $quality 
666    );
667   
668    if(!$image->SaveFile(
669        $image_file_out,
670        $self->GetWxBitmapType($type),
671    )){
672        Wx::LogMessage(
673            gettext("An error has occured. Can not save file %s"),
674            $image_file_out,
675        )
676    };
677}
678
679sub ResizeImage {
680    my ( $self, $image_file, $image_file_out, $type, $width, $height, $quality ) = @_;
681   
682
683    my $image = Wx::Image->new(
684            $image_file, 
685            $self->GetWxBitmapType($type),
686            0
687    );
688
689    my $w;
690    my $h;
691
692    my $img_w = $image->GetWidth;
693    my $img_h = $image->GetHeight;
694   
695        # portrait
696        if( $img_w < $img_h ){
697            $w = $height;
698        }
699        else{
700            $w = $width;
701        }
702        # to respect aspect ratio
703        $h = sprintf(
704            "%.0f",
705            ($w*$img_h)/$img_w
706        );
707
708   
709
710    $image->Rescale(
711        $w,
712        $h,
713        wxIMAGE_QUALITY_HIGH
714    );
715
716    $image->Resize(
717        [ $width, $height ], [ 0, 20],
718    );
719   
720    $quality ||= 90;
721   
722    $image->SetOption( 
723        "quality", 
724        $quality 
725    );
726   
727    if(!$image->SaveFile(
728        $image_file_out,
729        $self->GetWxBitmapType($type),
730    )){
731        Wx::LogMessage(
732            gettext("An error has occured. Can not save file %s"),
733            $image_file_out,
734        )
735    };
736}
737
738# some labels differ with branding ( piwigo.com or piwigo.org )
739sub _init_branding {
740    my ( $self ) =@_;
741   
742    if( $self->site_url =~ /\.piwigo\.com/ ){
743        $self->branding(
744            {
745                category  => gettext("album"), 
746                Category  => gettext("Album"), 
747                categories => gettext("albums"),       
748                Categories => gettext("Albums"),
749                'Add new category' => gettext("Add new album"), 
750                'Category name' => gettext("Album name :"),
751                'New category' => gettext("New album"),
752            }
753        );
754    }
755    else{
756        $self->branding(
757            {
758                category  => gettext("categorie"),     
759                Category  => gettext("Categorie"),     
760                categories => gettext("categories"),   
761                Categories => gettext("Categories"),   
762                'Add new category' => gettext("Add new category"),
763                'Category name' => gettext("Category name :"),
764                'New category' => gettext("New category"),
765            }
766        );
767    }   
768}
769
770sub SaveConfig {
771    my ( $self, $params ) = @_; 
772
773   my $config = Wx::ConfigBase::Get;
774
775   map {
776       $config->WriteInt( $_, $params->{$_} )
777   } keys %$params;
778
779   $config->Write( 'Perspective', $params->{Perspective} )
780       
781}
782
783
784sub _init_frame {
785    my ( $self ) = @_; 
786
787    my $url = $self->site_url;
788   
789    if($self->use_offline){
790        $url = gettext("Work Offline");
791    }
792
793    $self->frame(
794        Uploader::GUI::wxFrameAUI->new( 
795            {
796                title     => sprintf("pLoader - Piwigo uploader %s - [%s]", $self->version, $url),
797                pwg       => $self->pwg,
798                imagelist => $self->imagelist,
799                perspective => $self->perspective,
800                imageviewer_index => $self->imageviewerIndex,
801                frameLayout => $self->frameLayout,
802            }
803        )
804    );
805 
806    $self->frame->Show( 1 );
807    $self->SetTopWindow( $self->frame );
808
809    my $icon = Wx::Icon->new();
810    $icon->LoadFile('../res/favicon.ico', wxBITMAP_TYPE_ICO);
811    $self->frame->SetIcon($icon);       
812}
813
814sub _readParams {
815        my( $self, $file ) = @_ ;
816
817
818        my $expr_params ;
819        eval { $expr_params = read_file( $file ); } ;
820       
821        my $paramValues = [] ;
822        if($expr_params){
823                my $expr = '$paramValues = ' ;
824                $expr .=  "$expr_params ; " ;
825                eval $expr ;
826        }
827       
828        return unless 'ARRAY' eq ref $paramValues ;
829       
830        if(scalar(@$paramValues )){
831            my $params = $paramValues->[0] ;
832            $self->SetKeyValues($params);
833        }
834}
835
836
837
838sub SetKeyValues {
839    my ( $self, $params )= @_; 
840
841    foreach( keys %$params ) {
842        $self->{$_} = $params->{$_} ;
843    }
844}
845
846
8471;
Note: See TracBrowser for help on using the repository browser.