RefactoringRope/Refactoring.py

Sun, 23 Jan 2011 19:55:56 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 23 Jan 2011 19:55:56 +0100
changeset 1
9f687137a929
child 2
fc72a5b922a6
permissions
-rw-r--r--

Started implementing the basic functions.

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

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

"""
Module implementing the refactoring interface to rope.
"""

import os
import sys

sys.path.insert(0, os.path.dirname(__file__))
import rope
import rope.base.libutils
import rope.base.project
import rope.base.exceptions

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

from E5Gui.E5Application import e5App

from E5Gui import E5MessageBox
from E5Gui.E5Action import E5Action

from QScintilla.MiniEditor import MiniEditor

from FileSystemCommands import e5FileSystemCommands
from HelpDialog import HelpDialog


class Refactoring(QObject):
    """
    Class implementing the refactoring interface to rope.
    """
    def __init__(self, plugin, newStyle, parent = None):
        """
        Constructor
        
        @param plugin reference to the plugin object
        @param newStyle flag indicating usage of new style signals (bool)
        @param parent parent (QObject)
        """
        QObject.__init__(self, parent)
        
        self.__plugin = plugin
        self.__newStyle = newStyle
        self.__ui = parent
        self.__e5project = e5App().getObject("Project")
        self.__projectpath = ''
        self.__projectLanguage = ""
        self.__projectopen = False
        
        self.__mainMenu = None
        self.__helpDialog = None
        
        # Rope objects
        self.__project = None
        self.__fsCommands = e5FileSystemCommands(self.__e5project)
    
    def initActions(self):
        """
        Public method to define the refactoring actions.
        """
        self.actions = []
        
        
        #####################################################
        ## Various actions
        #####################################################
        
        self.refactoringEditConfigAct = E5Action(self.trUtf8('Configure Rope'),
                self.trUtf8('&Configure Rope'),
                0, 0,
                self,'refactoring_edit_config')
        self.refactoringEditConfigAct.setStatusTip(self.trUtf8(
            'Open the rope configuration file'))
        self.refactoringEditConfigAct.setWhatsThis(self.trUtf8(
            """<b>Configure Rope</b>"""
            """<p>Opens the rope configuration file in an editor.</p>"""
        ))
        if self.__newStyle:
            self.refactoringEditConfigAct.triggered[()].connect(
                self.__editConfig)
        else:
            self.connect(self.refactoringEditConfigAct, SIGNAL('triggered()'), 
                self.__editConfig)
        self.actions.append(self.refactoringEditConfigAct)
        
        self.refactoringHelpAct = E5Action(self.trUtf8('Rope help'),
                self.trUtf8('Rope &Help'),
                0, 0,
                self,'refactoring_help')
        self.refactoringHelpAct.setStatusTip(self.trUtf8(
            'Show help about the rope refactorings'))
        self.refactoringHelpAct.setWhatsThis(self.trUtf8(
            """<b>Rope help</b>"""
            """<p>Show some help text about the rope refactorings.</p>"""
        ))
        if self.__newStyle:
            self.refactoringHelpAct.triggered[()].connect(
                self.__showRopeHelp)
        else:
            self.connect(self.refactoringHelpAct, SIGNAL('triggered()'), 
                self.__showRopeHelp)
        self.actions.append(self.refactoringHelpAct)
        
        for act in self.actions:
            act.setEnabled(False)
    
    def initMenu(self):
        """
        Public slot to initialize the refactoring menu.
        
        @return the menu generated (QMenu)
        """
        menu = QMenu(self.trUtf8('&Refactoring'), self.__ui)
        menu.setTearOffEnabled(True)
        
        act = menu.addAction('rope', self.__ropeInfo)
        font = act.font()
        font.setBold(True)
        act.setFont(font)
        menu.addSeparator()
        
        menu.addSeparator()
        menu.addAction(self.refactoringEditConfigAct)
        menu.addAction(self.refactoringHelpAct)
        
        self.__mainMenu = menu
        return menu

    ##################################################################
    ## slots below implement general functionality
    ##################################################################
    
    def __ropeInfo(self):
        """
        Private slot to show some info about rope.
        """
        E5MessageBox.about(self.__ui,
            self.trUtf8("About rope"),
            self.trUtf8("{0}\nVersion {1}\n\n{2}".format(
                rope.INFO, rope.VERSION, rope.COPYRIGHT)))
    
    #####################################################
    ## Various actions
    #####################################################
    
    def __editConfig(self):
        """
        Private slot to open the rope configuration file in an editor.
        """
        ropedir = self.__project.ropefolder
        configfile = ""
        if ropedir is not None:
            configfile = os.path.join(ropedir.real_path, "config.py")
            if os.path.exists(configfile):
                self.__editor = MiniEditor(configfile)
                self.__editor.show()
                if self.__newStyle:
                    self.__editor.editorSaved.connect(self.__configChanged)
                else:
                    self.connect(self.__editor, SIGNAL("editorSaved"), 
                        self.__configChanged)
            else:
                E5MessageBox.critical(self.__ui,
                    self.trUtf8("Configure Rope"),
                    self.trUtf8("""The Rope configuration file '{0}' does"""
                                """ not exist.""").format(configfile))
        else:
            E5MessageBox.critical(self.__ui,
                self.trUtf8("Configure Rope"),
                self.trUtf8("""The Rope admin directory does not exist."""))
    
    def __showRopeHelp(self):
        """
        Private slot to show help about the refactorings offered by Rope.
        """
        if self.__helpDialog is None:
            helpfile = os.path.join(os.path.dirname(__file__), 
                                    "rope", "docs", "overview.txt")
            self.__helpDialog = \
                HelpDialog(self.trUtf8("Help about rope refactorings"), 
                           helpfile)
        self.__helpDialog.show()
    
    ##################################################################
    ## methods below are private utility methods
    ##################################################################
    
    def __ropeConfigFile(self):
        """
        Private method to get the name of the rope configuration file.
       
        @return name of the rope configuration file (string)
        """
        configfile = None
        if self.__project is not None:
            ropedir = self.__project.ropefolder
            if ropedir is not None:
                configfile = os.path.join(ropedir.real_path, "config.py")
                if not os.path.exists(configfile):
                    configfile = None
        return configfile
    
    def __configChanged(self):
        """
        Private slot called, when the rope config file has changed.
        """
        self.__project.close()
        self.__project = rope.base.project.Project(self.__projectpath, 
            fscommands = self.__fsCommands)
    
    def __defaultConfig(self):
        """
        Private slot to return the contents of rope's default configuration.
        
        @return string containing the source of rope's default
            configuration (string)
        """
        if self.__project is not None:
            return self.__project._default_config()
        else:
            return ""
    
    ##################################################################
    ## methods below are public utility methods
    ##################################################################
    
    def getActions(self):
        """
        Public method to get a list of all actions.
        
        @return list of all actions (list of E5Action)
        """
        return self.actions[:]
    
    def projectOpened(self):
        """
        Public slot to handle the projectOpened signal.
        """
        if self.__projectopen:
            self.projectClosed()
        
        self.__projectopen = True
        self.__projectpath = self.__e5project.getProjectPath()
        self.__projectLanguage = self.__e5project.getProjectLanguage()
        
        if self.__projectLanguage in ["Python3"]:
            self.__project = rope.base.project.Project(self.__projectpath, 
                fscommands = self.__fsCommands)
            for act in self.actions:
                act.setEnabled(True)
    
    def projectClosed(self):
        """
        Public slot to handle the projectClosed signal.
        """
        for act in self.actions:
            act.setEnabled(False)
        
        if self.__project is not None:
            self.__project.close()
            self.__project = None
        
        self.__projectopen = False
        self.__projectpath = ''
        self.__projectLanguage = ""
    
    def getProject(self):
        """
        Public method to get a reference to the rope project object.
        
        @return reference to the rope project object (RopeProject)
        """
        return self.__project
