~ubuntu-branches/ubuntu/saucy/padre/saucy-proposed

« back to all changes in this revision

Viewing changes to lib/Padre/Wx/VCS.pm

  • Committer: Package Import Robot
  • Author(s): Dominique Dumont, gregor herrmann, Dominique Dumont
  • Date: 2012-01-04 12:04:20 UTC
  • mfrom: (1.3.3)
  • Revision ID: package-import@ubuntu.com-20120104120420-i5oybqwf91m1d3il
Tags: 0.92.ds1-1
[ gregor herrmann ]
* Remove debian/source/local-options; abort-on-upstream-changes
  and unapply-patches are default in dpkg-source since 1.16.1.
* Swap order of alternative (build) dependencies after the perl
  5.14 transition.

[ Dominique Dumont ]
* Imported Upstream version 0.92.ds1
* removed fix-spelling patch (applied upstream)
* lintian-override: use wildcard to avoid listing a gazillion files
* updated size of some 'not-real-man-page' entries
* rules: remove dekstop cruft (replaced by a file provided in debian
  directory)
* control: removed Breaks statement. Add /me to uploaders. Updated
  dependencies
* rules: make sure that non-DFSG file (i.e. the cute butterfly, sigh)
  is not distributed

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package Padre::Wx::VCS;
 
2
 
 
3
use 5.008;
 
4
use strict;
 
5
use warnings;
 
6
use Padre::Role::Task     ();
 
7
use Padre::Wx::Role::View ();
 
8
use Padre::Wx             ();
 
9
use Padre::Wx::FBP::VCS   ();
 
10
use Padre::Task::VCS      ();
 
11
use Padre::Logger;
 
12
 
 
13
our $VERSION = '0.92';
 
14
our @ISA     = qw{
 
15
        Padre::Role::Task
 
16
        Padre::Wx::Role::View
 
17
        Padre::Wx::FBP::VCS
 
18
};
 
19
 
 
20
use constant {
 
21
        RED        => Wx::Colour->new('red'),
 
22
        DARK_GREEN => Wx::Colour->new( 0x00, 0x90, 0x00 ),
 
23
        BLUE       => Wx::Colour->new('blue'),
 
24
        GRAY       => Wx::Colour->new('gray'),
 
25
        BLACK      => Wx::Colour->new('black'),
 
26
};
 
27
 
 
28
# Constructor
 
29
sub new {
 
30
        my $class = shift;
 
31
        my $main  = shift;
 
32
        my $panel = shift || $main->right;
 
33
        my $self  = $class->SUPER::new($panel);
 
34
 
 
35
        # Set the bitmap button icons
 
36
        $self->{add}->SetBitmapLabel( Padre::Wx::Icon::find('actions/list-add') );
 
37
        $self->{delete}->SetBitmapLabel( Padre::Wx::Icon::find('actions/list-remove') );
 
38
        $self->{update}->SetBitmapLabel( Padre::Wx::Icon::find('actions/stock_update-data') );
 
39
        $self->{commit}->SetBitmapLabel( Padre::Wx::Icon::find('actions/document-save') );
 
40
        $self->{revert}->SetBitmapLabel( Padre::Wx::Icon::find('actions/edit-undo') );
 
41
        $self->{refresh}->SetBitmapLabel( Padre::Wx::Icon::find('actions/view-refresh') );
 
42
 
 
43
        # Set up column sorting
 
44
        $self->{sort_column} = 0;
 
45
        $self->{sort_desc}   = 1;
 
46
 
 
47
        # Setup columns
 
48
        my @column_headers = (
 
49
                Wx::gettext('Status'),
 
50
                Wx::gettext('Path'),
 
51
                Wx::gettext('Author'),
 
52
                Wx::gettext('Revision'),
 
53
        );
 
54
        my $index = 0;
 
55
        for my $column_header (@column_headers) {
 
56
                $self->{list}->InsertColumn( $index++, $column_header );
 
57
        }
 
58
 
 
59
        # Column ascending/descending image
 
60
        my $images = Wx::ImageList->new( 16, 16 );
 
61
        $self->{images} = {
 
62
                asc => $images->Add(
 
63
                        Wx::ArtProvider::GetBitmap(
 
64
                                'wxART_GO_UP',
 
65
                                'wxART_OTHER_C',
 
66
                                [ 16, 16 ],
 
67
                        ),
 
68
                ),
 
69
                desc => $images->Add(
 
70
                        Wx::ArtProvider::GetBitmap(
 
71
                                'wxART_GO_DOWN',
 
72
                                'wxART_OTHER_C',
 
73
                                [ 16, 16 ],
 
74
                        ),
 
75
                ),
 
76
        };
 
77
        $self->{list}->AssignImageList( $images, Wx::IMAGE_LIST_SMALL );
 
78
 
 
79
        # Tidy the list
 
80
        Padre::Util::tidy_list( $self->{list} );
 
81
 
 
82
        # Update the checkboxes with their corresponding values in the
 
83
        # configuration
 
84
        my $config = $main->config;
 
85
        $self->{show_normal}->SetValue( $config->vcs_normal_shown );
 
86
        $self->{show_unversioned}->SetValue( $config->vcs_unversioned_shown );
 
87
        $self->{show_ignored}->SetValue( $config->vcs_ignored_shown );
 
88
 
 
89
        # Hide vcs command buttons at startup
 
90
        $self->{commit}->Hide;
 
91
        $self->{add}->Hide;
 
92
        $self->{delete}->Hide;
 
93
        $self->{revert}->Hide;
 
94
        $self->{update}->Hide;
 
95
 
 
96
        return $self;
 
97
}
 
