72 self.radonService.complexityDone.connect(self.__processResult) |
72 self.radonService.complexityDone.connect(self.__processResult) |
73 self.radonService.error.connect(self.__processError) |
73 self.radonService.error.connect(self.__processError) |
74 self.radonService.batchFinished.connect(self.__batchFinished) |
74 self.radonService.batchFinished.connect(self.__batchFinished) |
75 |
75 |
76 self.__isSingle = isSingle |
76 self.__isSingle = isSingle |
|
77 self.__batch = False |
77 self.cancelled = False |
78 self.cancelled = False |
78 |
79 |
79 self.__project = ericApp().getObject("Project") |
80 self.__project = ericApp().getObject("Project") |
80 self.__locale = QLocale() |
81 self.__locale = QLocale() |
81 self.__finished = True |
82 self.__finished = True |
82 self.__errorItem = None |
83 self.__errorItem = None |
83 |
84 |
84 self.__fileList = [] |
85 self.__fileList = [] |
85 self.filterFrame.setVisible(False) |
86 self.filterFrame.setVisible(False) |
86 |
87 |
|
88 self.summaryHeader.setText(self.tr("<b>Summary:</b>")) |
|
89 self.explanationHeader.setText(self.tr("<b>Ranking:</b>")) |
87 self.explanationLabel.setText( |
90 self.explanationLabel.setText( |
88 self.tr( |
91 self.tr( |
89 "<table>" |
92 "<table>" |
90 "<tr><td colspan=3><b>Ranking:</b></td></tr>" |
|
91 "<tr><td><b>A</b></td><td>1 - 5</td>" |
93 "<tr><td><b>A</b></td><td>1 - 5</td>" |
92 "<td>(low risk - simple block)</td></tr>" |
94 "<td>(low risk - simple block)</td></tr>" |
93 "<tr><td><b>B</b></td><td>6 - 10</td>" |
95 "<tr><td><b>B</b></td><td>6 - 10</td>" |
94 "<td>(low risk - well structured and stable block)</td></tr>" |
96 "<td>(low risk - well structured and stable block)</td></tr>" |
95 "<tr><td><b>C</b></td><td>11 - 20</td>" |
97 "<tr><td><b>C</b></td><td>11 - 20</td>" |
101 "<tr><td><b>F</b></td><td>> 40</td>" |
103 "<tr><td><b>F</b></td><td>> 40</td>" |
102 "<td>(very high risk - error-prone, unstable block)</td></tr>" |
104 "<td>(very high risk - error-prone, unstable block)</td></tr>" |
103 "</table>" |
105 "</table>" |
104 ) |
106 ) |
105 ) |
107 ) |
|
108 self.typeHeader.setText(self.tr("<b>Type:</b>")) |
106 self.typeLabel.setText( |
109 self.typeLabel.setText( |
107 self.tr( |
110 self.tr( |
108 "<table>" |
111 "<table>" |
109 "<tr><td colspan=2><b>Type:</b></td></tr>" |
|
110 "<tr><td><b>C</b></td><td>Class</td></tr>" |
112 "<tr><td><b>C</b></td><td>Class</td></tr>" |
111 "<tr><td><b>F</b></td><td>Function</td></tr>" |
113 "<tr><td><b>F</b></td><td>Function</td></tr>" |
112 "<tr><td><b>M</b></td><td>Method</td></tr>" |
114 "<tr><td><b>M</b></td><td>Method</td></tr>" |
113 "</table>" |
115 "</table>" |
114 ) |
116 ) |
269 self.__minimumRank = self.__data["MinimumRank"] |
271 self.__minimumRank = self.__data["MinimumRank"] |
270 self.rankComboBox.setCurrentIndex( |
272 self.rankComboBox.setCurrentIndex( |
271 self.rankComboBox.findText(self.__minimumRank) |
273 self.rankComboBox.findText(self.__minimumRank) |
272 ) |
274 ) |
273 |
275 |
274 def start(self, fn, minRank="D"): |
276 def start(self, fn): |
275 """ |
277 """ |
276 Public slot to start the cyclomatic complexity determination. |
278 Public slot to start the cyclomatic complexity determination. |
277 |
279 |
278 @param fn file or list of files or directory to show |
280 @param fn file or list of files or directory to show |
279 the cyclomatic complexity for |
281 the cyclomatic complexity for |
280 @type str or list of str |
282 @type str or list of str |
281 @param minRank minimum rank of entries to be shown |
|
282 @type str (one character out of A - F) |
|
283 """ |
283 """ |
284 self.cancelled = False |
284 self.cancelled = False |
285 self.__errorItem = None |
285 self.__errorItem = None |
286 self.resultList.clear() |
286 self.resultList.clear() |
287 self.summaryLabel.clear() |
287 self.summaryLabel.clear() |
322 self.__ccCount = 0 |
322 self.__ccCount = 0 |
323 |
323 |
324 self.__minimumRank = self.rankComboBox.currentText() |
324 self.__minimumRank = self.rankComboBox.currentText() |
325 |
325 |
326 if len(self.files) > 0: |
326 if len(self.files) > 0: |
327 # disable updates of the list for speed |
|
328 self.resultList.setUpdatesEnabled(False) |
|
329 self.resultList.setSortingEnabled(False) |
327 self.resultList.setSortingEnabled(False) |
330 |
328 |
331 self.checkProgress.setMaximum(len(self.files)) |
329 self.checkProgress.setMaximum(len(self.files)) |
332 self.checkProgress.setVisible(len(self.files) > 1) |
330 self.checkProgress.setVisible(len(self.files) > 1) |
333 QApplication.processEvents() |
331 QApplication.processEvents() |
339 self.cyclomaticComplexity() |
337 self.cyclomaticComplexity() |
340 else: |
338 else: |
341 self.__batch = True |
339 self.__batch = True |
342 self.cyclomaticComplexityBatch() |
340 self.cyclomaticComplexityBatch() |
343 |
341 |
344 def cyclomaticComplexity(self, codestring=""): |
342 def cyclomaticComplexity(self): |
345 """ |
343 """ |
346 Public method to start a cyclomatic complexity calculation for one |
344 Public method to start a cyclomatic complexity calculation for one |
347 Python file. |
345 Python file. |
348 |
346 |
349 The results are reported to the __processResult slot. |
347 The results are reported to the __processResult slot. |
350 |
|
351 @param codestring optional sourcestring |
|
352 @type str |
|
353 """ |
348 """ |
354 if not self.files: |
349 if not self.files: |
355 self.checkProgress.setMaximum(1) |
350 self.checkProgress.setMaximum(1) |
356 self.checkProgress.setValue(1) |
351 self.checkProgress.setValue(1) |
357 self.__finish() |
352 self.__finish() |
358 return |
353 return |
359 |
354 |
360 self.filename = self.files.pop(0) |
355 self.filename = self.files.pop(0) |
361 self.checkProgress.setValue(self.progress) |
356 self.checkProgress.setValue(self.progress) |
362 QApplication.processEvents() |
|
363 |
357 |
364 if self.cancelled: |
358 if self.cancelled: |
365 return |
359 return |
366 |
360 |
367 try: |
361 try: |
386 self.__lastFileItem = None |
380 self.__lastFileItem = None |
387 |
381 |
388 argumentsList = [] |
382 argumentsList = [] |
389 for progress, filename in enumerate(self.files, start=1): |
383 for progress, filename in enumerate(self.files, start=1): |
390 self.checkProgress.setValue(progress) |
384 self.checkProgress.setValue(progress) |
391 QApplication.processEvents() |
|
392 |
385 |
393 try: |
386 try: |
394 source = Utilities.readEncodedFile(filename)[0] |
387 source = Utilities.readEncodedFile(filename)[0] |
395 source = Utilities.normalizeCode(source) |
388 source = Utilities.normalizeCode(source) |
396 except (UnicodeError, OSError) as msg: |
389 except (UnicodeError, OSError) as msg: |
399 |
392 |
400 argumentsList.append((filename, source)) |
393 argumentsList.append((filename, source)) |
401 |
394 |
402 # reset the progress bar to the checked files |
395 # reset the progress bar to the checked files |
403 self.checkProgress.setValue(self.progress) |
396 self.checkProgress.setValue(self.progress) |
404 QApplication.processEvents() |
|
405 |
397 |
406 self.__finished = False |
398 self.__finished = False |
407 self.radonService.cyclomaticComplexityBatch(argumentsList) |
399 self.radonService.cyclomaticComplexityBatch(argumentsList) |
408 |
400 |
409 def __batchFinished(self, type_): |
401 def __batchFinished(self, type_): |
468 self.__ccSum += result["total_cc"] |
460 self.__ccSum += result["total_cc"] |
469 for rank in result["summary"]: |
461 for rank in result["summary"]: |
470 self.__summary[rank] += result["summary"][rank] |
462 self.__summary[rank] += result["summary"][rank] |
471 |
463 |
472 self.progress += 1 |
464 self.progress += 1 |
473 |
|
474 self.checkProgress.setValue(self.progress) |
465 self.checkProgress.setValue(self.progress) |
475 QApplication.processEvents() |
|
476 |
466 |
477 if not self.__batch: |
467 if not self.__batch: |
478 self.cyclomaticComplexity() |
468 self.cyclomaticComplexity() |
479 |
469 |
480 def __finish(self): |
470 def __finish(self): |
484 from radon.complexity import cc_rank |
474 from radon.complexity import cc_rank |
485 |
475 |
486 if not self.__finished: |
476 if not self.__finished: |
487 self.__finished = True |
477 self.__finished = True |
488 |
478 |
489 # re-enable updates of the list |
|
490 self.resultList.setSortingEnabled(True) |
479 self.resultList.setSortingEnabled(True) |
491 self.resultList.sortItems(0, Qt.SortOrder.AscendingOrder) |
480 self.resultList.sortItems(0, Qt.SortOrder.AscendingOrder) |
492 self.resultList.sortItems(1, Qt.SortOrder.AscendingOrder) |
481 self.resultList.sortItems(1, Qt.SortOrder.AscendingOrder) |
493 self.resultList.setUpdatesEnabled(True) |
|
494 |
482 |
495 self.cancelled = True |
483 self.cancelled = True |
496 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled( |
484 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled( |
497 True |
485 True |
498 ) |
486 ) |
514 |
502 |
515 averageCC = float(self.__ccSum) / (self.__ccCount or 1) |
503 averageCC = float(self.__ccSum) / (self.__ccCount or 1) |
516 |
504 |
517 self.summaryLabel.setText( |
505 self.summaryLabel.setText( |
518 self.tr( |
506 self.tr( |
519 "<b>Summary:</b><br/>" |
|
520 "{0} blocks (classes, functions, methods) analyzed.<br/>" |
507 "{0} blocks (classes, functions, methods) analyzed.<br/>" |
521 "Average complexity: {7} ({8})" |
508 "Average complexity: {7} ({8})" |
522 "<table>" |
509 "<table>" |
523 "<tr><td width=30><b>A</b></td>" |
510 "<tr><td width=30><b>A</b></td>" |
524 "<td align='right'>{1} blocks</td></tr>" |
511 "<td align='right'>{1} blocks</td></tr>" |
546 ) |
533 ) |
547 ) |
534 ) |
548 |
535 |
549 self.checkProgress.setVisible(False) |
536 self.checkProgress.setVisible(False) |
550 |
537 |
|
538 def __cancel(self): |
|
539 """ |
|
540 Private method to cancel the current check run. |
|
541 """ |
|
542 if self.__batch: |
|
543 self.radonService.cancelComplexityBatch() |
|
544 QTimer.singleShot(1000, self.__finish) |
|
545 else: |
|
546 self.__finish() |
|
547 |
|
548 def closeEvent(self, evt): |
|
549 """ |
|
550 Protected method to handle a close event. |
|
551 |
|
552 @param evt reference to the close event |
|
553 @type QCloseEvent |
|
554 """ |
|
555 self.__cancel() |
|
556 |
551 @pyqtSlot(QAbstractButton) |
557 @pyqtSlot(QAbstractButton) |
552 def on_buttonBox_clicked(self, button): |
558 def on_buttonBox_clicked(self, button): |
553 """ |
559 """ |
554 Private slot called by a button of the button box clicked. |
560 Private slot called by a button of the button box clicked. |
555 |
561 |
557 @type QAbstractButton |
563 @type QAbstractButton |
558 """ |
564 """ |
559 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close): |
565 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close): |
560 self.close() |
566 self.close() |
561 elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel): |
567 elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel): |
562 if self.__batch: |
568 self.__cancel() |
563 self.radonService.cancelComplexityBatch() |
|
564 QTimer.singleShot(1000, self.__finish) |
|
565 else: |
|
566 self.__finish() |
|
567 |
569 |
568 @pyqtSlot() |
570 @pyqtSlot() |
569 def on_startButton_clicked(self): |
571 def on_startButton_clicked(self): |
570 """ |
572 """ |
571 Private slot to start a cyclomatic complexity run. |
573 Private slot to start a cyclomatic complexity run. |
642 lineno = item.data(0, self.LineNumberRole) |
644 lineno = item.data(0, self.LineNumberRole) |
643 if filename: |
645 if filename: |
644 vm = ericApp().getObject("ViewManager") |
646 vm = ericApp().getObject("ViewManager") |
645 vm.openSourceFile(filename, lineno) |
647 vm.openSourceFile(filename, lineno) |
646 |
648 |
647 @pyqtSlot(str) |
649 @pyqtSlot(int) |
648 def on_rankComboBox_activated(self, rank): |
650 def on_rankComboBox_activated(self, index): |
649 """ |
651 """ |
650 Private slot to handle the selection of a minimum rank. |
652 Private slot to handle the selection of a minimum rank. |
651 |
653 |
652 @param rank selected minimum rank |
654 @param index index of the selected minimum rank |
653 @type str |
655 @type str |
654 """ |
656 """ |
655 if self.__isSingle: |
657 if self.__isSingle: |
656 self.start(self.__fileList[:]) |
658 self.start(self.__fileList[:]) |