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

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

Reupload option management.

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