src/eric7/HexEdit/HexEditSearchReplaceWidget.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
--- a/src/eric7/HexEdit/HexEditSearchReplaceWidget.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/HexEdit/HexEditSearchReplaceWidget.py	Wed Jul 13 14:55:47 2022 +0200
@@ -21,10 +21,11 @@
     """
     Class implementing a search and replace widget for the hex editor.
     """
+
     def __init__(self, editor, mainWindow, replace=False, parent=None):
         """
         Constructor
-        
+
         @param editor reference to the hex editor widget
         @type HexEditWidget
         @param mainWindow reference to the main window
@@ -35,54 +36,61 @@
         @type QWidget
         """
         super().__init__(parent)
-        
+
         self.__replace = replace
         self.__editor = editor
-        
+
         # keep this in sync with the logic in __getContent()
         self.__formatAndValidators = {
-            "hex": (self.tr("Hex"), QRegularExpressionValidator(
-                QRegularExpression("[0-9a-f]*"))),
-            "dec": (self.tr("Dec"), QRegularExpressionValidator(
-                QRegularExpression("[0-9]*"))),
-            "oct": (self.tr("Oct"), QRegularExpressionValidator(
-                QRegularExpression("[0-7]*"))),
-            "bin": (self.tr("Bin"), QRegularExpressionValidator(
-                QRegularExpression("[01]*"))),
+            "hex": (
+                self.tr("Hex"),
+                QRegularExpressionValidator(QRegularExpression("[0-9a-f]*")),
+            ),
+            "dec": (
+                self.tr("Dec"),
+                QRegularExpressionValidator(QRegularExpression("[0-9]*")),
+            ),
+            "oct": (
+                self.tr("Oct"),
+                QRegularExpressionValidator(QRegularExpression("[0-7]*")),
+            ),
+            "bin": (
+                self.tr("Bin"),
+                QRegularExpressionValidator(QRegularExpression("[01]*")),
+            ),
             "iso-8859-1": (self.tr("Text"), None),
             # text as latin-1/iso-8859-1
             "utf-8": (self.tr("UTF-8"), None),
             # text as utf-8
         }
         formatOrder = ["hex", "dec", "oct", "bin", "iso-8859-1", "utf-8"]
-        
+
         self.__currentFindFormat = ""
         self.__currentReplaceFormat = ""
-        
+
         self.__findHistory = mainWindow.getSRHistory("search")
         if replace:
             from .Ui_HexEditReplaceWidget import Ui_HexEditReplaceWidget
+
             self.__replaceHistory = mainWindow.getSRHistory("replace")
             self.__ui = Ui_HexEditReplaceWidget()
         else:
             from .Ui_HexEditSearchWidget import Ui_HexEditSearchWidget
+
             self.__ui = Ui_HexEditSearchWidget()
         self.__ui.setupUi(self)
-        
+
         self.__ui.closeButton.setIcon(UI.PixmapCache.getIcon("close"))
-        self.__ui.findPrevButton.setIcon(
-            UI.PixmapCache.getIcon("1leftarrow"))
-        self.__ui.findNextButton.setIcon(
-            UI.PixmapCache.getIcon("1rightarrow"))
-        
+        self.__ui.findPrevButton.setIcon(UI.PixmapCache.getIcon("1leftarrow"))
+        self.__ui.findNextButton.setIcon(UI.PixmapCache.getIcon("1rightarrow"))
+
         if replace:
-            self.__ui.replaceButton.setIcon(
-                UI.PixmapCache.getIcon("editReplace"))
+            self.__ui.replaceButton.setIcon(UI.PixmapCache.getIcon("editReplace"))
             self.__ui.replaceSearchButton.setIcon(
-                UI.PixmapCache.getIcon("editReplaceSearch"))
-            self.__ui.replaceAllButton.setIcon(
-                UI.PixmapCache.getIcon("editReplaceAll"))
-        
+                UI.PixmapCache.getIcon("editReplaceSearch")
+            )
+            self.__ui.replaceAllButton.setIcon(UI.PixmapCache.getIcon("editReplaceAll"))
+
         for dataFormat in formatOrder:
             formatStr, validator = self.__formatAndValidators[dataFormat]
             self.__ui.findFormatCombo.addItem(formatStr, dataFormat)
@@ -90,60 +98,70 @@
             for dataFormat in formatOrder:
                 formatStr, validator = self.__formatAndValidators[dataFormat]
                 self.__ui.replaceFormatCombo.addItem(formatStr, dataFormat)
