~bzr-gtk/bzr-gtk/0.95

« back to all changes in this revision

Viewing changes to __init__.py

  • Committer: Daniel Schierbeck
  • Date: 2008-04-02 00:31:14 UTC
  • mto: (450.1.15 trunk)
  • mto: This revision was merged to the branch mainline in revision 458.
  • Revision ID: daniel.schierbeck@gmail.com-20080402003114-kwkxtnv7za97ur6t
Added tag icon to branch history window.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
"""Graphical support for Bazaar using GTK.
16
16
 
17
17
This plugin includes:
 
18
commit-notify     Start the graphical notifier of commits.
18
19
gannotate         GTK+ annotate. 
19
20
gbranch           GTK+ branching. 
20
21
gcheckout         GTK+ checkout. 
21
22
gcommit           GTK+ commit dialog.
22
23
gconflicts        GTK+ conflicts. 
23
24
gdiff             Show differences in working tree in a GTK+ Window. 
 
25
ghandle-patch     Display and optionally merge a merge directive or patch.
24
26
ginit             Initialise a new branch.
25
 
gloom             GTK+ loom browse dialog
26
 
gmerge            GTK+ merge dialog
27
27
gmissing          GTK+ missing revisions dialog. 
28
28
gpreferences      GTK+ preferences dialog. 
29
29
gpush             GTK+ push.
37
37
 
38
38
import bzrlib
39
39
 
40
 
version_info = (0, 95, 0, 'dev', 1)
 
40
version_info = (0, 94, 0, 'dev', 0)
41
41
 
42
42
if version_info[3] == 'final':
43
43
    version_string = '%d.%d.%d' % version_info[:3]
105
105
    bzrlib.ui.ui_factory = GtkUIFactory()
106
106
 
107
107
 
108
 
def data_basedirs():
109
 
    return [os.path.dirname(__file__),
 
108
def data_path():
 
109
    return os.path.dirname(__file__)
 
110
 
 
111
 
 
112
def icon_path(*args):
 
113
    basedirs = [os.path.join(data_path()),
110
114
             "/usr/share/bzr-gtk", 
111
115
             "/usr/local/share/bzr-gtk"]
112
 
 
113
 
 
114
 
def data_path(*args):
115
 
    for basedir in data_basedirs():
116
 
        path = os.path.join(basedir, *args)
 
116
    for basedir in basedirs:
 
117
        path = os.path.join(basedir, 'icons', *args)
117
118
        if os.path.exists(path):
118
119
            return path
119
120
    return None
120
121
 
121
122
 
122
 
def icon_path(*args):
123
 
    return data_path(os.path.join('icons', *args))
124
 
 
125
 
 
126
 
def open_display():
127
 
    pygtk = import_pygtk()
128
 
    try:
129
 
        import gtk
130
 
    except RuntimeError, e:
131
 
        if str(e) == "could not open display":
132
 
            raise NoDisplayError
133
 
    set_ui_factory()
134
 
    return gtk
135
 
 
136
 
 
137
123
class GTKCommand(Command):
138
124
    """Abstract class providing GTK specific run commands."""
139
125
 
 
126
    def open_display(self):
 
127
        pygtk = import_pygtk()
 
128
        try:
 
129
            import gtk
 
130
        except RuntimeError, e:
 
131
            if str(e) == "could not open display":
 
132
                raise NoDisplayError
 
133
        set_ui_factory()
 
134
        return gtk
 
135
 
140
136
    def run(self):
141
 
        open_display()
 
137
        self.open_display()
142
138
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
143
139
        dialog.run()
144
140
 
172
168
 
173
169
    def run(self, location="."):
174
170
        (br, path) = branch.Branch.open_containing(location)
175
 
        open_display()
176
 
        from bzrlib.plugins.gtk.push import PushDialog
 
171
        self.open_display()
 
172
        from push import PushDialog
177
173
        dialog = PushDialog(br.repository, br.last_revision(), br)
178
174
        dialog.run()
179
175
 
180
176
 
181
 
class cmd_gloom(GTKCommand):
182
 
    """ GTK+ loom.
