/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: Jasper Groenewegen
  • Date: 2008-07-27 12:01:40 UTC
  • mfrom: (576.3.2 improve-merge)
  • mto: This revision was merged to the branch mainline in revision 579.
  • Revision ID: colbrac@xs4all.nl-20080727120140-1agdlzkc9fumjk5f
Merge merge dialog improvements

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.
19
18
gannotate         GTK+ annotate. 
20
19
gbranch           GTK+ branching. 
21
20
gcheckout         GTK+ checkout. 
22
21
gcommit           GTK+ commit dialog.
23
22
gconflicts        GTK+ conflicts. 
24
23
gdiff             Show differences in working tree in a GTK+ Window. 
25
 
ghandle-patch     Display and optionally merge a merge directive or patch.
26
24
ginit             Initialise a new branch.
 
25
gmerge            GTK+ merge dialog
27
26
gmissing          GTK+ missing revisions dialog. 
28
27
gpreferences      GTK+ preferences dialog. 
29
28
gpush             GTK+ push.
37
36
 
38
37
import bzrlib
39
38
 
40
 
version_info = (0, 94, 0, 'dev', 0)
 
39
version_info = (0, 95, 0, 'dev', 1)
41
40
 
42
41
if version_info[3] == 'final':
43
42
    version_string = '%d.%d.%d' % version_info[:3]
45
44
    version_string = '%d.%d.%d%s%d' % version_info
46
45
__version__ = version_string
47
46
 
48
 
required_bzrlib = (1, 0)
 
47
required_bzrlib = (1, 3)
49
48
 
50
49
def check_bzrlib_version(desired):
51
50
    """Check that bzrlib is compatible.
105
104
    bzrlib.ui.ui_factory = GtkUIFactory()
106
105
 
107
106
 
108
 
def data_path():
109
 
    return os.path.dirname(__file__)
110
 
 
 
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
 
111
135
 
112
136
class GTKCommand(Command):
113
137
    """Abstract class providing GTK specific run commands."""
114
138
 
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
 
 
125
139
    def run(self):
126
 
        self.open_display()
 
140
        open_display()
127
141
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
128
142
        dialog.run()
129
143
 
157
171
 
158
172
    def run(self, location="."):
159
173
        (br, path) = branch.Branch.open_containing(location)
160
 
        self.open_display()
 
174
        open_display()
161
175
        from push import PushDialog
162
176
        dialog = PushDialog(br.repository, br.last_revision(), br)
163
177
        dialog.run()
182
196
            if revision is not None:
183
197
                if len(revision) == 1:
184
198
                    tree1 = wt
185
 
                    revision_id = revision[0].in_history(branch).rev_id
 
199
                    revision_id = revision[0].as_revision_id(tree1.branch)
186
200
                    tree2 = branch.repository.revision_tree(revision_id)
187
201
                elif len(revision) == 2:
188
 
                    revision_id_0 = revision[0].in_history(branch).rev_id
 
202
                    revision_id_0 = revision[0].as_revision_id(branch)
189
203
                    tree2 = branch.repository.revision_tree(revision_id_0)
190
 
                    revision_id_1 = revision[1].in_history(branch).rev_id
 
204
                    revision_id_1 = revision[1].as_revision_id(branch)
191
205
                    tree1 = branch.repository.revision_tree(revision_id_1)
192
206
            else:
193
207
                tree1 = wt
215
229
            wt.unlock()
216
230
 
217
231
 
218
 
def start_viz_window(branch, revision, limit=None):
 
232
def start_viz_window(branch, revisions, limit=None):
219
233
    """Start viz on branch with revision revision.
220
234
    
221
235
    :return: The viz window object.
