/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
49 by Jelmer Vernooij
Merge in Dan Loda's gannotate plugin and put it in annotate/
1
# This program is free software; you can redistribute it and/or modify
2
# it under the terms of the GNU General Public License as published by
3
# the Free Software Foundation; either version 2 of the License, or
4
# (at your option) any later version.
5
6
# This program is distributed in the hope that it will be useful,
7
# but WITHOUT ANY WARRANTY; without even the implied warranty of
8
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9
# GNU General Public License for more details.
10
11
# You should have received a copy of the GNU General Public License
12
# along with this program; if not, write to the Free Software
13
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
14
208.2.1 by Robert Collins
Better module docstring.
15
"""Graphical support for Bazaar using GTK.
16
17
This plugin includes:
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 
242.1.2 by Adeodato Simó
Fix gconflicts docstring.
23
gconflicts        GTK+ conflicts. 
208.2.1 by Robert Collins
Better module docstring.
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. 
28
gpush             GTK+ push. 
29
gstatus           GTK+ status dialog 
30
gtags             Manage branch tags.
31
visualise         Graphically visualise this branch. 
32
"""
73 by Jelmer Vernooij
Release 0.9, list myself as maintainer.
33
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
34
import bzrlib
35
287 by Jelmer Vernooij
Use standard version tuple.
36
version_info = (0, 92, 0, 'dev', 0)
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
37
287 by Jelmer Vernooij
Use standard version tuple.
38
if version_info[3] == 'final':
39
    version_string = '%d.%d.%d' % version_info[:3]
40
else:
41
    version_string = '%d.%d.%d%s%d' % version_info
42
__version__ = version_string
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
43
44
def check_bzrlib_version(desired):
45
    """Check that bzrlib is compatible.
46
47
    If version is < bzr-gtk version, assume incompatible.
48
    If version == bzr-gtk version, assume completely compatible
49
    If version == bzr-gtk version + 1, assume compatible, with deprecations
50
    Otherwise, assume incompatible.
51
    """
52
    desired_plus = (desired[0], desired[1]+1)
53
    bzrlib_version = bzrlib.version_info[:2]
203 by Aaron Bentley
Don't warn if bzrlib is dev version of next release
54
    if bzrlib_version == desired or (bzrlib_version == desired_plus and
55
                                     bzrlib.version_info[3] == 'dev'):
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
56
        return
57
    try:
58
        from bzrlib.trace import warning
59
    except ImportError:
60
        # get the message out any way we can
61
        from warnings import warn as warning
62
    if bzrlib_version < desired:
207 by Aaron Bentley
Import BzrError before using it
63
        from bzrlib.errors import BzrError
271 by Jelmer Vernooij
Add common widget for selecting branches.
64
        warning('Installed Bazaar version %s is too old to be used with bzr-gtk'
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
65
                ' %s.' % (bzrlib.__version__, __version__))
287 by Jelmer Vernooij
Use standard version tuple.
66
        raise BzrError('Version mismatch: %r, %r' % (version_info, bzrlib.version_info) )
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
67
    else:
68
        warning('bzr-gtk is not up to date with installed bzr version %s.'
69
                ' \nThere should be a newer version available, e.g. %i.%i.' 
70
                % (bzrlib.__version__, bzrlib_version[0], bzrlib_version[1]))
71
72
287 by Jelmer Vernooij
Use standard version tuple.
73
if version_info[2] == "final":
74
    check_bzrlib_version(version_info[:2])
137 by Jelmer Vernooij
Warn about incompatible versions (taken from bzrtools, thanks Aaron).
75
146 by Jelmer Vernooij
Move more code to top-level directory.
76
from bzrlib.trace import warning
77
if __name__ != 'bzrlib.plugins.gtk':
78
    warning("Not running as bzrlib.plugins.gtk, things may break.")
