/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to diff.py

  • Committer: Curtis Hovey
  • Date: 2012-02-03 19:49:55 UTC
  • mto: This revision was merged to the branch mainline in revision 773.
  • Revision ID: sinzui.is@verizon.net-20120203194955-69jvr0mgu8igea0i
Updated bzr-notify to gtk3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 
11
11
from cStringIO import StringIO
12
12
 
 
13
import os
 
14
import re
13
15
import sys
14
16
import inspect
 
17
try:
 
18
    from xml.etree.ElementTree import (
 
19
        Element,
 
20
        SubElement,
 
21
        tostring,
 
22
        )
 
23
    Element, SubElement, tostring  # Hush PEP8 redefinition.
 
24
except ImportError:
 
25
    from elementtree.ElementTree import (
 
26
        Element,
 
27
        SubElement,
 
28
        tostring,
 
29
        )
15
30
 
16
31
from gi.repository import Gtk
17
32
from gi.repository import Pango
20
35
    have_gtksourceview = True
21
36
except ImportError:
22
37
    have_gtksourceview = False
 
38
try:
 
39
    from gi.repository import GConf
 
40
    have_gconf = True
 
41
except ImportError:
 
42
    have_gconf = False
23
43
 
24
44
from bzrlib import (
25
45
    errors,
30
50
    )
31
51
from bzrlib.diff import show_diff_trees
32
52
from bzrlib.patches import parse_patches
 
