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

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

Set version number to 2.0.5b in application caption.

  • 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.5b'
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.