9 |
9 |
10 import os |
10 import os |
11 import fnmatch |
11 import fnmatch |
12 import contextlib |
12 import contextlib |
13 |
13 |
14 from PyQt5.QtCore import pyqtSlot, qVersion, Qt, QTimer, QRegExp |
14 from PyQt6.QtCore import pyqtSlot, Qt, QTimer |
15 from PyQt5.QtWidgets import ( |
15 from PyQt6.QtWidgets import ( |
16 QDialog, QDialogButtonBox, QAbstractButton, QHeaderView, QTreeWidgetItem, |
16 QDialog, QDialogButtonBox, QAbstractButton, QHeaderView, QTreeWidgetItem, |
17 QApplication, QMenu |
17 QApplication, QMenu |
18 ) |
18 ) |
19 |
19 |
20 from .Ui_VultureCheckerDialog import Ui_VultureCheckerDialog |
20 from .Ui_VultureCheckerDialog import Ui_VultureCheckerDialog |
21 |
21 |
22 from E5Gui.E5Application import e5App |
22 from EricWidgets.EricApplication import ericApp |
23 |
23 |
24 import Preferences |
24 import Preferences |
25 import Utilities |
25 import Utilities |
26 |
26 |
27 |
27 |
57 |
57 |
58 class VultureCheckerDialog(QDialog, Ui_VultureCheckerDialog): |
58 class VultureCheckerDialog(QDialog, Ui_VultureCheckerDialog): |
59 """ |
59 """ |
60 Class implementing a dialog to show the vulture check results. |
60 Class implementing a dialog to show the vulture check results. |
61 """ |
61 """ |
62 FilePathRole = Qt.UserRole + 1 |
62 FilePathRole = Qt.ItemDataRole.UserRole + 1 |
63 TypeRole = Qt.UserRole + 2 |
63 TypeRole = Qt.ItemDataRole.UserRole + 2 |
64 |
64 |
65 def __init__(self, vultureService, parent=None): |
65 def __init__(self, vultureService, parent=None): |
66 """ |
66 """ |
67 Constructor |
67 Constructor |
68 |
68 |
71 @param parent reference to the parent widget |
71 @param parent reference to the parent widget |
72 @type QWidget |
72 @type QWidget |
73 """ |
73 """ |
74 super().__init__(parent) |
74 super().__init__(parent) |
75 self.setupUi(self) |
75 self.setupUi(self) |
76 self.setWindowFlags(Qt.Window) |
76 self.setWindowFlags(Qt.WindowType.Window) |
77 |
77 |
78 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) |
78 self.buttonBox.button( |
79 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) |
79 QDialogButtonBox.StandardButton.Close).setEnabled(False) |
|
80 self.buttonBox.button( |
|
81 QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
80 |
82 |
81 self.resultList.headerItem().setText(self.resultList.columnCount(), "") |
83 self.resultList.headerItem().setText(self.resultList.columnCount(), "") |
82 |
84 |
83 self.__menu = QMenu(self) |
85 self.__menu = QMenu(self) |
84 self.__whiteListAct = self.__menu.addAction( |
86 self.__whiteListAct = self.__menu.addAction( |
99 self.vultureService.error.connect(self.__processError) |
101 self.vultureService.error.connect(self.__processError) |
100 self.vultureService.batchFinished.connect(self.__batchFinished) |
102 self.vultureService.batchFinished.connect(self.__batchFinished) |
101 |
103 |
102 self.cancelled = False |
104 self.cancelled = False |
103 |
105 |
104 self.__project = e5App().getObject("Project") |
106 self.__project = ericApp().getObject("Project") |
105 self.__finished = True |
107 self.__finished = True |
106 self.__errorItem = None |
108 self.__errorItem = None |
107 self.__data = None |
109 self.__data = None |
108 self.__slotsAreUsed = True |
110 self.__slotsAreUsed = True |
109 |
111 |
131 """ |
133 """ |
132 if self.__errorItem is None: |
134 if self.__errorItem is None: |
133 self.__errorItem = QTreeWidgetItem(self.resultList, [ |
135 self.__errorItem = QTreeWidgetItem(self.resultList, [ |
134 self.tr("Errors")]) |
136 self.tr("Errors")]) |
135 self.__errorItem.setExpanded(True) |
137 self.__errorItem.setExpanded(True) |
136 self.__errorItem.setForeground(0, Qt.red) |
138 self.__errorItem.setForeground(0, Qt.GlobalColor.red) |
137 |
139 |
138 msg = "{0} ({1})".format(self.__project.getRelativePath(filename), |
140 msg = "{0} ({1})".format(self.__project.getRelativePath(filename), |
139 message) |
141 message) |
140 if not self.resultList.findItems(msg, Qt.MatchExactly): |
142 if not self.resultList.findItems(msg, Qt.MatchFlag.MatchExactly): |
141 itm = QTreeWidgetItem(self.__errorItem, [msg]) |
143 itm = QTreeWidgetItem(self.__errorItem, [msg]) |
142 itm.setForeground(0, Qt.red) |
144 itm.setForeground(0, Qt.GlobalColor.red) |
143 itm.setFirstColumnSpanned(True) |
145 itm.setFirstColumnSpanned(True) |
144 |
146 |
145 def prepare(self, fileList, project): |
147 def prepare(self, fileList, project): |
146 """ |
148 """ |
147 Public method to prepare the dialog with a list of filenames. |
149 Public method to prepare the dialog with a list of filenames. |
152 @type Project |
154 @type Project |
153 """ |
155 """ |
154 self.__fileList = fileList[:] |
156 self.__fileList = fileList[:] |
155 self.__project = project |
157 self.__project = project |
156 |
158 |
157 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) |
159 self.buttonBox.button( |
158 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) |
160 QDialogButtonBox.StandardButton.Close).setEnabled(True) |
159 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) |
161 self.buttonBox.button( |
|
162 QDialogButtonBox.StandardButton.Cancel).setEnabled(False) |
|
163 self.buttonBox.button( |
|
164 QDialogButtonBox.StandardButton.Close).setDefault(True) |
160 |
165 |
161 self.filterFrame.setVisible(True) |
166 self.filterFrame.setVisible(True) |
162 |
167 |
163 self.__data = self.__project.getData( |
168 self.__data = self.__project.getData( |
164 "CHECKERSPARMS", "Vulture") |
169 "CHECKERSPARMS", "Vulture") |
195 @type str or list of str |
200 @type str or list of str |
196 """ |
201 """ |
197 self.cancelled = False |
202 self.cancelled = False |
198 self.__errorItem = None |
203 self.__errorItem = None |
199 self.resultList.clear() |
204 self.resultList.clear() |
200 QApplication.processEvents() |
205 |
201 |
206 self.buttonBox.button( |
202 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) |
207 QDialogButtonBox.StandardButton.Close).setEnabled(False) |
203 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) |
208 self.buttonBox.button( |
204 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) |
209 QDialogButtonBox.StandardButton.Cancel).setEnabled(True) |
|
210 self.buttonBox.button( |
|
211 QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
205 QApplication.processEvents() |
212 QApplication.processEvents() |
206 |
213 |
207 self.__prepareResultLists() |
214 self.__prepareResultLists() |
208 |
215 |
209 if isinstance(fn, list): |
216 if isinstance(fn, list): |
210 self.files = fn |
217 self.files = fn |
211 elif os.path.isdir(fn): |
218 elif os.path.isdir(fn): |
212 self.files = [] |
219 self.files = [] |
213 extensions = set(Preferences.getPython("PythonExtensions") + |
220 extensions = set(Preferences.getPython("Python3Extensions")) |
214 Preferences.getPython("Python3Extensions")) |
|
215 for ext in extensions: |
221 for ext in extensions: |
216 self.files.extend( |
222 self.files.extend( |
217 Utilities.direntries(fn, True, '*{0}'.format(ext), 0)) |
223 Utilities.direntries(fn, True, '*{0}'.format(ext), 0)) |
218 else: |
224 else: |
219 self.files = [fn] |
225 self.files = [fn] |
371 if not self.cancelled: |
377 if not self.cancelled: |
372 self.__createResultItems() |
378 self.__createResultItems() |
373 |
379 |
374 # reenable updates of the list |
380 # reenable updates of the list |
375 self.resultList.setSortingEnabled(True) |
381 self.resultList.setSortingEnabled(True) |
376 self.resultList.sortItems(0, Qt.AscendingOrder) |
382 self.resultList.sortItems(0, Qt.SortOrder.AscendingOrder) |
377 self.resultList.setUpdatesEnabled(True) |
383 self.resultList.setUpdatesEnabled(True) |
378 |
384 |
379 self.cancelled = True |
385 self.cancelled = True |
380 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) |
386 self.buttonBox.button( |
381 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) |
387 QDialogButtonBox.StandardButton.Close).setEnabled(True) |
382 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) |
388 self.buttonBox.button( |
|
389 QDialogButtonBox.StandardButton.Cancel).setEnabled(False) |
|
390 self.buttonBox.button( |
|
391 QDialogButtonBox.StandardButton.Close).setDefault(True) |
383 |
392 |
384 self.resultList.header().resizeSections( |
393 self.resultList.header().resizeSections( |
385 QHeaderView.ResizeToContents) |
394 QHeaderView.ResizeToContents) |
386 self.resultList.header().setStretchLastSection(True) |
395 self.resultList.header().setStretchLastSection(True) |
387 if qVersion() >= "5.0.0": |
396 self.resultList.header().setSectionResizeMode( |
388 self.resultList.header().setSectionResizeMode( |
397 QHeaderView.ResizeMode.Interactive) |
389 QHeaderView.Interactive) |
|
390 else: |
|
391 self.resultList.header().setResizeMode(QHeaderView.Interactive) |
|
392 |
398 |
393 self.checkProgress.setVisible(False) |
399 self.checkProgress.setVisible(False) |
394 self.checkProgressLabel.setVisible(False) |
400 self.checkProgressLabel.setVisible(False) |
395 |
401 |
396 if self.resultList.topLevelItemCount() == 0: |
402 if self.resultList.topLevelItemCount() == 0: |
404 Private slot called by a button of the button box clicked. |
410 Private slot called by a button of the button box clicked. |
405 |
411 |
406 @param button button that was clicked |
412 @param button button that was clicked |
407 @type QAbstractButton |
413 @type QAbstractButton |
408 """ |
414 """ |
409 if button == self.buttonBox.button(QDialogButtonBox.Close): |
415 if button == self.buttonBox.button( |
|
416 QDialogButtonBox.StandardButton.Close |
|
417 ): |
410 self.close() |
418 self.close() |
411 elif button == self.buttonBox.button(QDialogButtonBox.Cancel): |
419 elif button == self.buttonBox.button( |
|
420 QDialogButtonBox.StandardButton.Cancel |
|
421 ): |
412 self.cancelled = True |
422 self.cancelled = True |
413 if self.__batch: |
423 if self.__batch: |
414 self.vultureService.cancelVultureCheckBatch() |
424 self.vultureService.cancelVultureCheckBatch() |
415 QTimer.singleShot(1000, self.__finish) |
425 QTimer.singleShot(1000, self.__finish) |
416 else: |
426 else: |
458 try: |
468 try: |
459 lineno = int(item.text(0)) |
469 lineno = int(item.text(0)) |
460 except ValueError: |
470 except ValueError: |
461 lineno = 1 |
471 lineno = 1 |
462 if filename: |
472 if filename: |
463 vm = e5App().getObject("ViewManager") |
473 vm = ericApp().getObject("ViewManager") |
464 vm.openSourceFile(filename, lineno) |
474 vm.openSourceFile(filename, lineno) |
465 |
475 |
466 def __prepareResultLists(self): |
476 def __prepareResultLists(self): |
467 """ |
477 """ |
468 Private method to prepare the result lists. |
478 Private method to prepare the result lists. |
519 @return list of filtered items |
529 @return list of filtered items |
520 @rtype list of VultureItem |
530 @rtype list of VultureItem |
521 """ |
531 """ |
522 filteredList = itemList |
532 filteredList = itemList |
523 for pattern in self.__data["WhiteLists"]["__patterns__"]: |
533 for pattern in self.__data["WhiteLists"]["__patterns__"]: |
524 regExp = QRegExp(pattern, Qt.CaseSensitive, QRegExp.Wildcard) |
|
525 filteredList = [item for item in filteredList |
534 filteredList = [item for item in filteredList |
526 if not regExp.exactMatch(item.name)] |
535 if not fnmatch.fnmatchcase(item.name, pattern)] |
527 return filteredList # __IGNORE_WARNING_M834__ |
536 return filteredList # __IGNORE_WARNING_M834__ |
528 |
537 |
529 def __filterUnusedItems(self, unused, whitelistName): |
538 def __filterUnusedItems(self, unused, whitelistName): |
530 """ |
539 """ |
531 Private method to get a list of unused items. |
540 Private method to get a list of unused items. |
641 itm = QTreeWidgetItem(parent, [ |
650 itm = QTreeWidgetItem(parent, [ |
642 "{0:6d}".format(item.first_lineno), item.name, |
651 "{0:6d}".format(item.first_lineno), item.name, |
643 "{0:3d}%".format(item.confidence), translatedType]) |
652 "{0:3d}%".format(item.confidence), translatedType]) |
644 itm.setData(0, self.FilePathRole, item.filename) |
653 itm.setData(0, self.FilePathRole, item.filename) |
645 itm.setData(0, self.TypeRole, item.typ) |
654 itm.setData(0, self.TypeRole, item.typ) |
646 itm.setTextAlignment(0, Qt.Alignment(Qt.AlignRight)) # line no |
655 itm.setTextAlignment(0, Qt.AlignmentFlag.AlignRight) # line no |
647 itm.setTextAlignment(2, Qt.Alignment(Qt.AlignRight)) # confidence |
656 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignRight) # confidence |
648 |
657 |
649 def __createFileItem(self, filename): |
658 def __createFileItem(self, filename): |
650 """ |
659 """ |
651 Private method to create a file item. |
660 Private method to create a file item. |
652 |
661 |
707 """ |
716 """ |
708 Private slot to edit the whitelist. |
717 Private slot to edit the whitelist. |
709 """ |
718 """ |
710 from .EditWhiteListDialog import EditWhiteListDialog |
719 from .EditWhiteListDialog import EditWhiteListDialog |
711 dlg = EditWhiteListDialog(self.__data["WhiteLists"]) |
720 dlg = EditWhiteListDialog(self.__data["WhiteLists"]) |
712 if dlg.exec() == QDialog.Accepted: |
721 if dlg.exec() == QDialog.DialogCode.Accepted: |
713 whitelists = dlg.getWhiteLists() |
722 whitelists = dlg.getWhiteLists() |
714 self.__storeWhiteLists(whitelists) |
723 self.__storeWhiteLists(whitelists) |
715 |
724 |
716 def __whiteList(self): |
725 def __whiteList(self): |
717 """ |
726 """ |