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

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

Bug 1367 fixed : crash when refreshing categories.

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