RefactoringRope/Refactoring.py

changeset 4
2e2463ef1aae
parent 3
3be1b4662b48
child 5
49a4abfc1f89
--- a/RefactoringRope/Refactoring.py	Sat Jan 29 15:10:40 2011 +0100
+++ b/RefactoringRope/Refactoring.py	Sat Jan 29 19:16:29 2011 +0100
@@ -49,6 +49,7 @@
 from MatchesDialog import MatchesDialog
 from RenameDialog import RenameDialog
 from ChangeOccurrencesDialog import ChangeOccurrencesDialog
+from HistoryDialog import HistoryDialog
 
 import Utilities
 
@@ -168,6 +169,145 @@
         self.actions.append(self.refactoringChangeOccurrencesAct)
         
         #####################################################
+        ## Undo/Redo actions
+        #####################################################
+        
+        self.refactoringUndoAct = E5Action(self.trUtf8('Undo'),
+                self.trUtf8('&Undo'), 
+                0, 0,
+                self,'refactoring_undo')
+        self.refactoringUndoAct.setStatusTip(self.trUtf8(
+            'Undo the last refactoring'))
+        self.refactoringUndoAct.setWhatsThis(self.trUtf8(
+            """<b>Undo</b>"""
+            """<p>Undo the last refactoring.</p>"""
+        ))
+        if self.__newStyle:
+            self.refactoringUndoAct.triggered[()].connect(
+                self.__undo)
+        else:
+            self.connect(self.refactoringUndoAct, 
+                SIGNAL('triggered()'), self.__undo)
+        self.actions.append(self.refactoringUndoAct)
+        
+        self.refactoringRedoAct = E5Action(self.trUtf8('Redo'),
+                self.trUtf8('Re&do'), 
+                0, 0,
+                self,'refactoring_redo')
+        self.refactoringRedoAct.setStatusTip(self.trUtf8(
+            'Redo the last refactoring'))
+        self.refactoringRedoAct.setWhatsThis(self.trUtf8(
+            """<b>Redo</b>"""
+            """<p>Redo the last refactoring.</p>"""
+        ))
+        if self.__newStyle:
+            self.refactoringRedoAct.triggered[()].connect(
+                self.__redo)
+        else:
+            self.connect(self.refactoringRedoAct, 
+                SIGNAL('triggered()'), self.__redo)
+        self.actions.append(self.refactoringRedoAct)
+        
+        self.refactoringUndoHistoryAct = \
+            E5Action(self.trUtf8('Show Project Undo History'),
+                self.trUtf8('Show Project Undo History'), 
+                0, 0,
+                self,'refactoring_show_project_undo_history')
+        self.refactoringUndoHistoryAct.setStatusTip(self.trUtf8(
+            'Show the undo history of the project'))
+        self.refactoringUndoHistoryAct.setWhatsThis(self.trUtf8(
+            """<b>Show Project Undo History</b>"""
+            """<p>Opens a dialog to show the undo history list of"""
+            """ the project.</p>"""
+        ))
+        if self.__newStyle:
+            self.refactoringUndoHistoryAct.triggered[()].connect(
+                self.__showProjectUndoHistory)
+        else:
+            self.connect(self.refactoringUndoHistoryAct,
+                SIGNAL('triggered()'), self.__showProjectUndoHistory)
+        self.actions.append(self.refactoringUndoHistoryAct)
+        
+        self.refactoringRedoHistoryAct = \
+            E5Action(self.trUtf8('Show Project Redo History'),
+                self.trUtf8('Show Project Redo History'), 
+                0, 0,
+                self,'refactoring_show_project_redo_history')
+        self.refactoringRedoHistoryAct.setStatusTip(self.trUtf8(
+            'Show the redo history of the project'))
+        self.refactoringRedoHistoryAct.setWhatsThis(self.trUtf8(
+            """<b>Show Project Redo History</b>"""
+            """<p>Opens a dialog to show the redo history list of"""
+            """ the project.</p>"""
+        ))
+        if self.__newStyle:
+            self.refactoringRedoHistoryAct.triggered[()].connect(
+                self.__showProjectRedoHistory)
+        else:
+            self.connect(self.refactoringRedoHistoryAct,
+                SIGNAL('triggered()'), self.__showProjectRedoHistory)
+        self.actions.append(self.refactoringRedoHistoryAct)
+        
+        self.refactoringUndoFileHistoryAct = \
+            E5Action(self.trUtf8('Show Current File Undo History'),
+                self.trUtf8('Show Current File Undo History'), 
+                0, 0,
+                self,'refactoring_show_file_undo_history')
+        self.refactoringUndoFileHistoryAct.setStatusTip(self.trUtf8(
+            'Show the undo history of the current file'))
+        self.refactoringUndoFileHistoryAct.setWhatsThis(self.trUtf8(
+            """<b>Show Current File Undo History</b>"""
+            """<p>Opens a dialog to show the undo history list of"""
+            """ the current file.</p>"""
+        ))
+        if self.__newStyle:
+            self.refactoringUndoFileHistoryAct.triggered[()].connect(
+                self.__showFileUndoHistory)
+        else:
+            self.connect(self.refactoringUndoFileHistoryAct,
+                SIGNAL('triggered()'), self.__showFileUndoHistory)
+        self.actions.append(self.refactoringUndoFileHistoryAct)
+        
+        self.refactoringRedoFileHistoryAct = \
+            E5Action(self.trUtf8('Show Current File Redo History'),
+                self.trUtf8('Show Current File Redo History'), 
+                0, 0,
+                self,'refactoring_show_file_redo_history')
+        self.refactoringRedoFileHistoryAct.setStatusTip(self.trUtf8(
+            'Show the redo history of the current file'))
+        self.refactoringRedoFileHistoryAct.setWhatsThis(self.trUtf8(
+            """<b>Show Current File Redo History</b>"""
+            """<p>Opens a dialog to show the redo history list of"""
+            """ the current file.</p>"""
+        ))
+        if self.__newStyle:
+            self.refactoringRedoFileHistoryAct.triggered[()].connect(
+                self.__showFileRedoHistory)
+        else:
+            self.connect(self.refactoringRedoFileHistoryAct,
+                SIGNAL('triggered()'), self.__showFileRedoHistory)
+        self.actions.append(self.refactoringRedoFileHistoryAct)
+        
+        self.refactoringClearHistoryAct = \
+            E5Action(self.trUtf8('Clear History'),
+                self.trUtf8('Clear History'), 
+                0, 0,
+                self,'refactoring_clear_history')
+        self.refactoringClearHistoryAct.setStatusTip(self.trUtf8(
+            'Clear the refactoring history'))
+        self.refactoringClearHistoryAct.setWhatsThis(self.trUtf8(
+            """<b>Clear History</b>"""
+            """<p>Clears the refactoring history.</p>"""
+        ))
+        if self.__newStyle:
+            self.refactoringClearHistoryAct.triggered[()].connect(
+                self.__clearHistory)
+        else:
+            self.connect(self.refactoringClearHistoryAct,
+                SIGNAL('triggered()'), self.__clearHistory)
+        self.actions.append(self.refactoringClearHistoryAct)
+        
+        #####################################################
         ## Query actions
         #####################################################
         
