/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to olive/__init__.py

  • Committer: Jelmer Vernooij
  • Date: 2008-06-29 19:18:34 UTC
  • mto: This revision was merged to the branch mainline in revision 515.
  • Revision ID: jelmer@samba.org-20080629191834-ha2ecpv5szt96nge
Make sure signed testament matches repository data.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 #!/usr/bin/python
 
2
 
1
3
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
2
4
#
3
5
# This program is free software; you can redistribute it and/or modify
39
41
from bzrlib.ui import ui_factory
40
42
from bzrlib.workingtree import WorkingTree
41
43
 
 
44
from bzrlib.plugins.gtk import _i18n
42
45
from bzrlib.plugins.gtk.dialog import error_dialog, info_dialog, warning_dialog
43
46
from bzrlib.plugins.gtk.errors import show_bzr_error
44
47
from guifiles import GLADEFILENAME
53
56
from bzrlib.plugins.gtk.conflicts import ConflictsDialog
54
57
from bzrlib.plugins.gtk.initialize import InitDialog
55
58
from bzrlib.plugins.gtk.push import PushDialog
 
59
from bzrlib.plugins.gtk.revbrowser import RevisionBrowser
 
60
 
 
61
def about():
 
62
    """ Display the AboutDialog. """
 
63
    from bzrlib.plugins.gtk import __version__
 
64
    from bzrlib.plugins.gtk.olive.guifiles import GLADEFILENAME
 
65
 
 
66
    # Load AboutDialog description
 
67
    dglade = gtk.glade.XML(GLADEFILENAME, 'aboutdialog')
 
68
    dialog = dglade.get_widget('aboutdialog')
 
69
 
 
70
    # Set version
 
71
    dialog.set_version(__version__)
 
72
    dialog.set_authors([ _i18n("Lead Developer:"),
 
73
                         "Szilveszter Farkas <szilveszter.farkas@gmail.com>",
 
74
                         _i18n("Contributors:"),
 
75
                         "Jelmer Vernooij <jelmer@samba.org>",
 
76
                         "Mateusz Korniak <mateusz.korniak@ant.gliwice.pl>",
 
77
                         "Gary van der Merwe <garyvdm@gmail.com>" ])
 
78
    dialog.set_artists([ "Simon Pascal Klein <klepas@klepas.org>",
 
79
                         "Jakub Steiner <jimmac@novell.com>" ])
 
80
 
 
81
    dialog.run()
 
82
    # Destroy the dialog
 
83
    dialog.destroy()
56
84
 
