Sun, 10 Jan 2016 16:52:22 +0100
Added search and replace capability to the hex editor.
--- a/HexEdit/HexEditMainWindow.py Sat Jan 09 19:44:31 2016 +0100 +++ b/HexEdit/HexEditMainWindow.py Sun Jan 10 16:52:22 2016 +0100 @@ -13,13 +13,14 @@ from PyQt5.QtCore import pyqtSignal, pyqtSlot, QFile, QFileInfo, QSize from PyQt5.QtGui import QKeySequence -from PyQt5.QtWidgets import QWhatsThis, QLabel +from PyQt5.QtWidgets import QWhatsThis, QLabel, QWidget, QVBoxLayout from E5Gui.E5Action import E5Action from E5Gui.E5MainWindow import E5MainWindow from E5Gui import E5FileDialog, E5MessageBox from .HexEditWidget import HexEditWidget +from .HexEditSearchReplaceWidget import HexEditSearchReplaceWidget import UI.PixmapCache import UI.Config @@ -59,7 +60,19 @@ Preferences.getUI("StyleSheet")) self.__editor = HexEditWidget() - self.setCentralWidget(self.__editor) + self.__searchWidget = HexEditSearchReplaceWidget(self.__editor, False) + self.__replaceWidget = HexEditSearchReplaceWidget(self.__editor, True) + cw = QWidget() + layout = QVBoxLayout(cw) + layout.setContentsMargins(1, 1, 1, 1) + layout.setSpacing(1) + layout.addWidget(self.__editor) + layout.addWidget(self.__searchWidget) + cw.setLayout(layout) + layout.addWidget(self.__replaceWidget) + self.__searchWidget.hide() + self.__replaceWidget.hide() + self.setCentralWidget(cw) g = Preferences.getGeometry("HexEditorGeometry") if g.isEmpty(): @@ -100,8 +113,6 @@ self.__initFileActions() self.__initEditActions() -## self.__initViewActions() -## self.__initToolsActions() self.__initHelpActions() def __initFileActions(self): @@ -406,6 +417,76 @@ self.readonlyAct.toggled[bool].connect(self.__editor.setReadOnly) self.__actions.append(self.readonlyAct) + self.searchAct = E5Action( + self.tr('Search'), + UI.PixmapCache.getIcon("find.png"), + self.tr('&Search...'), + QKeySequence(self.tr("Ctrl+F", "Search|Search")), + 0, + self, 'hexEditor_edit_search') + self.searchAct.setStatusTip(self.tr('Search for a text')) + self.searchAct.setWhatsThis(self.tr( + """<b>Search</b>""" + """<p>Search for some text in the current editor. A""" + """ dialog is shown to enter the searchtext and options""" + """ for the search.</p>""" + )) + self.searchAct.triggered.connect(self.__search) + self.__actions.append(self.searchAct) + + self.searchNextAct = E5Action( + self.tr('Search next'), + UI.PixmapCache.getIcon("findNext.png"), + self.tr('Search &next'), + QKeySequence(self.tr("F3", "Search|Search next")), + 0, + self, 'hexEditor_edit_search_next') + self.searchNextAct.setStatusTip(self.tr( + 'Search next occurrence of text')) + self.searchNextAct.setWhatsThis(self.tr( + """<b>Search next</b>""" + """<p>Search the next occurrence of some text in the current""" + """ editor. The previously entered searchtext and options are""" + """ reused.</p>""" + )) + self.searchNextAct.triggered.connect(self.__searchWidget.findPrevNext) + self.__actions.append(self.searchNextAct) + + self.searchPrevAct = E5Action( + self.tr('Search previous'), + UI.PixmapCache.getIcon("findPrev.png"), + self.tr('Search &previous'), + QKeySequence(self.tr("Shift+F3", "Search|Search previous")), + 0, + self, 'hexEditor_edit_search_previous') + self.searchPrevAct.setStatusTip(self.tr( + 'Search previous occurrence of text')) + self.searchPrevAct.setWhatsThis(self.tr( + """<b>Search previous</b>""" + """<p>Search the previous occurrence of some text in the current""" + """ editor. The previously entered searchtext and options are""" + """ reused.</p>""" + )) + self.searchPrevAct.triggered.connect( + lambda: self.__searchWidget.findPrevNext(True)) + self.__actions.append(self.searchPrevAct) + + self.replaceAct = E5Action( + self.tr('Replace'), + self.tr('&Replace...'), + QKeySequence(self.tr("Ctrl+R", "Search|Replace")), + 0, + self, 'hexEditor_edit_search_replace') + self.replaceAct.setStatusTip(self.tr('Replace some text')) + self.replaceAct.setWhatsThis(self.tr( + """<b>Replace</b>""" + """<p>Search for some text in the current editor and replace it.""" + """ A dialog is shown to enter the searchtext, the replacement""" + """ text and options for the search and replace.</p>""" + )) + self.replaceAct.triggered.connect(self.__replace) + self.__actions.append(self.replaceAct) + self.redoAct.setEnabled(False) self.__editor.canRedoChanged.connect(self.redoAct.setEnabled) @@ -508,6 +589,11 @@ menu.addAction(self.deselectAllAct) menu.addAction(self.saveSelectionReadableAct) menu.addSeparator() + menu.addAction(self.searchAct) + menu.addAction(self.searchNextAct) + menu.addAction(self.searchPrevAct) + menu.addAction(self.replaceAct) + menu.addSeparator() menu.addAction(self.readonlyAct) mb.addSeparator() @@ -545,6 +631,13 @@ edittb.addAction(self.copyAct) edittb.addAction(self.pasteAct) + searchtb = self.addToolBar(self.tr("Find")) + searchtb.setObjectName("SearchToolBar") + searchtb.setIconSize(UI.Config.ToolBarIconSize) + searchtb.addAction(self.searchAct) + searchtb.addAction(self.searchNextAct) + searchtb.addAction(self.searchPrevAct) + helptb = self.addToolBar(self.tr("Help")) helptb.setObjectName("HelpToolBar") helptb.setIconSize(UI.Config.ToolBarIconSize) @@ -1014,3 +1107,17 @@ Private slot called in to enter Whats This mode. """ QWhatsThis.enterWhatsThisMode() + + def __search(self): + """ + Private method to handle the search action. + """ + self.__replaceWidget.hide() + self.__searchWidget.show() + + def __replace(self): + """ + Private method to handle the replace action. + """ + self.__searchWidget.hide() + self.__replaceWidget.show()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HexEdit/HexEditReplaceWidget.ui Sun Jan 10 16:52:22 2016 +0100 @@ -0,0 +1,194 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>HexEditReplaceWidget</class> + <widget class="QWidget" name="HexEditReplaceWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>58</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Find and Replace</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <property name="leftMargin"> + <number>1</number> + </property> + <property name="topMargin"> + <number>1</number> + </property> + <property name="rightMargin"> + <number>1</number> + </property> + <property name="bottomMargin"> + <number>1</number> + </property> + <item row="0" column="0"> + <widget class="QToolButton" name="closeButton"> + <property name="toolTip"> + <string>Press to close the window</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Find:</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QComboBox" name="findFormatCombo"> + <property name="toolTip"> + <string>Select the data format of the find data field</string> + </property> + <item> + <property name="text"> + <string>Hex</string> + </property> + </item> + <item> + <property name="text"> + <string>Text</string> + </property> + </item> + </widget> + </item> + <item row="0" column="3"> + <widget class="QComboBox" name="findtextCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + <property name="editable"> + <bool>true</bool> + </property> + <property name="insertPolicy"> + <enum>QComboBox::InsertAtTop</enum> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="0" column="4"> + <widget class="QToolButton" name="findPrevButton"> + <property name="toolTip"> + <string>Press to find the previous occurrence</string> + </property> + </widget> + </item> + <item row="0" column="5"> + <widget class="QToolButton" name="findNextButton"> + <property name="toolTip"> + <string>Press to find the next occurrence</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Replace:</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QComboBox" name="replaceFormatCombo"> + <property name="toolTip"> + <string>Select the data format of the replace data field</string> + </property> + <item> + <property name="text"> + <string>Hex</string> + </property> + </item> + <item> + <property name="text"> + <string>Text</string> + </property> + </item> + </widget> + </item> + <item row="1" column="3"> + <widget class="QComboBox" name="replacetextCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + <property name="editable"> + <bool>true</bool> + </property> + <property name="insertPolicy"> + <enum>QComboBox::InsertAtTop</enum> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="4"> + <widget class="QToolButton" name="replaceButton"> + <property name="toolTip"> + <string>Press to replace the selection</string> + </property> + </widget> + </item> + <item row="1" column="5"> + <widget class="QToolButton" name="replaceSearchButton"> + <property name="toolTip"> + <string>Press to replace the selection and search for the next occurence</string> + </property> + </widget> + </item> + <item row="1" column="6"> + <widget class="QToolButton" name="replaceAllButton"> + <property name="toolTip"> + <string>Press to replace all occurrences</string> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>findtextCombo</tabstop> + <tabstop>findFormatCombo</tabstop> + <tabstop>replacetextCombo</tabstop> + <tabstop>replaceFormatCombo</tabstop> + <tabstop>findPrevButton</tabstop> + <tabstop>findNextButton</tabstop> + <tabstop>replaceButton</tabstop> + <tabstop>replaceSearchButton</tabstop> + <tabstop>replaceAllButton</tabstop> + <tabstop>closeButton</tabstop> + </tabstops> + <resources/> + <connections/> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HexEdit/HexEditSearchReplaceWidget.py Sun Jan 10 16:52:22 2016 +0100 @@ -0,0 +1,361 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a search and replace widget for the hex editor. +""" + +from PyQt5.QtCore import pyqtSlot, Qt, QByteArray +from PyQt5.QtWidgets import QWidget + +from E5Gui.E5Action import E5Action +from E5Gui import E5MessageBox + +import UI.PixmapCache + + +class HexEditSearchReplaceWidget(QWidget): + """ + Class implementing a search and replace widget for the hex editor. + """ + def __init__(self, editor, replace=False, parent=None): + """ + Constructor + + @param editor reference to the hex editor widget + @type HexEditWidget + @param replace flag indicating a replace widget + @type bool + @param parent reference to the parent widget + @type QWidget + """ + super(HexEditSearchReplaceWidget, self).__init__(parent) + + self.__replace = replace + self.__editor = editor + + self.__findHistory = [] + if replace: + from .Ui_HexEditReplaceWidget import Ui_HexEditReplaceWidget + self.__replaceHistory = [] + 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.png")) + self.__ui.findPrevButton.setIcon( + UI.PixmapCache.getIcon("1leftarrow.png")) + self.__ui.findNextButton.setIcon( + UI.PixmapCache.getIcon("1rightarrow.png")) + + if replace: + self.__ui.replaceButton.setIcon( + UI.PixmapCache.getIcon("editReplace.png")) + self.__ui.replaceSearchButton.setIcon( + UI.PixmapCache.getIcon("editReplaceSearch.png")) + self.__ui.replaceAllButton.setIcon( + UI.PixmapCache.getIcon("editReplaceAll.png")) + + self.__ui.findtextCombo.setCompleter(None) + self.__ui.findtextCombo.lineEdit().returnPressed.connect( + self.__findByReturnPressed) + if replace: + self.__ui.replacetextCombo.setCompleter(None) + self.__ui.replacetextCombo.lineEdit().returnPressed.connect( + self.on_replaceButton_clicked) + + self.findNextAct = E5Action( + 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 = E5Action( + 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 + + def on_findtextCombo_editTextChanged(self, txt): + """ + Private slot to enable/disable the find buttons. + + @param txt text of the find text combo (string) + """ + if not txt: + self.__ui.findNextButton.setEnabled(False) + self.findNextAct.setEnabled(False) + self.__ui.findPrevButton.setEnabled(False) + self.findPrevAct.setEnabled(False) + if self.__replace: + self.__ui.replaceButton.setEnabled(False) + self.__ui.replaceSearchButton.setEnabled(False) + self.__ui.replaceAllButton.setEnabled(False) + else: + self.__ui.findNextButton.setEnabled(True) + self.findNextAct.setEnabled(True) + self.__ui.findPrevButton.setEnabled(True) + self.findPrevAct.setEnabled(True) + if self.__replace: + self.__ui.replaceButton.setEnabled(False) + self.__ui.replaceSearchButton.setEnabled(False) + self.__ui.replaceAllButton.setEnabled(True) + + 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 + @rtype tuple of bytearray and str + """ + if replace: + textCombo = self.__ui.replacetextCombo + formatCombo = self.__ui.replaceFormatCombo + history = self.__replaceHistory + else: + textCombo = self.__ui.findtextCombo + formatCombo = self.__ui.findFormatCombo + history = self.__findHistory + + txt = textCombo.currentText() + idx = formatCombo.currentIndex() + if idx == 0: # hex format + ba = bytearray(QByteArray.fromHex( + bytes(txt, encoding="ascii"))) + else: + ba = bytearray(txt, encoding="utf-8") + + # This moves any previous occurrence of this statement to the head + # of the list and updates the combobox + if txt in history: + history.remove(txt) + history.insert(0, txt) + textCombo.clear() + textCombo.addItems(history) + + 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 + @rtype bool + """ + if not self.__havefound or not self.__ui.findtextCombo.currentText(): + self.show() + return + + 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(): + # 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: + # 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: + E5MessageBox.information( + 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. + """ + if self.__findBackwards: + self.findPrevNext(True) + else: + self.findPrevNext(False) + + @pyqtSlot() + def on_replaceButton_clicked(self): + """ + Private slot to replace one occurrence of data. + """ + self.__doReplace(False) + + @pyqtSlot() + def on_replaceSearchButton_clicked(self): + """ + Private slot to replace one occurrence of data and search for the next + 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 + (boolean). + """ + # Check enabled status due to dual purpose usage of this method + if not self.__ui.replaceButton.isEnabled() and \ + not self.__ui.replaceSearchButton.isEnabled(): + return + + 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(rba), 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) + if idx >= 0: + self.__editor.replaceByteArray(idx, len(rba), rba) + idx += len(rba) + replacements += 1 + + if replacements: + E5MessageBox.information( + self, self.windowTitle(), + self.tr("Replaced {0} occurrences.") + .format(replacements)) + else: + E5MessageBox.information( + 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=''): + """ + Private method to display this widget in find mode. + + @param text text to be shown in the findtext edit (string) + """ + self.__replace = False + + self.__ui.findtextCombo.clear() + self.__ui.findtextCombo.addItems(self.__findHistory) + 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=''): + """ + Private slot to display this widget in replace mode. + + @param text text to be shown in the findtext edit + """ + self.__replace = True + + self.__ui.findtextCombo.clear() + self.__ui.findtextCombo.addItems(self.__findHistory) + self.__ui.findtextCombo.setEditText(text) + self.__ui.findtextCombo.lineEdit().selectAll() + self.__ui.findtextCombo.setFocus() + self.on_findtextCombo_editTextChanged(text) + + self.__ui.replacetextCombo.clear() + self.__ui.replacetextCombo.addItems(self.__replaceHistory) + self.__ui.replacetextCombo.setEditText('') + + self.__havefound = True + self.__findBackwards = False + + def show(self, text=''): + """ + Public slot to show the widget. + + @param text text to be shown in the findtext edit (string) + """ + if self.__replace: + self.__showReplace(text) + else: + self.__showFind(text) + super(HexEditSearchReplaceWidget, self).show() + self.activateWindow() + + @pyqtSlot() + def on_closeButton_clicked(self): + """ + Private slot to close the widget. + """ + self.__editor.setFocus(Qt.OtherFocusReason) + self.close() + + def keyPressEvent(self, event): + """ + Protected slot to handle key press events. + + @param event reference to the key press event (QKeyEvent) + """ + if event.key() == Qt.Key_Escape: + self.close()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HexEdit/HexEditSearchWidget.ui Sun Jan 10 16:52:22 2016 +0100 @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>HexEditSearchWidget</class> + <widget class="QWidget" name="HexEditSearchWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>27</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Find</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="leftMargin"> + <number>1</number> + </property> + <property name="topMargin"> + <number>1</number> + </property> + <property name="rightMargin"> + <number>1</number> + </property> + <property name="bottomMargin"> + <number>1</number> + </property> + <item> + <widget class="QToolButton" name="closeButton"> + <property name="toolTip"> + <string>Press to close the window</string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Find:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="findFormatCombo"> + <property name="toolTip"> + <string>Select the data format of the find data field</string> + </property> + <item> + <property name="text"> + <string>Hex</string> + </property> + </item> + <item> + <property name="text"> + <string>Text</string> + </property> + </item> + </widget> + </item> + <item> + <widget class="QComboBox" name="findtextCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>0</height> + </size> + </property> + <property name="editable"> + <bool>true</bool> + </property> + <property name="insertPolicy"> + <enum>QComboBox::InsertAtTop</enum> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="findPrevButton"> + <property name="toolTip"> + <string>Press to find the previous occurrence</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="findNextButton"> + <property name="toolTip"> + <string>Press to find the next occurrence</string> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>findtextCombo</tabstop> + <tabstop>findFormatCombo</tabstop> + <tabstop>findPrevButton</tabstop> + <tabstop>findNextButton</tabstop> + <tabstop>closeButton</tabstop> + </tabstops> + <resources/> + <connections/> +</ui>
--- a/HexEdit/HexEditWidget.py Sat Jan 09 19:44:31 2016 +0100 +++ b/HexEdit/HexEditWidget.py Sun Jan 10 16:52:22 2016 +0100 @@ -94,7 +94,7 @@ self.__readOnly = False # set read only mode on/off self.__cursorPosition = 0 - # absolute positioin of cursor, 1 Byte == 2 tics + # absolute position of cursor, 1 Byte == 2 tics self.__addrDigits = 0 self.__blink = True @@ -732,7 +732,7 @@ @return formatted representation of the selection @rtype str """ - byteArray = self.__chunks.data(self.__getSelectionBegin(), + byteArray = self.__chunks.data(self.getSelectionBegin(), self.__getSelectionLength()) return self.__toReadable(byteArray) @@ -1039,7 +1039,7 @@ """ if not self.__readOnly: byteArray = self.__toHex(self.__chunks.data( - self.__getSelectionBegin(), self.__getSelectionLength())) + self.getSelectionBegin(), self.__getSelectionLength())) idx = 32 while idx < len(byteArray): byteArray.insert(idx, "\n") @@ -1048,20 +1048,20 @@ cb.setText(byteArray.decode(encoding="latin1")) if self.__overwriteMode: length = self.__getSelectionLength() - self.replaceByteArray(self.__getSelectionBegin(), length, + self.replaceByteArray(self.getSelectionBegin(), length, bytearray(length)) else: - self.remove(self.__getSelectionBegin(), + self.remove(self.getSelectionBegin(), self.__getSelectionLength()) - self.setCursorPosition(2 * self.__getSelectionBegin()) - self.__resetSelection(2 * self.__getSelectionBegin()) + self.setCursorPosition(2 * self.getSelectionBegin()) + self.__resetSelection(2 * self.getSelectionBegin()) def copy(self): """ Public method to copy the selected bytes to the clipboard. """ byteArray = self.__toHex(self.__chunks.data( - self.__getSelectionBegin(), self.__getSelectionLength())) + self.getSelectionBegin(), self.__getSelectionLength())) idx = 32 while idx < len(byteArray): byteArray.insert(idx, "\n") @@ -1083,7 +1083,7 @@ self.insertByteArray(self.__bPosCurrent, byteArray) self.setCursorPosition( self.__cursorPosition + 2 * len(byteArray)) - self.__resetSelection(2 * self.__getSelectionBegin()) + self.__resetSelection(2 * self.getSelectionBegin()) def deleteByte(self): """ @@ -1091,7 +1091,7 @@ """ if not self.__readOnly: if self.hasSelection(): - self.__bPosCurrent = self.__getSelectionBegin() + self.__bPosCurrent = self.getSelectionBegin() if self.__overwriteMode: byteArray = bytearray(self.__getSelectionLength()) self.replaceByteArray(self.__bPosCurrent, len(byteArray), @@ -1113,7 +1113,7 @@ """ if not self.__readOnly: if self.hasSelection(): - self.__bPosCurrent = self.__getSelectionBegin() + self.__bPosCurrent = self.getSelectionBegin() self.setCursorPosition(2 * self.__bPosCurrent) if self.__overwriteMode: byteArray = bytearray(self.__getSelectionLength()) @@ -1222,12 +1222,12 @@ if self.__overwriteMode: length = self.__getSelectionLength() self.replaceByteArray( - self.__getSelectionBegin(), length, + self.getSelectionBegin(), length, bytearray(length)) else: - self.remove(self.__getSelectionBegin(), + self.remove(self.getSelectionBegin(), self.__getSelectionLength()) - self.__bPosCurrent = self.__getSelectionBegin() + self.__bPosCurrent = self.getSelectionBegin() self.setCursorPosition(2 * self.__bPosCurrent) self.__resetSelection(2 * self.__bPosCurrent) @@ -1349,8 +1349,8 @@ painter.setPen(colStandard) posBa = self.__bPosFirst + bPosLine + colIdx - if self.__getSelectionBegin() <= posBa and \ - self.__getSelectionEnd() > posBa: + if self.getSelectionBegin() <= posBa and \ + self.getSelectionEnd() > posBa: c = self.__selectionBrush.color() painter.setPen(self.__selectionPen) elif self.__highlighting: @@ -1478,18 +1478,18 @@ self.selectionAvailable.emit(True) - def __getSelectionBegin(self): + def getSelectionBegin(self): """ - Private method to get the start of the selection. + Public method to get the start of the selection. @return selection start @rtype int """ return self.__bSelectionBegin - def __getSelectionEnd(self): + def getSelectionEnd(self): """ - Private method to get the end of the selection. + Public method to get the end of the selection. @return selection end @rtype int
--- a/eric6.e4p Sat Jan 09 19:44:31 2016 +0100 +++ b/eric6.e4p Sun Jan 10 16:52:22 2016 +0100 @@ -468,6 +468,7 @@ <Source>Helpviewer/data/javascript_rc.py</Source> <Source>HexEdit/HexEditChunks.py</Source> <Source>HexEdit/HexEditMainWindow.py</Source> + <Source>HexEdit/HexEditSearchReplaceWidget.py</Source> <Source>HexEdit/HexEditUndoStack.py</Source> <Source>HexEdit/HexEditWidget.py</Source> <Source>HexEdit/__init__.py</Source> @@ -1370,6 +1371,8 @@ <Form>Helpviewer/WebPlugins/ClickToFlash/ClickToFlash.ui</Form> <Form>Helpviewer/WebPlugins/ClickToFlash/ClickToFlashWhitelistDialog.ui</Form> <Form>Helpviewer/ZoomManager/ZoomValuesDialog.ui</Form> + <Form>HexEdit/HexEditReplaceWidget.ui</Form> + <Form>HexEdit/HexEditSearchWidget.ui</Form> <Form>IconEditor/IconSizeDialog.ui</Form> <Form>MultiProject/AddProjectDialog.ui</Form> <Form>MultiProject/PropertiesDialog.ui</Form>