/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 __init__.py

  • Committer: Jelmer Vernooij
  • Date: 2008-03-09 13:47:52 UTC
  • mto: This revision was merged to the branch mainline in revision 447.
  • Revision ID: jelmer@samba.org-20080309134752-syf9kwzy6e919jhj
Add note about python-nautilus requiring a libpythonXX.so symlink.

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
 
gmerge            GTK+ merge dialog
26
27
gmissing          GTK+ missing revisions dialog. 
27
28
gpreferences      GTK+ preferences dialog. 
28
29
gpush             GTK+ push.
36
37
 
37
38
import bzrlib
38
39
 
39
 
version_info = (0, 95, 0, 'dev', 1)
 
40
version_info = (0, 94, 0, 'dev', 0)
40
41
 
41
42
if version_info[3] == 'final':
42
43
    version_string = '%d.%d.%d' % version_info[:3]
44
45
    version_string = '%d.%d.%d%s%d' % version_info
45
46
__version__ = version_string
46
47
 
47
 
required_bzrlib = (1, 3)
 
48
required_bzrlib = (1, 0)
48
49
 
49
50
def check_bzrlib_version(desired):
50
51
    """Check that bzrlib is compatible.
104
105
    bzrlib.ui.ui_factory = GtkUIFactory()
105
106
 
106
107
 
107
 
def data_basedirs():
108
 
    return [os.path.dirname(__file__),
109
 
             "/usr/share/bzr-gtk", 
110
 
             "/usr/local/share/bzr-gtk"]
111
 
 
112
 
 
113
 
def data_path(*args):
114
 
    for basedir in data_basedirs():
115
 
        path = os.path.join(basedir, *args)
116
 
        if os.path.exists(path):
117
 
            return path
118
 
    return None
119
 
 
120
 
 
121
 
def icon_path(*args):
122
 
    return data_path(os.path.join('icons', *args))
123
 
 
124
 
 
125
 
def open_display():
126
 
    pygtk = import_pygtk()
127
 
    try:
128
 
        import gtk
129
 
    except RuntimeError, e:
130
 
        if str(e) == "could not open display":
131
 
            raise NoDisplayError
132
 
    set_ui_factory()
133
 
    return gtk
134
 
 
 
108
def data_path():
 
109
    return os.path.dirname(__file__)
 
110
 
135
111
 
136
112
class GTKCommand(Command):
137
113
    """Abstract class providing GTK specific run commands."""
138
114
 
 
115
    def open_display(self):
 
116
        pygtk = import_pygtk()
 
117
        try:
 
118
            import gtk
 
119
        except RuntimeError, e:
 
120
            if str(e) == "could not open display":
 
121
                raise NoDisplayError
 
122
        set_ui_factory()
 
123
        return gtk
 
124
 
139
125
    def run(self):
140
 
        open_display()
 
126
        self.open_display()
141
127
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
142
128
        dialog.run()
143
129
 
171
157
 
172
158
    def run(self, location="."):
173
159
        (br, path) = branch.Branch.open_containing(location)
174
 
        open_display()
 
160
        self.open_display()
175
161
        from push import PushDialog
176
162
        dialog = PushDialog(br.repository, br.last_revision(), br)
177
163
        dialog.run()
196
182
            if revision is not None:
197
183
                if len(revision) == 1:
198
184
                    tree1 = wt
199
 
                    revision_id = revision[0].as_revision_id(tree1.branch)
 
185
                    revision_id = revision[0].in_history(branch).rev_id
200
186
                    tree2 = branch.repository.revision_tree(revision_id)
201
187
                elif len(revision) == 2:
202
 
                    revision_id_0 = revision[0].as_revision_id(branch)
 
188
                    revision_id_0 = revision[0].in_history(branch).rev_id
203
189
                    tree2 = branch.repository.revision_tree(revision_id_0)
204
 
                    revision_id_1 = revision[1].as_revision_id(branch)
 
190
                    revision_id_1 = revision[1].in_history(branch).rev_id
205
191
                    tree1 = branch.repository.revision_tree(revision_id_1)
206
192
            else:
207
193
                tree1 = wt
229
215
            wt.unlock()
230
216
 
231
217
 
232
 
def start_viz_window(branch, revisions, limit=None):
 
218
def start_viz_window(branch, revision, limit=None):
233
219
    """Start viz on branch with revision revision.