57
85
class OliveGtk:
58
86
    """ The main Olive GTK frontend class. This is called when launching the
78
106
        # Get some important menu items
79
107
        self.menuitem_add_files = self.toplevel.get_widget('menuitem_add_files')
80
108
        self.menuitem_remove_files = self.toplevel.get_widget('menuitem_remove_file')
 
109
        self.menuitem_file_bookmark = self.toplevel.get_widget('menuitem_file_bookmark')
81
110
        self.menuitem_file_make_directory = self.toplevel.get_widget('menuitem_file_make_directory')
82
111
        self.menuitem_file_rename = self.toplevel.get_widget('menuitem_file_rename')
83
112
        self.menuitem_file_move = self.toplevel.get_widget('menuitem_file_move')
84
113
        self.menuitem_file_annotate = self.toplevel.get_widget('menuitem_file_annotate')
85
114
        self.menuitem_view_show_hidden_files = self.toplevel.get_widget('menuitem_view_show_hidden_files')
 
115
        self.menuitem_view_show_ignored_files = self.toplevel.get_widget('menuitem_view_show_ignored_files')
86
116
        self.menuitem_branch = self.toplevel.get_widget('menuitem_branch')
87
117
        self.menuitem_branch_init = self.toplevel.get_widget('menuitem_branch_initialize')
88
118
        self.menuitem_branch_get = self.toplevel.get_widget('menuitem_branch_get')
89
119
        self.menuitem_branch_checkout = self.toplevel.get_widget('menuitem_branch_checkout')
90
120
        self.menuitem_branch_pull = self.toplevel.get_widget('menuitem_branch_pull')
91
121
        self.menuitem_branch_push = self.toplevel.get_widget('menuitem_branch_push')
 
122
        self.menuitem_branch_update = self.toplevel.get_widget('menuitem_branch_update')
92
123
        self.menuitem_branch_revert = self.toplevel.get_widget('menuitem_branch_revert')
93
124
        self.menuitem_branch_merge = self.toplevel.get_widget('menuitem_branch_merge')
94
125
        self.menuitem_branch_commit = self.toplevel.get_widget('menuitem_branch_commit')
106
137
        self.toolbutton_commit = self.toplevel.get_widget('toolbutton_commit')
107
138
        self.toolbutton_pull = self.toplevel.get_widget('toolbutton_pull')
108
139
        self.toolbutton_push = self.toplevel.get_widget('toolbutton_push')
 
140
        self.toolbutton_update = self.toplevel.get_widget('toolbutton_update')
109
141
        # Get the drive selector
110
142
        self.combobox_drive = gtk.combo_box_new_text()
111
143
        self.combobox_drive.connect("changed", self._refresh_drives)
117
149
        self.entry_location = self.toplevel.get_widget('entry_location')
118
150
        self.image_location_error = self.toplevel.get_widget('image_location_error')
119
151
        
 
152
        # Get the History widgets
 
153
        self.check_history = self.toplevel.get_widget('checkbutton_history')
 
154
        self.entry_history = self.toplevel.get_widget('entry_history_revno')
 
155
        self.button_history = self.toplevel.get_widget('button_history_browse')
 
156
        
120
157
        self.vbox_main_right = self.toplevel.get_widget('vbox_main_right')
121
158
        
122
159
        # Dictionary for signal_autoconnect
126
163
                "on_about_activate": self.on_about_activate,
127
164
                "on_menuitem_add_files_activate": self.on_menuitem_add_files_activate,
128
165
                "on_menuitem_remove_file_activate": self.on_menuitem_remove_file_activate,
 
166
                "on_menuitem_file_bookmark_activate": self.on_menuitem_file_bookmark_activate,
129
167
                "on_menuitem_file_make_directory_activate": self.on_menuitem_file_make_directory_activate,
130
168
                "on_menuitem_file_move_activate": self.on_menuitem_file_move_activate,
131
169
                "on_menuitem_file_rename_activate": self.on_menuitem_file_rename_activate,
132
170
                "on_menuitem_file_annotate_activate": self.on_menuitem_file_annotate_activate,
133
171
                "on_menuitem_view_show_hidden_files_activate": self.on_menuitem_view_show_hidden_files_activate,
 
172
                "on_menuitem_view_show_ignored_files_activate": self.on_menuitem_view_show_ignored_files_activate,
134
173
                "on_menuitem_view_refresh_activate": self.on_menuitem_view_refresh_activate,
135
174
                "on_menuitem_branch_initialize_activate": self.on_menuitem_branch_initialize_activate,
136
175
                "on_menuitem_branch_get_activate": self.on_menuitem_branch_get_activate,
140
179
                "on_menuitem_branch_commit_activate": self.on_menuitem_branch_commit_activate,
141
180
                "on_menuitem_branch_push_activate": self.on_menuitem_branch_push_activate,
142
181
                "on_menuitem_branch_pull_activate": self.on_menuitem_branch_pull_activate,
 
182
                "on_menuitem_branch_update_activate": self.on_menuitem_branch_update_activate,                
143
183
                "on_menuitem_branch_tags_activate": self.on_menuitem_branch_tags_activate,
144
184
                "on_menuitem_branch_status_activate": self.on_menuitem_branch_status_activate,
145
185
                "on_menuitem_branch_missing_revisions_activate": self.on_menuitem_branch_missing_revisions_activate,
154
194
                "on_toolbutton_commit_clicked": self.on_menuitem_branch_commit_activate,
155
195
                "on_toolbutton_pull_clicked": self.on_menuitem_branch_pull_activate,
156
196
                "on_toolbutton_push_clicked": self.on_menuitem_branch_push_activate,
 
197
                "on_toolbutton_update_clicked": self.on_menuitem_branch_update_activate,
157
198
                "on_treeview_right_button_press_event": self.on_treeview_right_button_press_event,
158
199
                "on_treeview_right_row_activated": self.on_treeview_right_row_activated,
159
200
                "on_treeview_left_button_press_event": self.on_treeview_left_button_press_event,
 
201
                "on_treeview_left_button_release_event": self.on_treeview_left_button_release_event,
160
202
                "on_treeview_left_row_activated": self.on_treeview_left_row_activated,
161
203
                "on_button_location_up_clicked": self.on_button_location_up_clicked,
162
204
                "on_button_location_jump_clicked": self.on_button_location_jump_clicked,
163
 
                "on_entry_location_key_press_event": self.on_entry_location_key_press_event
 
205
                "on_entry_location_key_press_event": self.on_entry_location_key_press_event,
 
206
                "on_checkbutton_history_toggled": self.on_checkbutton_history_toggled,
 
207
                "on_entry_history_revno_key_press_event": self.on_entry_history_revno_key_press_event,
 
208
                "on_button_history_browse_clicked": self.on_button_history_browse_clicked
164
209
            }
165
210
        
166
211
        # Connect the signals to the handlers
197
242
 
198
243
        # Apply menu state
199
244
        self.menuitem_view_show_hidden_files.set_active(self.pref.get_preference('dotted_files', 'bool'))
 
245
        self.menuitem_view_show_ignored_files.set_active(self.pref.get_preference('ignored_files', 'bool'))
200
246
 
201
247
        # We're starting local
202
248
        self.remote = False
203
249
        self.remote_branch = None
204
250
        self.remote_path = None
 
251
        self.remote_revision = None
205
252
        
206
253
        self.set_path(os.getcwd())
207
254
        self._load_right()
208
255
        
209
256
        self._just_started = False
210
257
 
211
 
    def set_path(self, path):
 
258
    def set_path(self, path, force_remote=False):
212
259
        self.notbranch = False
213
260
        
214
 
        if os.path.isdir(path):
215
 
            self.image_location_error.destroy()
216
 
            self.remote = False
217
 
            
218
 
            # We're local
219
 
            try:
220
 
                self.wt, self.wtpath = WorkingTree.open_containing(path)
221
 
            except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
222
 
                self.notbranch = True
223
 
            
224
 
            # If we're in the root, we cannot go up anymore
225
 
            if sys.platform == 'win32':
226
 
                drive, tail = os.path.splitdrive(path)
227
 
                if tail in ('', '/', '\\'):
228
 
                    self.button_location_up.set_sensitive(False)
229
 
                else:
230
 
                    self.button_location_up.set_sensitive(True)
231
 
            else:
232
 
                if self.path == '/':
233
 
                    self.button_location_up.set_sensitive(False)
234
 
                else:
235
 
                    self.button_location_up.set_sensitive(True)
236
 
        elif not os.path.isfile(path):
237
 
            # Doesn't seem to be a file nor a directory, trying to open a
238
 
            # remote location
 
261
        if force_remote:
 
262
            # Forcing remote mode (reading data from inventory)
239
263
            self._show_stock_image(gtk.STOCK_DISCONNECT)
240
264
            try:
241
265
                br = Branch.open_containing(path)[0]
242
266
            except bzrerrors.NotBranchError:
243
267
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
268
                self.check_history.set_active(False)
 
269
                self.check_history.set_sensitive(False)
244
270
                return False
245
271
            except bzrerrors.UnsupportedProtocol:
246
272
                self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
273
                self.check_history.set_active(False)
 
274
                self.check_history.set_sensitive(False)
247
275
                return False
248
276
            
249
277
            self._show_stock_image(gtk.STOCK_CONNECT)
253
281
            # We're remote
254
282
            self.remote_branch, self.remote_path = Branch.open_containing(path)
255
283
            
256
 
            self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).entries()
 
284
            if self.remote_revision is None:
 
285
                self.remote_revision = self.remote_branch.last_revision()
 
286
            
 
287
            self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
257
288
            
258
289
            if len(self.remote_path) == 0:
259
290
                self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
270
301
                self.button_location_up.set_sensitive(False)
271
302
            else:
272
303
                self.button_location_up.set_sensitive(True)
 
304
        else:
 
305
            if os.path.isdir(path):
 
306
                self.image_location_error.destroy()
 
307
                self.remote = False
 
308
                
 
309
                # We're local
 
310
                try:
 
311
                    self.wt, self.wtpath = WorkingTree.open_containing(path)
 
312
                except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
 
313
                    self.notbranch = True
 
314
                
 
315
                # If we're in the root, we cannot go up anymore
 
316
                if sys.platform == 'win32':
 
317
                    drive, tail = os.path.splitdrive(path)
 
318
                    if tail in ('', '/', '\\'):
 
319
                        self.button_location_up.set_sensitive(False)
 
320
                    else:
 
321
                        self.button_location_up.set_sensitive(True)
 
322
                else:
 
323
                    if self.path == '/':
 
324
                        self.button_location_up.set_sensitive(False)
 
325
                    else:
 
326
                        self.button_location_up.set_sensitive(True)
 
327
            elif not os.path.isfile(path):
 
328
                # Doesn't seem to be a file nor a directory, trying to open a
 
329
                # remote location
 
330
                self._show_stock_image(gtk.STOCK_DISCONNECT)
 
331
                try:
 
332
                    br = Branch.open_containing(path)[0]
 
333
                except bzrerrors.NotBranchError:
 
334
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
335
                    self.check_history.set_active(False)
 
336
                    self.check_history.set_sensitive(False)
 
337
                    return False
 
338
                except bzrerrors.UnsupportedProtocol:
 
339
                    self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
 
340
                    self.check_history.set_active(False)
 
341
                    self.check_history.set_sensitive(False)
 
342
                    return False
 
343
                
 
344
                self._show_stock_image(gtk.STOCK_CONNECT)
 
345
                
 
346
                self.remote = True
 
347
               
 
348
                # We're remote
 
349
                self.remote_branch, self.remote_path = Branch.open_containing(path)
 
350
                
 
351
                if self.remote_revision is None:
 
352
                    self.remote_revision = self.remote_branch.last_revision()
 
353
                
 
354
                self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
 
355
                
 
356
                if len(self.remote_path) == 0:
 
357
                    self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
 
358
                else:
 
359
                    for (name, type) in self.remote_entries:
 
360
                        if name == self.remote_path:
 
361
                            self.remote_parent = type.file_id
 
362
                            break
 
363
                
 
364
                if not path.endswith('/'):
 
365
                    path += '/'
 
366
                
 
367
                if self.remote_branch.base == path:
 
368
                    self.button_location_up.set_sensitive(False)
 
369
                else:
 
370
                    self.button_location_up.set_sensitive(True)
 
371
        
 
372
        if self.notbranch:
 
373
            self.check_history.set_active(False)
 
374
            self.check_history.set_sensitive(False)
 
375
        else:
 
376
            self.check_history.set_sensitive(True)
273
377
        
274
378
        self.statusbar.push(self.context_id, path)
275
379
        self.entry_location.set_text(path)
287
391
                return self.remote_branch.base
288
392
   
289
393
    def on_about_activate(self, widget):
290
 
        from bzrlib.plugins.gtk.dialog import about
291
394
        about()
292
 
        
 
395
    
 
396
    def on_button_history_browse_clicked(self, widget):
 
397
        """ Browse for revision button handler. """
 
398
        if self.remote:
 
399
            br = self.remote_branch
 
400
        else:
 
401
            br = self.wt.branch
 
402
            
 
403
        revb = RevisionBrowser(br, self.window)
 
404
        response = revb.run()
 
405
        if response != gtk.RESPONSE_NONE:
 
406
            revb.hide()
 
407
        
 
408
            if response == gtk.RESPONSE_OK:
 
409
                if revb.selected_revno is not None:
 
410
                    self.entry_history.set_text(revb.selected_revno)
 
411
            
 
412
            revb.destroy()
 
413
    
 
414
    def on_button_location_jump_clicked(self, widget):
 
415
        """ Location Jump button handler. """
 
416
        location = self.entry_location.get_text()
 
417
        
 
418
        if self.set_path(location):
 
419
            self.refresh_right()
 
420
    
293
421
    def on_button_location_up_clicked(self, widget):
294
422
        """ Location Up button handler. """
295
423
        if not self.remote:
304
432
 
305
433
        self.refresh_right()
306
434
    
307
 
    def on_button_location_jump_clicked(self, widget):
308
 
        """ Location Jump button handler. """
309
 
        location = self.entry_location.get_text()
310
 
        
311
 
        if self.set_path(location):
312
 
            self.refresh_right()
 
435
    def on_checkbutton_history_toggled(self, widget):
 
436
        """ History Mode toggle handler. """
 
437
        if self.check_history.get_active():
 
438
            # History Mode activated
 
439
            self.entry_history.set_sensitive(True)
 
440
            self.button_history.set_sensitive(True)
 
441
        else:
 
442
            # History Mode deactivated
 
443
            self.entry_history.set_sensitive(False)
 
444
            self.button_history.set_sensitive(False)
 
445
    
 
446
    @show_bzr_error
 
447
    def on_entry_history_revno_key_press_event(self, widget, event):
 
448
        """ Key pressed handler for the history entry. """
 
449
        if event.keyval == gtk.gdk.keyval_from_name('Return') or event.keyval == gtk.gdk.keyval_from_name('KP_Enter'):
 
450
            # Return was hit, so we have to load that specific revision
 
451
            # Emulate being remote, so inventory should be used
 
452
            path = self.get_path()
 
453
            if not self.remote:
 
454
                self.remote = True
 
455
                self.remote_branch = self.wt.branch
 
456
            
 
457
            revno = int(self.entry_history.get_text())
 
458
            self.remote_revision = self.remote_branch.get_rev_id(revno)
 
459
            if self.set_path(path, True):
 
460
                self.refresh_right()
313
461
    
314
462
    def on_entry_location_key_press_event(self, widget, event):
315
463
        """ Key pressed handler for the location entry. """
316
 
        if event.keyval == 65293:
 
464
        if event.keyval == gtk.gdk.keyval_from_name('Return') or event.keyval == gtk.gdk.keyval_from_name('KP_Enter'):
317
465
            # Return was hit, so we have to jump
318
466
            self.on_button_location_jump_clicked(widget)
319
467
    
360
508
    @show_bzr_error
361
509
    def on_menuitem_branch_commit_activate(self, widget):
362
510
        """ Branch/Commit... menu handler. """
363
 
        commit = CommitDialog(self.wt, self.wtpath, self.notbranch, self.get_selected_right(), self.window)
 
511
#     def __init__(self, wt, wtpath, notbranch, selected=None, parent=None):
 
512
        selected = self.get_selected_right()
 
513
        if selected:
 
514
            selected = os.path.join(self.wtpath, selected)
 
515
        commit = CommitDialog(wt=self.wt,
 
516
                              parent=self.window,
 
517
                              selected=selected,
 
518
                             )
364
519
        response = commit.run()
365
520
        if response != gtk.RESPONSE_NONE:
366
521
            commit.hide()
382
537
        from bzrlib.plugins.gtk.merge import MergeDialog
383
538
        
384
539
        if self.check_for_changes():
385
 
            error_dialog(_('There are local changes in the branch'),
386
 
                         _('Please commit or revert the changes before merging.'))
 
540
            error_dialog(_i18n('There are local changes in the branch'),
 
541
                         _i18n('Please commit or revert the changes before merging.'))
387
542
        else:
388
 
            merge = MergeDialog(self.wt, self.wtpath)
 
543
            parent_branch_path = self.wt.branch.get_parent()
 
544
            merge = MergeDialog(self.wt, self.wtpath,default_branch_path=parent_branch_path )
389
545
            merge.display()
390
546
 
391
547
    @show_bzr_error
392
548
    def on_menuitem_branch_missing_revisions_activate(self, widget):
393
549
        """ Branch/Missing revisions menu handler. """
 
550
        
 
551
        from bzrlib.missing import find_unmerged, iter_log_revisions
 
552
        
394
553
        local_branch = self.wt.branch
395
 
        
396
 
        other_branch = local_branch.get_parent()
397
 
        if other_branch is None:
398
 
            error_dialog(_('Parent location is unknown'),
399
 
                         _('Cannot determine missing revisions if no parent location is known.'))
 
554
        parent_branch_path = local_branch.get_parent()
 
555
        if parent_branch_path is None:
 
556
            error_dialog(_i18n('Parent location is unknown'),
 
557
                         _i18n('Cannot determine missing revisions if no parent location is known.'))
400
558
            return
401
559
        
402
 
        remote_branch = Branch.open(other_branch)
403
 
        
404
 
        if remote_branch.base == local_branch.base:
405
 
            remote_branch = local_branch
406
 
 
407
 
        ret = len(local_branch.missing_revisions(remote_branch))
408
 
 
409
 
        if ret > 0:
410
 
            info_dialog(_('There are missing revisions'),
411
 
                        _('%d revision(s) missing.') % ret)
 
560
        parent_branch = Branch.open(parent_branch_path)
 
561
        
 
562
        if parent_branch.base == local_branch.base:
 
563
            parent_branch = local_branch
 
564
        
 
565
        local_extra, remote_extra = find_unmerged(local_branch,parent_branch)
 
566
 
 
567
        if local_extra or remote_extra:
 
568
            
 
569
            ## def log_revision_one_line_text(log_revision):
 
570
            ##    """ Generates one line description of log_revison ended with end of line."""
 
571
            ##    revision = log_revision.rev
 
572
            ##    txt =  "- %s (%s)\n" % (revision.get_summary(), revision.committer, )
 
573
            ##    txt = txt.replace("<"," ") # Seems < > chars are expected to be xml tags ...
 
574
            ##    txt = txt.replace(">"," ")
 
575
            ##    return txt
 
576
            
 
577
            dlg_txt = ""
 
578
            if local_extra:
 
579
                dlg_txt += _i18n('%d local extra revision(s). \n') % (len(local_extra),) 
 
580
                ## NOTE: We do not want such ugly info about missing revisions
 
581
                ##       Revision Browser should be used there
 
582
                ## max_revisions = 10
 
583
                ## for log_revision in iter_log_revisions(local_extra, local_branch.repository, verbose=1):
 
584
                ##    dlg_txt += log_revision_one_line_text(log_revision)
 
585
                ##    if max_revisions <= 0:
 
586
                ##        dlg_txt += _i18n("more ... \n")
 
587
                ##        break
 
588
                ## max_revisions -= 1
 
589
            ## dlg_txt += "\n"
 
590
            if remote_extra:
 
591
                dlg_txt += _i18n('%d local missing revision(s).\n') % (len(remote_extra),) 
 
592
                ## max_revisions = 10
 
593
                ## for log_revision in iter_log_revisions(remote_extra, parent_branch.repository, verbose=1):
 
594
                ##    dlg_txt += log_revision_one_line_text(log_revision)
 
595
                ##    if max_revisions <= 0:
 
596
                ##        dlg_txt += _i18n("more ... \n")
 
597
                ##        break
 
598
                ##    max_revisions -= 1
 
599
                
 
600
            info_dialog(_i18n('There are missing revisions'),
 
601
                        dlg_txt)
412
602
        else:
413
 
            info_dialog(_('Local branch up to date'),
414
 
                        _('There are no missing revisions.'))
 
603
            info_dialog(_i18n('Local branch up to date'),
 
604
                        _i18n('There are no missing revisions.'))
415
605
 
416
606
    @show_bzr_error
417
607
    def on_menuitem_branch_pull_activate(self, widget):
420
610
 
421
611
        location = branch_to.get_parent()
422
612
        if location is None:
423
 
            error_dialog(_('Parent location is unknown'),
424
 
                                     _('Pulling is not possible until there is a parent location.'))
 
613
            error_dialog(_i18n('Parent location is unknown'),
 
614
                                     _i18n('Pulling is not possible until there is a parent location.'))
425
615
            return
426
616
 
427
617
        branch_from = Branch.open(location)
431
621
 
432
622
        ret = branch_to.pull(branch_from)
433
623
        
434
 
        info_dialog(_('Pull successful'), _('%d revision(s) pulled.') % ret)
 
624
        info_dialog(_i18n('Pull successful'), _i18n('%d revision(s) pulled.') % ret)
 
625
        
 
626
    @show_bzr_error
 
627
    def on_menuitem_branch_update_activate(self, widget):
 
628
        """ Brranch/checkout update menu handler. """
 
629
        
 
630
        ret = self.wt.update()
 
631
        conflicts = self.wt.conflicts()
 
632
        if conflicts:
 
633
            info_dialog(_i18n('Update successful but conflicts generated'), _i18n('Number of conflicts generated: %d.') % (len(conflicts),) )
 
634
        else:
 
635
            info_dialog(_i18n('Update successful'), _i18n('No conflicts generated.') )
435
636
    
436
637
    def on_menuitem_branch_push_activate(self, widget):
437
638
        """ Branch/Push... menu handler. """
438
 
        push = PushDialog(self.wt.branch, self.window)
 
639
        push = PushDialog(repository=None,revid=None,branch=self.wt.branch, parent=self.window)
439
640
        response = push.run()
440
641
        if response != gtk.RESPONSE_NONE:
441
642
            push.destroy()
445
646
        """ Branch/Revert all changes menu handler. """
446
647
        ret = self.wt.revert([])
447
648
        if ret:
448
 
            warning_dialog(_('Conflicts detected'),
449
 
                           _('Please have a look at the working tree before continuing.'))
 
649
            warning_dialog(_i18n('Conflicts detected'),
 
650
                           _i18n('Please have a look at the working tree before continuing.'))
450
651
        else:
451
 
            info_dialog(_('Revert successful'),
452
 
                        _('All files reverted to last revision.'))
 
652
            info_dialog(_i18n('Revert successful'),
 
653
                        _i18n('All files reverted to last revision.'))
453
654
        self.refresh_right()
454
655
    
455
656
    def on_menuitem_branch_status_activate(self, widget):
484
685
    def on_menuitem_file_annotate_activate(self, widget):
485
686
        """ File/Annotate... menu handler. """
486
687
        if self.get_selected_right() is None:
487
 
            error_dialog(_('No file was selected'),
488
 
                         _('Please select a file from the list.'))
 
688
            error_dialog(_i18n('No file was selected'),
 
689
                         _i18n('Please select a file from the list.'))
489
690
            return
490
691
        
491
692
        branch = self.wt.branch
492
693
        file_id = self.wt.path2id(self.wt.relpath(os.path.join(self.path, self.get_selected_right())))
493
694
        
494
 
        window = GAnnotateWindow(all=False, plain=False)
 
695
        window = GAnnotateWindow(all=False, plain=False, parent=self.window)
495
696
        window.set_title(os.path.join(self.path, self.get_selected_right()) + " - Annotate")
496
697
        config = GAnnotateConfig(window)
497
698
        window.show()
501
702
        finally:
502
703
            branch.unlock()
503
704
    
 
705
    def on_menuitem_file_bookmark_activate(self, widget):
 
706
        """ File/Bookmark current directory menu handler. """
 
707
        if self.pref.add_bookmark(self.path):
 
708
            info_dialog(_i18n('Bookmark successfully added'),
 
709
                        _i18n('The current directory was bookmarked. You can reach\nit by selecting it from the left panel.'))
 
710
            self.pref.write()
 
711
        else:
 
712
            warning_dialog(_i18n('Location already bookmarked'),
 
713
                           _i18n('The current directory is already bookmarked.\nSee the left panel for reference.'))
 
714
        
 
715
        self.refresh_left()
 
716
    
504
717
    def on_menuitem_file_make_directory_activate(self, widget):
505
718
        """ File/Make directory... menu handler. """
506
719
        from mkdir import OliveMkdir
538
751
    
539
752
    def on_menuitem_stats_diff_activate(self, widget):
540
753
        """ Statistics/Differences... menu handler. """
541
 
        window = DiffWindow()
 
754
        window = DiffWindow(parent=self.window)
542
755
        parent_tree = self.wt.branch.repository.revision_tree(self.wt.branch.last_revision())
543
756
        window.set_diff(self.wt.branch.nick, self.wt, parent_tree)
544
757
        window.show()
554
767
    
555
768
    def on_menuitem_stats_log_activate(self, widget):
556
769
        """ Statistics/Log... menu handler. """
557
 
        window = branchwin.BranchWindow()
 
770
 
558
771
        if not self.remote:
559
 
            window.set_branch(self.wt.branch, self.wt.branch.last_revision(), None)
 
772
            branch = self.wt.branch
560
773
        else:
561
 
            window.set_branch(self.remote_branch, self.remote_branch.last_revision(), None)
 
774
            branch = self.remote_branch
 
775
 
 
776
        window = branchwin.BranchWindow(branch, branch.last_revision(), None, parent=self.window)
562
777
        window.show()
563
778
    
564
779
    def on_menuitem_view_refresh_activate(self, widget):
574
789
        if self.path is not None:
575
790
            self.refresh_right()
576
791
 
 
792
    def on_menuitem_view_show_ignored_files_activate(self, widget):
 
793
        """ Hide/Show ignored files menu handler. """
 
794
        self.pref.set_preference('ignored_files', widget.get_active())
 
795
        if self.path is not None:
 
796
            self.refresh_right()
 
797
            
577
798
    def on_treeview_left_button_press_event(self, widget, event):
578
799
        """ Occurs when somebody right-clicks in the bookmark list. """
579
800
        if event.button == 3:
590
811
            menu.left_context_menu().popup(None, None, None, 0,
591
812
                                           event.time)
592
813
 
 
814
    def on_treeview_left_button_release_event(self, widget, event):
 
815
        """ Occurs when somebody just clicks a bookmark. """
 
816
        if event.button != 3:
 
817
            # Allow one-click bookmark opening
 
818
            if self.get_selected_left() == None:
 
819
                return
 
820
            
 
821
            newdir = self.get_selected_left()
 
822
            if newdir == None:
 
823
                return
 
824
 
 
825
            if self.set_path(newdir):
 
826
                self.refresh_right()
 
827
 
593
828
    def on_treeview_left_row_activated(self, treeview, path, view_column):
594
829
        """ Occurs when somebody double-clicks or enters an item in the
