/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: Szilveszter Farkas
  • Date: 2009-05-26 09:57:29 UTC
  • mto: (635.2.6 trunk)
  • mto: This revision was merged to the branch mainline in revision 639.
  • Revision ID: szilveszter.farkas@gmail.com-20090526095729-qjx9lpjm8yo5r658
Support gedit color schemes for gtksourceview2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: UTF-8 -*-
2
1
"""Difference window.
3
2
 
4
3
This module contains the code to manage the diff window which shows
5
4
the changes made between two revisions on a branch.
6
5
"""
7
6
 
8
 
__copyright__ = "Copyright © 2005 Canonical Ltd."
 
7
__copyright__ = "Copyright 2005 Canonical Ltd."
9
8
__author__    = "Scott James Remnant <scott@ubuntu.com>"
10
9
 
11
10
 
20
19
import sys
21
20
 
22
21
try:
23
 
    import gtksourceview
 
22
    import gtksourceview2
24
23
    have_gtksourceview = True
25
24
except ImportError:
26
25
    have_gtksourceview = False
64
63
        self.set_shadow_type(gtk.SHADOW_IN)
65
64
 
66
65
        if have_gtksourceview:
67
 
            self.buffer = gtksourceview.SourceBuffer()
68
 
            slm = gtksourceview.SourceLanguagesManager()
69
 
            gsl = slm.get_language_from_mime_type("text/x-patch")
 
66
            self.buffer = gtksourceview2.Buffer()
 
67
            slm = gtksourceview2.LanguageManager()
 
68
            gsl = slm.guess_language(content_type="text/x-patch")
70
69
            if have_gconf:
71
 
                self.apply_gedit_colors(gsl)
 
70
                self.apply_gedit_colors(self.buffer)
72
71
            self.apply_colordiff_colors(gsl)
73
72
            self.buffer.set_language(gsl)
74
 
            self.buffer.set_highlight(True)
 
73
            self.buffer.set_highlight_syntax(True)
75
74
 
76
 
            sourceview = gtksourceview.SourceView(self.buffer)
 
75
            self.sourceview = gtksourceview2.View(self.buffer)
77
76
        else:
78
77
            self.buffer = gtk.TextBuffer()
79
 
            sourceview = gtk.TextView(self.buffer)
 
78
            self.sourceview = gtk.TextView(self.buffer)
80
79
 
81
 
        sourceview.set_editable(False)
82
 
        sourceview.modify_font(pango.FontDescription("Monospace"))
83
 
        self.add(sourceview)
84
 
        sourceview.show()
 
80
        self.sourceview.set_editable(False)
 
81
        self.sourceview.modify_font(pango.FontDescription("Monospace"))
 
82
        self.add(self.sourceview)
 
83
        self.sourceview.show()
85
84
 
86
85
    @staticmethod
87
 
    def apply_gedit_colors(lang):
88
 
        """Set style for lang to that specified in gedit configuration.
 
86
    def apply_gedit_colors(buf):
 
87
        """Set style to that specified in gedit configuration.
89
88
 
90
89
        This method needs the gconf module.
91
90
 
92
 
        :param lang: a gtksourceview.SourceLanguage object.
 
91
        :param buf: a gtksourceview2.Buffer object.
