/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
210 by Jelmer Vernooij
Add notification area icon for commit-notify.
1
#
2
#
49 by Jelmer Vernooij
Merge in Dan Loda's gannotate plugin and put it in annotate/
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
208.2.1 by Robert Collins
Better module docstring.
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
"""
73 by Jelmer Vernooij
Release 0.9, list myself as maintainer.
35
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
36
import bzrlib
37
210 by Jelmer Vernooij
Add notification area icon for commit-notify.
38
__version__ = '0.18.0'
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
39
version_info = tuple(int(n) for n in __version__.split('.'))
40
41
42
def check_bzrlib_version(desired):
43
    """Check that bzrlib is compatible.
44
45
    If version is < bzr-gtk version, assume incompatible.
46
    If version == bzr-gtk version, assume completely compatible
47
    If version == bzr-gtk version + 1, assume compatible, with deprecations
48
    Otherwise, assume incompatible.
49
    """
50
    desired_plus = (desired[0], desired[1]+1)
51
    bzrlib_version = bzrlib.version_info[:2]
203 by Aaron Bentley
Don't warn if bzrlib is dev version of next release
52
    if bzrlib_version == desired or (bzrlib_version == desired_plus and
53
                                     bzrlib.version_info[3] == 'dev'):
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
54
        return
55
    try:
56
        from bzrlib.trace import warning
57
    except ImportError:
58
        # get the message out any way we can
59
        from warnings import warn as warning
60
    if bzrlib_version < desired:
207 by Aaron Bentley
Import BzrError before using it
61
        from bzrlib.errors import BzrError
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
62
        warning('Installed bzr version %s is too old to be used with bzr-gtk'
63
                ' %s.' % (bzrlib.__version__, __version__))
199 by Jelmer Vernooij
Merge upstream.
64
        raise BzrError('Version mismatch: %r' % version_info)
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
65
    else:
66
        warning('bzr-gtk is not up to date with installed bzr version %s.'
67
                ' \nThere should be a newer version available, e.g. %i.%i.' 
68
                % (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
69
70
71
check_bzrlib_version(version_info[:2])
72
146 by Jelmer Vernooij
Move more code to top-level directory.
73
from bzrlib.trace import warning
74
if __name__ != 'bzrlib.plugins.gtk':
75
    warning("Not running as bzrlib.plugins.gtk, things may break.")
76
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
77
from bzrlib.lazy_import import lazy_import
78
lazy_import(globals(), """
79
from bzrlib import (
80
    branch,
81
    errors,
82
    workingtree,
83
    )
84
""")
85
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
86
from bzrlib.commands import Command, register_command, display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
87
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
88
from bzrlib.option import Option
89
126.1.5 by Szilveszter Farkas (Phanatic)
bzr gbranch should work now (Fixed: #77751)
90
import os.path
91
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
92
def import_pygtk():
93
    try:
94
        import pygtk
95
    except ImportError:
96
        raise errors.BzrCommandError("PyGTK not installed.")
97
    pygtk.require('2.0')
98
    return pygtk
99
100
133 by Jelmer Vernooij
Actually use the ui factory.
101
def set_ui_factory():
177 by Jelmer Vernooij
Register commands all at once.
102
    import_pygtk()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
103
    from ui import GtkUIFactory
133 by Jelmer Vernooij
Actually use the ui factory.
104
    import bzrlib.ui
105
    bzrlib.ui.ui_factory = GtkUIFactory()
106
107
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
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()
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
119
        return gtk
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
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):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
128
    """GTK+ branching.
129
    
130
    """
131
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
132
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
133
        from bzrlib.plugins.gtk.branch import BranchDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
134
        return BranchDialog(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
135
136
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
137
class cmd_gcheckout(GTKCommand):
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
138
    """ GTK+ checkout.
139
    
140
    """
141
    
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
142
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
143
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
144
        return CheckoutDialog(path)
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
145
146
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
147
148
class cmd_gpush(GTKCommand):
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
149
    """ GTK+ push.
150
    
