src/eric7/UI/CompareDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
28 28
29 def sbsdiff(a, b, linenumberwidth=4): 29 def sbsdiff(a, b, linenumberwidth=4):
30 """ 30 """
31 Compare two sequences of lines; generate the delta for display side by 31 Compare two sequences of lines; generate the delta for display side by
32 side. 32 side.
33 33
34 @param a first sequence of lines (list of strings) 34 @param a first sequence of lines (list of strings)
35 @param b second sequence of lines (list of strings) 35 @param b second sequence of lines (list of strings)
36 @param linenumberwidth width (in characters) of the linenumbers (integer) 36 @param linenumberwidth width (in characters) of the linenumbers (integer)
37 @yield tuples of differences. Each tuple is composed of strings as follows. 37 @yield tuples of differences. Each tuple is composed of strings as follows.
38 <ul> 38 <ul>
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)
205 pane.setCurrentCharFormat(charFormat) 222 pane.setCurrentCharFormat(charFormat)
206 if interLine: 223 if interLine:
207 pane.insertPlainText("{0} ".format(linenumber)) 224 pane.insertPlainText("{0} ".format(linenumber))
208 for txt in re.split(self.markerPattern, line): 225 for txt in re.split(self.markerPattern, line):
209 if txt: 226 if txt:
210 if txt.count('\1'): 227 if txt.count("\1"):
211 txt1, txt = txt.split('\1', 1) 228 txt1, txt = txt.split("\1", 1)
212 tc = pane.textCursor() 229 tc = pane.textCursor()
213 tc.movePosition(QTextCursor.MoveOperation.End) 230 tc.movePosition(QTextCursor.MoveOperation.End)
214 pane.setTextCursor(tc) 231 pane.setTextCursor(tc)
215 pane.setCurrentCharFormat(charFormat) 232 pane.setCurrentCharFormat(charFormat)
216 pane.insertPlainText(txt1) 233 pane.insertPlainText(txt1)
223 pane.insertPlainText("{0} {1}".format(linenumber, line)) 240 pane.insertPlainText("{0} {1}".format(linenumber, line))
224 241
225 def on_buttonBox_clicked(self, button): 242 def on_buttonBox_clicked(self, button):
226 """ 243 """
227 Private slot called by a button of the button box clicked. 244 Private slot called by a button of the button box clicked.
228 245
229 @param button button that was clicked (QAbstractButton) 246 @param button button that was clicked (QAbstractButton)
230 """ 247 """
231 if button == self.diffButton: 248 if button == self.diffButton:
232 self.on_diffButton_clicked() 249 self.on_diffButton_clicked()
233 250
234 @pyqtSlot() 251 @pyqtSlot()
235 def on_diffButton_clicked(self): 252 def on_diffButton_clicked(self):
236 """ 253 """
237 Private slot to handle the Compare button press. 254 Private slot to handle the Compare button press.
238 """ 255 """
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

eric ide

mercurial