79
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
80
from bzrlib.lazy_import import lazy_import
81
lazy_import(globals(), """
82
from bzrlib import (
83
    branch,
249 by Aaron Bentley
Add gselftest command
84
    builtins,
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
85
    errors,
86
    workingtree,
87
    )
88
""")
89
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
90
from bzrlib.commands import Command, register_command, display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
91
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
92
from bzrlib.option import Option
93
126.1.5 by Szilveszter Farkas (Phanatic)
bzr gbranch should work now (Fixed: #77751)
94
import os.path
95
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
96
def import_pygtk():
97
    try:
98
        import pygtk
99
    except ImportError:
100
        raise errors.BzrCommandError("PyGTK not installed.")
101
    pygtk.require('2.0')
102
    return pygtk
103
104
133 by Jelmer Vernooij
Actually use the ui factory.
105
def set_ui_factory():
177 by Jelmer Vernooij
Register commands all at once.
106
    import_pygtk()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
107
    from ui import GtkUIFactory
133 by Jelmer Vernooij
Actually use the ui factory.
108
    import bzrlib.ui
109
    bzrlib.ui.ui_factory = GtkUIFactory()
110
111
247 by Jelmer Vernooij
Use application path to find icons.
112
def data_path():
113
    return os.path.dirname(__file__)
114
115
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
116
class GTKCommand(Command):
117
    """Abstract class providing GTK specific run commands."""
118
119
    def open_display(self):
120
        pygtk = import_pygtk()
121
        try:
122
            import gtk
123
        except RuntimeError, e:
124
            if str(e) == "could not open display":
125
                raise NoDisplayError
126
        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.
127
        return gtk
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
128
129
    def run(self):
130
        self.open_display()
131
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
132
        dialog.run()
133
134
135
class cmd_gbranch(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
136
    """GTK+ branching.
137
    
138
    """
139
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
140
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
141
        from bzrlib.plugins.gtk.branch import BranchDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
142
        return BranchDialog(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
143
144
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
145
class cmd_gcheckout(GTKCommand):
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
146
    """ GTK+ checkout.
147
    
148
    """
149
    
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
150
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
151
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
152
        return CheckoutDialog(path)
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
153
154
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
155
156
class cmd_gpush(GTKCommand):
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
157
    """ GTK+ push.
158
    
159
    """
160
    takes_args = [ "location?" ]
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
161
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
162
    def run(self, location="."):
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
163
        (br, path) = branch.Branch.open_containing(location)
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
164
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
165
        from push import PushDialog
233 by Jelmer Vernooij
Get rid of test button in push.
166
        dialog = PushDialog(br.repository, br.last_revision(), br)
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
167
        dialog.run()
168
169
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
170
171
class cmd_gdiff(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
172
    """Show differences in working tree in a GTK+ Window.
173
    
174
    Otherwise, all changes for the tree are listed.
175
    """
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
176
    takes_args = ['filename?']
58.1.1 by Aaron Bentley
gdiff takes -r arguments
177
    takes_options = ['revision']
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
178
179
    @display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
180
    def run(self, revision=None, filename=None):
133 by Jelmer Vernooij
Actually use the ui factory.
181
        set_ui_factory()
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
182
        wt = workingtree.WorkingTree.open_containing(".")[0]
161 by Aaron Bentley
Fix gannotate interaction with dirstate
183
        wt.lock_read()
184
        try:
185
            branch = wt.branch
186
            if revision is not None:
187
                if len(revision) == 1:
188
                    tree1 = wt
189
                    revision_id = revision[0].in_history(branch).rev_id
190
                    tree2 = branch.repository.revision_tree(revision_id)
191
                elif len(revision) == 2:
192
                    revision_id_0 = revision[0].in_history(branch).rev_id
193
                    tree2 = branch.repository.revision_tree(revision_id_0)
194
                    revision_id_1 = revision[1].in_history(branch).rev_id
195
                    tree1 = branch.repository.revision_tree(revision_id_1)
196
            else:
58.1.1 by Aaron Bentley
gdiff takes -r arguments
197
                tree1 = wt
161 by Aaron Bentley
Fix gannotate interaction with dirstate
198
                tree2 = tree1.basis_tree()
199
200
            from diff import DiffWindow
201
            import gtk
202
            window = DiffWindow()
203
            window.connect("destroy", gtk.main_quit)
204
            window.set_diff("Working Tree", tree1, tree2)
205
            if filename is not None:
206
                tree_filename = wt.relpath(filename)
207
                try:
208
                    window.set_file(tree_filename)
209
                except NoSuchFile:
188.3.1 by John Arbash Meinel
Use tree.path2id to avoid getting 'Object Not Locked' errors.
210
                    if (tree1.path2id(tree_filename) is None and 
211
                        tree2.path2id(tree_filename) is None):
161 by Aaron Bentley
Fix gannotate interaction with dirstate
212
                        raise NotVersionedError(filename)
213
                    raise BzrCommandError('No changes found for file "%s"' % 
214
                                          filename)
215
            window.show()
216
217
            gtk.main()
218
        finally:
219
            wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
220
221
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
222
def start_viz_window(branch, revision, limit=None):
223
    """Start viz on branch with revision revision.
224
    
225
    :return: The viz window object.
226
    """
227
    from viz.branchwin import BranchWindow
228
    branch.lock_read()
229
    pp = BranchWindow()
230
    pp.set_branch(branch, revision, limit)
231
    # cleanup locks when the window is closed
232
    pp.connect("destroy", lambda w: branch.unlock())
233
    return pp
234
235
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
236
class cmd_visualise(Command):
237
    """Graphically visualise this branch.
238
239
    Opens a graphical window to allow you to see the history of the branch
240
    and relationships between revisions in a visual manner,
241
242
    The default starting point is latest revision on the branch, you can
243
    specify a starting point with -r revision.
244
    """
245
    takes_options = [
246
        "revision",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
247
        Option('limit', "Maximum number of revisions to display.",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
248
               int, 'count')]
249
    takes_args = [ "location?" ]
250
    aliases = [ "visualize", "vis", "viz" ]
251
252
    def run(self, location=".", revision=None, limit=None):
133 by Jelmer Vernooij
Actually use the ui factory.
253
        set_ui_factory()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
254
        (br, path) = branch.Branch.open_containing(location)
255
        br.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
256
        try:
257
            if revision is None:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
258
                revid = br.last_revision()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
259
                if revid is None:
260
                    return
261
            else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
262
                (revno, revid) = revision[0].in_history(br)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
263
152 by Jelmer Vernooij
Cleanup some more code.
264
            import gtk
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
265
            pp = start_viz_window(br, revid, limit)
152 by Jelmer Vernooij
Cleanup some more code.
266
            pp.connect("destroy", lambda w: gtk.main_quit())
267
            pp.show()
268
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
269
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
270
            br.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
271
272
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
273
class cmd_gannotate(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
274
    """GTK+ annotate.
275
    
276
    Browse changes to FILENAME line by line in a GTK+ window.
277
    """
278
59.2.1 by Aaron Bentley
Gannotate takes a line number
279
    takes_args = ["filename", "line?"]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
280
    takes_options = [
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
281
        Option("all", help="Show annotations on all lines."),
282
        Option("plain", help="Don't highlight annotation lines."),
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
283
        Option("line", type=int, argname="lineno",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
284
               help="Jump to specified line number."),
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
285
        "revision",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
286
    ]
287
    aliases = ["gblame", "gpraise"]
288
    
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
289
    def run(self, filename, all=False, plain=False, line='1', revision=None):
187 by Jelmer Vernooij
Fix gannotate.
290
        gtk = self.open_display()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
291
59.2.1 by Aaron Bentley
Gannotate takes a line number
292
        try:
293
            line = int(line)
294
        except ValueError:
295
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
296
                                  line)
297
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
298
        from annotate.gannotate import GAnnotateWindow
299
        from annotate.config import GAnnotateConfig
177 by Jelmer Vernooij
Register commands all at once.
300
        from bzrlib.bzrdir import BzrDir
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
301
161 by Aaron Bentley
Fix gannotate interaction with dirstate
302
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
303
        if wt is not None:
304
            tree = wt
305
        else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
306
            tree = br.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
307
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
308
        file_id = tree.path2id(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
309
310
        if file_id is None:
311
            raise NotVersionedError(filename)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
312
        if revision is not None:
313
            if len(revision) != 1:
314
                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
315
            revision_id = revision[0].in_history(br).rev_id
316
            tree = br.repository.revision_tree(revision_id)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
317
        else:
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
318
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
319
320
        window = GAnnotateWindow(all, plain)
321
        window.connect("destroy", lambda w: gtk.main_quit())
322
        window.set_title(path + " - gannotate")
323
        config = GAnnotateConfig(window)
324
        window.show()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
325
        br.lock_read()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
326
        if wt is not None:
327
            wt.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
328
        try:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
329
            window.annotate(tree, br, file_id)
161 by Aaron Bentley
Fix gannotate interaction with dirstate
330
            window.jump_to_line(line)
331
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
332
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
333
            br.unlock()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
334
            if wt is not None:
335
                wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
336
337
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
338
339
class cmd_gcommit(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
340
    """GTK+ commit dialog
341
342
    Graphical user interface for committing revisions"""
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
343
145 by Jelmer Vernooij
Fix some strings, import.
344
    aliases = [ "gci" ]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
345
    takes_args = []
346
    takes_options = []
347
348
    def run(self, filename=None):
93.1.17 by Alexander Belchenko
gcommit reworked again.
349
        import os
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
350
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
351
        from commit import CommitDialog
93.1.17 by Alexander Belchenko
gcommit reworked again.
352
        from bzrlib.errors import (BzrCommandError,
353
                                   NotBranchError,
178 by Jelmer Vernooij
Remove unneeded imports.
354
                                   NoWorkingTree)
93.1.17 by Alexander Belchenko
gcommit reworked again.
355
356
        wt = None
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
357
        br = None
93.1.17 by Alexander Belchenko
gcommit reworked again.
358
        try:
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
359
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
360
            br = wt.branch
93.1.17 by Alexander Belchenko
gcommit reworked again.
361
        except NoWorkingTree, e:
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
362
            from dialog import error_dialog
363
            error_dialog(_('Directory does not have a working tree'),
364
                         _('Operation aborted.'))
365
            return 1 # should this be retval=3?
366
367
        # It is a good habit to keep things locked for the duration, but it
368
        # could cause difficulties if someone wants to do things in another
369
        # window... We could lock_read() until we actually go to commit
370
        # changes... Just a thought.
371
        wt.lock_write()
372
        try:
373
            dlg = CommitDialog(wt)
374
            return dlg.run()
375
        finally:
376
            wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
377
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
378
250 by Aaron Bentley
oops- revert status change
379
class cmd_gstatus(GTKCommand):
157 by Jelmer Vernooij
Add gstatus command.
380
    """GTK+ status dialog
381
382
    Graphical user interface for showing status 
383
    information."""
384
    
385
    aliases = [ "gst" ]
386
    takes_args = ['PATH?']
387
    takes_options = []
388
389
    def run(self, path='.'):
390
        import os
184 by Jelmer Vernooij
Fix gstatus
391
        gtk = self.open_display()
157 by Jelmer Vernooij
Add gstatus command.
392
        from status import StatusDialog
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
393
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
157 by Jelmer Vernooij
Add gstatus command.
394
        status = StatusDialog(wt, wt_path)
395
        status.connect("destroy", gtk.main_quit)
396
        status.run()
397
398
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
399
400
class cmd_gconflicts(GTKCommand):
242.1.2 by Adeodato Simó
Fix gconflicts docstring.
401
    """ GTK+ conflicts.
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
402
    
242.1.2 by Adeodato Simó
Fix gconflicts docstring.
403
    Select files from the list of conflicts and run an external utility to
404
    resolve them.
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
405
    """
406
    def run(self):
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
407
        (wt, path) = workingtree.WorkingTree.open_containing('.')
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
408
        self.open_display()
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
409
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
410
        dialog = ConflictsDialog(wt)
411
        dialog.run()
412
157 by Jelmer Vernooij
Add gstatus command.
413
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
414
415
class cmd_gpreferences(GTKCommand):
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
416
    """ GTK+ preferences dialog.
417
418
    """
419
    def run(self):
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
420
        self.open_display()
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
421
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
422
        dialog = PreferencesWindow()
423
        dialog.run()
424
425
175 by Jelmer Vernooij
Add very simple gmissing command.
426
427
class cmd_gmissing(Command):
428
    """ GTK+ missing revisions dialog.
429
430
    """
431
    takes_args = ["other_branch?"]
432
    def run(self, other_branch=None):
433
        pygtk = import_pygtk()
434
        try:
435
            import gtk
436
        except RuntimeError, e:
437
            if str(e) == "could not open display":
438
                raise NoDisplayError
439
440
        from bzrlib.plugins.gtk.missing import MissingWindow
441
        from bzrlib.branch import Branch
442
443
        local_branch = Branch.open_containing(".")[0]
444
        if other_branch is None:
445
            other_branch = local_branch.get_parent()
446
            
447
            if other_branch is None:
448
                raise errors.BzrCommandError("No peer location known or specified.")
449
        remote_branch = Branch.open_containing(other_branch)[0]
450
        set_ui_factory()
451
        local_branch.lock_read()
452
        try:
453
            remote_branch.lock_read()
454
            try:
455
                dialog = MissingWindow(local_branch, remote_branch)
456
                dialog.run()
457
            finally:
458
                remote_branch.unlock()
459
        finally:
460
            local_branch.unlock()
461
177 by Jelmer Vernooij
Register commands all at once.
462
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
463
class cmd_ginit(GTKCommand):
464
    def run(self):
465
        self.open_display()
466
        from initialize import InitDialog
467
        dialog = InitDialog(os.path.abspath(os.path.curdir))
468
        dialog.run()
469
470
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
471
class cmd_gtags(GTKCommand):
472
    def run(self):
473
        br = branch.Branch.open_containing('.')[0]
474
        
475
        gtk = self.open_display()
476
        from tags import TagsWindow
477
        window = TagsWindow(br)
478
        window.show()
479
        gtk.main()
480
481
177 by Jelmer Vernooij
Register commands all at once.
482
commands = [
483
    cmd_gmissing, 
484
    cmd_gpreferences, 
485
    cmd_gconflicts, 
486
    cmd_gstatus,
487
    cmd_gcommit, 
488
    cmd_gannotate, 
489
    cmd_visualise, 
490
    cmd_gdiff,
491
    cmd_gpush, 
492
    cmd_gcheckout, 
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
493
    cmd_gbranch,
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
494
    cmd_ginit,
495
    cmd_gtags
177 by Jelmer Vernooij
Register commands all at once.
496
    ]
497
498
for cmd in commands:
499
    register_command(cmd)
175 by Jelmer Vernooij
Add very simple gmissing command.
500
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
501
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
502
class cmd_commit_notify(GTKCommand):
503
    """Run the bzr commit notifier.
504
505
    This is a background program which will pop up a notification on the users
506
    screen when a commit occurs.
507
    """
508
509
    def run(self):
211 by Jelmer Vernooij
Move notification area code into separate file.
510
        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.
511
        gtk = self.open_display()
211 by Jelmer Vernooij
Move notification area code into separate file.
512
        menu = NotifyPopupMenu()
247 by Jelmer Vernooij
Use application path to find icons.
513
        icon = gtk.status_icon_new_from_file(os.path.join(data_path(), "bzr-icon-64.png"))
211 by Jelmer Vernooij
Move notification area code into separate file.
514
        icon.connect('popup-menu', menu.display)
210 by Jelmer Vernooij
Add notification area icon for commit-notify.
515
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
516
        import cgi
517
        import dbus
518
        import dbus.service
519
        import pynotify
520
        from bzrlib.bzrdir import BzrDir
521
        from bzrlib import errors
522
        from bzrlib.osutils import format_date
523
        from bzrlib.transport import get_transport
524
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
525
            import dbus.glib
526
        from bzrlib.plugins.dbus import activity
527
        bus = dbus.SessionBus()
528
        # get the object so we can subscribe to callbacks from it.
529
        broadcast_service = bus.get_object(
530
            activity.Broadcast.DBUS_NAME,
531
            activity.Broadcast.DBUS_PATH)
211 by Jelmer Vernooij
Move notification area code into separate file.
532
182.1.1 by Robert Collins
Update commit-notify to use new dbus api, and show remote URL's.
533
        def catch_branch(revision_id, urls):
534
            # TODO: show all the urls, or perhaps choose the 'best'.
535
            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.
536
            try:
537
                if isinstance(revision_id, unicode):
538
                    revision_id = revision_id.encode('utf8')
539
                transport = get_transport(url)
540
                a_dir = BzrDir.open_from_transport(transport)
541
                branch = a_dir.open_branch()
542
                revno = branch.revision_id_to_revno(revision_id)
543
                revision = branch.repository.get_revision(revision_id)
544
                summary = 'New revision %d in %s' % (revno, url)
545
                body  = 'Committer: %s\n' % revision.committer
546
                body += 'Date: %s\n' % format_date(revision.timestamp,
547
                    revision.timezone)
548
                body += '\n'
549
                body += revision.message
550
                body = cgi.escape(body)
551
                nw = pynotify.Notification(summary, body)
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
552
                def start_viz(notification=None, action=None, data=None):
553
                    """Start the viz program."""
554
                    pp = start_viz_window(branch, revision_id)
555
                    pp.show()
208.2.3 by Robert Collins
Add a Branch button to commit-notify.
556
                def start_branch(notification=None, action=None, data=None):
557
                    """Start a Branch dialog"""
558
                    from bzrlib.plugins.gtk.branch import BranchDialog
559
                    bd = BranchDialog(remote_path=url)
560
                    bd.run()
208.2.4 by Robert Collins
Unbreak inspect of commits due to misunderstanding of pynotify api.
561
                nw.add_action("inspect", "Inspect", start_viz, None)
562
                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.
563
                nw.set_timeout(5000)
564
                nw.show()
565
            except Exception, e:
566
                print e
567
                raise
568
        broadcast_service.connect_to_signal("Revision", catch_branch,
569
            dbus_interface=activity.Broadcast.DBUS_INTERFACE)
570
        pynotify.init("bzr commit-notify")
571
        gtk.main()
572
573
register_command(cmd_commit_notify)
574
575
249 by Aaron Bentley
Add gselftest command
576
class cmd_gselftest(GTKCommand):
577
    """Version of selftest that displays a notification at the end"""
578
579
    takes_args = builtins.cmd_selftest.takes_args
580
    takes_options = builtins.cmd_selftest.takes_options
581
    _see_also = ['selftest']
582
583
    def run(self, *args, **kwargs):
584
        import cgi
253 by Aaron Bentley
Avoid encoding problems from pygtk
585
        import sys
586
        default_encoding = sys.getdefaultencoding()
249 by Aaron Bentley
Add gselftest command
587
        # prevent gtk from blowing up later
588
        gtk = import_pygtk()
253 by Aaron Bentley
Avoid encoding problems from pygtk
589
        # prevent gtk from messing with default encoding
249 by Aaron Bentley
Add gselftest command
590
        import pynotify
253 by Aaron Bentley
Avoid encoding problems from pygtk
591
        if sys.getdefaultencoding() != default_encoding:
592
            reload(sys)
593
            sys.setdefaultencoding(default_encoding)
249 by Aaron Bentley
Add gselftest command
594
        result = builtins.cmd_selftest().run(*args, **kwargs)
595
        if result == 0:
596
            summary = 'Success'
597
            body = 'Selftest succeeded in "%s"' % os.getcwd()
598
        if result == 1:
599
            summary = 'Failure'
600
            body = 'Selftest failed in "%s"' % os.getcwd()
601
        pynotify.init("bzr gselftest")
602
        note = pynotify.Notification(cgi.escape(summary), cgi.escape(body))
603
        note.set_timeout(pynotify.EXPIRES_NEVER)
604
        note.show()
605
606
607
register_command(cmd_gselftest)
608
609
152 by Jelmer Vernooij
Cleanup some more code.
610
import gettext
611
gettext.install('olive-gtk')
612
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
613
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
614
class NoDisplayError(BzrCommandError):
615
    """gtk could not find a proper display"""
616
617
    def __str__(self):
133 by Jelmer Vernooij
Actually use the ui factory.
618
        return "No DISPLAY. Unable to run GTK+ application."
619
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
620
140 by Jelmer Vernooij
add framework for tests.
621
def test_suite():
622
    from unittest import TestSuite
623
    import tests
163 by Aaron Bentley
Prevent test suite from causing default-encoding changes
624
    import sys
625
    default_encoding = sys.getdefaultencoding()
626
    try:
627
        result = TestSuite()
628
        result.addTest(tests.test_suite())
629
    finally:
170.1.2 by Aaron Bentley
Test suite only fixes encoding if it's changed. Fixes test_selftest bug.
630
        if sys.getdefaultencoding() != default_encoding:
631
            reload(sys)
632
            sys.setdefaultencoding(default_encoding)
140 by Jelmer Vernooij
add framework for tests.
633
    return result