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

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

Feature 1395 added : new layout for Global settings panel, using a Toolbook.

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