eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.py

changeset 7609
d5aff4fd0ef8
parent 7600
d2bf0476484b
child 7610
df7025fe26a3
equal deleted inserted replaced
7606:a3a4760b59ec 7609:d5aff4fd0ef8
9 9
10 10
11 import os 11 import os
12 import fnmatch 12 import fnmatch
13 13
14 from PyQt5.QtCore import pyqtSlot, Qt, QTimer 14 from PyQt5.QtCore import pyqtSlot, Qt, QTimer, QCoreApplication
15 from PyQt5.QtGui import QIcon 15 from PyQt5.QtGui import QIcon
16 from PyQt5.QtWidgets import ( 16 from PyQt5.QtWidgets import (
17 QDialog, QTreeWidgetItem, QAbstractButton, QDialogButtonBox, QApplication, 17 QDialog, QTreeWidgetItem, QAbstractButton, QDialogButtonBox, QApplication,
18 QHeaderView, QListWidgetItem 18 QHeaderView, QListWidgetItem
19 ) 19 )
49 availableFutures = [ 49 availableFutures = [
50 'division', 'absolute_import', 'with_statement', 50 'division', 'absolute_import', 'with_statement',
51 'print_function', 'unicode_literals', 'generator_stop', 51 'print_function', 'unicode_literals', 'generator_stop',
52 'annotations'] 52 'annotations']
53 53
54 checkCategories = {
55 "A": QCoreApplication.translate(
56 "CheckerCategories",
57 "Annotations"),
58 "C": QCoreApplication.translate(
59 "CheckerCategories",
60 "Code Complexity"),
61 "D": QCoreApplication.translate(
62 "CheckerCategories",
63 "Documentation"),
64 "E": QCoreApplication.translate(
65 "CheckerCategories",
66 "Errors"),
67 "M": QCoreApplication.translate(
68 "CheckerCategories",
69 "Miscellaneous"),
70 "N": QCoreApplication.translate(
71 "CheckerCategories",
72 "Naming"),
73 "W": QCoreApplication.translate(
74 "CheckerCategories",
75 "Warnings"),
76 }
77
54 noResults = 0 78 noResults = 0
55 noFiles = 1 79 noFiles = 1
56 hasResults = 2 80 hasResults = 2
57 81
58 def __init__(self, styleCheckService, parent=None): 82 def __init__(self, styleCheckService, parent=None):
59 """ 83 """
60 Constructor 84 Constructor
61 85
62 @param styleCheckService reference to the service 86 @param styleCheckService reference to the service
63 (CodeStyleCheckService) 87 @type CodeStyleCheckService
64 @param parent reference to the parent widget (QWidget) 88 @param parent reference to the parent widget
89 @type QWidget
65 """ 90 """
66 super(CodeStyleCheckerDialog, self).__init__(parent) 91 super(CodeStyleCheckerDialog, self).__init__(parent)
67 self.setupUi(self) 92 self.setupUi(self)
68 self.setWindowFlags(Qt.Window) 93 self.setWindowFlags(Qt.Window)
69 94
78 self.noFixIssuesSelectButton.setIcon( 103 self.noFixIssuesSelectButton.setIcon(
79 UI.PixmapCache.getIcon("select")) 104 UI.PixmapCache.getIcon("select"))
80 105
81 self.docTypeComboBox.addItem(self.tr("PEP-257"), "pep257") 106 self.docTypeComboBox.addItem(self.tr("PEP-257"), "pep257")
82 self.docTypeComboBox.addItem(self.tr("Eric"), "eric") 107 self.docTypeComboBox.addItem(self.tr("Eric"), "eric")
108
109 for category, text in CodeStyleCheckerDialog.checkCategories.items():
110 itm = QListWidgetItem(text, self.categoriesList)
111 itm.setData(Qt.UserRole, category)
112 itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
113 itm.setCheckState(Qt.Unchecked)
83 114
84 for future in CodeStyleCheckerDialog.availableFutures: 115 for future in CodeStyleCheckerDialog.availableFutures:
85 itm = QListWidgetItem(future, self.futuresList) 116 itm = QListWidgetItem(future, self.futuresList)
86 itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable) 117 itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
87 itm.setCheckState(Qt.Unchecked) 118 itm.setCheckState(Qt.Unchecked)
171 def __createResultItem(self, filename, line, pos, message, fixed, 202 def __createResultItem(self, filename, line, pos, message, fixed,
172 autofixing, ignored): 203 autofixing, ignored):
173 """ 204 """
174 Private method to create an entry in the result list. 205 Private method to create an entry in the result list.
175 206
176 @param filename file name of the file (string) 207 @param filename file name of the file
177 @param line line number of issue (integer or string) 208 @type str
178 @param pos character position of issue (integer or string) 209 @param line line number of issue
179 @param message message text (string) 210 @type int or str
180 @param fixed flag indicating a fixed issue (boolean) 211 @param pos character position of issue
212 @type int or str
213 @param message message text
214 @type str
215 @param fixed flag indicating a fixed issue
216 @type bool
181 @param autofixing flag indicating, that we are fixing issues 217 @param autofixing flag indicating, that we are fixing issues
182 automatically (boolean) 218 automatically
183 @param ignored flag indicating an ignored issue (boolean) 219 @type bool
184 @return reference to the created item (QTreeWidgetItem) 220 @param ignored flag indicating an ignored issue
221 @type bool
222 @return reference to the created item
223 @rtype QTreeWidgetItem
185 """ 224 """
186 from .CodeStyleFixer import FixableCodeStyleIssues 225 from .CodeStyleFixer import FixableCodeStyleIssues
187 226
188 if self.__lastFileItem is None: 227 if self.__lastFileItem is None:
189 # It's a new file 228 # It's a new file
198 itm = QTreeWidgetItem( 237 itm = QTreeWidgetItem(
199 self.__lastFileItem, 238 self.__lastFileItem,
200 ["{0:6}".format(line), code, message]) 239 ["{0:6}".format(line), code, message])
201 if code.startswith(("W", "-", "C", "M")): 240 if code.startswith(("W", "-", "C", "M")):
202 itm.setIcon(1, UI.PixmapCache.getIcon("warning")) 241 itm.setIcon(1, UI.PixmapCache.getIcon("warning"))
203 elif code.startswith("N"): 242 elif code.startswith(("A", "N")):
204 itm.setIcon(1, UI.PixmapCache.getIcon("namingError")) 243 itm.setIcon(1, UI.PixmapCache.getIcon("namingError"))
205 elif code.startswith("D"): 244 elif code.startswith("D"):
206 itm.setIcon(1, UI.PixmapCache.getIcon("docstringError")) 245 itm.setIcon(1, UI.PixmapCache.getIcon("docstringError"))
207 else: 246 else:
208 itm.setIcon(1, UI.PixmapCache.getIcon("syntaxError")) 247 itm.setIcon(1, UI.PixmapCache.getIcon("syntaxError"))
241 def __modifyFixedResultItem(self, itm, text, fixed): 280 def __modifyFixedResultItem(self, itm, text, fixed):
242 """ 281 """
243 Private method to modify a result list entry to show its 282 Private method to modify a result list entry to show its
244 positive fixed state. 283 positive fixed state.
245 284
246 @param itm reference to the item to modify (QTreeWidgetItem) 285 @param itm reference to the item to modify
247 @param text text to be appended (string) 286 @type QTreeWidgetItem
248 @param fixed flag indicating a fixed issue (boolean) 287 @param text text to be appended
288 @type str
289 @param fixed flag indicating a fixed issue
290 @type bool
249 """ 291 """
250 if fixed: 292 if fixed:
251 code, message = text.split(None, 1) 293 code, message = text.split(None, 1)
252 itm.setText(2, message) 294 itm.setText(2, message)
253 itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed")) 295 itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed"))
261 """ 303 """
262 Private method to update the collected statistics. 304 Private method to update the collected statistics.
263 305
264 @param statistics dictionary of statistical data with 306 @param statistics dictionary of statistical data with
265 message code as key and message count as value 307 message code as key and message count as value
266 @param fixer reference to the code style fixer (CodeStyleFixer) 308 @type dict
267 @param ignoredErrors number of ignored errors (integer) 309 @param fixer reference to the code style fixer
310 @type CodeStyleFixer
311 @param ignoredErrors number of ignored errors
312 @type int
268 """ 313 """
269 self.__statistics["_FilesCount"] += 1 314 self.__statistics["_FilesCount"] += 1
270 stats = [k for k in statistics.keys() if k[0].isupper()] 315 stats = [k for k in statistics.keys() if k[0].isupper()]
271 if stats: 316 if stats:
272 self.__statistics["_FilesIssues"] += 1 317 self.__statistics["_FilesIssues"] += 1
280 325
281 def __updateFixerStatistics(self, fixer): 326 def __updateFixerStatistics(self, fixer):
282 """ 327 """
283 Private method to update the collected fixer related statistics. 328 Private method to update the collected fixer related statistics.
284 329
285 @param fixer reference to the code style fixer (CodeStyleFixer) 330 @param fixer reference to the code style fixer
331 @type CodeStyleFixer
286 """ 332 """
287 self.__statistics["_IssuesFixed"] += fixer 333 self.__statistics["_IssuesFixed"] += fixer
288 334
289 def __resetStatistics(self): 335 def __resetStatistics(self):
290 """ 336 """
298 344
299 def prepare(self, fileList, project): 345 def prepare(self, fileList, project):
300 """ 346 """
301 Public method to prepare the dialog with a list of filenames. 347 Public method to prepare the dialog with a list of filenames.
302 348
303 @param fileList list of filenames (list of strings) 349 @param fileList list of filenames
304 @param project reference to the project object (Project) 350 @type list of str
351 @param project reference to the project object
352 @type Project
305 """ 353 """
306 self.__fileOrFileList = fileList[:] 354 self.__fileOrFileList = fileList[:]
307 self.__project = project 355 self.__project = project
308 self.__forProject = True 356 self.__forProject = True
309 357
323 "IncludeMessages": "", 371 "IncludeMessages": "",
324 "RepeatMessages": False, 372 "RepeatMessages": False,
325 "FixCodes": "", 373 "FixCodes": "",
326 "FixIssues": False, 374 "FixIssues": False,
327 } 375 }
376 if "EnabledCheckerCategories" not in self.__data:
377 self.__data["EnabledCheckerCategories"] = ",".join(
378 CodeStyleCheckerDialog.checkCategories.keys())
328 if "MaxLineLength" not in self.__data: 379 if "MaxLineLength" not in self.__data:
329 self.__data["MaxLineLength"] = pycodestyle.MAX_LINE_LENGTH 380 self.__data["MaxLineLength"] = pycodestyle.MAX_LINE_LENGTH
330 if "MaxDocLineLength" not in self.__data: 381 if "MaxDocLineLength" not in self.__data:
331 # Use MAX_LINE_LENGTH to avoid messages on existing code 382 # Use MAX_LINE_LENGTH to avoid messages on existing code
332 self.__data["MaxDocLineLength"] = pycodestyle.MAX_LINE_LENGTH 383 self.__data["MaxDocLineLength"] = pycodestyle.MAX_LINE_LENGTH
370 self.__data["AnnotationsChecker"] = { 421 self.__data["AnnotationsChecker"] = {
371 "MinimumCoverage": 75, 422 "MinimumCoverage": 75,
372 "MaximumComplexity": 3, 423 "MaximumComplexity": 3,
373 } 424 }
374 425
426 self.__initCategoriesList(self.__data["EnabledCheckerCategories"])
375 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"]) 427 self.excludeFilesEdit.setText(self.__data["ExcludeFiles"])
376 self.excludeMessagesEdit.setText(self.__data["ExcludeMessages"]) 428 self.excludeMessagesEdit.setText(self.__data["ExcludeMessages"])
377 self.includeMessagesEdit.setText(self.__data["IncludeMessages"]) 429 self.includeMessagesEdit.setText(self.__data["IncludeMessages"])
378 self.repeatCheckBox.setChecked(self.__data["RepeatMessages"]) 430 self.repeatCheckBox.setChecked(self.__data["RepeatMessages"])
379 self.fixIssuesEdit.setText(self.__data["FixCodes"]) 431 self.fixIssuesEdit.setText(self.__data["FixCodes"])
401 self.__data["CommentedCodeChecker"]["Aggressive"]) 453 self.__data["CommentedCodeChecker"]["Aggressive"])
402 self.minAnnotationsCoverageSpinBox.setValue( 454 self.minAnnotationsCoverageSpinBox.setValue(
403 self.__data["AnnotationsChecker"]["MinimumCoverage"]) 455 self.__data["AnnotationsChecker"]["MinimumCoverage"])
404 self.maxAnnotationsComplexitySpinBox.setValue( 456 self.maxAnnotationsComplexitySpinBox.setValue(
405 self.__data["AnnotationsChecker"]["MaximumComplexity"]) 457 self.__data["AnnotationsChecker"]["MaximumComplexity"])
458
459 self.__cleanupData()
406 460
407 def start(self, fn, save=False, repeat=None): 461 def start(self, fn, save=False, repeat=None):
408 """ 462 """
409 Public slot to start the code style check. 463 Public slot to start the code style check.
410 464
411 @param fn file or list of files or directory to be checked 465 @param fn file or list of files or directory to be checked
412 (string or list of strings) 466 @type str or list of str
413 @keyparam save flag indicating to save the given 467 @param save flag indicating to save the given file/file list/directory
414 file/file list/directory (boolean) 468 @type bool
415 @keyparam repeat state of the repeat check box if it is not None 469 @param repeat state of the repeat check box if it is not None
416 (None or boolean) 470 @type None or bool
417 """ 471 """
418 if self.__project is None: 472 if self.__project is None:
419 self.__project = e5App().getObject("Project") 473 self.__project = e5App().getObject("Project")
420 474
421 self.mainWidget.setCurrentWidget(self.runTab) 475 self.mainWidget.setCurrentWidget(self.runTab)
461 ] 515 ]
462 516
463 self.__errorItem = None 517 self.__errorItem = None
464 self.__resetStatistics() 518 self.__resetStatistics()
465 self.__clearErrors(self.files) 519 self.__clearErrors(self.files)
520 self.__cleanupData()
466 521
467 if len(self.files) > 0: 522 if len(self.files) > 0:
468 self.checkProgress.setMaximum(len(self.files)) 523 self.checkProgress.setMaximum(len(self.files))
469 self.checkProgressLabel.setVisible(len(self.files) > 1) 524 self.checkProgressLabel.setVisible(len(self.files) > 1)
470 self.checkProgress.setVisible(len(self.files) > 1) 525 self.checkProgress.setVisible(len(self.files) > 1)
471 QApplication.processEvents() 526 QApplication.processEvents()
472 527
473 # extract the configuration values 528 # extract the configuration values
474 excludeMessages = self.excludeMessagesEdit.text() 529 excludeMessages = self.__assembleExcludeMessages()
475 includeMessages = self.includeMessagesEdit.text() 530 includeMessages = self.includeMessagesEdit.text()
476 repeatMessages = self.repeatCheckBox.isChecked() 531 repeatMessages = self.repeatCheckBox.isChecked()
477 fixCodes = self.fixIssuesEdit.text() 532 fixCodes = self.fixIssuesEdit.text()
478 noFixCodes = self.noFixIssuesEdit.text() 533 noFixCodes = self.noFixIssuesEdit.text()
479 self.__noFixCodesList = [ 534 self.__noFixCodesList = [
542 597
543 This method looks for comment lines like '# eflag: noqa = M601' 598 This method looks for comment lines like '# eflag: noqa = M601'
544 at the end of the source in order to extend the list of excluded 599 at the end of the source in order to extend the list of excluded
545 messages for one file only. 600 messages for one file only.
546 601
547 @param source source text (list of str or str) 602 @param source source text
603 @type list of str or str
548 @return list of checker options 604 @return list of checker options
605 @rtype list
549 """ 606 """
550 options = self.__options[:] 607 options = self.__options[:]
551 flags = Utilities.extractFlags(source) 608 flags = Utilities.extractFlags(source)
552 if "noqa" in flags and isinstance(flags["noqa"], basestring): 609 if "noqa" in flags and isinstance(flags["noqa"], basestring):
553 excludeMessages = options[0].strip().rstrip(",") 610 excludeMessages = options[0].strip().rstrip(",")
561 """ 618 """
562 Public method to start a style check for one file. 619 Public method to start a style check for one file.
563 620
564 The results are reported to the __processResult slot. 621 The results are reported to the __processResult slot.
565 622
566 @keyparam codestring optional sourcestring (str) 623 @param codestring optional sourcestring
624 @type str
567 """ 625 """
568 if not self.files: 626 if not self.files:
569 self.checkProgressLabel.setPath("") 627 self.checkProgressLabel.setPath("")
570 self.checkProgress.setMaximum(1) 628 self.checkProgress.setMaximum(1)
571 self.checkProgress.setValue(1) 629 self.checkProgress.setValue(1)
702 760
703 def __processResult(self, fn, codeStyleCheckerStats, fixes, results): 761 def __processResult(self, fn, codeStyleCheckerStats, fixes, results):
704 """ 762 """
705 Private slot called after perfoming a style check on one file. 763 Private slot called after perfoming a style check on one file.
706 764
707 @param fn filename of the just checked file (str) 765 @param fn filename of the just checked file
708 @param codeStyleCheckerStats stats of style and name check (dict) 766 @type str
709 @param fixes number of applied fixes (int) 767 @param codeStyleCheckerStats stats of style and name check
768 @type dict
769 @param fixes number of applied fixes
770 @type int
710 @param results tuple for each found violation of style (tuple of 771 @param results tuple for each found violation of style (tuple of
711 lineno (int), position (int), text (str), ignored (bool), 772 lineno, position, text, ignored, fixed, autofixing)
712 fixed (bool), autofixing (bool)) 773 @type tuplt of tuple of (int, int, str, bool, bool, bool)
713 """ 774 """
714 if self.__finished: 775 if self.__finished:
715 return 776 return
716 777
717 # Check if it's the requested file, otherwise ignore signal if not 778 # Check if it's the requested file, otherwise ignore signal if not
805 866
806 def __getEol(self, fn): 867 def __getEol(self, fn):
807 """ 868 """
808 Private method to get the applicable eol string. 869 Private method to get the applicable eol string.
809 870
810 @param fn filename where to determine the line ending (str) 871 @param fn filename where to determine the line ending
811 @return eol string (string) 872 @type str
873 @return eol string
874 @rtype str
812 """ 875 """
813 if self.__project.isOpen() and self.__project.isProjectFile(fn): 876 if self.__project.isOpen() and self.__project.isProjectFile(fn):
814 eol = self.__project.getEolString() 877 eol = self.__project.getEolString()
815 else: 878 else:
816 eol = Utilities.linesep() 879 eol = Utilities.linesep()
819 @pyqtSlot() 882 @pyqtSlot()
820 def on_startButton_clicked(self): 883 def on_startButton_clicked(self):
821 """ 884 """
822 Private slot to start a code style check run. 885 Private slot to start a code style check run.
823 """ 886 """
887 self.__cleanupData()
888
824 if self.__forProject: 889 if self.__forProject:
825 data = { 890 data = {
891 "EnabledCheckerCategories": self.__getCategories(True),
826 "ExcludeFiles": self.excludeFilesEdit.text(), 892 "ExcludeFiles": self.excludeFilesEdit.text(),
827 "ExcludeMessages": self.excludeMessagesEdit.text(), 893 "ExcludeMessages": self.excludeMessagesEdit.text(),
828 "IncludeMessages": self.includeMessagesEdit.text(), 894 "IncludeMessages": self.includeMessagesEdit.text(),
829 "RepeatMessages": self.repeatCheckBox.isChecked(), 895 "RepeatMessages": self.repeatCheckBox.isChecked(),
830 "FixCodes": self.fixIssuesEdit.text(), 896 "FixCodes": self.fixIssuesEdit.text(),
874 """ 940 """
875 Private slot to restart a code style check run. 941 Private slot to restart a code style check run.
876 """ 942 """
877 self.on_startButton_clicked() 943 self.on_startButton_clicked()
878 944
879 def __selectCodes(self, edit, showFixCodes): 945 def __selectCodes(self, edit, categories, showFixCodes):
880 """ 946 """
881 Private method to select message codes via a selection dialog. 947 Private method to select message codes via a selection dialog.
882 948
883 @param edit reference of the line edit to be populated (QLineEdit) 949 @param edit reference of the line edit to be populated
950 @type QLineEdit
951 @param categories list of message categories to omit
952 @type list of str
884 @param showFixCodes flag indicating to show a list of fixable 953 @param showFixCodes flag indicating to show a list of fixable
885 issues (boolean) 954 issues
955 @type bool
886 """ 956 """
887 from .CodeStyleCodeSelectionDialog import CodeStyleCodeSelectionDialog 957 from .CodeStyleCodeSelectionDialog import CodeStyleCodeSelectionDialog
888 dlg = CodeStyleCodeSelectionDialog(edit.text(), showFixCodes, self) 958 dlg = CodeStyleCodeSelectionDialog(edit.text(), categories,
959 showFixCodes, self)
889 if dlg.exec_() == QDialog.Accepted: 960 if dlg.exec_() == QDialog.Accepted:
890 edit.setText(dlg.getSelectedCodes()) 961 edit.setText(dlg.getSelectedCodes())
891 962
892 @pyqtSlot() 963 @pyqtSlot()
893 def on_excludeMessagesSelectButton_clicked(self): 964 def on_excludeMessagesSelectButton_clicked(self):
894 """ 965 """
895 Private slot to select the message codes to be excluded via a 966 Private slot to select the message codes to be excluded via a
896 selection dialog. 967 selection dialog.
897 """ 968 """
898 self.__selectCodes(self.excludeMessagesEdit, False) 969 self.__selectCodes(self.excludeMessagesEdit,
970 self.__getCategories(False, asList=True),
971 False)
899 972
900 @pyqtSlot() 973 @pyqtSlot()
901 def on_includeMessagesSelectButton_clicked(self): 974 def on_includeMessagesSelectButton_clicked(self):
902 """ 975 """
903 Private slot to select the message codes to be included via a 976 Private slot to select the message codes to be included via a
904 selection dialog. 977 selection dialog.
905 """ 978 """
906 self.__selectCodes(self.includeMessagesEdit, False) 979 self.__selectCodes(self.includeMessagesEdit,
980 self.__getCategories(True, asList=True),
981 False)
907 982
908 @pyqtSlot() 983 @pyqtSlot()
909 def on_fixIssuesSelectButton_clicked(self): 984 def on_fixIssuesSelectButton_clicked(self):
910 """ 985 """
911 Private slot to select the issue codes to be fixed via a 986 Private slot to select the issue codes to be fixed via a
912 selection dialog. 987 selection dialog.
913 """ 988 """
914 self.__selectCodes(self.fixIssuesEdit, True) 989 self.__selectCodes(self.fixIssuesEdit, [], True)
915 990
916 @pyqtSlot() 991 @pyqtSlot()
917 def on_noFixIssuesSelectButton_clicked(self): 992 def on_noFixIssuesSelectButton_clicked(self):
918 """ 993 """
919 Private slot to select the issue codes not to be fixed via a 994 Private slot to select the issue codes not to be fixed via a
920 selection dialog. 995 selection dialog.
921 """ 996 """
922 self.__selectCodes(self.noFixIssuesEdit, True) 997 self.__selectCodes(self.noFixIssuesEdit, [], True)
923 998
924 @pyqtSlot(QTreeWidgetItem, int) 999 @pyqtSlot(QTreeWidgetItem, int)
925 def on_resultList_itemActivated(self, item, column): 1000 def on_resultList_itemActivated(self, item, column):
926 """ 1001 """
927 Private slot to handle the activation of an item. 1002 Private slot to handle the activation of an item.
928 1003
929 @param item reference to the activated item (QTreeWidgetItem) 1004 @param item reference to the activated item
930 @param column column the item was activated in (integer) 1005 @type QTreeWidgetItem
1006 @param column column the item was activated in
1007 @type int
931 """ 1008 """
932 if self.results != CodeStyleCheckerDialog.hasResults: 1009 if self.results != CodeStyleCheckerDialog.hasResults:
933 return 1010 return
934 1011
935 if item.parent(): 1012 if item.parent():
1012 @pyqtSlot() 1089 @pyqtSlot()
1013 def on_loadDefaultButton_clicked(self): 1090 def on_loadDefaultButton_clicked(self):
1014 """ 1091 """
1015 Private slot to load the default configuration values. 1092 Private slot to load the default configuration values.
1016 """ 1093 """
1094 self.__initCategoriesList(Preferences.Prefs.settings.value(
1095 "PEP8/EnabledCheckerCategories",
1096 ",".join(CodeStyleCheckerDialog.checkCategories.keys())))
1017 self.excludeFilesEdit.setText(Preferences.Prefs.settings.value( 1097 self.excludeFilesEdit.setText(Preferences.Prefs.settings.value(
1018 "PEP8/ExcludeFilePatterns", "")) 1098 "PEP8/ExcludeFilePatterns", ""))
1019 self.excludeMessagesEdit.setText(Preferences.Prefs.settings.value( 1099 self.excludeMessagesEdit.setText(Preferences.Prefs.settings.value(
1020 "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE)) 1100 "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE))
1021 self.includeMessagesEdit.setText(Preferences.Prefs.settings.value( 1101 self.includeMessagesEdit.setText(Preferences.Prefs.settings.value(
1073 Preferences.Prefs.settings.value( 1153 Preferences.Prefs.settings.value(
1074 "PEP8/MinimumAnnotationsCoverage", 75))) 1154 "PEP8/MinimumAnnotationsCoverage", 75)))
1075 self.maxAnnotationsComplexitySpinBox.setValue(int( 1155 self.maxAnnotationsComplexitySpinBox.setValue(int(
1076 Preferences.Prefs.settings.value( 1156 Preferences.Prefs.settings.value(
1077 "PEP8/MaximumAnnotationComplexity", 3))) 1157 "PEP8/MaximumAnnotationComplexity", 3)))
1158
1159 self.__cleanupData()
1078 1160
1079 @pyqtSlot() 1161 @pyqtSlot()
1080 def on_storeDefaultButton_clicked(self): 1162 def on_storeDefaultButton_clicked(self):
1081 """ 1163 """
1082 Private slot to store the current configuration values as 1164 Private slot to store the current configuration values as
1083 default values. 1165 default values.
1084 """ 1166 """
1085 Preferences.Prefs.settings.setValue( 1167 Preferences.Prefs.settings.setValue(
1168 "PEP8/EnabledCheckerCategories", self.__getCategories(True))
1169 Preferences.Prefs.settings.setValue(
1086 "PEP8/ExcludeFilePatterns", self.excludeFilesEdit.text()) 1170 "PEP8/ExcludeFilePatterns", self.excludeFilesEdit.text())
1087 Preferences.Prefs.settings.setValue( 1171 Preferences.Prefs.settings.setValue(
1088 "PEP8/ExcludeMessages", self.excludeMessagesEdit.text()) 1172 "PEP8/ExcludeMessages", self.excludeMessagesEdit.text())
1089 Preferences.Prefs.settings.setValue( 1173 Preferences.Prefs.settings.setValue(
1090 "PEP8/IncludeMessages", self.includeMessagesEdit.text()) 1174 "PEP8/IncludeMessages", self.includeMessagesEdit.text())
1142 @pyqtSlot() 1226 @pyqtSlot()
1143 def on_resetDefaultButton_clicked(self): 1227 def on_resetDefaultButton_clicked(self):
1144 """ 1228 """
1145 Private slot to reset the configuration values to their default values. 1229 Private slot to reset the configuration values to their default values.
1146 """ 1230 """
1231 Preferences.Prefs.settings.setValue(
1232 "PEP8/EnabledCheckerCategories",
1233 ",".join(CodeStyleCheckerDialog.checkCategories.keys()))
1147 Preferences.Prefs.settings.setValue("PEP8/ExcludeFilePatterns", "") 1234 Preferences.Prefs.settings.setValue("PEP8/ExcludeFilePatterns", "")
1148 Preferences.Prefs.settings.setValue( 1235 Preferences.Prefs.settings.setValue(
1149 "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE) 1236 "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE)
1150 Preferences.Prefs.settings.setValue("PEP8/IncludeMessages", "") 1237 Preferences.Prefs.settings.setValue("PEP8/IncludeMessages", "")
1151 Preferences.Prefs.settings.setValue("PEP8/RepeatMessages", False) 1238 Preferences.Prefs.settings.setValue("PEP8/RepeatMessages", False)
1188 @pyqtSlot(QAbstractButton) 1275 @pyqtSlot(QAbstractButton)
1189 def on_buttonBox_clicked(self, button): 1276 def on_buttonBox_clicked(self, button):
1190 """ 1277 """
1191 Private slot called by a button of the button box clicked. 1278 Private slot called by a button of the button box clicked.
1192 1279
1193 @param button button that was clicked (QAbstractButton) 1280 @param button button that was clicked
1281 @type QAbstractButton
1194 """ 1282 """
1195 if button == self.buttonBox.button(QDialogButtonBox.Close): 1283 if button == self.buttonBox.button(QDialogButtonBox.Close):
1196 self.close() 1284 self.close()
1197 elif button == self.buttonBox.button(QDialogButtonBox.Cancel): 1285 elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
1198 if self.__batch: 1286 if self.__batch:
1208 def __clearErrors(self, files): 1296 def __clearErrors(self, files):
1209 """ 1297 """
1210 Private method to clear all warning markers of open editors to be 1298 Private method to clear all warning markers of open editors to be
1211 checked. 1299 checked.
1212 1300
1213 @param files list of files to be checked (list of string) 1301 @param files list of files to be checked
1302 @type list of str
1214 """ 1303 """
1215 vm = e5App().getObject("ViewManager") 1304 vm = e5App().getObject("ViewManager")
1216 openFiles = vm.getOpenFilenames() 1305 openFiles = vm.getOpenFilenames()
1217 for file in [f for f in openFiles if f in files]: 1306 for file in [f for f in openFiles if f in files]:
1218 editor = vm.getOpenEditor(file) 1307 editor = vm.getOpenEditor(file)
1222 def on_fixButton_clicked(self): 1311 def on_fixButton_clicked(self):
1223 """ 1312 """
1224 Private slot to fix selected issues. 1313 Private slot to fix selected issues.
1225 1314
1226 Build a dictionary of issues to fix. Update the initialized __options. 1315 Build a dictionary of issues to fix. Update the initialized __options.
1227 Then call check with the dict as keyparam to fix selected issues. 1316 Then call check with the dict as keyparam to fix selected issues.
1228 """ 1317 """
1229 fixableItems = self.__getSelectedFixableItems() 1318 fixableItems = self.__getSelectedFixableItems()
1230 # dictionary of lists of tuples containing the issue and the item 1319 # dictionary of lists of tuples containing the issue and the item
1231 fixesDict = {} 1320 fixesDict = {}
1232 for itm in fixableItems: 1321 for itm in fixableItems:
1258 1347
1259 def __getSelectedFixableItems(self): 1348 def __getSelectedFixableItems(self):
1260 """ 1349 """
1261 Private method to extract all selected items for fixable issues. 1350 Private method to extract all selected items for fixable issues.
1262 1351
1263 @return selected items for fixable issues (list of QTreeWidgetItem) 1352 @return selected items for fixable issues
1353 @rtype list of QTreeWidgetItem
1264 """ 1354 """
1265 fixableItems = [] 1355 fixableItems = []
1266 for itm in self.resultList.selectedItems(): 1356 for itm in self.resultList.selectedItems():
1267 if itm.childCount() > 0: 1357 if itm.childCount() > 0:
1268 for index in range(itm.childCount()): 1358 for index in range(itm.childCount()):
1276 1366
1277 def __itemFixable(self, itm): 1367 def __itemFixable(self, itm):
1278 """ 1368 """
1279 Private method to check, if an item has a fixable issue. 1369 Private method to check, if an item has a fixable issue.
1280 1370
1281 @param itm item to be checked (QTreeWidgetItem) 1371 @param itm item to be checked
1282 @return flag indicating a fixable issue (boolean) 1372 @type QTreeWidgetItem
1373 @return flag indicating a fixable issue
1374 @rtype bool
1283 """ 1375 """
1284 return (itm.data(0, self.fixableRole) and 1376 return (itm.data(0, self.fixableRole) and
1285 not itm.data(0, self.ignoredRole)) 1377 not itm.data(0, self.ignoredRole))
1286 1378
1287 def __initFuturesList(self, selectedFutures): 1379 def __initFuturesList(self, selectedFutures):
1379 """ 1471 """
1380 for itm in self.builtinsAssignmentList.selectedItems(): 1472 for itm in self.builtinsAssignmentList.selectedItems():
1381 index = self.builtinsAssignmentList.indexOfTopLevelItem(itm) 1473 index = self.builtinsAssignmentList.indexOfTopLevelItem(itm)
1382 self.builtinsAssignmentList.takeTopLevelItem(index) 1474 self.builtinsAssignmentList.takeTopLevelItem(index)
1383 del itm 1475 del itm
1476
1477 def __initCategoriesList(self, enabledCategories):
1478 """
1479 Private method to set the enabled status of the checker categories.
1480
1481 @param enabledCategories comma separated list of enabled checker
1482 categories
1483 @type str
1484 """
1485 if enabledCategories:
1486 enabledCategoriesList = [
1487 c.strip() for c in enabledCategories.split(",")
1488 if bool(c.strip())]
1489 else:
1490 enabledCategoriesList = list(
1491 CodeStyleCheckerDialog.checkCategories.keys())
1492 for row in range(self.categoriesList.count()):
1493 itm = self.categoriesList.item(row)
1494 if itm.data(Qt.UserRole) in enabledCategoriesList:
1495 itm.setCheckState(Qt.Checked)
1496 else:
1497 itm.setCheckState(Qt.Unchecked)
1498
1499 def __getCategories(self, enabled, asList=False):
1500 """
1501 Private method to get the enabled or disabled checker categories.
1502
1503 @param enabled flag indicating to return enabled categories
1504 @type bool
1505 @param asList flag indicating to return the checker categories as a
1506 Python list
1507 @type bool
1508 @return checker categories as a list or comma separated string
1509 @rtype str or list of str
1510 """
1511 state = Qt.Checked if enabled else Qt.Unchecked
1512
1513 checkerList = []
1514 for row in range(self.categoriesList.count()):
1515 itm = self.categoriesList.item(row)
1516 if itm.checkState() == state:
1517 checkerList.append(itm.data(Qt.UserRole))
1518 if asList:
1519 return checkerList
1520 else:
1521 return ", ".join(checkerList)
1522
1523 def __assembleExcludeMessages(self):
1524 """
1525 Private method to assemble the list of excluded checks.
1526
1527 @return list of excluded checks as a comma separated string.
1528 @rtype str
1529 """
1530 excludeMessages = self.excludeMessagesEdit.text()
1531 disabledCategories = self.__getCategories(False)
1532
1533 if excludeMessages and disabledCategories:
1534 return disabledCategories + "," + excludeMessages
1535 elif disabledCategories:
1536 return disabledCategories
1537 elif excludeMessages:
1538 return excludeMessages
1539 else:
1540 return ""
1541
1542 def __cleanupData(self):
1543 """
1544 Private method to clean the loaded/entered data of redundant entries.
1545 """
1546 # Migrate single letter exclude messages to disabled checker categories
1547 # and delete them from exlude messages
1548 excludedMessages = [
1549 m.strip()
1550 for m in self.excludeMessagesEdit.text().split(",")
1551 if bool(m)
1552 ]
1553 excludedMessageCategories = [
1554 c for c in excludedMessages if len(c) == 1
1555 ]
1556 enabledCheckers = self.__getCategories(True, asList=True)
1557 for category in excludedMessageCategories:
1558 if category in enabledCheckers:
1559 enabledCheckers.remove(category)
1560 excludedMessages.remove(category)
1561
1562 # Remove excluded messages of an already excluded category
1563 disabledCheckers = self.__getCategories(False, asList=True)
1564 for message in excludedMessages[:]:
1565 if message[0] in disabledCheckers:
1566 excludedMessages.remove(message)
1567
1568 self.excludeMessagesEdit.setText(",".join(excludedMessages))
1569 self.__initCategoriesList(",".join(enabledCheckers))

eric ide

mercurial