-        
+
         self.__ui.findtextCombo.setCompleter(None)
         self.__ui.findtextCombo.lineEdit().returnPressed.connect(
-            self.__findByReturnPressed)
+            self.__findByReturnPressed
+        )
         if replace:
             self.__ui.replacetextCombo.setCompleter(None)
             self.__ui.replacetextCombo.lineEdit().returnPressed.connect(
-                self.on_replaceButton_clicked)
-        
+                self.on_replaceButton_clicked
+            )
+
         self.findNextAct = EricAction(
-            self.tr('Find Next'),
-            self.tr('Find Next'),
-            0, 0, self, 'hexEditor_search_widget_find_next')
+            self.tr("Find Next"),
+            self.tr("Find Next"),
+            0,
+            0,
+            self,
+            "hexEditor_search_widget_find_next",
+        )
         self.findNextAct.triggered.connect(self.on_findNextButton_clicked)
         self.findNextAct.setEnabled(False)
         self.__ui.findtextCombo.addAction(self.findNextAct)
-        
+
         self.findPrevAct = EricAction(
-            self.tr('Find Prev'),
-            self.tr('Find Prev'),
-            0, 0, self, 'hexEditor_search_widget_find_prev')
+            self.tr("Find Prev"),
+            self.tr("Find Prev"),
+            0,
+            0,
+            self,
+            "hexEditor_search_widget_find_prev",
+        )
         self.findPrevAct.triggered.connect(self.on_findPrevButton_clicked)
         self.findPrevAct.setEnabled(False)
         self.__ui.findtextCombo.addAction(self.findPrevAct)
-        
+
         self.__havefound = False
-    
+
     @pyqtSlot(int)
     def on_findFormatCombo_currentIndexChanged(self, idx):
         """
         Private slot to handle a selection from the find format.
-        
+
         @param idx index of the selected entry
         @type int
         """
         if idx >= 0:
             findFormat = self.__ui.findFormatCombo.itemData(idx)
-            
+
             if findFormat != self.__currentFindFormat:
                 txt = self.__ui.findtextCombo.currentText()
-                newTxt = self.__convertText(
-                    txt, self.__currentFindFormat, findFormat)
+                newTxt = self.__convertText(txt, self.__currentFindFormat, findFormat)
                 self.__currentFindFormat = findFormat
-                
+
                 self.__ui.findtextCombo.setValidator(
-                    self.__formatAndValidators[findFormat][1])
-                
+                    self.__formatAndValidators[findFormat][1]
+                )
+
                 self.__ui.findtextCombo.setEditText(newTxt)
-    
+
     @pyqtSlot(str)
     def on_findtextCombo_editTextChanged(self, txt):
         """
         Private slot to enable/disable the find buttons.
-        
+
         @param txt text of the find text combo
         @type str
         """
@@ -165,12 +183,12 @@
                 self.__ui.replaceButton.setEnabled(False)
                 self.__ui.replaceSearchButton.setEnabled(False)
                 self.__ui.replaceAllButton.setEnabled(True)
-    
+
     @pyqtSlot(int)
     def on_findtextCombo_activated(self, idx):
         """
         Private slot to handle a selection from the find history.
-        
+
         @param idx index of the selected entry
         @type int
         """
@@ -178,12 +196,12 @@
             formatIndex = self.__ui.findtextCombo.itemData(idx)
             if formatIndex is not None:
                 self.__ui.findFormatCombo.setCurrentIndex(formatIndex)
-    
+
     def __getContent(self, replace=False):
         """
         Private method to get the contents of the find/replace combo as
         a bytearray.
-        
+
         @param replace flag indicating to retrieve the replace contents
         @type bool
         @return search or replace term as text and binary data
@@ -197,12 +215,12 @@
             textCombo = self.__ui.findtextCombo
             formatCombo = self.__ui.findFormatCombo
             history = self.__findHistory
-        
+
         txt = textCombo.currentText()
         idx = formatCombo.currentIndex()
         findFormat = formatCombo.itemData(idx)
         ba = self.__text2bytearray(txt, findFormat)
-        
+
         # This moves any previous occurrence of this statement to the head
         # of the list and updates the combobox
         historyEntry = (idx, txt)
@@ -212,27 +230,27 @@
         textCombo.clear()
         for index, text in history:
             textCombo.addItem(text, index)
-        
+
         return ba, txt
-    
+
     @pyqtSlot()
     def on_findNextButton_clicked(self):
         """
         Private slot to find the next occurrence.
         """
         self.findPrevNext(False)
-    
+
     @pyqtSlot()
     def on_findPrevButton_clicked(self):
         """
         Private slot to find the previous occurrence.
         """
         self.findPrevNext(True)
-    
+
     def findPrevNext(self, prev=False):
         """
         Public slot to find the next occurrence of the search term.
