/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
        if bzrlib_version != desired_plus:
70
            raise Exception, 'Version mismatch'
71
72
73
check_bzrlib_version(version_info[:2])
74
146 by Jelmer Vernooij
Move more code to top-level directory.
75
from bzrlib.trace import warning
76
if __name__ != 'bzrlib.plugins.gtk':
77
    warning("Not running as bzrlib.plugins.gtk, things may break.")
78
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
79
from bzrlib.lazy_import import lazy_import
80
lazy_import(globals(), """
81
from bzrlib import (
82
    branch,
83
    errors,
84
    workingtree,
85
    )
86
""")
87
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
88
from bzrlib.commands import Command, register_command, display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
89
from bzrlib.errors import NotVersionedError, BzrCommandError, NoSuchFile
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
90
from bzrlib.option import Option
91
126.1.5 by Szilveszter Farkas (Phanatic)
bzr gbranch should work now (Fixed: #77751)
92
import os.path
93
66.2.20 by Aaron Bentley
Nicer error when PyGTK not installed
94
def import_pygtk():
95
    try:
96
        import pygtk
97
    except ImportError:
98
        raise errors.BzrCommandError("PyGTK not installed.")
99
    pygtk.require('2.0')
100
    return pygtk
101
102
133 by Jelmer Vernooij
Actually use the ui factory.
103
def set_ui_factory():
177 by Jelmer Vernooij
Register commands all at once.
104
    import_pygtk()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
105
    from ui import GtkUIFactory
133 by Jelmer Vernooij
Actually use the ui factory.
106
    import bzrlib.ui
107
    bzrlib.ui.ui_factory = GtkUIFactory()
108
109
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
110
class GTKCommand(Command):
111
    """Abstract class providing GTK specific run commands."""
112
113
    def open_display(self):
114
        pygtk = import_pygtk()
115
        try:
116
            import gtk
117
        except RuntimeError, e:
118
            if str(e) == "could not open display":
119
                raise NoDisplayError
120
        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.
121
        return gtk
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
122
123
    def run(self):
124
        self.open_display()
125
        dialog = self.get_gtk_dialog(os.path.abspath('.'))
126
        dialog.run()
127
128
129
class cmd_gbranch(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
130
    """GTK+ branching.
131
    
132
    """
133
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
134
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
135
        from bzrlib.plugins.gtk.branch import BranchDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
136
        return BranchDialog(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
137
138
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
139
class cmd_gcheckout(GTKCommand):
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
140
    """ GTK+ checkout.
141
    
142
    """
143
    
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
144
    def get_gtk_dialog(self, path):
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
145
        from bzrlib.plugins.gtk.checkout import CheckoutDialog
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
146
        return CheckoutDialog(path)
126.1.18 by Szilveszter Farkas (Phanatic)
Improved Branch dialog. Refactored Checkout dialog.
147
148
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
149
150
class cmd_gpush(GTKCommand):
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
151
    """ GTK+ push.
152
    
153
    """
154
    takes_args = [ "location?" ]
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
155
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
156
    def run(self, location="."):
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
157
        (br, path) = branch.Branch.open_containing(location)
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
158
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
159
        from push import PushDialog
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
160
        dialog = PushDialog(br)
126.1.19 by Szilveszter Farkas (Phanatic)
Refactored the Push dialog. Add 'gpush' command.
161
        dialog.run()
162
163
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
164
165
class cmd_gdiff(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
166
    """Show differences in working tree in a GTK+ Window.
167
    
168
    Otherwise, all changes for the tree are listed.
169
    """
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
170
    takes_args = ['filename?']
58.1.1 by Aaron Bentley
gdiff takes -r arguments
171
    takes_options = ['revision']
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
172
173
    @display_command
59.2.4 by Aaron Bentley
Teach gdiff to accept a single file argument
174
    def run(self, revision=None, filename=None):
133 by Jelmer Vernooij
Actually use the ui factory.
175
        set_ui_factory()
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
176
        wt = workingtree.WorkingTree.open_containing(".")[0]
161 by Aaron Bentley
Fix gannotate interaction with dirstate
177
        wt.lock_read()
178
        try:
179
            branch = wt.branch
180
            if revision is not None:
181
                if len(revision) == 1:
182
                    tree1 = wt
183
                    revision_id = revision[0].in_history(branch).rev_id
184
                    tree2 = branch.repository.revision_tree(revision_id)
185
                elif len(revision) == 2:
186
                    revision_id_0 = revision[0].in_history(branch).rev_id
187
                    tree2 = branch.repository.revision_tree(revision_id_0)
188
                    revision_id_1 = revision[1].in_history(branch).rev_id
189
                    tree1 = branch.repository.revision_tree(revision_id_1)
190
            else:
58.1.1 by Aaron Bentley
gdiff takes -r arguments
191
                tree1 = wt
161 by Aaron Bentley
Fix gannotate interaction with dirstate
192
                tree2 = tree1.basis_tree()
193
194
            from diff import DiffWindow
195
            import gtk
196
            window = DiffWindow()
197
            window.connect("destroy", gtk.main_quit)
198
            window.set_diff("Working Tree", tree1, tree2)
199
            if filename is not None:
200
                tree_filename = wt.relpath(filename)
201
                try:
202
                    window.set_file(tree_filename)
203
                except NoSuchFile:
188.3.1 by John Arbash Meinel
Use tree.path2id to avoid getting 'Object Not Locked' errors.
204
                    if (tree1.path2id(tree_filename) is None and 
205
                        tree2.path2id(tree_filename) is None):
161 by Aaron Bentley
Fix gannotate interaction with dirstate
206
                        raise NotVersionedError(filename)
207
                    raise BzrCommandError('No changes found for file "%s"' % 
208
                                          filename)
209
            window.show()
210
211
            gtk.main()
212
        finally:
213
            wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
214
215
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
216
def start_viz_window(branch, revision, limit=None):
217
    """Start viz on branch with revision revision.
218
    
219
    :return: The viz window object.
220
    """
221
    from viz.branchwin import BranchWindow
222
    branch.lock_read()
223
    pp = BranchWindow()
224
    pp.set_branch(branch, revision, limit)
225
    # cleanup locks when the window is closed
226
    pp.connect("destroy", lambda w: branch.unlock())
227
    return pp
228
229
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
230
class cmd_visualise(Command):
231
    """Graphically visualise this branch.
232
233
    Opens a graphical window to allow you to see the history of the branch
234
    and relationships between revisions in a visual manner,
235
236
    The default starting point is latest revision on the branch, you can
237
    specify a starting point with -r revision.
238
    """
239
    takes_options = [
240
        "revision",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
241
        Option('limit', "Maximum number of revisions to display.",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
242
               int, 'count')]
243
    takes_args = [ "location?" ]
244
    aliases = [ "visualize", "vis", "viz" ]
245
246
    def run(self, location=".", revision=None, limit=None):
133 by Jelmer Vernooij
Actually use the ui factory.
247
        set_ui_factory()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
248
        (br, path) = branch.Branch.open_containing(location)
249
        br.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
250
        try:
251
            if revision is None:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
252
                revid = br.last_revision()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
253
                if revid is None:
254
                    return
255
            else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
256
                (revno, revid) = revision[0].in_history(br)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
257
152 by Jelmer Vernooij
Cleanup some more code.
258
            import gtk
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
259
            pp = start_viz_window(br, revid, limit)
152 by Jelmer Vernooij
Cleanup some more code.
260
            pp.connect("destroy", lambda w: gtk.main_quit())
261
            pp.show()
262
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
263
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
264
            br.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
265
266
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
267
class cmd_gannotate(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
268
    """GTK+ annotate.
269
    
270
    Browse changes to FILENAME line by line in a GTK+ window.
271
    """
272
59.2.1 by Aaron Bentley
Gannotate takes a line number
273
    takes_args = ["filename", "line?"]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
274
    takes_options = [
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
275
        Option("all", help="Show annotations on all lines."),
276
        Option("plain", help="Don't highlight annotation lines."),
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
277
        Option("line", type=int, argname="lineno",
208.2.7 by Vincent Ladeuil
Fix option help strings to comply with the style guide.
278
               help="Jump to specified line number."),
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
279
        "revision",
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
280
    ]
281
    aliases = ["gblame", "gpraise"]
282
    
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
283
    def run(self, filename, all=False, plain=False, line='1', revision=None):
187 by Jelmer Vernooij
Fix gannotate.
284
        gtk = self.open_display()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
285
59.2.1 by Aaron Bentley
Gannotate takes a line number
286
        try:
287
            line = int(line)
288
        except ValueError:
289
            raise BzrCommandError('Line argument ("%s") is not a number.' % 
290
                                  line)
291
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
292
        from annotate.gannotate import GAnnotateWindow
293
        from annotate.config import GAnnotateConfig
177 by Jelmer Vernooij
Register commands all at once.
294
        from bzrlib.bzrdir import BzrDir
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
295
161 by Aaron Bentley
Fix gannotate interaction with dirstate
296
        wt, br, path = BzrDir.open_containing_tree_or_branch(filename)
297
        if wt is not None:
298
            tree = wt
299
        else:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
300
            tree = br.basis_tree()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
301
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
302
        file_id = tree.path2id(path)
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
303
304
        if file_id is None:
305
            raise NotVersionedError(filename)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
306
        if revision is not None:
307
            if len(revision) != 1:
308
                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
309
            revision_id = revision[0].in_history(br).rev_id
310
            tree = br.repository.revision_tree(revision_id)
66.2.1 by Aaron Bentley
Gannotate takes a revision argument
311
        else:
66.2.18 by Aaron Bentley
Gannotate works with branches, not just trees
312
            revision_id = getattr(tree, 'get_revision_id', lambda: None)()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
313
314
        window = GAnnotateWindow(all, plain)
315
        window.connect("destroy", lambda w: gtk.main_quit())
316
        window.set_title(path + " - gannotate")
317
        config = GAnnotateConfig(window)
318
        window.show()
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
319
        br.lock_read()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
320
        if wt is not None:
321
            wt.lock_read()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
322
        try:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
323
            window.annotate(tree, br, file_id)
161 by Aaron Bentley
Fix gannotate interaction with dirstate
324
            window.jump_to_line(line)
325
            gtk.main()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
326
        finally:
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
327
            br.unlock()
161 by Aaron Bentley
Fix gannotate interaction with dirstate
328
            if wt is not None:
329
                wt.unlock()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
330
331
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
332
333
class cmd_gcommit(GTKCommand):
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
334
    """GTK+ commit dialog
335
336
    Graphical user interface for committing revisions"""
337
    
145 by Jelmer Vernooij
Fix some strings, import.
338
    aliases = [ "gci" ]
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
339
    takes_args = []
340
    takes_options = []
341
342
    def run(self, filename=None):
93.1.17 by Alexander Belchenko
gcommit reworked again.
343
        import os
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
344
        self.open_display()
142 by Jelmer Vernooij
Move some files to the top-level directory, add first test.
345
        from commit import CommitDialog
93.1.17 by Alexander Belchenko
gcommit reworked again.
346
        from bzrlib.errors import (BzrCommandError,
347
                                   NotBranchError,
178 by Jelmer Vernooij
Remove unneeded imports.
348
                                   NoWorkingTree)
93.1.17 by Alexander Belchenko
gcommit reworked again.
349
350
        wt = None
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
351
        br = None
93.1.17 by Alexander Belchenko
gcommit reworked again.
352
        try:
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
353
            (wt, path) = workingtree.WorkingTree.open_containing(filename)
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
354
            br = wt.branch
93.1.17 by Alexander Belchenko
gcommit reworked again.
355
        except NoWorkingTree, e:
356
            path = e.base
195.2.1 by Szilveszter Farkas (Phanatic)
NotBranchError exception shouldn't be handled. (Fixes: #113394)
357
            (br, path) = branch.Branch.open_containing(path)
93.1.17 by Alexander Belchenko
gcommit reworked again.
358
157.2.1 by Vincent Ladeuil
Rename variable 'branch' to 'br' where it conflicts with 'branch' module
359
        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'.
360
        commit.run()
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
361
362
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
363
364
class cmd_gstatus(GTKCommand):
157 by Jelmer Vernooij
Add gstatus command.
365
    """GTK+ status dialog
366
367
    Graphical user interface for showing status 
368
    information."""
369
    
370
    aliases = [ "gst" ]
371
    takes_args = ['PATH?']
372
    takes_options = []
373
374
    def run(self, path='.'):
375
        import os
184 by Jelmer Vernooij
Fix gstatus
376
        gtk = self.open_display()
157 by Jelmer Vernooij
Add gstatus command.
377
        from status import StatusDialog
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
378
        (wt, wt_path) = workingtree.WorkingTree.open_containing(path)
157 by Jelmer Vernooij
Add gstatus command.
379
        status = StatusDialog(wt, wt_path)
380
        status.connect("destroy", gtk.main_quit)
381
        status.run()
382
383
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
384
385
class cmd_gconflicts(GTKCommand):
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
386
    """ GTK+ push.
387
    
388
    """
389
    def run(self):
157.1.5 by Aaron Bentley
Use lazy_import to reduce rocks time by .015s
390
        (wt, path) = workingtree.WorkingTree.open_containing('.')
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
391
        self.open_display()
126.1.24 by Szilveszter Farkas (Phanatic)
Implemented Conflicts dialog. Added gconflicts command.
392
        from bzrlib.plugins.gtk.conflicts import ConflictsDialog
393
        dialog = ConflictsDialog(wt)
394
        dialog.run()
395
157 by Jelmer Vernooij
Add gstatus command.
396
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
397
398
class cmd_gpreferences(GTKCommand):
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
399
    """ GTK+ preferences dialog.
400
401
    """
402
    def run(self):
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
403
        self.open_display()
171 by Jelmer Vernooij
Initial work on a preferences dialog in GTK+, including a list of plugins with metadata browser.
404
        from bzrlib.plugins.gtk.preferences import PreferencesWindow
405
        dialog = PreferencesWindow()
406
        dialog.run()
407
408
175 by Jelmer Vernooij
Add very simple gmissing command.
409
410
class cmd_gmissing(Command):
411
    """ GTK+ missing revisions dialog.
412
413
    """
414
    takes_args = ["other_branch?"]
415
    def run(self, other_branch=None):
416
        pygtk = import_pygtk()
417
        try:
418
            import gtk
419
        except RuntimeError, e:
420
            if str(e) == "could not open display":
421
                raise NoDisplayError
422
423
        from bzrlib.plugins.gtk.missing import MissingWindow
424
        from bzrlib.branch import Branch
425
426
        local_branch = Branch.open_containing(".")[0]
427
        if other_branch is None:
428
            other_branch = local_branch.get_parent()
429
            
430
            if other_branch is None:
431
                raise errors.BzrCommandError("No peer location known or specified.")
432
        remote_branch = Branch.open_containing(other_branch)[0]
433
        set_ui_factory()
434
        local_branch.lock_read()
435
        try:
436
            remote_branch.lock_read()
437
            try:
438
                dialog = MissingWindow(local_branch, remote_branch)
439
                dialog.run()
440
            finally:
441
                remote_branch.unlock()
442
        finally:
443
            local_branch.unlock()
444
177 by Jelmer Vernooij
Register commands all at once.
445
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
446
class cmd_ginit(GTKCommand):
447
    def run(self):
448
        self.open_display()
449
        from initialize import InitDialog
450
        dialog = InitDialog(os.path.abspath(os.path.curdir))
451
        dialog.run()
452
453
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
454
class cmd_gtags(GTKCommand):
455
    def run(self):
456
        br = branch.Branch.open_containing('.')[0]
457
        
458
        gtk = self.open_display()
459
        from tags import TagsWindow
460
        window = TagsWindow(br)
461
        window.show()
462
        gtk.main()
463
464
177 by Jelmer Vernooij
Register commands all at once.
465
commands = [
466
    cmd_gmissing, 
467
    cmd_gpreferences, 
468
    cmd_gconflicts, 
469
    cmd_gstatus,
470
    cmd_gcommit, 
471
    cmd_gannotate, 
472
    cmd_visualise, 
473
    cmd_gdiff,
474
    cmd_gpush, 
475
    cmd_gcheckout, 
188.1.1 by Szilveszter Farkas (Phanatic)
Inital implementation of the Initialize dialog. Not fully functional yet.
476
    cmd_gbranch,
190.1.1 by Szilveszter Farkas (Phanatic)
Added 'gtags' command and basic Tags window (just a skeleton).
477
    cmd_ginit,
478
    cmd_gtags
177 by Jelmer Vernooij
Register commands all at once.
479
    ]
480
481
for cmd in commands:
482
    register_command(cmd)
175 by Jelmer Vernooij
Add very simple gmissing command.
483
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
484
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
485
class cmd_commit_notify(GTKCommand):
486
    """Run the bzr commit notifier.
487
488
    This is a background program which will pop up a notification on the users
489
    screen when a commit occurs.
490
    """
491
492
    def run(self):
211 by Jelmer Vernooij
Move notification area code into separate file.
493
        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.
494
        gtk = self.open_display()
211 by Jelmer Vernooij
Move notification area code into separate file.
495
        menu = NotifyPopupMenu()
496
        icon = gtk.status_icon_new_from_file("bzr-icon-64.png")
497
        icon.connect('popup-menu', menu.display)
210 by Jelmer Vernooij
Add notification area icon for commit-notify.
498
173.1.3 by Robert Collins
Add new command 'commit-notify' to listen for commits on dbus and show them via pynotify.
499
        import cgi
500
        import dbus
501
        import dbus.service
502
        import pynotify
503
        from bzrlib.bzrdir import BzrDir
504
        from bzrlib import errors
505
        from bzrlib.osutils import format_date
506
        from bzrlib.transport import get_transport
507
        if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
508
            import dbus.glib
509
        from bzrlib.plugins.dbus import activity
510
        bus = dbus.SessionBus()
511
        # get the object so we can subscribe to callbacks from it.
512
        broadcast_service = bus.get_object(
513
            activity.Broadcast.DBUS_NAME,
514
            activity.Broadcast.DBUS_PATH)
211 by Jelmer Vernooij
Move notification area code into separate file.
515
182.1.1 by Robert Collins
Update commit-notify to use new dbus api, and show remote URL's.
516
        def catch_branch(revision_id, urls):
517
            # TODO: show all the urls, or perhaps choose the 'best'.
518
            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.
519
            try:
520
                if isinstance(revision_id, unicode):
521
                    revision_id = revision_id.encode('utf8')
522
                transport = get_transport(url)
523
                a_dir = BzrDir.open_from_transport(transport)
524
                branch = a_dir.open_branch()
525
                revno = branch.revision_id_to_revno(revision_id)
526
                revision = branch.repository.get_revision(revision_id)
527
                summary = 'New revision %d in %s' % (revno, url)
528
                body  = 'Committer: %s\n' % revision.committer
529
                body += 'Date: %s\n' % format_date(revision.timestamp,
530
                    revision.timezone)
531
                body += '\n'
532
                body += revision.message
533
                body = cgi.escape(body)
534
                nw = pynotify.Notification(summary, body)
208.2.2 by Robert Collins
Add inspect window to bzr commity-notify.
535
                def start_viz(notification=None, action=None, data=None):
536
                    """Start the viz program."""
537
                    pp = start_viz_window(branch, revision_id)
538
                    pp.show()
208.2.3 by Robert Collins
Add a Branch button to commit-notify.
539
                def start_branch(notification=None, action=None, data=None):
540
                    """Start a Branch dialog"""
541
                    from bzrlib.plugins.gtk.branch import BranchDialog
542
                    bd = BranchDialog(remote_path=url)
543
                    bd.run()
208.2.4 by Robert Collins
Unbreak inspect of commits due to misunderstanding of pynotify api.
544
                nw.add_action("inspect", "Inspect", start_viz, None)
545
                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.
546
                nw.set_timeout(5000)
547
                nw.show()
548
            except Exception, e:
549
                print e
550
                raise
551
        broadcast_service.connect_to_signal("Revision", catch_branch,
552
            dbus_interface=activity.Broadcast.DBUS_INTERFACE)
553
        pynotify.init("bzr commit-notify")
554
        gtk.main()
555
556
register_command(cmd_commit_notify)
557
558
152 by Jelmer Vernooij
Cleanup some more code.
559
import gettext
560
gettext.install('olive-gtk')
561
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
562
55.1.2 by Jelmer Vernooij
Move commands to top-level __init__
563
class NoDisplayError(BzrCommandError):
564
    """gtk could not find a proper display"""
565
566
    def __str__(self):
133 by Jelmer Vernooij
Actually use the ui factory.
567
        return "No DISPLAY. Unable to run GTK+ application."
568
173.1.2 by Robert Collins
Minor refactoring of __init__ to have less duplication.
569
140 by Jelmer Vernooij
add framework for tests.
570
def test_suite():
571
    from unittest import TestSuite
572
    import tests
163 by Aaron Bentley
Prevent test suite from causing default-encoding changes
573
    import sys
574
    default_encoding = sys.getdefaultencoding()
575
    try:
576
        result = TestSuite()
577
        result.addTest(tests.test_suite())
578
    finally:
170.1.2 by Aaron Bentley
Test suite only fixes encoding if it's changed. Fixes test_selftest bug.
579
        if sys.getdefaultencoding() != default_encoding:
580
            reload(sys)
581
            sys.setdefaultencoding(default_encoding)
140 by Jelmer Vernooij
add framework for tests.
582
    return result