PluginRefactoringRope.py

Sun, 04 Nov 2018 18:41:51 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 04 Nov 2018 18:41:51 +0100
changeset 287
09afe26b734c
parent 285
247d62c682dc
child 293
dd1c7ed6d880
permissions
-rw-r--r--

Changes to start the backend clients with a clean PATH setting.

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

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

"""
Module implementing the Rope refactoring plugin.
"""

from __future__ import unicode_literals

import os

from PyQt5.QtCore import Qt, QObject, QTranslator, QCoreApplication

from E5Gui.E5Application import e5App

import Preferences
import Utilities

# Start-Of-Header
name = "Refactoring Rope Plugin"
author = "Detlev Offenbach <detlev@die-offenbachs.de>"
autoactivate = True
deactivateable = True
version = "6.6.1"
className = "RefactoringRopePlugin"
packageName = "RefactoringRope"
internalPackages = "rope"
shortDescription = "Refactoring using the Rope library."
longDescription = """This plug-in implements refactoring functionality""" \
    """ using the Rope refactoring library. Additionally it implements an""" \
    """ alternative auto-completion and call-tips provider. It is a""" \
    """ provider for code documentation as well."""
pyqtApi = 2
doNotCompile = True
python2Compatible = True
# End-Of-Header

error = ""

refactoringRopePluginObject = None


def createAutoCompletionPage(configDlg):
    """
    Module function to create the autocompletion configuration page.
    
    @param configDlg reference to the configuration dialog
    @return reference to the configuration page
    """
    global refactoringRopePluginObject
    from RefactoringRope.ConfigurationPage.AutoCompletionRopePage \
        import AutoCompletionRopePage
    page = AutoCompletionRopePage(refactoringRopePluginObject)
    return page


def createCallTipsPage(configDlg):
    """
    Module function to create the calltips configuration page.
    
    @param configDlg reference to the configuration dialog
    @return reference to the configuration page
    """
    global refactoringRopePluginObject
    from RefactoringRope.ConfigurationPage.CallTipsRopePage \
        import CallTipsRopePage
    page = CallTipsRopePage(refactoringRopePluginObject)
    return page


def createMouseClickHandlerPage(configDlg):
    """
    Module function to create the mouse click handler configuration page.
    
    @param configDlg reference to the configuration dialog
    @return reference to the configuration page
    """
    global refactoringRopePluginObject
    from RefactoringRope.ConfigurationPage.MouseClickHandlerRopePage \
        import MouseClickHandlerRopePage
    page = MouseClickHandlerRopePage(refactoringRopePluginObject)
    return page


def getConfigData():
    """
    Module function returning data as required by the configuration dialog.
    
    @return dictionary containing the relevant data
    @rtype dict
    """
    data = {
        "ropeAutoCompletionPage": [
            QCoreApplication.translate("RefactoringRopePlugin", "Rope"),
            os.path.join("RefactoringRope", "ConfigurationPage",
                         "preferences-refactoring.png"),
            createAutoCompletionPage, "editorAutocompletionPage", None],
        "ropeCallTipsPage": [
            QCoreApplication.translate("RefactoringRopePlugin", "Rope"),
            os.path.join("RefactoringRope", "ConfigurationPage",
                         "preferences-refactoring.png"),
            createCallTipsPage, "editorCalltipsPage", None],
        "ropeMouseClickHandlerPage": [
            QCoreApplication.translate("RefactoringRopePlugin", "Rope"),
            os.path.join("RefactoringRope", "ConfigurationPage",
                         "preferences-refactoring.png"),
            createMouseClickHandlerPage, "1editorMouseClickHandlers", None],
    }
    
    return data


def prepareUninstall():
    """
    Module function to prepare for an uninstallation.
    """
    Preferences.Prefs.settings.remove(RefactoringRopePlugin.PreferencesKey)


