/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: 2007-07-15 15:22:29 UTC
  • Revision ID: jelmer@samba.org-20070715152229-clmlen0vpd8d2pzx
Add docstrings, remove unused code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
#
1
3
# This program is free software; you can redistribute it and/or modify
2
4
# it under the terms of the GNU General Public License as published by
3
5
# the Free Software Foundation; either version 2 of the License, or
12
14
# along with this program; if not, write to the Free Software
13
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14
16
 
15
 
"""GTK+ frontends to Bazaar commands """
 
17
"""Graphical support for Bazaar using GTK.
 
18
 
 
19
This plugin includes:
 
20
commit-notify     Start the graphical notifier of commits.
 
21
gannotate         GTK+ annotate. 
 
22
gbranch           GTK+ branching. 
 
23
gcheckout         GTK+ checkout. 
 
24
gcommit           GTK+ commit dialog 
 
25
gconflicts        GTK+ push. 
 
26
gdiff             Show differences in working tree in a GTK+ Window. 
 
27
ginit             Initialise a new branch.
 
28
gmissing          GTK+ missing revisions dialog. 
 
29
gpreferences      GTK+ preferences dialog. 
 
30
gpush             GTK+ push. 
 
31
gstatus           GTK+ status dialog 
 
32
gtags             Manage branch tags.
 
33
visualise         Graphically visualise this branch. 
 
34
"""
16
35
 
17
36
import bzrlib
18
37
 
19
 
__version__ = '0.16.0'
 
38
__version__ = '0.18.0'
20
39
version_info = tuple(int(n) for n in __version__.split('.'))
21
40
 
22
41
 
30
49
    """
31
50
    desired_plus = (desired[0], desired[1]+1)
32
51
    bzrlib_version = bzrlib.version_info[:2]
33
 
    if bzrlib_version == desired:
 
52
    if bzrlib_version == desired or (bzrlib_version == desired_plus and
 
53
                                     bzrlib.version_info[3] == 'dev'):
34
54
        return
35
55
    try:
36
56
        from bzrlib.trace import warning
38
58
        # get the message out any way we can
39
59
        from warnings import warn as warning
40
60
    if bzrlib_version < desired:
 
61
        from bzrlib.errors import BzrError
41
62
        warning('Installed bzr version %s is too old to be used with bzr-gtk'
42
63
                ' %s.' % (bzrlib.__version__, __version__))
43
 
        # Not using BzrNewError, because it may not exist.
44
 
        raise Exception, ('Version mismatch', version_info)
 
64
        raise BzrError('Version mismatch: %r' % version_info)
45
65
    else:
46
66
        warning('bzr-gtk is not up to date with installed bzr version %s.'
47
67
                ' \nThere should be a newer version available, e.g. %i.%i.' 
48
68
                % (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
49
 
        if bzrlib_version != desired_plus:
50
 
            raise Exception, 'Version mismatch'
51
69
 
52
70
 
53
71
check_bzrlib_version(version_info[:2])
67
85
 
68
86
from bzrlib.commands import Command, register_command, display_command
69
87
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
70
 
from bzrlib.commands import Command, register_command
71
88
from bzrlib.option import Option
72
 
from bzrlib.bzrdir import BzrDir
73
89
 
74
90
import os.path
75
91
 
83
99
 
84
100
 
85
101
def set_ui_factory():
86
 
    pygtk = import_pygtk()
 
102
    import_pygtk()
87
103
    from ui import GtkUIFactory
88
104
    import bzrlib.ui
89
105
    bzrlib.ui.ui_factory = GtkUIFactory()
90
106
 
91
107
 
92
 
class cmd_gbranch(Command):
 
108
class GTKCommand(Command):
 
109
    """Abstract class providing GTK specific run commands."""
 
110
 
 
111
    def open_display(self):
 
112
        pygtk = import_pygtk()
 
113
        try:
 
114
            import gtk
 
115
        except RuntimeError, e:
 
116
            if str(e) == "could not open display":
 
117
                raise NoDisplayError
 
118
        set_ui_factory()
 
119
        return gtk
 
120
 
 
121
    def run(self):
 
122
        self.open_display()
 
123
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
 
124
        dialog.run()
 
125
 
 
126
 
 
127
class cmd_gbranch(GTKCommand):
93
128
    """GTK+ branching.
94
129
    
