RefactoringRope/Refactoring.py

changeset 2
fc72a5b922a6
parent 1
9f687137a929
child 3
3be1b4662b48
--- a/RefactoringRope/Refactoring.py	Sun Jan 23 19:55:56 2011 +0100
+++ b/RefactoringRope/Refactoring.py	Sat Jan 29 13:38:30 2011 +0100
@@ -16,8 +16,10 @@
 import rope.base.project
 import rope.base.exceptions
 
+import rope.contrib.findit
+
 from PyQt4.QtCore import QObject, SIGNAL
-from PyQt4.QtGui import QMenu
+from PyQt4.QtGui import QMenu, QApplication, QMessageBox
 
 from E5Gui.E5Application import e5App
 
@@ -28,13 +30,17 @@
 
 from FileSystemCommands import e5FileSystemCommands
 from HelpDialog import HelpDialog
+from ProgressHandle import ProgressHandle
+from MatchesDialog import MatchesDialog
+
+import Utilities
 
 
 class Refactoring(QObject):
     """
     Class implementing the refactoring interface to rope.
     """
-    def __init__(self, plugin, newStyle, parent = None):
+    def __init__(self, plugin, newStyle, parent=None):
         """
         Constructor
         
@@ -65,6 +71,66 @@
         """
         self.actions = []
         
+        #####################################################
+        ## Query actions
+        #####################################################
+        
+        self.queryReferencesAct = E5Action(self.trUtf8('Find occurrences'),
+                self.trUtf8('Find &Occurrences'),
+                0, 0,
+                self,'refactoring_find_occurrences')
+        self.queryReferencesAct.setStatusTip(self.trUtf8(
+            'Find occurrences of the highlighted object'))
+        self.queryReferencesAct.setWhatsThis(self.trUtf8(
+            """<b>Find occurrences</b>"""
+            """<p>Find occurrences of the highlighted class, method,"""
+            """ function or variable.</p>"""
+        ))
+        if self.__newStyle:
+            self.queryReferencesAct.triggered[()].connect(
+                self.__queryReferences)
+        else:
+            self.connect(self.queryReferencesAct, SIGNAL('triggered()'), 
+                self.__queryReferences)
+        self.actions.append(self.queryReferencesAct)
+        
+        self.queryDefinitionAct = E5Action(self.trUtf8('Find definition'),
+                self.trUtf8('Find &Definition'),
+                0, 0,
+                self,'refactoring_find_definition')
+        self.queryDefinitionAct.setStatusTip(self.trUtf8(
+            'Find definition of the highlighted item'))
+        self.queryDefinitionAct.setWhatsThis(self.trUtf8(
+            """<b>Find definition</b>"""
+            """<p>Find the definition of the highlighted class, method,"""
+            """ function or variable.</p>"""
+        ))
+        if self.__newStyle:
+            self.queryDefinitionAct.triggered[()].connect(
+                self.__queryDefinition)
+        else:
+            self.connect(self.queryDefinitionAct, SIGNAL('triggered()'), 
+                self.__queryDefinition)
+        self.actions.append(self.queryDefinitionAct)
+        
+        self.queryImplementationsAct = E5Action(
+                self.trUtf8('Find implementations'),
+                self.trUtf8('Find &Implementations'),
+                0, 0,
+                self,'refactoring_find_implementations')
+        self.queryImplementationsAct.setStatusTip(self.trUtf8(
+            'Find places where the selected method is overridden'))
+        self.queryImplementationsAct.setWhatsThis(self.trUtf8(
+            """<b>Find implementations</b>"""
+            """<p>Find places where the selected method is overridden.</p>"""
+        ))
+        if self.__newStyle:
+            self.queryImplementationsAct.triggered[()].connect(
+                self.__queryImplementations)
+        else:
+            self.connect(self.queryImplementationsAct, SIGNAL('triggered()'), 
+                self.__queryImplementations)
+        self.actions.append(self.queryImplementationsAct)
         
         #####################################################
         ## Various actions
@@ -124,6 +190,11 @@
         act.setFont(font)
         menu.addSeparator()
         
+        smenu = menu.addMenu(self.trUtf8("&Query"))
+        smenu.addAction(self.queryReferencesAct)
+        smenu.addAction(self.queryDefinitionAct)
+        smenu.addAction(self.queryImplementationsAct)
+        
         menu.addSeparator()
         menu.addAction(self.refactoringEditConfigAct)
         menu.addAction(self.refactoringHelpAct)
@@ -144,6 +215,171 @@
             self.trUtf8("{0}\nVersion {1}\n\n{2}".format(
                 rope.INFO, rope.VERSION, rope.COPYRIGHT)))
     
