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

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

Feature 1478 added : ability to set properties for a photo selection.

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