12
12
# along with this program; if not, write to the Free Software
13
13
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
"""Graphical support for Bazaar using GTK.
18
commit-notify Start the graphical notifier of commits.
19
gannotate GTK+ annotate.
20
gbranch GTK+ branching.
21
gcheckout GTK+ checkout.
22
gcommit GTK+ commit dialog
23
gconflicts GTK+ conflicts.
24
gdiff Show differences in working tree in a GTK+ Window.
25
ginit Initialise a new branch.
26
gmissing GTK+ missing revisions dialog.
27
gpreferences GTK+ preferences dialog.
29
gstatus GTK+ status dialog
30
gtags Manage branch tags.
31
visualise Graphically visualise this branch.
15
"""GTK+ frontends to Bazaar commands """
36
version_info = (0, 92, 0, 'dev', 0)
19
__version__ = '0.16.0'
20
version_info = tuple(int(n) for n in __version__.split('.'))
38
if version_info[3] == 'final':
39
version_string = '%d.%d.%d' % version_info[:3]
41
version_string = '%d.%d.%d%s%d' % version_info
42
__version__ = version_string
44
23
def check_bzrlib_version(desired):
45
24
"""Check that bzrlib is compatible.
60
38
# get the message out any way we can
61
39
from warnings import warn as warning
62
40
if bzrlib_version < desired:
63
from bzrlib.errors import BzrError
64
warning('Installed Bazaar version %s is too old to be used with bzr-gtk'
41
warning('Installed bzr version %s is too old to be used with bzr-gtk'
65
42
' %s.' % (bzrlib.__version__, __version__))
66
raise BzrError('Version mismatch: %r, %r' % (version_info, bzrlib.version_info) )
43
# Not using BzrNewError, because it may not exist.
44
raise Exception, ('Version mismatch', version_info)
68
46
warning('bzr-gtk is not up to date with installed bzr version %s.'
69
47
' \nThere should be a newer version available, e.g. %i.%i.'
70
48
% (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
73
if version_info[2] == "final":
74
check_bzrlib_version(version_info[:2])
49
if bzrlib_version != desired_plus:
50
raise Exception, 'Version mismatch'
53
check_bzrlib_version(version_info[:2])
76
55
from bzrlib.trace import warning
77
56
if __name__ != 'bzrlib.plugins.gtk':
105
85
def set_ui_factory():
86
pygtk = import_pygtk()
107
87
from ui import GtkUIFactory
109
89
bzrlib.ui.ui_factory = GtkUIFactory()
113
return os.path.dirname(__file__)
116
class GTKCommand(Command):
117
"""Abstract class providing GTK specific run commands."""
119
def open_display(self):
120
pygtk = import_pygtk()
123
except RuntimeError, e:
124
if str(e) == "could not open display":
131
dialog = self.get_gtk_dialog(os.path.abspath('.'))
135
class cmd_gbranch(GTKCommand):
92
class cmd_gbranch(Command):
136
93
"""GTK+ branching.
140
def get_gtk_dialog(self, path):
98
pygtk = import_pygtk()
101
except RuntimeError, e:
102
if str(e) == "could not open display":
141
105
from bzrlib.plugins.gtk.branch import BranchDialog
142
return BranchDialog(path)
145
class cmd_gcheckout(GTKCommand):
108
dialog = BranchDialog(os.path.abspath('.'))
111
register_command(cmd_gbranch)
113
class cmd_gcheckout(Command):
146
114
""" GTK+ checkout.
150
def get_gtk_dialog(self, path):
119
pygtk = import_pygtk()
122
except RuntimeError, e:
123
if str(e) == "could not open display":
151
126
from bzrlib.plugins.gtk.checkout import CheckoutDialog
152
return CheckoutDialog(path)
156
class cmd_gpush(GTKCommand):
129
dialog = CheckoutDialog(os.path.abspath('.'))
132
register_command(cmd_gcheckout)
134
class cmd_gpush(Command):
375
385
def run(self, path='.'):
377
gtk = self.open_display()
387
pygtk = import_pygtk()
391
except RuntimeError, e:
392
if str(e) == "could not open display":
378
396
from status import StatusDialog
379
397
(wt, wt_path) = workingtree.WorkingTree.open_containing(path)
380
398
status = StatusDialog(wt, wt_path)
381
399
status.connect("destroy", gtk.main_quit)
386
class cmd_gconflicts(GTKCommand):
402
register_command(cmd_gstatus)
404
class cmd_gconflicts(Command):
389
Select files from the list of conflicts and run an external utility to
393
409
(wt, path) = workingtree.WorkingTree.open_containing('.')
411
pygtk = import_pygtk()
414
except RuntimeError, e:
415
if str(e) == "could not open display":
395
418
from bzrlib.plugins.gtk.conflicts import ConflictsDialog
396
421
dialog = ConflictsDialog(wt)
401
class cmd_gpreferences(GTKCommand):
402
""" GTK+ preferences dialog.
407
from bzrlib.plugins.gtk.preferences import PreferencesWindow
408
dialog = PreferencesWindow()
413
class cmd_gmissing(Command):
414
""" GTK+ missing revisions dialog.
417
takes_args = ["other_branch?"]
418
def run(self, other_branch=None):
419
pygtk = import_pygtk()
422
except RuntimeError, e:
423
if str(e) == "could not open display":
426
from bzrlib.plugins.gtk.missing import MissingWindow
427
from bzrlib.branch import Branch
429
local_branch = Branch.open_containing(".")[0]
430
if other_branch is None:
431
other_branch = local_branch.get_parent()
433
if other_branch is None:
434
raise errors.BzrCommandError("No peer location known or specified.")
435
remote_branch = Branch.open_containing(other_branch)[0]
437
local_branch.lock_read()
439
remote_branch.lock_read()
441
dialog = MissingWindow(local_branch, remote_branch)
444
remote_branch.unlock()
446
local_branch.unlock()
449
class cmd_ginit(GTKCommand):
452
from initialize import InitDialog
453
dialog = InitDialog(os.path.abspath(os.path.curdir))
457
class cmd_gtags(GTKCommand):
459
br = branch.Branch.open_containing('.')[0]
461
gtk = self.open_display()
462
from tags import TagsWindow
463
window = TagsWindow(br)
485
register_command(cmd)
488
class cmd_commit_notify(GTKCommand):
489
"""Run the bzr commit notifier.
491
This is a background program which will pop up a notification on the users
492
screen when a commit occurs.
496
from notify import NotifyPopupMenu
497
gtk = self.open_display()
498
menu = NotifyPopupMenu()
499
icon = gtk.status_icon_new_from_file(os.path.join(data_path(), "bzr-icon-64.png"))
500
icon.connect('popup-menu', menu.display)
506
from bzrlib.bzrdir import BzrDir
507
from bzrlib import errors
508
from bzrlib.osutils import format_date
509
from bzrlib.transport import get_transport
510
if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
512
from bzrlib.plugins.dbus import activity
513
bus = dbus.SessionBus()
514
# get the object so we can subscribe to callbacks from it.
515
broadcast_service = bus.get_object(
516
activity.Broadcast.DBUS_NAME,
517
activity.Broadcast.DBUS_PATH)
519
def catch_branch(revision_id, urls):
520
# TODO: show all the urls, or perhaps choose the 'best'.
523
if isinstance(revision_id, unicode):
524
revision_id = revision_id.encode('utf8')
525
transport = get_transport(url)
526
a_dir = BzrDir.open_from_transport(transport)
527
branch = a_dir.open_branch()
528
revno = branch.revision_id_to_revno(revision_id)
529
revision = branch.repository.get_revision(revision_id)
530
summary = 'New revision %d in %s' % (revno, url)
531
body = 'Committer: %s\n' % revision.committer
532
body += 'Date: %s\n' % format_date(revision.timestamp,
535
body += revision.message
536
body = cgi.escape(body)
537
nw = pynotify.Notification(summary, body)
538
def start_viz(notification=None, action=None, data=None):
539
"""Start the viz program."""
540
pp = start_viz_window(branch, revision_id)
542
def start_branch(notification=None, action=None, data=None):
543
"""Start a Branch dialog"""
544
from bzrlib.plugins.gtk.branch import BranchDialog
545
bd = BranchDialog(remote_path=url)
547
nw.add_action("inspect", "Inspect", start_viz, None)
548
nw.add_action("branch", "Branch", start_branch, None)
554
broadcast_service.connect_to_signal("Revision", catch_branch,
555
dbus_interface=activity.Broadcast.DBUS_INTERFACE)
556
pynotify.init("bzr commit-notify")
559
register_command(cmd_commit_notify)
562
class cmd_gselftest(GTKCommand):
563
"""Version of selftest that displays a notification at the end"""
565
takes_args = builtins.cmd_selftest.takes_args
566
takes_options = builtins.cmd_selftest.takes_options
567
_see_also = ['selftest']
569
def run(self, *args, **kwargs):
572
default_encoding = sys.getdefaultencoding()
573
# prevent gtk from blowing up later
575
# prevent gtk from messing with default encoding
577
if sys.getdefaultencoding() != default_encoding:
579
sys.setdefaultencoding(default_encoding)
580
result = builtins.cmd_selftest().run(*args, **kwargs)
583
body = 'Selftest succeeded in "%s"' % os.getcwd()
586
body = 'Selftest failed in "%s"' % os.getcwd()
587
pynotify.init("bzr gselftest")
588
note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
589
note.set_timeout(pynotify.EXPIRES_NEVER)
593
register_command(cmd_gselftest)
424
register_command(cmd_gconflicts)
597
427
gettext.install('olive-gtk')
600
429
class NoDisplayError(BzrCommandError):
601
430
"""gtk could not find a proper display"""
603
432
def __str__(self):
604
433
return "No DISPLAY. Unable to run GTK+ application."
607
435
def test_suite():
608
436
from unittest import TestSuite