/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: Mark Lee
  • Date: 2009-07-11 18:39:14 UTC
  • mto: This revision was merged to the branch mainline in revision 661.
  • Revision ID: bzr@lazymalevolence.com-20090711183914-zuii3et5skiv2njo
Re-ignore credits.pickle.

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 
11
11
from cStringIO import StringIO
12
12
 
13
 
from gi.repository import Gtk
14
 
from gi.repository import Pango
 
13
import pygtk
 
14
pygtk.require("2.0")
 
15
import gtk
 
16
import pango
15
17
import os
16
18
import re
17
19
import sys
18
 
import inspect
19
 
try:
20
 
    from xml.etree.ElementTree import Element, SubElement, tostring
21
 
except ImportError:
22
 
    from elementtree.ElementTree import Element, SubElement, tostring
 
20
from xml.etree.ElementTree import Element, SubElement, tostring
23
21
 
24
22
try:
25
 
    from gi.repository import GtkSource
 
23
    import gtksourceview2
26
24
    have_gtksourceview = True
27
25
except ImportError:
28
26
    have_gtksourceview = False
29
27
try:
30
 
    from gi.repository import GConf
 
28
    import gconf
31
29
    have_gconf = True
32
30
except ImportError:
33
31
    have_gconf = False
34
32
 
35
33
from bzrlib import (
36
 
    errors,
37
34
    merge as _mod_merge,
38
35
    osutils,
 
36
    progress,
39
37
    urlutils,
40
38
    workingtree,
41
39
)
42
 
from bzrlib.diff import show_diff_trees
 
40
from bzrlib.diff import show_diff_trees, internal_diff
 
41
from bzrlib.errors import NoSuchFile
43
42
from bzrlib.patches import parse_patches
44
43
from bzrlib.trace import warning
45
 
from bzrlib.plugins.gtk.dialog import (
46
 
    error_dialog,
47
 
    info_dialog,
48
 
    warning_dialog,
49
 
    )
50
 
from bzrlib.plugins.gtk.i18n import _i18n
 
44
from bzrlib.plugins.gtk import _i18n
51
45
from bzrlib.plugins.gtk.window import Window
52
 
 
53
 
 
54
 
def fallback_guess_language(slm, content_type):
55
 
    for lang_id in slm.get_language_ids():
56
 
        lang = slm.get_language(lang_id)
57
 
        if "text/x-patch" in lang.get_mime_types():
58
 
            return lang
59
 
    return None
 
46
from dialog import error_dialog, info_dialog, warning_dialog
60
47
 
61
48
 
62
49
class SelectCancelled(Exception):
64
51
    pass
65
52
 
66
53
 
67
 
class DiffFileView(Gtk.ScrolledWindow):
 
54
class DiffFileView(gtk.ScrolledWindow):
68
55
    """Window for displaying diffs from a diff file"""
69
56
 
70
57
    def __init__(self):
71
 
        super(DiffFileView, self).__init__()
 
58
        gtk.ScrolledWindow.__init__(self)
72
59
        self.construct()
73
60
        self._diffs = {}
74
61
 
75
62
    def construct(self):
76
 
        self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
77
 
        self.set_shadow_type(Gtk.ShadowType.IN)
 
63
        self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 
64
        self.set_shadow_type(gtk.SHADOW_IN)
78
65
 
79
66
        if have_gtksourceview:
80
 
            self.buffer = GtkSource.Buffer()
81
 
            lang_manager = GtkSource.LanguageManager.get_default()
82
 
            language = lang_manager.guess_language(None, "text/x-patch")
 
67
            self.buffer = gtksourceview2.Buffer()
 
68
            slm = gtksourceview2.LanguageManager()
 
69
            gsl = slm.guess_language(content_type="text/x-patch")
83
70
            if have_gconf:
84
71
                self.apply_gedit_colors(self.buffer)
85
72
            self.apply_colordiff_colors(self.buffer)
86
 
            self.buffer.set_language(language)
 
73
            self.buffer.set_language(gsl)
87
74
            self.buffer.set_highlight_syntax(True)
88
75
 
89
 
            self.sourceview = GtkSource.View(buffer=self.buffer)
 
76
            self.sourceview = gtksourceview2.View(self.buffer)
90
77
        else:
91
 
            self.buffer = Gtk.TextBuffer()
92
 
            self.sourceview = Gtk.TextView(self.buffer)
 
78
            self.buffer = gtk.TextBuffer()
 
79
            self.sourceview = gtk.TextView(self.buffer)
93
80
 
94
81
        self.sourceview.set_editable(False)
95
 
        self.sourceview.modify_font(Pango.FontDescription("Monospace"))
 
82
        self.sourceview.modify_font(pango.FontDescription("Monospace"))
96
83
        self.add(self.sourceview)
97
84
        self.sourceview.show()
98
85
 
102
89
 
103
90
        This method needs the gconf module.
104
91
 
105
 
        :param buf: a GtkSource.Buffer object.
 
92
        :param buf: a gtksourceview2.Buffer object.
106
93
        """
107
94
        GEDIT_SCHEME_PATH = '/apps/gedit-2/preferences/editor/colors/scheme'
108
 
        GEDIT_USER_STYLES_PATH = os.path.expanduser('~/.gnome2/gedit/styles')
109
95
 
110
 
        client = GConf.Client.get_default()
 
96
        client = gconf.client_get_default()
111
97
        style_scheme_name = client.get_string(GEDIT_SCHEME_PATH)
112
98
        if style_scheme_name is not None:
113
 
            style_scheme_mgr = GtkSource.StyleSchemeManager()
114
 
            style_scheme_mgr.append_search_path(GEDIT_USER_STYLES_PATH)
115
 
            
116
 
            style_scheme = style_scheme_mgr.get_scheme(style_scheme_name)
117
 
            
118
 
            if style_scheme is not None:
119
 
                buf.set_style_scheme(style_scheme)
 
99
            style_scheme = gtksourceview2.StyleSchemeManager().get_scheme(style_scheme_name)
 
100
            
 
101
            buf.set_style_scheme(style_scheme)
120
102
 
121
103
    @classmethod
122
104
    def apply_colordiff_colors(klass, buf):
124
106
 
125
107
        Both ~/.colordiffrc and ~/.colordiffrc.bzr-gtk are read.
126
108
 
127
 
        :param buf: a "Diff" GtkSource.Buffer object.
 
109
        :param buf: a "Diff" gtksourceview2.Buffer object.
128
110
        """
129
 
        scheme_manager = GtkSource.StyleSchemeManager()
 
111
        scheme_manager = gtksourceview2.StyleSchemeManager()
130
112
        style_scheme = scheme_manager.get_scheme('colordiff')
131
113
        
132
114
        # if style scheme not found, we'll generate it from colordiffrc
250
232
    """This is the soft and chewy filling for a DiffWindow."""
251
233
 
252
234
    def __init__(self):
253
 
        super(DiffView, self).__init__()
 
235
        DiffFileView.__init__(self)
254
236
        self.rev_tree = None
255
237
        self.parent_tree = None
256
238
 
280
262
        self.buffer.set_text(decoded.encode('UTF-8'))
281
263
 
282
264
 
283
 
class DiffWidget(Gtk.HPaned):
 
265
class DiffWidget(gtk.HPaned):
284
266
    """Diff widget
285
267
 
286
268
    """
288
270
        super(DiffWidget, self).__init__()
289
271
 
290
272
        # The file hierarchy: a scrollable treeview
291
 
        scrollwin = Gtk.ScrolledWindow()
292
 
        scrollwin.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
293
 
        scrollwin.set_shadow_type(Gtk.ShadowType.IN)
 
273
        scrollwin = gtk.ScrolledWindow()
 
274
        scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
 
275
        scrollwin.set_shadow_type(gtk.SHADOW_IN)
294
276
        self.pack1(scrollwin)
295
277
        scrollwin.show()
296
278
        
297
 
        self.model = Gtk.TreeStore(str, str)
298
 
        self.treeview = Gtk.TreeView(model=self.model)
 
279
        self.model = gtk.TreeStore(str, str)
 
280
        self.treeview = gtk.TreeView(self.model)
299
281
        self.treeview.set_headers_visible(False)
300
282
        self.treeview.set_search_column(1)
301
283
        self.treeview.connect("cursor-changed", self._treeview_cursor_cb)
302
284
        scrollwin.add(self.treeview)