93
92
        """
94
 
        GEDIT_SYNTAX_PATH = '/apps/gedit-2/preferences/syntax_highlighting'
95
 
        GEDIT_LANG_PATH = GEDIT_SYNTAX_PATH + '/' + lang.get_id()
 
93
        GEDIT_SCHEME_PATH = '/apps/gedit-2/preferences/editor/colors/scheme'
96
94
 
97
95
        client = gconf.client_get_default()
98
 
        client.add_dir(GEDIT_LANG_PATH, gconf.CLIENT_PRELOAD_NONE)
99
 
 
100
 
        for tag in lang.get_tags():
101
 
            tag_id = tag.get_id()
102
 
            gconf_key = GEDIT_LANG_PATH + '/' + tag_id
103
 
            style_string = client.get_string(gconf_key)
104
 
 
105
 
            if style_string is None:
106
 
                continue
107
 
 
108
 
            # function to get a bool from a string that's either '0' or '1'
109
 
            string_bool = lambda x: bool(int(x))
110
 
 
111
 
            # style_string is a string like "2/#FFCCAA/#000000/0/1/0/0"
112
 
            # values are: mask, fg, bg, italic, bold, underline, strike
113
 
            # this packs them into (str_value, attr_name, conv_func) tuples
114
 
            items = zip(style_string.split('/'), ['mask', 'foreground',
115
 
                'background', 'italic', 'bold', 'underline', 'strikethrough' ],
116
 
                [ int, gtk.gdk.color_parse, gtk.gdk.color_parse, string_bool,
117
 
                    string_bool, string_bool, string_bool ]
118
 
            )
119
 
 
120
 
            style = gtksourceview.SourceTagStyle()
121
 
 
122
 
            # XXX The mask attribute controls whether the present values of
123
 
            # foreground and background color should in fact be used. Ideally
124
 
            # (and that's what gedit does), one could set all three attributes,
125
 
            # and let the TagStyle object figure out which colors to use.
126
 
            # However, in the GtkSourceview python bindings, the mask attribute
127
 
            # is read-only, and it's derived instead from the colors being
128
 
            # set or not. This means that we have to sometimes refrain from
129
 
            # setting fg or bg colors, depending on the value of the mask.
130
 
            # This code could go away if mask were writable.
131
 
            mask = int(items[0][0])
132
 
            if not (mask & 1): # GTK_SOURCE_TAG_STYLE_USE_BACKGROUND
133
 
                items[2:3] = []
134
 
            if not (mask & 2): # GTK_SOURCE_TAG_STYLE_USE_FOREGROUND
135
 
                items[1:2] = []
136
 
            items[0:1] = [] # skip the mask unconditionally
137
 
 
138
 
            for value, attr, func in items:
139
 
                try:
140
 
                    value = func(value)
141
 
                except ValueError:
142
 
                    warning('gconf key %s contains an invalid value: %s'
143
 
                            % gconf_key, value)
144
 
                else:
145
 
                    setattr(style, attr, value)
146
 
 
147
 
            lang.set_tag_style(tag_id, style)
 
96
        style_scheme_name = client.get_string(GEDIT_SCHEME_PATH)
 
97
        style_scheme = gtksourceview2.StyleSchemeManager().get_scheme(style_scheme_name)
 
98
        
 
99
        buf.set_style_scheme(style_scheme)
148
100
 
149
101
    @classmethod
150
102
    def apply_colordiff_colors(klass, lang):
152
104
 
153
105
        Both ~/.colordiffrc and ~/.colordiffrc.bzr-gtk are read.
154
106
 
155
 
        :param lang: a "Diff" gtksourceview.SourceLanguage object.
 
107
        :param lang: a "Diff" gtksourceview2.Language object.
156
108
        """
157
109
        colors = {}
158
110
 
195
147
            if color is None:
196
148
                continue
197
149
 
198
 
            style = gtksourceview.SourceTagStyle()
 
150
            style = gtksourceview2.Style()
199
151
            try:
200
152
                style.foreground = gtk.gdk.color_parse(color)
201
153
            except ValueError:
305
257
        scrollwin.set_shadow_type(gtk.SHADOW_IN)
306
258
        self.pack1(scrollwin)
307
259
        scrollwin.show()
308
 
 
 
260
        
309
261
        self.model = gtk.TreeStore(str, str)
310
262
        self.treeview = gtk.TreeView(self.model)
311
263
        self.treeview.set_headers_visible(False)
330
282
        # text view
331
283
 
332
284
    def set_diff_text_sections(self, sections):
333
 
        self.diff_view = DiffFileView()
 
285
        if getattr(self, 'diff_view', None) is None:
 
286
            self.diff_view = DiffFileView()
 
287
            self.pack2(self.diff_view)
334
288
        self.diff_view.show()
335
 
        self.pack2(self.diff_view)
336
289
        for oldname, newname, patch in sections:
337
290
            self.diff_view._diffs[newname] = str(patch)
338
291
            if newname is None:
346
299
        Compares the two trees and populates the window with the
347
300
        differences.
348
301
        """
349
 
        self.diff_view = DiffView()
350
 
        self.pack2(self.diff_view)
 
302
        if getattr(self, 'diff_view', None) is None:
 
303
            self.diff_view = DiffView()
 
304
            self.pack2(self.diff_view)
351
305
        self.diff_view.show()
352
306
        self.diff_view.set_trees(rev_tree, parent_tree)
353
307
        self.rev_tree = rev_tree
380
334
                self.model.append(titer, [ path, path ])
381
335
 
382
336
        self.treeview.expand_all()
 
337
        self.diff_view.show_diff(None)
383
338
 
384
339
    def set_file(self, file_path):
385
340
        """Select the current file to display"""
402
357
            return
403
358
        elif specific_files == [ "" ]:
404
359
            specific_files = None
405
 
 
 
360
        
406
361
        self.diff_view.show_diff(specific_files)
407
 
 
 
362
    
 
363
    def _on_wraplines_toggled(self, widget=None, wrap=False):
 
364
        """Callback for when the wrap lines checkbutton is toggled"""
 
365
        if wrap or widget.get_active():
 
366
            self.diff_view.sourceview.set_wrap_mode(gtk.WRAP_WORD)
 
367
        else:
 
368
            self.diff_view.sourceview.set_wrap_mode(gtk.WRAP_NONE)
408
369
 
409
370
class DiffWindow(Window):
410
371
    """Diff window.