183
 
    
184
 
    """
185
 
    takes_args = [ "location?" ]
186
 
 
187
 
    def run(self, location="."):
188
 
        try:
189
 
            (tree, path) = workingtree.WorkingTree.open_containing(location)
190
 
            br = tree.branch
191
 
        except NoWorkingTree, e:
192
 
            (br, path) = branch.Branch.open_containing(location)
193
 
            tree = None
194
 
        open_display()
195
 
        from bzrlib.plugins.gtk.loom import LoomDialog
196
 
        dialog = LoomDialog(br, tree)
197
 
        dialog.run()
198
 
 
199
177
 
200
178
class cmd_gdiff(GTKCommand):
201
179
    """Show differences in working tree in a GTK+ Window.
215
193
            if revision is not None:
216
194
                if len(revision) == 1:
217
195
                    tree1 = wt
218
 
                    revision_id = revision[0].as_revision_id(tree1.branch)
 
196
                    revision_id = revision[0].in_history(branch).rev_id
219
197
                    tree2 = branch.repository.revision_tree(revision_id)
220
198
                elif len(revision) == 2:
221
 
                    revision_id_0 = revision[0].as_revision_id(branch)
 
199
                    revision_id_0 = revision[0].in_history(branch).rev_id
222
200
                    tree2 = branch.repository.revision_tree(revision_id_0)
223
 
                    revision_id_1 = revision[1].as_revision_id(branch)
 
201
                    revision_id_1 = revision[1].in_history(branch).rev_id
224
202
                    tree1 = branch.repository.revision_tree(revision_id_1)
225
203
            else:
226
204
                tree1 = wt
253
231
    
254
232
    :return: The viz window object.
255
233
    """
256
 
    from bzrlib.plugins.gtk.viz import BranchWindow
 
234
    from viz import BranchWindow
257
235
    return BranchWindow(branch, revisions, limit)
258
236
 
259
237
 
283
261
            if revision is None:
284
262
                revids.append(br.last_revision())
285
263
            else:
286
 
                revids.append(revision[0].as_revision_id(br))
 
264
                (revno, revid) = revision[0].in_history(br)
 
265
                revids.append(revid)
287
266
        import gtk
288
267
        pp = start_viz_window(br, revids, limit)
289
268
        pp.connect("destroy", lambda w: gtk.main_quit())
308
287
    aliases = ["gblame", "gpraise"]
309
288
    
310
289
    def run(self, filename, all=False, plain=False, line='1', revision=None):
311
 
        gtk = open_display()
 
290
        gtk = self.open_display()
312
291
 
313
292
        try:
314
293
            line = int(line)
333
312
        if revision is not None:
334
313
            if len(revision) != 1:
335
314
                raise BzrCommandError("Only 1 revion may be specified.")
336
 
            revision_id = revision[0].as_revision_id(br)
 
315
            revision_id = revision[0].in_history(br).rev_id
337
316
            tree = br.repository.revision_tree(revision_id)
338
317
        else:
339
318
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
340
319
 
341
 
        window = GAnnotateWindow(all, plain, branch=br)
 
320
        window = GAnnotateWindow(all, plain)
342
321
        window.connect("destroy", lambda w: gtk.main_quit())
343
322
        config = GAnnotateConfig(window)
344
323
        window.show()
367
346
 
368
347
    def run(self, filename=None):
369
348
        import os
370
 
        open_display()
 
349
        self.open_display()
371
350
        from commit import CommitDialog
372
351
        from bzrlib.errors import (BzrCommandError,
373
352
                                   NotBranchError,
380
359
            br = wt.branch
381
360
        except NoWorkingTree, e:
382
361
            from dialog import error_dialog
383
 
            error_dialog(_i18n('Directory does not have a working tree'),
384
 
                         _i18n('Operation aborted.'))
 
362
            error_dialog(_('Directory does not have a working tree'),
 
363
                         _('Operation aborted.'))
385
364
            return 1 # should this be retval=3?
386
365
 
387
366
        # It is a good habit to keep things locked for the duration, but it
404
383
    
405
384
    aliases = [ "gst" ]
406
385
    takes_args = ['PATH?']
407
 
    takes_options = ['revision']
 
386
    takes_options = []
408
387
 
409
 
    def run(self, path='.', revision=None):
 
388
    def run(self, path='.'):
410
389
        import os
411
 
        gtk = open_display()
 
390
        gtk = self.open_display()
412
391
        from status import StatusDialog
413
392
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
414
 
        
415
 
        if revision is not None:
416
 
            try:
417
 
                revision_id = revision[0].as_revision_id(wt.branch)
418
 
            except:
419
 
                from bzrlib.errors import BzrError
420
 
                raise BzrError('Revision %r doesn\'t exist' % revision[0].user_spec )
421
 
        else:
422
 
            revision_id = None
423
 
 
424
 
        status = StatusDialog(wt, wt_path, revision_id)
 
393
        status = StatusDialog(wt, wt_path)
425
394
        status.connect("destroy", gtk.main_quit)
426
395
        status.run()
427
396
 
432
401
    """