53
from bzrlib.trace import warning
33
54
from bzrlib.plugins.gtk.dialog import (
34
55
    error_dialog,
35
56
    info_dialog,
55
76
class DiffFileView(Gtk.ScrolledWindow):
56
77
    """Window for displaying diffs from a diff file"""
57
78
 
58
 
    SHOW_WIDGETS = True
59
 
 
60
79
    def __init__(self):
61
80
        super(DiffFileView, self).__init__()
62
81
        self.construct()
70
89
            self.buffer = GtkSource.Buffer()
71
90
            lang_manager = GtkSource.LanguageManager.get_default()
72
91
            language = lang_manager.guess_language(None, "text/x-patch")
 
92
            if have_gconf:
 
93
                self.apply_gedit_colors(self.buffer)
 
94
            self.apply_colordiff_colors(self.buffer)
73
95
            self.buffer.set_language(language)
74
96
            self.buffer.set_highlight_syntax(True)
 
97
 
75
98
            self.sourceview = GtkSource.View(buffer=self.buffer)
76
99
        else:
77
100
            self.buffer = Gtk.TextBuffer()
78
101
            self.sourceview = Gtk.TextView(self.buffer)
79
102
 
80
103
        self.sourceview.set_editable(False)
81
 
        self.sourceview.override_font(Pango.FontDescription("Monospace"))
 
104
        self.sourceview.modify_font(Pango.FontDescription("Monospace"))
82
105
        self.add(self.sourceview)
83
 
        if self.SHOW_WIDGETS:
84
 
            self.sourceview.show()
 
106
        self.sourceview.show()
 
107
 
 
108
    @staticmethod
 
109
    def apply_gedit_colors(buf):
 
110
        """Set style to that specified in gedit configuration.
 
111
 
 
112
        This method needs the gconf module.
 
113
 
 
114
        :param buf: a GtkSource.Buffer object.
 
115
        """
 
116
        GEDIT_SCHEME_PATH = '/apps/gedit-2/preferences/editor/colors/scheme'
 
117
        GEDIT_USER_STYLES_PATH = os.path.expanduser('~/.gnome2/gedit/styles')
 
118
 
 
119
        client = GConf.Client.get_default()
 
120
        style_scheme_name = client.get_string(GEDIT_SCHEME_PATH)
 
121
        if style_scheme_name is not None:
 
122
            style_scheme_mgr = GtkSource.StyleSchemeManager()
 
123
            style_scheme_mgr.append_search_path(GEDIT_USER_STYLES_PATH)
 
124
 
 
125
            style_scheme = style_scheme_mgr.get_scheme(style_scheme_name)
 
126
 
 
127
            if style_scheme is not None:
 
128
                buf.set_style_scheme(style_scheme)
 
129
 
 
130
    @classmethod
 
131
    def apply_colordiff_colors(klass, buf):
 
132
        """Set style colors for lang using the colordiff configuration file.
 
133
 
 
134
        Both ~/.colordiffrc and ~/.colordiffrc.bzr-gtk are read.
 
135
 
 
136
        :param buf: a "Diff" GtkSource.Buffer object.
 
137
        """
 
138
        scheme_manager = GtkSource.StyleSchemeManager()
 
139
        style_scheme = scheme_manager.get_scheme('colordiff')
 
140
 
 
141
        # if style scheme not found, we'll generate it from colordiffrc
 
142
        # TODO: reload if colordiffrc has changed.
 
143
        if style_scheme is None:
 
144
            colors = {}
 
145
 
 
146
            for f in ('~/.colordiffrc', '~/.colordiffrc.bzr-gtk'):
 
147
                f = os.path.expanduser(f)
 
148
                if os.path.exists(f):
 
149
                    try:
 
150
                        f = file(f)
 
151
                    except IOError, e:
 
152
                        warning('could not open file %s: %s' % (f, str(e)))
 
153
                    else:
 
154
                        colors.update(klass.parse_colordiffrc(f))
 
155
                        f.close()
 
156
 
 
157
            if not colors:
 
158
                # ~/.colordiffrc does not exist
 
159
                return
 
160
 
 
161
            mapping = {
 
162
                # map GtkSourceView2 scheme styles to colordiff names
 
163
                # since GSV is richer, accept new names for extra bits,
 
164
                # defaulting to old names if they're not present
 
165
                'diff:added-line': ['newtext'],
 
166
                'diff:removed-line': ['oldtext'],
 
167
                'diff:location': ['location', 'diffstuff'],
 
168
                'diff:file': ['file', 'diffstuff'],
 
169
                'diff:special-case': ['specialcase', 'diffstuff'],
 
170
            }
 
171
 
 
172
            converted_colors = {}
 
173
            for name, values in mapping.items():
 
174
                color = None
 
175
                for value in values:
 
176
                    color = colors.get(value, None)
 
177
                    if color is not None:
 
178
                        break
 
179
                if color is None:
 
180
                    continue
 
181
                converted_colors[name] = color
 
182
 
 
183
            # some xml magic to produce needed style scheme description
 
184
            e_style_scheme = Element('style-scheme')
 
185
            e_style_scheme.set('id', 'colordiff')
 
186
            e_style_scheme.set('_name', 'ColorDiff')
 
187
            e_style_scheme.set('version', '1.0')
 
188
            for name, color in converted_colors.items():
 
189
                style = SubElement(e_style_scheme, 'style')
 
190
                style.set('name', name)
 
191
                style.set('foreground', '#%s' % color)
 
192
 
 
193
            scheme_xml = tostring(e_style_scheme, 'UTF-8')
 
194
            if not os.path.exists(os.path.expanduser(
 
195
                '~/.local/share/gtksourceview-2.0/styles')):
 
196
                os.makedirs(os.path.expanduser(
 
197
                    '~/.local/share/gtksourceview-2.0/styles'))
 
198
            file(os.path.expanduser(
 
199
                '~/.local/share/gtksourceview-2.0/styles/colordiff.xml'),
 
200
                'w').write(scheme_xml)
 
201
 
 
202
            scheme_manager.force_rescan()
 
203
            style_scheme = scheme_manager.get_scheme('colordiff')
 
204
 
 
205
        buf.set_style_scheme(style_scheme)
 
206
 
 
207
    @staticmethod
 
208
    def parse_colordiffrc(fileobj):
 
209
        """Parse fileobj as a colordiff configuration file.
 
210
 
 
211
        :return: A dict with the key -> value pairs.
 
212
        """
 
213
        colors = {}
 
214
        for line in fileobj:
 
215
            if re.match(r'^\s*#', line):
 
216
                continue
 
217
            if '=' not in line:
 
218
                continue
 
219
            key, val = line.split('=', 1)
 
220
            colors[key.strip()] = val.strip()
 
221
        return colors
85
222
 
86
223
    def set_trees(self, rev_tree, parent_tree):
87
224
        self.rev_tree = rev_tree
298
435
    differences between two revisions on a branch.
299
436
    """
300
437
 
301
 
    SHOW_WIDGETS = True
302
 
 
303
438
    def __init__(self, parent=None, operations=None):
304
439
        super(DiffWindow, self).__init__(parent=parent)
305
440
        self.set_border_width(0)
306
 
        self.set_title("bzr diff")
 
441
        self.set_title("bzrk diff")
307
442
 
308
443
        # Use two thirds of the screen by default
309
444
        screen = self.get_screen()
317
452
        """Construct the window contents."""
318
453
        self.vbox = Gtk.VBox()
319
454
        self.add(self.vbox)
320
 
        if self.SHOW_WIDGETS:
321
 
            self.vbox.show()
 
455
        self.vbox.show()
322
456
        self.diff = DiffWidget()
323
457
        self.vbox.pack_end(self.diff, True, True, 0)
324
 
        if self.SHOW_WIDGETS:
325
 
            self.diff.show_all()
 
458
        self.diff.show_all()
326
459
        # Build after DiffWidget to connect signals
327
460
        menubar = self._get_menu_bar()
328
461
        self.vbox.pack_start(menubar, False, False, 0)
338
471
        mb_view_wrapsource = Gtk.CheckMenuItem.new_with_mnemonic(
339
472
            _i18n("Wrap _Long Lines"))
340
473
        mb_view_wrapsource.connect('activate', self.diff._on_wraplines_toggled)
 
474
        mb_view_wrapsource.show()
341
475
        mb_view_menu.append(mb_view_wrapsource)
 
476
        mb_view.show()
342
477
        mb_view.set_submenu(mb_view_menu)
 
478
        mb_view.show()
343
479
        menubar.append(mb_view)
344
 
        if self.SHOW_WIDGETS:
345
 
            menubar.show_all()
 
480
        menubar.show()
346
481
        return menubar
347
482
 
348
483
    def _get_button_bar(self, operations):
356
491
        hbox.set_layout(Gtk.ButtonBoxStyle.START)
357
492
        for title, method in operations:
358
493
            merge_button = Gtk.Button(title)
359
 
            if self.SHOW_WIDGETS:
360
 
                merge_button.show()
 
494
            merge_button.show()
361
495
            merge_button.set_relief(Gtk.ReliefStyle.NONE)
362
496
            merge_button.connect("clicked", method)
363
 
            hbox.pack_start(merge_button, False, True, 0)
364
 
        if self.SHOW_WIDGETS:
365
 
            hbox.show()
 
497
            hbox.pack_start(merge_button, expand=False, fill=True)
 
498
        hbox.show()
366
499
        return hbox
367
500
 
368
501
    def _get_merge_target(self):