431
392
        self.vbox = gtk.VBox()
432
393
        self.add(self.vbox)
433
394
        self.vbox.show()
 
395
        self.diff = DiffWidget()
 
396
        self.vbox.pack_end(self.diff, True, True, 0)
 
397
        self.diff.show_all()
 
398
        # Build after DiffWidget to connect signals
 
399
        menubar = self._get_menu_bar()
 
400
        self.vbox.pack_start(menubar, False, False, 0)
434
401
        hbox = self._get_button_bar(operations)
435
402
        if hbox is not None:
436
 
            self.vbox.pack_start(hbox, expand=False, fill=True)
437
 
        self.diff = DiffWidget()
438
 
        self.vbox.add(self.diff)
439
 
        self.diff.show_all()
440
 
 
 
403
            self.vbox.pack_start(hbox, False, True, 0)
 
404
        
 
405
    
 
406
    def _get_menu_bar(self):
 
407
        menubar = gtk.MenuBar()
 
408
        # View menu
 
409
        mb_view = gtk.MenuItem(_i18n("_View"))
 
410
        mb_view_menu = gtk.Menu()
 
411
        mb_view_wrapsource = gtk.CheckMenuItem(_i18n("Wrap _Long Lines"))
 
412
        mb_view_wrapsource.connect('activate', self.diff._on_wraplines_toggled)
 
413
        mb_view_wrapsource.show()
 
414
        mb_view_menu.append(mb_view_wrapsource)
 
415
        mb_view.show()
 
416
        mb_view.set_submenu(mb_view_menu)
 
417
        mb_view.show()
 
418
        menubar.append(mb_view)
 
419
        menubar.show()
 
420
        return menubar
 
421
    
441
422
    def _get_button_bar(self, operations):
442
423
        """Return a button bar to use.
443
424
 
606
587
    renamed_and_modified = 'renamed and modified'
607
588
    modified = 'modified'
608
589
    kind_changed = 'kind changed'
 
590
    missing = 'missing'
609
591
 
610
592
    # TODO: Handle metadata changes
611
593
 
626
608
                    source_marker = ''
627
609
                else:
628
610
                    source_marker = osutils.kind_marker(kinds[0])
 
611
 
629
612
                if kinds[1] is None:
630
 
                    assert kinds[0] is not None
631
 
                    marker = osutils.kind_marker(kinds[0])
 
613
                    if kinds[0] is None:
 
614
                        # We assume bzr will flag only files in that case,
 
615
                        # there may be a bzr bug there as only files seems to
 
616
                        # not receive any kind.
 
617
                        marker = osutils.kind_marker('file')
 
618
                    else:
 
619
                        marker = osutils.kind_marker(kinds[0])
632
620
                else:
633
621
                    marker = osutils.kind_marker(kinds[1])
634
622
 
636
624
                if real_path is None:
637
625
                    real_path = paths[0]
638
626
                assert real_path is not None
639
 
                display_path = real_path + marker
640
627
 
641
628
                present_source = versioned[0] and kinds[0] is not None
642
629
                present_target = versioned[1] and kinds[1] is not None
643
630
 
644
 
                if present_source != present_target:
 
631
                if kinds[0] is None and kinds[1] is None:
 
632
                    change_type = missing
 
633
                    display_path = real_path + marker
 
634
                elif present_source != present_target:
645
635
                    if present_target:
646
636
                        change_type = added
647
637
                    else:
648
638
                        assert present_source
649
639
                        change_type = removed
 
640
                    display_path = real_path + marker
650
641
                elif names[0] != names[1] or parent_ids[0] != parent_ids[1]:
651
642
                    # Renamed
652
643
                    if changed_content or executables[0] != executables[1]:
660
651
                    change_type = kind_changed
661
652
                    display_path = (paths[0] + source_marker
662
653
                                    + ' => ' + paths[1] + marker)
663
 
                elif changed_content is True or executables[0] != executables[1]:
 
654
                elif changed_content or executables[0] != executables[1]:
664
655
                    change_type = modified
 
656
                    display_path = real_path + marker
665
657
                else:
666
658
                    assert False, "How did we get here?"
667
659