##    
##    def confirmBufferIsSaved(self, editor):
##        """
##        Public method to check, if an editor has unsaved changes.
##        
##        @param editor reference to the editor to be checked
##        """
##        res =  editor.checkDirty()
##        self.__project.validate(self.__project.root)
##        return res
##    
##    def confirmAllBuffersSaved(self):
##        """
##        Private method to check, if any editor has unsaved changes.
##        """
##        res = e5App().getObject("ViewManager").checkAllDirty()
##        self.__project.validate(self.__project.root)
##        return res
##    
##    def refreshEditors(self, changes):
##        """
##        Public method to refresh modified editors.
##        
##        @param reference to the Changes object (rope.base.change.ChangeSet)
##        """
##        vm = e5App().getObject("ViewManager")
##        
##        changedFiles = []
##        for resource in changes.get_changed_resources():
##            if not resource.is_folder():
##                changedFiles.append(resource.real_path)
##        
##        openFiles = [Utilities.normcasepath(f) for f in vm.getOpenFilenames()]
##        
##        for file in changedFiles:
##            normfile = Utilities.normcasepath(file)
##            if normfile in openFiles:
##                editor = vm.getEditor(normfile)[1]
##                editor.refresh()
##        
##        aw = vm.activeWindow()
##        if aw is not None:
##            filename = aw.getFileName()
##            if filename is not None:
##                vm.openSourceFile(filename, aw.getCursorPosition()[0] + 1)

eric ide

mercurial