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

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

"""
Package implementing various modules for source code checks.
"""

import os
import sys
import copy

from qt import *

from TabnannyDialog import TabnannyDialog
from SyntaxCheckerDialog import SyntaxCheckerDialog
from PyLintConfigDialog import PyLintConfigDialog
from PyLintExecDialog import PyLintExecDialog

from UI.E3Action import E3Action

import Utilities

class Checkers(QObject):
    """ 
    Class implementing the high level 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
        self.tabnannyDialog = None
        self.syntaxcheckDialog = None

    def initActions(self):
        """
        Private method to initialize the Checkers actions.
        """
        self.actions = []
        
        self.checkSyntaxAct = E3Action(self.trUtf8('Check Syntax'),
                self.trUtf8('&Syntax...'),0,0,
                self,'project_check_syntax')
        self.checkSyntaxAct.setStatusTip(self.trUtf8('Check syntax.'))
        self.checkSyntaxAct.setWhatsThis(self.trUtf8(
            """<b>Check Syntax...</b>"""
            """<p>This checks all Python files for syntax errors.</p>"""
        ))
        self.checkSyntaxAct.connectIt(SIGNAL('activated()'),
            self.projectOrBrowser.handleSyntaxCheck)
        self.actions.append(self.checkSyntaxAct)

        self.tabnannyAct = E3Action(self.trUtf8('Check Indentations'),
                self.trUtf8('&Indentations...'),0,0,
                self,'project_check_indentations')
        self.tabnannyAct.setStatusTip(self.trUtf8('Check indentations using tabnanny.'))
        self.tabnannyAct.setWhatsThis(self.trUtf8(
            """<b>Check Indentations...</b>"""
            """<p>This checks all Python files"""
            """ for bad indentations using tabnanny.</p>"""
        ))
        self.tabnannyAct.connectIt(SIGNAL('activated()'),
            self.projectOrBrowser.handleTabnanny)
        self.actions.append(self.tabnannyAct)

        self.pylintAct = E3Action(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('activated()'),
            self.projectOrBrowser.handlePyLint)
        self.actions.append(self.pylintAct)

        self.pylintShowAct = E3Action(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('activated()'),
            self.handlePyLintShow)
        self.actions.append(self.pylintShowAct)
        
    def initMenu(self):
        """
        Private method called to build the project packagers submenu.
        
        @return the menu or None
        """
        menu = QPopupMenu(self.parent())
        menu.insertTearOffHandle()
        
        self.checkSyntaxAct.addTo(menu)
        self.tabnannyAct.addTo(menu)
        menu.insertSeparator()
        self.pylintAct.addTo(menu)
        self.pylintShowAct.addTo(menu)
        
        # entry for cxfreeze is only activated if it is accessible
        exe = 'pylint'
        if sys.platform == "win32":
            exe += '.bat'
        self.pylintAct.setEnabled(Utilities.isinpath(exe))
        
        # connect the aboutToShow signal
        self.connect(menu, SIGNAL('aboutToShow()'), self.handleShowMenu)
        
        return menu
        
    def getActions(self):
        """
        Public method to get a list of all actions.
        
        @return list of all actions (list of E3Action)
        """
        return self.actions[:]

    def handleTabnanny(self, files):
        """
        Private slot used to check the project files for bad indentations.
        
        @param files File or list of files or directory to be checked
                (string or list of strings)
        """
        self.tabnannyDialog = TabnannyDialog(qApp.mainWidget().getViewManager())
        self.tabnannyDialog.show()
        self.tabnannyDialog.start(files)
    
    def handleSyntaxCheck(self, files):
        """
        Private slot used to check the project files for bad syntax.
        
        @param files File or list of files or directory to be checked
                (string or list of strings)
        """
        self.syntaxcheckDialog = SyntaxCheckerDialog(qApp.mainWidget().getViewManager())
        self.syntaxcheckDialog.show()
        self.syntaxcheckDialog.start(files)

    def handlePyLint(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_loop() == QDialog.Accepted:
            args, parms = dlg.generateParameters()
            
            # test for changes of selected parameters and save the 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(1)
            # 2. there were some, now there aren't
            elif len(project.pdata['PYLINTPARMS']) > 0 and len(parms) == 0:
                project.pdata['PYLINTPARMS'] = []
                project.setDirty(1)
            # 3. there were some and still are
            else:
                if parms != project.pdata['PYLINTPARMS'][0]:
                    project.pdata['PYLINTPARMS'] = [copy.deepcopy(parms)]
                    project.setDirty(1)
                    
            # 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 handlePyLintShow(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 handleShowMenu(self):
        """
        Private slot to handle the aboutToShow signal of the menu.
        """
        self.pylintShowAct.setEnabled(self.pylintDialog is not None)