151
    """
152
    takes_args = [ "location?" ]
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
153
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
154
    def run(self, location="."):
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
155
        (br, path) = branch.Branch.open_containing(location)
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
156
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
157
        from push import PushDialog
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
158
        dialog = PushDialog(br)
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
159
        dialog.run()
160
161
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
162
163
class cmd_gdiff(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
164
    """Show differences in working tree in a GTK+ Window.
165
    
166
    Otherwise, all changes for the tree are listed.
167
    """
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
168
    takes_args = ['filename?']
58.1.1 by Aaron Bentley
gdiff takes -r arguments
169
    takes_options = ['revision']
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
170
171
    @display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
172
    def run(self, revision=None, filename=None):
133 by Jelmer Vernooij
Actually use the ui factory.
173
        set_ui_factory()
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
174
        wt = workingtree.WorkingTree.open_containing(".")[0]
161 by Aaron Bentley
Fix gannotate interaction with dirstate
175
        wt.lock_read()
176
        try:
177
            branch = wt.branch
178
            if revision is not None:
179
                if len(revision) == 1:
180
                    tree1 = wt
181
                    revision_id = revision[0].in_history(branch).rev_id
182
                    tree2 = branch.repository.revision_tree(revision_id)
183
                elif len(revision) == 2:
184
                    revision_id_0 = revision[0].in_history(branch).rev_id
185
                    tree2 = branch.repository.revision_tree(revision_id_0)
186
                    revision_id_1 = revision[1].in_history(branch).rev_id
187
                    tree1 = branch.repository.revision_tree(revision_id_1)
188
            else:
58.1.1 by Aaron Bentley
gdiff takes -r arguments
189
                tree1 = wt
161 by Aaron Bentley
Fix gannotate interaction with dirstate
190
                tree2 = tree1.basis_tree()
191
192
            from diff import DiffWindow
193
            import gtk
194
            window = DiffWindow()
195
            window.connect("destroy", gtk.main_quit)
196
            window.set_diff("Working Tree", tree1, tree2)
197
            if filename is not None:
198
                tree_filename = wt.relpath(filename)
199
                try:
200
                    window.set_file(tree_filename)
201
                except NoSuchFile:
188.3.1 by John Arbash Meinel
Use tree.path2id to avoid getting 'Object Not Locked' errors.
202
                    if (tree1.path2id(tree_filename) is None and 
203
                        tree2.path2id(tree_filename) is None):
161 by Aaron Bentley
Fix gannotate interaction with dirstate
204
                        raise NotVersionedError(filename)
205
                    raise BzrCommandError('No changes found for file "%s"' % 
206
                                          filename)
207
            window.show()
208
209
            gtk.main()
210
        finally:
211
            wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
212
213
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
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
227
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
228
class cmd_visualise(Command):
229
    """Graphically visualise this branch.
230
231
    Opens a graphical window to allow you to see the history of the branch
232
    and relationships between revisions in a visual manner,
233
234
    The default starting point is latest revision on the branch, you can
235
    specify a starting point with -r revision.
236
    """
237
    takes_options = [
238
        "revision",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
239
        Option('limit', "Maximum number of revisions to display.",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
240
               int, 'count')]
241
    takes_args = [ "location?" ]
242
    aliases = [ "visualize", "vis", "viz" ]
243
244
    def run(self, location=".", revision=None, limit=None):
133 by Jelmer Vernooij
Actually use the ui factory.
245
        set_ui_factory()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
246
        (br, path) = branch.Branch.open_containing(location)
247
        br.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
248
        try:
249
            if revision is None:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
250
                revid = br.last_revision()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
251
                if revid is None:
252
                    return
253
            else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
254
                (revno, revid) = revision[0].in_history(br)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
255
152 by Jelmer Vernooij
Cleanup some more code.
256
            import gtk
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
257
            pp = start_viz_window(br, revid, limit)
152 by Jelmer Vernooij
Cleanup some more code.
258
            pp.connect("destroy", lambda w: gtk.main_quit())
259
            pp.show()
260
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
261
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
262
            br.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
263
264
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
265
class cmd_gannotate(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
266
    """GTK+ annotate.
267
    