98
 
 
99
 
 
100
 
 
101
 
 
102
 
 
103
######################################################################
 
104
# Padre::Wx::Role::View Methods
 
105
 
 
106
sub view_panel {
 
107
        return 'right';
 
108
}
 
109
 
 
110
sub view_label {
 
111
        shift->gettext_label(@_);
 
112
}
 
113
 
 
114
sub view_close {
 
115
        $_[0]->main->show_vcs(0);
 
116
}
 
117
 
 
118
sub view_start {
 
119
}
 
120
 
 
121
sub view_stop {
 
122
        my $self = shift;
 
123
 
 
124
        # Clear out any state and tasks
 
125
        $self->task_reset;
 
126
        $self->clear;
 
127
 
 
128
        return;
 
129
}
 
130
 
 
131
#####################################################################
 
132
# Event Handlers
 
133
 
 
134
sub on_refresh_click {
 
135
        $_[0]->main->vcs->refresh( $_[0]->current );
 
136
}
 
137
 
 
138
#####################################################################
 
139
# General Methods
 
140
 
 
141
sub gettext_label {
 
142
        Wx::gettext('Version Control');
 
143
}
 
144
 
 
145
# Clear everything...
 
146
sub clear {
 
147
        my $self = shift;
 
148
 
 
149
        $self->{list}->DeleteAllItems;
 
150
        $self->_show_command_bar(0);
 
151
 
 
152
        return;
 
153
}
 
154
 
 
155
# Nothing to implement here
 
156
sub relocale {
 
157
        return;
 
158
}
 
159
 
 
160
sub refresh {
 
161
        my $self    = shift;
 
162
        my $current = shift or return;
 
163
        my $command = shift || Padre::Task::VCS::VCS_STATUS;
 
164
 
 
165
        my $document = $current->document;
 
166
 
 
167
        # Abort any in-flight checks
 
168
        $self->task_reset;
 
169
 
 
170
        # Flush old results
 
171
        $self->clear;
 
172
 
 
173
        # Do not display anything where there is no open documents
 
174
        return unless $document;
 
175
 
 
176
        # Shortcut if there is nothing in the document to do
 
177
        if ( $document->is_unused ) {
 
178
                $self->{status}->SetValue( Wx::gettext('Current file is not saved in a version control system') );
 
179
                return;
 
180
        }
 
181
 
 
182
        # Retrieve project version control system
 
183
        my $vcs = $document->project->vcs;
 
184
 
 
185
        # No version control system?
 
186
        unless ($vcs) {
 
187
                $self->{status}->SetValue( Wx::gettext('Current file is not in a version control system') );
 
188
                return;
 
189
        }
 
190
 
 
191
        # Not supported VCS check
 
192
        if ( $vcs ne Padre::Constant::SUBVERSION and $vcs ne Padre::Constant::GIT ) {
 
193
                $self->{status}->SetValue( sprintf( Wx::gettext('%s version control is not currently available'), $vcs ) );
 
194
                return;
 
195
        }
 
196
 
 
197
 
 
198
        # Start a background VCS status task
 
199
        $self->task_request(
 
200
                task     => 'Padre::Task::VCS',
 
201
                command  => $command,
 
202
                document => $document,
 
203
        );
 
204
 
 
205
        return 1;
 
206
}
 