595
830
        bookmark list. """
650
885
                m_annotate.set_sensitive(False)
651
886
                m_diff.set_sensitive(False)
652
887
 
653
 
            menu.right_context_menu().popup(None, None, None, 0,
654
 
                                            event.time)
 
888
            if not self.remote:
 
889
                menu.right_context_menu().popup(None, None, None, 0,
 
890
                                                event.time)
 
891
            else:
 
892
                menu.remote_context_menu().popup(None, None, None, 0,
 
893
                                                 event.time)
655
894
        
656
895
    def on_treeview_right_row_activated(self, treeview, path, view_column):
657
896
        """ Occurs when somebody double-clicks or enters an item in the
701
940
        bookmarks = self.pref.get_bookmarks()
702
941
        
703
942
        # Add them to the TreeStore
704
 
        titer = treestore.append(None, [_('Bookmarks'), None])
 
943
        titer = treestore.append(None, [_i18n('Bookmarks'), None])
705
944
        for item in bookmarks:
706
945
            title = self.pref.get_bookmark_title(item)
707
946
            treestore.append(titer, [title, item])
708
947
        
709
948
        # Create the column and add it to the TreeView
710
949
        self.treeview_left.set_model(treestore)
711
 
        tvcolumn_bookmark = gtk.TreeViewColumn(_('Bookmark'))
 
