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

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

Bug 1646 fixed : use previously chosen image directory when opening file dialog.

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