28 import Preferences |
29 import Preferences |
29 |
30 |
30 |
31 |
31 def sbsdiff(a, b, linenumberwidth=4): |
32 def sbsdiff(a, b, linenumberwidth=4): |
32 """ |
33 """ |
33 Compare two sequences of lines; generate the delta for display side by side. |
34 Compare two sequences of lines; generate the delta for display side by |
|
35 side. |
34 |
36 |
35 @param a first sequence of lines (list of strings) |
37 @param a first sequence of lines (list of strings) |
36 @param b second sequence of lines (list of strings) |
38 @param b second sequence of lines (list of strings) |
37 @param linenumberwidth width (in characters) of the linenumbers (integer) |
39 @param linenumberwidth width (in characters) of the linenumbers (integer) |
38 @return a generator yielding tuples of differences. The tuple is composed |
40 @return a generator yielding tuples of differences. The tuple is composed |
39 of strings as follows. |
41 of strings as follows. |
40 <ul> |
42 <ul> |
41 <li>opcode -- one of e, d, i, r for equal, delete, insert, replace</li> |
43 <li>opcode -- one of e, d, i, r for equal, delete, insert, |
|
44 replace</li> |
42 <li>lineno a -- linenumber of sequence a</li> |
45 <li>lineno a -- linenumber of sequence a</li> |
43 <li>line a -- line of sequence a</li> |
46 <li>line a -- line of sequence a</li> |
44 <li>lineno b -- linenumber of sequence b</li> |
47 <li>lineno b -- linenumber of sequence b</li> |
45 <li>line b -- line of sequence b</li> |
48 <li>line b -- line of sequence b</li> |
46 </ul> |
49 </ul> |
59 .replace('\1', "") |
62 .replace('\1', "") |
60 |
63 |
61 linenumberformat = "{{0:{0:d}d}}".format(linenumberwidth) |
64 linenumberformat = "{{0:{0:d}d}}".format(linenumberwidth) |
62 emptylineno = ' ' * linenumberwidth |
65 emptylineno = ' ' * linenumberwidth |
63 |
66 |
64 for (ln1, l1), (ln2, l2), flag in _mdiff(a, b, None, None, IS_CHARACTER_JUNK): |
67 for (ln1, l1), (ln2, l2), flag in _mdiff(a, b, None, None, |
|
68 IS_CHARACTER_JUNK): |
65 if not flag: |
69 if not flag: |
66 yield ('e', linenumberformat.format(ln1), l1, |
70 yield ('e', linenumberformat.format(ln1), l1, |
67 linenumberformat.format(ln2), l2) |
71 linenumberformat.format(ln2), l2) |
68 continue |
72 continue |
69 if ln2 == "" and l2 == "\n": |
73 if ln2 == "" and l2 == "\n": |
78 linenumberformat.format(ln2), l2) |
82 linenumberformat.format(ln2), l2) |
79 |
83 |
80 |
84 |
81 class CompareDialog(QWidget, Ui_CompareDialog): |
85 class CompareDialog(QWidget, Ui_CompareDialog): |
82 """ |
86 """ |
83 Class implementing a dialog to compare two files and show the result side by side. |
87 Class implementing a dialog to compare two files and show the result side |
|
88 by side. |
84 """ |
89 """ |
85 def __init__(self, files=[], parent=None): |
90 def __init__(self, files=[], parent=None): |
86 """ |
91 """ |
87 Constructor |
92 Constructor |
88 |
93 |
94 self.setupUi(self) |
99 self.setupUi(self) |
95 |
100 |
96 self.file1Completer = E5FileCompleter(self.file1Edit) |
101 self.file1Completer = E5FileCompleter(self.file1Edit) |
97 self.file2Completer = E5FileCompleter(self.file2Edit) |
102 self.file2Completer = E5FileCompleter(self.file2Edit) |
98 |
103 |
99 self.diffButton = \ |
104 self.diffButton = self.buttonBox.addButton( |
100 self.buttonBox.addButton(self.trUtf8("Compare"), QDialogButtonBox.ActionRole) |
105 self.trUtf8("Compare"), QDialogButtonBox.ActionRole) |
101 self.diffButton.setToolTip( |
106 self.diffButton.setToolTip( |
102 self.trUtf8("Press to perform the comparison of the two files")) |
107 self.trUtf8("Press to perform the comparison of the two files")) |
103 self.diffButton.setEnabled(False) |
108 self.diffButton.setEnabled(False) |
104 self.diffButton.setDefault(True) |
109 self.diffButton.setDefault(True) |
105 |
110 |
226 lines1 = f1.readlines() |
231 lines1 = f1.readlines() |
227 f1.close() |
232 f1.close() |
228 except IOError: |
233 except IOError: |
229 E5MessageBox.critical(self, |
234 E5MessageBox.critical(self, |
230 self.trUtf8("Compare Files"), |
235 self.trUtf8("Compare Files"), |
231 self.trUtf8("""<p>The file <b>{0}</b> could not be read.</p>""") |
236 self.trUtf8( |
|
237 """<p>The file <b>{0}</b> could not be read.</p>""") |
232 .format(filename1)) |
238 .format(filename1)) |
233 return |
239 return |
234 |
240 |
235 filename2 = Utilities.toNativeSeparators(self.file2Edit.text()) |
241 filename2 = Utilities.toNativeSeparators(self.file2Edit.text()) |
236 try: |
242 try: |
238 lines2 = f2.readlines() |
244 lines2 = f2.readlines() |
239 f2.close() |
245 f2.close() |
240 except IOError: |
246 except IOError: |
241 E5MessageBox.critical(self, |
247 E5MessageBox.critical(self, |
242 self.trUtf8("Compare Files"), |
248 self.trUtf8("Compare Files"), |
243 self.trUtf8("""<p>The file <b>{0}</b> could not be read.</p>""") |
249 self.trUtf8( |
|
250 """<p>The file <b>{0}</b> could not be read.</p>""") |
244 .format(filename2)) |
251 .format(filename2)) |
245 return |
252 return |
246 |
253 |
247 self.__compare(lines1, lines2) |
254 self.__compare(lines1, lines2) |
248 |
255 |
478 (list of two tuples of two strings) |
485 (list of two tuples of two strings) |
479 @param parent reference to the parent widget (QWidget) |
486 @param parent reference to the parent widget (QWidget) |
480 """ |
487 """ |
481 super(CompareWindow, self).__init__(parent) |
488 super(CompareWindow, self).__init__(parent) |
482 |
489 |
483 self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) |
490 self.setStyle(Preferences.getUI("Style"), |
|
491 Preferences.getUI("StyleSheet")) |
484 |
492 |
485 self.cw = CompareDialog(files, self) |
493 self.cw = CompareDialog(files, self) |
486 self.cw.installEventFilter(self) |
494 self.cw.installEventFilter(self) |
487 size = self.cw.size() |
495 size = self.cw.size() |
488 self.setCentralWidget(self.cw) |
496 self.setCentralWidget(self.cw) |