950
        tvcolumn_bookmark = gtk.TreeViewColumn(_i18n('Bookmark'))
712
951
        self.treeview_left.append_column(tvcolumn_bookmark)
713
952
        
714
953
        # Set up the cells
722
961
    def _load_right(self):
723
962
        """ Load data into the right panel. (Filelist) """
724
963
        # Create ListStore
725
 
        # Model: [icon, dir, name, status text, status, size (int), size (human), mtime (int), mtime (local)]
726
 
        liststore = gtk.ListStore(str, gobject.TYPE_BOOLEAN, str, str, str, gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_STRING)
 
964
        # Model: [ icon, dir, name, status text, status, size (int), size (human), mtime (int), mtime (local), fileid ]
 
965
        liststore = gtk.ListStore(gobject.TYPE_STRING,
 
966
                                  gobject.TYPE_BOOLEAN,
 
967
                                  gobject.TYPE_STRING,
 
968
                                  gobject.TYPE_STRING,
 
969
                                  gobject.TYPE_STRING,
 
970
                                  gobject.TYPE_STRING,
 
971
                                  gobject.TYPE_STRING,
 
972
                                  gobject.TYPE_INT,
 
973
                                  gobject.TYPE_STRING,
 
974
                                  gobject.TYPE_STRING)
727
975
        