207
 
 
208
sub task_finish {
 
209
        my $self = shift;
 
210
        my $task = shift;
 
211
        $self->{model} = Params::Util::_ARRAY0( $task->{model} ) or return;
 
212
        $self->{vcs} = $task->{vcs} or return;
 
213
 
 
214
        $self->render;
 
215
}
 
216
 
 
217
sub render {
 
218
        my $self = shift;
 
219
 
 
220
        # Clear if needed. Please note that this is needed
 
221
        # for sorting
 
222
        $self->clear;
 
223
 
 
224
        return unless $self->{model};
 
225
 
 
226
        # Subversion status codes
 
227
        my %SVN_STATUS = (
 
228
                ' ' => { name => Wx::gettext('Normal') },
 
229
                'A' => { name => Wx::gettext('Added') },
 
230
                'D' => { name => Wx::gettext('Deleted') },
 
231
                'M' => { name => Wx::gettext('Modified') },
 
232
                'C' => { name => Wx::gettext('Conflicted') },
 
233
                'I' => { name => Wx::gettext('Ignored') },
 
234
                '?' => { name => Wx::gettext('Unversioned') },
 
235
                '!' => { name => Wx::gettext('Missing') },
 
236
                '~' => { name => Wx::gettext('Obstructed') }
 
237
        );
 
238
 
 
239
        # GIT status code
 
240
        my %GIT_STATUS = (
 
241
                ' ' => { name => Wx::gettext('Unmodified') },
 
242
                'M' => { name => Wx::gettext('Modified') },
 
243
                'A' => { name => Wx::gettext('Added') },
 
244
                'D' => { name => Wx::gettext('Deleted') },
 
245
                'R' => { name => Wx::gettext('Renamed') },
 
246
                'C' => { name => Wx::gettext('Copied') },
 
247
                'U' => { name => Wx::gettext('Updated but unmerged') },
 
248
                '?' => { name => Wx::gettext('Unversioned') },
 
249
        );
 
250
 
 
251
        my %vcs_status = $self->{vcs} eq Padre::Constant::SUBVERSION ? %SVN_STATUS : %GIT_STATUS;
 
252
 
 
253
        # Add a zero count key for VCS status hash
 
254
        $vcs_status{$_}->{count} = 0 for keys %vcs_status;
 
255
 
 
256
        # Retrieve the state of the checkboxes
 
257
        my $show_normal      = $self->{show_normal}->IsChecked      ? 1 : 0;
 
258
        my $show_unversioned = $self->{show_unversioned}->IsChecked ? 1 : 0;
 
259
        my $show_ignored     = $self->{show_ignored}->IsChecked     ? 1 : 0;
 
260
 
 
261
        my $index = 0;
 
262
        my $list  = $self->{list};
 
263
 
 
264
        $self->_sort_model(%vcs_status);
 
265
        my $model = $self->{model};
 
266
 
 
267
        my $model_index = 0;
 
268
        for my $rec (@$model) {
 
269
                my $status      = $rec->{status};
 
270
                my $path_status = $vcs_status{$status};
 
271
                if ( defined $path_status ) {
 
272
 
 
273
                        if ( $show_normal or $status ne ' ' ) {
 
274
 
 
275
                                if ( $show_unversioned or $status ne '?' ) {
 
276
                                        if ( $show_ignored or $status ne 'I' ) {
 
277
 
 
278
                                                # Add a version control path to the list
 
279
                                                $list->InsertImageStringItem( $index, $path_status->{name}, -1 );
 
280
                                                $list->SetItemData( $index, $model_index );
 
281
                                                $list->SetItem( $index, 1, $rec->{path} );
 
282
                                                my $color;
 
283
                                                if ( $status eq ' ' ) {
 
284
                                                        $color = DARK_GREEN;
 
285
                                                } elsif ( $status eq 'A' or $status eq 'D' ) {
 
286
                                                        $color = RED;
 
287
                                                } elsif ( $status eq 'M' ) {
 
288
                                                        $color = BLUE;
 
289
                                                } elsif ( $status eq 'I' ) {
 
290
                                                        $color = GRAY;
 
291
                                                } else {
 
292
                                                        $color = BLACK;
 
293
                                                }
 
294
                                                $list->SetItemTextColour( $index, $color );
 
295
 
 
296
                                                $list->SetItem( $index,   2, $rec->{author} );
 
297
                                                $list->SetItem( $index++, 3, $rec->{revision} );
 
298
                                        }
 
299
                                }
 
300
                        }
 
301
 
 
302
                }
 
303
                $path_status->{count}++;
 
304
                $model_index++;
 
305
        }
 
306
 
 
307
        # Select the first item
 
308
        if ( $list->GetItemCount > 0 ) {
 
309
                $list->SetItemState( 0, Wx::LIST_STATE_SELECTED, Wx::LIST_STATE_SELECTED );
 
310
        }
 
311
 
 
312
        # Show Subversion statistics
 
313
        my $message = '';
 
314
        for my $status ( sort keys %vcs_status ) {
 
315
                my $vcs_status_obj = $vcs_status{$status};
 
316
                next if $vcs_status_obj->{count} == 0;
 
317
                if ( length($message) > 0 ) {
 
318
                        $message .= Wx::gettext(', ');
 
319
                }
 
320
                $message .= sprintf( '%s=%d', $vcs_status_obj->{name}, $vcs_status_obj->{count} );
 
321
        }
 
322
        $self->{status}->SetValue($message);
 
323
 
 
324
        $self->_show_command_bar( $list->GetItemCount > 0 )
 
325
                if $self->main->config->vcs_enable_command_bar;
 
326
 
 
327
        # Update the list sort image
 
328
        $self->set_icon_image( $self->{sort_column}, $self->{sort_desc} );
 
329
 
 
330
        # Tidy the list
 
331
        Padre::Util::tidy_list($list);
 
332
 
 
333
        return 1;
 
334
}
 