-        
+
         @param prev flag indicating a backwards search
         @type bool
         @return flag indicating a successful search
@@ -241,41 +259,41 @@
         if not self.__havefound or not self.__ui.findtextCombo.currentText():
             self.show()
             return False
-        
+
         self.__findBackwards = prev
         ba, txt = self.__getContent()
-        
+
         idx = -1
         if len(ba) > 0:
             startIndex = self.__editor.cursorPosition() // 2
             if prev:
                 if (
-                    self.__editor.hasSelection() and
-                    startIndex == self.__editor.getSelectionEnd()
+                    self.__editor.hasSelection()
+                    and startIndex == self.__editor.getSelectionEnd()
                 ):
                     # skip to the selection start
                     startIndex = self.__editor.getSelectionBegin()
                 idx = self.__editor.lastIndexOf(ba, startIndex)
             else:
                 if (
-                    self.__editor.hasSelection() and
-                    startIndex == self.__editor.getSelectionBegin() - 1
+                    self.__editor.hasSelection()
+                    and startIndex == self.__editor.getSelectionBegin() - 1
                 ):
                     # skip to the selection end
                     startIndex = self.__editor.getSelectionEnd()
                 idx = self.__editor.indexOf(ba, startIndex)
-        
+
         if idx >= 0:
             if self.__replace:
                 self.__ui.replaceButton.setEnabled(True)
                 self.__ui.replaceSearchButton.setEnabled(True)
         else:
             EricMessageBox.information(
-                self, self.windowTitle(),
-                self.tr("'{0}' was not found.").format(txt))
-        
+                self, self.windowTitle(), self.tr("'{0}' was not found.").format(txt)
+            )
+
         return idx >= 0
-    
+
     def __findByReturnPressed(self):
         """
         Private slot to handle a return pressed in the find combo.
@@ -284,34 +302,36 @@
             self.findPrevNext(True)
         else:
             self.findPrevNext(False)
-    
+
     @pyqtSlot(int)
     def on_replaceFormatCombo_currentIndexChanged(self, idx):
         """
         Private slot to handle a selection from the replace format.
-        
+
         @param idx index of the selected entry
         @type int
         """
         if idx >= 0:
             replaceFormat = self.__ui.replaceFormatCombo.itemData(idx)
-            
+
             if replaceFormat != self.__currentReplaceFormat:
                 txt = self.__ui.replacetextCombo.currentText()
                 newTxt = self.__convertText(
-                    txt, self.__currentReplaceFormat, replaceFormat)
+                    txt, self.__currentReplaceFormat, replaceFormat
+                )
                 self.__currentReplaceFormat = replaceFormat
-                
+
                 self.__ui.replacetextCombo.setValidator(
-                    self.__formatAndValidators[replaceFormat][1])
-                
+                    self.__formatAndValidators[replaceFormat][1]
+                )
+
                 self.__ui.replacetextCombo.setEditText(newTxt)
-    
+
     @pyqtSlot(int)
     def on_replacetextCombo_activated(self, idx):
         """
         Private slot to handle a selection from the replace history.
-        
+
         @param idx index of the selected entry
         @type int
         """
@@ -326,7 +346,7 @@
         Private slot to replace one occurrence of data.
         """
         self.__doReplace(False)
-    
+
     @pyqtSlot()
     def on_replaceSearchButton_clicked(self):
         """
@@ -334,49 +354,49 @@
         one.
         """
         self.__doReplace(True)
-    
+
     def __doReplace(self, searchNext):
         """
         Private method to replace one occurrence of data.
-        
+
         @param searchNext flag indicating to search for the next occurrence
         @type bool
         """
         # Check enabled status due to dual purpose usage of this method
         if (
-            not self.__ui.replaceButton.isEnabled() and
-            not self.__ui.replaceSearchButton.isEnabled()
+            not self.__ui.replaceButton.isEnabled()
+            and not self.__ui.replaceSearchButton.isEnabled()
         ):
             return
-        
+
         fba, ftxt = self.__getContent(False)
         rba, rtxt = self.__getContent(True)
-        
+
         ok = False
         if self.__editor.hasSelection():
             # we did a successful search before
             startIdx = self.__editor.getSelectionBegin()
             self.__editor.replaceByteArray(startIdx, len(fba), rba)