class RefactoringRopePlugin(QObject):
    """
    Class implementing the Rope refactoring plugin.
    """
    PreferencesKey = "RefactoringRope"
    
    def __init__(self, ui):
        """
        Constructor
        
        @param ui reference to the user interface object
        @type UI.UserInterface
        """
        QObject.__init__(self, ui)
        self.__ui = ui
        self.__initialize()
        
        self.__defaults = {
            "CodeAssistEnabled": False,
            "MaxFixes": 10,
            
            "CodeAssistCalltipsEnabled": False,
            "CalltipsMaxFixes": 10,
            
            "MouseClickEnabled": True,
            "MouseClickGotoModifiers": int(Qt.ControlModifier),
            "MouseClickGotoButton": int(Qt.LeftButton),
        }
        
        self.__translator = None
        self.__loadTranslator()
    
    def __initialize(self):
        """
        Private slot to (re)initialize the plugin.
        """
        self.__refactoringServer = None
        self.__codeAssistServer = None
        
        self.__editors = []
        
        self.__currentEditor = None
        self.__savedEditorName = None
        self.__oldEditorText = ""
    
    def activate(self):
        """
        Public method to activate this plugin.
        
        @return tuple of None and activation status
        @rtype tuple of (None, bool)
        """
        global refactoringRopePluginObject
        refactoringRopePluginObject = self
        
        e5App().getObject("PluginManager").shutdown.connect(
            self.__shutdown)
        
        from RefactoringRope.CodeAssistServer import CodeAssistServer
        self.__codeAssistServer = CodeAssistServer(self, self.__ui)
        self.__codeAssistServer.activate()
        
        from RefactoringRope.RefactoringServer import RefactoringServer
        self.__refactoringServer = RefactoringServer(self, self.__ui)
        self.__refactoringServer.activate()
        
        e5App().getObject("PluginManager").shutdown.connect(
            self.__shutdown)
        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 plugin.
        """
        if self.__refactoringServer:
            self.__refactoringServer.deactivate()
        
        if self.__codeAssistServer:
            self.__codeAssistServer.deactivate()
        
        e5App().getObject("PluginManager").shutdown.disconnect(
            self.__shutdown)
        e5App().getObject("ViewManager").editorOpenedEd.disconnect(
            self.__editorOpened)
        e5App().getObject("ViewManager").editorClosedEd.disconnect(
            self.__editorClosed)
        
        for editor in self.__editors[:]:
            self.__editorClosed(editor)
        
        self.__initialize()
    
    def __shutdown(self):
        """
        Private slot handling the shutdown signal of the plug-in manager.
        """
        if self.__codeAssistServer:
            self.__codeAssistServer.deactivate()
    
    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__),
                                 "RefactoringRope", "i18n")
                translation = "rope_{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 getPreferences(self, key):
        """
        Public method to retrieve the various refactoring settings.
        
        @param key the key of the value to get
        @type str
        @return the requested refactoring setting
        """
        if key in ["CodeAssistEnabled", "CodeAssistCalltipsEnabled",
                   "MouseClickEnabled"]:
            return Preferences.toBool(Preferences.Prefs.settings.value(
                self.PreferencesKey + "/" + key, self.__defaults[key]))
        else:
            return int(Preferences.Prefs.settings.value(
                self.PreferencesKey + "/" + key, self.__defaults[key]))
    
    def setPreferences(self, key, value):
        """
        Public method to store the various refactoring settings.
        
        @param key the key of the setting to be set
        @type str
        @param value the value to be set
        """
        Preferences.Prefs.settings.setValue(
            self.PreferencesKey + "/" + key, value)
        
        if key in ["CodeAssistEnabled", "CodeAssistCalltipsEnabled",
                   "MouseClickEnabled"]:
            if value:
                if e5App().getObject("Project").isOpen():
                    for editor in e5App().getObject("ViewManager")\
                            .getOpenEditors():
                        if editor not in self.__editors:
                            self.__editorOpened(editor)
            else:
                for editor in self.__editors[:]:
                    self.__editorClosed(editor)
        elif key in ["MouseClickGotoModifiers", "MouseClickGotoButton"]:
            for editor in self.__editors:
                self.__refactoringServer.disconnectEditor(editor)
                self.__refactoringServer.connectEditor(editor)
    
    def __editorOpened(self, editor):
        """
        Private slot called, when a new editor was opened.
        
        @param editor reference to the new editor
        @type QScintilla.Editor.Editor
        """
        self.__connectEditor(editor)
        
        editor.languageChanged.connect(self.__editorLanguageChanged)
        self.__editors.append(editor)
    
    def __editorClosed(self, editor):
        """
        Private slot called, when an editor was closed.
        
        @param editor reference to the editor
        @type QScintilla.Editor.Editor
        """
        if editor in self.__editors:
            editor.languageChanged.disconnect(self.__editorLanguageChanged)
            self.__disconnectEditor(editor)
            self.__editors.remove(editor)
    
    def __editorLanguageChanged(self, language):
        """
        Private slot to handle the language change of an editor.
        
        @param language programming language of the editor
        @type str
        """
        editor = self.sender()
        
        self.__disconnectEditor(editor)
        self.__connectEditor(editor)
    
    def __connectEditor(self, editor):
        """
        Private method to connect an editor.
        
        @param editor reference to the editor
        @type QScintilla.Editor.Editor
        """
        editor.editorAboutToBeSaved.connect(self.__editorAboutToBeSaved)
        editor.editorSaved.connect(self.__editorSaved)
        
        self.__codeAssistServer.connectEditor(editor)
        self.__refactoringServer.connectEditor(editor)
    
    def __disconnectEditor(self, editor):
        """
        Private method to disconnect an editor.
        
        @param editor reference to the editor
        @type QScintilla.Editor.Editor
        """
        try:
            editor.editorAboutToBeSaved.disconnect(self.__editorAboutToBeSaved)
            editor.editorSaved.disconnect(self.__editorSaved)
        except TypeError:
            # just ignore it
            pass
        
        self.__codeAssistServer.disconnectEditor(editor)
        self.__refactoringServer.disconnectEditor(editor)
    
    def __editorAboutToBeSaved(self, filename):
        """
        Private slot to get the old contents of the named file.
        
        @param filename name of the file about to be saved
        @type str
        """
        if filename and os.path.exists(filename):
            try:
                self.__oldEditorText = Utilities.readEncodedFile(filename)[0]
            except IOError:
                self.__oldEditorText = ""
            self.__savedEditorName = filename
        else:
            self.__savedEditorName = ""
            self.__oldEditorText = ""
    
    def __editorSaved(self, filename):
        """
        Private slot to activate SOA.
        
        @param filename name of the file that was saved
        @type str
        """
        if filename == self.__savedEditorName and self.__oldEditorText:
            self.__refactoringServer.reportChanged(self.__savedEditorName,
                                                   self.__oldEditorText)
            self.__codeAssistServer.reportChanged(self.__savedEditorName,
                                                  self.__oldEditorText)
        else:
            self.__refactoringServer.reportChanged(filename, "")
            self.__codeAssistServer.reportChanged(filename, "")
    
    def getCodeAssistServer(self):
        """
        Public method to get a reference to the code assist server.
        
        @return reference to the code assist server
        @rtype CodeAssistServer
        """
        return self.__codeAssistServer

#
# eflag: noqa = M801

eric ide

mercurial