source: extensions/pLoader/trunk/src/Uploader/GUI/Frame.pm @ 4765

Last change on this file since 4765 was 4765, checked in by ronosman, 14 years ago

Bug 1410 : pLoader may crash when adding or uploading photo is canceled. Fix dialog box crash on Ubuntu 8 caused by dialog destroy.

File size: 58.1 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::Frame;
21use strict;
22use Carp;
23use Wx;
24use Wx::DND;
25use Wx qw/
26             wxSP_3DBORDER
27             wxSP_3D
28             wxNO_FULL_REPAINT_ON_RESIZE
29             wxCLIP_CHILDREN
30             wxYES_NO
31             wxYES
32             wxICON_QUESTION
33             wxITEM_NORMAL
34             wxNullBitmap
35             wxID_OK
36             wxDEFAULT_FRAME_STYLE
37             wxVERTICAL
38             wxGROW
39             wxSHAPED
40             wxBITMAP_TYPE_JPEG
41             wxBITMAP_TYPE_GIF
42             wxBITMAP_TYPE_PNG
43             wxBITMAP_TYPE_ANY
44             wxTB_FLAT
45             wxSIZE
46             wxWHITE
47             wxBLACK
48             wxID_CANCEL
49             wxFD_OPEN
50             wxFD_MULTIPLE
51             wxLI_HORIZONTAL
52             wxALIGN_CENTER_VERTICAL
53             wxALIGN_CENTER_HORIZONTAL
54             wxALL
55             wxGROW
56             wxDefaultPosition
57             wxDefaultSize
58             wxTheApp
59             wxIMAGE_LIST_NORMAL
60             wxAUI_NB_TAB_MOVE
61             wxAUI_NB_TAB_SPLIT
62             wxNO_BORDER
63             wxTE_MULTILINE
64             wxTE_READONLY
65             wxITEM_NORMAL
66             wxCLIP_CHILDREN
67             wxBORDER_NONE
68             wxNullBitmap
69             wxTR_MULTIPLE
70             wxTR_EXTENDED
71             wxTR_HIDE_ROOT
72             wxTR_HAS_BUTTONS
73             wxTR_EDIT_LABELS
74             wxMAXIMIZE
75             wxOK
76             wxICON_EXCLAMATION
77             wxICON_INFORMATION
78             WXK_DELETE
79             wxHORIZONTAL
80             wxVERTICAL
81         /;
82use base qw/Wx::Frame Class::Accessor::Fast/;
83use File::Spec;
84use Wx::Locale qw/:default/;
85use POSIX qw(ceil floor);
86
87require Win32 if($^O =~ /MSWin32/);
88
89
90my @properties = 
91    qw/
92          progressdlg
93          upload_progressdlg
94          imageviewer
95          imageviewer_img
96          tree
97          tree_root
98          treeimglist
99          tree_item_default
100          pwg
101          logwnd
102          oldlogwnd
103          getting_started
104          categories
105          imagelist
106          image_preview
107          image_prop_piwigo
108          image_prop_exif
109          image_prop_tags
110          global_settings_panel
111          piwigo_property_list
112          exif_properties
113          global_settings
114          toolbar
115          branding
116          current_imageviewer_index
117          imageviewer_mnu
118          tree_mnu
119          imageviewer_select_multi
120          frameLayout
121          piwigo_tags
122          image_tags
123          piwigo_photo_properties
124          dlg_piwigo_photo_properties
125          piwigo_photo_properties_tags
126          image_preview_refresh
127          imageviewer_refresh
128          imageviewer_item_refresh
129          horizontal_splitter
130      /;
131__PACKAGE__->mk_accessors( @properties );
132
133use Wx::Event 
134    qw/
135          EVT_MENU
136          EVT_BUTTON
137          EVT_TREE_SEL_CHANGED
138          EVT_TREE_END_LABEL_EDIT
139          EVT_CLOSE
140          EVT_LIST_END_LABEL_EDIT
141          EVT_LIST_ITEM_SELECTED
142          EVT_LIST_ITEM_ACTIVATED
143          EVT_LIST_ITEM_RIGHT_CLICK
144          EVT_TREE_ITEM_RIGHT_CLICK
145          EVT_LIST_KEY_DOWN
146          EVT_SPLITTER_SASH_POS_CHANGING
147      /;
148     
149use Wx::Perl::TextValidator;
150use Uploader::GUI::wxImageListCtrl;
151use Uploader::GUI::wxPropertyListDlg;
152use Uploader::GUI::wxHtmlWindow;
153use Uploader::GUI::wxGlobalSettings;
154use Uploader::GUI::wxImagePreview;
155use Uploader::GUI::wxPhotoProperties;
156use Uploader::GUI::wxImageReuploadDlg;
157use Uploader::GUI::wxImageProcessingProgressDlg;
158use utf8;
159$|=1;
160
161my $ID_TREE_CTX_MENU = 20000 ;
162my $ID_IMAGEVIEWER_CTX_MENU = 20100 ;
163
164sub new {
165    my( $class, $params ) = @_;
166    my $self  = $class->SUPER::new( 
167        undef, 
168        -1, 
169        $params->{title},
170        wxDefaultPosition,
171        wxDefaultSize, 
172        wxDEFAULT_FRAME_STYLE
173    );
174
175
176    $self->pwg( $params->{pwg} );
177    $self->imagelist( $params->{imagelist} );
178
179    # callback for GUI refresh : add thumbnail images to the imageviewer control
180    $self->imagelist->SetNewFilesViewerRefreshCallback(
181        sub { $self->SetNewFilesViewerRefresh(@_) }
182    );
183
184    # callback for GUI refresh : progress dialog display of thumbnail image being created
185    $self->imagelist->SetNewFilesProgressCallback(
186        sub { $self->SetNewFilesProgress(@_) }
187    );
188
189    $self->imagelist->SetNewFilesDisplayEndInfoCallback(
190        sub { $self->SetNewFilesDisplayEndInfo(@_) }
191    );
192
193    # callback for GUI refresh : remove thumbnail images from imageviewer control
194    $self->imagelist->UploadImagesViewerCallback(
195        sub { $self->UploadImagesViewerRefresh(@_) }
196    );
197   
198    $self->imagelist->ReuploadCallback(
199    sub 
200    {
201        Uploader::GUI::wxImageReuploadDlg->new(
202        { 
203            title => gettext("Photo update management"),
204            properties => 
205            {
206                $main::ID_REUPLOAD_ACTION_FILES => 
207                {
208                    selection=>sub {$self->imagelist->reupload_action_files(@_)},
209                    label=>gettext("What shall we do with files? (thumbnail, resized, high resolution)"),
210                    labels=>[
211                        gettext("nothing"),
212                        gettext("replace"),
213                    ],
214                },
215                $main::ID_REUPLOAD_ACTION_PROPERTIES => 
216                { 
217                    selection=>sub{$self->imagelist->reupload_action_properties(@_)},
218                    label=>gettext("What shall we do with single value properties?(caption, comment, author, create date)"),
219                    labels=>[
220                        gettext("nothing"),
221                        gettext("fill if empty (only replace properties currently empty in Piwigo)"),
222                        gettext("replace"),
223                    ],
224                },
225                $main::ID_REUPLOAD_ACTION_PROPERTIES_M =>
226                { 
227                    selection=>sub{$self->imagelist->reupload_action_properties_m(@_)},
228                    label=>gettext("What shall we do with multiple values properties? (categories, tags)"),
229                    labels=>[
230                        gettext("nothing"),
231                        gettext("append (keep existing and add new)"),
232                        gettext("replace"),
233                    ],
234                },
235                $main::ID_REUPLOAD_NOT_ASK => 
236                { 
237                    value=>sub{$self->imagelist->reupload_not_ask(@_)}, 
238                    label=>gettext("Do not ask me again"),
239                },
240                $main::ID_REUPLOAD_TEXT => 
241                { 
242                    label=>gettext("A least one photo has already been added in the past."),
243                },
244            },
245        } )->ShowModal();}
246    );
247
248
249    # callback for GUI refresh : progress dialog display current uploaded image
250    $self->imagelist->progress_thumbnail_refresh(
251        sub { $self->UploadProgressThumbnailRefresh(@_) }
252    );
253
254    $self->imagelist->progress_msg_refresh(
255        sub { $self->UploadProgressMessageRefresh(@_) }
256    );
257
258    $self->imagelist->progress_msg_details_refresh(
259        sub { $self->UploadProgressMessageDetailsRefresh(@_) }
260    );
261
262    $self->imagelist->progressbar_refresh(
263        sub { $self->UploadProgressBarRefresh(@_) }
264    );
265   
266    $self->imagelist->progress_endinfo_refresh(
267        sub { $self->UploadDisplayEndInfo(@_) }
268    );
269
270
271    $self->imagelist->pwg(
272        $self->pwg
273    );
274
275    $self->imagelist->categories(
276        []
277    );
278
279
280    $self->_set_setting_properties;
281    $self->_initFrame;
282    $self->_initMenus;
283    $self->_initEventHandlers;
284    $self->_initImgTypes;   
285
286    # only refresh when calling event is finished
287    Wx::Event::EVT_IDLE(
288        $self,
289        sub {
290            my ( $self, $event ) = @_;
291            if ( $self->image_preview_refresh and $self->image_preview->IsShown ){
292                $self->set_preview_image; 
293                $self->image_preview->Refresh;
294                $self->image_preview_refresh(0);
295            }
296
297            if($self->imageviewer_refresh){
298                $self->imageviewer->Refresh;
299                $self->imageviewer_refresh(0);
300            }
301
302            if($self->imageviewer_item_refresh){
303                $self->imageviewer->ItemRefresh(
304                    $self->current_imageviewer_index
305                );
306                $self->imageviewer_item_refresh(0);
307            }
308            $self->OnUpdateToolbar;
309            $event->Skip;
310        }
311    );
312
313    $self->imageviewer->SelectItem(
314        $self->current_imageviewer_index
315    ) if $self->imageviewer->GetItemCount;
316   
317    $self->Show;
318    $self;
319}
320
321
322sub _initImgTypes {
323    my ( $self ) = @_;
324
325    $self->{IMGTYPE} = {
326        'jpg' => wxBITMAP_TYPE_JPEG,
327        'gif' => wxBITMAP_TYPE_GIF,
328        'png' => wxBITMAP_TYPE_PNG,
329    };
330}
331
332
333sub GetWxBitmapType {
334    my ( $self, $type ) = @_;
335   
336    $self->{IMGTYPE}->{$type};
337}
338
339
340
341sub _set_setting_properties {
342    my ( $self ) = @_;
343
344    $self->piwigo_photo_properties(
345        {
346            $main::CAPTION => { label=>gettext("Photo caption")},
347            $main::PHOTO_PROPERTIES_CAPTION => { 
348                value => sub { $self->imagelist->current_image->site_name(@_) },
349                frame_callback => sub { $self->imageviewer_item_refresh(1); },
350            },
351            $main::COMMENT => { label=>gettext("Comment")},
352            $main::PHOTO_PROPERTIES_COMMENT => { 
353                value => sub { $self->imagelist->current_image->site_comment(@_) },
354                frame_callback => sub { $self->imageviewer_item_refresh(1); },
355            },
356            $main::AUTHOR => { label=>gettext("Author")},
357            $main::PHOTO_PROPERTIES_AUTHOR => { 
358                value => sub { $self->imagelist->current_image->site_author(@_) },
359                frame_callback => sub { $self->imageviewer_item_refresh(1); },
360            },
361            $main::TAGS => { label=>gettext("Tags")},
362            $main::CREATE_DATE => { label=>gettext("Create date")},
363            $main::PHOTO_PROPERTIES_CREATE_DATE => { 
364                value => sub { $self->imagelist->current_image->create_date(@_) },
365                frame_callback => sub { $self->imageviewer_item_refresh(1); },
366            },
367            $main::PRIVACY_LEVEL => { label=>gettext("Who can see the photo?")},
368            $main::PHOTO_PROPERTIES_PRIVACY_LEVEL => {
369                selection => sub { $self->imagelist->current_image->privacy_level(@_)},
370                choices => wxTheApp->privacy_level_choices,
371            }
372        }
373    );   
374
375    $self->global_settings(
376        {
377            $main::DEFAULT_PHOTO_CAPTION => { label => gettext("Default photo caption") },
378            $main::CPANE_RESIZE_ADVANCED => { label => gettext("Advanced") },
379            $main::CPANE_HD_ADVANCED => { label => gettext("Advanced") },
380            $main::CPANE_TRANSFERT_ADVANCED => { label => gettext("Advanced") },
381            $main::GS_THUMBNAIL => { label => gettext("Thumbnail") },
382            $main::GS_SITE_IMG => { label => gettext("Web sized") },
383            $main::GS_HD => { label => gettext("High definition") },
384            $main::GS_CLOSE => { label => gettext("Close")},
385            $main::GS_DEFAULT_PHOTO_CAPTION => {
386                string_selection => sub { $self->imagelist->default_photo_name(@_) },
387                choices =>
388                [
389                    map { gettext $_ } @{wxTheApp->default_photo_names}
390                ],
391                pre_process => sub { my ( $value ) = @_; wxTheApp->eng_default_photo_names->{$value} },
392                frame_callback => sub { 
393                    my( $self, $ctrl, $event ) = @_; 
394                    $self->OnDefaultPhotoCaption($event);
395                },
396            },
397            $main::PHOTO_CAPTION_PREFIX => { label => gettext("Photo caption  prefix") },
398            $main::GS_PHOTO_CAPTION_PREFIX => {
399                value => sub { $self->imagelist->default_name_prefix(@_) },
400            },
401            $main::GS_AUTO_ROTATE => {
402                label => gettext("Auto rotate image"),
403                value => sub { $self->imagelist->auto_rotate(@_) }
404           },
405            $main::DEFAULT_AUTHOR => { label => gettext("Default author")},
406            $main::GS_DEFAULT_AUTHOR => { value => sub { $self->imagelist->author(@_) } },
407            $main::THUMBNAIL_SIZE => { label => gettext("Site thumbnail size") },
408            $main::GS_THUMBNAIL_SIZE => {
409                value => sub { $self->imagelist->thumb_size(@_) },
410                validator => Wx::Perl::TextValidator->new( '\d' ) 
411            },
412            $main::THUMBNAIL_JPEG_QUALITY => { label => gettext("Site thumbnail jpeg quality") },
413            $main::GS_THUMBNAIL_JPEG_QUALITY => {
414                value => sub { $self->imagelist->th_quality(@_) },
415                validator => Wx::Perl::TextValidator->new( '\d' ) 
416            },
417            $main::GS_CREATE_RESIZED => {
418                selection => sub { $self->imagelist->create_resized(@_) },
419                choices =>
420                [
421                    map { gettext $_ } ( "Use original", "Use resized original" ) 
422                ],
423                frame_callback => sub { 
424                    my( $dlg, $ctrl, $event ) = @_;
425                    $dlg->OnCreateResized($event);
426                },
427            },
428            $main::SITE_IMG_WIDTH => { label => gettext("Maximum width") },
429            $main::GS_SITE_IMG_WIDTH => {
430                value => sub { $self->imagelist->resize_w(@_) },
431                validator => Wx::Perl::TextValidator->new( '\d' ) 
432            },
433            $main::SITE_IMG_HEIGHT => { label => gettext("Maximum height") },
434            $main::GS_SITE_IMG_HEIGHT => {
435                value => sub { $self->imagelist->resize_h(@_) },
436                validator => Wx::Perl::TextValidator->new( '\d' ) 
437            },
438            $main::SITE_IMG_JPEG_QUALITY => { label => gettext("Site image jpeg quality") },
439            $main::GS_SITE_IMG_JPEG_QUALITY => {
440                value => sub { $self->imagelist->quality(@_) },
441                validator => Wx::Perl::TextValidator->new( '\d' ) 
442            },
443            $main::SITE_IMG_FILTER => { label => gettext("Site image filter") },
444            $main::GS_SITE_IMG_FILTER => {
445                string_selection =>  sub { $self->imagelist->filter(@_) },
446                choices =>
447                [
448                    qw/Point Box Triangle Hermite Hanning Hamming Blackman Gaussian Quadratic Cubic Catrom Mitchell Lanczos Bessel Sinc/ 
449                ],
450            },
451            $main::SITE_IMG_BLUR => { label => gettext("Site image blur") },
452            $main::GS_SITE_IMG_BLUR => {
453                value => sub { $self->imagelist->blur(@_) },
454                validator => Wx::Perl::TextValidator->new( '\d' ) 
455            },
456            $main::SITE_IMG_INTERLACE => { label => gettext("Site image interlace") },
457            $main::GS_SITE_IMG_INTERLACE => {
458                string_selection => sub { $self->imagelist->interlace(@_) },
459                choices =>
460                [
461                    qw/None Line Plane Partition JPEG GIF PNG/ 
462                ],
463            },
464            $main::GS_REMOVE_UPLOADED_FROM_SELECTION => {
465                label => gettext("Remove uploaded photo from selection"),
466                value => sub { $self->imagelist->remove_uploaded_from_selection(@_) },
467            },
468            $main::GS_HD_UPLOAD => {
469                choices  =>
470                [
471                    map { gettext $_ } @{wxTheApp->upload_hd}
472                ],
473                pre_process => sub { my ( $value ) = @_; wxTheApp->eng_upload_hd->{$value} },
474                string_selection => sub { $self->imagelist->upload_hd(@_) },
475                frame_callback => sub { 
476                    my( $self, $ctrl, $event ) = @_; 
477                    $self->OnHDUpload($event);
478                },
479            },
480            $main::HD_IMG_WIDTH => { label => gettext("Maximum width") },
481            $main::GS_HD_IMG_WIDTH => {
482                label => gettext("HD image width"),
483                value => sub { $self->imagelist->hd_w(@_) },
484                validator => Wx::Perl::TextValidator->new( '\d' ) 
485            },
486            $main::HD_IMG_HEIGHT => { label => gettext("Maximum height") },
487            $main::GS_HD_IMG_HEIGHT => {
488                label => gettext("HD image height"),
489                value => sub { $self->imagelist->hd_h(@_) },
490                validator => Wx::Perl::TextValidator->new( '\d' ) 
491            },
492            $main::HD_IMG_JPEG_QUALITY => { label => gettext("HD image jpeg quality") },
493            $main::GS_HD_IMG_JPEG_QUALITY => {
494                value => sub { $self->imagelist->hd_quality(@_) },
495                validator => Wx::Perl::TextValidator->new( '\d' ) 
496            },
497            $main::HD_IMG_FILTER => { label => gettext("HD image filter") },
498            $main::GS_HD_IMG_FILTER => {
499                string_selection =>  sub { $self->imagelist->hd_filter(@_) },
500                choices =>
501                [
502                    qw/Point Box Triangle Hermite Hanning Hamming Blackman Gaussian Quadratic Cubic Catrom Mitchell Lanczos Bessel Sinc/ 
503                ],
504            },
505            $main::HD_IMG_BLUR => { label => gettext("HD image blur") },
506            $main::GS_HD_IMG_BLUR => {
507                value => sub { $self->imagelist->hd_blur(@_) },
508                validator => Wx::Perl::TextValidator->new( '\d' ) 
509            },
510            $main::HD_IMG_INTERLACE => { label => gettext("HD image interlace") },
511            $main::GS_HD_IMG_INTERLACE => {
512                string_selection => sub { $self->imagelist->hd_interlace(@_) },
513                choices =>
514                [
515                    qw/None Line Plane Partition JPEG GIF PNG/ 
516                ],
517            },
518            $main::GS_WMARK_ACTIVATE => {
519              label  => gettext("Activate watermark"),
520              value  => sub { $self->imagelist->watermark_activate(@_) },
521              frame_callback => sub { 
522                  my( $self, $ctrl, $event ) = @_; 
523                  $self->OnWatermark($event);
524              },
525            },
526            $main::GS_WMARK_ACTIVATE_HD => {
527              label => gettext("Activate watermark on high definition"),
528              value => sub { $self->imagelist->watermark_activate_pwg_high(@_) },
529              frame_callback => sub { 
530                  my( $self, $ctrl, $event ) = @_; 
531                  $self->OnWatermark($event);
532              },
533            },
534            $main::WMARK_TEXT => { label  => gettext("Text") },
535            $main::GS_WMARK_TEXT => { 
536              value  => sub { $self->imagelist->watermark_text(@_) },
537            },
538            $main::WMARK_TEXT_SIZE => { label     => gettext("Text size") },
539            $main::GS_WMARK_TEXT_SIZE => {
540                value   => sub { $self->imagelist->watermark_text_size(@_) },
541            },
542            $main::WMARK_COLOR => { label     => gettext("Color") },
543            $main::GS_WMARK_COLOR => {
544                string_selection => sub { $self->imagelist->watermark_color(@_) },
545                choices   => [
546                               map { gettext $_ } @{wxTheApp->colors}
547                             ],
548                pre_process => sub { my ( $value ) = @_; wxTheApp->eng_colors->{$value} },
549            },
550            $main::WMARK_POSITION => { label     => gettext("Position") },
551            $main::GS_WMARK_POSITION => {
552                string_selection => sub { $self->imagelist->watermark_position(@_) },
553                choices  => [
554                               map { gettext $_ } @{wxTheApp->positions}
555                           ],
556                pre_process => sub { my ( $value ) = @_; wxTheApp->eng_positions->{$value} },
557            },
558            $main::WMARK_MARGIN_TOP => { label => gettext("Top margin") },
559            $main::GS_WMARK_MARGIN_TOP => {
560                value   => sub { $self->imagelist->watermark_y(@_) },
561            },
562            $main::WMARK_MARGIN_LEFT => { label => gettext("Left margin") },
563            $main::GS_WMARK_MARGIN_LEFT => {
564                value   => sub { $self->imagelist->watermark_x(@_) },
565            },
566            $main::CHUNK_SIZE => { label => gettext("Transfert chunk size") },
567            $main::GS_CHUNK_SIZE => {
568                value   => sub { wxTheApp->chunk_size(@_) },
569            },
570        }   
571    );
572
573    $self->piwigo_property_list(
574        [
575            {
576                label => gettext("Photo caption"),
577            },
578            {
579                label => gettext("Comment"),
580            },
581            {
582                label => gettext("Author"),
583            },
584            {
585                label => gettext("File name"),
586            },
587            {
588                label => gettext("Create date"),
589            },
590        ]   
591    );
592
593    $self->exif_properties(
594        [
595            {
596                label    => gettext("Create date"),
597                value    => sub { $self->imagelist->current_image->create_date }, 
598                readonly => 1,
599            },   
600            {
601                label    => gettext("Model"),
602                value    => sub { $self->imagelist->current_image->exif_tag('Model') }, 
603                readonly => 1,
604            },   
605            {
606                label    => gettext("Width"),
607                value    => sub { $self->imagelist->current_image->exif_tag('ImageWidth') }, 
608                readonly => 1,
609            },   
610            {
611                label    => gettext("Height"),
612                value    => sub { $self->imagelist->current_image->exif_tag('ImageHeight') }, 
613                readonly => 1,
614            },   
615            {
616                label    => gettext("Orientation"),
617                value    => sub { $self->imagelist->current_image->exif_tag('Orientation') }, 
618                readonly => 1,
619            },   
620            {
621                label    => "ISO",
622                value    => sub { $self->imagelist->current_image->exif_tag('ISO') }, 
623                readonly => 1,
624            },   
625            {
626                label    => gettext("Shutter speed"),
627                value    => sub { $self->imagelist->current_image->exif_tag('ExposureTime') }, 
628                readonly => 1,
629            },   
630            {
631                label    => gettext("Aperture"),
632                value    => sub { $self->imagelist->current_image->exif_tag('ApertureValue') }, 
633                readonly => 1,
634            },   
635            {
636                label    => gettext("Focal length"),
637                value    => sub { $self->imagelist->current_image->exif_tag('FocalLength') }, 
638                readonly => 1,
639            },   
640            {
641                label    => gettext("Lens"),
642                value    => sub { $self->imagelist->current_image->exif_tag('Lens') }, 
643                readonly => 1,
644            },   
645        ]
646    );   
647
648    $self->image_tags(
649        sub { eval { $self->imagelist->current_image->site_tags(@_) } }
650    );
651
652    $self->piwigo_tags(
653        sub { wxTheApp->pwg->tags }
654    );   
655}
656
657sub _create_piwigo_tag {
658    my ( $self, $name ) = @_;
659   
660    if(
661        Wx::MessageBox( 
662            sprintf(
663                "%s \"%s\" ?",
664                gettext("Do you want to create"), 
665                $name,
666            ),
667            gettext("Piwigo search information"),
668            wxYES_NO | wxICON_QUESTION, 
669        ) == wxYES
670    ){   
671        $self->pwg->AddTags($name);
672        $self->pwg->RefreshTags;
673    }
674}
675
676sub _refreshFrame {
677    my ( $self ) = @_;
678   
679    eval { $self->_set_setting_properties; };
680    $self->_refresh_settings_panels_properties;
681    map {
682        $_->Refresh;
683    }
684    (
685        $self->image_prop_exif,
686        $self->global_settings_panel,
687        $self->piwigo_photo_properties_tags
688    );
689   
690}
691
692#
693sub _initFrame {
694    my ( $self ) = @_;
695   
696    $self->create_toolbar;
697
698    $self->{sizer_h} = Wx::BoxSizer->new( wxHORIZONTAL );
699   
700
701
702    $self->imageviewer(
703        Uploader::GUI::wxImageListCtrl->new( 
704            { 
705                parentwnd => $self,
706                imagelist => $self->imagelist,
707                image_size => $self->imagelist->wx_thumb_size,
708                columns => $self->piwigo_property_list,
709            }
710        )
711    );
712
713    $self->horizontal_splitter(
714        Wx::SplitterWindow->new( $self, -1 , wxDefaultPosition, wxDefaultSize, wxSP_3D )
715    );
716
717    $self->init_panels;
718
719    $self->dlg_piwigo_photo_properties (
720        Uploader::GUI::wxPhotoProperties->new(
721            {
722                parentwnd       => $self->horizontal_splitter,
723                properties      => $self->piwigo_photo_properties,
724                tags            =>
725                {
726                    id => $main::PHOTO_PROPERTIES_TAG,
727                    choices => $self->piwigo_tags,
728                    selection => $self->image_tags,
729                    creation_callback => sub { $self->_create_piwigo_tag(@_) },
730               },
731            }
732        )
733    );
734
735    $self->piwigo_photo_properties_tags(
736        $self->dlg_piwigo_photo_properties->FindWindow($main::PHOTO_PROPERTIES_TAG)
737    );
738
739    $self->create_tree;
740
741    $self->horizontal_splitter->SetMinimumPaneSize(50);
742    $self->horizontal_splitter->SplitHorizontally(
743        $self->dlg_piwigo_photo_properties,
744        $self->tree,
745        400
746    );
747
748    $self->init_dnd_targets;
749
750    if( $self->imagelist->wx_thumb_imglist->GetImageCount){
751        $self->ShowImageViewer;
752       
753        $self->imageviewer->Refresh(
754            $self->imagelist->wx_thumb_imglist
755        );
756       
757    }
758
759    # the imageviewer has a stretch factor of 1 : expands its size on frame resize
760    $self->{sizer_h}->AddWindow( $self->imageviewer, 1, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxALL||wxSHAPED, 2 );
761    $self->{sizer_h}->AddWindow( $self->horizontal_splitter, 0, wxGROW|wxALIGN_CENTER_HORIZONTAL|wxALL||wxSHAPED, 2 );
762    $self->SetSizer(
763        $self->{sizer_h}
764    );
765
766    $self->{sizer_h}->SetSizeHints(
767        $self
768    );
769
770
771}
772
773sub _refresh_settings_panels_properties {
774    my ( $self ) = @_;   
775
776    $self->dlg_piwigo_photo_properties->properties(
777        $self->piwigo_photo_properties
778    );
779
780   
781    $self->image_prop_exif->properties(
782        $self->exif_properties
783    );
784
785    $self->global_settings_panel->properties(
786        $self->global_settings
787    );   
788
789}
790
791sub _init_settings_panels {
792    my ( $self ) = @_;   
793
794
795    $self->image_prop_exif(
796        Uploader::GUI::wxPropertyListDlg->new( 
797            { 
798                parentwnd       => $self,
799                properties      => $self->exif_properties,
800                caption         => sprintf("%s - EXIF", gettext("Properties")),
801            }
802        )
803    );
804    $self->image_prop_exif->Hide;
805
806    $self->global_settings_panel(
807        Uploader::GUI::wxGlobalSettings->new( 
808            { 
809                parentwnd       => $self,
810                caption         => gettext("Global settings"),
811                properties      => $self->global_settings,
812            }
813        )
814    );
815    $self->global_settings_panel->Hide;
816
817
818
819    $self->image_preview(
820        Uploader::GUI::wxImagePreview->new(
821            { 
822                parentwnd    => $self,
823                caption      => gettext("Preview"),
824            }
825        )
826    );
827
828}
829
830sub init_panels {
831    my ( $self ) = @_;
832   
833    $self->getting_started(
834        Uploader::GUI::wxHtmlWindow->new(
835            {   
836                html => $self->_gs_html(
837                    {
838                        label   => gettext("Click links below to start using pLoader."),
839                        lnk1    => gettext("Add a new album."),
840                        lnk2    => gettext("Add photos to the selection."),
841                        lnk3    => gettext("Upload the photo selection into your album."),
842                    }
843                ),
844                caption => gettext("Getting started"),
845                size => [450, 350],
846            }
847        )
848    );
849   
850   
851    $self->getting_started->InitHrefCallbacks(
852        {
853            new_album => sub {$self->OnAddCategories(@_) },
854            add_photos => sub { $self->OnAddImages(@_) },
855            upload_photos => sub { $self->ProcessImageSelection(@_)},   
856        }
857    );
858    $self->getting_started->Hide;
859   
860    $self->_init_settings_panels;   
861}
862
863# HTML code for getting started dialog box
864sub _gs_html {
865    my ( $self, $params ) = @_;
866
867
868   my $logo = File::Spec->catfile(wxTheApp->bin_dir, '..', wxTheApp->resource_dir, 'piwigo_logo.PNG');
869
870
871    my $html = '<html>';
872    $html .= '<body text="#E15918" link="#E15918">';
873    $html .= '<font size=5 face="verdana, arial">';
874    $html .= '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head>';
875    $html .= sprintf("<img src=\"%s\" /><br /><br />", $logo);
876    $html .= $params->{label};
877    $html .= "<br /><br /><br />";
878    $html .= '1. <a href="new_album">';
879    $html .= $params->{lnk1};
880    $html .= '</a><br /><br />';
881    $html .= '2. <a href="add_photos">';
882    $html .= $params->{lnk2};
883    $html .= '</a><br /><br />';
884    $html .= '3. <a href="upload_photos">';
885    $html .= $params->{lnk3};
886    $html .= '</a><br /><br />';
887
888    $html .= '</font></body></html>';
889
890    $html;
891}
892
893
894sub init_dnd_targets {
895    my ( $self ) = @_;   
896
897    $self->imageviewer->SetDropTarget( 
898        DNDImageListDropTarget->new(
899            $self->imageviewer
900        ) 
901    );
902
903    $self->tree->SetDropTarget( 
904        DNDCategoryTreeDropTarget->new(
905            $self->tree
906        )
907    );
908   
909}
910
911
912
913sub OnPhotoProperties {
914    my ( $self ) = @_;
915
916    $self->image_prop_exif->Show(1);
917}
918
919sub OnPreview {
920    my ( $self ) = @_;
921
922    $self->image_preview->Show(1);
923
924
925
926}
927
928sub OnGettingStarted {
929    my ( $self ) = @_;
930
931    $self->getting_started->Show(1);
932}
933
934sub OnGlobalSettings {
935    my ( $self ) = @_;
936
937    $self->global_settings_panel->Show(1);
938}
939
940sub OnChooseLanguage {
941    my ( $self ) = @_;   
942
943  my $languages = wxTheApp->available_languages;
944
945
946  my $dialog = new Wx::SingleChoiceDialog( 
947    undef, 
948    gettext( "Choose a language" ), 
949    gettext( "Choose a language" ),
950    [ map { sprintf($_->[0], gettext($_->[2])) } @$languages ] 
951  );
952
953  if( $dialog->ShowModal() == wxID_OK ) {
954    wxTheApp->current_language(
955        $languages->[$dialog->GetSelection][1]
956    );
957
958    Wx::LogMessage(
959        sprintf(
960            "%s : %s", 
961            gettext("pLoader needs to be restarted to display the new selected language"),
962            gettext($languages->[$dialog->GetSelection][2])
963        )
964    );
965    wxTheApp->layout_clean(1);
966  }
967
968  $dialog->Destroy;
969
970}
971
972sub OnDefaultPhotoNameChanged {
973    my ( $self ) = @_;
974   
975    Wx::LogMessage("New default_photo_name %s", $self->imagelist->default_photo_name);   
976}
977
978sub OnGeneralSettingsClose {
979    my ( $self, $event ) = @_;
980
981    $self->global_settings_panel->Hide;
982}
983
984sub OnImageExifPropClose {
985    my ( $self, $event ) = @_;
986
987    $self->image_exif_prop->Hide;
988}
989
990sub create_tree {
991    my ( $self ) = @_;
992
993    my $images = [
994        map {
995            Wx::Bitmap->new( $_, wxBITMAP_TYPE_PNG )
996           
997        }
998        (
999          wxTheApp->resource_path('tree_pwg.png'),
1000          wxTheApp->resource_path('tree_folder.png'),
1001        )   
1002    ];
1003
1004    $self->treeimglist( Wx::ImageList->new( 16, 16, 1 ) );
1005    map {
1006        $self->treeimglist->Add($_);
1007    }
1008    @$images;
1009   
1010    $self->tree( 
1011        Wx::TreeCtrl->new( 
1012           $self->horizontal_splitter, 
1013           -1, 
1014           wxDefaultPosition, 
1015           wxDefaultSize, 
1016           wxCLIP_CHILDREN|
1017           wxTR_HAS_BUTTONS|
1018           wxTR_EDIT_LABELS
1019        ) 
1020    );
1021
1022    $self->tree->SetImageList( $self->treeimglist );
1023    $self->populate_tree_categories if !wxTheApp->use_offline;
1024    $self->tree ;
1025}
1026
1027
1028sub populate_tree_categories {
1029    my ( $self ) = @_;
1030
1031    $self->populate_tree(
1032        $self->tree,
1033        wxTheApp->pwg->categories,
1034    ) if defined wxTheApp->pwg ;
1035   
1036
1037}
1038
1039
1040# returns a valid itemData
1041sub itemData { Wx::TreeItemData->new( $_[0] ) }
1042
1043sub populate_tree {
1044    my ( $self, $tree, $tree_items ) = @_;
1045    my $root = shift @{$tree_items};
1046
1047    $self->tree_root(
1048        $tree->AddRoot( 
1049            $root->[0], 
1050            $root->[3], 
1051            $root->[4], 
1052            itemData( $root->[2] ) 
1053        )
1054    );
1055
1056  $self->populate_tree_helper( $tree, $self->tree_root, $tree_items );
1057 
1058  $tree->SelectItem( $self->tree_root );
1059  $tree->Expand( $self->tree_root );
1060}
1061
1062sub populate_tree_helper {
1063  my ( $self, $tree, $parent_id, $tree_items ) = @_;
1064
1065  my $id;
1066
1067  map {
1068      my $name = $_->[0];
1069
1070      $id = $tree->AppendItem( 
1071                                   $parent_id, 
1072                                   $name,
1073                                   defined($_->[3]) ? $_->[3] : 0, 
1074                                   defined($_->[4]) ? $_->[4] : 0, 
1075                                   itemData( $_->[2]) 
1076                              );
1077      $self->tree_item_default($id) if ! defined $self->tree_item_default;
1078      # current item has children
1079      if( ref( $_->[1] ) eq 'ARRAY' ) {
1080          $self->populate_tree_helper( $tree, $id, $_->[1] );
1081      } 
1082  }
1083  @{$tree_items};
1084
1085}
1086
1087sub _initMenus {
1088    my ( $self ) = @_ ;
1089
1090    $self->_tree_mnu;
1091    $self->_imageviewer_mnu;   
1092}
1093
1094
1095sub _tree_mnu {
1096    my ( $self ) = @_;   
1097
1098    my $ctx_mnu = Wx::Menu->new;
1099   
1100    map {
1101        $ctx_mnu->Append(
1102            @$_[0..2], wxITEM_NORMAL
1103        );
1104    }
1105    (
1106        # workaround : first item does not show bitmap
1107        [
1108            0, 
1109            "",
1110            "",
1111            wxTheApp->resource_path('mnu_folder_new.png'),
1112        ],
1113        [
1114            1+$ID_TREE_CTX_MENU, 
1115            wxTheApp->branding->{'Add new category'},
1116            sprintf(
1117                "%s %s %s %s", 
1118                gettext("Add a new"), 
1119                wxTheApp->branding->{category},
1120                gettext("to the currently selected"),
1121                wxTheApp->branding->{category},
1122            ),
1123            wxTheApp->resource_path('mnu_folder_new.png'),
1124        ],
1125        [
1126            2+$ID_TREE_CTX_MENU, 
1127            gettext("Refresh"),
1128            sprintf(
1129                "Refresh %s list.",
1130                wxTheApp->branding->{category},
1131            ),
1132            wxTheApp->resource_path('mnu_refresh.png'),
1133        ],
1134        [
1135            3+$ID_TREE_CTX_MENU, 
1136            gettext("Expand all"),
1137            sprintf(
1138                "Expand %s list.",
1139                wxTheApp->branding->{category},
1140            ),
1141            wxTheApp->resource_path('mnu_expandall.png'),
1142        ],
1143        [
1144            4+$ID_TREE_CTX_MENU, 
1145            gettext("Collapse all"),
1146            sprintf(
1147                "Collapse %s list.",
1148                wxTheApp->branding->{category},
1149            ),
1150            wxTheApp->resource_path('mnu_collapseall.png'),
1151        ],
1152    );
1153
1154    $ctx_mnu->Delete(0);
1155    $self->tree_mnu(
1156         $ctx_mnu
1157    );   
1158}   
1159
1160sub _imageviewer_mnu {
1161    my ( $self ) = @_;   
1162
1163    my $ctx_mnu = Wx::Menu->new;
1164   
1165    map {
1166        $ctx_mnu->Append(
1167            @$_[0..2]
1168        );
1169    }
1170    (
1171        # workaround : first item does not show bitmap
1172        [
1173            0, 
1174            "",
1175            "",
1176            wxTheApp->resource_path('mnu_properties.png'),
1177        ],
1178        [
1179            1+$ID_IMAGEVIEWER_CTX_MENU, 
1180            gettext("Properties"),
1181            gettext("Modify photo properties"),
1182            wxTheApp->resource_path('mnu_properties.png'),
1183        ],
1184        [
1185            2+$ID_IMAGEVIEWER_CTX_MENU, 
1186            gettext("Preview"),
1187            gettext("Display photo preview"),
1188            wxTheApp->resource_path('mnu_preview.png'),
1189        ],
1190    );
1191   
1192    $ctx_mnu->Delete(0);
1193    $self->imageviewer_mnu(
1194         $ctx_mnu
1195    );   
1196}
1197
1198sub _initEventHandlers {
1199    my ( $self ) = @_ ;
1200   
1201    Wx::Event::EVT_MENU( $self, 100, \&OnGettingStarted );
1202    Wx::Event::EVT_MENU( $self, 101, \&OnAddImages );
1203    Wx::Event::EVT_MENU( $self, 102, \&OnRemoveImages );
1204    Wx::Event::EVT_MENU( $self, 103, \&OnUploadImages );
1205    Wx::Event::EVT_MENU( $self, 104, \&OnGlobalSettings );
1206    Wx::Event::EVT_MENU( $self, 105, \&OnChooseLanguage );
1207    Wx::Event::EVT_CHOICE( $self, 106, \&OnPhotoSelMode );
1208    EVT_TREE_SEL_CHANGED( $self, $self->tree, \&OnTreeSelChanged );
1209    EVT_TREE_ITEM_RIGHT_CLICK( $self, $self->tree, \&OnTreeItemRightClick );
1210    EVT_TREE_END_LABEL_EDIT( $self, $self->tree, \&OnTreeEndLabelEdit );
1211
1212    EVT_LIST_END_LABEL_EDIT( $self, $self->imageviewer, \&OnImageViewerEndLabelEdit );
1213    EVT_LIST_ITEM_ACTIVATED( $self, $self->imageviewer, \&OnImageViewerItemActivated );
1214    EVT_LIST_ITEM_SELECTED($self, $self->imageviewer, \&OnImageViewerItemSelected) ;
1215    EVT_LIST_ITEM_RIGHT_CLICK($self, $self->imageviewer, \&OnImageViewerItemRightClick) ;
1216
1217    EVT_LIST_KEY_DOWN($self, $self->imageviewer, \&OnImageViewerKeyDown) ;
1218
1219    EVT_CLOSE( $self, \&OnClose );
1220
1221
1222    Wx::Event::EVT_MENU( $self, 1+$ID_TREE_CTX_MENU, \&OnAddCategories );
1223    Wx::Event::EVT_MENU( $self, 2+$ID_TREE_CTX_MENU, \&OnRefreshCategories );
1224    Wx::Event::EVT_MENU( $self, 3+$ID_TREE_CTX_MENU, \&OnExpandCategories );
1225    Wx::Event::EVT_MENU( $self, 4+$ID_TREE_CTX_MENU, \&OnCollapseCategories );
1226
1227    Wx::Event::EVT_MENU( $self, 1+$ID_IMAGEVIEWER_CTX_MENU, \&OnPhotoProperties );
1228    Wx::Event::EVT_MENU( $self, 2+$ID_IMAGEVIEWER_CTX_MENU, \&OnPreview );
1229
1230
1231
1232}
1233
1234{
1235  my $prevdir;
1236  my $prevfile;
1237
1238  sub OnAddImages {
1239    my( $self, $event ) = @_;
1240    my $dialog = Wx::FileDialog->new
1241      ( $self, gettext("Select photos for upload"), $prevfile, $prevdir,
1242        sprintf("%s (*.JPG)|*.JPG|(*.jpg)|*.jpg|All(*.*)|*.*", gettext("JPEG files")),
1243        wxFD_OPEN|wxFD_MULTIPLE );
1244
1245    my $file_paths = [];
1246    if( $dialog->ShowModal != wxID_CANCEL ) {
1247        @$file_paths = $dialog->GetPaths;
1248        $self->SetNewFiles($file_paths) ;
1249    }
1250    $dialog->Destroy;
1251  }
1252}
1253
1254sub OnUpdateToolbar {
1255    my( $self ) = @_;
1256   
1257    if($self->global_settings_panel->IsShown){
1258        $self->toolbar->EnableTool(104, 0);
1259    }
1260    else{   
1261        $self->toolbar->EnableTool(104, 1);
1262    }
1263
1264    if($self->global_settings_panel->IsShown){
1265        $self->toolbar->EnableTool(104, 0);
1266    }
1267    else{   
1268        $self->toolbar->EnableTool(104, 1);
1269    }
1270
1271}
1272
1273sub OnRemoveImages {
1274    my( $self, $event ) = @_;
1275
1276   
1277    $self->imagelist->RemoveImageSelection;
1278    $self->imageviewer->Refresh;   
1279
1280    if (!$self->imageviewer->GetItemCount){
1281        $self->image_preview->image(
1282            0
1283        ); 
1284        # have to reset
1285        $self->dlg_piwigo_photo_properties->ClearProperties;
1286        $self->piwigo_photo_properties_tags->ClearAllSelection;
1287        $self->imagelist->SetCurrentImage(-1);
1288    }
1289
1290    $self->image_preview->Refresh;
1291    $self->image_prop_exif->Refresh;
1292}
1293
1294sub SetNewFiles {
1295    my ( $self, $file_paths ) = @_;
1296
1297    $self->ShowImageViewer();
1298   
1299    $self->progressdlg->Destroy if defined $self->progressdlg;
1300    $self->progressdlg( 
1301        Uploader::GUI::wxImageProcessingProgressDlg->new(
1302            { 
1303                title => gettext("Image processing progress information"),
1304                bt_label => gettext("Cancel image processing"), 
1305                bt_close_label => gettext("Close"),
1306                stop_processing => sub { $self->imagelist->stop_processing(1); Wx::Yield(); },
1307             }
1308        )       
1309    );
1310    $self->progressdlg->Show(1);
1311    Wx::Yield();
1312
1313   
1314    my $files = [
1315        map {
1316            # to make sure that unicode chars in filenames are supported
1317            {
1318                ANSIPathName => $^O =~ /MSWin32/ ? Win32::GetANSIPathName($_) : $_,
1319                PathName => $_,
1320            },
1321        }@$file_paths   
1322    ];
1323
1324    @$files = sort { $a->{PathName} cmp $b->{PathName} } @$files;   
1325
1326    $self->imagelist->SetNewFiles(
1327        $files
1328    );
1329
1330   
1331}
1332
1333sub OnTreeSelChanged {
1334    my( $self, $event ) = @_;
1335 
1336    my @items = $self->tree->GetSelections;
1337
1338    $self->imagelist->categories(
1339        [
1340            map {
1341                my $category = $self->tree->GetPlData( $_ );
1342                $category->{id} if $category != -1;
1343            }
1344            @items
1345        ]
1346    );
1347}
1348
1349sub OnTreeItemRightClick {
1350    my( $self, $event ) = @_;
1351
1352
1353    $self->PopupMenu($self->tree_mnu, wxDefaultPosition);
1354   
1355}
1356
1357sub OnTreeEndLabelEdit {
1358    my( $self, $event ) = @_;
1359
1360    my $label = $event->GetLabel;
1361   
1362    $label =~ s/^\s+$//;
1363
1364    if(defined($label) and !( "" eq $label )){
1365        $self->_SetLabel($event)
1366    }
1367    else{
1368        $event->Veto;
1369    }
1370}
1371
1372sub _SetLabel {
1373    my( $self, $event ) = @_;
1374   
1375    my $category = $self->tree->GetPlData($event->GetItem);
1376    my $category_id;
1377   
1378    $category_id = $category->{id} if 'HASH' eq ref($category) ;
1379    my $comment;
1380    my ( $success, $status_msg, $content ) = $self->pwg->SetInfoCategories( 
1381        $event->GetLabel, 
1382        $comment, 
1383        $category_id
1384    );
1385
1386    my $ok = 1;
1387   
1388    if(!$success){
1389        $ok = 0;
1390    }
1391
1392    if('fail' eq $content->{stat}){
1393        $ok = 0;
1394    }
1395
1396    # method call failed
1397    if(!$ok){
1398        $event->Veto;
1399        Wx::MessageBox( 
1400            sprintf(
1401                "%s %s", 
1402                gettext("Update failed : "),
1403                $status_msg
1404            ),
1405            gettext("Piwigo update error"),
1406            wxOK | wxICON_EXCLAMATION, 
1407        );
1408        Wx::LogMessage("%s\n\n%s", Dumper($content), gettext("This function is not available. A Piwigo upgrade may resolve this issue."));
1409    }
1410}
1411
1412sub OnImageViewerItemRightClick {
1413    my( $self, $event ) = @_;
1414
1415   
1416    $self->PopupMenu($self->imageviewer_mnu, wxDefaultPosition);
1417   
1418   
1419}
1420
1421sub OnExpandCategories {
1422    my ( $self, $event ) = @_;
1423
1424    my $parent_item = $self->tree->GetSelection;
1425    $self->tree->ExpandAllChildren($parent_item);
1426    $self->tree->EnsureVisible($parent_item);
1427}
1428
1429sub OnCollapseCategories {
1430    my ( $self, $event ) = @_;
1431
1432    my $parent_item = $self->tree->GetSelection;
1433    $self->tree->CollapseAllChildren($parent_item);
1434    $self->tree->Expand($parent_item) if -1 == $self->tree->GetPlData($parent_item);
1435}
1436
1437sub OnAddCategories {
1438    my ( $self, $event ) = @_;
1439
1440    my $parent_item = $self->tree->GetSelection;
1441
1442    my $category = $self->tree->GetPlData($parent_item);
1443    my $category_id;
1444   
1445    $category_id = $category->{id} if 'HASH' eq ref($category) ;
1446
1447    my $dialog = Wx::TextEntryDialog->new( 
1448        $self, 
1449        wxTheApp->branding->{'Category name'}, 
1450        wxTheApp->branding->{'Add new category'},
1451        wxTheApp->branding->{'New category'}, 
1452    );
1453
1454    if( $dialog->ShowModal != wxID_CANCEL ) {
1455        my $name = $dialog->GetValue;
1456        my ( $success, $status_msg, $content ) = $self->pwg->AddCategories( $name, $category_id);
1457
1458        if($success){
1459            $self->_append_category($parent_item, $name, $content->{result}{id});
1460        }
1461    }
1462    $dialog->Destroy;
1463}
1464
1465sub OnRefreshCategories {
1466    my ( $self, $event ) = @_;
1467
1468    $self->_refresh_all_categories_helper;
1469}
1470
1471
1472sub _refresh_all_categories_helper {
1473    my ( $self ) = @_;   
1474
1475    my $busycursor = Wx::BusyCursor->new();
1476    $self->tree->CollapseAll;
1477    $self->tree->DeleteAllItems;
1478    $self->imagelist->categories([]);
1479    $self->pwg->RefreshCategories();
1480    $self->populate_tree_categories;
1481}
1482
1483sub _append_category {
1484    my ( $self, $parent_id, $name, $id ) = @_;
1485
1486    $self->tree->SelectItem(
1487        $self->tree->AppendItem(
1488            $parent_id, 
1489            $name, 
1490            1, 
1491            -1, 
1492            Wx::TreeItemData->new( { id => $id } )
1493        )
1494    );
1495}
1496
1497sub OnImageViewerEndLabelEdit {
1498    my( $self, $event ) = @_;
1499 
1500    my $image = $self->imagelist->GetImage($event->GetIndex);
1501    $image->site_name(
1502        $event->GetLabel
1503    );
1504       
1505    $self->dlg_piwigo_photo_properties->SetProperties;
1506}
1507
1508sub OnImageViewerItemActivated {
1509    my( $self, $event ) = @_;
1510   
1511    $self->current_imageviewer_index(
1512        $event->GetIndex
1513    );
1514
1515    $self->OnPhotoProperties;
1516}
1517
1518
1519sub OnImageViewerItemSelected {
1520    my( $self, $event ) = @_;
1521
1522    my $bc = Wx::BusyCursor->new;
1523    my $indx = $event->GetIndex;
1524    $self->_on_imageviewer_item_selected($indx);
1525
1526    $event->Skip;
1527
1528}
1529
1530sub _on_imageviewer_item_selected {
1531    my ( $self, $index ) = @_;   
1532    $self->current_imageviewer_index($index);
1533    $self->imagelist->SetCurrentImage($index);
1534   
1535    $self->imagelist->image_selection(
1536        $self->imageviewer->GetSelectedItems
1537    );
1538
1539    # process image_preview in idle time
1540    # and when current event is processed
1541    # see call to EVT_IDLE
1542    $self->image_preview_refresh(1);
1543
1544    $self->dlg_piwigo_photo_properties->SetProperties if defined $self->dlg_piwigo_photo_properties;
1545    $self->image_prop_exif->Refresh;
1546    $self->piwigo_photo_properties_tags->Refresh;
1547
1548}
1549
1550sub set_preview_image {
1551    my ( $self ) = @_;   
1552
1553    my $current_image = $self->imagelist->current_image;
1554    my $image = Wx::Image->new;
1555    $image->LoadFile(
1556        $current_image->file, 
1557        wxBITMAP_TYPE_ANY
1558    );
1559 
1560    if($self->imagelist->auto_rotate){
1561        # exif from original image
1562        my $orientation = $current_image->exif_metadata->{Orientation};
1563
1564        # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
1565        if( $orientation =~ m/Rotate (\d+)/ ){
1566            for(my $i=0; $i < floor($1/90) ; $i++){
1567                $image = $image->Rotate90;
1568            }               
1569        }
1570    }
1571
1572    $self->image_preview->image_size(
1573        [$image->GetWidth, $image->GetHeight, ]
1574    );       
1575
1576    $self->image_preview->image(
1577        $image
1578    );       
1579}
1580
1581sub OnImageViewerKeyDown {
1582    my( $self, $event ) = @_;
1583
1584    if(WXK_DELETE == $event->GetKeyCode){
1585        $self->OnRemoveImages();
1586       
1587        my $index = $self->current_imageviewer_index < $self->imageviewer->GetItemCount ?
1588            $self->current_imageviewer_index : $self->imageviewer->GetItemCount -1 ;
1589        $self->imageviewer->SelectItem(
1590            $index
1591        );
1592        $self->imageviewer->EnsureVisible(
1593            $index
1594        );
1595    }   
1596
1597}
1598
1599sub OnUploadImages {
1600    my( $self, $event ) = @_;
1601
1602    eval {
1603        $self->ProcessImageSelection();   
1604    };
1605}
1606
1607# remove image from imagelist when uploaded
1608sub UploadImagesViewerRefresh {
1609    my ( $self ) = @_;   
1610
1611
1612    $self->imageviewer->Refresh;
1613
1614    $self->image_preview->image(
1615        0
1616    ) if !$self->imageviewer->GetItemCount;
1617
1618
1619    $self->image_preview->Refresh;
1620    Wx::Yield();
1621}
1622
1623sub UploadProgressMessageRefresh {
1624    my ( $self, $msg ) = @_;   
1625
1626    Wx::Yield();
1627
1628    $self->upload_progressdlg->processing(
1629        $msg   
1630    );   
1631    $self->upload_progressdlg->LogProgress();
1632
1633    Wx::Yield();
1634}
1635
1636sub UploadProgressMessageDetailsRefresh {
1637    my ( $self, $msg ) = @_;   
1638
1639    Wx::Yield();
1640
1641    $self->upload_progressdlg->processing_details(
1642        $msg   
1643    );   
1644    $self->upload_progressdlg->LogProgress();
1645
1646    Wx::Yield();
1647}
1648
1649
1650sub UploadProgressThumbnailRefresh {
1651    my ( $self ) = @_;   
1652
1653    my $imagelist = $self->imagelist ;
1654
1655 
1656    $self->upload_progressdlg->image->SetBitmap(wxNullBitmap);
1657    $self->upload_progressdlg->image->SetBitmap(
1658        Wx::Bitmap->new( 
1659            $self->imagelist->current_image->wx_thumb_file, 
1660            $self->GetWxBitmapType($self->imagelist->type), 
1661        )
1662    );
1663
1664    Wx::Yield();
1665}
1666
1667sub UploadProgressBarRefresh {
1668    my ( $self, $value ) = @_;   
1669
1670    eval {
1671        $self->upload_progressdlg->progress(
1672            $value
1673        );
1674        $self->upload_progressdlg->LogProgress();
1675    };
1676    #croak gettext("Upload cancelled") if $@;
1677
1678    Wx::Yield();
1679}
1680
1681sub SetNewFilesDisplayEndInfo {
1682    my ( $self, $msg ) = @_;   
1683   
1684    $self->progressdlg->DisplayEndInfo($msg);
1685}
1686
1687sub UploadDisplayEndInfo {
1688    my ( $self, $msg ) = @_;   
1689   
1690    my $imagelist = $self->imagelist ;
1691   
1692    $self->upload_progressdlg->DisplayEndInfo($msg);
1693}
1694
1695sub ShowImageViewer {
1696    my ( $self ) = @_;   
1697
1698    if(!$self->imageviewer->IsShown){
1699        $self->imageviewer->Show(1);
1700    }
1701}
1702
1703
1704sub ActivateImageViewer {
1705    my ( $self ) = @_;   
1706   
1707}
1708
1709
1710sub SetNewFilesViewerRefresh {
1711
1712    my ( $self ) = @_;   
1713
1714    my $wximagelist = $self->imagelist->wx_thumb_imglist;
1715    #print Dumper "SetNewFilesViewerRefresh", $self->imagelist->current_image;
1716    my $indx = $wximagelist->Add(
1717        Wx::Bitmap->new( 
1718            $self->imagelist->current_image->wx_thumb_file, 
1719            $self->GetWxBitmapType($self->imagelist->type), 
1720        )
1721    ) if defined $self->imagelist->current_image->wx_thumb_file;
1722    #print $self->imagelist->current_image->wx_thumb_file, " added with index ", $indx, "\n";   
1723   
1724    $self->imageviewer->Refresh(
1725        $wximagelist
1726    );
1727
1728    Wx::Yield();
1729}
1730
1731
1732
1733# prepare and upload image_selection
1734sub ProcessImageSelection {
1735    my ( $self ) = @_;
1736
1737    return if !scalar @{$self->imagelist->sums};
1738
1739    if( scalar @{$self->imagelist->categories} ){
1740        # all selected is implicit
1741        if(!scalar @{$self->imageviewer->GetSelectedItems}){
1742       
1743            $self->imagelist->image_selection(
1744                $self->imageviewer->GetAllItems
1745            );
1746        }
1747       
1748        return if( !defined $self->imagelist->image_selection );
1749        return if( !scalar @{$self->imagelist->image_selection} );
1750       
1751        $self->upload_progressdlg->Destroy if defined $self->upload_progressdlg;
1752        $self->upload_progressdlg(
1753            Uploader::GUI::wxImageProcessingProgressDlg->new(
1754                { 
1755                    title    => gettext("Image upload progress information"),
1756                    bt_label => gettext("Cancel upload"),
1757                    bt_close_label => gettext("Close"), 
1758                    stop_processing => sub { $self->imagelist->stop_processing(1); Wx::Yield(); }, 
1759                 }
1760            )       
1761        );
1762        # modeless dialog
1763        $self->upload_progressdlg->Show(1);
1764        Wx::Yield();
1765        eval {
1766            $self->imagelist->UploadSelection;
1767        };
1768        if($@){
1769            Wx::MessageBox( 
1770                sprintf(
1771                    gettext("Upload cancelled"),
1772                ),
1773                gettext("Piwigo upload information"),
1774                wxOK | wxICON_INFORMATION, 
1775            );
1776        }
1777    }
1778    else {
1779        Wx::MessageBox( 
1780            sprintf(
1781                "%s", 
1782                wxTheApp->branding->{'What is the destination category?'}
1783            ),
1784            gettext("Piwigo upload error"),
1785            wxOK | wxICON_EXCLAMATION, 
1786        );
1787    }
1788}
1789
1790
1791sub SetNewFilesProgress {
1792    my ( $self ) = @_;
1793
1794    my $imagelist = $self->imagelist;
1795
1796    $self->progressdlg->processing(
1797        sprintf(
1798            $imagelist->progress_msg, 
1799            $imagelist->current_image->file,
1800        )
1801    );
1802
1803    eval {
1804        $self->progressdlg->image->SetSize([ $imagelist->wx_thumb_size, $imagelist->wx_thumb_size]);
1805        $self->progressdlg->image->SetBitmap(wxNullBitmap);
1806        $self->progressdlg->image->SetBitmap(
1807            Wx::Bitmap->new( 
1808                $imagelist->current_image->wx_thumb_file,
1809                $self->GetWxBitmapType( $imagelist->type )
1810            )
1811        );
1812        $self->progressdlg->progress(
1813            $imagelist->count * ( 100/scalar @{$imagelist->new_files} )
1814        );
1815        $self->progressdlg->LogProgress();
1816    };
1817    Wx::Yield();
1818}
1819
1820sub OnClose {
1821  my $self = shift;
1822
1823
1824    # Restaure previous log wnd
1825    Wx::Log::SetActiveTarget( $self->oldlogwnd );
1826
1827    # allways store
1828 
1829    wxTheApp->StoreConnectionProperties;
1830   
1831    $self->imagelist->Store;
1832    wxTheApp->login_dlg->Destroy;   
1833
1834   
1835    wxTheApp->imageviewerIndex(
1836        $self->current_imageviewer_index
1837    );
1838   
1839    my $frameLayout = {};
1840   
1841    ( $frameLayout->{pX}, $frameLayout->{pY}, $frameLayout->{W}, $frameLayout->{H} ) = ( $self->GetPositionXY, $self->GetSizeWH ) ; 
1842   
1843    wxTheApp->frameLayout(
1844        $frameLayout
1845    );
1846
1847    wxTheApp->StoreLayoutProperties;
1848
1849    #destroy hidden dialogs
1850    $self->global_settings_panel->Destroy;
1851    $self->image_preview->Destroy;
1852    $self->image_prop_exif->Destroy;
1853    $self->getting_started->Destroy;
1854
1855    $self->progressdlg->Destroy if defined $self->progressdlg;
1856    $self->upload_progressdlg->Destroy if defined $self->upload_progressdlg;
1857
1858    $self->Destroy;
1859}
1860
1861
1862sub create_toolbar {
1863    my( $self ) = @_;
1864
1865    my $tb = Wx::ToolBar->new( $self, -1, wxDefaultPosition, [600, -1], wxTB_FLAT );
1866    $tb->SetToolBitmapSize( wxSIZE( 32, 32 ) );
1867    map {
1868        my $icon1 = Wx::Icon->new();
1869        eval {
1870            $icon1->LoadFile($_->[2], $_->[3]);
1871        };
1872        my $tb_icon1 = Wx::Bitmap->new( $icon1 );
1873
1874        my $icon2 = Wx::Icon->new();
1875        eval {
1876            $icon2->LoadFile($_->[5], $_->[3]);
1877        };
1878        my $tb_icon2 = Wx::Bitmap->new( $icon2 );
1879
1880
1881        $tb->AddTool( $_->[0], $_->[1], $tb_icon1, $tb_icon2, wxITEM_NORMAL, $_->[1] );
1882        $tb->EnableTool( $_->[0], $_->[4]);
1883    }
1884    (
1885        [
1886            100, 
1887            gettext("Getting started"), 
1888            wxTheApp->resource_path('tb_getting_started.png'), 
1889            wxBITMAP_TYPE_PNG, 
1890            1, 
1891            wxTheApp->resource_path('tb_getting_started.png'), 
1892            gettext("Display getting started panel")
1893        ],
1894        [
1895            101, 
1896            gettext("Add photo to selection"), 
1897            wxTheApp->resource_path('tb_add.png'), 
1898            wxBITMAP_TYPE_PNG, 
1899            1, 
1900            wxTheApp->resource_path('tb_add.png'), 
1901            gettext("Add photo to selection for resizing and uploading")
1902        ],
1903        [
1904            102, 
1905            gettext("Remove photo from selection"), 
1906            wxTheApp->resource_path('tb_remove.png'), 
1907            wxBITMAP_TYPE_PNG, 
1908            1, 
1909            wxTheApp->resource_path('tb_remove.png'),
1910            gettext("Remove photo from selection. Files are not deleted ")
1911        ],
1912        [
1913            103, 
1914            gettext("Upload to Piwigo"), 
1915            wxTheApp->resource_path('tb_upload.png'), 
1916            wxBITMAP_TYPE_PNG, 
1917            wxTheApp->use_offline ? 0 : 1, 
1918            wxTheApp->resource_path('tb_upload.png'),
1919            gettext("Upload photos to Piwigo.")
1920        ],
1921        [
1922            104, 
1923            gettext("Global settings"), 
1924            wxTheApp->resource_path('tb_settings.png'), 
1925            wxBITMAP_TYPE_PNG, 
1926            0, 
1927            wxTheApp->resource_path('tb_settings.png'),
1928            gettext("Change global settings.")
1929        ],
1930        [
1931            105, 
1932            gettext("Language choice"), 
1933            wxTheApp->resource_path('tb_i18n.png'), 
1934            wxBITMAP_TYPE_PNG, 
1935            1, 
1936            wxTheApp->resource_path('tb_i18n.png'),
1937            gettext("Language choice")
1938        ],
1939   
1940    );
1941   
1942    $tb->AddSeparator;
1943   
1944    $tb->AddControl(
1945        Wx::Choice->new(
1946        $tb,
1947            106,
1948            wxDefaultPosition,
1949            [300, -1],
1950            [],
1951        )
1952    );
1953    my $ch = $tb->FindWindow(106);
1954    $ch->SetToolTip(gettext("How photo selection is displayed"));
1955    map {
1956        $ch->Append(gettext($_), $_);
1957    }(
1958        "Thumbnail and caption",
1959        "Thumbnail",
1960        "Property list"
1961    );
1962   
1963    $ch->SetStringSelection(gettext($self->imagelist->display_mode));
1964    $tb->Realize;
1965
1966    $self->toolbar(
1967        $tb
1968    );
1969    $self->SetToolBar($tb);
1970
1971    return $tb;
1972}
1973
1974sub OnPhotoSelMode {
1975    my ( $self, $event )= @_;
1976   
1977    $self->imagelist->display_mode(
1978        $event->GetClientData
1979    );
1980
1981    $self->imageviewer->change_display_mode(1);
1982}
1983
1984sub _create_textctrl {
1985    my( $self, $parent, $text, $size ) = @_;
1986
1987    return Wx::TextCtrl->new( $parent, -1, $text, [0, 0], $size,
1988                              wxNO_BORDER | wxTE_MULTILINE | wxTE_READONLY  );
1989}
1990
1991sub create_textctrl {
1992    my( $self, $text, $size ) = @_;
1993
1994    return $self->_create_textctrl( $self, $text, $size );
1995}
1996
1997sub DESTROY {
1998    my( $self ) = @_;
1999
2000}
2001
2002
2003
20041;
2005
2006
2007
2008
2009
2010package DNDImageListDropTarget;
2011use Wx qw/wxTheApp/;
2012use base qw(Wx::FileDropTarget Class::Accessor::Fast);
2013
2014__PACKAGE__->mk_accessors( 
2015    qw/
2016          imageviewer
2017      /
2018);
2019
2020sub new {
2021  my $class = shift;
2022  my $imageviewer = shift;
2023  my $self = $class->SUPER::new( @_ );
2024
2025  $self->imageviewer($imageviewer);
2026
2027  return $self;
2028}
2029
2030sub OnDropFiles {
2031  my( $self, $x, $y, $files ) = @_;
2032
2033  wxTheApp->frame->SetNewFiles($files) ;
2034}
2035
2036
2037
2038
20391;
2040
2041
2042package DNDCategoryTreeDropTarget;
2043
2044use base qw(Wx::TextDropTarget Class::Accessor::Fast);
2045use Data::Dumper;
2046use Wx qw/
2047              wxDragNone
2048              wxDragCopy
2049              wxDragMove
2050         /;
2051
2052__PACKAGE__->mk_accessors( 
2053    qw/
2054          tree
2055          frame
2056      /
2057);
2058
2059sub new {
2060  my ( $class, $tree ) = @_;
2061  my $self = $class->SUPER::new();
2062
2063  $self->tree($tree);
2064  $self->frame($tree->GetParent);
2065  return $self;
2066}
2067
2068
2069
2070sub OnDropText {
2071  my( $self, $x, $y, $textdata ) = @_;
2072
2073  # must be $VAR1 because $textdata is the result of Data::Dumper
2074  my $VAR1;
2075  eval $textdata;
2076  eval {
2077      if(scalar @$VAR1){
2078             my @items;
2079             if(scalar @items < 2) {
2080               my ($dropItem, $flag) = $self->tree->HitTest([$x, $y]);
2081                 push @items, $dropItem;
2082             }
2083             else {
2084                 @items = $self->tree->GetSelections;
2085             }
2086             
2087             # remove root item which is not a valid category
2088             @items = grep { $self->tree->GetPlData( $_ ) != -1 } @items;
2089             
2090           $self->frame->imagelist->categories(
2091               [
2092                   map {
2093                       $self->tree->GetPlData( $_ )->{id};
2094                   }
2095                   @items
2096               ]
2097           );
2098           
2099             $self->frame->imagelist->image_selection($VAR1);
2100             $self->frame->ProcessImageSelection ;
2101      }   
2102  };
2103}
2104
2105
21061;
Note: See TracBrowser for help on using the repository browser.