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

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

Feature 1504 : move language switch in Preferences.

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