47 """ |
47 """ |
48 # __IGNORE_WARNING_D234r__ |
48 # __IGNORE_WARNING_D234r__ |
49 def removeMarkers(line): |
49 def removeMarkers(line): |
50 """ |
50 """ |
51 Internal function to remove all diff markers. |
51 Internal function to remove all diff markers. |
52 |
52 |
53 @param line line to work on (string) |
53 @param line line to work on (string) |
54 @return line without diff markers (string) |
54 @return line without diff markers (string) |
55 """ |
55 """ |
56 return ( |
56 return ( |
57 line |
57 line.replace("\0+", "") |
58 .replace('\0+', "") |
58 .replace("\0-", "") |
59 .replace('\0-', "") |
59 .replace("\0^", "") |
60 .replace('\0^', "") |
60 .replace("\1", "") |
61 .replace('\1', "") |
|
62 ) |
61 ) |
63 |
62 |
64 linenumberformat = "{{0:{0:d}d}}".format(linenumberwidth) |
63 linenumberformat = "{{0:{0:d}d}}".format(linenumberwidth) |
65 emptylineno = ' ' * linenumberwidth |
64 emptylineno = " " * linenumberwidth |
66 |
65 |
67 for (ln1, l1), (ln2, l2), flag in _mdiff(a, b, None, None, |
66 for (ln1, l1), (ln2, l2), flag in _mdiff(a, b, None, None, IS_CHARACTER_JUNK): |
68 IS_CHARACTER_JUNK): |
|
69 if not flag: |
67 if not flag: |
70 yield ('e', linenumberformat.format(ln1), l1, |
68 yield ( |
71 linenumberformat.format(ln2), l2) |
69 "e", |
|
70 linenumberformat.format(ln1), |
|
71 l1, |
|
72 linenumberformat.format(ln2), |
|
73 l2, |
|
74 ) |
72 continue |
75 continue |
73 if ln2 == "" and l2 in ("\r\n", "\n", "\r"): |
76 if ln2 == "" and l2 in ("\r\n", "\n", "\r"): |
74 yield ('d', linenumberformat.format(ln1), removeMarkers(l1), |
77 yield ( |
75 emptylineno, l2) |
78 "d", |
|
79 linenumberformat.format(ln1), |
|
80 removeMarkers(l1), |
|
81 emptylineno, |
|
82 l2, |
|
83 ) |
76 continue |
84 continue |
77 if ln1 == "" and l1 in ("\r\n", "\n", "\r"): |
85 if ln1 == "" and l1 in ("\r\n", "\n", "\r"): |
78 yield ('i', emptylineno, l1, |
86 yield ( |
79 linenumberformat.format(ln2), removeMarkers(l2)) |
87 "i", |
|
88 emptylineno, |
|
89 l1, |
|
90 linenumberformat.format(ln2), |
|
91 removeMarkers(l2), |
|
92 ) |
80 continue |
93 continue |
81 yield ('r', linenumberformat.format(ln1), l1, |
94 yield ("r", linenumberformat.format(ln1), l1, linenumberformat.format(ln2), l2) |
82 linenumberformat.format(ln2), l2) |
|
83 |
95 |
84 |
96 |
85 class CompareDialog(QWidget, Ui_CompareDialog): |
97 class CompareDialog(QWidget, Ui_CompareDialog): |
86 """ |
98 """ |
87 Class implementing a dialog to compare two files and show the result side |
99 Class implementing a dialog to compare two files and show the result side |
88 by side. |
100 by side. |
89 """ |
101 """ |
|
102 |
90 def __init__(self, files=None, parent=None): |
103 def __init__(self, files=None, parent=None): |
91 """ |
104 """ |
92 Constructor |
105 Constructor |
93 |
106 |
94 @param files list of files to compare and their label |
107 @param files list of files to compare and their label |
95 (list of two tuples of two strings) |
108 (list of two tuples of two strings) |
96 @param parent parent widget (QWidget) |
109 @param parent parent widget (QWidget) |
97 """ |
110 """ |
98 super().__init__(parent) |
111 super().__init__(parent) |
99 self.setupUi(self) |
112 self.setupUi(self) |
100 |
113 |
101 if files is None: |
114 if files is None: |
102 files = [] |
115 files = [] |
103 |
116 |
104 self.file1Picker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
117 self.file1Picker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
105 self.file2Picker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
118 self.file2Picker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
106 |
119 |
107 self.diffButton = self.buttonBox.addButton( |
120 self.diffButton = self.buttonBox.addButton( |
108 self.tr("Compare"), QDialogButtonBox.ButtonRole.ActionRole) |
121 self.tr("Compare"), QDialogButtonBox.ButtonRole.ActionRole |
|
122 ) |
109 self.diffButton.setToolTip( |
123 self.diffButton.setToolTip( |
110 self.tr("Press to perform the comparison of the two files")) |
124 self.tr("Press to perform the comparison of the two files") |
|
125 ) |
111 self.diffButton.setEnabled(False) |
126 self.diffButton.setEnabled(False) |
112 self.diffButton.setDefault(True) |
127 self.diffButton.setDefault(True) |
113 |
128 |
114 self.firstButton.setIcon(UI.PixmapCache.getIcon("2uparrow")) |
129 self.firstButton.setIcon(UI.PixmapCache.getIcon("2uparrow")) |
115 self.upButton.setIcon(UI.PixmapCache.getIcon("1uparrow")) |
130 self.upButton.setIcon(UI.PixmapCache.getIcon("1uparrow")) |
116 self.downButton.setIcon(UI.PixmapCache.getIcon("1downarrow")) |
131 self.downButton.setIcon(UI.PixmapCache.getIcon("1downarrow")) |
117 self.lastButton.setIcon(UI.PixmapCache.getIcon("2downarrow")) |
132 self.lastButton.setIcon(UI.PixmapCache.getIcon("2downarrow")) |
118 |
133 |
119 self.totalLabel.setText(self.tr('Total: {0}').format(0)) |
134 self.totalLabel.setText(self.tr("Total: {0}").format(0)) |
120 self.changedLabel.setText(self.tr('Changed: {0}').format(0)) |
135 self.changedLabel.setText(self.tr("Changed: {0}").format(0)) |
121 self.addedLabel.setText(self.tr('Added: {0}').format(0)) |
136 self.addedLabel.setText(self.tr("Added: {0}").format(0)) |
122 self.deletedLabel.setText(self.tr('Deleted: {0}').format(0)) |
137 self.deletedLabel.setText(self.tr("Deleted: {0}").format(0)) |
123 |
138 |
124 self.updateInterval = 20 # update every 20 lines |
139 self.updateInterval = 20 # update every 20 lines |
125 |
140 |
126 self.vsb1 = self.contents_1.verticalScrollBar() |
141 self.vsb1 = self.contents_1.verticalScrollBar() |
127 self.hsb1 = self.contents_1.horizontalScrollBar() |
142 self.hsb1 = self.contents_1.horizontalScrollBar() |
128 self.vsb2 = self.contents_2.verticalScrollBar() |
143 self.vsb2 = self.contents_2.verticalScrollBar() |
129 self.hsb2 = self.contents_2.horizontalScrollBar() |
144 self.hsb2 = self.contents_2.horizontalScrollBar() |
130 |
145 |
131 self.on_synchronizeCheckBox_toggled(True) |
146 self.on_synchronizeCheckBox_toggled(True) |
132 |
147 |
133 self.__generateFormats() |
148 self.__generateFormats() |
134 |
149 |
135 # connect some of our widgets explicitly |
150 # connect some of our widgets explicitly |
136 self.file1Picker.textChanged.connect(self.__fileChanged) |
151 self.file1Picker.textChanged.connect(self.__fileChanged) |
137 self.file2Picker.textChanged.connect(self.__fileChanged) |
152 self.file2Picker.textChanged.connect(self.__fileChanged) |
138 self.vsb1.valueChanged.connect(self.__scrollBarMoved) |
153 self.vsb1.valueChanged.connect(self.__scrollBarMoved) |
139 self.vsb1.valueChanged.connect(self.vsb2.setValue) |
154 self.vsb1.valueChanged.connect(self.vsb2.setValue) |
140 self.vsb2.valueChanged.connect(self.vsb1.setValue) |
155 self.vsb2.valueChanged.connect(self.vsb1.setValue) |
141 |
156 |
142 self.diffParas = [] |
157 self.diffParas = [] |
143 self.currentDiffPos = -1 |
158 self.currentDiffPos = -1 |
144 |
159 |
145 self.markerPattern = r"\0\+|\0\^|\0\-" |
160 self.markerPattern = r"\0\+|\0\^|\0\-" |
146 |
161 |
147 if len(files) == 2: |
162 if len(files) == 2: |
148 self.filesGroup.hide() |
163 self.filesGroup.hide() |
149 self.file1Picker.setText(files[0][1]) |
164 self.file1Picker.setText(files[0][1]) |
150 self.file2Picker.setText(files[1][1]) |
165 self.file2Picker.setText(files[1][1]) |
151 self.file1Label.setText(files[0][0]) |
166 self.file1Label.setText(files[0][0]) |
153 self.diffButton.hide() |
168 self.diffButton.hide() |
154 QTimer.singleShot(0, self.on_diffButton_clicked) |
169 QTimer.singleShot(0, self.on_diffButton_clicked) |
155 else: |
170 else: |
156 self.file1Label.hide() |
171 self.file1Label.hide() |
157 self.file2Label.hide() |
172 self.file2Label.hide() |
158 |
173 |
159 def __generateFormats(self): |
174 def __generateFormats(self): |
160 """ |
175 """ |
161 Private method to generate the various text formats. |
176 Private method to generate the various text formats. |
162 """ |
177 """ |
163 font = Preferences.getEditorOtherFonts("MonospacedFont") |
178 font = Preferences.getEditorOtherFonts("MonospacedFont") |
164 self.contents_1.setFontFamily(font.family()) |
179 self.contents_1.setFontFamily(font.family()) |
165 self.contents_1.setFontPointSize(font.pointSize()) |
180 self.contents_1.setFontPointSize(font.pointSize()) |
166 self.contents_2.setFontFamily(font.family()) |
181 self.contents_2.setFontFamily(font.family()) |
167 self.contents_2.setFontPointSize(font.pointSize()) |
182 self.contents_2.setFontPointSize(font.pointSize()) |
168 self.fontHeight = QFontMetrics(self.contents_1.currentFont()).height() |
183 self.fontHeight = QFontMetrics(self.contents_1.currentFont()).height() |
169 |
184 |
170 self.cNormalFormat = self.contents_1.currentCharFormat() |
185 self.cNormalFormat = self.contents_1.currentCharFormat() |
171 self.cInsertedFormat = self.contents_1.currentCharFormat() |
186 self.cInsertedFormat = self.contents_1.currentCharFormat() |
172 self.cInsertedFormat.setBackground( |
187 self.cInsertedFormat.setBackground( |
173 QBrush(Preferences.getDiffColour("AddedColor"))) |
188 QBrush(Preferences.getDiffColour("AddedColor")) |
|
189 ) |
174 self.cDeletedFormat = self.contents_1.currentCharFormat() |
190 self.cDeletedFormat = self.contents_1.currentCharFormat() |
175 self.cDeletedFormat.setBackground( |
191 self.cDeletedFormat.setBackground( |
176 QBrush(Preferences.getDiffColour("RemovedColor"))) |
192 QBrush(Preferences.getDiffColour("RemovedColor")) |
|
193 ) |
177 self.cReplacedFormat = self.contents_1.currentCharFormat() |
194 self.cReplacedFormat = self.contents_1.currentCharFormat() |
178 self.cReplacedFormat.setBackground( |
195 self.cReplacedFormat.setBackground( |
179 QBrush(Preferences.getDiffColour("ReplacedColor"))) |
196 QBrush(Preferences.getDiffColour("ReplacedColor")) |
180 |
197 ) |
|
198 |
181 def show(self, filename=None): |
199 def show(self, filename=None): |
182 """ |
200 """ |
183 Public slot to show the dialog. |
201 Public slot to show the dialog. |
184 |
202 |
185 @param filename name of a file to use as the first file (string) |
203 @param filename name of a file to use as the first file (string) |
186 """ |
204 """ |
187 if filename: |
205 if filename: |
188 self.file1Picker.setText(filename) |
206 self.file1Picker.setText(filename) |
189 super().show() |
207 super().show() |
190 |
208 |
191 def __appendText(self, pane, linenumber, line, charFormat, |
209 def __appendText(self, pane, linenumber, line, charFormat, interLine=False): |
192 interLine=False): |
|
193 """ |
210 """ |
194 Private method to append text to the end of the contents pane. |
211 Private method to append text to the end of the contents pane. |
195 |
212 |
196 @param pane text edit widget to append text to (QTextedit) |
213 @param pane text edit widget to append text to (QTextedit) |
197 @param linenumber number of line to insert (string) |
214 @param linenumber number of line to insert (string) |
198 @param line text to insert (string) |
215 @param line text to insert (string) |
199 @param charFormat text format to be used (QTextCharFormat) |
216 @param charFormat text format to be used (QTextCharFormat) |
200 @param interLine flag indicating interline changes (boolean) |
217 @param interLine flag indicating interline changes (boolean) |
242 lines1 = f1.readlines() |
259 lines1 = f1.readlines() |
243 except OSError: |
260 except OSError: |
244 EricMessageBox.critical( |
261 EricMessageBox.critical( |
245 self, |
262 self, |
246 self.tr("Compare Files"), |
263 self.tr("Compare Files"), |
247 self.tr( |
264 self.tr("""<p>The file <b>{0}</b> could not be read.</p>""").format( |
248 """<p>The file <b>{0}</b> could not be read.</p>""") |
265 filename1 |
249 .format(filename1)) |
266 ), |
|
267 ) |
250 return |
268 return |
251 |
269 |
252 filename2 = self.file2Picker.text() |
270 filename2 = self.file2Picker.text() |
253 try: |
271 try: |
254 with open(filename2, "r", encoding="utf-8") as f2: |
272 with open(filename2, "r", encoding="utf-8") as f2: |
255 lines2 = f2.readlines() |
273 lines2 = f2.readlines() |
256 except OSError: |
274 except OSError: |
257 EricMessageBox.critical( |
275 EricMessageBox.critical( |
258 self, |
276 self, |
259 self.tr("Compare Files"), |
277 self.tr("Compare Files"), |
260 self.tr( |
278 self.tr("""<p>The file <b>{0}</b> could not be read.</p>""").format( |
261 """<p>The file <b>{0}</b> could not be read.</p>""") |
279 filename2 |
262 .format(filename2)) |
280 ), |
|
281 ) |
263 return |
282 return |
264 |
283 |
265 self.__compare(lines1, lines2) |
284 self.__compare(lines1, lines2) |
266 |
285 |
267 def compare(self, lines1, lines2, name1="", name2=""): |
286 def compare(self, lines1, lines2, name1="", name2=""): |
268 """ |
287 """ |
269 Public method to compare two lists of text. |
288 Public method to compare two lists of text. |
270 |
289 |
271 @param lines1 text to compare against (string or list of strings) |
290 @param lines1 text to compare against (string or list of strings) |
272 @param lines2 text to compare (string or list of strings) |
291 @param lines2 text to compare (string or list of strings) |
273 @param name1 name to be shown for the first text (string) |
292 @param name1 name to be shown for the first text (string) |
274 @param name2 name to be shown for the second text (string) |
293 @param name2 name to be shown for the second text (string) |
275 """ |
294 """ |
280 self.file1Picker.setReadOnly(True) |
299 self.file1Picker.setReadOnly(True) |
281 self.file2Picker.setText(name2) |
300 self.file2Picker.setText(name2) |
282 self.file2Picker.setReadOnly(True) |
301 self.file2Picker.setReadOnly(True) |
283 self.diffButton.setEnabled(False) |
302 self.diffButton.setEnabled(False) |
284 self.diffButton.hide() |
303 self.diffButton.hide() |
285 |
304 |
286 if isinstance(lines1, str): |
305 if isinstance(lines1, str): |
287 lines1 = lines1.splitlines(True) |
306 lines1 = lines1.splitlines(True) |
288 if isinstance(lines2, str): |
307 if isinstance(lines2, str): |
289 lines2 = lines2.splitlines(True) |
308 lines2 = lines2.splitlines(True) |
290 |
309 |
291 self.__compare(lines1, lines2) |
310 self.__compare(lines1, lines2) |
292 |
311 |
293 def __compare(self, lines1, lines2): |
312 def __compare(self, lines1, lines2): |
294 """ |
313 """ |
295 Private method to compare two lists of text. |
314 Private method to compare two lists of text. |
296 |
315 |
297 @param lines1 text to compare against (list of strings) |
316 @param lines1 text to compare against (list of strings) |
298 @param lines2 text to compare (list of strings) |
317 @param lines2 text to compare (list of strings) |
299 """ |
318 """ |
300 self.contents_1.clear() |
319 self.contents_1.clear() |
301 self.contents_2.clear() |
320 self.contents_2.clear() |
302 |
321 |
303 self.__generateFormats() |
322 self.__generateFormats() |
304 |
323 |
305 # counters for changes |
324 # counters for changes |
306 added = 0 |
325 added = 0 |
307 deleted = 0 |
326 deleted = 0 |
308 changed = 0 |
327 changed = 0 |
309 |
328 |
310 self.diffParas = [] |
329 self.diffParas = [] |
311 self.currentDiffPos = -1 |
330 self.currentDiffPos = -1 |
312 oldOpcode = '' |
331 oldOpcode = "" |
313 for paras, (opcode, ln1, l1, ln2, l2) in enumerate( |
332 for paras, (opcode, ln1, l1, ln2, l2) in enumerate( |
314 sbsdiff(lines1, lines2), start=1 |
333 sbsdiff(lines1, lines2), start=1 |
315 ): |
334 ): |
316 if opcode in 'idr': |
335 if opcode in "idr": |
317 if oldOpcode != opcode: |
336 if oldOpcode != opcode: |
318 oldOpcode = opcode |
337 oldOpcode = opcode |
319 self.diffParas.append(paras) |
338 self.diffParas.append(paras) |
320 # update counters |
339 # update counters |
321 if opcode == 'i': |
340 if opcode == "i": |
322 added += 1 |
341 added += 1 |
323 elif opcode == 'd': |
342 elif opcode == "d": |
324 deleted += 1 |
343 deleted += 1 |
325 elif opcode == 'r': |
344 elif opcode == "r": |
326 changed += 1 |
345 changed += 1 |
327 if opcode == 'i': |
346 if opcode == "i": |
328 format1 = self.cNormalFormat |
347 format1 = self.cNormalFormat |
329 format2 = self.cInsertedFormat |
348 format2 = self.cInsertedFormat |
330 elif opcode == 'd': |
349 elif opcode == "d": |
331 format1 = self.cDeletedFormat |
350 format1 = self.cDeletedFormat |
332 format2 = self.cNormalFormat |
351 format2 = self.cNormalFormat |
333 elif opcode == 'r': |
352 elif opcode == "r": |
334 if ln1.strip(): |
353 if ln1.strip(): |
335 format1 = self.cReplacedFormat |
354 format1 = self.cReplacedFormat |
336 else: |
355 else: |
337 format1 = self.cNormalFormat |
356 format1 = self.cNormalFormat |
338 if ln2.strip(): |
357 if ln2.strip(): |
339 format2 = self.cReplacedFormat |
358 format2 = self.cReplacedFormat |
340 else: |
359 else: |
341 format2 = self.cNormalFormat |
360 format2 = self.cNormalFormat |
342 else: |
361 else: |
343 oldOpcode = '' |
362 oldOpcode = "" |
344 format1 = self.cNormalFormat |
363 format1 = self.cNormalFormat |
345 format2 = self.cNormalFormat |
364 format2 = self.cNormalFormat |
346 self.__appendText(self.contents_1, ln1, l1, format1, opcode == 'r') |
365 self.__appendText(self.contents_1, ln1, l1, format1, opcode == "r") |
347 self.__appendText(self.contents_2, ln2, l2, format2, opcode == 'r') |
366 self.__appendText(self.contents_2, ln2, l2, format2, opcode == "r") |
348 if not (paras % self.updateInterval): |
367 if not (paras % self.updateInterval): |
349 QApplication.processEvents() |
368 QApplication.processEvents() |
350 |
369 |
351 self.vsb1.setValue(0) |
370 self.vsb1.setValue(0) |
352 self.vsb2.setValue(0) |
371 self.vsb2.setValue(0) |
353 self.firstButton.setEnabled(False) |
372 self.firstButton.setEnabled(False) |
354 self.upButton.setEnabled(False) |
373 self.upButton.setEnabled(False) |
355 self.downButton.setEnabled( |
374 self.downButton.setEnabled( |
356 len(self.diffParas) > 0 and |
375 len(self.diffParas) > 0 and (self.vsb1.isVisible() or self.vsb2.isVisible()) |
357 (self.vsb1.isVisible() or self.vsb2.isVisible())) |
376 ) |
358 self.lastButton.setEnabled( |
377 self.lastButton.setEnabled( |
359 len(self.diffParas) > 0 and |
378 len(self.diffParas) > 0 and (self.vsb1.isVisible() or self.vsb2.isVisible()) |
360 (self.vsb1.isVisible() or self.vsb2.isVisible())) |
379 ) |
361 |
380 |
362 self.totalLabel.setText(self.tr('Total: {0}') |
381 self.totalLabel.setText(self.tr("Total: {0}").format(added + deleted + changed)) |
363 .format(added + deleted + changed)) |
382 self.changedLabel.setText(self.tr("Changed: {0}").format(changed)) |
364 self.changedLabel.setText(self.tr('Changed: {0}').format(changed)) |
383 self.addedLabel.setText(self.tr("Added: {0}").format(added)) |
365 self.addedLabel.setText(self.tr('Added: {0}').format(added)) |
384 self.deletedLabel.setText(self.tr("Deleted: {0}").format(deleted)) |
366 self.deletedLabel.setText(self.tr('Deleted: {0}').format(deleted)) |
385 |
367 |
|
368 # move to the first difference |
386 # move to the first difference |
369 self.downButton.click() |
387 self.downButton.click() |
370 |
388 |
371 def __moveTextToCurrentDiffPos(self): |
389 def __moveTextToCurrentDiffPos(self): |
372 """ |
390 """ |
374 """ |
392 """ |
375 if 0 <= self.currentDiffPos < len(self.diffParas): |
393 if 0 <= self.currentDiffPos < len(self.diffParas): |
376 value = (self.diffParas[self.currentDiffPos] - 1) * self.fontHeight |
394 value = (self.diffParas[self.currentDiffPos] - 1) * self.fontHeight |
377 self.vsb1.setValue(value) |
395 self.vsb1.setValue(value) |
378 self.vsb2.setValue(value) |
396 self.vsb2.setValue(value) |
379 |
397 |
380 def __scrollBarMoved(self, value): |
398 def __scrollBarMoved(self, value): |
381 """ |
399 """ |
382 Private slot to enable the buttons and set the current diff position |
400 Private slot to enable the buttons and set the current diff position |
383 depending on scrollbar position. |
401 depending on scrollbar position. |
384 |
402 |
385 @param value scrollbar position (integer) |
403 @param value scrollbar position (integer) |
386 """ |
404 """ |
387 tPos = value / self.fontHeight + 1 |
405 tPos = value / self.fontHeight + 1 |
388 bPos = (value + self.vsb1.pageStep()) / self.fontHeight + 1 |
406 bPos = (value + self.vsb1.pageStep()) / self.fontHeight + 1 |
389 |
407 |
390 self.currentDiffPos = -1 |
408 self.currentDiffPos = -1 |
391 |
409 |
392 if self.diffParas: |
410 if self.diffParas: |
393 self.firstButton.setEnabled(tPos > self.diffParas[0]) |
411 self.firstButton.setEnabled(tPos > self.diffParas[0]) |
394 self.upButton.setEnabled(tPos > self.diffParas[0]) |
412 self.upButton.setEnabled(tPos > self.diffParas[0]) |
395 self.downButton.setEnabled(bPos < self.diffParas[-1]) |
413 self.downButton.setEnabled(bPos < self.diffParas[-1]) |
396 self.lastButton.setEnabled(bPos < self.diffParas[-1]) |
414 self.lastButton.setEnabled(bPos < self.diffParas[-1]) |
397 |
415 |
398 if tPos >= self.diffParas[0]: |
416 if tPos >= self.diffParas[0]: |
399 for diffPos in self.diffParas: |
417 for diffPos in self.diffParas: |
400 self.currentDiffPos += 1 |
418 self.currentDiffPos += 1 |
401 if tPos <= diffPos: |
419 if tPos <= diffPos: |
402 break |
420 break |
403 |
421 |
404 @pyqtSlot() |
422 @pyqtSlot() |
405 def on_upButton_clicked(self): |
423 def on_upButton_clicked(self): |
406 """ |
424 """ |
407 Private slot to go to the previous difference. |
425 Private slot to go to the previous difference. |
408 """ |
426 """ |
409 self.currentDiffPos -= 1 |
427 self.currentDiffPos -= 1 |
410 self.__moveTextToCurrentDiffPos() |
428 self.__moveTextToCurrentDiffPos() |
411 |
429 |
412 @pyqtSlot() |
430 @pyqtSlot() |
413 def on_downButton_clicked(self): |
431 def on_downButton_clicked(self): |
414 """ |
432 """ |
415 Private slot to go to the next difference. |
433 Private slot to go to the next difference. |
416 """ |
434 """ |
417 self.currentDiffPos += 1 |
435 self.currentDiffPos += 1 |
418 self.__moveTextToCurrentDiffPos() |
436 self.__moveTextToCurrentDiffPos() |
419 |
437 |
420 @pyqtSlot() |
438 @pyqtSlot() |
421 def on_firstButton_clicked(self): |
439 def on_firstButton_clicked(self): |
422 """ |
440 """ |
423 Private slot to go to the first difference. |
441 Private slot to go to the first difference. |
424 """ |
442 """ |
425 self.currentDiffPos = 0 |
443 self.currentDiffPos = 0 |
426 self.__moveTextToCurrentDiffPos() |
444 self.__moveTextToCurrentDiffPos() |
427 |
445 |
428 @pyqtSlot() |
446 @pyqtSlot() |
429 def on_lastButton_clicked(self): |
447 def on_lastButton_clicked(self): |
430 """ |
448 """ |
431 Private slot to go to the last difference. |
449 Private slot to go to the last difference. |
432 """ |
450 """ |
433 self.currentDiffPos = len(self.diffParas) - 1 |
451 self.currentDiffPos = len(self.diffParas) - 1 |
434 self.__moveTextToCurrentDiffPos() |
452 self.__moveTextToCurrentDiffPos() |
435 |
453 |
436 def __fileChanged(self): |
454 def __fileChanged(self): |
437 """ |
455 """ |
438 Private slot to enable/disable the Compare button. |
456 Private slot to enable/disable the Compare button. |
439 """ |
457 """ |
440 if ( |
458 if not self.file1Picker.text() or not self.file2Picker.text(): |
441 not self.file1Picker.text() or |
|
442 not self.file2Picker.text() |
|
443 ): |
|
444 self.diffButton.setEnabled(False) |
459 self.diffButton.setEnabled(False) |
445 else: |
460 else: |
446 self.diffButton.setEnabled(True) |
461 self.diffButton.setEnabled(True) |
447 |
462 |
448 @pyqtSlot(bool) |
463 @pyqtSlot(bool) |
449 def on_synchronizeCheckBox_toggled(self, sync): |
464 def on_synchronizeCheckBox_toggled(self, sync): |
450 """ |
465 """ |
451 Private slot to connect or disconnect the scrollbars of the displays. |
466 Private slot to connect or disconnect the scrollbars of the displays. |
452 |
467 |
453 @param sync flag indicating synchronisation status (boolean) |
468 @param sync flag indicating synchronisation status (boolean) |
454 """ |
469 """ |
455 if sync: |
470 if sync: |
456 self.hsb2.setValue(self.hsb1.value()) |
471 self.hsb2.setValue(self.hsb1.value()) |
457 self.hsb1.valueChanged.connect(self.hsb2.setValue) |
472 self.hsb1.valueChanged.connect(self.hsb2.setValue) |
463 |
478 |
464 class CompareWindow(EricMainWindow): |
479 class CompareWindow(EricMainWindow): |
465 """ |
480 """ |
466 Main window class for the standalone dialog. |
481 Main window class for the standalone dialog. |
467 """ |
482 """ |
|
483 |
468 def __init__(self, files=None, parent=None): |
484 def __init__(self, files=None, parent=None): |
469 """ |
485 """ |
470 Constructor |
486 Constructor |
471 |
487 |
472 @param files list of files to compare and their label |
488 @param files list of files to compare and their label |
473 (list of two tuples of two strings) |
489 (list of two tuples of two strings) |
474 @param parent reference to the parent widget (QWidget) |
490 @param parent reference to the parent widget (QWidget) |
475 """ |
491 """ |
476 super().__init__(parent) |
492 super().__init__(parent) |
477 |
493 |
478 self.setStyle(Preferences.getUI("Style"), |
494 self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) |
479 Preferences.getUI("StyleSheet")) |
495 |
480 |
|
481 self.cw = CompareDialog(files, self) |
496 self.cw = CompareDialog(files, self) |
482 self.cw.installEventFilter(self) |
497 self.cw.installEventFilter(self) |
483 size = self.cw.size() |
498 size = self.cw.size() |
484 self.setCentralWidget(self.cw) |
499 self.setCentralWidget(self.cw) |
485 self.resize(size) |
500 self.resize(size) |
486 |
501 |
487 def eventFilter(self, obj, event): |
502 def eventFilter(self, obj, event): |
488 """ |
503 """ |
489 Public method to filter events. |
504 Public method to filter events. |
490 |
505 |
491 @param obj reference to the object the event is meant for (QObject) |
506 @param obj reference to the object the event is meant for (QObject) |
492 @param event reference to the event object (QEvent) |
507 @param event reference to the event object (QEvent) |
493 @return flag indicating, whether the event was handled (boolean) |
508 @return flag indicating, whether the event was handled (boolean) |
494 """ |
509 """ |
495 if event.type() == QEvent.Type.Close: |
510 if event.type() == QEvent.Type.Close: |
496 QApplication.exit() |
511 QApplication.exit() |
497 return True |
512 return True |
498 |
513 |
499 return False |
514 return False |