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

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

"""
Package implementing the interface to the PyLint source code checker.
"""

import os
import sys
import copy

from PyQt4.QtCore import QObject, SIGNAL
from PyQt4.QtGui import QDialog

from PyLintConfigDialog import PyLintConfigDialog
from PyLintExecDialog import PyLintExecDialog

from E4Gui.E4Action import E4Action

import Utilities

class PyLint(QObject):
    """ 
    Class implementing the high level PyLint interface.
    """
    def __init__(self, projectOrBrowser, parent):
        """
        Constructor
        
        @param projectOrBrowser reference to the project or project browser object
        @param parent parent object of this class (QObject)
        """
        QObject.__init__(self, parent)
        
        self.projectOrBrowser = projectOrBrowser
        self.actions = []
        
        self.pylintDialog = None

    def initActions(self):
        """
        Public method to initialize the PyLint actions.
        """
        self.actions = []
        
        self.pylintAct = E4Action(self.trUtf8('Run PyLint'),
                self.trUtf8('Run &PyLint...'),0,0,
                self,'project_check_pylint')
        self.pylintAct.setStatusTip(\
            self.trUtf8('Check project, packages or modules with pylint.'))
        self.pylintAct.setWhatsThis(self.trUtf8(
            """<b>Run PyLint...</b>"""
            """<p>This checks the project, packages or modules using pylint.</p>"""
        ))
        self.pylintAct.connectIt(SIGNAL('triggered()'),
            self.projectOrBrowser.handlePyLint)
        self.actions.append(self.pylintAct)
        
        self.pylintShowAct = E4Action(self.trUtf8('Show PyLint Dialog'),
                self.trUtf8('Show Py&Lint Dialog...'),0,0,
                self,'project_check_pylintshow')
        self.pylintShowAct.setStatusTip(\
            self.trUtf8('Show the PyLint dialog with the results of the last run.'))
        self.pylintShowAct.setWhatsThis(self.trUtf8(
            """<b>Show PyLint Dialog...</b>"""
            """<p>This shows the PyLint dialog with the results of the last run.</p>"""
        ))
        self.pylintShowAct.connectIt(SIGNAL('triggered()'),
            self.__pyLintShow)
        self.actions.append(self.pylintShowAct)
    
    def initMenu(self, menu):
        """
        Public method called to build the Checkers submenu.
        
        @param menu reference to the menu to add the actions to (QMenu)
        """
        menu.addSeparator()
        self.pylintAct.addTo(menu)
        self.pylintShowAct.addTo(menu)
        
        # entry for pylint is only activated if it is available
        exe = 'pylint'
        if sys.platform == "win32":
            exe = os.path.join(sys.exec_prefix, "Scripts", exe + '.bat')
        self.pylintAct.setEnabled(False)
        if Utilities.isinpath(exe):
            try:
                from pylint.__pkginfo__ import numversion
                if numversion > (0, 11, 99):
                    self.pylintAct.setEnabled(True)
            except ImportError:
                pass
    
    def getActions(self):
        """
        Public method to get a list of all actions.
        
        @return list of all actions (list of E4Action)
        """
        return self.actions[:]
    
    def checkActions(self):
        """
        Public slot to activate/deactivate action upon display of the menu.
        """
        self.pylintShowAct.setEnabled(self.pylintDialog is not None)

    def pyLint(self, project, mpName):
        """
        Public method used to perform a PyLint run.
        
        @param project reference to the Project object
        @param mpName name of module or package to be checked (string or QString)
        """
        if len(project.pdata['PYLINTPARMS']):
            parms = copy.deepcopy(project.pdata['PYLINTPARMS'][0])
        else:
            parms = None
        dlg = PyLintConfigDialog(project.ppath, parms)
        if dlg.exec_() == QDialog.Accepted:
            args, parms = dlg.generateParameters()
            
            # test for changes of selected parameters and save them in the project
            # 1. there were none, now there are
            if len(project.pdata['PYLINTPARMS']) == 0 and len(parms) > 0:
                project.pdata['PYLINTPARMS'] = [copy.deepcopy(parms)]
                project.setDirty(True)
            # 2. there were some, now there aren't
            elif len(project.pdata['PYLINTPARMS']) > 0 and len(parms) == 0:
                project.pdata['PYLINTPARMS'] = []
                project.setDirty(True)
            # 3. there were some and still are
            else:
                if parms != project.pdata['PYLINTPARMS'][0]:
                    project.pdata['PYLINTPARMS'] = [copy.deepcopy(parms)]
                    project.setDirty(True)
            
            # now do the call
            self.pylintDialog = PyLintExecDialog()
            try:
                reportFile = parms['reportFile']
            except KeyError:
                reportFile = None
            res = self.pylintDialog.start(args, mpName, reportFile, project.ppath)
            if res:
                self.pylintDialog.show()
    
    def __pyLintShow(self):
        """
        Private slot to show the PyLint dialog with the results of the last run.
        """
        if self.pylintDialog is not None:
            self.pylintDialog.show()

    def closeAllWindows(self):
        """
        Public method to close all windows.
        """
        self.pylintDialog and self.pylintDialog.close()
