/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-05-04 13:11:26 UTC
  • Revision ID: jelmer@samba.org-20080504131126-82j2fsopc66vrfr1
Fix diff test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
# -*- coding: UTF-8 -*-
 
3
 
1
4
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
2
5
#
3
6
# This program is free software; you can redistribute it and/or modify
17
20
import os
18
21
import sys
19
22
import time
20
 
import errno
21
23
 
22
24
# gettext support
23
25
import gettext
32
34
import gobject
33
35
import gtk
34
36
import gtk.gdk
 
37
import gtk.glade
35
38
 
36
39
from bzrlib.branch import Branch
37
40
import bzrlib.errors as bzrerrors
39
42
from bzrlib.ui import ui_factory
40
43
from bzrlib.workingtree import WorkingTree
41
44
 
42
 
from bzrlib.plugins.gtk import _i18n
43
45
from bzrlib.plugins.gtk.dialog import error_dialog, info_dialog, warning_dialog
44
46
from bzrlib.plugins.gtk.errors import show_bzr_error
45
 
from bzrlib.plugins.gtk.olive.window import OliveGui
 
47
from guifiles import GLADEFILENAME
46
48
 
47
49
from bzrlib.plugins.gtk.diff import DiffWindow
48
50
lazy_import(globals(), """
58
60
 
59
61
def about():
60
62
    """ Display the AboutDialog. """
61
 
    from bzrlib.plugins.gtk import __version__, icon_path
62
 
    
63
 
    iconpath = icon_path() + os.sep
64
 
    
65
 
    dialog = gtk.AboutDialog()
66
 
    dialog.set_name("Olive")
 
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
67
71
    dialog.set_version(__version__)
68
 
    dialog.set_copyright("Copyright (C) 2006 Szilveszter Farkas (Phanatic)")
69
 
    dialog.set_website("https://launchpad.net/products/olive")
70
 
    dialog.set_website_label("https://launchpad.net/products/olive")
71
 
    dialog.set_icon_from_file(iconpath+"oliveicon2.png")
72
 
    dialog.set_logo(gtk.gdk.pixbuf_new_from_file(iconpath+"oliveicon2.png"))
73
 
    dialog.set_authors([ _i18n("Lead Developer:"),
 
72
    dialog.set_authors([ _("Lead Developer:"),
74
73
                         "Szilveszter Farkas <szilveszter.farkas@gmail.com>",
75
 
                         _i18n("Contributors:"),
 
74
                         _("Contributors:"),
76
75
                         "Jelmer Vernooij <jelmer@samba.org>",
77
76
                         "Mateusz Korniak <mateusz.korniak@ant.gliwice.pl>",
78
77
                         "Gary van der Merwe <garyvdm@gmail.com>" ])
88
87
    program. """
89
88
    
90
89
    def __init__(self):
91
 
        self.window = OliveGui(calling_app = self)
92
 
        
 
90
        self.toplevel = gtk.glade.XML(GLADEFILENAME, 'window_main', 'olive-gtk')
 
91
        self.window = self.toplevel.get_widget('window_main')
93
92
        self.pref = Preferences()
94
93
        self.path = None
95
94
 
96
95
        # Initialize the statusbar
97
 
        self.context_id = self.window.statusbar.get_context_id('olive')
98
 
        
99
 
                # Get the TreeViews
100
 
        self.treeview_left = self.window.treeview_left
101
 
        self.treeview_right = self.window.treeview_right
102
 
        
 
96
        self.statusbar = self.toplevel.get_widget('statusbar')
 
97
        self.context_id = self.statusbar.get_context_id('olive')
 
98
        
 
99
        # Get the main window
 
100
        self.window_main = self.toplevel.get_widget('window_main')
 
101
        # Get the HPaned
 
102
        self.hpaned_main = self.toplevel.get_widget('hpaned_main')
 
103
        # Get the TreeViews
 
104
        self.treeview_left = self.toplevel.get_widget('treeview_left')
 
105
        self.treeview_right = self.toplevel.get_widget('treeview_right')
 
106
        # Get some important menu items
 
107
        self.menuitem_add_files = self.toplevel.get_widget('menuitem_add_files')
 
108
        self.menuitem_remove_files = self.toplevel.get_widget('menuitem_remove_file')
 
109
        self.menuitem_file_bookmark = self.toplevel.get_widget('menuitem_file_bookmark')
 
110
        self.menuitem_file_make_directory = self.toplevel.get_widget('menuitem_file_make_directory')
 
111
        self.menuitem_file_rename = self.toplevel.get_widget('menuitem_file_rename')
 
112
        self.menuitem_file_move = self.toplevel.get_widget('menuitem_file_move')
 
113
        self.menuitem_file_annotate = self.toplevel.get_widget('menuitem_file_annotate')
 
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')
 
116
        self.menuitem_branch = self.toplevel.get_widget('menuitem_branch')
 
117
        self.menuitem_branch_init = self.toplevel.get_widget('menuitem_branch_initialize')
 
118
        self.menuitem_branch_get = self.toplevel.get_widget('menuitem_branch_get')
 
119
        self.menuitem_branch_checkout = self.toplevel.get_widget('menuitem_branch_checkout')
 
120
        self.menuitem_branch_pull = self.toplevel.get_widget('menuitem_branch_pull')
 
121
        self.menuitem_branch_push = self.toplevel.get_widget('menuitem_branch_push')
 
122
        self.menuitem_branch_update = self.toplevel.get_widget('menuitem_branch_update')
 
123
        self.menuitem_branch_revert = self.toplevel.get_widget('menuitem_branch_revert')
 
124
        self.menuitem_branch_merge = self.toplevel.get_widget('menuitem_branch_merge')
 
125
        self.menuitem_branch_commit = self.toplevel.get_widget('menuitem_branch_commit')
 
126
        self.menuitem_branch_tags = self.toplevel.get_widget('menuitem_branch_tags')
 
127
        self.menuitem_branch_status = self.toplevel.get_widget('menuitem_branch_status')
 
128
        self.menuitem_branch_missing = self.toplevel.get_widget('menuitem_branch_missing_revisions')
 
129
        self.menuitem_branch_conflicts = self.toplevel.get_widget('menuitem_branch_conflicts')
 
130
        self.menuitem_stats = self.toplevel.get_widget('menuitem_stats')
 
131
        self.menuitem_stats_diff = self.toplevel.get_widget('menuitem_stats_diff')
 
132
        self.menuitem_stats_log = self.toplevel.get_widget('menuitem_stats_log')
 
133
        # Get some toolbuttons
 
134
        #self.menutoolbutton_diff = self.toplevel.get_widget('menutoolbutton_diff')
 
135
        self.toolbutton_diff = self.toplevel.get_widget('toolbutton_diff')
 
136
        self.toolbutton_log = self.toplevel.get_widget('toolbutton_log')
 
137
        self.toolbutton_commit = self.toplevel.get_widget('toolbutton_commit')
 
138
        self.toolbutton_pull = self.toplevel.get_widget('toolbutton_pull')
 
139
        self.toolbutton_push = self.toplevel.get_widget('toolbutton_push')
 
140
        self.toolbutton_update = self.toplevel.get_widget('toolbutton_update')
103
141
        # Get the drive selector
104
142
        self.combobox_drive = gtk.combo_box_new_text()
105
143
        self.combobox_drive.connect("changed", self._refresh_drives)
106
144
        
107
145
        # Get the navigation widgets
108
 
        self.hbox_location = self.window.locationbar
109
 
        self.button_location_up = self.window.button_location_up
110
 
        self.button_location_jump = self.window.button_location_jump
111
 
        self.entry_location = self.window.entry_location
112
 
        self.image_location_error = self.window.image_location_error
 
146
        self.hbox_location = self.toplevel.get_widget('hbox_location')
 
147
        self.button_location_up = self.toplevel.get_widget('button_location_up')
 
148
        self.button_location_jump = self.toplevel.get_widget('button_location_jump')
 
149
        self.entry_location = self.toplevel.get_widget('entry_location')
 
150
        self.image_location_error = self.toplevel.get_widget('image_location_error')
113
151
        
114
152
        # Get the History widgets
115
 
        self.check_history = self.window.checkbutton_history
116
 
        self.entry_history = self.window.entry_history_revno
117
 
        self.button_history = self.window.button_history_browse
 
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
        
 
157
        self.vbox_main_right = self.toplevel.get_widget('vbox_main_right')
 
158
        
 
159
        # Dictionary for signal_autoconnect
 
160
        dic = { "on_window_main_destroy": gtk.main_quit,
 
161
                "on_window_main_delete_event": self.on_window_main_delete_event,
 
162
                "on_quit_activate": self.on_window_main_delete_event,
 
163
                "on_about_activate": self.on_about_activate,
 
164
                "on_menuitem_add_files_activate": self.on_menuitem_add_files_activate,
 
165
                "on_menuitem_remove_file_activate": self.on_menuitem_remove_file_activate,
 
166
                "on_menuitem_file_bookmark_activate": self.on_menuitem_file_bookmark_activate,
 
167
                "on_menuitem_file_make_directory_activate": self.on_menuitem_file_make_directory_activate,
 
168
                "on_menuitem_file_move_activate": self.on_menuitem_file_move_activate,
 
169
                "on_menuitem_file_rename_activate": self.on_menuitem_file_rename_activate,
 
170
                "on_menuitem_file_annotate_activate": self.on_menuitem_file_annotate_activate,
 
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,
 
173
                "on_menuitem_view_refresh_activate": self.on_menuitem_view_refresh_activate,
 
174
                "on_menuitem_branch_initialize_activate": self.on_menuitem_branch_initialize_activate,
 
175
                "on_menuitem_branch_get_activate": self.on_menuitem_branch_get_activate,
 
176
                "on_menuitem_branch_checkout_activate": self.on_menuitem_branch_checkout_activate,
 
177
                "on_menuitem_branch_revert_activate": self.on_menuitem_branch_revert_activate,
 
178
                "on_menuitem_branch_merge_activate": self.on_menuitem_branch_merge_activate,
 
179
                "on_menuitem_branch_commit_activate": self.on_menuitem_branch_commit_activate,
 
180
                "on_menuitem_branch_push_activate": self.on_menuitem_branch_push_activate,
 
181
                "on_menuitem_branch_pull_activate": self.on_menuitem_branch_pull_activate,
 
182
                "on_menuitem_branch_update_activate": self.on_menuitem_branch_update_activate,                
 
183
                "on_menuitem_branch_tags_activate": self.on_menuitem_branch_tags_activate,
 
184
                "on_menuitem_branch_status_activate": self.on_menuitem_branch_status_activate,
 
185
                "on_menuitem_branch_missing_revisions_activate": self.on_menuitem_branch_missing_revisions_activate,
 
186
                "on_menuitem_branch_conflicts_activate": self.on_menuitem_branch_conflicts_activate,
 
187
                "on_menuitem_stats_diff_activate": self.on_menuitem_stats_diff_activate,
 
188
                "on_menuitem_stats_log_activate": self.on_menuitem_stats_log_activate,
 
189
                "on_menuitem_stats_infos_activate": self.on_menuitem_stats_infos_activate,
 
190
                "on_toolbutton_refresh_clicked": self.on_menuitem_view_refresh_activate,
 
191
                "on_toolbutton_log_clicked": self.on_menuitem_stats_log_activate,
 
192
                #"on_menutoolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
 
193
                "on_toolbutton_diff_clicked": self.on_menuitem_stats_diff_activate,
 
194
                "on_toolbutton_commit_clicked": self.on_menuitem_branch_commit_activate,
 
195
                "on_toolbutton_pull_clicked": self.on_menuitem_branch_pull_activate,
 
196
                "on_toolbutton_push_clicked": self.on_menuitem_branch_push_activate,
 
197
                "on_toolbutton_update_clicked": self.on_menuitem_branch_update_activate,
 
198
                "on_treeview_right_button_press_event": self.on_treeview_right_button_press_event,
 
199
                "on_treeview_right_row_activated": self.on_treeview_right_row_activated,
 
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,
 
202
                "on_treeview_left_row_activated": self.on_treeview_left_row_activated,
 
203
                "on_button_location_up_clicked": self.on_button_location_up_clicked,
 
204
                "on_button_location_jump_clicked": self.on_button_location_jump_clicked,
 
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
 
209
            }
 
210
        
 
211
        # Connect the signals to the handlers
 
212
        self.toplevel.signal_autoconnect(dic)
118
213
        
119
214
        self._just_started = True
120
215
        
127
222
        self.window.move(x, y)
128
223
        # Apply paned position
129
224
        pos = self.pref.get_preference('paned_position', 'int')
130
 
        self.window.hpaned_main.set_position(pos)
 
225
        self.hpaned_main.set_position(pos)
 
226
        
 
227
        # Apply menu to the toolbutton
 
228
        #menubutton = self.toplevel.get_widget('menutoolbutton_diff')
 
229
        #menubutton.set_menu(handler.menu.toolbar_diff)
131
230
        
132
231
        # Now we can show the window
133
232
        self.window.show()
139
238
            self.combobox_drive.show()
140
239
            self.gen_hard_selector()
141
240
        
142
 
        # Acceptable errors when loading files/folders in the treeviews
143
 
        self.acceptable_errors = (errno.ENOENT, errno.ELOOP)
144
 
        
145
241
        self._load_left()
146
242
 
147
243
        # Apply menu state
148
 
        self.window.mb_view_showhidden.set_active(self.pref.get_preference('dotted_files', 'bool'))
149
 
        self.window.mb_view_showignored.set_active(self.pref.get_preference('ignored_files', 'bool'))
 
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'))
150
246
 
151
247
        # We're starting local
152
248
        self.remote = False
279
375
        else:
280
376
            self.check_history.set_sensitive(True)
281
377
        
282
 
        self.window.statusbar.push(self.context_id, path)
 
378
        self.statusbar.push(self.context_id, path)
283
379
        self.entry_location.set_text(path)
284
380
        self.path = path
285
381
        return True
312
408
            if response == gtk.RESPONSE_OK:
313
409
                if revb.selected_revno is not None:
314
410
                    self.entry_history.set_text(revb.selected_revno)
315
 
                    self.on_entry_history_revno_activate()
316
411
            
317
412
            revb.destroy()
318
413
    
343
438
            # History Mode activated
344
439
            self.entry_history.set_sensitive(True)
345
440
            self.button_history.set_sensitive(True)
346
 
            if self.entry_history.get_text() != "":
347
 
                self.on_entry_history_revno_activate()
348
441
        else:
349
442
            # History Mode deactivated
350
443
            self.entry_history.set_sensitive(False)
351
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 == 65293:
 
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
352
456
            
353
 
            # Return right window to normal view by acting like we jump to it
 
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()
 
461
    
 
462
    def on_entry_location_key_press_event(self, widget, event):
 
463
        """ Key pressed handler for the location entry. """
 
464
        if event.keyval == 65293:
 
465
            # Return was hit, so we have to jump
354
466
            self.on_button_location_jump_clicked(widget)
355
467
    
356
 
    @show_bzr_error
357
 
    def on_entry_history_revno_activate(self, widget=None):
358
 
        """ Key pressed handler for the history entry. """
359
 
        path = self.get_path()
360
 
        if not self.remote:
361
 
            self.remote = True
362
 
            self.remote_branch = self.wt.branch
363
 
        
364
 
        revno = int(self.entry_history.get_text())
365
 
        self.remote_revision = self.remote_branch.get_rev_id(revno)
366
 
        if self.set_path(path, True):
367
 
            self.refresh_right()
368
 
 
369
468
    def on_menuitem_add_files_activate(self, widget):
370
469
        """ Add file(s)... menu handler. """
371
 
        from bzrlib.plugins.gtk.olive.add import AddDialog
372
 
        add = AddDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
373
 
        response = add.run()
374
 
        add.destroy()
375
 
        if response == gtk.RESPONSE_OK:
376
 
            self.refresh_right()
377
 
 
 
470
        from add import OliveAdd
 
471
        add = OliveAdd(self.wt, self.wtpath, self.get_selected_right())
 
472
        add.display()
 
473
    
378
474
    def on_menuitem_branch_get_activate(self, widget):
379
475
        """ Branch/Get... menu handler. """
380
476
        from bzrlib.plugins.gtk.branch import BranchDialog
412
508
    @show_bzr_error
413
509
    def on_menuitem_branch_commit_activate(self, widget):
414
510
        """ Branch/Commit... menu handler. """
 
511
#     def __init__(self, wt, wtpath, notbranch, selected=None, parent=None):
415
512
        selected = self.get_selected_right()
416
513
        if selected:
417
514
            selected = os.path.join(self.wtpath, selected)
440
537
        from bzrlib.plugins.gtk.merge import MergeDialog
441
538
        
442
539
        if self.check_for_changes():
443
 
            error_dialog(_i18n('There are local changes in the branch'),
444
 
                         _i18n('Please commit or revert the changes before merging.'))
 
540
            error_dialog(_('There are local changes in the branch'),
 
541
                         _('Please commit or revert the changes before merging.'))
445
542
        else:
446
543
            parent_branch_path = self.wt.branch.get_parent()
447
 
            merge = MergeDialog(self.wt, self.wtpath, parent_branch_path, self.window)
448
 
            response = merge.run()
449
 
            merge.destroy()
450
 
            if response == gtk.RESPONSE_OK:
451
 
                self.refresh_right()
 
544
            merge = MergeDialog(self.wt, self.wtpath,default_branch_path=parent_branch_path )
 
545
            merge.display()
452
546
 
453
547
    @show_bzr_error
454
548
    def on_menuitem_branch_missing_revisions_activate(self, widget):
459
553
        local_branch = self.wt.branch
460
554
        parent_branch_path = local_branch.get_parent()
461
555
        if parent_branch_path is None:
462
 
            error_dialog(_i18n('Parent location is unknown'),
463
 
                         _i18n('Cannot determine missing revisions if no parent location is known.'))
 
556
            error_dialog(_('Parent location is unknown'),
 
557
                         _('Cannot determine missing revisions if no parent location is known.'))
464
558
            return
465
559
        
466
560
        parent_branch = Branch.open(parent_branch_path)
482
576
            
483
577
            dlg_txt = ""
484
578
            if local_extra:
485
 
                dlg_txt += _i18n('%d local extra revision(s). \n') % (len(local_extra),) 
 
579
                dlg_txt += _('%d local extra revision(s). \n') % (len(local_extra),) 
486
580
                ## NOTE: We do not want such ugly info about missing revisions
487
581
                ##       Revision Browser should be used there
488
582
                ## max_revisions = 10
489
583
                ## for log_revision in iter_log_revisions(local_extra, local_branch.repository, verbose=1):
490
584
                ##    dlg_txt += log_revision_one_line_text(log_revision)
491
585
                ##    if max_revisions <= 0:
492
 
                ##        dlg_txt += _i18n("more ... \n")
 
586
                ##        dlg_txt += _("more ... \n")
493
587
                ##        break
494
588
                ## max_revisions -= 1
495
589
            ## dlg_txt += "\n"
496
590
            if remote_extra:
497
 
                dlg_txt += _i18n('%d local missing revision(s).\n') % (len(remote_extra),) 
 
591
                dlg_txt += _('%d local missing revision(s).\n') % (len(remote_extra),) 
498
592
                ## max_revisions = 10
499
593
                ## for log_revision in iter_log_revisions(remote_extra, parent_branch.repository, verbose=1):
500
594
                ##    dlg_txt += log_revision_one_line_text(log_revision)
501
595
                ##    if max_revisions <= 0:
502
 
                ##        dlg_txt += _i18n("more ... \n")
 
596
                ##        dlg_txt += _("more ... \n")
503
597
                ##        break
504
598
                ##    max_revisions -= 1
505
599
                
506
 
            info_dialog(_i18n('There are missing revisions'),
 
600
            info_dialog(_('There are missing revisions'),
507
601
                        dlg_txt)
508
602
        else:
509
 
            info_dialog(_i18n('Local branch up to date'),
510
 
                        _i18n('There are no missing revisions.'))
 
603
            info_dialog(_('Local branch up to date'),
 
604
                        _('There are no missing revisions.'))
511
605
 
512
606
    @show_bzr_error
513
607
    def on_menuitem_branch_pull_activate(self, widget):
516
610
 
517
611
        location = branch_to.get_parent()
518
612
        if location is None:
519
 
            error_dialog(_i18n('Parent location is unknown'),
520
 
                                     _i18n('Pulling is not possible until there is a parent location.'))
 
613
            error_dialog(_('Parent location is unknown'),
 
614
                                     _('Pulling is not possible until there is a parent location.'))
521
615
            return
522
616
 
523
617
        branch_from = Branch.open(location)
527
621
 
528
622
        ret = branch_to.pull(branch_from)
529
623
        
530
 
        info_dialog(_i18n('Pull successful'), _i18n('%d revision(s) pulled.') % ret)
 
624
        info_dialog(_('Pull successful'), _('%d revision(s) pulled.') % ret)
531
625
        
532
626
    @show_bzr_error
533
627
    def on_menuitem_branch_update_activate(self, widget):
536
630
        ret = self.wt.update()
537
631
        conflicts = self.wt.conflicts()
538
632
        if conflicts:
539
 
            info_dialog(_i18n('Update successful but conflicts generated'), _i18n('Number of conflicts generated: %d.') % (len(conflicts),) )
 
633
            info_dialog(_('Update successful but conflicts generated'), _('Number of conflicts generated: %d.') % (len(conflicts),) )
540
634
        else:
541
 
            info_dialog(_i18n('Update successful'), _i18n('No conflicts generated.') )
 
635
            info_dialog(_('Update successful'), _('No conflicts generated.') )
542
636
    
543
637
    def on_menuitem_branch_push_activate(self, widget):
544
638
        """ Branch/Push... menu handler. """
550
644
    @show_bzr_error
551
645
    def on_menuitem_branch_revert_activate(self, widget):
552
646
        """ Branch/Revert all changes menu handler. """
553
 
        ret = self.wt.revert(None)
 
647
        ret = self.wt.revert([])
554
648
        if ret:
555
 
            warning_dialog(_i18n('Conflicts detected'),
556
 
                           _i18n('Please have a look at the working tree before continuing.'))
 
649
            warning_dialog(_('Conflicts detected'),
 
650
                           _('Please have a look at the working tree before continuing.'))
557
651
        else:
558
 
            info_dialog(_i18n('Revert successful'),
559
 
                        _i18n('All files reverted to last revision.'))
 
652
            info_dialog(_('Revert successful'),
 
653
                        _('All files reverted to last revision.'))
560
654
        self.refresh_right()
561
655
    
562
656
    def on_menuitem_branch_status_activate(self, widget):
591
685
    def on_menuitem_file_annotate_activate(self, widget):
592
686
        """ File/Annotate... menu handler. """
593
687
        if self.get_selected_right() is None:
594
 
            error_dialog(_i18n('No file was selected'),
595
 
                         _i18n('Please select a file from the list.'))
 
688
            error_dialog(_('No file was selected'),
 
689
                         _('Please select a file from the list.'))
596
690
            return
597
691
        
598
692
        branch = self.wt.branch
611
705
    def on_menuitem_file_bookmark_activate(self, widget):
612
706
        """ File/Bookmark current directory menu handler. """
613
707
        if self.pref.add_bookmark(self.path):
614
 
            info_dialog(_i18n('Bookmark successfully added'),
615
 
                        _i18n('The current directory was bookmarked. You can reach\nit by selecting it from the left panel.'))
 
708
            info_dialog(_('Bookmark successfully added'),
 
709
                        _('The current directory was bookmarked. You can reach\nit by selecting it from the left panel.'))
616
710
            self.pref.write()
617
711
        else:
618
 
            warning_dialog(_i18n('Location already bookmarked'),
619
 
                           _i18n('The current directory is already bookmarked.\nSee the left panel for reference.'))
 
712
            warning_dialog(_('Location already bookmarked'),
 
713
                           _('The current directory is already bookmarked.\nSee the left panel for reference.'))
620
714
        
621
715
        self.refresh_left()
622
716
    
623
717
    def on_menuitem_file_make_directory_activate(self, widget):
624
718
        """ File/Make directory... menu handler. """
625
 
        from bzrlib.plugins.gtk.olive.mkdir import MkdirDialog
626
 
        mkdir = MkdirDialog(self.wt, self.wtpath, self.window)
627
 
        response = mkdir.run()
628
 
        mkdir.destroy()
629
 
        if response == gtk.RESPONSE_OK:
630
 
            self.refresh_right()
 
719
        from mkdir import OliveMkdir
 
720
        mkdir = OliveMkdir(self.wt, self.wtpath)
 
721
        mkdir.display()
631
722
    
632
723
    def on_menuitem_file_move_activate(self, widget):
633
724
        """ File/Move... menu handler. """
634
 
        from bzrlib.plugins.gtk.olive.move import MoveDialog
635
 
        move = MoveDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
636
 
        response = move.run()
637
 
        move.destroy()
638
 
        if response == gtk.RESPONSE_OK:
639
 
            self.refresh_right()
 
725
        from move import OliveMove
 
726
        move = OliveMove(self.wt, self.wtpath, self.get_selected_right())
 
727
        move.display()
640
728
    
641
729
    def on_menuitem_file_rename_activate(self, widget):
642
730
        """ File/Rename... menu handler. """
643
 
        from bzrlib.plugins.gtk.olive.rename import RenameDialog
644
 
        rename = RenameDialog(self.wt, self.wtpath, self.get_selected_right(), self.window)
645
 
        response = rename.run()
646
 
        rename.destroy()
647
 
        if response == gtk.RESPONSE_OK:
648
 
            self.refresh_right()
 
731
        from rename import OliveRename
 
732
        rename = OliveRename(self.wt, self.wtpath, self.get_selected_right())
 
733
        rename.display()
649
734
 
650
735
    def on_menuitem_remove_file_activate(self, widget):
651
736
        """ Remove (unversion) selected file. """
652
 
        from bzrlib.plugins.gtk.olive.remove import RemoveDialog
653
 
        remove = RemoveDialog(self.wt, self.wtpath,
 
737
        from remove import OliveRemoveDialog
 
738
        remove = OliveRemoveDialog(self.wt, self.wtpath,
654
739
                                   selected=self.get_selected_right(),
655
740
                                   parent=self.window)
656
741
        response = remove.run()
673
758
    
674
759
    def on_menuitem_stats_infos_activate(self, widget):
675
760
        """ Statistics/Informations... menu handler. """
676
 
        from bzrlib.plugins.gtk.olive.info import InfoDialog
 
761
        from info import OliveInfo
677
762
        if self.remote:
678
 
            info = InfoDialog(self.remote_branch)
 
763
            info = OliveInfo(self.remote_branch)
679
764
        else:
680
 
            info = InfoDialog(self.wt.branch)
 
765
            info = OliveInfo(self.wt.branch)
681
766
        info.display()
682
767
    
683
768
    def on_menuitem_stats_log_activate(self, widget):
688
773
        else:
689
774
            branch = self.remote_branch
690
775
 
691
 
        window = branchwin.BranchWindow(branch, [branch.last_revision()], None, 
692
 
                                        parent=self.window)
 
776
        window = branchwin.BranchWindow(branch, branch.last_revision(), None, parent=self.window)
693
777
        window.show()
694
778
    
695
779
    def on_menuitem_view_refresh_activate(self, widget):
712
796
            self.refresh_right()
713
797
            
714
798
    def on_treeview_left_button_press_event(self, widget, event):
715
 
        """ Occurs when somebody clicks in the bookmark list. """
716
 
        treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
717
 
        treeselection = widget.get_selection()
718
 
        if treepathpos is not None:
719
 
            treeselection.select_path(treepathpos[0])
720
 
            if event.button == 1:
721
 
                newdir = self.get_selected_left()
722
 
                if newdir == None:
723
 
                    return
724
 
 
725
 
                if self.set_path(newdir):
726
 
                    self.refresh_right()
727
 
            elif event.button == 3:
728
 
                # Don't show context with nothing selected
729
 
                if self.get_selected_left() == None:
730
 
                    return
731
 
 
732
 
                # Create a menu
733
 
                from menu import OliveMenu
734
 
                menu = OliveMenu(path=self.get_path(),
735
 
                                 selected=self.get_selected_left(),
736
 
                                 app=self)
737
 
                
738
 
                menu.left_context_menu().popup(None, None, None, 0,
739
 
                                               event.time)
740
 
        else:
741
 
            if treeselection is not None:
742
 
                treeselection.unselect_all()
 
799
        """ Occurs when somebody right-clicks in the bookmark list. """
 
800
        if event.button == 3:
 
801
            # Don't show context with nothing selected
 
802
            if self.get_selected_left() == None:
 
803
                return
 
804
 
 
805
            # Create a menu
 
806
            from menu import OliveMenu
 
807
            menu = OliveMenu(path=self.get_path(),
 
808
                             selected=self.get_selected_left(),
 
809
                             app=self)
 
810
            
 
811
            menu.left_context_menu().popup(None, None, None, 0,
 
812
                                           event.time)
 
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()
743
827
 
744
828
    def on_treeview_left_row_activated(self, treeview, path, view_column):
745
829
        """ Occurs when somebody double-clicks or enters an item in the
753
837
            self.refresh_right()
754
838
 
755
839
    def on_treeview_right_button_press_event(self, widget, event):
756
 
        """ Occurs when somebody clicks in the file list. """
757
 
        treepathpos = widget.get_path_at_pos(int(event.x), int(event.y))
758
 
        if event.button == 1:
759
 
            if treepathpos is None and widget.get_selection is not None:
760
 
                treeselection = widget.get_selection()
761
 
                treeselection.unselect_all()
762
 
        elif event.button == 3:
763
 
            treeselection = widget.get_selection()
764
 
            if treepathpos is not None:
765
 
                treeselection.select_path(treepathpos[0])
766
 
            else:
767
 
                if treeselection is not None:
768
 
                    treeselection.unselect_all()
 
840
        """ Occurs when somebody right-clicks in the file list. """
 
841
        if event.button == 3:
769
842
            # Create a menu
770
843
            from menu import OliveMenu
771
844
            menu = OliveMenu(path=self.get_path(),
775
848
            m_open = menu.ui.get_widget('/context_right/open')
776
849
            m_add = menu.ui.get_widget('/context_right/add')
777
850
            m_remove = menu.ui.get_widget('/context_right/remove')
778
 
            m_remove_and_delete = menu.ui.get_widget('/context_right/remove_and_delete')
779
851
            m_rename = menu.ui.get_widget('/context_right/rename')
780
852
            m_revert = menu.ui.get_widget('/context_right/revert')
781
853
            m_commit = menu.ui.get_widget('/context_right/commit')
789
861
                    m_open.set_sensitive(False)
790
862
                    m_add.set_sensitive(False)
791
863
                    m_remove.set_sensitive(False)
792
 
                    m_remove_and_delete.set_sensitive(False)
793
864
                    m_rename.set_sensitive(False)
794
865
                    m_revert.set_sensitive(False)
795
866
                    m_commit.set_sensitive(False)
796
867
                    m_annotate.set_sensitive(False)
797
868
                    m_diff.set_sensitive(False)
798
869
                else:
799
 
                    if treepathpos is None:
800
 
                        m_open.set_sensitive(False)
801
 
                        m_add.set_sensitive(False)
802
 
                        m_remove.set_sensitive(False)
803
 
                        m_remove_and_delete.set_sensitive(False)
804
 
                        m_rename.set_sensitive(False)
805
 
                        m_annotate.set_sensitive(False)
806
 
                        m_diff.set_sensitive(False)
807
 
                        m_revert.set_sensitive(False)
808
 
                    else:
809
 
                        m_open.set_sensitive(True)
810
 
                        m_add.set_sensitive(True)
811
 
                        m_remove.set_sensitive(True)
812
 
                        m_remove_and_delete.set_sensitive(True)
813
 
                        m_rename.set_sensitive(True)
814
 
                        m_annotate.set_sensitive(True)
815
 
                        m_diff.set_sensitive(True)
816
 
                        m_revert.set_sensitive(True)
 
870
                    m_open.set_sensitive(True)
 
871
                    m_add.set_sensitive(True)
 
872
                    m_remove.set_sensitive(True)
 
873
                    m_rename.set_sensitive(True)
 
874
                    m_revert.set_sensitive(True)
817
875
                    m_commit.set_sensitive(True)
 
876
                    m_annotate.set_sensitive(True)
 
877
                    m_diff.set_sensitive(True)
818
878
            except bzrerrors.NotBranchError:
819
 
                if treepathpos is None:
820
 
                    m_open.set_sensitive(False)
821
 
                else:
822
 
                    m_open.set_sensitive(True)
 
879
                m_open.set_sensitive(True)
823
880
                m_add.set_sensitive(False)
824
881
                m_remove.set_sensitive(False)
825
 
                m_remove_and_delete.set_sensitive(False)
826
882
                m_rename.set_sensitive(False)
827
883
                m_revert.set_sensitive(False)
828
884
                m_commit.set_sensitive(False)
863
919
    
864
920
    def on_window_main_delete_event(self, widget, event=None):
865
921
        """ Do some stuff before exiting. """
866
 
        width, height = self.window.get_size()
 
922
        width, height = self.window_main.get_size()
867
923
        self.pref.set_preference('window_width', width)
868
924
        self.pref.set_preference('window_height', height)
869
 
        x, y = self.window.get_position()
 
925
        x, y = self.window_main.get_position()
870
926
        self.pref.set_preference('window_x', x)
871
927
        self.pref.set_preference('window_y', y)
872
928
        self.pref.set_preference('paned_position',
873
 
                                 self.window.hpaned_main.get_position())
 
929
                                 self.hpaned_main.get_position())
874
930
        
875
931
        self.pref.write()
876
 
        self.window.destroy()
 
932
        self.window_main.destroy()
877
933
        
878
934
    def _load_left(self):
879
935
        """ Load data into the left panel. (Bookmarks) """
884
940
        bookmarks = self.pref.get_bookmarks()
885
941
        
886
942
        # Add them to the TreeStore
887
 
        titer = treestore.append(None, [_i18n('Bookmarks'), None])
888
 
 
889
 
        # Get titles and sort by title
890
 
        bookmarks = [[self.pref.get_bookmark_title(item), item] for item in bookmarks]
891
 
        bookmarks.sort()
892
 
        for title_item in bookmarks:
893
 
            treestore.append(titer, title_item)
 
943
        titer = treestore.append(None, [_('Bookmarks'), None])
 
944
        for item in bookmarks:
 
945
            title = self.pref.get_bookmark_title(item)
 
946
            treestore.append(titer, [title, item])
894
947
        
895
948
        # Create the column and add it to the TreeView
896
949
        self.treeview_left.set_model(treestore)
897
 
        tvcolumn_bookmark = gtk.TreeViewColumn(_i18n('Bookmark'))
 
950
        tvcolumn_bookmark = gtk.TreeViewColumn(_('Bookmark'))
898
951
        self.treeview_left.append_column(tvcolumn_bookmark)
899
952
        
900
953
        # Set up the cells
944
997
            try:
945
998
                statinfo = os.stat(self.path + os.sep + item)
946
999
            except OSError, e:
947
 
                if e.errno in self.acceptable_errors:
 
1000
                if e.errno == 40:
948
1001
                    continue
949
1002
                else:
950
1003
                    raise
994
1047
                    self.wt.unlock()
995
1048
            
996
1049
            if status == 'renamed':
997
 
                st = _i18n('renamed')
 
1050
                st = _('renamed')
998
1051
            elif status == 'removed':
999
 
                st = _i18n('removed')
 
1052
                st = _('removed')
1000
1053
            elif status == 'added':
1001
 
                st = _i18n('added')
 
1054
                st = _('added')
1002
1055
            elif status == 'modified':
1003
 
                st = _i18n('modified')
 
1056
                st = _('modified')
1004
1057
            elif status == 'unchanged':
1005
 
                st = _i18n('unchanged')
 
1058
                st = _('unchanged')
1006
1059
            elif status == 'ignored':
1007
 
                st = _i18n('ignored')
 
1060
                st = _('ignored')
1008
1061
            else:
1009
 
                st = _i18n('unknown')
 
1062
                st = _('unknown')
1010
1063
            
1011
1064
            try:
1012
1065
                statinfo = os.stat(self.path + os.sep + item)
1013
1066
            except OSError, e:
1014
 
                if e.errno in self.acceptable_errors:
 
1067
                if e.errno == 40:
1015
1068
                    continue
1016
1069
                else:
1017
1070
                    raise
1028
1081
        
1029
1082
        # Create the columns and add them to the TreeView
1030
1083
        self.treeview_right.set_model(liststore)
1031
 
        self._tvcolumn_filename = gtk.TreeViewColumn(_i18n('Filename'))
1032
 
        self._tvcolumn_status = gtk.TreeViewColumn(_i18n('Status'))
1033
 
        self._tvcolumn_size = gtk.TreeViewColumn(_i18n('Size'))
1034
 
        self._tvcolumn_mtime = gtk.TreeViewColumn(_i18n('Last modified'))
 
1084
        self._tvcolumn_filename = gtk.TreeViewColumn(_('Filename'))
 
1085
        self._tvcolumn_status = gtk.TreeViewColumn(_('Status'))
 
1086
        self._tvcolumn_size = gtk.TreeViewColumn(_('Size'))
 
1087
        self._tvcolumn_mtime = gtk.TreeViewColumn(_('Last modified'))
1035
1088
        self.treeview_right.append_column(self._tvcolumn_filename)
1036
1089
        self.treeview_right.append_column(self._tvcolumn_status)
1037
1090
        self.treeview_right.append_column(self._tvcolumn_size)
1102
1155
 
1103
1156
    def set_statusbar(self, message):
1104
1157
        """ Set the statusbar message. """
1105
 
        self.window.statusbar.push(self.context_id, message)
 
1158
        self.statusbar.push(self.context_id, message)
1106
1159
    
1107
1160
    def clear_statusbar(self):
1108
1161
        """ Clean the last message from the statusbar. """
1109
 
        self.window.statusbar.pop(self.context_id)
 
1162
        self.statusbar.pop(self.context_id)
1110
1163
    
1111
1164
    def set_sensitivity(self):
1112
1165
        """ Set menu and toolbar sensitivity. """
1113
1166
        if not self.remote:
1114
 
            self.window.set_view_to_localbranch(self.notbranch)
 
1167
            # We're local
 
1168
            self.menuitem_branch_init.set_sensitive(self.notbranch)
 
1169
            self.menuitem_branch_get.set_sensitive(self.notbranch)
 
1170
            self.menuitem_branch_checkout.set_sensitive(self.notbranch)
 
1171
            self.menuitem_branch_pull.set_sensitive(not self.notbranch)
 
1172
            self.menuitem_branch_push.set_sensitive(not self.notbranch)
 
1173
            self.menuitem_branch_update.set_sensitive(not self.notbranch)
 
1174
            self.menuitem_branch_revert.set_sensitive(not self.notbranch)
 
1175
            self.menuitem_branch_merge.set_sensitive(not self.notbranch)
 
1176
            self.menuitem_branch_commit.set_sensitive(not self.notbranch)
 
1177
            self.menuitem_branch_tags.set_sensitive(not self.notbranch)
 
1178
            self.menuitem_branch_status.set_sensitive(not self.notbranch)
 
1179
            self.menuitem_branch_missing.set_sensitive(not self.notbranch)
 
1180
            self.menuitem_branch_conflicts.set_sensitive(not self.notbranch)
 
1181
            self.menuitem_stats.set_sensitive(not self.notbranch)
 
1182
            self.menuitem_stats_diff.set_sensitive(not self.notbranch)
 
1183
            self.menuitem_add_files.set_sensitive(not self.notbranch)
 
1184
            self.menuitem_remove_files.set_sensitive(not self.notbranch)
 
1185
            self.menuitem_file_make_directory.set_sensitive(not self.notbranch)
 
1186
            self.menuitem_file_rename.set_sensitive(not self.notbranch)
 
1187
            self.menuitem_file_move.set_sensitive(not self.notbranch)
 
1188
            self.menuitem_file_annotate.set_sensitive(not self.notbranch)
 
1189
            #self.menutoolbutton_diff.set_sensitive(True)
 
1190
            self.toolbutton_diff.set_sensitive(not self.notbranch)
 
1191
            self.toolbutton_log.set_sensitive(not self.notbranch)
 
1192
            self.toolbutton_commit.set_sensitive(not self.notbranch)
 
1193
            self.toolbutton_pull.set_sensitive(not self.notbranch)
 
1194
            self.toolbutton_push.set_sensitive(not self.notbranch)
 
1195
            self.toolbutton_update.set_sensitive(not self.notbranch)
1115
1196
        else:
1116
 
            self.window.set_view_to_remotebranch()
 
1197
            # We're remote
 
1198
            self.menuitem_branch_init.set_sensitive(False)
 
1199
            self.menuitem_branch_get.set_sensitive(True)
 
1200
            self.menuitem_branch_checkout.set_sensitive(True)
 
1201
            self.menuitem_branch_pull.set_sensitive(False)
 
1202
            self.menuitem_branch_push.set_sensitive(False)
 
1203
            self.menuitem_branch_update.set_sensitive(False)
 
1204
            self.menuitem_branch_revert.set_sensitive(False)
 
1205
            self.menuitem_branch_merge.set_sensitive(False)
 
1206
            self.menuitem_branch_commit.set_sensitive(False)
 
1207
            self.menuitem_branch_tags.set_sensitive(True)
 
1208
            self.menuitem_branch_status.set_sensitive(False)
 
1209
            self.menuitem_branch_missing.set_sensitive(False)
 
1210
            self.menuitem_branch_conflicts.set_sensitive(False)
 
1211
            self.menuitem_stats.set_sensitive(True)
 
1212
            self.menuitem_stats_diff.set_sensitive(False)
 
1213
            self.menuitem_add_files.set_sensitive(False)
 
1214
            self.menuitem_remove_files.set_sensitive(False)
 
1215
            self.menuitem_file_make_directory.set_sensitive(False)
 
1216
            self.menuitem_file_rename.set_sensitive(False)
 
1217
            self.menuitem_file_move.set_sensitive(False)
 
1218
            self.menuitem_file_annotate.set_sensitive(False)
 
1219
            #self.menutoolbutton_diff.set_sensitive(True)
 
1220
            self.toolbutton_diff.set_sensitive(False)
 
1221
            self.toolbutton_log.set_sensitive(True)
 
1222
            self.toolbutton_commit.set_sensitive(False)
 
1223
            self.toolbutton_pull.set_sensitive(False)
 
1224
            self.toolbutton_push.set_sensitive(False)
 
1225
            self.toolbutton_update.set_sensitive(False)
1117
1226
    
1118
1227
    def refresh_left(self):
1119
1228
        """ Refresh the bookmark list. """
1129
1238
        bookmarks = self.pref.get_bookmarks()
1130
1239
 
1131
1240
        # Add them to the TreeStore
1132
 
        titer = treestore.append(None, [_i18n('Bookmarks'), None])
 
1241
        titer = treestore.append(None, [_('Bookmarks'), None])
 
1242
        for item in bookmarks:
 
1243
            title = self.pref.get_bookmark_title(item)
 
1244
            treestore.append(titer, [title, item])
1133
1245
 
1134
 
        # Get titles and sort by title
1135
 
        bookmarks = [[self.pref.get_bookmark_title(item), item] for item in bookmarks]
1136
 
        bookmarks.sort()
1137
 
        for title_item in bookmarks:
1138
 
            treestore.append(titer, title_item)
1139
 
        
1140
1246
        # Add the TreeStore to the TreeView
1141
1247
        self.treeview_left.set_model(treestore)
1142
1248
 
1196
1302
                try:
1197
1303
                    statinfo = os.stat(self.path + os.sep + item)
1198
1304
                except OSError, e:
1199
 
                    if e.errno in self.acceptable_errors:
 
1305
                    if e.errno == 40:
1200
1306
                        continue
1201
1307
                    else:
1202
1308
                        raise
1246
1352
                        self.wt.unlock()
1247
1353
                
1248
1354
                if status == 'renamed':
1249
 
                    st = _i18n('renamed')
 
1355
                    st = _('renamed')
1250
1356
                elif status == 'removed':
1251
 
                    st = _i18n('removed')
 
1357
                    st = _('removed')
1252
1358
                elif status == 'added':
1253
 
                    st = _i18n('added')
 
1359
                    st = _('added')
1254
1360
                elif status == 'modified':
1255
 
                    st = _i18n('modified')
 
1361
                    st = _('modified')
1256
1362
                elif status == 'unchanged':
1257
 
                    st = _i18n('unchanged')
 
1363
                    st = _('unchanged')
1258
1364
                elif status == 'ignored':
1259
 
                    st = _i18n('ignored')
 
1365
                    st = _('ignored')
1260
1366
                    if not ignored_files:
1261
1367
                        continue
1262
1368
                else:
1263
 
                    st = _i18n('unknown')
 
1369
                    st = _('unknown')
1264
1370
                
1265
1371
                try:
1266
1372
                    statinfo = os.stat(self.path + os.sep + item)
1267
1373
                except OSError, e:
1268
 
                    if e.errno in self.acceptable_errors:
 
1374
                    if e.errno == 40:
1269
1375
                        continue
1270
1376
                    else:
1271
1377
                        raise
1374
1480
            if sys.platform == 'win32':
1375
1481
                print "pyWin32 modules needed to run Olive on Win32."
1376
1482
                sys.exit(1)
 
1483
            else:
 
1484
                pass
1377
1485
        
1378
1486
        driveletters = []
1379
1487
        for drive in string.ascii_uppercase:
1380
 
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED or\
1381
 
                win32file.GetDriveType(drive+':') == win32file.DRIVE_REMOTE:
 
1488
            if win32file.GetDriveType(drive+':') == win32file.DRIVE_FIXED:
1382
1489
                driveletters.append(drive+':')
1383
1490
        return driveletters
1384
1491
    
1617
1724
                return self._get_default(option)
1618
1725
            except KeyError:
1619
1726
                return None
 
1727