Wed, 23 Oct 2024 17:45:37 +0200
Adjusted code for eric7 24.10 and newer.
# -*- coding: utf-8 -*- # Copyright (c) 2010 - 2024 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the History dialog. """ from PyQt6.QtCore import QItemSelectionModel, Qt, pyqtSlot from PyQt6.QtGui import QBrush, QTextCursor from PyQt6.QtWidgets import QAbstractButton, QDialog, QDialogButtonBox, QListWidgetItem from eric7 import Preferences, Utilities from eric7.EricWidgets import EricMessageBox from eric7.EricWidgets.EricApplication import ericApp try: from eric7.SystemUtilities.OSUtilities import isWindowsPlatform except ImportError: # backward compatibility for eric < 23.1 from eric7.Globals import isWindowsPlatform from .Ui_HistoryDialog import Ui_HistoryDialog class HistoryDialog(QDialog, Ui_HistoryDialog): """ Class implementing the History dialog. """ ChangeIDRole = Qt.ItemDataRole.UserRole def __init__(self, refactoring, filename="", parent=None): """ Constructor @param refactoring reference to the main refactoring object @type RefactoringServer @param filename name of the file to show the history for @type str @param parent reference to the parent widget @type QWidget """ QDialog.__init__(self, parent) self.setupUi(self) self.setWindowFlags(Qt.WindowType.Window) if isWindowsPlatform(): self.previewEdit.setFontFamily("Lucida Console") else: self.previewEdit.setFontFamily("Monospace") self.formats = {} self.formats[" "] = self.previewEdit.currentCharFormat() charFormat = self.previewEdit.currentCharFormat() charFormat.setBackground(QBrush(Preferences.getDiffColour("AddedColor"))) self.formats["+"] = charFormat charFormat = self.previewEdit.currentCharFormat() charFormat.setBackground(QBrush(Preferences.getDiffColour("RemovedColor"))) self.formats["-"] = charFormat charFormat = self.previewEdit.currentCharFormat() charFormat.setBackground(QBrush(Preferences.getDiffColour("ReplacedColor"))) self.formats["@"] = charFormat charFormat = self.previewEdit.currentCharFormat() charFormat.setBackground(QBrush(Preferences.getDiffColour("ContextColor"))) self.formats["?"] = charFormat charFormat = self.previewEdit.currentCharFormat() charFormat.setBackground(QBrush(Preferences.getDiffColour("HeaderColor"))) self.formats["="] = charFormat self.__refactoring = refactoring self.__filename = filename if not filename: self.header.setText(self.tr("<b>Project History</b>")) else: self.header.setText(self.tr("<b>File History: {0}</b>").format(filename)) self.__undoButton = self.buttonBox.addButton( self.tr("&Undo"), QDialogButtonBox.ButtonRole.ActionRole ) self.__redoButton = self.buttonBox.addButton( self.tr("&Redo"), QDialogButtonBox.ButtonRole.ActionRole ) self.__refreshButton = self.buttonBox.addButton( self.tr("Re&fresh"), QDialogButtonBox.ButtonRole.ActionRole ) self.__clearButton = self.buttonBox.addButton( self.tr("&Clear History"), QDialogButtonBox.ButtonRole.ActionRole ) # populate the list self.__refreshHistories() def __appendText(self, txt, charFormat): """ Private method to append text to the end of the preview pane. @param txt text to insert @type str @param charFormat text format to be used @type QTextCharFormat """ tc = self.previewEdit.textCursor() tc.movePosition(QTextCursor.MoveOperation.End) self.previewEdit.setTextCursor(tc) self.previewEdit.setCurrentCharFormat(charFormat) self.previewEdit.insertPlainText(txt) @pyqtSlot(QAbstractButton) def on_buttonBox_clicked(self, button): """ Private slot handling the selection of a dialog button. @param button reference to the button clicked @type QAbstractButton """ if button == QDialogButtonBox.StandardButton.Close: self.close() elif button == self.__undoButton: self.__undoChanges() elif button == self.__redoButton: self.__redoChanges() elif button == self.__refreshButton: self.__refreshHistories() elif button == self.__clearButton: self.__clearHistory() def __currentItemChanged(self, current): """ Private method to request change data of an item. @param current reference to the item to get change data for @type QListWidgetItem """ if current is None: return self.previewEdit.clear() changeId = current.data(HistoryDialog.ChangeIDRole) self.__refactoring.sendJson( "History", { "Subcommand": "GetChange", "Id": changeId, }, ) @pyqtSlot(QListWidgetItem, QListWidgetItem) def on_redoChangesList_currentItemChanged(self, current, previous): # noqa: U100 """ Private slot handling a change of the current redo change. @param current reference to the new current redo item @type QListWidgetItem @param previous reference to the previous current redo item @type QListWidgetItem """ self.__redoButton.setEnabled(current is not None) self.__currentItemChanged(current) @pyqtSlot(QListWidgetItem) def on_redoChangesList_itemClicked(self, item): """ Private slot handling a click on a redo entry. @param item reference to the clicked item @type QListWidgetItem """ self.__currentItemChanged(item) @pyqtSlot(QListWidgetItem, QListWidgetItem) def on_undoChangesList_currentItemChanged(self, current, previous): # noqa: U100 """ Private slot handling a change of the current undo change. @param current reference to the new current undo item @type QListWidgetItem @param previous reference to the previous current undo item @type QListWidgetItem """ self.__undoButton.setEnabled(current is not None) self.__currentItemChanged(current) @pyqtSlot(QListWidgetItem) def on_undoChangesList_itemClicked(self, item): """ Private slot handling a click on an undo entry. @param item reference to the clicked item @type QListWidgetItem """ self.__currentItemChanged(item) def __undoChanges(self): """ Private method to undo the selected set of changes. """ currentUndoItem = self.undoChangesList.currentItem() change = currentUndoItem.text() changeId = currentUndoItem.data(HistoryDialog.ChangeIDRole) res = EricMessageBox.yesNo( None, self.tr("Undo Refactorings"), self.tr("""Shall all refactorings up to <b>{0}</b> be undone?""").format( Utilities.html_encode(change) ), ) if res: if not self.__refactoring.confirmAllBuffersSaved(): return self.__refactoring.sendJson( "History", { "Subcommand": "Undo", "Id": changeId, }, ) def __redoChanges(self): """ Private method to redo the selected set of changes. """ currentRedoItem = self.redoChangesList.currentItem() change = currentRedoItem.text() changeId = currentRedoItem.data(HistoryDialog.ChangeIDRole) res = EricMessageBox.yesNo( None, self.tr("Redo Refactorings"), self.tr("""Shall all refactorings up to <b>{0}</b> be redone?""").format( Utilities.html_encode(change) ), ) if res: if not self.__refactoring.confirmAllBuffersSaved(): return self.__refactoring.sendJson( "History", { "Subcommand": "Redo", "Id": changeId, }, ) def __refreshHistories(self): """ Private method to refresh the undo and redo history lists. """ self.__undoButton.setEnabled(False) self.__redoButton.setEnabled(False) self.__refreshButton.setEnabled(False) self.__clearButton.setEnabled(False) self.undoChangesList.clear() self.redoChangesList.clear() self.previewEdit.clear() self.__refactoring.sendJson( "History", {"Subcommand": "Get", "Filename": self.__filename} ) def __clearHistory(self): """ Private method to clear the refactoring history. """ res = EricMessageBox.yesNo( None, self.tr("Clear History"), self.tr("Do you really want to clear the refactoring history?"), ) if res: self.sendJson( "History", { "Subcommand": "Clear", }, ) self.historyCleared() def historyCleared(self): """ Public method to indicate, that the refactoring history was cleared through the menu. """ self.__refreshHistories() def processHistoryCommand(self, data): """ Public method to process the data sent by the refactoring client. @param data dictionary containing the history data @type dict """ subcommand = data["Subcommand"] if subcommand == "Histories": for change, changeId in data["Undo"]: itm = QListWidgetItem(change, self.undoChangesList) itm.setData(HistoryDialog.ChangeIDRole, changeId) for change, changeId in data["Redo"]: itm = QListWidgetItem(change, self.redoChangesList) itm.setData(HistoryDialog.ChangeIDRole, changeId) if self.undoChangesList.count() > 0: self.undoChangesList.setCurrentItem( self.undoChangesList.item(0), QItemSelectionModel.SelectionFlag.Select, ) elif self.redoChangesList.count() > 0: self.redoChangesList.setCurrentItem( self.redoChangesList.item(0), QItemSelectionModel.SelectionFlag.Select, ) self.__refreshButton.setEnabled(True) if self.undoChangesList.count() > 0 or self.redoChangesList.count() > 0: self.__clearButton.setEnabled(True) elif subcommand == "ChangeDescription": for line in data["Description"].splitlines(True): try: charFormat = self.formats[line[0]] except (IndexError, KeyError): charFormat = self.formats[" "] self.__appendText(line, charFormat) elif subcommand in ["Undo", "Redo"]: self.__refactoring.refreshEditors(data["ChangedFiles"]) p = ericApp().getObject("Project") if p.isDirty(): p.saveProject() self.raise_() self.__refreshHistories() def closeEvent(self, evt): """ Protected method handling close events. @param evt reference to the close event object @type QCloseEvent """ self.__refactoring.sendJson( "History", { "Subcommand": "ClearChanges", }, ) evt.accept()