728
976
        dirs = []
729
977
        files = []
746
994
        
747
995
        # Add'em to the ListStore
748
996
        for item in dirs:
749
 
            statinfo = os.stat(self.path + os.sep + item)
750
 
            liststore.append([gtk.STOCK_DIRECTORY, True, item, '', '', statinfo.st_size, self._format_size(statinfo.st_size), statinfo.st_mtime, self._format_date(statinfo.st_mtime)])
 
997
            try:
 
998
                statinfo = os.stat(self.path + os.sep + item)
 
999
            except OSError, e:
 
1000
                if e.errno == 40:
 
1001
                    continue
 
1002
                else:
 
1003
                    raise
 
1004
            liststore.append([ gtk.STOCK_DIRECTORY,
 
1005
                               True,
 
1006
                               item,
 
1007
                               '',
 
1008
                               '',
 
1009
                               "<DIR>",
 
1010
                               "<DIR>",
 
1011
                               statinfo.st_mtime,
 
1012
                               self._format_date(statinfo.st_mtime),
 
1013
                               ''])
751
1014
        for item in files:
752
1015
            status = 'unknown'
 
1016
            fileid = ''
753
1017
            if not self.notbranch:
754
1018
                filename = self.wt.relpath(self.path + os.sep + item)
755
1019
                