268
    Browse changes to FILENAME line by line in a GTK+ window.
269
    """
270
59.2.1 by Aaron Bentley
Gannotate takes a line number
271
    takes_args = ["filename", "line?"]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
272
    takes_options = [
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
273
        Option("all", help="Show annotations on all lines."),
274
        Option("plain", help="Don't highlight annotation lines."),
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
275
        Option("line", type=int, argname="lineno",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
276
               help="Jump to specified line number."),
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
277
        "revision",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
278
    ]
279
    aliases = ["gblame", "gpraise"]
280
    
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
281
    def run(self, filename, all=False, plain=False, line='1', revision=None):
187 by Jelmer Vernooij
Fix gannotate.
282
        gtk = self.open_display()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
283
59.2.1 by Aaron Bentley
Gannotate takes a line number
284
        try:
285
            line = int(line)
286
        except ValueError:
287
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
288
                                  line)
289
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
290
        from annotate.gannotate import GAnnotateWindow
291
        from annotate.config import GAnnotateConfig
177 by Jelmer Vernooij
Register commands all at once.
292
        from bzrlib.bzrdir import BzrDir
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
293
161 by Aaron Bentley
Fix gannotate interaction with dirstate
294
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
295
        if wt is not None:
296
            tree = wt
297
        else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
298
            tree = br.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
299
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
300
        file_id = tree.path2id(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
301
302
        if file_id is None:
303
            raise NotVersionedError(filename)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
304
        if revision is not None:
305
            if len(revision) != 1:
306
                raise BzrCommandError("Only 1 revion may be specified.")
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
307
            revision_id = revision[0].in_history(br).rev_id
308
            tree = br.repository.revision_tree(revision_id)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
309
        else:
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
310
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
311
312
        window = GAnnotateWindow(all, plain)
313
        window.connect("destroy", lambda w: gtk.main_quit())
314
        window.set_title(path + " - gannotate")
315
        config = GAnnotateConfig(window)
316
        window.show()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
317
        br.lock_read()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
318
        if wt is not None:
319
            wt.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
320
        try:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
321
            window.annotate(tree, br, file_id)
161 by Aaron Bentley
Fix gannotate interaction with dirstate
322
            window.jump_to_line(line)
323
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
324
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
325
            br.unlock()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
326
            if wt is not None:
327
                wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
328
329
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
330
331
class cmd_gcommit(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
332
    """GTK+ commit dialog
333
334
    Graphical user interface for committing revisions"""
335
    
145 by Jelmer Vernooij
Fix some strings, import.
336
    aliases = [ "gci" ]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
337
    takes_args = []
338
    takes_options = []
339
340
    def run(self, filename=None):
93.1.17 by Alexander Belchenko
gcommit reworked again.
341
        import os
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
342
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
343
        from commit import CommitDialog
93.1.17 by Alexander Belchenko
gcommit reworked again.
344
        from bzrlib.errors import (BzrCommandError,
345
                                   NotBranchError,
178 by Jelmer Vernooij
Remove unneeded imports.
346
                                   NoWorkingTree)
93.1.17 by Alexander Belchenko
gcommit reworked again.
347
348
        wt = None
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
349
        br = None
93.1.17 by Alexander Belchenko
gcommit reworked again.
350
        try:
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
351
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
352
            br = wt.branch
93.1.17 by Alexander Belchenko
gcommit reworked again.
353
        except NoWorkingTree, e:
354
            path = e.base
195.2.1 by Szilveszter Farkas (Phanatic)
NotBranchError exception shouldn't be handled. (Fixes: #113394)
355
            (br, path) = branch.Branch.open_containing(path)
93.1.17 by Alexander Belchenko
gcommit reworked again.
356
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
357
        commit = CommitDialog(wt, path, not br)
135 by Jelmer Vernooij
Throw out the old CommitDialog code and use the new code instead, also for 'gcommit'.
358
        commit.run()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
359
360
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
361
362
class cmd_gstatus(GTKCommand):
157 by Jelmer Vernooij
Add gstatus command.
363
    """GTK+ status dialog
364
365
    Graphical user interface for showing status 