95
130
    """
96
131
 
97
 
    def run(self):
98
 
        pygtk = import_pygtk()
99
 
        try:
100
 
            import gtk
101
 
        except RuntimeError, e:
102
 
            if str(e) == "could not open display":
103
 
                raise NoDisplayError
104
 
 
 
132
    def get_gtk_dialog(self, path):
105
133
        from bzrlib.plugins.gtk.branch import BranchDialog
106
 
 
107
 
        set_ui_factory()
108
 
        dialog = BranchDialog(os.path.abspath('.'))
109
 
        dialog.run()
110
 
 
111
 
register_command(cmd_gbranch)
112
 
 
113
 
class cmd_gcheckout(Command):
 
134
        return BranchDialog(path)
 
135
 
 
136
 
 
137
class cmd_gcheckout(GTKCommand):
114
138
    """ GTK+ checkout.
115
139
    
116
140
    """
117
141
    
118
 
    def run(self):
119
 
        pygtk = import_pygtk()
120
 
        try:
121
 
            import gtk
122
 
        except RuntimeError, e:
123
 
            if str(e) == "could not open display":
124
 
                raise NoDisplayError
125
 
 
 
142
    def get_gtk_dialog(self, path):
126
143
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
127
 
 
128
 
        set_ui_factory()
129
 
        dialog = CheckoutDialog(os.path.abspath('.'))
130
 
        dialog.run()
131
 
 
132
 
register_command(cmd_gcheckout)
133
 
 
134
 
class cmd_gpush(Command):
 
144
        return CheckoutDialog(path)
 
145
 
 
146
 
 
147
 
 
148
class cmd_gpush(GTKCommand):
135
149
    """ GTK+ push.
136
150
    
137
151
    """
139
153
 
140
154
    def run(self, location="."):
141
155
        (br, path) = branch.Branch.open_containing(location)
142
 
 
143
 
        pygtk = import_pygtk()
144
 
        try:
145
 
            import gtk
146
 
        except RuntimeError, e:
147
 
            if str(e) == "could not open display":
148
 
                raise NoDisplayError
149
 
 
 
156
        self.open_display()
150
157
        from push import PushDialog
151
 
 
152
 
        set_ui_factory()
153
158
        dialog = PushDialog(br)
154
159
        dialog.run()
155
160
 
156
 
register_command(cmd_gpush)
157
 
 
158
 
class cmd_gdiff(Command):
 
161
 
 
162
 
 
163
class cmd_gdiff(GTKCommand):
159
164
    """Show differences in working tree in a GTK+ Window.
160
165
    
161
166
    Otherwise, all changes for the tree are listed.
194
199
                try:
195
200
                    window.set_file(tree_filename)
196
201
                except NoSuchFile:
197
 
                    if (tree1.inventory.path2id(tree_filename) is None and 
198
 
                        tree2.inventory.path2id(tree_filename) is None):
 
202
                    if (tree1.path2id(tree_filename) is None and 
 
203
                        tree2.path2id(tree_filename) is None):
199
204
                        raise NotVersionedError(filename)
200
205
                    raise BzrCommandError('No changes found for file "%s"' % 
201
206
                                          filename)
205
210
        finally:
206
211
            wt.unlock()
207
212
 
208
 
register_command(cmd_gdiff)
 
213
 
 
214
def start_viz_window(branch, revision, limit=None):
 
215
    """Start viz on branch with revision revision.
 
216
    
 
217
    :return: The viz window object.
 
218
    """
 
219
    from viz.branchwin import BranchWindow
 
220
    branch.lock_read()
 
221
    pp = BranchWindow()
 
222
    pp.set_branch(branch, revision, limit)
 
223
    # cleanup locks when the window is closed
 
224
    pp.connect("destroy", lambda w: branch.unlock())
 
225
    return pp
 
226
 
209
227
 
210
228
class cmd_visualise(Command):
211
229
    """Graphically visualise this branch.
218
236
    """