335
 
 
336
sub _show_command_bar {
 
337
        my ( $self, $shown ) = @_;
 
338
 
 
339
        $self->{commit}->Show($shown);
 
340
        $self->{add}->Show($shown);
 
341
        $self->{delete}->Show($shown);
 
342
        $self->{revert}->Show($shown);
 
343
        $self->{update}->Show($shown);
 
344
        $self->Layout;
 
345
}
 
346
 
 
347
sub _sort_model {
 
348
        my ( $self, %vcs_status ) = @_;
 
349
 
 
350
        my @model = @{ $self->{model} };
 
351
        if ( $self->{sort_column} == 0 ) {
 
352
 
 
353
                # Sort by status
 
354
                @model = sort { $vcs_status{ $a->{status} }{name} cmp $vcs_status{ $b->{status} }{name} } @model;
 
355
 
 
356
        } elsif ( $self->{sort_column} == 1 ) {
 
357
 
 
358
                # Sort by path
 
359
                @model = sort { $a->{path} cmp $b->{path} } @model;
 
360
        } elsif ( $self->{sort_column} == 2 ) {
 
361
 
 
362
                # Sort by author
 
363
                @model = sort { $a->{author} cmp $b->{author} } @model;
 
364
        } elsif ( $self->{sort_column} == 3 ) {
 
365
 
 
366
                # Sort by revision
 
367
                @model = sort { $a->{revision} cmp $b->{revision} } @model;
 
368
 
 
369
        }
 
370
 
 
371
        if ( $self->{sort_desc} ) {
 
372
 
 
373
                # reverse the sorting
 
374
                @model = reverse @model;
 
375
        }
 
376
 
 
377
        $self->{model} = \@model;
 
378
}
 