234
220
    
235
221
    :return: The viz window object.
236
222
    """
237
223
    from viz import BranchWindow
238
 
    return BranchWindow(branch, revisions, limit)
 
224
    return BranchWindow(branch, revision, limit)
239
225
 
240
226
 
241
227
class cmd_visualise(Command):
251
237
        "revision",
252
238
        Option('limit', "Maximum number of revisions to display.",
253
239
               int, 'count')]
254
 
    takes_args = [ "locations*" ]
 
240
    takes_args = [ "location?" ]
255
241
    aliases = [ "visualize", "vis", "viz" ]
256
242
 
257
 
    def run(self, locations_list, revision=None, limit=None):
 
243
    def run(self, location=".", revision=None, limit=None):
258
244
        set_ui_factory()
259
 
        if locations_list is None:
260
 
            locations_list = ["."]
261
 
        revids = []
262
 
        for location in locations_list:
263
 
            (br, path) = branch.Branch.open_containing(location)
264
 
            if revision is None:
265
 
                revids.append(br.last_revision())
266
 
            else:
267
 
                revids.append(revision[0].as_revision_id(br))
 
245
        (br, path) = branch.Branch.open_containing(location)
 
246
        if revision is None:
 
247
            revid = br.last_revision()
 
248
            if revid is None:
 
249
                return
 
250
        else:
 
251
            (revno, revid) = revision[0].in_history(br)
 
252
 
268
253
        import gtk
269
 
        pp = start_viz_window(br, revids, limit)
 
254
        pp = start_viz_window(br, revid, limit)
270
255
        pp.connect("destroy", lambda w: gtk.main_quit())
271
256
        pp.show()
272
257
        gtk.main()
289
274
    aliases = ["gblame", "gpraise"]
290
275
    
291
276
    def run(self, filename, all=False, plain=False, line='1', revision=None):
292
 
        gtk = open_display()
 
277
        gtk = self.open_display()
293
278
 
294
279
        try:
295
280
            line = int(line)
314
299
        if revision is not None:
315
300
            if len(revision) != 1:
316
301
                raise BzrCommandError("Only 1 revion may be specified.")
317
 
            revision_id = revision[0].as_revision_id(br)
 
302
            revision_id = revision[0].in_history(br).rev_id
318
303
            tree = br.repository.revision_tree(revision_id)
319
304
        else:
320
305
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
321
306
 
322
 
        window = GAnnotateWindow(all, plain, branch=br)
 
307
        window = GAnnotateWindow(all, plain)
323
308
        window.connect("destroy", lambda w: gtk.main_quit())
324
309
        config = GAnnotateConfig(window)
325
310
        window.show()
348
333
 
349
334
    def run(self, filename=None):
350
335
        import os
351
 
        open_display()
 
336
        self.open_display()
352
337
        from commit import CommitDialog
353
338
        from bzrlib.errors import (BzrCommandError,
354
339
                                   NotBranchError,
361
346
            br = wt.branch
362
347
        except NoWorkingTree, e:
363
348
            from dialog import error_dialog
364
 
            error_dialog(_i18n('Directory does not have a working tree'),
365
 
                         _i18n('Operation aborted.'))
 
349
            error_dialog(_('Directory does not have a working tree'),
 
350
                         _('Operation aborted.'))
366
351
            return 1 # should this be retval=3?
367
352
 
368
353
        # It is a good habit to keep things locked for the duration, but it
385
370
    
386
371
    aliases = [ "gst" ]
387
372
    takes_args = ['PATH?']
388
 
    takes_options = ['revision']
 
373
    takes_options = []
389
374
 
390
 
    def run(self, path='.', revision=None):
 
375
    def run(self, path='.'):
391
376
        import os
392
 
        gtk = open_display()
 
377
        gtk = self.open_display()
393
378
        from status import StatusDialog
394
379
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
395
 
        
396
 
        if revision is not None:
397
 
            try:
398
 
                revision_id = revision[0].as_revision_id(wt.branch)
399
 
            except:
400
 
                from bzrlib.errors import BzrError
401
 
                raise BzrError('Revision %r doesn\'t exist' % revision[0].user_spec )
402
 
        else:
403
 
            revision_id = None
404
 
 
405
 
        status = StatusDialog(wt, wt_path, revision_id)
 
380
        status = StatusDialog(wt, wt_path)
406
381
        status.connect("destroy", gtk.main_quit)
407
382
        status.run()
408
383
 
413
388
    """
