--- a/RefactoringRope/Refactoring.py Sat Sep 16 18:51:19 2017 +0200 +++ b/RefactoringRope/Refactoring.py Sun Sep 17 17:03:16 2017 +0200 @@ -60,8 +60,9 @@ self.__ropeConfig = {} self.__mainMenu = None + self.__progressDialog = None self.__helpDialog = None - self.__progressDialog = None + self.__historyDialog = None from FileSystemCommands import E5FileSystemCommands self.__fsCommands = E5FileSystemCommands(self.__e5project) @@ -77,6 +78,8 @@ "FileSystemCommand": self.__fsCommands.processFileSystemCommand, "ClientException": self.__processClientException, + + "HistoryResult": self.__processHistoryResult, } def initActions(self): @@ -489,102 +492,40 @@ self.actions.append(self.refactoringMethodToMethodObjectAct) ##################################################### - ## Undo/Redo actions + ## History actions ##################################################### - self.refactoringUndoAct = E5Action( - self.tr('Undo'), - self.tr('&Undo'), - 0, 0, - self, 'refactoring_undo') - self.refactoringUndoAct.setStatusTip(self.tr( - 'Undo the last refactoring')) - self.refactoringUndoAct.setWhatsThis(self.tr( - """<b>Undo</b>""" - """<p>Undo the last refactoring.</p>""" - )) - self.refactoringUndoAct.triggered.connect( - self.__undo) - self.actions.append(self.refactoringUndoAct) - - self.refactoringRedoAct = E5Action( - self.tr('Redo'), - self.tr('Re&do'), + self.refactoringProjectHistoryAct = E5Action( + self.tr('Show Project History'), + self.tr('Show Project History...'), 0, 0, - self, 'refactoring_redo') - self.refactoringRedoAct.setStatusTip(self.tr( - 'Redo the last refactoring')) - self.refactoringRedoAct.setWhatsThis(self.tr( - """<b>Redo</b>""" - """<p>Redo the last refactoring.</p>""" - )) - self.refactoringRedoAct.triggered.connect( - self.__redo) - self.actions.append(self.refactoringRedoAct) - - self.refactoringUndoHistoryAct = E5Action( - self.tr('Show Project Undo History'), - self.tr('Show Project Undo History'), - 0, 0, - self, 'refactoring_show_project_undo_history') - self.refactoringUndoHistoryAct.setStatusTip(self.tr( - 'Show the undo history of the project')) - self.refactoringUndoHistoryAct.setWhatsThis(self.tr( - """<b>Show Project Undo History</b>""" - """<p>Opens a dialog to show the undo history list of""" + self, 'refactoring_show_project_history') + self.refactoringProjectHistoryAct.setStatusTip(self.tr( + 'Show the refactoring history of the project')) + self.refactoringProjectHistoryAct.setWhatsThis(self.tr( + """<b>Show Project History</b>""" + """<p>This opens a dialog to show the refactoring history of""" """ the project.</p>""" )) - self.refactoringUndoHistoryAct.triggered.connect( - self.__showProjectUndoHistory) - self.actions.append(self.refactoringUndoHistoryAct) + self.refactoringProjectHistoryAct.triggered.connect( + self.__showProjectHistory) + self.actions.append(self.refactoringProjectHistoryAct) - self.refactoringRedoHistoryAct = E5Action( - self.tr('Show Project Redo History'), - self.tr('Show Project Redo History'), + self.refactoringFileHistoryAct = E5Action( + self.tr('Show Current File History'), + self.tr('Show Current File History...'), 0, 0, - self, 'refactoring_show_project_redo_history') - self.refactoringRedoHistoryAct.setStatusTip(self.tr( - 'Show the redo history of the project')) - self.refactoringRedoHistoryAct.setWhatsThis(self.tr( - """<b>Show Project Redo History</b>""" - """<p>Opens a dialog to show the redo history list of""" - """ the project.</p>""" - )) - self.refactoringRedoHistoryAct.triggered.connect( - self.__showProjectRedoHistory) - self.actions.append(self.refactoringRedoHistoryAct) - - self.refactoringUndoFileHistoryAct = E5Action( - self.tr('Show Current File Undo History'), - self.tr('Show Current File Undo History'), - 0, 0, - self, 'refactoring_show_file_undo_history') - self.refactoringUndoFileHistoryAct.setStatusTip(self.tr( - 'Show the undo history of the current file')) - self.refactoringUndoFileHistoryAct.setWhatsThis(self.tr( - """<b>Show Current File Undo History</b>""" - """<p>Opens a dialog to show the undo history list of""" + self, 'refactoring_show_file_history') + self.refactoringFileHistoryAct.setStatusTip(self.tr( + 'Show the refactoring history of the current file')) + self.refactoringFileHistoryAct.setWhatsThis(self.tr( + """<b>Show Current File History</b>""" + """<p>This opens a dialog to show the refactoring history of""" """ the current file.</p>""" )) - self.refactoringUndoFileHistoryAct.triggered.connect( - self.__showFileUndoHistory) - self.actions.append(self.refactoringUndoFileHistoryAct) - - self.refactoringRedoFileHistoryAct = E5Action( - self.tr('Show Current File Redo History'), - self.tr('Show Current File Redo History'), - 0, 0, - self, 'refactoring_show_file_redo_history') - self.refactoringRedoFileHistoryAct.setStatusTip(self.tr( - 'Show the redo history of the current file')) - self.refactoringRedoFileHistoryAct.setWhatsThis(self.tr( - """<b>Show Current File Redo History</b>""" - """<p>Opens a dialog to show the redo history list of""" - """ the current file.</p>""" - )) - self.refactoringRedoFileHistoryAct.triggered.connect( - self.__showFileRedoHistory) - self.actions.append(self.refactoringRedoFileHistoryAct) + self.refactoringFileHistoryAct.triggered.connect( + self.__showFileHistory) + self.actions.append(self.refactoringFileHistoryAct) self.refactoringClearHistoryAct = E5Action( self.tr('Clear History'), @@ -745,7 +686,6 @@ smenu.addAction(self.queryImplementationsAct) smenu = menu.addMenu(self.tr("&Refactoring")) - smenu.aboutToShow.connect(self.__showRefactoringMenu) smenu.addAction(self.refactoringRenameAct) smenu.addAction(self.refactoringRenameLocalAct) smenu.addAction(self.refactoringChangeOccurrencesAct) @@ -784,17 +724,11 @@ imenu.addAction(self.refactoringImportsHandleLongAct) smenu.addSeparator() - smenu.addAction(self.refactoringUndoAct) - smenu.addAction(self.refactoringRedoAct) - smenu.addSeparator() hmenu = smenu.addMenu(self.tr("History")) hmenu.aboutToShow.connect(self.__showRefactoringHistoryMenu) - hmenu.addAction(self.refactoringUndoHistoryAct) - hmenu.addAction(self.refactoringUndoFileHistoryAct) - hmenu.addSeparator() - hmenu.addAction(self.refactoringRedoHistoryAct) - hmenu.addAction(self.refactoringRedoFileHistoryAct) + hmenu.addAction(self.refactoringProjectHistoryAct) + hmenu.addAction(self.refactoringFileHistoryAct) hmenu.addSeparator() hmenu.addAction(self.refactoringClearHistoryAct) @@ -828,103 +762,18 @@ self.__ropeConfig["RopeVersion"], self.__ropeConfig["RopeCopyright"]))) - def __canUndo(self): - """ - Private slot to check, if there are changes to be undone. - - @return flag indicating, that undoable changes are available (boolean) - """ - return False - return self.__project is not None and \ - len(self.__project.history.undo_list) > 0 - - def __canRedo(self): - """ - Private slot to check, if there are changes to be redone. - - @return flag indicating, that redoable changes are available (boolean) - """ - return False - return self.__project is not None and \ - len(self.__project.history.redo_list) > 0 - - def __getFileUndoList(self, resource): - """ - Private slot to get a list of undoable changes. - - @param resource file resource to filter against - (rope.base.resources.File) - @return list of change objects (list of rope.base.change.Change) - """ - undoList = [] - for change in self.__project.history.undo_list: - if resource in change.get_changed_resources(): - undoList.append(change) - return undoList - - def __getFileRedoList(self, resource): - """ - Private slot to get a list of redoable changes. - - @param resource file resource to filter against - (rope.base.resources.File) - @return list of change objects (list of rope.base.change.Change) - """ - redoList = [] - for change in self.__project.history.redo_list: - if resource in change.get_changed_resources(): - redoList.append(change) - return redoList - - def __canUndoFile(self, resource): - """ - Private slot to check, if there are undoable changes for a resource. - - @param resource file resource to check against - (rope.base.resources.File) - @return flag indicating, that undoable changes are available (boolean) - """ - return self.__canUndo() and len(self.__getFileUndoList(resource)) > 0 - - def __canRedoFile(self, resource): - """ - Private slot to check, if there are redoable changes for a resource. - - @param resource file resource to check against - (rope.base.resources.File) - @return flag indicating, that redoable changes are available (boolean) - """ - return self.__canRedo() and len(self.__getFileRedoList(resource)) > 0 - - def __showRefactoringMenu(self): - """ - Private slot called before the refactoring menu is shown. - """ - 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 and self.__project is not None: - filename = aw.getFileName() - if filename is not None: - resource = rope.base.libutils.path_to_resource( - self.__project, filename) + enable = aw is not None and bool(aw.getFileName()) - 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)) + self.refactoringFileHistoryAct.setEnabled(enable) - def __handleRopeError(self, result): + def handleRopeError(self, result): """ - Private method to handle a rope error. + Public method to handle a rope error. @param result dictionary containing the error information @type dict @@ -1779,122 +1628,39 @@ self.dlg.show() ##################################################### - ## Undo/Redo refactorings + ## Refactoring History ##################################################### - def __undo(self): - """ - Private slot to undo the last refactoring. + def __showProjectHistory(self): """ - title = self.tr("Undo refactoring") - history = self.__project.history - res = E5MessageBox.yesNo( - None, - title, - self.tr("""Shall the refactoring <b>{0}</b> be undone?""") - .format(Utilities.html_encode( - history.undo_list[-1].description))) - if res: - if not self.confirmAllBuffersSaved(): - return - - from ProgressHandle import ProgressHandle - changes = history.undo_list[-1] - handle = ProgressHandle(self.tr("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. + Private method to show the project refactoring history. """ - title = self.tr("Redo refactoring") - history = self.__project.history - res = E5MessageBox.yesNo( - None, - title, - self.tr("""Shall the refactoring <b>{0}</b> be redone?""") - .format(Utilities.html_encode( - history.redo_list[-1].description))) - if res: - if not self.confirmAllBuffersSaved(): - return - - from ProgressHandle import ProgressHandle - changes = history.redo_list[-1] - handle = ProgressHandle(self.tr("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() + if self.__historyDialog is not None: + self.__historyDialog.close() + + from HistoryDialog import HistoryDialog + self.__historyDialog = HistoryDialog(self, parent=self.__ui) + self.__historyDialog.finished.connect(self.__historyDialogClosed) + self.__historyDialog.show() - def __showProjectUndoHistory(self): - """ - Private method to show list of changes available for an undo operation. - """ - from HistoryDialog import HistoryDialog - undoList = list(reversed(self.__project.history.undo_list)) - self.dlg = HistoryDialog(self, undoList, True, self.__ui) - self.dlg.show() - - def __showProjectRedoHistory(self): + def __showFileHistory(self): """ - Private method to show list of changes available for a redo operation. - """ - from HistoryDialog import HistoryDialog - 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. + Private method to show the refactoring history of the current file. """ aw = e5App().getObject("ViewManager").activeWindow() if aw is None: return - from HistoryDialog import HistoryDialog - 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 + if self.__historyDialog is not None: + self.__historyDialog.close() from HistoryDialog import HistoryDialog 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() + if filename: + self.__historyDialog = HistoryDialog( + self, filename=filename, parent=self.__ui) + self.__historyDialog.show() def __clearHistory(self): """ @@ -1903,10 +1669,31 @@ res = E5MessageBox.yesNo( None, self.tr("Clear History"), - self.tr("""Do you really want to clear the undo""" - """ and redo history?""")) + self.tr("Do you really want to clear the refactoring history?")) if res: - self.__project.history.clear() + self.sendJson("History", { + "Subcommand": "Clear", + }) + + if self.__historyDialog is not None: + self.__historyDialog.historyCleared() + + def __processHistoryResult(self, result): + """ + Private method to process the history data sent by the refactoring + client. + + @param result dictionary containing the history data + @type dict + """ + if self.handleRopeError(result) and self.__historyDialog is not None: + self.__historyDialog.processHistoryCommand(result) + + def __historyDialogClosed(self): + """ + Private slot handling the closing of the history dialog. + """ + self.__historyDialog = None ##################################################### ## Find actions including mouse click handler @@ -1944,7 +1731,7 @@ @param result dictionary containing the result data @type dict """ - if self.__handleRopeError(result): + if self.handleRopeError(result): title = result["Title"] if result["EntriesCount"] > 0: from MatchesDialog import MatchesDialog @@ -2015,7 +1802,7 @@ @type dict """ if result["Subcommand"] == "Query": - if self.__handleRopeError(result): + if self.handleRopeError(result): title = result["Title"] if "Location" in result: location = result["Location"] @@ -2077,7 +1864,7 @@ @param result dictionary containing the result data @type dict """ - if self.__handleRopeError(result): + if self.handleRopeError(result): title = result["Title"] if result["EntriesCount"] > 0: from MatchesDialog import MatchesDialog @@ -2182,7 +1969,7 @@ @param result dictionary containing the result data @type dict """ - if self.__handleRopeError(result): + if self.handleRopeError(result): title = result["Title"] E5MessageBox.information( @@ -2333,22 +2120,22 @@ act.setEnabled(False) self.__mainMenu.menuAction().setEnabled(False) - self.stopClient() + if self.__helpDialog is not None: + self.__helpDialog.close() + self.__helpDialog = None + if self.__historyDialog is not None: + self.__historyDialog.close() + self.__historyDialog = None + + self.sendJson("CloseProject", {}, flush=True) self.__projectopen = False self.__projectpath = '' self.__projectLanguage = "" self.__ropeConfig = {} + + self.stopClient() - # TODO: delete this or move to client -## 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. @@ -2372,25 +2159,18 @@ self.sendJson("Validate", {}) return res - # TODO: port this - def refreshEditors(self, changes): + def refreshEditors(self, changedFiles): """ Public method to refresh modified editors. - @param changes reference to the ChangeSet object - (rope.base.change.ChangeSet) + @param changedFiles list of changed files + @type list of str """ 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) + for fileName in changedFiles: + normfile = Utilities.normcasepath(fileName) if normfile in openFiles: editor = vm.getEditor(normfile)[1] editor.refresh()