379
 
 
380
# Called when a version control list column is clicked
 
381
sub on_list_column_click {
 
382
        my ( $self, $event ) = @_;
 
383
 
 
384
        my $column   = $event->GetColumn;
 
385
        my $prevcol  = $self->{sort_column};
 
386
        my $reversed = $self->{sort_desc};
 
387
        $reversed = $column == $prevcol ? !$reversed : 0;
 
388
        $self->{sort_column} = $column;
 
389
        $self->{sort_desc}   = $reversed;
 
390
 
 
391
        # Reset the previous column sort image
 
392
        $self->set_icon_image( $prevcol, -1 );
 
393
 
 
394
        $self->render;
 
395
 
 
396
        return;
 
397
}
 
398
 
 
399
sub set_icon_image {
 
400
        my ( $self, $column, $image_index ) = @_;
 
401
 
 
402
        my $item = Wx::ListItem->new;
 
403
        $item->SetMask(Wx::LIST_MASK_IMAGE);
 
404
        $item->SetImage($image_index);
 
405
        $self->{list}->SetColumn( $column, $item );
 
406
 
 
407
        return;
 
408
}
 
409
 
 
410
sub on_list_item_activated {
 
411
        my ( $self, $event ) = @_;
 
412
 
 
413
        my $main     = $self->main;
 
414
        my $rec      = $self->{model}->[ $self->{list}->GetItemData( $event->GetIndex ) ] or return;
 
415
        my $filename = $rec->{fullpath};
 
416
        eval {
 
417
 
 
418
                # Try to open the file now
 
419
                if ( my $id = $main->editor_of_file($filename) ) {
 
420
                        my $page = $main->notebook->GetPage($id);
 
421
                        $page->SetFocus;
 
422
                } else {
 
423
                        $main->setup_editor($filename);
 
424
                }
 
425
 
 
426
                # Select the next difference after opening the file
 
427
                Wx::Event::EVT_IDLE(
 
428
                        $main,
 
429
                        sub {
 
430
                                $main->{diff}->select_next_difference;
 
431
                                Wx::Event::EVT_IDLE( $main, undef );
 
432
                        },
 
433
                ) if $main->config->feature_document_diffs;
 
434
 
 
435
        };
 
436
        $main->error( Wx::gettext('Error while trying to perform Padre action') ) if $@;
 
437
}
 
438
 
 
439
# Called when "Show normal" checkbox is clicked
 
440
sub on_show_normal_click {
 
441
        my ( $self, $event ) = @_;
 
442
 
 
443
        # Save to configuration
 
444
        my $config = $self->main->config;
 
445
        $config->apply( vcs_normal_shown => $event->IsChecked ? 1 : 0 );
 
446
        $config->write;
 
447
 
 
448
        # refresh list
 
449
        $self->render;
 
450
}
 
451
 
 
452
# Called when "Show unversioned" checkbox is clicked
 
453
sub on_show_unversioned_click {
 
454
        my ( $self, $event ) = @_;
 
455
 
 
456
        # Save to configuration
 
457
        my $config = $self->main->config;
 
458
        $config->apply( vcs_unversioned_shown => $event->IsChecked ? 1 : 0 );
 
459
        $config->write;
 
460
 
 
461
        # refresh list
 
462
        $self->render;
 
463
}
 
464
 
 
465
# Called when "Show ignored" checkbox is clicked
 
466
sub on_show_ignored_click {
 
467
        my ( $self, $event ) = @_;
 
468
 
 
469
        # Save to configuration
 
470
        my $config = $self->main->config;
 
471
        $config->apply( vcs_ignored_shown => $event->IsChecked ? 1 : 0 );
 
472
        $config->write;
 
473
 
 
474
        # refresh list
 
475
        $self->render;
 
476
}
 