-            
+
             if searchNext:
                 ok = self.findPrevNext(self.__findBackwards)
-        
+
         if not ok:
             self.__ui.replaceButton.setEnabled(False)
             self.__ui.replaceSearchButton.setEnabled(False)
-    
+
     @pyqtSlot()
     def on_replaceAllButton_clicked(self):
         """
         Private slot to replace all occurrences of data.
         """
         replacements = 0
-        
+
         cursorPosition = self.__editor.cursorPosition()
-        
+
         fba, ftxt = self.__getContent(False)
         rba, rtxt = self.__getContent(True)
-        
+
         idx = 0
         while idx >= 0:
             idx = self.__editor.indexOf(fba, idx)
@@ -384,76 +404,78 @@
                 self.__editor.replaceByteArray(idx, len(fba), rba)
                 idx += len(rba)
                 replacements += 1
-        
+
         if replacements:
             EricMessageBox.information(
-                self, self.windowTitle(),
-                self.tr("Replaced {0} occurrences.")
-                .format(replacements))
+                self,
+                self.windowTitle(),
+                self.tr("Replaced {0} occurrences.").format(replacements),
+            )
         else:
             EricMessageBox.information(
-                self, self.windowTitle(),
-                self.tr("Nothing replaced because '{0}' was not found.")
-                .format(ftxt))
-        
+                self,
+                self.windowTitle(),
+                self.tr("Nothing replaced because '{0}' was not found.").format(ftxt),
+            )
+
         self.__editor.setCursorPosition(cursorPosition)
         self.__editor.ensureVisible()
-    
-    def __showFind(self, text=''):
+
+    def __showFind(self, text=""):
         """
         Private method to display this widget in find mode.
-        
+
         @param text hex encoded text to be shown in the findtext edit
         @type str
         """
         self.__replace = False
-        
+
         self.__ui.findtextCombo.clear()
         for index, txt in self.__findHistory:
             self.__ui.findtextCombo.addItem(txt, index)
-        self.__ui.findFormatCombo.setCurrentIndex(0)    # 0 is always Hex
+        self.__ui.findFormatCombo.setCurrentIndex(0)  # 0 is always Hex
         self.on_findFormatCombo_currentIndexChanged(0)
         self.__ui.findtextCombo.setEditText(text)
         self.__ui.findtextCombo.lineEdit().selectAll()
         self.__ui.findtextCombo.setFocus()
         self.on_findtextCombo_editTextChanged(text)
-        
+
         self.__havefound = True
         self.__findBackwards = False
-    
-    def __showReplace(self, text=''):
+
+    def __showReplace(self, text=""):
         """
         Private slot to display this widget in replace mode.
-        
+
         @param text hex encoded text to be shown in the findtext edit
         @type str
         """
         self.__replace = True
-        
+
         self.__ui.findtextCombo.clear()
         for index, txt in self.__findHistory:
             self.__ui.findtextCombo.addItem(txt, index)
-        self.__ui.findFormatCombo.setCurrentIndex(0)    # 0 is always Hex
+        self.__ui.findFormatCombo.setCurrentIndex(0)  # 0 is always Hex
         self.on_findFormatCombo_currentIndexChanged(0)
         self.__ui.findtextCombo.setEditText(text)
         self.__ui.findtextCombo.lineEdit().selectAll()
         self.__ui.findtextCombo.setFocus()
         self.on_findtextCombo_editTextChanged(text)
-        
+
         self.__ui.replacetextCombo.clear()
         for index, txt in self.__replaceHistory:
             self.__ui.replacetextCombo.addItem(txt, index)
-        self.__ui.replaceFormatCombo.setCurrentIndex(0)    # 0 is always Hex
+        self.__ui.replaceFormatCombo.setCurrentIndex(0)  # 0 is always Hex
         self.on_replaceFormatCombo_currentIndexChanged(0)
-        self.__ui.replacetextCombo.setEditText('')
-        
+        self.__ui.replacetextCombo.setEditText("")
+
         self.__havefound = True
         self.__findBackwards = False
-    
-    def show(self, text=''):
+
+    def show(self, text=""):
         """
         Public slot to show the widget.
-        
+
         @param text hex encoded text to be shown in the findtext edit
         @type str
         """
@@ -463,7 +485,7 @@
             self.__showFind(text)
         super().show()
         self.activateWindow()
-    
+
     @pyqtSlot()
     def on_closeButton_clicked(self):
         """
@@ -475,17 +497,17 @@
     def keyPressEvent(self, event):
         """
         Protected slot to handle key press events.