219
237
    takes_options = [
220
238
        "revision",
221
 
        Option('limit', "maximum number of revisions to display",
 
239
        Option('limit', "Maximum number of revisions to display.",
222
240
               int, 'count')]
223
241
    takes_args = [ "location?" ]
224
242
    aliases = [ "visualize", "vis", "viz" ]
227
245
        set_ui_factory()
228
246
        (br, path) = branch.Branch.open_containing(location)
229
247
        br.lock_read()
230
 
        br.repository.lock_read()
231
248
        try:
232
249
            if revision is None:
233
250
                revid = br.last_revision()
236
253
            else:
237
254
                (revno, revid) = revision[0].in_history(br)
238
255
 
239
 
            from viz.branchwin import BranchWindow
240
256
            import gtk
241
 
                
242
 
            pp = BranchWindow()
243
 
            pp.set_branch(br, revid, limit)
 
257
            pp = start_viz_window(br, revid, limit)
244
258
            pp.connect("destroy", lambda w: gtk.main_quit())
245
259
            pp.show()
246
260
            gtk.main()
247
261
        finally:
248
 
            br.repository.unlock()
249
262
            br.unlock()
250
263
 
251
264
 
252
 
register_command(cmd_visualise)
253
 
 
254
 
class cmd_gannotate(Command):
 
265
class cmd_gannotate(GTKCommand):
255
266
    """GTK+ annotate.
256
267
    
257
268
    Browse changes to FILENAME line by line in a GTK+ window.
259
270
 
260
271
    takes_args = ["filename", "line?"]
261
272
    takes_options = [
262
 
        Option("all", help="show annotations on all lines"),
263
 
        Option("plain", help="don't highlight annotation lines"),
 
273
        Option("all", help="Show annotations on all lines."),
 
274
        Option("plain", help="Don't highlight annotation lines."),
264
275
        Option("line", type=int, argname="lineno",
265
 
               help="jump to specified line number"),
 
276
               help="Jump to specified line number."),
266
277
        "revision",
267
278
    ]
268
279
    aliases = ["gblame", "gpraise"]
269
280
    
270
281
    def run(self, filename, all=False, plain=False, line='1', revision=None):
271
 
        pygtk = import_pygtk()
272
 
 
273
 
        try:
274
 
            import gtk
275
 
        except RuntimeError, e:
276
 
            if str(e) == "could not open display":
277
 
                raise NoDisplayError
278
 
        set_ui_factory()
 
282
        gtk = self.open_display()
279
283
 
280
284
        try:
281
285
            line = int(line)
285
289
 
286
290
        from annotate.gannotate import GAnnotateWindow
287
291
        from annotate.config import GAnnotateConfig
 
292
        from bzrlib.bzrdir import BzrDir
288
293
 
289
294
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
290
295
        if wt is not None:
321
326
            if wt is not None:
322
327
                wt.unlock()
323
328
 
324
 
register_command(cmd_gannotate)
325
 
 
326
 
class cmd_gcommit(Command):
 
329
 
 
330
 
 
331
class cmd_gcommit(GTKCommand):
327
332
    """GTK+ commit dialog
328
333
 
329
334
    Graphical user interface for committing revisions"""
334
339
 
335
340
    def run(self, filename=None):
336
341
        import os
337
 
        pygtk = import_pygtk()
338
 
 
339
 
        try:
340
 
            import gtk
341
 
        except RuntimeError, e:
342
 
            if str(e) == "could not open display":
343
 
                raise NoDisplayError
344
 
 
345
 
        set_ui_factory()
 
342
        self.open_display()
346
343
        from commit import CommitDialog
347
 
        from bzrlib.commit import Commit
348
344
        from bzrlib.errors import (BzrCommandError,
349
345
                                   NotBranchError,
350
 
                                   NoWorkingTree,
351
 
                                   PointlessCommit,
352
 
                                   ConflictsInTree,
353
 
                                   StrictCommitFailed)
 
346
                                   NoWorkingTree)
354
347
 
355
348
        wt = None
356
349
        br = None
357
350
        try:
358
351
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
359
352
            br = wt.branch
360
 
        except NotBranchError, e:
361
 
            path = e.path
362
353
        except NoWorkingTree, e:
363
354
            path = e.base
364
 
            try:
365
 
                (br, path) = branch.Branch.open_containing(path)
366
 
            except NotBranchError, e:
367
 
                path = e.path
368
 
 
 
355
            (br, path) = branch.Branch.open_containing(path)
369
356
 
370
357
        commit = CommitDialog(wt, path, not br)
371
358
        commit.run()
372
359
 
373
 
register_command(cmd_gcommit)
374
 
 
375
 
class cmd_gstatus(Command):
 
360
 
 
361
 
 
362
class cmd_gstatus(GTKCommand):
376
363
    """GTK+ status dialog
377
364
 
378
365
    Graphical user interface for showing status 
384
371
 
385
372
    def run(self, path='.'):
386
373
        import os
387
 
        pygtk = import_pygtk()
388
 
 
389
 
        try:
390
 
            import gtk
391
 
        except RuntimeError, e:
392
 
            if str(e) == "could not open display":
393
 
                raise NoDisplayError
394
 
 
395
 
        set_ui_factory()
 
374
        gtk = self.open_display()
396
375
        from status import StatusDialog
397
376
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
398
377
        status = StatusDialog(wt, wt_path)
399
378
        status.connect("destroy", gtk.main_quit)
400
379
        status.run()
401
380
 
402
 
register_command(cmd_gstatus)
403
 
 
404
 
class cmd_gconflicts(Command):
 
381
 
 
382
 
 
383
class cmd_gconflicts(GTKCommand):
405
384
    """ GTK+ push.
406
385
    
407
386
    """
408
387
    def run(self):
409
388
        (wt, path) = workingtree.WorkingTree.open_containing('.')
410
 
        
411
 
        pygtk = import_pygtk()
412
 
        try:
413
 
            import gtk
414
 
        except RuntimeError, e:
415
 
            if str(e) == "could not open display":
416
 
                raise NoDisplayError
417
 
 
 
389
        self.open_display()
418
390
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
419
 
 
420
 
        set_ui_factory()
421
391
        dialog = ConflictsDialog(wt)
422
392
        dialog.run()
423
393
 
424
 
register_command(cmd_gconflicts)
425
 
 
426
 
class cmd_gpreferences(Command):
 
394
 
 
395
 
 
396
class cmd_gpreferences(GTKCommand):
427
397
    """ GTK+ preferences dialog.
428
398
 
429
399
    """
430
400
    def run(self):
431
 
        pygtk = import_pygtk()
432
 
        try:
433
 
            import gtk
434
 
        except RuntimeError, e:
435
 
            if str(e) == "could not open display":
436
 
                raise NoDisplayError
437
 
 
 
401
        self.open_display()
438
402
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
439
 
 
440
 
        set_ui_factory()
441
403
        dialog = PreferencesWindow()
442
404
        dialog.run()
443
405
 
444
 
register_command(cmd_gpreferences)
 
406
 
 
407
 
 
408
class cmd_gmissing(Command):
 
409
    """ GTK+ missing revisions dialog.
 
410
 
 
411
    """
 
412
    takes_args = ["other_branch?"]
 
413
    def run(self, other_branch=None):
 
414
        pygtk = import_pygtk()
 
415
        try:
 
416
            import gtk
 
417
        except RuntimeError, e:
 
418
            if str(e) == "could not open display":
 
419
                raise NoDisplayError
 
420
 
 
421
        from bzrlib.plugins.gtk.missing import MissingWindow
 
422
        from bzrlib.branch import Branch
 
423
 
 
424
        local_branch = Branch.open_containing(".")[0]
 
425
        if other_branch is None:
 
426
            other_branch = local_branch.get_parent()
 
427
            
 
428
            if other_branch is None:
 
429
                raise errors.BzrCommandError("No peer location known or specified.")
 
430
        remote_branch = Branch.open_containing(other_branch)[0]
 
431
        set_ui_factory()
 
432
        local_branch.lock_read()
 
433
        try:
 
434
            remote_branch.lock_read()
 
435
            try:
 
436
                dialog = MissingWindow(local_branch, remote_branch)
 
437
                dialog.run()
 
438
            finally:
 
439
                remote_branch.unlock()
 
440
        finally:
 
441
            local_branch.unlock()
 
442
 
 
443
 
 
444
class cmd_ginit(GTKCommand):
 
445
    def run(self):
 
446
        self.open_display()
 
447
        from initialize import InitDialog
 
448
        dialog = InitDialog(os.path.abspath(os.path.curdir))
 
449
        dialog.run()
 
450
 
 
451
 
 
452
class cmd_gtags(GTKCommand):
 
453
    def run(self):
 
454
        br = branch.Branch.open_containing('.')[0]
 
455
        
 
456
        gtk = self.open_display()
 
457
        from tags import TagsWindow
 
458
        window = TagsWindow(br)
 
459
        window.show()
 
460
        gtk.main()
 
461
 
 
462
 
 
463
commands = [
 
464
    cmd_gmissing, 
 
465
    cmd_gpreferences, 
 
466
    cmd_gconflicts, 
 
467
    cmd_gstatus,
 
468
    cmd_gcommit, 
 
469
    cmd_gannotate, 
 
470
    cmd_visualise, 
 
471
    cmd_gdiff,
 
472
    cmd_gpush, 
 
473
    cmd_gcheckout, 
 
474
    cmd_gbranch,
 
475
    cmd_ginit,
 
476
    cmd_gtags
 
477
    ]
 
478
 
 
479
for cmd in commands:
 
480
    register_command(cmd)
 
481
 
 
482
 
 
483
class cmd_commit_notify(GTKCommand):
 
484
    """Run the bzr commit notifier.
 
485
 
 
486
    This is a background program which will pop up a notification on the users
 
487
    screen when a commit occurs.
 
488
    """
 
489
 
 
490
    def run(self):
 
491
        from notify import NotifyPopupMenu
 
492
        gtk = self.open_display()
 
493
        menu = NotifyPopupMenu()
 
494
        icon = gtk.status_icon_new_from_file("bzr-icon-64.png")
 
495
        icon.connect('popup-menu', menu.display)
 
496
 
 
497
        import cgi
 
498
        import dbus
 
499
        import dbus.service
 
500
        import pynotify
 
501
        from bzrlib.bzrdir import BzrDir
 
502
        from bzrlib import errors
 
503
        from bzrlib.osutils import format_date
 
504
        from bzrlib.transport import get_transport
 
505
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
 
506
            import dbus.glib
 
507
        from bzrlib.plugins.dbus import activity
 
508
        bus = dbus.SessionBus()
 
509
        # get the object so we can subscribe to callbacks from it.
 
510
        broadcast_service = bus.get_object(
 
511
            activity.Broadcast.DBUS_NAME,
 
512
            activity.Broadcast.DBUS_PATH)
 
513
 
 
514
        def catch_branch(revision_id, urls):
 
515
            # TODO: show all the urls, or perhaps choose the 'best'.
 
516
            url = urls[0]
 
517
            try:
 
518
                if isinstance(revision_id, unicode):
 
519
                    revision_id = revision_id.encode('utf8')
 
520
                transport = get_transport(url)
 
521
                a_dir = BzrDir.open_from_transport(transport)
 
522
                branch = a_dir.open_branch()
 
523
                revno = branch.revision_id_to_revno(revision_id)
 
524
                revision = branch.repository.get_revision(revision_id)
 
525
                summary = 'New revision %d in %s' % (revno, url)
 
526
                body  = 'Committer: %s\n' % revision.committer
 
527
                body += 'Date: %s\n' % format_date(revision.timestamp,
 
528
                    revision.timezone)
 
529
                body += '\n'
 
530
                body += revision.message
 
531
                body = cgi.escape(body)
 
532
                nw = pynotify.Notification(summary, body)
 
533
                def start_viz(notification=None, action=None, data=None):
 
534
                    """Start the viz program."""
 
535
                    pp = start_viz_window(branch, revision_id)
 
536
                    pp.show()
 
537
                def start_branch(notification=None, action=None, data=None):
 
538
                    """Start a Branch dialog"""
 
539
                    from bzrlib.plugins.gtk.branch import BranchDialog
 
540
                    bd = BranchDialog(remote_path=url)
 
541
                    bd.run()
 
542
                nw.add_action("inspect", "Inspect", start_viz, None)
 
543
                nw.add_action("branch", "Branch", start_branch, None)
 
544
                nw.set_timeout(5000)
 
545
                nw.show()
 
546
            except Exception, e:
 
547
                print e
 
548
                raise
 
549
        broadcast_service.connect_to_signal("Revision", catch_branch,
 
550
            dbus_interface=activity.Broadcast.DBUS_INTERFACE)
 
551
        pynotify.init("bzr commit-notify")
 
552
        gtk.main()
 
553
 
 
554
register_command(cmd_commit_notify)
 
555
 
445
556
 
446
557
import gettext
447
558
gettext.install('olive-gtk')
448
559
 
 
560
 
449
561
class NoDisplayError(BzrCommandError):
450
562
    """gtk could not find a proper display"""
451
563
 
452
564
    def __str__(self):
453
565
        return "No DISPLAY. Unable to run GTK+ application."
454
566
 
 
567
 
455
568
def test_suite():
456
569
    from unittest import TestSuite
457
570
    import tests