--- 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 #####################################################