56 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) |
56 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) |
57 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) |
57 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) |
58 |
58 |
59 self.resultList.headerItem().setText(self.resultList.columnCount(), "") |
59 self.resultList.headerItem().setText(self.resultList.columnCount(), "") |
60 |
60 |
|
61 self.__menu = QMenu(self) |
|
62 self.__whiteListAct = self.__menu.addAction( |
|
63 self.tr("Add to Whitelist"), self.__whiteList) |
|
64 self.__menu.addSeparator() |
|
65 self.__menu.addAction( |
|
66 self.tr("Edit Whitelist"), self.__editWhiteList) |
|
67 self.__menu.addSeparator() |
|
68 self.__collapseAct = self.__menu.addAction( |
|
69 self.tr("Collapse all"), self.__resultCollapse) |
|
70 self.__expandAct = self.__menu.addAction( |
|
71 self.tr("Expand all"), self.__resultExpand) |
|
72 self.resultList.customContextMenuRequested.connect( |
|
73 self.__showContextMenu) |
|
74 |
61 self.vultureService = vultureService |
75 self.vultureService = vultureService |
62 self.vultureService.analysisDone.connect(self.__processResult) |
76 self.vultureService.analysisDone.connect(self.__processResult) |
63 self.vultureService.error.connect(self.__processError) |
77 self.vultureService.error.connect(self.__processError) |
64 self.vultureService.batchFinished.connect(self.__batchFinished) |
78 self.vultureService.batchFinished.connect(self.__batchFinished) |
65 |
79 |
66 self.cancelled = False |
80 self.cancelled = False |
67 |
81 |
68 self.__project = e5App().getObject("Project") |
82 self.__project = e5App().getObject("Project") |
69 self.__locale = QLocale() |
|
70 self.__finished = True |
83 self.__finished = True |
71 self.__errorItem = None |
84 self.__errorItem = None |
|
85 self.__data = None |
72 |
86 |
73 self.__fileList = [] |
87 self.__fileList = [] |
74 self.filterFrame.setVisible(False) |
88 self.filterFrame.setVisible(False) |
75 |
89 |
76 def __resizeResultColumns(self): |
90 self.__translatedTypes = { |
77 """ |
91 "property": self.tr("Property"), |
78 Private method to resize the list columns. |
92 "function": self.tr("Function"), |
79 """ |
93 "attribute": self.tr("Attribute"), |
80 self.resultList.header().resizeSections(QHeaderView.ResizeToContents) |
94 "variable": self.tr("Variable"), |
81 self.resultList.header().setStretchLastSection(True) |
95 "class": self.tr("Class"), |
|
96 } |
82 |
97 |
83 def __createErrorItem(self, filename, message): |
98 def __createErrorItem(self, filename, message): |
84 """ |
99 """ |
85 Private slot to create a new error item in the result list. |
100 Private slot to create a new error item in the result list. |
86 |
101 |
422 Private method to store the result of an analysis. |
448 Private method to store the result of an analysis. |
423 |
449 |
424 @param result result dictionary |
450 @param result result dictionary |
425 @type dict |
451 @type dict |
426 """ |
452 """ |
427 self.__definedAttrs.extend( |
453 self.__definedAttrs.extend(self.__filteredList( |
428 [self.__dict2Item(d) for d in result["DefinedAttributes"]]) |
454 [self.__dict2Item(d) for d in result["DefinedAttributes"]])) |
429 self.__definedFuncs.extend( |
455 self.__definedFuncs.extend(self.__filteredList( |
430 [self.__dict2Item(d) for d in result["DefinedFunctions"]]) |
456 [self.__dict2Item(d) for d in result["DefinedFunctions"]])) |
431 self.__definedProps.extend( |
457 self.__definedProps.extend(self.__filteredList( |
432 [self.__dict2Item(d) for d in result["DefinedProperties"]]) |
458 [self.__dict2Item(d) for d in result["DefinedProperties"]])) |
433 self.__definedVars.extend( |
459 self.__definedVars.extend(self.__filteredList( |
434 [self.__dict2Item(d) for d in result["DefinedVariables"]]) |
460 [self.__dict2Item(d) for d in result["DefinedVariables"]])) |
435 self.__usedAttrs.extend( |
461 self.__usedAttrs.extend( |
436 [self.__dict2Item(d) for d in result["UsedAttributes"]]) |
462 [self.__dict2Item(d) for d in result["UsedAttributes"]]) |
437 self.__usedVars.extend( |
463 self.__usedVars.extend( |
438 [self.__dict2Item(d) for d in result["UsedVariables"]]) |
464 [self.__dict2Item(d) for d in result["UsedVariables"]]) |
439 self.__tupleAssignVars.extend( |
465 self.__tupleAssignVars.extend( |
493 @rtype list of vulture.Item |
541 @rtype list of vulture.Item |
494 """ |
542 """ |
495 return self.__getUnusedItems( |
543 return self.__getUnusedItems( |
496 self.__definedVars, |
544 self.__definedVars, |
497 self.__usedAttrs + self.__usedVars + self.__tupleAssignVars + |
545 self.__usedAttrs + self.__usedVars + self.__tupleAssignVars + |
498 self.__namesImportedAsAliases) |
546 self.__namesImportedAsAliases + |
|
547 self.__data["WhiteLists"]["variable"]) |
499 |
548 |
500 def __unusedAttributes(self): |
549 def __unusedAttributes(self): |
501 """ |
550 """ |
502 Private method to get the list of unused attributes. |
551 Private method to get the list of unused attributes. |
503 |
552 |
504 @return list of unused attributes |
553 @return list of unused attributes |
505 @rtype list of vulture.Item |
554 @rtype list of vulture.Item |
506 """ |
555 """ |
507 return self.__getUnusedItems(self.__definedAttrs, self.__usedAttrs) |
556 return self.__getUnusedItems( |
|
557 self.__definedAttrs, |
|
558 self.__usedAttrs + self.__data["WhiteLists"]["attribute"]) |
508 |
559 |
509 def __createResultItems(self): |
560 def __createResultItems(self): |
510 """ |
561 """ |
511 Private method to populate the list with the analysis result. |
562 Private method to populate the list with the analysis result. |
512 """ |
563 """ # __IGNORE_WARNING__ |
513 def filename(item): |
564 def filename(item): |
514 return item.file |
565 return item.file |
515 |
566 |
516 lastFileItem = None |
567 lastFileItem = None |
517 lastFileName = "" |
568 lastFileName = "" |
518 for item in sorted(self.__unusedFunctions() + |
569 for item in sorted(self.__unusedFunctions() + |
519 self.__unusedProperties() + |
570 self.__unusedProperties() + |
520 self.__unusedVariables() + |
571 self.__unusedVariables() + |
521 self.__unusedAttributes(), |
572 self.__unusedAttributes(), |
522 key=filename): |
573 key=filename): |
523 if lastFileItem is None or lastFileName != item.file: |
574 if lastFileItem is None or lastFileName != item.file: |
524 lastFileItem = QTreeWidgetItem(self.resultList, [ |
575 lastFileItem = self.__createFileItem(item.file) |
525 self.__project.getRelativePath(item.file)]) |
|
526 lastFileItem.setData(0, self.FilePathRole, item.file) |
|
527 lastFileItem.setExpanded(True) |
|
528 lastFileItem.setFirstColumnSpanned(True) |
|
529 lastFileName = item.file |
576 lastFileName = item.file |
530 |
577 |
531 itm = QTreeWidgetItem(lastFileItem, [ |
578 self.__createResultItem(lastFileItem, item) |
532 "{0:6d}".format(item.lineno), str(item), item.typ]) |
579 |
533 itm.setData(0, self.FilePathRole, item.file) |
580 def __createResultItem(self, parent, item): |
|
581 """ |
|
582 Private method to create a result item. |
|
583 |
|
584 @param parent reference to the parent item |
|
585 @type QTreeWidgetItem |
|
586 @param item reference to the item |
|
587 @type vulture.Item |
|
588 """ |
|
589 try: |
|
590 translatedType = self.__translatedTypes[item.typ] |
|
591 except KeyError: |
|
592 translatedType = item.typ |
|
593 itm = QTreeWidgetItem(parent, [ |
|
594 "{0:6d}".format(item.lineno), str(item), translatedType]) |
|
595 itm.setData(0, self.FilePathRole, item.file) |
|
596 itm.setData(0, self.TypeRole, item.typ) |
|
597 itm.setTextAlignment(0, Qt.Alignment(Qt.AlignRight)) |
|
598 |
|
599 def __createFileItem(self, filename): |
|
600 """ |
|
601 Private method to create a file item. |
|
602 |
|
603 @param filename file name for the item |
|
604 @type str |
|
605 """ |
|
606 itm = QTreeWidgetItem(self.resultList, [ |
|
607 self.__project.getRelativePath(filename)]) |
|
608 itm.setData(0, self.FilePathRole, filename) |
|
609 itm.setExpanded(True) |
|
610 itm.setFirstColumnSpanned(True) |
|
611 |
|
612 return itm |
|
613 |
|
614 def __showContextMenu(self, coord): |
|
615 """ |
|
616 Private slot to show the context menu of the listview. |
|
617 |
|
618 @param coord the position of the mouse pointer |
|
619 @type QPoint |
|
620 """ |
|
621 topLevelPresent = self.resultList.topLevelItemCount() > 0 |
|
622 self.__collapseAct.setEnabled(topLevelPresent) |
|
623 self.__expandAct.setEnabled(topLevelPresent) |
|
624 |
|
625 self.__whiteListAct.setEnabled( |
|
626 len(self.__getSelectedNonFileItems()) != 0) |
|
627 |
|
628 self.__menu.popup(self.resultList.mapToGlobal(coord)) |
|
629 |
|
630 def __resultCollapse(self): |
|
631 """ |
|
632 Private slot to collapse all entries of the resultlist. |
|
633 """ |
|
634 for index in range(self.resultList.topLevelItemCount()): |
|
635 self.resultList.topLevelItem(index).setExpanded(False) |
|
636 |
|
637 def __resultExpand(self): |
|
638 """ |
|
639 Private slot to expand all entries of the resultlist. |
|
640 """ |
|
641 for index in range(self.resultList.topLevelItemCount()): |
|
642 self.resultList.topLevelItem(index).setExpanded(True) |
|
643 |
|
644 def __getSelectedNonFileItems(self): |
|
645 """ |
|
646 Private method to get a list of selected non file items. |
|
647 |
|
648 @return list of selected non file items |
|
649 @rtype list of QTreeWidgetItem |
|
650 """ |
|
651 itmList = [i for i in self.resultList.selectedItems() |
|
652 if i.parent() is not None] |
|
653 return itmList |
|
654 |
|
655 def __editWhiteList(self): |
|
656 """ |
|
657 Private slot to edit the whitelist. |
|
658 """ |
|
659 # TODO: add a whitelist edit dialog with "add" and "delete" |
|
660 ## whitelist = dlg.getWhiteList() |
|
661 ## self.__storeWhiteList(whitelist) |
|
662 |
|
663 def __whiteList(self): |
|
664 """ |
|
665 Private slot to add entries to the whitelist. |
|
666 """ |
|
667 whitelists = {} |
|
668 for key in self.__data["WhiteLists"]: |
|
669 whitelists[key] = self.__data["WhiteLists"][key][:] |
|
670 for itm in self.__getSelectedNonFileItems(): |
|
671 try: |
|
672 whitelists[itm.data(0, self.TypeRole)].append(itm.text(1)) |
|
673 except KeyError: |
|
674 # ignore non-existing types |
|
675 pass |
|
676 # remove the item from the result list |
|
677 pitm = itm.parent() |
|
678 pitm.removeChild(itm) |
|
679 del itm |
|
680 if pitm.childCount() == 0: |
|
681 self.resultList.takeTopLevelItem( |
|
682 self.resultList.indexOfTopLevelItem(pitm)) |
|
683 del pitm |
|
684 self.__storeWhiteList(whitelists) |
|
685 |
|
686 def __storeWhiteList(self, whitelists): |
|
687 """ |
|
688 Private method to store the new whitelists, if they have changed. |
|
689 |
|
690 @param whitelists dictionary of lists of whitelisted names |
|
691 @type dict of list of str |
|
692 """ |
|
693 changed = False |
|
694 for key in whitelists: |
|
695 whitelist = list(set(whitelists[key])) |
|
696 try: |
|
697 if sorted(whitelist) != sorted(self.__data["WhiteLists"][key]): |
|
698 self.__data["WhiteLists"][key] = whitelist[:] |
|
699 changed = True |
|
700 except KeyError: |
|
701 # ignore non-existing types |
|
702 pass |
|
703 |
|
704 if changed: |
|
705 self.__project.setData("CHECKERSPARMS", "Vulture", self.__data) |