414
389
    def run(self):
415
390
        (br, path) = branch.Branch.open_containing(".")
416
 
        gtk = open_display()
 
391
        gtk = self.open_display()
417
392
        from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
418
393
        from StringIO import StringIO
419
394
        dialog = SendMergeDirectiveDialog(br)
435
410
    """
436
411
    def run(self):
437
412
        (wt, path) = workingtree.WorkingTree.open_containing('.')
438
 
        open_display()
 
413
        self.open_display()
439
414
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
440
415
        dialog = ConflictsDialog(wt)
441
416
        dialog.run()
446
421
 
447
422
    """
448
423
    def run(self):
449
 
        open_display()
 
424
        self.open_display()
450
425
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
451
426
        dialog = PreferencesWindow()
452
427
        dialog.run()
453
428
 
454
429
 
455
 
class cmd_gmerge(Command):
456
 
    """ GTK+ merge dialog
457
 
    
458
 
    """
459
 
    takes_args = ["merge_from_path?"]
460
 
    def run(self, merge_from_path=None):
461
 
        from bzrlib import workingtree
462
 
        from bzrlib.plugins.gtk.dialog import error_dialog
463
 
        from bzrlib.plugins.gtk.merge import MergeDialog
464
 
        
465
 
        (wt, path) = workingtree.WorkingTree.open_containing('.')
466
 
        old_tree = wt.branch.repository.revision_tree(wt.branch.last_revision())
467
 
        delta = wt.changes_from(old_tree)
468
 
        if len(delta.added) or len(delta.removed) or len(delta.renamed) or len(delta.modified):
469
 
            error_dialog(_i18n('There are local changes in the branch'),
470
 
                         _i18n('Please commit or revert the changes before merging.'))
471
 
        else:
472
 
            parent_branch_path = wt.branch.get_parent()
473
 
            merge = MergeDialog(wt, path, parent_branch_path)
474
 
            response = merge.run()
475
 
            merge.destroy()
476
 
 
477
 
 
478
430
class cmd_gmissing(Command):
479
431
    """ GTK+ missing revisions dialog.
480
432
 
513
465
 
514
466
class cmd_ginit(GTKCommand):
515
467
    def run(self):
516
 
        open_display()
 
468
        self.open_display()
517
469
        from initialize import InitDialog
518
470
        dialog = InitDialog(os.path.abspath(os.path.curdir))
519
471
        dialog.run()
523
475
    def run(self):
524
476
        br = branch.Branch.open_containing('.')[0]
525
477
        
526
 
        gtk = open_display()
 
478
        gtk = self.open_display()
527
479
        from tags import TagsWindow
528
480
        window = TagsWindow(br)
529
481
        window.show()
538
490
    cmd_gconflicts, 
539
491
    cmd_gdiff,
540
492
    cmd_ginit,
541
 
    cmd_gmerge,
542
493
    cmd_gmissing, 
543
494
    cmd_gpreferences, 
544
495
    cmd_gpush, 
552
503
    register_command(cmd)
553
504
 
554
505
 
 
506
class cmd_commit_notify(GTKCommand):
 
507
    """Run the bzr commit notifier.
 
508
 
 
509
    This is a background program which will pop up a notification on the users
 
510
    screen when a commit occurs.
 
