source: extensions/pLoader/trunk/src/Uploader/Images.pm @ 6707

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

use tranfer error messages in progress list. various bug fixes.

File size: 13.1 KB
Line 
1package Uploader::Images;
2use strict;
3use base qw/Uploader::Object/;
4use Uploader::Image;
5use Digest::MD5::File qw/file_md5_hex md5_hex/;
6require Win32 if($^O =~ /MSWin32/);
7use Storable;
8use Data::Dumper;
9
10$|=1;
11
12my @cbk_properties = qw/
13    add_images_cbk
14    delete_images_cbk
15    create_wx_thumbnail_cbk
16    default_caption_cbk
17    default_caption_pattern_cbk
18/;
19
20my @storable_properties = qw/
21    ordered_image_ids
22    selection
23    _images
24    current_image
25    selection_tags
26    selection_privacy_level
27    selection_name
28    selection_comment
29    selection_author
30    selection_create_date
31    author
32    type
33    global_rank
34    global_rank_indx
35/;
36
37my @app_properties = qw/
38    eng_caption_patterns
39/;
40
41my @tmp_properties = qw/
42    to_be_removed_grank
43/;
44
45
46__PACKAGE__->mk_accessors(@cbk_properties);
47__PACKAGE__->mk_accessors(@storable_properties);
48__PACKAGE__->mk_accessors(@app_properties);
49__PACKAGE__->mk_accessors(@tmp_properties);
50
51
52sub Init {
53    my ( $self ) = @_;
54
55    $self->_images({}) if !defined $self->_images;
56    $self->ordered_image_ids([]) if !defined $self->ordered_image_ids;
57    $self->selection([]) if !defined $self->selection;
58    $self->global_rank(-1) if !defined $self->global_rank;
59    $self->global_rank_indx({}) if !defined $self->global_rank_indx;
60    $self->to_be_removed_grank([]) if !defined $self->to_be_removed_grank;
61}
62
63
64sub add_images {
65    my ( $self, $file_paths ) = @_;
66
67    my $files = [
68        map {
69            # to make sure that unicode chars in filenames are supported
70            {
71                ANSIPathName => $^O =~ /MSWin32/ ? Win32::GetANSIPathName($_) : $_,
72                PathName => $_,
73            },
74        }@$file_paths
75    ];
76
77    @$files = sort { $a->{PathName} cmp $b->{PathName} } @$files;   
78
79
80
81    foreach my $file ( @{$files} ) {
82        # to append at the end of list
83        $self->add_image_from_file($file);
84    }
85   
86    $self->Store;
87   
88}
89
90
91sub add_image_from_file {
92    my ( $self, $file ) = @_;   
93
94    # pLoader image id
95    my $image_id = $self->new_image_id(
96        $file->{ANSIPathName}
97    );
98
99    my $i = $self->image_count;
100    $self->ordered_image_ids->[$i] = $image_id ;
101
102    $self->global_rank(
103        1+$self->global_rank
104    );
105
106    $self->global_rank_indx->{
107        $self->global_rank
108    } = $i;
109
110    my $image = $self->_images->{
111        $image_id
112    };
113    if ( !defined $image ){
114        $image = Uploader::Image->new(
115            {
116                file              => $file->{ANSIPathName},
117                image_id          => $image_id,
118                caption           => $self->default_caption_cbk->(),
119                site_author       => $self->author,
120                add_rank          => $i,
121                site_tags         => [],
122                site_high_file    => $file->{ANSIPathName},
123                global_rank       => $self->global_rank,
124            }
125        );
126
127        $image->site_name(
128            $self->init_caption_from_pattern(
129                $image->file,
130                $image->create_date,
131                $image->add_rank,
132                $self->default_caption_cbk->(),
133                $self->default_caption_pattern_cbk->()
134            )
135        );
136
137        $self->create_wx_thumbnail_cbk->($image)
138            if 'CODE' eq ref $self->create_wx_thumbnail_cbk;
139
140        $self->_images->{$image_id} = $image ;
141    }
142
143    $self->add_images_cbk->($image->wx_thumb_file)
144       if 'CODE' eq ref $self->add_images_cbk;
145
146    $image;
147}
148
149
150sub new_image_id {
151    my ( $self, $filename ) = @_;
152
153    my $image_id = file_md5_hex(
154        $filename
155    );
156
157    $image_id;
158}
159
160
161sub Store {
162    my ( $self ) = @_;
163   
164    my $data = $self->get_storable(
165        [ 
166            qw/
167                version
168                storable_file
169            /,
170            @storable_properties
171        ] 
172   
173    );
174    eval {
175        #print Dumper $data;
176        store $data, $self->storable_file if defined $self->storable_file;
177    };
178    if($@){
179        print $@, "\n";   
180    }
181}
182
183
184sub set_current_image {
185    my ( $self, $indx ) = @_;
186    $self->current_image(
187        $indx != -1 ? $self->get_image($indx) : Uploader::Image->new()
188    );
189}
190
191
192sub get_image {
193    my ( $self, $indx ) = @_;
194   
195    return unless defined $indx;
196    my $id = $self->ordered_image_ids->[$indx];
197
198    $self->_images->{$id};
199}
200
201
202sub Image {
203    my ( $self, $id ) = @_;
204   
205    $self->_images->{$id};
206}
207
208
209sub is_empty {
210    my ( $self ) = @_;
211
212    !$self->image_count;
213}
214
215
216sub image_count {
217    my ( $self ) = @_;
218
219    scalar @{$self->ordered_image_ids};
220}
221
222
223sub selection_count {
224    my ( $self ) = @_;
225
226    scalar @{$self->selection};
227}
228
229
230sub remove_selection {
231    my ( $self ) = @_;
232   
233    return if ( $self->is_empty );
234    return if (! defined $self->selection );
235   
236    $self->_remove_selection($self->selection);
237    # clear image selection
238    $self->selection([]);
239}
240
241
242sub remove_processed {
243    my ( $self ) = @_;
244   
245    return if ( $self->is_empty );
246    return if (! defined $self->to_be_removed_grank );
247
248    my $to_remove_indx = [];
249    # check if the global rank correspond
250    # the image may have changed
251    foreach(@{$self->to_be_removed_grank}) {
252        my $indx = $self->global_rank_indx->{$_};
253        my $img;
254        if(defined $indx){
255            $img = $self->get_image($indx);
256        }
257        if(defined $img){
258            push @$to_remove_indx, $indx if
259                $img->global_rank == $_;
260        }
261    } 
262
263    $self->_remove_selection($to_remove_indx);
264    # clear image selection
265    $self->to_be_removed_grank([]);
266}
267
268
269sub _remove_selection {
270    my ( $self, $list ) = @_;
271    printf("_remove_selection %s\n", Dumper $list);
272    # the list is sorted, ascendant
273    # we reverse it to have
274    # higher first, and keep same indexes while deleting
275    @$list = reverse @$list;     
276    map {
277        $self->delete_image($_);
278        $self->delete_images_cbk->($_);
279        splice @{$self->ordered_image_ids}, $_, 1 ;
280        shift @$list;
281    }
282    @$list;
283
284}
285
286
287# postpone actual removal.
288sub set_to_be_removed {
289    my ( $self, $global_rank ) = @_;
290
291    push @{$self->to_be_removed_grank}, $global_rank;
292}
293
294
295sub delete_image {
296    my ( $self, $indx ) = @_;
297   
298    my $id = $self->ordered_image_ids->[$indx];
299
300    # have to check if that id is used more than once
301    my $count = grep { $id eq $_} @{$self->ordered_image_ids};
302
303    # global rank is unique
304    delete $self->global_rank_indx->{
305        $self->_images->{$id}->global_rank
306    };
307
308    delete $self->_images->{$id} unless $count > 1;
309}
310
311
312sub multi_selection_mode {
313    my ( $self ) = @_;
314
315    scalar @{$self->selection} > 1;
316}
317
318
319sub set_image_selection_tags {
320    my ( $self, $tags ) = @_;
321
322    $self->selection_tags($tags) if 'ARRAY' eq ref $tags;
323
324    # append to each image
325    # if multiple selection
326    if($self->multi_selection_mode){
327        map {
328            # need to dedup
329            my $tags = [
330                @{$self->get_image($_)->site_tags},
331                @{$self->selection_tags},
332            ];
333            #deduplicate
334            my $uniq = {
335                 map { $_ => 1 } @$tags
336            };
337            @$tags = keys %$uniq;
338            $self->get_image($_)->site_tags(
339                $tags
340            );
341        }@{$self->selection};
342    }
343
344    $self->selection_tags;
345}
346
347
348sub set_image_selection_privacy_level {
349    my ( $self, $privacy_level ) = @_;
350
351    # append to each image
352    # if multiple selection
353    if($self->multi_selection_mode){
354        if(defined $privacy_level){
355            $self->selection_privacy_level($privacy_level);
356            map {
357                $self->get_image($_)->privacy_level(
358                    $privacy_level
359                ) ;
360            }@{$self->selection}
361        };
362    }
363
364    $self->selection_privacy_level;
365}
366
367
368sub set_image_selection_name {
369    my ( $self, $name, $param ) = @_;
370   
371    # works in single and multi selection mode
372    if(defined $name){
373        map {
374            my $_name;
375            if( 'CODE' eq ref $name ){
376                $_name = $name->($_, $param);
377            }
378            else{
379                $_name = $name;
380                $self->get_image($_)->caption(
381                    $_name
382                ) ;
383            }
384
385            $self->selection_name($_name);
386            $self->get_image($_)->site_name(
387                $_name
388            ) ;
389        }@{$self->selection}
390    }
391}
392
393
394sub set_image_selection_author {
395    my ( $self, $author ) = @_;
396
397    # append to each image
398    # if multiple selection
399    if($self->multi_selection_mode){
400        if(defined $author){
401            $self->selection_author($author);
402            map {
403                $self->get_image($_)->site_author(
404                    $author
405                ) ;
406            }@{$self->selection}
407        };
408    }
409
410    $self->selection_author;
411}
412
413sub set_image_selection_comment {
414    my ( $self, $comment ) = @_;
415
416    # append to each image
417    # if multiple selection
418    if($self->multi_selection_mode){
419        if(defined $comment){
420            $self->selection_comment($comment);
421            map {
422                $self->get_image($_)->site_comment(
423                    $comment
424                ) ;
425            }@{$self->selection}
426        };
427    }
428
429    $self->selection_comment;
430}
431
432
433sub set_image_selection_create_date {
434    my ( $self, $date ) = @_;
435
436    # append to each image
437    # if multiple selection
438    if($self->multi_selection_mode){
439        if(defined $date){
440            $self->selection_create_date($date);
441            map {
442                $self->get_image($_)->create_date(
443                    $date
444                ) ;
445            }@{$self->selection}
446        };
447    }
448
449    $self->selection_create_date;
450}
451
452
453sub get_current_image_caption {
454    my ( $self, $index, $pattern ) = @_;
455
456    $pattern = $self->eng_caption_patterns->{$pattern};
457
458    $self->set_current_image($index);
459
460    my $img = $self->current_image;
461
462    $self->init_caption_from_pattern(
463        $img->file,
464        $img->create_date,
465        $index,
466        $self->current_image->caption,
467        $pattern
468    );
469}
470
471
472sub init_caption_from_pattern {
473    my ( $self, $file, $create_date, $i, $caption, $pattern ) = @_;
474
475    my ( $yyyy, $mm, $dd, $hh, $mi, $ss ) = split /[:\s]/, $create_date ;
476 
477    my $chrono = join('', $yyyy, $mm, $dd);
478
479    my $caption_from_pattern;
480    my $ext;
481    my ( $vol, $path, $filename ) = File::Spec->splitpath($file);
482    ( $filename, $ext ) = split /\.\w+$/, $filename;
483   
484
485    if('Caption' eq $pattern){
486        $caption_from_pattern = $caption
487    }
488    elsif('File name' eq $pattern){
489        $caption_from_pattern = $filename
490    }
491    elsif('File path and name' eq $pattern){
492        $caption_from_pattern = sprintf(
493            "%s", 
494            File::Spec->catfile($path, $filename), 
495        )       
496    }   
497    elsif('Caption + rank number' eq $pattern){
498        $caption_from_pattern = sprintf(
499            "%s %s", 
500            $caption, 
501            1+$i,
502        )       
503    }   
504    elsif('Rank number + caption' eq $pattern){
505        $caption_from_pattern = sprintf(
506            "%s %s", 
507            1+$i,
508            $caption, 
509        )       
510    }   
511    elsif('Caption + create date chrono' eq $pattern){
512        $caption_from_pattern = sprintf(
513            "%s %s", 
514            $caption, 
515            $chrono,
516        )       
517    }   
518    elsif('Create date chrono + caption' eq $pattern){
519        $caption_from_pattern = sprintf(
520            "%s %s", 
521            $chrono,
522            $caption, 
523        )       
524    }
525    elsif('Create date chrono + rank' eq $pattern){
526        $caption_from_pattern = sprintf(
527            "%s %s", 
528            $chrono,
529            1+$i, 
530        )       
531    }
532    elsif('Rank + create date chrono' eq $pattern){
533        $caption_from_pattern = sprintf(
534            "%s %s", 
535            1+$i, 
536            $chrono,
537        )       
538    }
539
540    $caption_from_pattern;
541}
542
543
544# we cannot send objects in other threads
545# and thread use data as they were when the thread is created
546sub get_images {
547    my ( $self, $preferences, $destination_category, $all ) = @_;
548
549    my $image_id_list = $all ?
550        $self->ordered_image_ids :
551        [
552            map {
553                $self->ordered_image_ids->[$_]
554            }@{$self->selection}
555        ];
556
557    $self->get_images_data(
558        $image_id_list,
559        $preferences,
560        $destination_category
561    );
562}
563
564
565my $add_rank = 0;
566# copy data from image objects
567sub get_images_data {
568    my ( $self, $image_id_list, $preferences, $destination_category ) = @_;
569
570
571    return [
572        map{
573            $self->Image($_)->get_data($preferences, $destination_category, $add_rank++)
574        }@$image_id_list
575    ]
576}
577
578
579# when the progress list is cleared
580sub reset_add_rank {
581    my ( $self ) = @_;
582
583    $add_rank = 0;
584}
5851;
Note: See TracBrowser for help on using the repository browser.