RefactoringRope/HistoryDialog.py

branch
server_client_variant
changeset 168
53d76b4fc1ac
parent 151
5260100b6700
child 170
05ef7c12a6d4
diff -r 3c8e875d0326 -r 53d76b4fc1ac RefactoringRope/HistoryDialog.py
--- a/RefactoringRope/HistoryDialog.py	Sat Sep 16 18:51:19 2017 +0200
+++ b/RefactoringRope/HistoryDialog.py	Sun Sep 17 17:03:16 2017 +0200
@@ -9,127 +9,308 @@
 
 from __future__ import unicode_literals
 
-from PyQt5.QtCore import Qt, pyqtSlot
-from PyQt5.QtWidgets import QDialogButtonBox, QListWidgetItem, QApplication
+from PyQt5.QtCore import pyqtSlot, Qt, QItemSelectionModel
+from PyQt5.QtGui import QBrush, QColor, QTextCursor
+from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QListWidgetItem, \
+    QAbstractButton
 
 from E5Gui.E5Application import e5App
 from E5Gui import E5MessageBox
 
-from PreviewDialogBase import PreviewDialogBase
+from Ui_HistoryDialog import Ui_HistoryDialog
 
+import Globals
 import Utilities
 
 
-class HistoryDialog(PreviewDialogBase):
+class HistoryDialog(QDialog, Ui_HistoryDialog):
     """
     Class implementing the History dialog.
     """
     ChangeIDRole = Qt.UserRole
     
-    def __init__(self, refactoring, changes, isUndo, parent=None):
+    def __init__(self, refactoring, filename="", parent=None):
         """
         Constructor
         
         @param refactoring reference to the main refactoring object
-            (Refactoring)
-        @param changes list of ChangeSet objects
-            (list of rope.base.change.ChangeSet)
-        @param isUndo flag indicating an undo history dialog (boolean)
-        @param parent reference to the parent widget (QWidget)
+        @type Refactoring
+        @param filename name of the file to show the history for
+        @type str
+        @param parent reference to the parent widget
+        @type QWidget
         """
-        PreviewDialogBase.__init__(self, parent)
+        QDialog.__init__(self, parent)
+        self.setupUi(self)
+        self.setWindowFlags(Qt.Window)
+        
+        if Globals.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(QColor(190, 237, 190)))
+        self.formats['+'] = charFormat
+        charFormat = self.previewEdit.currentCharFormat()
+        charFormat.setBackground(QBrush(QColor(237, 190, 190)))
+        self.formats['-'] = charFormat
+        charFormat = self.previewEdit.currentCharFormat()
+        charFormat.setBackground(QBrush(QColor(190, 190, 237)))
+        self.formats['@'] = charFormat
+        charFormat = self.previewEdit.currentCharFormat()
+        charFormat.setBackground(QBrush(QColor(124, 124, 124)))
+        self.formats['?'] = charFormat
+        charFormat = self.previewEdit.currentCharFormat()
+        charFormat.setBackground(QBrush(QColor(190, 190, 190)))
+        self.formats['='] = charFormat
         
         self.__refactoring = refactoring
-        self.__isUndo = isUndo
+        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))
         
-        if self.__isUndo:
-            self.__actionButton = self.buttonBox.addButton(
-                self.tr("&Undo"),
-                QDialogButtonBox.AcceptRole)
-            self.description.setText(self.tr("Undoable Changes"))
-            title = self.tr("Undo History")
-        else:
-            self.__actionButton = self.buttonBox.addButton(
-                self.tr("&Redo"),
-                QDialogButtonBox.AcceptRole)
-            self.description.setText(self.tr("Redoable Changes"))
-            title = self.tr("Redo History")
-        self.buttonBox.addButton(QDialogButtonBox.Close)
-        self.setWindowTitle(title)
+        self.__undoButton = self.buttonBox.addButton(
+            self.tr("&Undo"), QDialogButtonBox.ActionRole)
+        self.__redoButton = self.buttonBox.addButton(
+            self.tr("&Redo"), QDialogButtonBox.ActionRole)
+        self.__refreshButton = self.buttonBox.addButton(
+            self.tr("Re&fresh"), QDialogButtonBox.ActionRole)
+        self.__clearButton = self.buttonBox.addButton(
+            self.tr("&Clear History"), QDialogButtonBox.ActionRole)
         
         # populate the list