477
 
 
478
# Called when "Commit" button is clicked
 
479
sub on_commit_click {
 
480
        my $self = shift;
 
481
        my $main = $self->main;
 
482
 
 
483
        return
 
484
                unless $main->yes_no(
 
485
                Wx::gettext("Do you want to commit?"),
 
486
                Wx::gettext('Commit file/directory to repository?')
 
487
                );
 
488
 
 
489
        $main->vcs->refresh( $self->current, Padre::Task::VCS::VCS_COMMIT );
 
490
}
 
491
 
 
492
# Called when "Add" button is clicked
 
493
sub on_add_click {
 
494
        my $self = shift;
 
495
 
 
496
        my $main           = $self->main;
 
497
        my $list           = $self->{list};
 
498
        my $selected_index = $list->GetNextItem( -1, Wx::LIST_NEXT_ALL, Wx::LIST_STATE_SELECTED );
 
499
        return if $selected_index == -1;
 
500
        my $rec = $self->{model}->[ $list->GetItemData($selected_index) ] or return;
 
501
        my $filename = $rec->{fullpath};
 
502
 
 
503
        return
 
504
                unless $main->yes_no(
 
505
                sprintf( Wx::gettext("Do you want to add '%s' to your repository"), $filename ),
 
506
                Wx::gettext('Add file to repository?')
 
507
                );
 
508
 
 
509
        $main->vcs->refresh( $self->current, Padre::Task::VCS::VCS_ADD );
 
510
}
 
511
 
 
512
# Called when "Delete" checkbox is clicked
 
513
sub on_delete_click {
 
514
        my $self           = shift;
 
515
        my $main           = $self->main;
 
516
        my $list           = $self->{list};
 
517
        my $selected_index = $list->GetNextItem( -1, Wx::LIST_NEXT_ALL, Wx::LIST_STATE_SELECTED );
 
518
        return if $selected_index == -1;
 
519
        my $rec = $self->{model}->[ $list->GetItemData($selected_index) ] or return;
 
520
        my $filename = $rec->{fullpath};
 
521
 
 
522
        return
 
523
                unless $main->yes_no(
 
524
                sprintf( Wx::gettext("Do you want to delete '%s' from your repository"), $filename ),
 
525
                Wx::gettext('Delete file from repository??')
 
526
                );
 
527
 
 
528
        $main->vcs->refresh( $self->current, Padre::Task::VCS::VCS_DELETE );
 
529
}
 
530
 
 
531
# Called when "Update" button is clicked
 
532
sub on_update_click {
 
533
        my $self = shift;
 
534
        my $main = $self->main;
 
535
 
 
536
        $main->vcs->refresh( $main->current, Padre::Task::VCS::VCS_UPDATE );
 
537
}
 
538
 
 
539
# Called when "Revert" button is clicked
 
540
sub on_revert_click {
 
541
        my $self           = shift;
 
542
        my $main           = $self->main;
 
543
        my $list           = $self->{list};
 
544
        my $selected_index = $list->GetNextItem( -1, Wx::LIST_NEXT_ALL, Wx::LIST_STATE_SELECTED );
 
545
        return if $selected_index == -1;
 
546
        my $rec = $self->{model}->[ $list->GetItemData($selected_index) ] or return;
 
547
        my $filename = $rec->{fullpath};
 
548
 
 
549
        return
 
550
                unless $main->yes_no(
 
551
                sprintf( Wx::gettext("Do you want to revert changes to '%s'"), $filename ),
 
552
                Wx::gettext('Revert changes?')
 
553
                );
 
554
 
 
555
        $main->vcs->refresh( $self->current, Padre::Task::VCS::VCS_REVERT );
 
556
}
 
557
 
 
558
1;
 
559
 
 
560
# Copyright 2008-2011 The Padre development team as listed in Padre.pm.
 
561
# LICENSE
 
562
# This program is free software; you can redistribute it and/or
 
563
# modify it under the same terms as Perl 5 itself.