366
    information."""
367
    
368
    aliases = [ "gst" ]
369
    takes_args = ['PATH?']
370
    takes_options = []
371
372
    def run(self, path='.'):
373
        import os
184 by Jelmer Vernooij
Fix gstatus
374
        gtk = self.open_display()
157 by Jelmer Vernooij
Add gstatus command.
375
        from status import StatusDialog
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
376
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
157 by Jelmer Vernooij
Add gstatus command.
377
        status = StatusDialog(wt, wt_path)
378
        status.connect("destroy", gtk.main_quit)
379
        status.run()
380
381
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
382
383
class cmd_gconflicts(GTKCommand):
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
384
    """ GTK+ push.
385
    
386
    """
387
    def run(self):
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
388
        (wt, path) = workingtree.WorkingTree.open_containing('.')
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
389
        self.open_display()
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
390
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
391
        dialog = ConflictsDialog(wt)
392
        dialog.run()
393
157 by Jelmer Vernooij
Add gstatus command.
394
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
395
396
class cmd_gpreferences(GTKCommand):
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
397
    """ GTK+ preferences dialog.
398
399
    """
400
    def run(self):
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
401
        self.open_display()
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
402
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
403
        dialog = PreferencesWindow()
404
        dialog.run()
405
406
175 by Jelmer Vernooij
Add very simple gmissing command.
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
177 by Jelmer Vernooij
Register commands all at once.
443
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
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
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
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
177 by Jelmer Vernooij
Register commands all at once.
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, 
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
474
    cmd_gbranch,
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
475
    cmd_ginit,
476
    cmd_gtags
177 by Jelmer Vernooij
Register commands all at once.
477
    ]
478
479
for cmd in commands:
480
    register_command(cmd)
175 by Jelmer Vernooij
Add very simple gmissing command.
481
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
482
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
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):
211 by Jelmer Vernooij
Move notification area code into separate file.
491
        from notify import NotifyPopupMenu
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
492
        gtk = self.open_display()
211 by Jelmer Vernooij
Move notification area code into separate file.
493
        menu = NotifyPopupMenu()
494
        icon = gtk.status_icon_new_from_file("bzr-icon-64.png")
495
        icon.connect('popup-menu', menu.display)
210 by Jelmer Vernooij
Add notification area icon for commit-notify.
496
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
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)
211 by Jelmer Vernooij
Move notification area code into separate file.
513
182.1.1 by Robert Collins
Update commit-notify to use new dbus api, and show remote URL's.
514
        def catch_branch(revision_id, urls):
515
            # TODO: show all the urls, or perhaps choose the 'best'.
516
            url = urls[0]
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
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)
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
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()
208.2.3 by Robert Collins
Add a Branch button to commit-notify.
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()
208.2.4 by Robert Collins
Unbreak inspect of commits due to misunderstanding of pynotify api.
542
                nw.add_action("inspect", "Inspect", start_viz, None)
543
                nw.add_action("branch", "Branch", start_branch, None)
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
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
556
152 by Jelmer Vernooij
Cleanup some more code.
557
import gettext
558
gettext.install('olive-gtk')
559
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
560
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
561
class NoDisplayError(BzrCommandError):
562
    """gtk could not find a proper display"""
563
564
    def __str__(self):
133 by Jelmer Vernooij
Actually use the ui factory.
565
        return "No DISPLAY. Unable to run GTK+ application."
566
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
567
140 by Jelmer Vernooij
add framework for tests.
568
def test_suite():
569
    from unittest import TestSuite
570
    import tests
163 by Aaron Bentley
Prevent test suite from causing default-encoding changes
571
    import sys
572
    default_encoding = sys.getdefaultencoding()
573
    try:
574
        result = TestSuite()
575
        result.addTest(tests.test_suite())
576
    finally:
170.1.2 by Aaron Bentley
Test suite only fixes encoding if it's changed. Fixes test_selftest bug.
577
        if sys.getdefaultencoding() != default_encoding:
578
            reload(sys)
579
            sys.setdefaultencoding(default_encoding)
140 by Jelmer Vernooij
add framework for tests.
580
    return result