759
1023
                    for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
760
1024
                        if rpathnew == filename:
761
1025
                            status = 'renamed'
 
1026
                            fileid = id
762
1027
                    for rpath, id, kind in delta.added:
763
1028
                        if rpath == filename:
764
1029
                            status = 'added'
 
1030
                            fileid = id
765
1031
                    for rpath, id, kind in delta.removed:
766
1032
                        if rpath == filename:
767
1033
                            status = 'removed'
 
1034
                            fileid = id
768
1035
                    for rpath, id, kind, text_modified, meta_modified in delta.modified:
769
1036
                        if rpath == filename:
770
1037
                            status = 'modified'
 
1038
                            fileid = id
771
1039
                    for rpath, id, kind in delta.unchanged:
772
1040
                        if rpath == filename:
773
1041
                            status = 'unchanged'
 
1042
                            fileid = id
774
1043
                    for rpath, file_class, kind, id, entry in self.wt.list_files():
775
1044
                        if rpath == filename and file_class == 'I':
776
1045
                            status = 'ignored'
777
1046
                finally:
778
1047
                    self.wt.unlock()
779
1048
            
780
 
            #try:
781
 
            #    status = fileops.status(path + os.sep + item)
782
 
            #except errors.PermissionDenied:
783
 
            #    continue
784
 
            
785
1049
            if status == 'renamed':
786
 
                st = _('renamed')
 
1050
                st = _i18n('renamed')
787
1051
            elif status == 'removed':
788
 
                st = _('removed')
 
1052
                st = _i18n('removed')
789
1053
            elif status == 'added':
790
 
                st = _('added')
 
1054
                st = _i18n('added')
791
1055
            elif status == 'modified':
792
 
                st = _('modified')
 
1056
                st = _i18n('modified')
793
1057
            elif status == 'unchanged':
794
 
                st = _('unchanged')
 
1058
                st = _i18n('unchanged')
795
1059
            elif status == 'ignored':
796
 
                st = _('ignored')
 