303
285
        self.treeview.show()
304
286
 
305
 
        cell = Gtk.CellRendererText()
 
287
        cell = gtk.CellRendererText()
306
288
        cell.set_property("width-chars", 20)
307
 
        column = Gtk.TreeViewColumn()
308
 
        column.pack_start(cell, True)
 
289
        column = gtk.TreeViewColumn()
 
290
        column.pack_start(cell, expand=True)
309
291
        column.add_attribute(cell, "text", 0)
310
292
        self.treeview.append_column(column)
311
293
 
381
363
                    tv_path = child.path
382
364
                    break
383
365
        if tv_path is None:
384
 
            raise errors.NoSuchFile(file_path)
385
 
        self.treeview.set_cursor(tv_path, None, False)
 
366
            raise NoSuchFile(file_path)
 
367
        self.treeview.set_cursor(tv_path)
386
368
        self.treeview.scroll_to_cell(tv_path)
387
369
 
388
370
    def _treeview_cursor_cb(self, *args):
399
381
    def _on_wraplines_toggled(self, widget=None, wrap=False):
400
382
        """Callback for when the wrap lines checkbutton is toggled"""
401
383
        if wrap or widget.get_active():
402
 
            self.diff_view.sourceview.set_wrap_mode(Gtk.WrapMode.WORD)
 
384
            self.diff_view.sourceview.set_wrap_mode(gtk.WRAP_WORD)
403
385
        else:
404
 
            self.diff_view.sourceview.set_wrap_mode(Gtk.WrapMode.NONE)
 
386
            self.diff_view.sourceview.set_wrap_mode(gtk.WRAP_NONE)
405
387
 
406
388
class DiffWindow(Window):
407
389
    """Diff window.
411
393
    """
412
394
 
413
395
    def __init__(self, parent=None, operations=None):
414
 
        super(DiffWindow, self).__init__(parent=parent)
 
396
        Window.__init__(self, parent)
415
397
        self.set_border_width(0)
416
398
        self.set_title("bzrk diff")
417
399
 
425
407
 
426
408
    def construct(self, operations):
427
409
        """Construct the window contents."""
428
 
        self.vbox = Gtk.VBox()
 
410
        self.vbox = gtk.VBox()
429
411
        self.add(self.vbox)
430
412
        self.vbox.show()
431
413
        self.diff = DiffWidget()
440
422
        
441
423
    
442
424
    def _get_menu_bar(self):
443
 
        menubar = Gtk.MenuBar()
 
425
        menubar = gtk.MenuBar()
444
426
        # View menu
445
 
        mb_view = Gtk.MenuItem.new_with_mnemonic(_i18n("_View"))
446
 
        mb_view_menu = Gtk.Menu()
447
 
        mb_view_wrapsource = Gtk.CheckMenuItem.new_with_mnemonic(
448
 
            _i18n("Wrap _Long Lines"))
 
427
        mb_view = gtk.MenuItem(_i18n("_View"))
 
428
        mb_view_menu = gtk.Menu()
 
429
        mb_view_wrapsource = gtk.CheckMenuItem(_i18n("Wrap _Long Lines"))
449
430
        mb_view_wrapsource.connect('activate', self.diff._on_wraplines_toggled)
450
431
        mb_view_wrapsource.show()
451
432
        mb_view_menu.append(mb_view_wrapsource)