222
236
    """
223
237
    from viz import BranchWindow
224
 
    return BranchWindow(branch, revision, limit)
 
238
    return BranchWindow(branch, revisions, limit)
225
239
 
226
240
 
227
241
class cmd_visualise(Command):
237
251
        "revision",
238
252
        Option('limit', "Maximum number of revisions to display.",
239
253
               int, 'count')]
240
 
    takes_args = [ "location?" ]
 
254
    takes_args = [ "locations*" ]
241
255
    aliases = [ "visualize", "vis", "viz" ]
242
256
 
243
 
    def run(self, location=".", revision=None, limit=None):
 
257
    def run(self, locations_list, revision=None, limit=None):
244
258
        set_ui_factory()
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
 
 
 
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))
253
268
        import gtk
254
 
        pp = start_viz_window(br, revid, limit)
 
269
        pp = start_viz_window(br, revids, limit)
255
270
        pp.connect("destroy", lambda w: gtk.main_quit())
256
271
        pp.show()
257
272
        gtk.main()
274
289
    aliases = ["gblame", "gpraise"]
275
290
    
276
291
    def run(self, filename, all=False, plain=False, line='1', revision=None):
277
 
        gtk = self.open_display()
 
292
        gtk = open_display()
278
293
 
279
294
        try:
280
295
            line = int(line)
299
314
        if revision is not None:
300
315
            if len(revision) != 1:
301
316
                raise BzrCommandError("Only 1 revion may be specified.")
302
 
            revision_id = revision[0].in_history(br).rev_id
 
317
            revision_id = revision[0].as_revision_id(br)
303
318
            tree = br.repository.revision_tree(revision_id)
304
319
        else:
305
320
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
306
321
 
307
 
        window = GAnnotateWindow(all, plain)
 
322
        window = GAnnotateWindow(all, plain, branch=br)
308
323
        window.connect("destroy", lambda w: gtk.main_quit())
309
324
        config = GAnnotateConfig(window)
310
325
        window.show()
333
348
 
334
349
    def run(self, filename=None):
335
350
        import os
336
 
        self.open_display()
 
351
        open_display()
337
352
        from commit import CommitDialog
338
353
        from bzrlib.errors import (BzrCommandError,
339
354
                                   NotBranchError,
346
361
            br = wt.branch
347
362
        except NoWorkingTree, e:
348
363
            from dialog import error_dialog
349
 
            error_dialog(_('Directory does not have a working tree'),
350
 
                         _('Operation aborted.'))
 
364
            error_dialog(_i18n('Directory does not have a working tree'),
 
365
                         _i18n('Operation aborted.'))
351
366
            return 1 # should this be retval=3?
352
367
 
353
368
        # It is a good habit to keep things locked for the duration, but it
370
385
    
371
386
    aliases = [ "gst" ]
372
387
    takes_args = ['PATH?']
373
 
    takes_options = []
 
388
    takes_options = ['revision']
374
389
 
375
 
    def run(self, path='.'):
 
390
    def run(self, path='.', revision=None):
376
391
        import os
377
 
        gtk = self.open_display()
 
392
        gtk = open_display()
378
393
        from status import StatusDialog
379
394
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
380
 
        status = StatusDialog(wt, wt_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)
381
406
        status.connect("destroy", gtk.main_quit)
382
407
        status.run()
383
408
 
388
413
    """
389
414
    def run(self):
390
415
        (br, path) = branch.Branch.open_containing(".")
391
 
        gtk = self.open_display()
 
416
        gtk = open_display()
392
417
        from bzrlib.plugins.gtk.mergedirective import SendMergeDirectiveDialog
393
418
        from StringIO import StringIO
394
419
        dialog = SendMergeDirectiveDialog(br)
410
435
    """
411
436
    def run(self):
412
437
        (wt, path) = workingtree.WorkingTree.open_containing('.')
413
 
        self.open_display()
 
438
        open_display()
414
439
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
415
440
        dialog = ConflictsDialog(wt)
416
441
        dialog.run()
421
446
 
422
447
    """
423
448
    def run(self):
424
 
        self.open_display()
 
449
        open_display()
425
450
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
426
451
        dialog = PreferencesWindow()
427
452
        dialog.run()
428
453
 
429
454
 
 
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
 
430
478
class cmd_gmissing(Command):
431
479
    """ GTK+ missing revisions dialog.
432
480
 
465
513
 
466
514
class cmd_ginit(GTKCommand):
467
515
    def run(self):
468
 
        self.open_display()
 
516
        open_display()
469
517
        from initialize import InitDialog
470
518
        dialog = InitDialog(os.path.abspath(os.path.curdir))
471
519
        dialog.run()
475
523
    def run(self):
476
524
        br = branch.Branch.open_containing('.')[0]
477
525
        
478
 
        gtk = self.open_display()
 
526
        gtk = open_display()
479
527
        from tags import TagsWindow
480
528
        window = TagsWindow(br)
481
529
        window.show()
490
538
    cmd_gconflicts, 
491
539
    cmd_gdiff,
492
540
    cmd_ginit,
 
541
    cmd_gmerge,
493
542
    cmd_gmissing, 
494
543
    cmd_gpreferences, 
495
544
    cmd_gpush, 
503
552
    register_command(cmd)
504
553
 
505
554
 
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
 
 
580
555
class cmd_gselftest(GTKCommand):
581
556
    """Version of selftest that displays a notification at the end"""
582
557
 
673
648
register_command(cmd_test_gtk)
674
649
 
675
650
 
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
 
 
712
651
 
713
652
import gettext
714
653
gettext.install('olive-gtk')
715
654
 
 
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
716
658
 
717
659
class NoDisplayError(BzrCommandError):
718
660
    """gtk could not find a proper display"""