Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.py

branch
Py2 comp.
changeset 3456
96232974dcdb
parent 3178
f25fc1364c88
parent 3413
5e63f809732a
child 3484
645c12de6b0c
equal deleted inserted replaced
3178:f25fc1364c88 3456:96232974dcdb
23 import UI.PixmapCache 23 import UI.PixmapCache
24 import Preferences 24 import Preferences
25 import Utilities 25 import Utilities
26 26
27 from . import pep8 27 from . import pep8
28 from .NamingStyleChecker import NamingStyleChecker
29
30 # register the name checker
31 pep8.register_check(NamingStyleChecker, NamingStyleChecker.Codes)
32
33 from .DocStyleChecker import DocStyleChecker
34
35
36 class CodeStyleCheckerReport(pep8.BaseReport):
37 """
38 Class implementing a special report to be used with our dialog.
39 """
40 def __init__(self, options):
41 """
42 Constructor
43
44 @param options options for the report (optparse.Values)
45 """
46 super(CodeStyleCheckerReport, self).__init__(options)
47
48 self.__repeat = options.repeat
49 self.errors = []
50
51 def error_args(self, line_number, offset, code, check, *args):
52 """
53 Public method to collect the error messages.
54
55 @param line_number line number of the issue (integer)
56 @param offset position within line of the issue (integer)
57 @param code message code (string)
58 @param check reference to the checker function (function)
59 @param args arguments for the message (list)
60 @return error code (string)
61 """
62 code = super(CodeStyleCheckerReport, self).error_args(
63 line_number, offset, code, check, *args)
64 if code and (self.counters[code] == 1 or self.__repeat):
65 if code in NamingStyleChecker.Codes:
66 text = NamingStyleChecker.getMessage(code, *args)
67 else:
68 text = pep8.getMessage(code, *args)
69 self.errors.append(
70 (self.filename, line_number, offset, text)
71 )
72 return code
73 28
74 29
75 class CodeStyleCheckerDialog(QDialog, Ui_CodeStyleCheckerDialog): 30 class CodeStyleCheckerDialog(QDialog, Ui_CodeStyleCheckerDialog):
76 """ 31 """
77 Class implementing a dialog to show the results of the code style check. 32 Class implementing a dialog to show the results of the code style check.
81 positionRole = Qt.UserRole + 3 36 positionRole = Qt.UserRole + 3
82 messageRole = Qt.UserRole + 4 37 messageRole = Qt.UserRole + 4
83 fixableRole = Qt.UserRole + 5 38 fixableRole = Qt.UserRole + 5
84 codeRole = Qt.UserRole + 6 39 codeRole = Qt.UserRole + 6
85 40
86 def __init__(self, parent=None): 41 def __init__(self, styleCheckService, parent=None):
87 """ 42 """
88 Constructor 43 Constructor
89 44
45 @param styleCheckService reference to the service
46 (CodeStyleCheckService)
90 @param parent reference to the parent widget (QWidget) 47 @param parent reference to the parent widget (QWidget)
91 """ 48 """
92 super(CodeStyleCheckerDialog, self).__init__(parent) 49 super(CodeStyleCheckerDialog, self).__init__(parent)
93 self.setupUi(self) 50 self.setupUi(self)
94 51
112 self.resultList.header().setSortIndicator(0, Qt.AscendingOrder) 69 self.resultList.header().setSortIndicator(0, Qt.AscendingOrder)
113 70
114 self.checkProgress.setVisible(False) 71 self.checkProgress.setVisible(False)
115 self.checkProgressLabel.setVisible(False) 72 self.checkProgressLabel.setVisible(False)
116 self.checkProgressLabel.setMaximumWidth(600) 73 self.checkProgressLabel.setMaximumWidth(600)
74
75 self.styleCheckService = styleCheckService
76 self.styleCheckService.styleChecked.connect(self.__processResult)
77 self.filename = None
117 78
118 self.noResults = True 79 self.noResults = True
119 self.cancelled = False 80 self.cancelled = False
120 self.__lastFileItem = None 81 self.__lastFileItem = None
121 82
200 @param itm reference to the item to modify (QTreeWidgetItem) 161 @param itm reference to the item to modify (QTreeWidgetItem)
201 @param text text to be appended (string) 162 @param text text to be appended (string)
202 @param fixed flag indicating a fixed issue (boolean) 163 @param fixed flag indicating a fixed issue (boolean)
203 """ 164 """
204 if fixed: 165 if fixed:
205 message = itm.data(0, self.messageRole) + text 166 code, message = text.split(None, 1)
206 itm.setText(2, message) 167 itm.setText(2, message)
207 itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed.png")) 168 itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed.png"))
208 169
209 itm.setData(0, self.messageRole, message) 170 itm.setData(0, self.messageRole, message)
210 else: 171 else:
226 for key in statistics: 187 for key in statistics:
227 if key in self.__statistics: 188 if key in self.__statistics:
228 self.__statistics[key] += statistics[key] 189 self.__statistics[key] += statistics[key]
229 else: 190 else:
230 self.__statistics[key] = statistics[key] 191 self.__statistics[key] = statistics[key]
231 if fixer: 192 self.__statistics["_IssuesFixed"] += fixer
232 self.__statistics["_IssuesFixed"] += fixer.fixed
233 193
234 def __updateFixerStatistics(self, fixer): 194 def __updateFixerStatistics(self, fixer):
235 """ 195 """
236 Private method to update the collected fixer related statistics. 196 Private method to update the collected fixer related statistics.
237 197
238 @param fixer reference to the code style fixer (CodeStyleFixer) 198 @param fixer reference to the code style fixer (CodeStyleFixer)
239 """ 199 """
240 self.__statistics["_IssuesFixed"] += fixer.fixed 200 self.__statistics["_IssuesFixed"] += fixer
241 201
242 def __resetStatistics(self): 202 def __resetStatistics(self):
243 """ 203 """
244 Private slot to reset the statistics data. 204 Private slot to reset the statistics data.
245 """ 205 """
325 285
326 if save: 286 if save:
327 self.__fileOrFileList = fn 287 self.__fileOrFileList = fn
328 288
329 if isinstance(fn, list): 289 if isinstance(fn, list):
330 files = fn[:] 290 self.files = fn[:]
331 elif os.path.isdir(fn): 291 elif os.path.isdir(fn):
332 files = [] 292 self.files = []
333 extensions = set(Preferences.getPython("PythonExtensions") + 293 extensions = set(Preferences.getPython("PythonExtensions") +
334 Preferences.getPython("Python3Extensions")) 294 Preferences.getPython("Python3Extensions"))
335 for ext in extensions: 295 for ext in extensions:
336 files.extend(Utilities.direntries( 296 self.files.extend(Utilities.direntries(
337 fn, True, '*{0}'.format(ext), 0)) 297 fn, True, '*{0}'.format(ext), 0))
338 else: 298 else:
339 files = [fn] 299 self.files = [fn]
340 300
341 # filter the list depending on the filter string 301 # filter the list depending on the filter string
342 if files: 302 if self.files:
343 filterString = self.excludeFilesEdit.text() 303 filterString = self.excludeFilesEdit.text()
344 filterList = [f.strip() for f in filterString.split(",") 304 filterList = [f.strip() for f in filterString.split(",")
345 if f.strip()] 305 if f.strip()]
346 for filter in filterList: 306 for filter in filterList:
347 files = \ 307 self.files = \
348 [f for f in files 308 [f for f in self.files
349 if not fnmatch.fnmatch(f, filter.strip())] 309 if not fnmatch.fnmatch(f, filter.strip())]
350 310
351 self.__resetStatistics() 311 self.__resetStatistics()
352 self.__clearErrors(files) 312 self.__clearErrors(self.files)
353 313
354 py3files = [f for f in files 314 if len(self.files) > 0:
355 if f.endswith( 315 self.checkProgress.setMaximum(len(self.files))
356 tuple(Preferences.getPython("Python3Extensions")))] 316 self.checkProgressLabel.setVisible(len(self.files) > 1)
357 py2files = [f for f in files 317 self.checkProgress.setVisible(len(self.files) > 1)
358 if f.endswith(
359 tuple(Preferences.getPython("PythonExtensions")))]
360
361 if len(py3files) + len(py2files) > 0:
362 self.checkProgress.setMaximum(len(py3files) + len(py2files))
363 self.checkProgressLabel.setVisible(
364 len(py3files) + len(py2files) > 1)
365 self.checkProgress.setVisible(
366 len(py3files) + len(py2files) > 1)
367 QApplication.processEvents() 318 QApplication.processEvents()
368 319
369 # extract the configuration values 320 # extract the configuration values
370 excludeMessages = self.excludeMessagesEdit.text() 321 excludeMessages = self.excludeMessagesEdit.text()
371 includeMessages = self.includeMessagesEdit.text() 322 includeMessages = self.includeMessagesEdit.text()
376 maxLineLength = self.lineLengthSpinBox.value() 327 maxLineLength = self.lineLengthSpinBox.value()
377 hangClosing = self.hangClosingCheckBox.isChecked() 328 hangClosing = self.hangClosingCheckBox.isChecked()
378 docType = self.docTypeComboBox.itemData( 329 docType = self.docTypeComboBox.itemData(
379 self.docTypeComboBox.currentIndex()) 330 self.docTypeComboBox.currentIndex())
380 331
381 try: 332 self.__options = [excludeMessages, includeMessages, repeatMessages,
382 # disable updates of the list for speed 333 fixCodes, noFixCodes, fixIssues, maxLineLength,
383 self.resultList.setUpdatesEnabled(False) 334 hangClosing, docType]
384 self.resultList.setSortingEnabled(False) 335
385 336 # now go through all the files
386 # now go through all the files 337 self.progress = 0
387 progress = 0 338 self.files.sort()
388 for file in sorted(py3files + py2files): 339 self.check()
389 self.checkProgress.setValue(progress) 340
390 self.checkProgressLabel.setPath(file) 341 def check(self, codestring='', onlyFixes={}):
391 QApplication.processEvents() 342 """
392 343 Start a style check for one file.
393 if self.cancelled: 344
394 self.__resort() 345 The results are reported to the __processResult slot.
395 return 346 @keyparam codestring optional sourcestring (str)
396 347 @keyparam onlyFixes dict which violations should be fixed (dict)
397 self.__lastFileItem = None 348 """
398 349 if not self.files:
399 try:
400 source, encoding = Utilities.readEncodedFile(file)
401 source = source.splitlines(True)
402 except (UnicodeError, IOError) as msg:
403 self.noResults = False
404 self.__createResultItem(
405 file, 1, 1,
406 self.trUtf8("Error: {0}").format(str(msg))
407 .rstrip()[1:-1], False, False)
408 progress += 1
409 continue
410
411 stats = {}
412 flags = Utilities.extractFlags(source)
413 ext = os.path.splitext(file)[1]
414 if fixIssues:
415 from .CodeStyleFixer import CodeStyleFixer
416 fixer = CodeStyleFixer(
417 self.__project, file, source, fixCodes, noFixCodes,
418 maxLineLength, True) # always fix in place
419 else:
420 fixer = None
421 if ("FileType" in flags and
422 flags["FileType"] in ["Python", "Python2"]) or \
423 file in py2files or \
424 (ext in [".py", ".pyw"] and
425 Preferences.getProject("DeterminePyFromProject") and
426 self.__project.isOpen() and
427 self.__project.isProjectFile(file) and
428 self.__project.getProjectLanguage() in ["Python",
429 "Python2"]):
430 from .CodeStyleChecker import CodeStyleCheckerPy2
431 report = CodeStyleCheckerPy2(
432 file, [],
433 repeat=repeatMessages,
434 select=includeMessages,
435 ignore=excludeMessages,
436 max_line_length=maxLineLength,
437 hang_closing=hangClosing,
438 docType=docType,
439 )
440 errors = report.errors[:]
441 stats.update(report.counters)
442 else:
443 if includeMessages:
444 select = [s.strip() for s in
445 includeMessages.split(',') if s.strip()]
446 else:
447 select = []
448 if excludeMessages:
449 ignore = [i.strip() for i in
450 excludeMessages.split(',') if i.strip()]
451 else:
452 ignore = []
453
454 # check coding style
455 styleGuide = pep8.StyleGuide(
456 reporter=CodeStyleCheckerReport,
457 repeat=repeatMessages,
458 select=select,
459 ignore=ignore,
460 max_line_length=maxLineLength,
461 hang_closing=hangClosing,
462 )
463 report = styleGuide.check_files([file])
464 stats.update(report.counters)
465
466 # check documentation style
467 docStyleChecker = DocStyleChecker(
468 source, file, select, ignore, [], repeatMessages,
469 maxLineLength=maxLineLength, docType=docType)
470 docStyleChecker.run()
471 stats.update(docStyleChecker.counters)
472
473 errors = report.errors + docStyleChecker.errors
474
475 deferredFixes = {}
476 for error in errors:
477 fname, lineno, position, text = error
478 if lineno > len(source):
479 lineno = len(source)
480 if "__IGNORE_WARNING__" not in \
481 Utilities.extractLineFlags(
482 source[lineno - 1].strip()):
483 self.noResults = False
484 if fixer:
485 res, msg, id_ = fixer.fixIssue(lineno,
486 position, text)
487 if res == 1:
488 text += "\n" + \
489 self.trUtf8("Fix: {0}").format(msg)
490 self.__createResultItem(
491 fname, lineno, position, text, True,
492 True)
493 elif res == 0:
494 self.__createResultItem(
495 fname, lineno, position, text, False,
496 True)
497 else:
498 itm = self.__createResultItem(
499 fname, lineno, position,
500 text, False, False)
501 deferredFixes[id_] = itm
502 else:
503 self.__createResultItem(
504 fname, lineno, position, text, False,
505 False)
506 if fixer:
507 deferredResults = fixer.finalize()
508 for id_ in deferredResults:
509 fixed, msg = deferredResults[id_]
510 itm = deferredFixes[id_]
511 if fixed == 1:
512 text = "\n" + \
513 self.trUtf8("Fix: {0}").format(msg)
514 self.__modifyFixedResultItem(itm, text, True)
515 else:
516 self.__modifyFixedResultItem(itm, "", False)
517 fixer.saveFile(encoding)
518 self.__updateStatistics(stats, fixer)
519 progress += 1
520 finally:
521 # reenable updates of the list
522 self.resultList.setSortingEnabled(True)
523 self.resultList.setUpdatesEnabled(True)
524 self.checkProgress.setValue(progress)
525 self.checkProgressLabel.setPath("") 350 self.checkProgressLabel.setPath("")
526 QApplication.processEvents()
527 self.__resort()
528 else:
529 self.checkProgress.setMaximum(1) 351 self.checkProgress.setMaximum(1)
530 self.checkProgress.setValue(1) 352 self.checkProgress.setValue(1)
531 self.__finish() 353 self.__finish()
354 return
355
356 self.filename = self.files.pop(0)
357 self.checkProgress.setValue(self.progress)
358 self.checkProgressLabel.setPath(self.filename)
359 QApplication.processEvents()
360
361 if self.cancelled:
362 self.__resort()
363 return
364
365 self.__lastFileItem = None
366
367 if codestring:
368 self.source = codestring
369 else:
370 try:
371 self.source, encoding = Utilities.readEncodedFile(
372 self.filename)
373 if encoding.endswith(
374 ('-selected', '-default', '-guessed', '-ignore')):
375 encoding = encoding.rsplit('-', 1)[0]
376
377 self.source = self.source.splitlines(True)
378 except (UnicodeError, IOError) as msg:
379 self.noResults = False
380 self.__createResultItem(
381 self.filename, 1, 1,
382 self.trUtf8("Error: {0}").format(str(msg))
383 .rstrip()[1:-1], False, False)
384 self.progress += 1
385 # Continue with next file
386 self.check()
387 return
388
389 errors = []
390 self.__itms = []
391 for error, itm in onlyFixes.get(self.filename, []):
392 errors.append(error)
393 self.__itms.append(itm)
394
395 eol = self.__getEol(self.filename)
396 args = self.__options + [errors, eol, encoding]
397 self.styleCheckService.styleCheck(
398 None, self.filename, self.source, args)
399
400 def __processResult(self, fn, codeStyleCheckerStats, fixes, results):
401 """
402 Privat slot called after perfoming a style check on one file.
403
404 @param fn filename of the just checked file (str)
405 @param codeStyleCheckerStats stats of style and name check (dict)
406 @param fixes number of applied fixes (int)
407 @param results tuple for each found violation of style (tuple of
408 lineno (int), position (int), text (str), fixed (bool),
409 autofixing (bool))
410 """
411 # Check if it's the requested file, otherwise ignore signal
412 if fn != self.filename:
413 return
414
415 # disable updates of the list for speed
416 self.resultList.setUpdatesEnabled(False)
417 self.resultList.setSortingEnabled(False)
418
419 fixed = None
420 if self.__itms:
421 for itm, (lineno, position, text, fixed, autofixing) in zip(
422 self.__itms, results):
423 self.__modifyFixedResultItem(itm, text, fixed)
424 self.__updateFixerStatistics(fixes)
425 else:
426 for lineno, position, text, fixed, autofixing in results:
427 self.noResults = False
428 self.__createResultItem(
429 fn, lineno, position, text, fixed, autofixing)
430
431 self.__updateStatistics(codeStyleCheckerStats, fixes)
432
433 if fixed:
434 vm = e5App().getObject("ViewManager")
435 editor = vm.getOpenEditor(fn)
436 if editor:
437 editor.refresh()
438
439 self.progress += 1
440
441 self.__resort()
442 # reenable updates of the list
443 self.resultList.setSortingEnabled(True)
444 self.resultList.setUpdatesEnabled(True)
445
446 self.checkProgress.setValue(self.progress)
447 QApplication.processEvents()
448
449 self.check()
532 450
533 def __finish(self): 451 def __finish(self):
534 """ 452 """
535 Private slot called when the code style check finished or the user 453 Private slot called when the code style check finished or the user
536 pressed the cancel button. 454 pressed the cancel button.
554 self.resultList.header().resizeSections(QHeaderView.ResizeToContents) 472 self.resultList.header().resizeSections(QHeaderView.ResizeToContents)
555 self.resultList.header().setStretchLastSection(True) 473 self.resultList.header().setStretchLastSection(True)
556 474
557 self.checkProgress.setVisible(False) 475 self.checkProgress.setVisible(False)
558 self.checkProgressLabel.setVisible(False) 476 self.checkProgressLabel.setVisible(False)
477
478 def __getEol(self, fn):
479 """
480 Private method to get the applicable eol string.
481
482 @param fn filename where to determine the line ending (str)
483 @return eol string (string)
484 """
485 if self.__project.isOpen() and self.__project.isProjectFile(fn):
486 eol = self.__project.getEolString()
487 else:
488 eol = Utilities.linesep()
489 return eol
559 490
560 @pyqtSlot() 491 @pyqtSlot()
561 def on_startButton_clicked(self): 492 def on_startButton_clicked(self):
562 """ 493 """
563 Private slot to start a code style check run. 494 Private slot to start a code style check run.
655 586
656 if code == "E901": 587 if code == "E901":
657 editor.toggleSyntaxError(lineno, 0, True, message, True) 588 editor.toggleSyntaxError(lineno, 0, True, message, True)
658 else: 589 else:
659 editor.toggleWarning( 590 editor.toggleWarning(
660 lineno, True, message, warningType=editor.WarningStyle) 591 lineno, 0, True, message, warningType=editor.WarningStyle)
661 592
662 @pyqtSlot() 593 @pyqtSlot()
663 def on_resultList_itemSelectionChanged(self): 594 def on_resultList_itemSelectionChanged(self):
664 """ 595 """
665 Private slot to change the dialog state depending on the selection. 596 Private slot to change the dialog state depending on the selection.
688 for cindex in range(itm.childCount()): 619 for cindex in range(itm.childCount()):
689 citm = itm.child(cindex) 620 citm = itm.child(cindex)
690 lineno = citm.data(0, self.lineRole) 621 lineno = citm.data(0, self.lineRole)
691 message = citm.data(0, self.messageRole) 622 message = citm.data(0, self.messageRole)
692 editor.toggleWarning( 623 editor.toggleWarning(
693 lineno, True, message, warningType=editor.WarningStyle) 624 lineno, 0, True, message, warningType=editor.WarningStyle)
694 625
695 # go through the list again to clear warning markers for files, 626 # go through the list again to clear warning markers for files,
696 # that are ok 627 # that are ok
697 openFiles = vm.getOpenFilenames() 628 openFiles = vm.getOpenFilenames()
698 errorFiles = [] 629 errorFiles = []
817 748
818 @pyqtSlot() 749 @pyqtSlot()
819 def on_fixButton_clicked(self): 750 def on_fixButton_clicked(self):
820 """ 751 """
821 Private slot to fix selected issues. 752 Private slot to fix selected issues.
822 """ 753
823 from .CodeStyleFixer import CodeStyleFixer 754 Build a dictionary of issues to fix. Update the initialized __options.
824 755 Then call check with the dict as keyparam to fix selected issues.
825 # build a dictionary of issues to fix 756 """
826 fixableItems = self.__getSelectedFixableItems() 757 fixableItems = self.__getSelectedFixableItems()
827 fixesDict = {} # dictionary of lists of tuples containing 758 # dictionary of lists of tuples containing the issue and the item
828 # the issue and the item 759 fixesDict = {}
829 for itm in fixableItems: 760 for itm in fixableItems:
830 filename = itm.data(0, self.filenameRole) 761 filename = itm.data(0, self.filenameRole)
831 if filename not in fixesDict: 762 if filename not in fixesDict:
832 fixesDict[filename] = [] 763 fixesDict[filename] = []
833 fixesDict[filename].append(( 764 fixesDict[filename].append((
834 (itm.data(0, self.lineRole), 765 (filename, itm.data(0, self.lineRole),
835 itm.data(0, self.positionRole), 766 itm.data(0, self.positionRole),
836 "{0} {1}".format(itm.data(0, self.codeRole), 767 "{0} {1}".format(itm.data(0, self.codeRole),
837 itm.data(0, self.messageRole))), 768 itm.data(0, self.messageRole))),
838 itm 769 itm
839 )) 770 ))
840 771
841 # extract the configuration values 772 # update the configuration values (3: fixCodes, 4: noFixCodes,
842 fixCodes = self.fixIssuesEdit.text() 773 # 5: fixIssues, 6: maxLineLength)
843 noFixCodes = self.noFixIssuesEdit.text() 774 self.__options[3] = self.fixIssuesEdit.text()
844 maxLineLength = self.lineLengthSpinBox.value() 775 self.__options[4] = self.noFixIssuesEdit.text()
845 776 self.__options[5] = True
777 self.__options[6] = self.lineLengthSpinBox.value()
778
779 self.files = list(fixesDict.keys())
846 # now go through all the files 780 # now go through all the files
847 if fixesDict: 781 self.progress = 0
848 self.checkProgress.setMaximum(len(fixesDict)) 782 self.files.sort()
849 progress = 0 783 self.cancelled = False
850 for file in fixesDict: 784 self.check(onlyFixes=fixesDict)
851 self.checkProgress.setValue(progress) 785
852 QApplication.processEvents()
853
854 try:
855 source, encoding = Utilities.readEncodedFile(file)
856 source = source.splitlines(True)
857 except (UnicodeError, IOError) as msg:
858 # skip silently because that should not happen
859 progress += 1
860 continue
861
862 deferredFixes = {}
863 fixer = CodeStyleFixer(
864 self.__project, file, source, fixCodes, noFixCodes,
865 maxLineLength, True) # always fix in place
866 errors = fixesDict[file]
867 errors.sort(key=lambda a: a[0][0])
868 for error in errors:
869 (lineno, position, text), itm = error
870 if lineno > len(source):
871 lineno = len(source)
872 fixed, msg, id_ = fixer.fixIssue(lineno, position, text)
873 if fixed == 1:
874 text = "\n" + self.trUtf8("Fix: {0}").format(msg)
875 self.__modifyFixedResultItem(itm, text, True)
876 elif fixed == 0:
877 self.__modifyFixedResultItem(itm, "", False)
878 else:
879 # remember item for the deferred fix
880 deferredFixes[id_] = itm
881 deferredResults = fixer.finalize()
882 for id_ in deferredResults:
883 fixed, msg = deferredResults[id_]
884 itm = deferredFixes[id_]
885 if fixed == 1:
886 text = "\n" + self.trUtf8("Fix: {0}").format(msg)
887 self.__modifyFixedResultItem(itm, text, True)
888 else:
889 self.__modifyFixedResultItem(itm, "", False)
890 fixer.saveFile(encoding)
891
892 self.__updateFixerStatistics(fixer)
893 progress += 1
894
895 self.checkProgress.setValue(progress)
896 QApplication.processEvents()
897
898 def __getSelectedFixableItems(self): 786 def __getSelectedFixableItems(self):
899 """ 787 """
900 Private method to extract all selected items for fixable issues. 788 Private method to extract all selected items for fixable issues.
901 789
902 @return selected items for fixable issues (list of QTreeWidgetItem) 790 @return selected items for fixable issues (list of QTreeWidgetItem)

eric ide

mercurial