433
402
    def run(self):
434
403
        (br, path) = branch.Branch.open_containing(".")
435
 
        gtk = open_display()
 
404
        gtk = self.open_display()
436
405
        from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
437
406
        from StringIO import StringIO
438
407
        dialog = SendMergeDirectiveDialog(br)
454
423
    """
455
424
    def run(self):
456
425
        (wt, path) = workingtree.WorkingTree.open_containing('.')
457
 
        open_display()
 
426
        self.open_display()
458
427
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
459
428
        dialog = ConflictsDialog(wt)
460
429
        dialog.run()
465
434
 
466
435
    """
467
436
    def run(self):
468
 
        open_display()
 
437
        self.open_display()
469
438
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
470
439
        dialog = PreferencesWindow()
471
440
        dialog.run()
472
441
 
473
442
 
474
 
class cmd_gmerge(Command):
475
 
    """ GTK+ merge dialog
476
 
    
477
 
    """
478
 
    takes_args = ["merge_from_path?"]
479
 
    def run(self, merge_from_path=None):
480
 
        from bzrlib import workingtree
481
 
        from bzrlib.plugins.gtk.dialog import error_dialog
482
 
        from bzrlib.plugins.gtk.merge import MergeDialog
483
 
        
484
 
        (wt, path) = workingtree.WorkingTree.open_containing('.')
485
 
        old_tree = wt.branch.repository.revision_tree(wt.branch.last_revision())
486
 
        delta = wt.changes_from(old_tree)
487
 
        if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
488
 
            error_dialog(_i18n('There are local changes in the branch'),
489
 
                         _i18n('Please commit or revert the changes before merging.'))
490
 
        else:
491
 
            parent_branch_path = wt.branch.get_parent()
492
 
            merge = MergeDialog(wt, path, parent_branch_path)
493
 
            response = merge.run()
494
 
            merge.destroy()
495
 
 
496
 
 
497
443
class cmd_gmissing(Command):
498
444
    """ GTK+ missing revisions dialog.
499
445
 
532
478
 
533
479
class cmd_ginit(GTKCommand):
534
480
    def run(self):
535
 
        open_display()
 
481
        self.open_display()
536
482
        from initialize import InitDialog
537
483
        dialog = InitDialog(os.path.abspath(os.path.curdir))
538
484
        dialog.run()
542
488
    def run(self):
543
489
        br = branch.Branch.open_containing('.')[0]
544
490
        
545
 
        gtk = open_display()
 
491
        gtk = self.open_display()
546
492
        from tags import TagsWindow
547
493
        window = TagsWindow(br)
548
494
        window.show()
557
503
    cmd_gconflicts, 
558
504
    cmd_gdiff,
559
505
    cmd_ginit,
560
 
    cmd_gmerge,
561
506
    cmd_gmissing, 
562
507
    cmd_gpreferences, 
563
508
    cmd_gpush, 
567
512
    cmd_visualise
568
513
    ]
569
514
 
570
 
try:
571
 
    from bzrlib.plugins import loom
572
 
except ImportError:
573
 
    pass # Loom plugin doesn't appear to be present
574
 
else:
575
 
    commands.append(cmd_gloom)
576
 
 
577
515
for cmd in commands:
578
516
    register_command(cmd)
579
517
 
580
518
 
 
519
class cmd_commit_notify(GTKCommand):
 
520
    """Run the bzr commit notifier.
 
521
 
 
522
    This is a background program which will pop up a notification on the users
 
523
    screen when a commit occurs.
 