+    def handleRopeError(self, err, title, handle=None):
+        """
+        Public slot to handle a rope error.
+        
+        @param err rope exception object (Exception)
+        @param title title to be displayed (string)
+        @param handle reference to a taskhandle (ProgressHandle)
+        """
+        if handle is not None:
+            handle.reset()
+        if str(type(err)).split()[-1][1:-2].split('.')[-1] == \
+                                                    'ModuleSyntaxError':
+            res = E5MessageBox.warning(self.__ui, title,
+                self.trUtf8("Rope error: {0}").format(str(err)), 
+                QMessageBox.Ok | QMessageBox.Open)
+            if res == QMessageBox.Open:
+                e5App().getObject("ViewManager").openSourceFile(
+                    os.path.join(self.__e4project.getProjectPath(), 
+                                 err.filename), 
+                    err.lineno)
+        else:
+            E5MessageBox.warning(self.__ui, title,
+                self.trUtf8("Rope error: {0}").format(str(err)))
+
+    #####################################################
+    ## Find actions
+    #####################################################
+    
+    def __queryReferences(self):
+        """
+        Private slot to handle the Find References action.
+        """
+        aw = e5App().getObject("ViewManager").activeWindow()
+        
+        if aw is None:
+            return
+        
+        title = self.trUtf8("Find Occurrences")
+        if not aw.hasSelectedText():
+            # no selection available
+            E5MessageBox.warning(self.__ui, title,
+                self.trUtf8("Highlight the class, method, function or variable"
+                    " to search for and try again."))
+            return 
+        
+        if not self.confirmAllBuffersSaved():
+            return
+        
+        filename = aw.getFileName()
+        line, index, line1, index1 = aw.getSelection()
+        offset = aw.positionFromLineIndex(line, index)
+        
+        resource = rope.base.libutils.path_to_resource(
+            self.__project, filename)
+        handle = ProgressHandle(title, True, self.__ui)
+        handle.show()
+        QApplication.processEvents()
+        try:
+            occurrences = rope.contrib.findit.find_occurrences(
+                self.__project, resource, offset,
+                unsure = True, in_hierarchy = True, task_handle = handle)
+        except Exception as err:
+            self.handleRopeError(err, title, handle)
+            return
+        handle.reset()
+        
+        if occurrences:
+            self.dlg = MatchesDialog(self.__ui, True)
+            self.dlg.show()
+            for occurrence in occurrences:
+                self.dlg.addEntry(occurrence.resource, 
+                    occurrence.lineno, occurrence.unsure)
+        else:
+            E5MessageBox.warning(self.__ui, title,
+                self.trUtf8("No occurrences found."))
+    
+    def __queryDefinition(self):
+        """
+        Private slot to handle the Find Definition action
+        """
+        aw = e5App().getObject("ViewManager").activeWindow()
+        
+        if aw is None:
+            return
+        
+        title = self.trUtf8("Find &Definition")
+        if not aw.hasSelectedText():
+            # no selection available
+            E5MessageBox.warning(self.__ui, title,
+                self.trUtf8("Highlight the class, method, function or"
+                    " variable reference to search definition for and"
+                    " try again."))
+            return 
+        
+        if not self.confirmAllBuffersSaved():
+            return
+        
+        filename = aw.getFileName()
+        line, index, line1, index1 = aw.getSelection()
+        offset = aw.positionFromLineIndex(line, index)
+        
+        resource = rope.base.libutils.path_to_resource(
+            self.__project, filename)
+        try:
+            location = rope.contrib.findit.find_definition(
+                self.__project, aw.text(), offset, resource)
+        except Exception as err:
+            self.handleRopeError(err, title)
+            return
+        
+        if location is not None:
+            self.dlg = MatchesDialog(self.__ui, False)
+            self.dlg.show()
+            self.dlg.addEntry(location.resource, location.lineno)
+        else:
+            E5MessageBox.warning(self.__ui, title,
+                self.trUtf8("No matching definition found."))
+    
+    def __queryImplementations(self):
+        """
+        Private slot to handle the Find Implementations action.
+        """
+        aw = e5App().getObject("ViewManager").activeWindow()
+        
+        if aw is None:
+            return
+        
+        title = self.trUtf8("Find Implementations")
+        if not aw.hasSelectedText():
+            # no selection available
+            E5MessageBox.warning(self.__ui, title,
+                self.trUtf8("Highlight the method to search for"
+                            " and try again."))
+            return 
+        
+        if not self.confirmAllBuffersSaved():
+            return
+        
+        filename = aw.getFileName()
+        line, index, line1, index1 = aw.getSelection()
+        offset = aw.positionFromLineIndex(line, index)
+        
+        resource = rope.base.libutils.path_to_resource(self.__project, 
+            filename)
+        handle = ProgressHandle(title, True, self.__ui)
+        handle.show()
+        QApplication.processEvents()
+        try:
+            occurrences = rope.contrib.findit.find_implementations(
+                self.__project, resource, offset, task_handle = handle)
+        except Exception as err:
+            self.handleRopeError(err, title, handle)
+            return
+        handle.reset()
+        
+        if occurrences:
+            self.dlg = MatchesDialog(self.__ui, True)
+            self.dlg.show()
+            for occurrence in occurrences:
+                self.dlg.addEntry(occurrence.resource, 
+                    occurrence.lineno, occurrence.unsure)
+        else:
+            E5MessageBox.warning(self.__ui, title,
+                self.trUtf8("No occurrences found."))
+    
     #####################################################
     ## Various actions
     #####################################################
@@ -276,48 +512,54 @@
         @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)
+    
+    def confirmBufferIsSaved(self, editor):
+        """
+        Public method to check, if an editor has unsaved changes.
+        
+        @param editor reference to the editor to be checked
+        @return flag indicating, that the editor doesn't contain 
+            unsaved edits (boolean)
+        """
+        res = editor.checkDirty()
+        self.__project.validate(self.__project.root)
+        return res
+    
+    def confirmAllBuffersSaved(self):
+        """
+        Private method to check, if any editor has unsaved changes.
+        
+        @return flag indicating, that no editor contains unsaved edits 
+            (boolean)
+        """
+        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