-        
+
         @param event reference to the key press event
         @type QKeyEvent
         """
         if event.key() == Qt.Key.Key_Escape:
             self.close()
-    
+
     def __convertText(self, txt, oldFormat, newFormat):
         """
         Private method to convert text from one format into another.
-        
+
         @param txt text to be converted
         @type str
         @param oldFormat current format of the text
@@ -498,16 +520,16 @@
         if txt and oldFormat and newFormat and oldFormat != newFormat:
             # step 1: convert the text to a byte array using the old format
             byteArray = self.__text2bytearray(txt, oldFormat)
-            
+
             # step 2: convert the byte array to text using the new format
             txt = self.__bytearray2text(byteArray, newFormat)
-        
+
         return txt
-    
+
     def __int2bytearray(self, value):
         """
         Private method to convert an integer to a byte array.
-        
+
         @param value value to be converted
         @type int
         @return byte array for the given value
@@ -517,13 +539,13 @@
         while value > 0:
             value, modulus = divmod(value, 256)
             ba.insert(0, modulus)
-        
+
         return ba
-    
+
     def __bytearray2int(self, array):
         """
         Private method to convert a byte array to an integer value.
-        
+
         @param array byte array to be converted
         @type bytearray
         @return integer value of the given array
@@ -532,13 +554,13 @@
         value = 0
         for b in array:
             value = value * 256 + b
-        
+
         return value
-    
+
     def __text2bytearray(self, txt, dataFormat):
         """
         Private method to convert a text to a byte array.
-        
+
         @param txt text to be converted
         @type str
         @param dataFormat format of the text
@@ -550,27 +572,26 @@
         """
         if dataFormat not in self.__formatAndValidators.keys():
             raise ValueError("Bad value for 'dataFormat' parameter.")
-        
-        if dataFormat == "hex":             # hex format
-            ba = bytearray(QByteArray.fromHex(
-                bytes(txt, encoding="ascii")))
-        elif dataFormat == "dec":           # decimal format
+
+        if dataFormat == "hex":  # hex format
+            ba = bytearray(QByteArray.fromHex(bytes(txt, encoding="ascii")))
+        elif dataFormat == "dec":  # decimal format
             ba = self.__int2bytearray(int(txt, 10))
-        elif dataFormat == "oct":           # octal format
+        elif dataFormat == "oct":  # octal format
             ba = self.__int2bytearray(int(txt, 8))
-        elif dataFormat == "bin":           # binary format
+        elif dataFormat == "bin":  # binary format
             ba = self.__int2bytearray(int(txt, 2))
-        elif dataFormat == "iso-8859-1":    # latin-1/iso-8859-1 text
+        elif dataFormat == "iso-8859-1":  # latin-1/iso-8859-1 text
             ba = bytearray(txt, encoding="iso-8859-1")
-        elif dataFormat == "utf-8":         # utf-8 text
+        elif dataFormat == "utf-8":  # utf-8 text
             ba = bytearray(txt, encoding="utf-8")
-        
+
         return ba
-    
+
     def __bytearray2text(self, array, dataFormat):
         """
         Private method to convert a byte array to a text.
-        
+
         @param array byte array to be converted
         @type bytearray
         @param dataFormat format of the text
@@ -582,18 +603,18 @@
         """
         if dataFormat not in self.__formatAndValidators.keys():
             raise ValueError("Bad value for 'dataFormat' parameter.")
-        
-        if dataFormat == "hex":             # hex format
+
+        if dataFormat == "hex":  # hex format
             txt = "{0:x}".format(self.__bytearray2int(array))
-        elif dataFormat == "dec":           # decimal format
+        elif dataFormat == "dec":  # decimal format
             txt = "{0:d}".format(self.__bytearray2int(array))
-        elif dataFormat == "oct":           # octal format
+        elif dataFormat == "oct":  # octal format
             txt = "{0:o}".format(self.__bytearray2int(array))
-        elif dataFormat == "bin":           # binary format
+        elif dataFormat == "bin":  # binary format
             txt = "{0:b}".format(self.__bytearray2int(array))
-        elif dataFormat == "iso-8859-1":    # latin-1/iso-8859-1 text
+        elif dataFormat == "iso-8859-1":  # latin-1/iso-8859-1 text
             txt = str(array, encoding="iso-8859-1")
-        elif dataFormat == "utf-8":         # utf-8 text
+        elif dataFormat == "utf-8":  # utf-8 text
             txt = str(array, encoding="utf-8", errors="replace")
-        
+
         return txt

eric ide

mercurial