1060
                st = _i18n('ignored')
797
1061
            else:
798
 
                st = _('unknown')
 
1062
                st = _i18n('unknown')
799
1063
            
800
 
            statinfo = os.stat(self.path + os.sep + item)
801
 
            liststore.append([gtk.STOCK_FILE, False, item, st, status, statinfo.st_size, self._format_size(statinfo.st_size), statinfo.st_mtime, self._format_date(statinfo.st_mtime)])
 
1064
            try:
 
1065
                statinfo = os.stat(self.path + os.sep + item)
 
1066
            except OSError, e:
 
1067
                if e.errno == 40:
 
1068
                    continue
 
1069
                else:
 
1070
                    raise
 
1071
            liststore.append([gtk.STOCK_FILE,
 
1072
                              False,
 
1073
                              item,
 
1074
                              st,
 
1075
                              status,
 
1076
                              str(statinfo.st_size), # NOTE: if int used there it will fail for large files (size expressed as long int)
 
1077
                              self._format_size(statinfo.st_size),
 
1078
                              statinfo.st_mtime,
 
1079
                              self._format_date(statinfo.st_mtime),
 
1080
                              fileid])
802
1081
        
803
1082
        # Create the columns and add them to the TreeView
804
1083
        self.treeview_right.set_model(liststore)
805
 
        self._tvcolumn_filename = gtk.TreeViewColumn(_('Filename'))
806
 
        self._tvcolumn_status = gtk.TreeViewColumn(_('Status'))
807
 
        self._tvcolumn_size = gtk.TreeViewColumn(_('Size'))
808
 
        self._tvcolumn_mtime = gtk.TreeViewColumn(_('Last modified'))
 
1084
        self._tvcolumn_filename = gtk.TreeViewColumn(_i18n('Filename'))
 
1085
        self._tvcolumn_status = gtk.TreeViewColumn(_i18n('Status'))
 
1086
        self._tvcolumn_size = gtk.TreeViewColumn(_i18n('Size'))
 
1087
        self._tvcolumn_mtime = gtk.TreeViewColumn(_i18n('Last modified'))
809
1088
        self.treeview_right.append_column(self._tvcolumn_filename)
810
1089
        self.treeview_right.append_column(self._tvcolumn_status)
811
1090
        self.treeview_right.append_column(self._tvcolumn_size)
844
1123
        # Set sensitivity
845
1124
        self.set_sensitivity()
846
1125
        
 
1126
    def get_selected_fileid(self):
 
1127
        """ Get the file_id of the selected file. """
 
1128
        treeselection = self.treeview_right.get_selection()
 
1129
        (model, iter) = treeselection.get_selected()
 
1130
        
 
1131
        if iter is None:
 
1132
            return None
 
1133
        else:
 
1134
            return model.get_value(iter, 9)
 
1135
    
847
1136
    def get_selected_right(self):
848
1137
        """ Get the selected filename. """
849
1138
        treeselection = self.treeview_right.get_selection()
881
1170
            self.menuitem_branch_checkout.set_sensitive(self.notbranch)
882
1171
            self.menuitem_branch_pull.set_sensitive(not self.notbranch)
883
1172
            self.menuitem_branch_push.set_sensitive(not self.notbranch)
 
1173
            self.menuitem_branch_update.set_sensitive(not self.notbranch)
884
1174
            self.menuitem_branch_revert.set_sensitive(not self.notbranch)
885
1175
            self.menuitem_branch_merge.set_sensitive(not self.notbranch)
886
1176
            self.menuitem_branch_commit.set_sensitive(not self.notbranch)
902
1192
            self.toolbutton_commit.set_sensitive(not self.notbranch)
903
1193
            self.toolbutton_pull.set_sensitive(not self.notbranch)
904
1194
            self.toolbutton_push.set_sensitive(not self.notbranch)
 
1195
            self.toolbutton_update.set_sensitive(not self.notbranch)
905
1196
        else:
906
1197
            # We're remote
907
1198
            self.menuitem_branch_init.set_sensitive(False)
909
1200
            self.menuitem_branch_checkout.set_sensitive(True)
910
1201
            self.menuitem_branch_pull.set_sensitive(False)
911
1202
            self.menuitem_branch_push.set_sensitive(False)
 
1203
            self.menuitem_branch_update.set_sensitive(False)
912
1204
            self.menuitem_branch_revert.set_sensitive(False)
913
1205
            self.menuitem_branch_merge.set_sensitive(False)
914
1206
            self.menuitem_branch_commit.set_sensitive(False)
930
1222
            self.toolbutton_commit.set_sensitive(False)
931
1223
            self.toolbutton_pull.set_sensitive(False)
932
1224
            self.toolbutton_push.set_sensitive(False)
 
1225
            self.toolbutton_update.set_sensitive(False)
933
1226
    
934
1227
    def refresh_left(self):
935
1228
        """ Refresh the bookmark list. """
945
1238
        bookmarks = self.pref.get_bookmarks()
946
1239
 
947
1240
        # Add them to the TreeStore
948
 
        titer = treestore.append(None, [_('Bookmarks'), None])
 
1241
        titer = treestore.append(None, [_i18n('Bookmarks'), None])
949
1242
        for item in bookmarks:
950
1243
            title = self.pref.get_bookmark_title(item)
951
1244
            treestore.append(titer, [title, item])
981
1274
    
982
1275
            # Fill the appropriate lists
983
1276
            dotted_files = self.pref.get_preference('dotted_files', 'bool')
 
1277
            ignored_files = self.pref.get_preference('ignored_files', 'bool')
 
1278
 
984
1279
            for item in os.listdir(path):
985
1280
                if not dotted_files and item[0] == '.':
986
1281
                    continue
1004
1299
                
1005
1300
            # Add'em to the ListStore
1006
1301
            for item in dirs:
1007
 
                statinfo = os.stat(self.path + os.sep + item)
1008
 
                liststore.append([gtk.STOCK_DIRECTORY, True, item, '', '', statinfo.st_size, self._format_size(statinfo.st_size), statinfo.st_mtime, self._format_date(statinfo.st_mtime)])
 
1302
                try:
 