511
    """
 
512
 
 
513
    def run(self):
 
514
        from notify import NotifyPopupMenu
 
515
        gtk = self.open_display()
 
516
        menu = NotifyPopupMenu()
 
517
        icon = gtk.status_icon_new_from_file(os.path.join(data_path(), "bzr-icon-64.png"))
 
518
        icon.connect('popup-menu', menu.display)
 
519
 
 
520
        import cgi
 
521
        import dbus
 
522
        import dbus.service
 
523
        import pynotify
 
524
        from bzrlib.bzrdir import BzrDir
 
525
        from bzrlib import errors
 
526
        from bzrlib.osutils import format_date
 
527
        from bzrlib.transport import get_transport
 
528
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
 
529
            import dbus.glib
 
530
        from bzrlib.plugins.dbus import activity
 
531
        bus = dbus.SessionBus()
 
532
        # get the object so we can subscribe to callbacks from it.
 
533
        broadcast_service = bus.get_object(
 
534
            activity.Broadcast.DBUS_NAME,
 
535
            activity.Broadcast.DBUS_PATH)
 
536
 
 
537
        def catch_branch(revision_id, urls):
 
538
            # TODO: show all the urls, or perhaps choose the 'best'.
 
539
            url = urls[0]
 
540
            try:
 
541
                if isinstance(revision_id, unicode):
 
542
                    revision_id = revision_id.encode('utf8')
 
543
                transport = get_transport(url)
 
544
                a_dir = BzrDir.open_from_transport(transport)
 
545
                branch = a_dir.open_branch()
 
546
                revno = branch.revision_id_to_revno(revision_id)
 
547
                revision = branch.repository.get_revision(revision_id)
 
548
                summary = 'New revision %d in %s' % (revno, url)
 
549
                body  = 'Committer: %s\n' % revision.committer
 
550
                body += 'Date: %s\n' % format_date(revision.timestamp,
 
551
                    revision.timezone)
 
552
                body += '\n'
 
553
                body += revision.message
 
554
                body = cgi.escape(body)
 
555
                nw = pynotify.Notification(summary, body)
 
556
                def start_viz(notification=None, action=None, data=None):
 
557
                    """Start the viz program."""
 
558
                    pp = start_viz_window(branch, revision_id)
 
559
                    pp.show()
 
560
                def start_branch(notification=None, action=None, data=None):
 
561
                    """Start a Branch dialog"""
 
562
                    from bzrlib.plugins.gtk.branch import BranchDialog
 
563
                    bd = BranchDialog(remote_path=url)
 
564
                    bd.run()
 
565
                nw.add_action("inspect", "Inspect", start_viz, None)
 
566
                nw.add_action("branch", "Branch", start_branch, None)
 
567
                nw.set_timeout(5000)
 
568
                nw.show()
 
569
            except Exception, e:
 
570
                print e
 
571
                raise
 
572
        broadcast_service.connect_to_signal("Revision", catch_branch,
 
573
            dbus_interface=activity.Broadcast.DBUS_INTERFACE)
 
574
        pynotify.init("bzr commit-notify")
 
575
        gtk.main()
 
576
 
 
577
register_command(cmd_commit_notify)
 
578
 
 
579
 
555
580
class cmd_gselftest(GTKCommand):
556
581
    """Version of selftest that displays a notification at the end"""
557
582
 
648
673
register_command(cmd_test_gtk)
649
674
 
650
675
 
 
676
class cmd_ghandle_patch(GTKCommand):
 
677
    """Display a patch or merge directive, possibly merging.
 
678
 
 
679
    This is a helper, meant to be launched from other programs like browsers
 
680
    or email clients.  Since these programs often do not allow parameters to
 
681
    be provided, a "handle-patch" script is included.
 
682
    """
 
683
 
 
684
    takes_args = ['path']
 
685
 
 
686
    def run(self, path):
 
687
        try:
 
688
            from bzrlib.plugins.gtk.diff import (DiffWindow,
 
689
                                                 MergeDirectiveWindow)
 
690
            lines = open(path, 'rb').readlines()
 
691
            lines = [l.replace('\r\n', '\n') for l in lines]
 
692
            try:
 
693
                directive = merge_directive.MergeDirective.from_lines(lines)
 
694
            except errors.NotAMergeDirective:
 
695
                window = DiffWindow()
 
696
                window.set_diff_text(path, lines)
 
697
            else:
 
698
                window = MergeDirectiveWindow(directive, path)
 
699
                window.set_diff_text(path, directive.patch.splitlines(True))
 
700
            window.show()
 
701
            gtk = self.open_display()
 
702
            window.connect("destroy", gtk.main_quit)
 
703
        except Exception, e:
 
704
            from dialog import error_dialog
 
705
            error_dialog('Error', str(e))
 
706
            raise
 
707
        gtk.main()
 
708
 
 
709
 
 
710
register_command(cmd_ghandle_patch)
 
711
 
651
712
 
652
713
import gettext
653
714
gettext.install('olive-gtk')
654
715
 
655
 
# Let's create a specialized alias to protect '_' from being erased by other
656
 
# uses of '_' as an anonymous variable (think pdb for one).
657
 
_i18n = gettext.gettext
658
716
 
659
717
class NoDisplayError(BzrCommandError):
660
718
    """gtk could not find a proper display"""