eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.py

changeset 6942
2602857055c5
parent 6786
701b511ba8f5
child 7040
f89952e5fc11
diff -r f99d60d6b59b -r 2602857055c5 eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/CodeStyleCheckerDialog.py	Sun Apr 14 15:09:21 2019 +0200
@@ -0,0 +1,1298 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to show the results of the code style check.
+"""
+
+from __future__ import unicode_literals
+
+import os
+import fnmatch
+
+from PyQt5.QtCore import pyqtSlot, Qt, QTimer
+from PyQt5.QtGui import QIcon
+from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QAbstractButton, \
+    QDialogButtonBox, QApplication, QHeaderView, QListWidgetItem
+
+from E5Gui.E5Application import e5App
+
+from .Ui_CodeStyleCheckerDialog import Ui_CodeStyleCheckerDialog
+
+import UI.PixmapCache
+import Preferences
+import Utilities
+
+from . import pycodestyle
+
+try:
+    basestring          # __IGNORE_WARNING__
+except Exception:
+    basestring = str    # define for Python3
+
+
+class CodeStyleCheckerDialog(QDialog, Ui_CodeStyleCheckerDialog):
+    """
+    Class implementing a dialog to show the results of the code style check.
+    """
+    filenameRole = Qt.UserRole + 1
+    lineRole = Qt.UserRole + 2
+    positionRole = Qt.UserRole + 3
+    messageRole = Qt.UserRole + 4
+    fixableRole = Qt.UserRole + 5
+    codeRole = Qt.UserRole + 6
+    ignoredRole = Qt.UserRole + 7
+    
+    availableFutures = [
+        'division', 'absolute_import', 'with_statement',
+        'print_function', 'unicode_literals', 'generator_stop']
+    
+    noResults = 0
+    noFiles = 1
+    hasResults = 2
+    
+    def __init__(self, styleCheckService, parent=None):
+        """
+        Constructor
+        
+        @param styleCheckService reference to the service
+            (CodeStyleCheckService)
+        @param parent reference to the parent widget (QWidget)
+        """
+        super(CodeStyleCheckerDialog, self).__init__(parent)
+        self.setupUi(self)
+        self.setWindowFlags(Qt.Window)
+        
+        self.optionsTabWidget.setCurrentIndex(0)
+        
+        self.excludeMessagesSelectButton.setIcon(
+            UI.PixmapCache.getIcon("select.png"))
+        self.includeMessagesSelectButton.setIcon(
+            UI.PixmapCache.getIcon("select.png"))
+        self.fixIssuesSelectButton.setIcon(
+            UI.PixmapCache.getIcon("select.png"))
+        self.noFixIssuesSelectButton.setIcon(
+            UI.PixmapCache.getIcon("select.png"))
+        
+        self.docTypeComboBox.addItem(self.tr("PEP-257"), "pep257")
+        self.docTypeComboBox.addItem(self.tr("Eric"), "eric")
+        
+        for future in CodeStyleCheckerDialog.availableFutures:
+            itm = QListWidgetItem(future, self.futuresList)
+            itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
+            itm.setCheckState(Qt.Unchecked)
+        
+        self.statisticsButton = self.buttonBox.addButton(
+            self.tr("Statistics..."), QDialogButtonBox.ActionRole)
+        self.statisticsButton.setToolTip(
+            self.tr("Press to show some statistics for the last run"))
+        self.statisticsButton.setEnabled(False)
+        self.showButton = self.buttonBox.addButton(
+            self.tr("Show"), QDialogButtonBox.ActionRole)
+        self.showButton.setToolTip(
+            self.tr("Press to show all files containing an issue"))
+        self.showButton.setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
+        
+        self.resultList.headerItem().setText(self.resultList.columnCount(), "")
+        self.resultList.header().setSortIndicator(0, Qt.AscendingOrder)
+        
+        self.addBuiltinButton.setIcon(UI.PixmapCache.getIcon("plus.png"))
+        self.deleteBuiltinButton.setIcon(UI.PixmapCache.getIcon("minus.png"))
+        
+        self.checkProgress.setVisible(False)
+        self.checkProgressLabel.setVisible(False)
+        self.checkProgressLabel.setMaximumWidth(600)
+        
+        self.styleCheckService = styleCheckService
+        self.styleCheckService.styleChecked.connect(self.__processResult)
+        self.styleCheckService.batchFinished.connect(self.__batchFinished)
+        self.styleCheckService.error.connect(self.__processError)
+        self.filename = None
+        
+        self.results = CodeStyleCheckerDialog.noResults
+        self.cancelled = False
+        self.__lastFileItem = None
+        self.__batch = False
+        self.__finished = True
+        self.__errorItem = None
+        
+        self.__fileOrFileList = ""
+        self.__project = None
+        self.__forProject = False
+        self.__data = {}
+        self.__statistics = {}
+        self.__onlyFixes = {}
+        self.__noFixCodesList = []
+        
+        self.on_loadDefaultButton_clicked()
+    
+    def __resort(self):
+        """
+        Private method to resort the tree.
+        """
+        self.resultList.sortItems(self.resultList.sortColumn(),
+                                  self.resultList.header().sortIndicatorOrder()
+                                  )
+    
+    def __createErrorItem(self, filename, message):
+        """
+        Private slot to create a new error item in the result list.
+        
+        @param filename name of the file
+        @type str
+        @param message error message
+        @type str
+        """
+        if self.__errorItem is None:
+            self.__errorItem = QTreeWidgetItem(self.resultList, [
+                self.tr("Errors")])
+            self.__errorItem.setExpanded(True)
+            self.__errorItem.setForeground(0, Qt.red)
+        
+        msg = "{0} ({1})".format(self.__project.getRelativePath(filename),
+                                 message)
+        if not self.resultList.findItems(msg, Qt.MatchExactly):
+            itm = QTreeWidgetItem(self.__errorItem, [msg])
+            itm.setForeground(0, Qt.red)
+            itm.setFirstColumnSpanned(True)
+    
+    def __createResultItem(self, filename, line, pos, message, fixed,
+                           autofixing, ignored):
+        """
+        Private method to create an entry in the result list.
+        
+        @param filename file name of the file (string)
+        @param line line number of issue (integer or string)
+        @param pos character position of issue (integer or string)
+        @param message message text (string)
+        @param fixed flag indicating a fixed issue (boolean)
+        @param autofixing flag indicating, that we are fixing issues
+            automatically (boolean)
+        @param ignored flag indicating an ignored issue (boolean)
+        @return reference to the created item (QTreeWidgetItem)
+        """
+        from .CodeStyleFixer import FixableCodeStyleIssues
+        
+        if self.__lastFileItem is None:
+            # It's a new file
+            self.__lastFileItem = QTreeWidgetItem(self.resultList, [
+                self.__project.getRelativePath(filename)])
+            self.__lastFileItem.setFirstColumnSpanned(True)
+            self.__lastFileItem.setExpanded(True)
+            self.__lastFileItem.setData(0, self.filenameRole, filename)
+        
+        fixable = False
+        code, message = message.split(None, 1)
+        itm = QTreeWidgetItem(
+            self.__lastFileItem,
+            ["{0:6}".format(line), code, message])
+        if code.startswith(("W", "-", "C", "M")):
+            itm.setIcon(1, UI.PixmapCache.getIcon("warning.png"))
+        elif code.startswith("N"):
+            itm.setIcon(1, UI.PixmapCache.getIcon("namingError.png"))
+        elif code.startswith("D"):
+            itm.setIcon(1, UI.PixmapCache.getIcon("docstringError.png"))
+        else:
+            itm.setIcon(1, UI.PixmapCache.getIcon("syntaxError.png"))
+        if fixed:
+            itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed.png"))
+        elif code in FixableCodeStyleIssues and not autofixing and \
+                code not in self.__noFixCodesList:
+            itm.setIcon(0, UI.PixmapCache.getIcon("issueFixable.png"))
+            fixable = True
+        
+        itm.setTextAlignment(0, Qt.AlignRight)
+        itm.setTextAlignment(1, Qt.AlignHCenter)
+        
+        itm.setTextAlignment(0, Qt.AlignVCenter)
+        itm.setTextAlignment(1, Qt.AlignVCenter)
+        itm.setTextAlignment(2, Qt.AlignVCenter)
+        
+        itm.setData(0, self.filenameRole, filename)
+        itm.setData(0, self.lineRole, int(line))
+        itm.setData(0, self.positionRole, int(pos))
+        itm.setData(0, self.messageRole, message)
+        itm.setData(0, self.fixableRole, fixable)
+        itm.setData(0, self.codeRole, code)
+        itm.setData(0, self.ignoredRole, ignored)
+        
+        if ignored:
+            font = itm.font(0)
+            font.setItalic(True)
+            for col in range(itm.columnCount()):
+                itm.setFont(col, font)
+        
+        return itm
+    
+    def __modifyFixedResultItem(self, itm, text, fixed):
+        """
+        Private method to modify a result list entry to show its
+        positive fixed state.
+        
+        @param itm reference to the item to modify (QTreeWidgetItem)
+        @param text text to be appended (string)
+        @param fixed flag indicating a fixed issue (boolean)
+        """
+        if fixed:
+            code, message = text.split(None, 1)
+            itm.setText(2, message)
+            itm.setIcon(0, UI.PixmapCache.getIcon("issueFixed.png"))
+            
+            itm.setData(0, self.messageRole, message)
+        else:
+            itm.setIcon(0, QIcon())
+        itm.setData(0, self.fixableRole, False)
+    
+    def __updateStatistics(self, statistics, fixer, ignoredErrors):
+        """
+        Private method to update the collected statistics.
+        
+        @param statistics dictionary of statistical data with
+            message code as key and message count as value
+        @param fixer reference to the code style fixer (CodeStyleFixer)
+        @param ignoredErrors number of ignored errors (integer)
+        """
+        self.__statistics["_FilesCount"] += 1
+        stats = [k for k in statistics.keys() if k[0].isupper()]
+        if stats:
+            self.__statistics["_FilesIssues"] += 1
+            for key in statistics:
+                if key in self.__statistics:
+                    self.__statistics[key] += statistics[key]
+                else:
+                    self.__statistics[key] = statistics[key]
+        self.__statistics["_IssuesFixed"] += fixer
+        self.__statistics["_IgnoredErrors"] += ignoredErrors
+    
+    def __updateFixerStatistics(self, fixer):
+        """
+        Private method to update the collected fixer related statistics.
+        
+        @param fixer reference to the code style fixer (CodeStyleFixer)
+        """
+        self.__statistics["_IssuesFixed"] += fixer
+    
+    def __resetStatistics(self):
+        """
+        Private slot to reset the statistics data.
+        """
+        self.__statistics = {}
+        self.__statistics["_FilesCount"] = 0
+        self.__statistics["_FilesIssues"] = 0
+        self.__statistics["_IssuesFixed"] = 0
+        self.__statistics["_IgnoredErrors"] = 0
+    
+    def prepare(self, fileList, project):
+        """
+        Public method to prepare the dialog with a list of filenames.
+        
+        @param fileList list of filenames (list of strings)
+        @param project reference to the project object (Project)
+        """
+        self.__fileOrFileList = fileList[:]
+        self.__project = project
+        self.__forProject = True
+        
+        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
+        
+        self.__data = self.__project.getData("CHECKERSPARMS", "Pep8Checker")
+        if self.__data is None or \
+           len(self.__data) < 6:
+            # initialize the data structure
+            self.__data = {
+                "ExcludeFiles": "",
+                "ExcludeMessages": pycodestyle.DEFAULT_IGNORE,
+                "IncludeMessages": "",
+                "RepeatMessages": False,
+                "FixCodes": "",
+                "FixIssues": False,
+            }
+        if "MaxLineLength" not in self.__data:
+            self.__data["MaxLineLength"] = pycodestyle.MAX_LINE_LENGTH
+        if "MaxDocLineLength" not in self.__data:
+            # Use MAX_LINE_LENGTH to avoid messages on existing code
+            self.__data["MaxDocLineLength"] = pycodestyle.MAX_LINE_LENGTH
+        if "BlankLines" not in self.__data:
+            self.__data["BlankLines"] = (2, 1)
+            # top level, method
+        if "HangClosing" not in self.__data:
+            self.__data["HangClosing"] = False
+        if "NoFixCodes" not in self.__data:
+            self.__data["NoFixCodes"] = "E501"
+        if "DocstringType" not in self.__data:
+            self.__data["DocstringType"] = "pep257"
+        if "ShowIgnored" not in self.__data:
+            self.__data["ShowIgnored"] = False
+        if "MaxCodeComplexity" not in self.__data:
+            self.__data["MaxCodeComplexity"] = 10
+        if "LineComplexity" not in self.__data:
+            self.__data["LineComplexity"] = 15
+        if "LineComplexityScore" not in self.__data:
+            self.__data["LineComplexityScore"] = 10
+        if "ValidEncodings" not in self.__data:
+            self.__data["ValidEncodings"] = "latin-1, utf-8"
+        if "CopyrightMinFileSize" not in self.__data or \
+                "CopyrightAuthor" not in self.__data:
+            self.__data["CopyrightMinFileSize"] = 0
+            self.__data["CopyrightAuthor"] = ""
+        if "FutureChecker" not in self.__data:
+            self.__data["FutureChecker"] = ""
+        if "BuiltinsChecker" not in self.__data:
+            self.__data["BuiltinsChecker"] = {
+                "str": ["unicode", ],
+                "chr": ["unichr", ],
+            }
+        
+        self.excludeFilesEdit.setText(self.__data["ExcludeFiles"])
+        self.excludeMessagesEdit.setText(self.__data["ExcludeMessages"])
+        self.includeMessagesEdit.setText(self.__data["IncludeMessages"])
+        self.repeatCheckBox.setChecked(self.__data["RepeatMessages"])
+        self.fixIssuesEdit.setText(self.__data["FixCodes"])
+        self.noFixIssuesEdit.setText(self.__data["NoFixCodes"])
+        self.fixIssuesCheckBox.setChecked(self.__data["FixIssues"])
+        self.ignoredCheckBox.setChecked(self.__data["ShowIgnored"])
+        self.lineLengthSpinBox.setValue(self.__data["MaxLineLength"])
+        self.docLineLengthSpinBox.setValue(self.__data["MaxDocLineLength"])
+        self.blankBeforeTopLevelSpinBox.setValue(self.__data["BlankLines"][0])
+        self.blankBeforeMethodSpinBox.setValue(self.__data["BlankLines"][1])
+        self.hangClosingCheckBox.setChecked(self.__data["HangClosing"])
+        self.docTypeComboBox.setCurrentIndex(
+            self.docTypeComboBox.findData(self.__data["DocstringType"]))
+        self.complexitySpinBox.setValue(self.__data["MaxCodeComplexity"])
+        self.lineComplexitySpinBox.setValue(self.__data["LineComplexity"])
+        self.lineComplexityScoreSpinBox.setValue(
+            self.__data["LineComplexityScore"])
+        self.encodingsEdit.setText(self.__data["ValidEncodings"])
+        self.copyrightFileSizeSpinBox.setValue(
+            self.__data["CopyrightMinFileSize"])
+        self.copyrightAuthorEdit.setText(self.__data["CopyrightAuthor"])
+        self.__initFuturesList(self.__data["FutureChecker"])
+        self.__initBuiltinsIgnoreList(self.__data["BuiltinsChecker"])
+    
+    def start(self, fn, save=False, repeat=None):
+        """
+        Public slot to start the code style check.
+        
+        @param fn file or list of files or directory to be checked
+                (string or list of strings)
+        @keyparam save flag indicating to save the given
+            file/file list/directory (boolean)
+        @keyparam repeat state of the repeat check box if it is not None
+            (None or boolean)
+        """
+        if self.__project is None:
+            self.__project = e5App().getObject("Project")
+        
+        self.cancelled = False
+        self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True)
+        self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
+        self.statisticsButton.setEnabled(False)
+        self.showButton.setEnabled(False)
+        self.fixButton.setEnabled(False)
+        self.startButton.setEnabled(False)
+        if repeat is not None:
+            self.repeatCheckBox.setChecked(repeat)
+        self.checkProgress.setVisible(True)
+        QApplication.processEvents()
+        
+        if save:
+            self.__fileOrFileList = fn
+        
+        if isinstance(fn, list):
+            self.files = fn[:]
+        elif os.path.isdir(fn):
+            self.files = []
+            extensions = set(Preferences.getPython("PythonExtensions") +
+                             Preferences.getPython("Python3Extensions"))
+            for ext in extensions:
+                self.files.extend(Utilities.direntries(
+                    fn, True, '*{0}'.format(ext), 0))
+        else:
+            self.files = [fn]
+
+        # filter the list depending on the filter string
+        if self.files:
+            filterString = self.excludeFilesEdit.text()
+            filterList = [f.strip() for f in filterString.split(",")
+                          if f.strip()]
+            for fileFilter in filterList:
+                self.files = \
+                    [f for f in self.files
+                     if not fnmatch.fnmatch(f, fileFilter.strip())]
+
+        self.__errorItem = None
+        self.__resetStatistics()
+        self.__clearErrors(self.files)
+        
+        if len(self.files) > 0:
+            self.checkProgress.setMaximum(len(self.files))
+            self.checkProgressLabel.setVisible(len(self.files) > 1)
+            self.checkProgress.setVisible(len(self.files) > 1)
+            QApplication.processEvents()
+            
+            # extract the configuration values
+            excludeMessages = self.excludeMessagesEdit.text()
+            includeMessages = self.includeMessagesEdit.text()
+            repeatMessages = self.repeatCheckBox.isChecked()
+            fixCodes = self.fixIssuesEdit.text()
+            noFixCodes = self.noFixIssuesEdit.text()
+            self.__noFixCodesList = \
+                [c.strip() for c in noFixCodes.split(",") if c.strip()]
+            fixIssues = self.fixIssuesCheckBox.isChecked() and repeatMessages
+            self.showIgnored = self.ignoredCheckBox.isChecked() and \
+                repeatMessages
+            maxLineLength = self.lineLengthSpinBox.value()
+            maxDocLineLength = self.docLineLengthSpinBox.value()
+            blankLines = (
+                self.blankBeforeTopLevelSpinBox.value(),
+                self.blankBeforeMethodSpinBox.value()
+            )
+            hangClosing = self.hangClosingCheckBox.isChecked()
+            docType = self.docTypeComboBox.itemData(
+                self.docTypeComboBox.currentIndex())
+            codeComplexityArgs = {
+                "McCabeComplexity": self.complexitySpinBox.value(),
+                "LineComplexity": self.lineComplexitySpinBox.value(),
+                "LineComplexityScore": self.lineComplexityScoreSpinBox.value(),
+            }
+            miscellaneousArgs = {
+                "CodingChecker": self.encodingsEdit.text(),
+                "CopyrightChecker": {
+                    "MinFilesize": self.copyrightFileSizeSpinBox.value(),
+                    "Author": self.copyrightAuthorEdit.text(),
+                },
+                "FutureChecker": self.__getSelectedFutureImports(),
+                "BuiltinsChecker": self.__getBuiltinsIgnoreList(),
+            }
+            
+            self.__options = [excludeMessages, includeMessages, repeatMessages,
+                              fixCodes, noFixCodes, fixIssues, maxLineLength,
+                              maxDocLineLength, blankLines, hangClosing,
+                              docType, codeComplexityArgs, miscellaneousArgs]
+            
+            # now go through all the files
+            self.progress = 0
+            self.files.sort()
+            if len(self.files) == 1:
+                self.__batch = False
+                self.check()
+            else:
+                self.__batch = True
+                self.checkBatch()
+        else:
+            self.results = CodeStyleCheckerDialog.noFiles
+            self.__finished = False
+            self.__finish()
+    
+    def __modifyOptions(self, source):
+        """
+        Private method to modify the options based on eflag: entries.
+        
+        This method looks for comment lines like '# eflag: noqa = M601'
+        at the end of the source in order to extend the list of excluded
+        messages for one file only.
+        
+        @param source source text (list of str or str)
+        @return list of checker options
+        """
+        options = self.__options[:]
+        flags = Utilities.extractFlags(source)
+        if "noqa" in flags and isinstance(flags["noqa"], basestring):
+            excludeMessages = \
+                options[0].strip().rstrip(",")
+            if excludeMessages:
+                excludeMessages += ","
+            excludeMessages += flags["noqa"]
+            options[0] = excludeMessages
+        return options
+    
+    def check(self, codestring=''):
+        """
+        Public method to start a style check for one file.
+        
+        The results are reported to the __processResult slot.
+        
+        @keyparam codestring optional sourcestring (str)
+        """
+        if not self.files:
+            self.checkProgressLabel.setPath("")
+            self.checkProgress.setMaximum(1)
+            self.checkProgress.setValue(1)
+            self.__finish()
+            return
+        
+        self.filename = self.files.pop(0)
+        self.checkProgress.setValue(self.progress)
+        self.checkProgressLabel.setPath(self.filename)
+        QApplication.processEvents()
+
+        if self.cancelled:
+            self.__resort()
+            return
+        
+        self.__lastFileItem = None
+        
+        if codestring:
+            source = codestring.splitlines(True)
+            encoding = Utilities.get_coding(source)
+        else:
+            try:
+                source, encoding = Utilities.readEncodedFile(
+                    self.filename)
+                source = source.splitlines(True)
+            except (UnicodeError, IOError) as msg:
+                self.results = CodeStyleCheckerDialog.hasResults
+                self.__createResultItem(
+                    self.filename, 1, 1,
+                    self.tr("Error: {0}").format(str(msg))
+                        .rstrip(), False, False, False)
+                self.progress += 1
+                # Continue with next file
+                self.check()
+                return
+        if encoding.endswith(
+                ('-selected', '-default', '-guessed', '-ignore')):
+            encoding = encoding.rsplit('-', 1)[0]
+        
+        options = self.__modifyOptions(source)
+        
+        errors = []
+        self.__itms = []
+        for error, itm in self.__onlyFixes.pop(self.filename, []):
+            errors.append(error)
+            self.__itms.append(itm)
+        
+        eol = self.__getEol(self.filename)
+        args = options + [
+            errors, eol, encoding, Preferences.getEditor("CreateBackupFile")
+        ]
+        self.__finished = False
+        self.styleCheckService.styleCheck(
+            None, self.filename, source, args)
+    
+    def checkBatch(self):
+        """
+        Public method to start a style check batch job.
+        
+        The results are reported to the __processResult slot.
+        """
+        self.__lastFileItem = None
+        
+        self.checkProgressLabel.setPath(self.tr("Preparing files..."))
+        progress = 0
+        
+        argumentsList = []
+        for filename in self.files:
+            progress += 1
+            self.checkProgress.setValue(progress)
+            QApplication.processEvents()
+            
+            try:
+                source, encoding = Utilities.readEncodedFile(
+                    filename)
+                source = source.splitlines(True)
+            except (UnicodeError, IOError) as msg:
+                self.results = CodeStyleCheckerDialog.hasResults
+                self.__createResultItem(
+                    filename, 1, 1,
+                    self.tr("Error: {0}").format(str(msg))
+                        .rstrip(), False, False, False)
+                continue
+            
+            if encoding.endswith(
+                    ('-selected', '-default', '-guessed', '-ignore')):
+                encoding = encoding.rsplit('-', 1)[0]
+            
+            options = self.__modifyOptions(source)
+            
+            errors = []
+            self.__itms = []
+            for error, itm in self.__onlyFixes.pop(filename, []):
+                errors.append(error)
+                self.__itms.append(itm)
+            
+            eol = self.__getEol(filename)
+            args = options + [
+                errors, eol, encoding,
+                Preferences.getEditor("CreateBackupFile")
+            ]
+            argumentsList.append((filename, source, args))
+        
+        # reset the progress bar to the checked files
+        self.checkProgress.setValue(self.progress)
+        self.checkProgressLabel.setPath(self.tr("Transferring data..."))
+        QApplication.processEvents()
+        
+        self.__finished = False
+        self.styleCheckService.styleBatchCheck(argumentsList)
+    
+    def __batchFinished(self):
+        """
+        Private slot handling the completion of a batch job.
+        """
+        self.checkProgressLabel.setPath("")
+        self.checkProgress.setMaximum(1)
+        self.checkProgress.setValue(1)
+        self.__finish()
+    
+    def __processError(self, fn, msg):
+        """
+        Private slot to process an error indication from the service.
+        
+        @param fn filename of the file
+        @type str
+        @param msg error message
+        @type str
+        """
+        self.__createErrorItem(fn, msg)
+        
+        if not self.__batch:
+            self.check()
+    
+    def __processResult(self, fn, codeStyleCheckerStats, fixes, results):
+        """
+        Private slot called after perfoming a style check on one file.
+        
+        @param fn filename of the just checked file (str)
+        @param codeStyleCheckerStats stats of style and name check (dict)
+        @param fixes number of applied fixes (int)
+        @param results tuple for each found violation of style (tuple of
+            lineno (int), position (int), text (str), ignored (bool),
+            fixed (bool), autofixing (bool))
+        """
+        if self.__finished:
+            return
+        
+        # Check if it's the requested file, otherwise ignore signal if not
+        # in batch mode
+        if not self.__batch and fn != self.filename:
+            return
+        
+        # disable updates of the list for speed
+        self.resultList.setUpdatesEnabled(False)
+        self.resultList.setSortingEnabled(False)
+        
+        fixed = None
+        ignoredErrors = 0
+        if self.__itms:
+            for itm, (_lineno, _position, text, _ignored, fixed,
+                      _autofixing) in zip(self.__itms, results):
+                self.__modifyFixedResultItem(itm, text, fixed)
+            self.__updateFixerStatistics(fixes)
+        else:
+            self.__lastFileItem = None
+            
+            for lineno, position, text, ignored, fixed, autofixing in results:
+                if ignored:
+                    ignoredErrors += 1
+                    if self.showIgnored:
+                        text = self.tr("{0} (ignored)").format(text)
+                    else:
+                        continue
+                self.results = CodeStyleCheckerDialog.hasResults
+                self.__createResultItem(
+                    fn, lineno, position, text, fixed, autofixing, ignored)
+
+            self.__updateStatistics(
+                codeStyleCheckerStats, fixes, ignoredErrors)
+        
+        if fixed:
+            vm = e5App().getObject("ViewManager")
+            editor = vm.getOpenEditor(fn)
+            if editor:
+                editor.refresh()
+        
+        self.progress += 1
+        
+        self.__resort()
+        # reenable updates of the list
+        self.resultList.setSortingEnabled(True)
+        self.resultList.setUpdatesEnabled(True)
+        
+        self.checkProgress.setValue(self.progress)
+        self.checkProgressLabel.setPath(fn)
+        QApplication.processEvents()
+        
+        if not self.__batch:
+            self.check()
+    
+    def __finish(self):
+        """
+        Private slot called when the code style check finished or the user
+        pressed the cancel button.
+        """
+        if not self.__finished:
+            self.__finished = True
+            
+            self.cancelled = True
+            self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
+            self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
+            self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
+            self.statisticsButton.setEnabled(True)
+            self.showButton.setEnabled(True)
+            self.startButton.setEnabled(True)
+            
+            if self.results != CodeStyleCheckerDialog.hasResults:
+                if self.results == CodeStyleCheckerDialog.noResults:
+                    QTreeWidgetItem(
+                        self.resultList, [self.tr('No issues found.')])
+                else:
+                    QTreeWidgetItem(
+                        self.resultList,
+                        [self.tr('No files found (check your ignore list).')])
+                QApplication.processEvents()
+                self.showButton.setEnabled(False)
+            else:
+                self.showButton.setEnabled(True)
+            self.resultList.header().resizeSections(
+                QHeaderView.ResizeToContents)
+            self.resultList.header().setStretchLastSection(True)
+            
+            self.checkProgress.setVisible(False)
+            self.checkProgressLabel.setVisible(False)
+    
+    def __getEol(self, fn):
+        """
+        Private method to get the applicable eol string.
+        
+        @param fn filename where to determine the line ending (str)
+        @return eol string (string)
+        """
+        if self.__project.isOpen() and self.__project.isProjectFile(fn):
+            eol = self.__project.getEolString()
+        else:
+            eol = Utilities.linesep()
+        return eol
+    
+    @pyqtSlot()
+    def on_startButton_clicked(self):
+        """
+        Private slot to start a code style check run.
+        """
+        if self.__forProject:
+            data = {
+                "ExcludeFiles": self.excludeFilesEdit.text(),
+                "ExcludeMessages": self.excludeMessagesEdit.text(),
+                "IncludeMessages": self.includeMessagesEdit.text(),
+                "RepeatMessages": self.repeatCheckBox.isChecked(),
+                "FixCodes": self.fixIssuesEdit.text(),
+                "NoFixCodes": self.noFixIssuesEdit.text(),
+                "FixIssues": self.fixIssuesCheckBox.isChecked(),
+                "ShowIgnored": self.ignoredCheckBox.isChecked(),
+                "MaxLineLength": self.lineLengthSpinBox.value(),
+                "MaxDocLineLength": self.docLineLengthSpinBox.value(),
+                "BlankLines": (
+                    self.blankBeforeTopLevelSpinBox.value(),
+                    self.blankBeforeMethodSpinBox.value()
+                ),
+                "HangClosing": self.hangClosingCheckBox.isChecked(),
+                "DocstringType": self.docTypeComboBox.itemData(
+                    self.docTypeComboBox.currentIndex()),
+                "MaxCodeComplexity": self.complexitySpinBox.value(),
+                "LineComplexity": self.lineComplexitySpinBox.value(),
+                "LineComplexityScore": self.lineComplexityScoreSpinBox.value(),
+                "ValidEncodings": self.encodingsEdit.text(),
+                "CopyrightMinFileSize": self.copyrightFileSizeSpinBox.value(),
+                "CopyrightAuthor": self.copyrightAuthorEdit.text(),
+                "FutureChecker": self.__getSelectedFutureImports(),
+                "BuiltinsChecker": self.__getBuiltinsIgnoreList(),
+            }
+            if data != self.__data:
+                self.__data = data
+                self.__project.setData("CHECKERSPARMS", "Pep8Checker",
+                                       self.__data)
+        
+        self.resultList.clear()
+        self.results = CodeStyleCheckerDialog.noResults
+        self.cancelled = False
+        self.start(self.__fileOrFileList)
+    
+    def __selectCodes(self, edit, showFixCodes):
+        """
+        Private method to select message codes via a selection dialog.
+        
+        @param edit reference of the line edit to be populated (QLineEdit)
+        @param showFixCodes flag indicating to show a list of fixable
+            issues (boolean)
+        """
+        from .CodeStyleCodeSelectionDialog import CodeStyleCodeSelectionDialog
+        dlg = CodeStyleCodeSelectionDialog(edit.text(), showFixCodes, self)
+        if dlg.exec_() == QDialog.Accepted:
+            edit.setText(dlg.getSelectedCodes())
+    
+    @pyqtSlot()
+    def on_excludeMessagesSelectButton_clicked(self):
+        """
+        Private slot to select the message codes to be excluded via a
+        selection dialog.
+        """
+        self.__selectCodes(self.excludeMessagesEdit, False)
+    
+    @pyqtSlot()
+    def on_includeMessagesSelectButton_clicked(self):
+        """
+        Private slot to select the message codes to be included via a
+        selection dialog.
+        """
+        self.__selectCodes(self.includeMessagesEdit, False)
+    
+    @pyqtSlot()
+    def on_fixIssuesSelectButton_clicked(self):
+        """
+        Private slot to select the issue codes to be fixed via a
+        selection dialog.
+        """
+        self.__selectCodes(self.fixIssuesEdit, True)
+    
+    @pyqtSlot()
+    def on_noFixIssuesSelectButton_clicked(self):
+        """
+        Private slot to select the issue codes not to be fixed via a
+        selection dialog.
+        """
+        self.__selectCodes(self.noFixIssuesEdit, True)
+    
+    @pyqtSlot(QTreeWidgetItem, int)
+    def on_resultList_itemActivated(self, item, column):
+        """
+        Private slot to handle the activation of an item.
+        
+        @param item reference to the activated item (QTreeWidgetItem)
+        @param column column the item was activated in (integer)
+        """
+        if self.results != CodeStyleCheckerDialog.hasResults:
+            return
+        
+        if item.parent():
+            fn = Utilities.normabspath(item.data(0, self.filenameRole))
+            lineno = item.data(0, self.lineRole)
+            position = item.data(0, self.positionRole)
+            message = item.data(0, self.messageRole)
+            code = item.data(0, self.codeRole)
+            
+            vm = e5App().getObject("ViewManager")
+            vm.openSourceFile(fn, lineno=lineno, pos=position + 1)
+            editor = vm.getOpenEditor(fn)
+            
+            if code in ["E901", "E902"]:
+                editor.toggleSyntaxError(lineno, 0, True, message, True)
+            else:
+                editor.toggleWarning(
+                    lineno, 0, True, message, warningType=editor.WarningStyle)
+            
+            editor.updateVerticalScrollBar()
+    
+    @pyqtSlot()
+    def on_resultList_itemSelectionChanged(self):
+        """
+        Private slot to change the dialog state depending on the selection.
+        """
+        self.fixButton.setEnabled(len(self.__getSelectedFixableItems()) > 0)
+    
+    @pyqtSlot()
+    def on_showButton_clicked(self):
+        """
+        Private slot to handle the "Show" button press.
+        """
+        vm = e5App().getObject("ViewManager")
+        
+        selectedIndexes = []
+        for index in range(self.resultList.topLevelItemCount()):
+            if self.resultList.topLevelItem(index).isSelected():
+                selectedIndexes.append(index)
+        if len(selectedIndexes) == 0:
+            selectedIndexes = list(range(self.resultList.topLevelItemCount()))
+        for index in selectedIndexes:
+            itm = self.resultList.topLevelItem(index)
+            fn = Utilities.normabspath(itm.data(0, self.filenameRole))
+            vm.openSourceFile(fn, 1)
+            editor = vm.getOpenEditor(fn)
+            editor.clearStyleWarnings()
+            for cindex in range(itm.childCount()):
+                citm = itm.child(cindex)
+                lineno = citm.data(0, self.lineRole)
+                message = citm.data(0, self.messageRole)
+                editor.toggleWarning(
+                    lineno, 0, True, message, warningType=editor.WarningStyle)
+        
+        # go through the list again to clear warning markers for files,
+        # that are ok
+        openFiles = vm.getOpenFilenames()
+        errorFiles = []
+        for index in range(self.resultList.topLevelItemCount()):
+            itm = self.resultList.topLevelItem(index)
+            errorFiles.append(
+                Utilities.normabspath(itm.data(0, self.filenameRole)))
+        for file in openFiles:
+            if file not in errorFiles:
+                editor = vm.getOpenEditor(file)
+                editor.clearStyleWarnings()
+        
+        editor = vm.activeWindow()
+        editor.updateVerticalScrollBar()
+    
+    @pyqtSlot()
+    def on_statisticsButton_clicked(self):
+        """
+        Private slot to show the statistics dialog.
+        """
+        from .CodeStyleStatisticsDialog import CodeStyleStatisticsDialog
+        dlg = CodeStyleStatisticsDialog(self.__statistics, self)
+        dlg.exec_()
+    
+    @pyqtSlot()
+    def on_loadDefaultButton_clicked(self):
+        """
+        Private slot to load the default configuration values.
+        """
+        self.excludeFilesEdit.setText(Preferences.Prefs.settings.value(
+            "PEP8/ExcludeFilePatterns", ""))
+        self.excludeMessagesEdit.setText(Preferences.Prefs.settings.value(
+            "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE))
+        self.includeMessagesEdit.setText(Preferences.Prefs.settings.value(
+            "PEP8/IncludeMessages", ""))
+        self.repeatCheckBox.setChecked(Preferences.toBool(
+            Preferences.Prefs.settings.value("PEP8/RepeatMessages", False)))
+        self.fixIssuesEdit.setText(Preferences.Prefs.settings.value(
+            "PEP8/FixCodes", ""))
+        self.noFixIssuesEdit.setText(Preferences.Prefs.settings.value(
+            "PEP8/NoFixCodes", "E501"))
+        self.fixIssuesCheckBox.setChecked(Preferences.toBool(
+            Preferences.Prefs.settings.value("PEP8/FixIssues", False)))
+        self.ignoredCheckBox.setChecked(Preferences.toBool(
+            Preferences.Prefs.settings.value("PEP8/ShowIgnored", False)))
+        self.lineLengthSpinBox.setValue(int(Preferences.Prefs.settings.value(
+            "PEP8/MaxLineLength", pycodestyle.MAX_LINE_LENGTH)))
+        # Use MAX_LINE_LENGTH to avoid messages on existing code
+        self.docLineLengthSpinBox.setValue(int(
+            Preferences.Prefs.settings.value(
+                "PEP8/MaxDocLineLength", pycodestyle.MAX_LINE_LENGTH)))
+        self.blankBeforeTopLevelSpinBox.setValue(
+            int(Preferences.Prefs.settings.value(
+                "PEP8/BlankLinesBeforeTopLevel", 2)))
+        self.blankBeforeMethodSpinBox.setValue(
+            int(Preferences.Prefs.settings.value(
+                "PEP8/BlankLinesBeforeMethod", 1)))
+        self.hangClosingCheckBox.setChecked(Preferences.toBool(
+            Preferences.Prefs.settings.value("PEP8/HangClosing", False)))
+        self.docTypeComboBox.setCurrentIndex(self.docTypeComboBox.findData(
+            Preferences.Prefs.settings.value("PEP8/DocstringType", "pep257")))
+        self.complexitySpinBox.setValue(int(Preferences.Prefs.settings.value(
+            "PEP8/MaxCodeComplexity", 10)))
+        self.lineComplexitySpinBox.setValue(
+            int(Preferences.Prefs.settings.value(
+                "PEP8/LineComplexity", 15)))
+        self.lineComplexityScoreSpinBox.setValue(
+            int(Preferences.Prefs.settings.value(
+                "PEP8/LineComplexityScore", 10)))
+        self.encodingsEdit.setText(Preferences.Prefs.settings.value(
+            "PEP8/ValidEncodings", "latin-1, utf-8"))
+        self.copyrightFileSizeSpinBox.setValue(int(
+            Preferences.Prefs.settings.value("PEP8/CopyrightMinFileSize", 0)))
+        self.copyrightAuthorEdit.setText(
+            Preferences.Prefs.settings.value("PEP8/CopyrightAuthor", ""))
+        self.__initFuturesList(
+            Preferences.Prefs.settings.value("PEP8/FutureChecker", ""))
+        self.__initBuiltinsIgnoreList(Preferences.toDict(
+            Preferences.Prefs.settings.value("PEP8/BuiltinsChecker", {
+                "str": ["unicode", ],
+                "chr": ["unichr", ],
+            })))
+    
+    @pyqtSlot()
+    def on_storeDefaultButton_clicked(self):
+        """
+        Private slot to store the current configuration values as
+        default values.
+        """
+        Preferences.Prefs.settings.setValue(
+            "PEP8/ExcludeFilePatterns", self.excludeFilesEdit.text())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/ExcludeMessages", self.excludeMessagesEdit.text())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/IncludeMessages", self.includeMessagesEdit.text())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/RepeatMessages", self.repeatCheckBox.isChecked())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/FixCodes", self.fixIssuesEdit.text())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/NoFixCodes", self.noFixIssuesEdit.text())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/FixIssues", self.fixIssuesCheckBox.isChecked())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/ShowIgnored", self.ignoredCheckBox.isChecked())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/MaxLineLength", self.lineLengthSpinBox.value())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/MaxDocLineLength", self.docLineLengthSpinBox.value())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/BlankLinesBeforeTopLevel",
+            self.blankBeforeTopLevelSpinBox.value())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/BlankLinesBeforeMethod",
+            self.blankBeforeMethodSpinBox.value())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/HangClosing", self.hangClosingCheckBox.isChecked())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/DocstringType", self.docTypeComboBox.itemData(
+                self.docTypeComboBox.currentIndex()))
+        Preferences.Prefs.settings.setValue(
+            "PEP8/MaxCodeComplexity", self.complexitySpinBox.value())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/LineComplexity", self.lineComplexitySpinBox.value())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/LineComplexityScore",
+            self.lineComplexityScoreSpinBox.value())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/ValidEncodings", self.encodingsEdit.text())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/CopyrightMinFileSize", self.copyrightFileSizeSpinBox.value())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/CopyrightAuthor", self.copyrightAuthorEdit.text())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/FutureChecker", self.__getSelectedFutureImports())
+        Preferences.Prefs.settings.setValue(
+            "PEP8/BuiltinsChecker", self.__getBuiltinsIgnoreList())
+    
+    @pyqtSlot()
+    def on_resetDefaultButton_clicked(self):
+        """
+        Private slot to reset the configuration values to their default values.
+        """
+        Preferences.Prefs.settings.setValue("PEP8/ExcludeFilePatterns", "")
+        Preferences.Prefs.settings.setValue(
+            "PEP8/ExcludeMessages", pycodestyle.DEFAULT_IGNORE)
+        Preferences.Prefs.settings.setValue("PEP8/IncludeMessages", "")
+        Preferences.Prefs.settings.setValue("PEP8/RepeatMessages", False)
+        Preferences.Prefs.settings.setValue("PEP8/FixCodes", "")
+        Preferences.Prefs.settings.setValue("PEP8/NoFixCodes", "E501")
+        Preferences.Prefs.settings.setValue("PEP8/FixIssues", False)
+        Preferences.Prefs.settings.setValue("PEP8/ShowIgnored", False)
+        Preferences.Prefs.settings.setValue(
+            "PEP8/MaxLineLength", pycodestyle.MAX_LINE_LENGTH)
+        # Hard reset to pycodestyle preferences
+        Preferences.Prefs.settings.setValue(
+            "PEP8/MaxDocLineLength", pycodestyle.MAX_DOC_LENGTH)
+        Preferences.Prefs.settings.setValue(
+            "PEP8/BlankLinesBeforeTopLevel", 2)
+        Preferences.Prefs.settings.setValue(
+            "PEP8/BlankLinesBeforeMethod", 1)
+        Preferences.Prefs.settings.setValue("PEP8/HangClosing", False)
+        Preferences.Prefs.settings.setValue("PEP8/DocstringType", "pep257")
+        Preferences.Prefs.settings.setValue("PEP8/MaxCodeComplexity", 10)
+        Preferences.Prefs.settings.setValue("PEP8/LineComplexity", 15)
+        Preferences.Prefs.settings.setValue("PEP8/LineComplexityScore", 10)
+        Preferences.Prefs.settings.setValue(
+            "PEP8/ValidEncodings", "latin-1, utf-8")
+        Preferences.Prefs.settings.setValue("PEP8/CopyrightMinFileSize", 0)
+        Preferences.Prefs.settings.setValue("PEP8/CopyrightAuthor", "")
+        Preferences.Prefs.settings.setValue("PEP8/FutureChecker", "")
+        Preferences.Prefs.settings.setValue("PEP8/BuiltinsChecker", {
+            "str": ["unicode", ],
+            "chr": ["unichr", ],
+        })
+        # Update UI with default values
+        self.on_loadDefaultButton_clicked()
+    
+    @pyqtSlot(QAbstractButton)
+    def on_buttonBox_clicked(self, button):
+        """
+        Private slot called by a button of the button box clicked.
+        
+        @param button button that was clicked (QAbstractButton)
+        """
+        if button == self.buttonBox.button(QDialogButtonBox.Close):
+            self.close()
+        elif button == self.buttonBox.button(QDialogButtonBox.Cancel):
+            if self.__batch:
+                self.styleCheckService.cancelStyleBatchCheck()
+                QTimer.singleShot(1000, self.__finish)
+            else:
+                self.__finish()
+        elif button == self.showButton:
+            self.on_showButton_clicked()
+        elif button == self.statisticsButton:
+            self.on_statisticsButton_clicked()
+    
+    def __clearErrors(self, files):
+        """
+        Private method to clear all warning markers of open editors to be
+        checked.
+        
+        @param files list of files to be checked (list of string)
+        """
+        vm = e5App().getObject("ViewManager")
+        openFiles = vm.getOpenFilenames()
+        for file in [f for f in openFiles if f in files]:
+            editor = vm.getOpenEditor(file)
+            editor.clearStyleWarnings()
+    
+    @pyqtSlot()
+    def on_fixButton_clicked(self):
+        """
+        Private slot to fix selected issues.
+        
+        Build a dictionary of issues to fix. Update the initialized __options.
+            Then call check with the dict as keyparam to fix selected issues.
+        """
+        fixableItems = self.__getSelectedFixableItems()
+        # dictionary of lists of tuples containing the issue and the item
+        fixesDict = {}
+        for itm in fixableItems:
+            filename = itm.data(0, self.filenameRole)
+            if filename not in fixesDict:
+                fixesDict[filename] = []
+            fixesDict[filename].append((
+                (filename, itm.data(0, self.lineRole),
+                 itm.data(0, self.positionRole),
+                 "{0} {1}".format(itm.data(0, self.codeRole),
+                                  itm.data(0, self.messageRole))),
+                itm
+            ))
+    
+        # update the configuration values (3: fixCodes, 4: noFixCodes,
+        # 5: fixIssues, 6: maxLineLength)
+        self.__options[3] = self.fixIssuesEdit.text()
+        self.__options[4] = self.noFixIssuesEdit.text()
+        self.__options[5] = True
+        self.__options[6] = self.lineLengthSpinBox.value()
+        
+        self.files = list(fixesDict.keys())
+        # now go through all the files
+        self.progress = 0
+        self.files.sort()
+        self.cancelled = False
+        self.__onlyFixes = fixesDict
+        self.check()
+    
+    def __getSelectedFixableItems(self):
+        """
+        Private method to extract all selected items for fixable issues.
+        
+        @return selected items for fixable issues (list of QTreeWidgetItem)
+        """
+        fixableItems = []
+        for itm in self.resultList.selectedItems():
+            if itm.childCount() > 0:
+                for index in range(itm.childCount()):
+                    citm = itm.child(index)
+                    if self.__itemFixable(citm) and citm not in fixableItems:
+                        fixableItems.append(citm)
+            elif self.__itemFixable(itm) and itm not in fixableItems:
+                fixableItems.append(itm)
+        
+        return fixableItems
+    
+    def __itemFixable(self, itm):
+        """
+        Private method to check, if an item has a fixable issue.
+        
+        @param itm item to be checked (QTreeWidgetItem)
+        @return flag indicating a fixable issue (boolean)
+        """
+        return (itm.data(0, self.fixableRole) and
+                not itm.data(0, self.ignoredRole))
+    
+    def __initFuturesList(self, selectedFutures):
+        """
+        Private method to set the selected status of the future imports.
+        
+        @param selectedFutures comma separated list of expected future imports
+        @type str
+        """
+        if selectedFutures:
+            expectedImports = [
+                i.strip() for i in selectedFutures.split(",")
+                if bool(i.strip())]
+        else:
+            expectedImports = []
+        for row in range(self.futuresList.count()):
+            itm = self.futuresList.item(row)
+            if itm.text() in expectedImports:
+                itm.setCheckState(Qt.Checked)
+            else:
+                itm.setCheckState(Qt.Unchecked)
+    
+    def __getSelectedFutureImports(self):
+        """
+        Private method to get the expected future imports.
+        
+        @return expected future imports as a comma separated string
+        @rtype str
+        """
+        selectedFutures = []
+        for row in range(self.futuresList.count()):
+            itm = self.futuresList.item(row)
+            if itm.checkState() == Qt.Checked:
+                selectedFutures.append(itm.text())
+        return ", ".join(selectedFutures)
+    
+    def __initBuiltinsIgnoreList(self, builtinsIgnoreDict):
+        """
+        Private method to populate the list of shadowed builtins to be ignored.
+        
+        @param builtinsIgnoreDict dictionary containing the builtins
+            assignments to be ignored
+        @type dict of list of str
+        """
+        self.builtinsAssignmentList.clear()
+        for left, rightList in builtinsIgnoreDict.items():
+            for right in rightList:
+                QTreeWidgetItem(self.builtinsAssignmentList, [left, right])
+        
+        self.on_builtinsAssignmentList_itemSelectionChanged()
+    
+    def __getBuiltinsIgnoreList(self):
+        """
+        Private method to get a dictionary containing the builtins assignments
+        to be ignored.
+        
+        @return dictionary containing the builtins assignments to be ignored
+        @rtype dict of list of str
+        """
+        builtinsIgnoreDict = {}
+        for row in range(self.builtinsAssignmentList.topLevelItemCount()):
+            itm = self.builtinsAssignmentList.topLevelItem(row)
+            left, right = itm.text(0), itm.text(1)
+            if left not in builtinsIgnoreDict:
+                builtinsIgnoreDict[left] = []
+            builtinsIgnoreDict[left].append(right)
+        
+        return builtinsIgnoreDict
+    
+    @pyqtSlot()
+    def on_builtinsAssignmentList_itemSelectionChanged(self):
+        """
+        Private slot to react upon changes of the selected builtin assignments.
+        """
+        self.deleteBuiltinButton.setEnabled(
+            len(self.builtinsAssignmentList.selectedItems()) > 0)
+    
+    @pyqtSlot()
+    def on_addBuiltinButton_clicked(self):
+        """
+        Private slot to add a built-in assignment to be ignored.
+        """
+        from .CodeStyleAddBuiltinIgnoreDialog import \
+            CodeStyleAddBuiltinIgnoreDialog
+        dlg = CodeStyleAddBuiltinIgnoreDialog(self)
+        if dlg.exec_() == QDialog.Accepted:
+            left, right = dlg.getData()
+            QTreeWidgetItem(self.builtinsAssignmentList, [left, right])
+    
+    @pyqtSlot()
+    def on_deleteBuiltinButton_clicked(self):
+        """
+        Private slot to delete the selected items from the list.
+        """
+        for itm in self.builtinsAssignmentList.selectedItems():
+            index = self.builtinsAssignmentList.indexOfTopLevelItem(itm)
+            self.builtinsAssignmentList.takeTopLevelItem(index)
+            del itm

eric ide

mercurial