8 """ |
8 """ |
9 |
9 |
10 import os |
10 import os |
11 import fnmatch |
11 import fnmatch |
12 import copy |
12 import copy |
|
13 import collections |
13 |
14 |
14 from PyQt5.QtCore import pyqtSlot, Qt, QTimer, QCoreApplication |
15 from PyQt5.QtCore import pyqtSlot, Qt, QTimer, QCoreApplication |
15 from PyQt5.QtGui import QIcon |
16 from PyQt5.QtGui import QIcon |
16 from PyQt5.QtWidgets import ( |
17 from PyQt5.QtWidgets import ( |
17 QDialog, QTreeWidgetItem, QAbstractButton, QDialogButtonBox, QApplication, |
18 QDialog, QTreeWidgetItem, QAbstractButton, QDialogButtonBox, QApplication, |
193 |
194 |
194 self.__fileOrFileList = "" |
195 self.__fileOrFileList = "" |
195 self.__project = None |
196 self.__project = None |
196 self.__forProject = False |
197 self.__forProject = False |
197 self.__data = {} |
198 self.__data = {} |
198 self.__statistics = {} |
199 self.__statistics = collections.defaultdict(self.__defaultStatistics) |
199 self.__onlyFixes = {} |
200 self.__onlyFixes = {} |
200 self.__noFixCodesList = [] |
201 self.__noFixCodesList = [] |
201 self.__detectedCodes = [] |
202 self.__detectedCodes = [] |
202 |
203 |
203 self.on_loadDefaultButton_clicked() |
204 self.on_loadDefaultButton_clicked() |
204 |
205 |
205 self.mainWidget.setCurrentWidget(self.configureTab) |
206 self.mainWidget.setCurrentWidget(self.configureTab) |
206 self.optionsTabWidget.setCurrentWidget(self.globalOptionsTab) |
207 self.optionsTabWidget.setCurrentWidget(self.globalOptionsTab) |
|
208 |
|
209 def __defaultStatistics(self): |
|
210 """ |
|
211 Private method to return the default statistics entry. |
|
212 |
|
213 @return dictionary with default statistics entry |
|
214 @rtype dict |
|
215 """ |
|
216 return { |
|
217 "total": 0, |
|
218 "ignored": 0, |
|
219 } |
207 |
220 |
208 def __resort(self): |
221 def __resort(self): |
209 """ |
222 """ |
210 Private method to resort the tree. |
223 Private method to resort the tree. |
211 """ |
224 """ |
379 @type int |
392 @type int |
380 @param securityOk number of acknowledged security reports |
393 @param securityOk number of acknowledged security reports |
381 @type int |
394 @type int |
382 """ |
395 """ |
383 self.__statistics["_FilesCount"] += 1 |
396 self.__statistics["_FilesCount"] += 1 |
384 stats = [k for k in statistics.keys() if k[0].isupper()] |
397 stats = [k for k in statistics if k[0].isupper()] |
385 if stats: |
398 if stats: |
386 self.__statistics["_FilesIssues"] += 1 |
399 self.__statistics["_FilesIssues"] += 1 |
387 for key in statistics: |
400 for key in stats: |
388 if key in self.__statistics: |
401 self.__statistics[key]["total"] += statistics[key] |
389 self.__statistics[key] += statistics[key] |
402 for key in ignoredErrors: |
390 else: |
403 self.__statistics[key]["ignored"] += ignoredErrors[key] |
391 self.__statistics[key] = statistics[key] |
|
392 self.__statistics["_IssuesFixed"] += fixer |
404 self.__statistics["_IssuesFixed"] += fixer |
393 self.__statistics["_IgnoredErrors"] += ignoredErrors |
|
394 self.__statistics["_SecurityOK"] += securityOk |
405 self.__statistics["_SecurityOK"] += securityOk |
395 |
406 |
396 def __updateFixerStatistics(self, fixer): |
407 def __updateFixerStatistics(self, fixer): |
397 """ |
408 """ |
398 Private method to update the collected fixer related statistics. |
409 Private method to update the collected fixer related statistics. |
404 |
415 |
405 def __resetStatistics(self): |
416 def __resetStatistics(self): |
406 """ |
417 """ |
407 Private slot to reset the statistics data. |
418 Private slot to reset the statistics data. |
408 """ |
419 """ |
409 self.__statistics = {} |
420 self.__statistics.clear() |
410 self.__statistics["_FilesCount"] = 0 |
421 self.__statistics["_FilesCount"] = 0 |
411 self.__statistics["_FilesIssues"] = 0 |
422 self.__statistics["_FilesIssues"] = 0 |
412 self.__statistics["_IssuesFixed"] = 0 |
423 self.__statistics["_IssuesFixed"] = 0 |
413 self.__statistics["_IgnoredErrors"] = 0 |
|
414 self.__statistics["_SecurityOK"] = 0 |
424 self.__statistics["_SecurityOK"] = 0 |
415 |
425 |
416 def prepare(self, fileList, project): |
426 def prepare(self, fileList, project): |
417 """ |
427 """ |
418 Public method to prepare the dialog with a list of filenames. |
428 Public method to prepare the dialog with a list of filenames. |
962 # disable updates of the list for speed |
972 # disable updates of the list for speed |
963 self.resultList.setUpdatesEnabled(False) |
973 self.resultList.setUpdatesEnabled(False) |
964 self.resultList.setSortingEnabled(False) |
974 self.resultList.setSortingEnabled(False) |
965 |
975 |
966 fixed = None |
976 fixed = None |
967 ignoredErrors = 0 |
977 ignoredErrors = collections.defaultdict(int) |
968 securityOk = 0 |
978 securityOk = 0 |
969 if self.__itms: |
979 if self.__itms: |
970 for itm, result in zip(self.__itms, results): |
980 for itm, result in zip(self.__itms, results): |
971 self.__modifyFixedResultItem(itm, result) |
981 self.__modifyFixedResultItem(itm, result) |
972 self.__updateFixerStatistics(fixes) |
982 self.__updateFixerStatistics(fixes) |
973 else: |
983 else: |
974 self.__lastFileItem = None |
984 self.__lastFileItem = None |
975 |
985 |
976 for result in results: |
986 for result in results: |
977 if result["ignored"]: |
987 if result["ignored"]: |
978 ignoredErrors += 1 |
988 ignoredErrors[result["code"]] += 1 |
979 if self.showIgnored: |
989 if self.showIgnored: |
980 result["display"] = self.tr( |
990 result["display"] = self.tr( |
981 "{0} (ignored)" |
991 "{0} (ignored)" |
982 ).format(result["display"]) |
992 ).format(result["display"]) |
983 else: |
993 else: |