PluginMetricsRadon.py

Fri, 18 Sep 2015 19:46:57 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 18 Sep 2015 19:46:57 +0200
changeset 10
8b1920a22df3
parent 9
7f6e04213998
child 11
de8cadbd6a41
permissions
-rw-r--r--

Changed the logic for the various code metrics calculations to be separate services and fine tuned the dialogs.

# -*- coding: utf-8 -*-

# Copyright (c) 2015 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing the radon code metrics plug-in.
"""

from __future__ import unicode_literals

import os

from PyQt5.QtCore import pyqtSignal, QObject, QTranslator
from PyQt5.QtWidgets import QAction

from E5Gui.E5Application import e5App
from E5Gui.E5Action import E5Action

from Project.ProjectBrowserModel import ProjectBrowserFileItem

import Preferences
from Utilities import determinePythonVersion

# Start-Of-Header
name = "Radon Metrics Plugin"
author = "Detlev Offenbach <detlev@die-offenbachs.de>"
autoactivate = True
deactivateable = True
version = "0.1.0"
className = "RadonMetricsPlugin"
packageName = "RadonMetrics"
shortDescription = "Code metrics plugin using radon package"
longDescription = (
    """This plug-in implements dialogs to show various code metrics. These"""
    """ are determined using the radon code metrics package."""
)
needsRestart = False
pyqtApi = 2
python2Compatible = True
# End-Of-Header

error = ""
    

class RadonMetricsPlugin(QObject):
    """
    Class implementing the radon code metrics plug-in.
    
    @signal metricsDone(str, dict) emitted when the code metrics were
        determined for a file
    @signal maintainabilityIndexDone(str, dict) emitted when the
        maintainability index was determined for a file
    @signal complexityDone(str, dict) emitted when the
        cyclomatic complexity was determined for a file
    @signal error(str, str, str) emitted in case of an error
    @signal batchFinished(str) emitted when a code metrics batch is done
    """
    metricsDone = pyqtSignal(str, dict)
    maintainabilityIndexDone = pyqtSignal(str, dict)
    complexityDone = pyqtSignal(str, dict)
    error = pyqtSignal(str, str, str)
    batchFinished = pyqtSignal(str)
    
    def __init__(self, ui):
        """
        Constructor
        
        @param ui reference to the user interface object
        @type UI.UserInterface
        """
        super(RadonMetricsPlugin, self).__init__(ui)
        self.__ui = ui
        self.__initialize()
        
        self.backgroundService = e5App().getObject("BackgroundService")
        
        path = os.path.join(os.path.dirname(__file__), packageName)
        try:
            # raw code metrics calculation
            self.backgroundService.serviceConnect(
                'radon_raw', 'Python2', path, 'CodeMetricsCalculator',
                lambda fn, res: self.metricsCalculationDone("raw", fn, res),
                onErrorCallback=lambda fx, lang, fn, msg: self.serviceErrorPy2(
                    "raw", fx, lang, fn, msg),
                onBatchDone=lambda fx, lang: self.batchJobDone(
                    "raw", fx, lang))
            self.backgroundService.serviceConnect(
                'radon_raw', 'Python3', path, 'CodeMetricsCalculator',
                lambda fn, res: self.metricsCalculationDone("raw", fn, res),
                onErrorCallback=lambda fx, lang, fn, msg: self.serviceErrorPy3(
                    "raw", fx, lang, fn, msg),
                onBatchDone=lambda fx, lang: self.batchJobDone(
                    "raw", fx, lang))
            
            # maintainability index calculation
            self.backgroundService.serviceConnect(
                'radon_mi', 'Python2', path, 'MaintainabilityIndexCalculator',
                lambda fn, res: self.metricsCalculationDone("mi", fn, res),
                onErrorCallback=lambda fx, lang, fn, msg: self.serviceErrorPy2(
                    "mi", fx, lang, fn, msg),
                onBatchDone=lambda fx, lang: self.batchJobDone(
                    "mi", fx, lang))
            self.backgroundService.serviceConnect(
                'radon_mi', 'Python3', path, 'MaintainabilityIndexCalculator',
                lambda fn, res: self.metricsCalculationDone("mi", fn, res),
                onErrorCallback=lambda fx, lang, fn, msg: self.serviceErrorPy3(
                    "mi", fx, lang, fn, msg),
                onBatchDone=lambda fx, lang: self.batchJobDone(
                    "mi", fx, lang))
            
            self.hasBatch = True
        except TypeError:
            # backward compatibility for eric 6.0
            # raw code metrics calculation
            self.backgroundService.serviceConnect(
                'radon_raw', 'Python2', path, 'CodeMetricsCalculator',
                lambda fn, res: self.metricsCalculationDone("raw", fn, res),
                onErrorCallback=lambda fx, lang, fn, msg: self.serviceErrorPy2(
                    "raw", fx, lang, fn, msg))
            self.backgroundService.serviceConnect(
                'radon_raw', 'Python3', path, 'CodeMetricsCalculator',
                lambda fn, res: self.metricsCalculationDone("raw", fn, res),
                onErrorCallback=lambda fx, lang, fn, msg: self.serviceErrorPy3(
                    "raw", fx, lang, fn, msg))
            
            # maintainability index calculation
            self.backgroundService.serviceConnect(
                'radon_mi', 'Python2', path, 'MaintainabilityIndexCalculator',
                lambda fn, res: self.metricsCalculationDone("mi", fn, res),
                onErrorCallback=lambda fx, lang, fn, msg: self.serviceErrorPy2(
                    "mi", fx, lang, fn, msg))
            self.backgroundService.serviceConnect(
                'radon_mi', 'Python3', path, 'MaintainabilityIndexCalculator',
                lambda fn, res: self.metricsCalculationDone("mi", fn, res),
                onErrorCallback=lambda fx, lang, fn, msg: self.serviceErrorPy3(
                    "mi", fx, lang, fn, msg))
            
            self.hasBatch = False
        
        self.queuedBatches = {
            "raw": [],
            "mi": [],
            "cc": [],
        }
        self.batchesFinished = {
            "raw": True,
            "mi": True,
            "cc": True,
        }
        
        self.__translator = None
        self.__loadTranslator()
    
    def __serviceError(self, type_, fn, msg):
        """
        Private slot handling service errors.
        
        @param type_ type of the calculated metrics
        @type str, one of ["raw", "mi", "cc"]
        @param fn file name
        @type str
        @param msg message text
        @type str
        """
        self.error.emit(type_, fn, msg)
    
    def serviceErrorPy2(self, type_, fx, lang, fn, msg):
        """
        Public slot handling service errors for Python 2.
        
        @param type_ type of the calculated metrics
        @type str, one of ["raw", "mi", "cc"]
        @param fx service name
        @type str
        @param lang language
        @type str
        @param fn file name
        @type str
        @param msg message text
        @type str
        """
        if fx in ['radon_' + type_, 'batch_radon_' + type_] and \
                lang == 'Python2':
            if fx == 'radon_' + type_:
                self.__serviceError(type_, fn, msg)
            else:
                self.__serviceError(type_, self.tr("Python 2 batch job"), msg)
                self.batchJobDone(type_, fx, lang)
    
    def serviceErrorPy3(self, type_, fx, lang, fn, msg):
        """
        Public slot handling service errors for Python 3.
        
        @param type_ type of the calculated metrics
        @type str, one of ["raw", "mi", "cc"]
        @param fx service name
        @type str
        @param lang language
        @type str
        @param fn file name
        @type str
        @param msg message text
        @type str
        """
        if fx in ['radon_' + type_, 'batch_radon_' + type_] and \
                lang == 'Python3':
            if fx == 'radon_' + type_:
                self.__serviceError(type_, fn, msg)
            else:
                self.__serviceError(type_, self.tr("Python 3 batch job"), msg)
                self.batchJobDone(type_, fx, lang)
    
    def batchJobDone(self, type_, fx, lang):
        """
        Public slot handling the completion of a batch job.
        
        @param type_ type of the calculated metrics
        @type str, one of ["raw", "mi", "cc"]
        @param fx service name
        @type str
        @param lang language
        @type str
        """
        if fx in ['radon_' + type_, 'batch_radon_' + type_]:
            if lang in self.queuedBatches[type_]:
                self.queuedBatches[type_].remove(lang)
            # prevent sending the signal multiple times
            if len(self.queuedBatches[type_]) == 0 and \
                    not self.batchesFinished[type_]:
                self.batchFinished.emit(type_)
                self.batchesFinished[type_] = True
    
    def metricsCalculationDone(self, type_, filename, result):
        """
        Public slot to dispatch the result.
        
        @param type_ type of the calculated metrics
        @type str, one of ["raw", "mi", "cc"]
        @param filename name of the file the results belong to
        @type str
        @param result result dictionary
        @type dict
        """
        if type_ == "raw":
            self.metricsDone.emit(filename, result)
        elif type_ == "mi":
            self.maintainabilityIndexDone.emit(filename, result)
        elif type_ == "cc":
            self.complexityDone.emit(filename, result)
        else:
            self.error.emit(
                type_,
                filename,
                self.tr("Unknown metrics result received ({0}).").format(
                    type_)
            )
    
    def __initialize(self):
        """
        Private slot to (re)initialize the plugin.
        """
        self.__projectRawMetricsAct = None
        self.__projectRawMetricsDialog = None
        self.__projectMIAct = None
        self.__projectMIDialog = None
        self.__projectSeparatorActs = []
        
        self.__projectBrowserMenu = None
        self.__projectBrowserRawMetricsAct = None
        self.__projectBrowserRawMetricsDialog = None
        self.__projectBrowserMIAct = None
        self.__projectBrowserMIDialog = None
        self.__projectBrowserSeparatorActs = []
        
        self.__editors = []
        self.__editorRawMetricsAct = None
        self.__editorRawMetricsDialog = None
        self.__editorMIAct = None
        self.__editorMIDialog = None
        self.__editorSeparatorActs = []

    def rawMetrics(self, lang, filename, source):
        """
        Public method to prepare raw code metrics calculation on one Python
        source file.

        @param lang language of the file or None to determine by internal
            algorithm
        @type str or None
        @param filename source filename
        @type str
        @param source string containing the code
        @type str
        """
        if lang is None:
            lang = 'Python{0}'.format(determinePythonVersion(filename, source))
        if lang not in ['Python2', 'Python3']:
            return
        
        self.backgroundService.enqueueRequest(
            'radon_raw', lang, filename, [source])

    def rawMetricsBatch(self, argumentsList):
        """
        Public method to prepare raw code metrics calculation on multiple
        Python source files.
        
        @param argumentsList list of arguments tuples with each tuple
            containing filename and source
        @type (str, str)
        """
        data = {
            "Python2": [],
            "Python3": [],
        }
        for filename, source in argumentsList:
            lang = 'Python{0}'.format(determinePythonVersion(filename, source))
            if lang not in ['Python2', 'Python3']:
                continue
            else:
                data[lang].append((filename, source))
        
        self.queuedBatches["raw"] = []
        for lang in ['Python2', 'Python3']:
            if data[lang]:
                self.queuedBatches["raw"].append(lang)
                self.backgroundService.enqueueRequest('batch_radon_raw', lang,
                                                      "", data[lang])
                self.batchesFinished["raw"] = False
    
    def cancelRawMetricsBatch(self):
        """
        Public method to cancel all batch jobs.
        """
        for lang in ['Python2', 'Python3']:
            self.backgroundService.requestCancel('batch_radon_raw', lang)

    def maintainabilityIndex(self, lang, filename, source):
        """
        Public method to prepare maintainability index calculation on one
        Python source file.

        @param lang language of the file or None to determine by internal
            algorithm
        @type str or None
        @param filename source filename
        @type str
        @param source string containing the code
        @type str
        """
        if lang is None:
            lang = 'Python{0}'.format(determinePythonVersion(filename, source))
        if lang not in ['Python2', 'Python3']:
            return
        
        self.backgroundService.enqueueRequest(
            'radon_mi', lang, filename, [source])

    def maintainabilityIndexBatch(self, argumentsList):
        """
        Public method to prepare maintainability index calculation on multiple
        Python source files.
        
        @param argumentsList list of arguments tuples with each tuple
            containing filename and source
        @type (str, str)
        """
        data = {
            "Python2": [],
            "Python3": [],
        }
        for filename, source in argumentsList:
            lang = 'Python{0}'.format(determinePythonVersion(filename, source))
            if lang not in ['Python2', 'Python3']:
                continue
            else:
                data[lang].append((filename, source))
        
        self.queuedBatches["mi"] = []
        for lang in ['Python2', 'Python3']:
            if data[lang]:
                self.queuedBatches["mi"].append(lang)
                self.backgroundService.enqueueRequest('batch_radon_mi', lang,
                                                      "", data[lang])
                self.batchesFinished["mi"] = False
    
    def cancelMaintainabilityIndexBatch(self):
        """
        Public method to cancel all batch jobs.
        """
        for lang in ['Python2', 'Python3']:
            self.backgroundService.requestCancel('batch_radon_mi', lang)
    
    def activate(self):
        """
        Public method to activate this plug-in.
        
        @return tuple of None and activation status
        @rtype (None, bool)
        """
        global error
        error = ""     # clear previous error
        
        menu = e5App().getObject("Project").getMenu("Show")
        if menu:
            if not menu.isEmpty():
                act = menu.addSeparator()
                act.setText(self.tr("Radon"))
                self.__projectSeparatorActs.append(act)
            
            self.__projectRawMetricsAct = E5Action(
                self.tr('Code Metrics'),
                self.tr('Code &Metrics...'), 0, 0,
                self, 'project_show_radon_raw')
            self.__projectRawMetricsAct.setStatusTip(
                self.tr('Show raw code metrics.'))
            self.__projectRawMetricsAct.setWhatsThis(self.tr(
                """<b>Code Metrics...</b>"""
                """<p>This calculates raw code metrics of Python files"""
                """ and shows the amount of lines of code, logical lines"""
                """ of code, source lines of code, comment lines,"""
                """ multi-line strings and blank lines.</p>"""
            ))
            self.__projectRawMetricsAct.triggered.connect(
                self.__projectRawMetrics)
            menu.addAction(self.__projectRawMetricsAct)
            
            self.__projectMIAct = E5Action(
                self.tr('Maintainability Index'),
                self.tr('Maintainability &Index...'), 0, 0,
                self, 'project_show_radon_mi')
            self.__projectMIAct.setStatusTip(
                self.tr('Show the maintainability index for Python files.'))
            self.__projectMIAct.setWhatsThis(self.tr(
                """<b>Maintainability Index...</b>"""
                """<p>This calculates the maintainability index of Python"""
                """ files and shows it together with a ranking.</p>"""
            ))
            self.__projectMIAct.triggered.connect(
                self.__projectMaintainabilityIndex)
            menu.addAction(self.__projectMIAct)
            
            act = menu.addSeparator()
            self.__projectSeparatorActs.append(act)
            
            e5App().getObject("Project").addE5Actions([
                self.__projectRawMetricsAct,
                self.__projectMIAct
            ])
        
        act = QAction("Radon", self)
        act.setSeparator(True)
        self.__editorSeparatorActs.append(act)
        act = QAction(self)
        act.setSeparator(True)
        self.__editorSeparatorActs.append(act)
        
        self.__editorRawMetricsAct = E5Action(
            self.tr('Code Metrics'),
            self.tr('Code &Metrics...'), 0, 0,
            self, "")
        self.__editorRawMetricsAct.setWhatsThis(self.tr(
            """<b>Code Metrics...</b>"""
            """<p>This calculates raw code metrics of Python files"""
            """ and shows the amount of lines of code, logical lines"""
            """ of code, source lines of code, comment lines,"""
            """ multi-line strings and blank lines.</p>"""
        ))
        self.__editorRawMetricsAct.triggered.connect(self.__editorRawMetrics)
        
        self.__editorMIAct = E5Action(
            self.tr('Maintainability Index'),
            self.tr('Maintainability &Index...'), 0, 0,
            self, "")
        self.__editorMIAct.setStatusTip(
            self.tr('Show the maintainability index for Python files.'))
        self.__projectMIAct.setWhatsThis(self.tr(
            """<b>Maintainability Index...</b>"""
            """<p>This calculates the maintainability index of Python"""
            """ files and shows it together with a ranking.</p>"""
        ))
        self.__editorMIAct.triggered.connect(
            self.__editorMaintainabilityIndex)
        
        e5App().getObject("Project").showMenu.connect(self.__projectShowMenu)
        e5App().getObject("ProjectBrowser").getProjectBrowser("sources")\
            .showMenu.connect(self.__projectBrowserShowMenu)
        e5App().getObject("ViewManager").editorOpenedEd.connect(
            self.__editorOpened)
        e5App().getObject("ViewManager").editorClosedEd.connect(
            self.__editorClosed)
        
        for editor in e5App().getObject("ViewManager").getOpenEditors():
            self.__editorOpened(editor)
        
        return None, True
    
    def deactivate(self):
        """
        Public method to deactivate this plug-in.
        """
        e5App().getObject("Project").showMenu.disconnect(
            self.__projectShowMenu)
        e5App().getObject("ProjectBrowser").getProjectBrowser("sources")\
            .showMenu.disconnect(self.__projectBrowserShowMenu)
        e5App().getObject("ViewManager").editorOpenedEd.disconnect(
            self.__editorOpened)
        e5App().getObject("ViewManager").editorClosedEd.disconnect(
            self.__editorClosed)
        
        menu = e5App().getObject("Project").getMenu("Show")
        if menu:
            for sep in self.__projectSeparatorActs:
                menu.removeAction(sep)
            menu.removeAction(self.__projectRawMetricsAct)
            menu.removeAction(self.__projectMIAct)
            e5App().getObject("Project").removeE5Actions([
                self.__projectRawMetricsAct,
                self.__projectMIAct
            ])
        
        if self.__projectBrowserMenu:
            for sep in self.__projectBrowserSeparatorActs:
                self.__projectBrowserMenu.removeAction(sep)
            if self.__projectBrowserRawMetricsAct:
                self.__projectBrowserMenu.removeAction(
                    self.__projectBrowserRawMetricsAct)
            if self.__projectBrowserMIAct:
                self.__projectBrowserMenu.removeAction(
                    self.__projectBrowserMIAct)
        
        for editor in self.__editors:
            editor.showMenu.disconnect(self.__editorShowMenu)
            menu = editor.getMenu("Show")
            if menu is not None:
                for sep in self.__editorSeparatorActs:
                    menu.removeAction(sep)
                menu.removeAction(self.__editorRawMetricsAct)
                menu.removeAction(self.__editorMIAct)
        
        self.__initialize()
    
    def __loadTranslator(self):
        """
        Private method to load the translation file.
        """
        if self.__ui is not None:
            loc = self.__ui.getLocale()
            if loc and loc != "C":
                locale_dir = os.path.join(
                    os.path.dirname(__file__), "RadonMetrics", "i18n")
                translation = "radon_{0}".format(loc)
                translator = QTranslator(None)
                loaded = translator.load(translation, locale_dir)
                if loaded:
                    self.__translator = translator
                    e5App().installTranslator(self.__translator)
                else:
                    print("Warning: translation file '{0}' could not be"
                          " loaded.".format(translation))
                    print("Using default.")
    
    def __projectShowMenu(self, menuName, menu):
        """
        Private slot called, when the the project menu or a submenu is
        about to be shown.
        
        @param menuName name of the menu to be shown
        @type str
        @param menu reference to the menu
        @type QMenu
        """
        if menuName == "Show":
            for act in [self.__projectRawMetricsAct, self.__projectMIAct]:
                if act is not None:
                    act.setEnabled(
                        e5App().getObject("Project").getProjectLanguage() in
                        ["Python3", "Python2", "Python"])
    
    def __projectBrowserShowMenu(self, menuName, menu):
        """
        Private slot called, when the the project browser context menu or a
        submenu is about to be shown.
        
        @param menuName name of the menu to be shown (string)
        @param menu reference to the menu (QMenu)
        """
        if menuName == "Show" and \
           e5App().getObject("Project").getProjectLanguage() in \
                ["Python3", "Python2", "Python"]:
            if self.__projectBrowserMenu is None:
                self.__projectBrowserMenu = menu
                act = menu.addSeparator()
                act.setText(self.tr("Radon"))
                self.__projectBrowserSeparatorActs.append(act)
                
                self.__projectBrowserRawMetricsAct = E5Action(
                    self.tr('Code Metrics'),
                    self.tr('Code &Metrics...'), 0, 0,
                        self, '')
                self.__projectBrowserRawMetricsAct.setStatusTip(
                    self.tr('Show raw code metrics.'))
                self.__projectBrowserRawMetricsAct.setWhatsThis(self.tr(
                    """<b>Code Metrics...</b>"""
                    """<p>This calculates raw code metrics of Python files"""
                    """ and shows the amount of lines of code, logical lines"""
                    """ of code, source lines of code, comment lines,"""
                    """ multi-line strings and blank lines.</p>"""
                ))
                self.__projectBrowserRawMetricsAct.triggered.connect(
                    self.__projectBrowserRawMetrics)
                menu.addAction(self.__projectBrowserRawMetricsAct)
                
                self.__projectBrowserMIAct = E5Action(
                    self.tr('Maintainability Index'),
                    self.tr('Maintainability &Index...'), 0, 0,
                    self, 'project_show_radon_mi')
                self.__projectBrowserMIAct.setStatusTip(
                    self.tr('Show the maintainability index for Python'
                            ' files.'))
                self.__projectBrowserMIAct.setWhatsThis(self.tr(
                    """<b>Maintainability Index...</b>"""
                    """<p>This calculates the maintainability index of"""
                    """ Python files and shows it together with a ranking."""
                    """</p>"""
                ))
                self.__projectBrowserMIAct.triggered.connect(
                    self.__projectBrowserMaintainabilityIndex)
                menu.addAction(self.__projectBrowserMIAct)
    
    def __editorOpened(self, editor):
        """
        Private slot called, when a new editor was opened.
        
        @param editor reference to the new editor
        @type QScintilla.Editor
        """
        menu = editor.getMenu("Show")
        if menu is not None:
            menu.addAction(self.__editorSeparatorActs[0])
            menu.addAction(self.__editorRawMetricsAct)
            menu.addAction(self.__editorMIAct)
            menu.addAction(self.__editorSeparatorActs[1])
            editor.showMenu.connect(self.__editorShowMenu)
            self.__editors.append(editor)
    
    def __editorClosed(self, editor):
        """
        Private slot called, when an editor was closed.
        
        @param editor reference to the editor (QScintilla.Editor)
        """
        try:
            self.__editors.remove(editor)
        except ValueError:
            pass
    
    def __editorShowMenu(self, menuName, menu, editor):
        """
        Private slot called, when the the editor context menu or a submenu is
        about to be shown.
        
        @param menuName name of the menu to be shown (string)
        @param menu reference to the menu (QMenu)
        @param editor reference to the editor
        """
        if menuName == "Show":
            enable = editor.isPyFile()
            self.__editorRawMetricsAct.setEnabled(enable)
            self.__editorMIAct.setEnabled(enable)
    
    ##################################################################
    ## Raw code metrics calculations
    ##################################################################
    
    def __projectRawMetrics(self):
        """
        Private slot used to calculate raw code metrics for the project.
        """
        project = e5App().getObject("Project")
        project.saveAllScripts()
        ppath = project.getProjectPath()
        files = [os.path.join(ppath, file)
                 for file in project.pdata["SOURCES"]
                 if file.endswith(
                     tuple(Preferences.getPython("Python3Extensions")) +
                     tuple(Preferences.getPython("PythonExtensions")))]
        
        from RadonMetrics.RawMetricsDialog import RawMetricsDialog
        self.__projectRawMetricsDialog = RawMetricsDialog(self)
        self.__projectRawMetricsDialog.show()
        self.__projectRawMetricsDialog.prepare(files, project)
    
    def __projectBrowserRawMetrics(self):
        """
        Private method to handle the code metrics context menu action of the
        project sources browser.
        """
        browser = e5App().getObject("ProjectBrowser").getProjectBrowser(
            "sources")
        if browser.getSelectedItemsCount([ProjectBrowserFileItem]) > 1:
            fn = []
            for itm in browser.getSelectedItems([ProjectBrowserFileItem]):
                fn.append(itm.fileName())
        else:
            itm = browser.model().item(browser.currentIndex())
            try:
                fn = itm.fileName()
            except AttributeError:
                fn = itm.dirName()
        
        from RadonMetrics.RawMetricsDialog import RawMetricsDialog
        self.__projectBrowserRawMetricsDialog = RawMetricsDialog(self)
        self.__projectBrowserRawMetricsDialog.show()
        self.__projectBrowserRawMetricsDialog.start(fn)
    
    def __editorRawMetrics(self):
        """
        Private slot to handle the raw code metrics action of the editor show
        menu.
        """
        editor = e5App().getObject("ViewManager").activeWindow()
        if editor is not None:
            if editor.checkDirty() and editor.getFileName() is not None:
                from RadonMetrics.RawMetricsDialog import RawMetricsDialog
                self.__editorRawMetricsDialog = RawMetricsDialog(self)
                self.__editorRawMetricsDialog.show()
                self.__editorRawMetricsDialog.start(editor.getFileName())
    
    ##################################################################
    ## Maintainability index calculations
    ##################################################################
    
    def __projectMaintainabilityIndex(self):
        """
        Private slot used to calculate the maintainability indexes for the
        project.
        """
        project = e5App().getObject("Project")
        project.saveAllScripts()
        ppath = project.getProjectPath()
        files = [os.path.join(ppath, file)
                 for file in project.pdata["SOURCES"]
                 if file.endswith(
                     tuple(Preferences.getPython("Python3Extensions")) +
                     tuple(Preferences.getPython("PythonExtensions")))]
        
        from RadonMetrics.MaintainabilityIndexDialog import \
            MaintainabilityIndexDialog
        self.__projectMIDialog = MaintainabilityIndexDialog(self)
        self.__projectMIDialog.show()
        self.__projectMIDialog.prepare(files, project)
    
    def __projectBrowserMaintainabilityIndex(self):
        """
        Private method to handle the maintainability index context menu action
        of the project sources browser.
        """
        browser = e5App().getObject("ProjectBrowser").getProjectBrowser(
            "sources")
        if browser.getSelectedItemsCount([ProjectBrowserFileItem]) > 1:
            fn = []
            for itm in browser.getSelectedItems([ProjectBrowserFileItem]):
                fn.append(itm.fileName())
        else:
            itm = browser.model().item(browser.currentIndex())
            try:
                fn = itm.fileName()
            except AttributeError:
                fn = itm.dirName()
        
        from RadonMetrics.MaintainabilityIndexDialog import \
            MaintainabilityIndexDialog
        self.__projectBrowserMIDialog = MaintainabilityIndexDialog(self)
        self.__projectBrowserMIDialog.show()
        self.__projectBrowserMIDialog.start(fn)
    
    def __editorMaintainabilityIndex(self):
        """
        Private slot to handle the maintainability index action of the editor
        show menu.
        """
        editor = e5App().getObject("ViewManager").activeWindow()
        if editor is not None:
            if editor.checkDirty() and editor.getFileName() is not None:
                from RadonMetrics.MaintainabilityIndexDialog import \
                    MaintainabilityIndexDialog
                self.__editorMIDialog = MaintainabilityIndexDialog(self)
                self.__editorMIDialog.show()
                self.__editorMIDialog.start(editor.getFileName())

eric ide

mercurial