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