@@ -304,6 +444,22 @@
         smenu.addAction(self.refactoringRenameModuleAct)
         smenu.addSeparator()
         
+        smenu.addSeparator()
+        smenu.addAction(self.refactoringUndoAct)
+        smenu.addAction(self.refactoringRedoAct)
+        smenu.addSeparator()
+        
+        hmenu = smenu.addMenu(self.trUtf8("History"))
+        self.connect(hmenu, SIGNAL("aboutToShow()"), 
+                     self.__showRefactoringHistoryMenu)
+        hmenu.addAction(self.refactoringUndoHistoryAct)
+        hmenu.addAction(self.refactoringUndoFileHistoryAct)
+        hmenu.addSeparator()
+        hmenu.addAction(self.refactoringRedoHistoryAct)
+        hmenu.addAction(self.refactoringRedoFileHistoryAct)
+        hmenu.addSeparator()
+        hmenu.addAction(self.refactoringClearHistoryAct)
+        
         menu.addSeparator()
         menu.addAction(self.refactoringEditConfigAct)
         menu.addAction(self.refactoringHelpAct)
@@ -394,9 +550,26 @@
         """
         Private slot called before the refactoring menu is shown.
         """
-        # TODO: enable these once undo/redo has been implemented
-##        self.refactoringUndoAct.setEnabled(self.__canUndo())
-##        self.refactoringRedoAct.setEnabled(self.__canRedo())
+        self.refactoringUndoAct.setEnabled(self.__canUndo())
+        self.refactoringRedoAct.setEnabled(self.__canRedo())
+    
+    def __showRefactoringHistoryMenu(self):
+        """
+        Private slot called before the refactoring history menu is shown.
+        """
+        aw = e5App().getObject("ViewManager").activeWindow()
+        resource = None
+        if aw is not None:
+            filename = aw.getFileName()
+            resource = rope.base.libutils.path_to_resource(
+                self.__project, filename)
+        
+        self.refactoringUndoHistoryAct.setEnabled(self.__canUndo())
+        self.refactoringUndoFileHistoryAct.setEnabled(
+            resource is not None and self.__canUndoFile(resource))
+        self.refactoringRedoHistoryAct.setEnabled(self.__canRedo())
+        self.refactoringRedoFileHistoryAct.setEnabled(
+            resource is not None and self.__canRedoFile(resource))
     
     def handleRopeError(self, err, title, handle=None):
         """
@@ -548,6 +721,139 @@
         self.dlg.show()
     
     #####################################################
+    ## Undo/Redo refactorings
+    #####################################################
+    
+    def __undo(self):
+        """
+        Private slot to undo the last refactoring.
+        """
+        title = self.trUtf8("Undo refactoring")
+        history = self.__project.history
+        res = E5MessageBox.question(None,
+            title,
+            self.trUtf8("""Shall the refactoring <b>{0}</b> be undone?""")\
+                .format(Utilities.html_encode(
+                    history.undo_list[-1].description)),
+            QMessageBox.StandardButtons(
+                QMessageBox.No | \
+                QMessageBox.Yes),
+            QMessageBox.No)
+        if res == QMessageBox.Yes:
+            if not self.confirmAllBuffersSaved():
+                return
+            
+            changes = history.undo_list[-1]
+            handle = ProgressHandle(self.trUtf8("Undo"), False, self.__ui)
+            handle.show()
+            QApplication.processEvents()
+            try:
+                history.undo(task_handle=handle)
+            except Exception as err:
+                self.handleRopeError(err, title, handle)
+            handle.reset()
+            self.refreshEditors(changes)
+            if self.__e5project.isDirty():
+                self.__e5project.saveProject()
+    
+    def __redo(self):
+        """
+        Private slot to redo the last refactoring.
+        """
+        title = self.trUtf8("Redo refactoring")
+        history = self.__project.history
+        res = E5MessageBox.question(None,
+            title,
+            self.trUtf8("""Shall the refactoring <b>{0}</b> be redone?""")\
+                .format(Utilities.html_encode(
+                    history.redo_list[-1].description)),
+            QMessageBox.StandardButtons(\
+                QMessageBox.No | \
+                QMessageBox.Yes),
+            QMessageBox.No)
+        if res == QMessageBox.Yes:
+            if not self.confirmAllBuffersSaved():
+                return
+            
+            changes = history.redo_list[-1]
+            handle = ProgressHandle(self.trUtf8("Redo"), False, self.__ui)
+            handle.show()
+            QApplication.processEvents()
+            try:
+                history.redo(task_handle=handle)
+            except Exception as err:
+                self.handleRopeError(err, title, handle)
+            handle.reset()
+            self.refreshEditors(changes)
+            if self.__e5project.isDirty():
+                self.__e5project.saveProject()
+    
+    def __showProjectUndoHistory(self):
+        """
+        Private method to show list of changes available for an undo operation.
+        """
+        undoList = list(reversed(self.__project.history.undo_list))
+        self.dlg = HistoryDialog(self, undoList, True, self.__ui)
+        self.dlg.show()
+    
+    def __showProjectRedoHistory(self):
+        """
+        Private method to show list of changes available for a redo operation.
+        """
+        redoList = self.__project.history.redo_list
+        self.dlg = HistoryDialog(self, redoList, False, self.__ui)
+        self.dlg.show()
+    
+    def __showFileUndoHistory(self):
+        """
+        Private method to show list of changes related to the current file 
+        available for an undo operation.
+        """
+        aw = e5App().getObject("ViewManager").activeWindow()
+        
+        if aw is None:
+            return
+        
+        filename = aw.getFileName()
+        resource = rope.base.libutils.path_to_resource(
+            self.__project, filename)
+        undoList = list(reversed(self.__getFileUndoList(resource)))
+        self.dlg = HistoryDialog(self, undoList, True, self.__ui)
+        self.dlg.show()
+    
+    def __showFileRedoHistory(self):
+        """
+        Private method to show list of changes related to the current file 
+        available for a redo operation.
+        """
+        aw = e5App().getObject("ViewManager").activeWindow()
+        
+        if aw is None:
+            return
+        
+        filename = aw.getFileName()
+        resource = rope.base.libutils.path_to_resource(
+            self.__project, filename)
+        redoList = self.__getFileRedoList(resource)
+        self.dlg = HistoryDialog(self, redoList, False, self.__ui)
+        self.dlg.show()
+    
+    def __clearHistory(self):
+        """
+        Private slot to clear the redo and undo lists.
+        """
+        res = E5MessageBox.question(None,
+            self.trUtf8("Clear History"),
+            self.trUtf8("""Do you really want to clear the undo"""
+                        """ and redo history?"""),
+            QMessageBox.StandardButtons(\
+                QMessageBox.No | \
+                QMessageBox.Yes),
+            QMessageBox.No)
+        if res == QMessageBox.Yes:
+            self.__project.history.clear()
+    
+    #####################################################
     ## Find actions
     #####################################################
     

eric ide

mercurial