524
    """
 
525
 
 
526
    def run(self):
 
527
        from notify import NotifyPopupMenu
 
528
        gtk = self.open_display()
 
529
        menu = NotifyPopupMenu()
 
530
        icon = gtk.status_icon_new_from_file(icon_path("bzr-icon-64.png"))
 
531
        icon.connect('popup-menu', menu.display)
 
532
 
 
533
        import cgi
 
534
        import dbus
 
535
        import dbus.service
 
536
        import pynotify
 
537
        from bzrlib.bzrdir import BzrDir
 
538
        from bzrlib import errors
 
539
        from bzrlib.osutils import format_date
 
540
        from bzrlib.transport import get_transport
 
541
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
 
542
            import dbus.glib
 
543
        BROADCAST_INTERFACE = "org.bazaarvcs.plugins.dbus.Broadcast"
 
544
        bus = dbus.SessionBus()
 
545
 
 
546
        def catch_branch(revision_id, urls):
 
547
            # TODO: show all the urls, or perhaps choose the 'best'.
 
548
            url = urls[0]
 
549
            try:
 
550
                if isinstance(revision_id, unicode):
 
551
                    revision_id = revision_id.encode('utf8')
 
552
                transport = get_transport(url)
 
553
                a_dir = BzrDir.open_from_transport(transport)
 
554
                branch = a_dir.open_branch()
 
555
                revno = branch.revision_id_to_revno(revision_id)
 
556
                revision = branch.repository.get_revision(revision_id)
 
557
                summary = 'New revision %d in %s' % (revno, url)
 
558
                body  = 'Committer: %s\n' % revision.committer
 
559
                body += 'Date: %s\n' % format_date(revision.timestamp,
 
560
                    revision.timezone)
 
561
                body += '\n'
 
562
                body += revision.message
 
563
                body = cgi.escape(body)
 
564
                nw = pynotify.Notification(summary, body)
 
565
                def start_viz(notification=None, action=None, data=None):
 
566
                    """Start the viz program."""
 
567
                    pp = start_viz_window(branch, revision_id)
 
568
                    pp.show()
 
569
                def start_branch(notification=None, action=None, data=None):
 
570
                    """Start a Branch dialog"""
 
571
                    from bzrlib.plugins.gtk.branch import BranchDialog
 
572
                    bd = BranchDialog(remote_path=url)
 
573
                    bd.run()
 
574
                nw.add_action("inspect", "Inspect", start_viz, None)
 
575
                nw.add_action("branch", "Branch", start_branch, None)
 
576
                nw.set_timeout(5000)
 
577
                nw.show()
 
578
            except Exception, e:
 
579
                print e
 
580
                raise
 
581
        bus.add_signal_receiver(catch_branch,
 
582
                                dbus_interface=BROADCAST_INTERFACE,
 
583
                                signal_name="Revision")
 
584
        pynotify.init("bzr commit-notify")
 
585
        gtk.main()
 
586
 
 
587
register_command(cmd_commit_notify)
 
588
 
 
589
 
581
590
class cmd_gselftest(GTKCommand):
582
591
    """Version of selftest that displays a notification at the end"""
583
592
 
674
683
register_command(cmd_test_gtk)
675
684
 
676
685
 
 
686
class cmd_ghandle_patch(GTKCommand):
 
687
    """Display a patch or merge directive, possibly merging.
 
688
 
 
689
    This is a helper, meant to be launched from other programs like browsers
 
690
    or email clients.  Since these programs often do not allow parameters to
 
691
    be provided, a "handle-patch" script is included.
 
692
    """
 
693
 
 
694
    takes_args = ['path']
 
695
 
 
696
    def run(self, path):
 
697
        try:
 
698
            from bzrlib.plugins.gtk.diff import (DiffWindow,
 
699
                                                 MergeDirectiveWindow)
 
700
            lines = open(path, 'rb').readlines()
 
701
            lines = [l.replace('\r\n', '\n') for l in lines]
 
702
            try:
 
703
                directive = merge_directive.MergeDirective.from_lines(lines)
 
704
            except errors.NotAMergeDirective:
 
705
                window = DiffWindow()
 
706
                window.set_diff_text(path, lines)
 
707
            else:
 
708
                window = MergeDirectiveWindow(directive, path)
 
709
                window.set_diff_text(path, directive.patch.splitlines(True))
 
710
            window.show()
 
711
            gtk = self.open_display()
 
712
            window.connect("destroy", gtk.main_quit)
 
713
        except Exception, e:
 
714
            from dialog import error_dialog
 
715
            error_dialog('Error', str(e))
 
716
            raise
 
717
        gtk.main()
 
718
 
 
719
 
 
720
register_command(cmd_ghandle_patch)
 
721
 
677
722
 
678
723
import gettext
679
724
gettext.install('olive-gtk')
680
725
 
681
 
# Let's create a specialized alias to protect '_' from being erased by other
682
 
# uses of '_' as an anonymous variable (think pdb for one).
683
 
_i18n = gettext.gettext
684
726
 
685
727
class NoDisplayError(BzrCommandError):
686
728
    """gtk could not find a proper display"""