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

Last change on this file since 4098 was 4098, checked in by ronosman, 11 years ago

Test if the locale is available before trying to create it. Chinese or japanese are not available by default on XP.

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