-        self.__changes = {}
-        for change in changes:
-            self.__changes[id(change)] = change
-            itm = QListWidgetItem(str(change), self.changesList)
-            itm.setData(HistoryDialog.ChangeIDRole, id(change))
-        if self.changesList.count() > 0:
-            self.changesList.item(0).setSelected(True)
+        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.End)
+        self.previewEdit.setTextCursor(tc)
+        self.previewEdit.setCurrentCharFormat(charFormat)
+        self.previewEdit.insertPlainText(txt)
     
-    @pyqtSlot(QListWidgetItem, QListWidgetItem)
-    def on_changesList_currentItemChanged(self, current, previous):
+    @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
         """
-        Private slot called when a change is selected.
+        if button == QDialogButtonBox.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 new current item (QListWidgetItem)
-        @param previous reference to the old current item (QListWidgetItem)
+        @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)
-        change = self.__changes[changeId]
-        for line in change.get_description().splitlines(True):
-            try:
-                charFormat = self.formats[line[0]]
-            except (IndexError, KeyError):
-                charFormat = self.formats[' ']
-            self._appendText(line, charFormat)
+        self.__refactoring.sendJson("History", {
+            "Subcommand": "GetChange",
+            "Id": changeId,
+        })
+    
+    @pyqtSlot(QListWidgetItem, QListWidgetItem)
+    def on_redoChangesList_currentItemChanged(self, current, previous):
+        """
+        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)
     
-    def accept(self):
+    @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
         """
-        Public slot to undo the selected set of changes.
+        self.__currentItemChanged(item)
+    
+    @pyqtSlot(QListWidgetItem, QListWidgetItem)
+    def on_undoChangesList_currentItemChanged(self, current, previous):
+        """
+        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
         """
-        changeId = self.changesList.currentItem()\
-            .data(HistoryDialog.ChangeIDRole)
-        change = self.__changes[changeId]
+        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.
         
-        if self.__isUndo:
-            res = E5MessageBox.yesNo(
-                None,
-                self.tr("Undo refactorings"),
-                self.tr("""Shall all refactorings up to <b>{0}</b>"""
-                        """ be undone?""")
-                .format(Utilities.html_encode(str(change))))
-        else:
-            res = E5MessageBox.yesNo(
-                None,
-                self.tr("Redo refactorings"),
-                self.tr("""Shall all refactorings up to <b>{0}</b>"""
-                        """ be redone?""")
-                .format(Utilities.html_encode(str(change))))
+        @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 = E5MessageBox.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 = E5MessageBox.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
             
-            from ProgressHandle import ProgressHandle
-            handle = ProgressHandle(change.description, False, self)
-            handle.show()
-            QApplication.processEvents()
-            if self.__isUndo:
-                self.__refactoring.getProject().history.undo(
-                    change, task_handle=handle)
-            else:
-                self.__refactoring.getProject().history.redo(
-                    change, task_handle=handle)
-            handle.reset()
+            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 = E5MessageBox.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.__refactoring.refreshEditors(change)
+            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.Select)
+            elif self.redoChangesList.count() > 0:
+                self.redoChangesList.setCurrentItem(
+                    self.redoChangesList.item(0),
+                    QItemSelectionModel.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 = e5App().getObject("Project")
             if p.isDirty():
                 p.saveProject()
             
-            PreviewDialogBase.accept(self)
-        else:
-            self.reject()
+            self.raise_()
+            self.__refreshHistories()

eric ide

mercurial