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

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

Feature 1417 added : ability to define tags for a photo selection.

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