1303
                    statinfo = os.stat(self.path + os.sep + item)
 
1304
                except OSError, e:
 
1305
                    if e.errno == 40:
 
1306
                        continue
 
1307
                    else:
 
1308
                        raise
 
1309
                liststore.append([gtk.STOCK_DIRECTORY,
 
1310
                                  True,
 
1311
                                  item,
 
1312
                                  '',
 
1313
                                  '',
 
1314
                                  "<DIR>",
 
1315
                                  "<DIR>",
 
1316
                                  statinfo.st_mtime,
 
1317
                                  self._format_date(statinfo.st_mtime),
 
1318
                                  ''])
1009
1319
            for item in files:
1010
1320
                status = 'unknown'
 
1321
                fileid = ''
1011
1322
                if not notbranch:
1012
1323
                    filename = tree1.relpath(path + os.sep + item)
1013
1324
                    
1017
1328
                        for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
1018
1329
                            if rpathnew == filename:
1019
1330
                                status = 'renamed'
 
1331
                                fileid = id
1020
1332
                        for rpath, id, kind in delta.added:
1021
1333
                            if rpath == filename:
1022
 
                                status = 'added'                
 
1334
                                status = 'added'
 
1335
                                fileid = id
1023
1336
                        for rpath, id, kind in delta.removed:
1024
1337
                            if rpath == filename:
1025
1338
                                status = 'removed'
 
1339
                                fileid = id
1026
1340
                        for rpath, id, kind, text_modified, meta_modified in delta.modified:
1027
1341
                            if rpath == filename:
1028
1342
                                status = 'modified'
 
1343
                                fileid = id
1029
1344
                        for rpath, id, kind in delta.unchanged:
1030
1345
                            if rpath == filename:
1031
1346
                                status = 'unchanged'
 
1347
                                fileid = id
1032
1348
                        for rpath, file_class, kind, id, entry in self.wt.list_files():
1033
1349
                            if rpath == filename and file_class == 'I':
1034
1350
                                status = 'ignored'
1036
1352
                        self.wt.unlock()
1037
1353
                
1038
1354
                if status == 'renamed':
1039
 
                    st = _('renamed')
 
1355
                    st = _i18n('renamed')
1040
1356
                elif status == 'removed':
1041
 
                    st = _('removed')
 
1357
                    st = _i18n('removed')
1042
1358
                elif status == 'added':
1043
 
                    st = _('added')
 
1359
                    st = _i18n('added')
1044
1360
                elif status == 'modified':
1045
 
                    st = _('modified')
 
1361
                    st = _i18n('modified')
1046
1362
                elif status == 'unchanged':
1047
 
                    st = _('unchanged')
 
1363
                    st = _i18n('unchanged')
1048
1364
                elif status == 'ignored':
1049
 
                    st = _('ignored')
 
1365
                    st = _i18n('ignored')
 
1366
                    if not ignored_files:
 
1367
                        continue
1050
1368
                else:
1051
 
                    st = _('unknown')
 
1369
                    st = _i18n('unknown')
1052
1370
                
1053
 
                statinfo = os.stat(self.path + os.sep + item)
1054
 
                liststore.append([gtk.STOCK_FILE, False, item, st, status, statinfo.st_size, self._format_size(statinfo.st_size), statinfo.st_mtime, self._format_date(statinfo.st_mtime)])
 
1371
                try:
 
1372
                    statinfo = os.stat(self.path + os.sep + item)
 
1373
                except OSError, e:
 
1374
                    if e.errno == 40:
 
1375
                        continue
 
1376
                    else:
 
1377
                        raise
 
1378
                liststore.append([gtk.STOCK_FILE,
 
1379
                                  False,
 
1380
                                  item,
 
1381
                                  st,
 
1382
                                  status,
 
1383
                                  str(statinfo.st_size),
 
1384
                                  self._format_size(statinfo.st_size),
 
1385
                                  statinfo.st_mtime,
 
1386
                                  self._format_date(statinfo.st_mtime),
 
1387
                                  fileid])
1055
1388
        else:
1056
1389
            # We're remote
1057
1390
            
1104
1437
                                       item.name,
1105
1438
                                       '',
1106
1439
                                       '',
1107
 
                                       0,
1108
 
                                       self._format_size(0),
 
1440
                                       "<DIR>",
 
1441
                                       "<DIR>",
1109
1442
                                       rev.timestamp,
1110
 
                                       self._format_date(rev.timestamp)
 
1443
                                       self._format_date(rev.timestamp),
 
1444
                                       ''
1111
1445
                                   ])
1112
1446
                while gtk.events_pending():
1113
1447
                    gtk.main_iteration()
1120
1454
                                       item.name,
1121
1455
                                       '',
1122
1456
                                       '',
1123
 
                                       item.text_size,
 
1457
                                       str(item.text_size),
1124
1458
                                       self._format_size(item.text_size),
1125
1459
                                       rev.timestamp,
1126
 
                                       self._format_date(rev.timestamp)
 
1460
                                       self._format_date(rev.timestamp),
 
1461
                                       item.file_id
1127
1462
                                   ])
1128
1463
                while gtk.events_pending():
1129
1464
                    gtk.main_iteration()
1221
1556
    
1222
1557
    def _format_size(self, size):
1223
1558
        """ Format size to a human readable format. """
1224
 
        return size
 
1559
        if size < 1000:
 
1560
            return "%d[B]" % (size,)
 
1561
        size = size / 1000.0
 
1562
        
 
1563
        for metric in ["kB","MB","GB","TB"]:
 
1564
            if size < 1000:
 
1565
                break
 
1566
            size = size / 1000.0
 
1567
        return "%.1f[%s]" % (size,metric) 
1225
1568
    
1226
1569
    def _format_date(self, timestamp):
1227
1570
        """ Format the time (given in secs) to a human readable format. """
1263
1606
        # Some default options
1264
1607
        self.defaults = { 'strict_commit' : False,
1265
1608
                          'dotted_files'  : False,
 
1609
                          'ignored_files' : True,
1266
1610
                          'window_width'  : 700,
1267
1611
                          'window_height' : 400,
1268
1612
                          'window_x'      : 40,