463
444
        """
464
445
        if operations is None:
465
446
            return None
466
 
        hbox = Gtk.HButtonBox()
467
 
        hbox.set_layout(Gtk.ButtonBoxStyle.START)
 
447
        hbox = gtk.HButtonBox()
 
448
        hbox.set_layout(gtk.BUTTONBOX_START)
468
449
        for title, method in operations:
469
 
            merge_button = Gtk.Button(title)
 
450
            merge_button = gtk.Button(title)
470
451
            merge_button.show()
471
 
            merge_button.set_relief(Gtk.ReliefStyle.NONE)
 
452
            merge_button.set_relief(gtk.RELIEF_NONE)
472
453
            merge_button.connect("clicked", method)
473
454
            hbox.pack_start(merge_button, expand=False, fill=True)
474
455
        hbox.show()
475
456
        return hbox
476
457
 
477
458
    def _get_merge_target(self):
478
 
        d = Gtk.FileChooserDialog('Merge branch', self,
479
 
                                  Gtk.FileChooserAction.SELECT_FOLDER,
480
 
                                  buttons=(Gtk.STOCK_OK, Gtk.ResponseType.OK,
481
 
                                           Gtk.STOCK_CANCEL,
482
 
                                           Gtk.ResponseType.CANCEL,))
 
459
        d = gtk.FileChooserDialog('Merge branch', self,
 
460
                                  gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
 
461
                                  buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
 
462
                                           gtk.STOCK_CANCEL,
 
463
                                           gtk.RESPONSE_CANCEL,))
483
464
        try:
484
465
            result = d.run()
485
 
            if result != Gtk.ResponseType.OK:
 
466
            if result != gtk.RESPONSE_OK:
486
467
                raise SelectCancelled()
487
468
            return d.get_current_folder_uri()
488
469
        finally:
502
483
        error_dialog('Error', str(e))
503
484
 
504
485
    def _get_save_path(self, basename):
505
 
        d = Gtk.FileChooserDialog('Save As', self,
506
 
                                  Gtk.FileChooserAction.SAVE,
507
 
                                  buttons=(Gtk.STOCK_OK, Gtk.ResponseType.OK,
508
 
                                           Gtk.STOCK_CANCEL,
509
 
                                           Gtk.ResponseType.CANCEL,))
 
486
        d = gtk.FileChooserDialog('Save As', self,
 
487
                                  gtk.FILE_CHOOSER_ACTION_SAVE,
 
488
                                  buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK,
 
489
                                           gtk.STOCK_CANCEL,
 
490
                                           gtk.RESPONSE_CANCEL,))
510
491
        d.set_current_name(basename)
511
492
        try:
512
493
            result = d.run()
513
 
            if result != Gtk.ResponseType.OK:
 
494
            if result != gtk.RESPONSE_OK:
514
495
                raise SelectCancelled()
515
496
            return urlutils.local_path_from_url(d.get_uri())
516
497
        finally:
531
512
 
532
513
class DiffController(object):
533
514
 
534
 
    def __init__(self, path, patch, window=None, allow_dirty=False):
 
515
    def __init__(self, path, patch, window=None):
535
516
        self.path = path
536
517
        self.patch = patch
537
 
        self.allow_dirty = allow_dirty
538
518
        if window is None:
539
519
            window = DiffWindow(operations=self._provide_operations())
540
520
            self.initialize_window(window)
546
526
 
547
527
    def get_diff_sections(self):
548
528
        yield "Complete Diff", None, ''.join(self.patch)
549
 
        # allow_dirty was added to parse_patches in bzrlib 2.2b1
550
 
        if 'allow_dirty' in inspect.getargspec(parse_patches).args:
551
 
            patches = parse_patches(self.patch, allow_dirty=self.allow_dirty)
552
 
        else:
553
 
            patches = parse_patches(self.patch)
554
 
        for patch in patches:
 
529
        for patch in parse_patches(self.patch):
555
530
            oldname = patch.oldname.split('\t')[0]
556
531
            newname = patch.newname.split('\t')[0]
557
532
            yield oldname, newname, str(patch)
578
553
class MergeDirectiveController(DiffController):
579
554
 
580
555
    def __init__(self, path, directive, window=None):
581
 
        super(MergeDirectiveController, self).__init__(
582
 
            path, directive.patch.splitlines(True), window)
 
556
        DiffController.__init__(self, path, directive.patch.splitlines(True),
 
557
                                window)
583
558
        self.directive = directive
584
559
        self.merge_target = None
585
560
 
596
571
        tree.lock_write()
597
572
        try:
598
573
            try:
599
 
                if tree.has_changes():
600
 
                    raise errors.UncommittedChanges(tree)
601
 
                merger, verified = _mod_merge.Merger.from_mergeable(
602
 
                    tree, self.directive, pb=None)
 
574
                merger, verified = _mod_merge.Merger.from_mergeable(tree,
 
575
                    self.directive, progress.DummyProgress())
 
576
                merger.check_basis(True)
603
577
                merger.merge_type = _mod_merge.Merge3Merger
604
578
                conflict_count = merger.do_merge()
605
579
                merger.set_pending()