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

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

Feature 1461 added : ability to specify photo file names in the command line.

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