6 """ |
6 """ |
7 Module implementing a search and replace widget for the hex editor. |
7 Module implementing a search and replace widget for the hex editor. |
8 """ |
8 """ |
9 |
9 |
10 from __future__ import unicode_literals |
10 from __future__ import unicode_literals |
|
11 try: |
|
12 str = unicode # __IGNORE_EXCEPTION__ |
|
13 except NameError: |
|
14 pass |
11 |
15 |
12 from PyQt5.QtCore import pyqtSlot, Qt, QByteArray, QRegExp |
16 from PyQt5.QtCore import pyqtSlot, Qt, QByteArray, QRegExp |
13 from PyQt5.QtGui import QRegExpValidator |
17 from PyQt5.QtGui import QRegExpValidator |
14 from PyQt5.QtWidgets import QWidget |
18 from PyQt5.QtWidgets import QWidget |
15 |
19 |
17 from E5Gui import E5MessageBox |
21 from E5Gui import E5MessageBox |
18 |
22 |
19 import UI.PixmapCache |
23 import UI.PixmapCache |
20 |
24 |
21 |
25 |
22 # TODO: change the text of the combo when the format changes |
|
23 class HexEditSearchReplaceWidget(QWidget): |
26 class HexEditSearchReplaceWidget(QWidget): |
24 """ |
27 """ |
25 Class implementing a search and replace widget for the hex editor. |
28 Class implementing a search and replace widget for the hex editor. |
26 """ |
29 """ |
27 def __init__(self, editor, mainWindow, replace=False, parent=None): |
30 def __init__(self, editor, mainWindow, replace=False, parent=None): |
46 self.__formatAndValidators = { |
49 self.__formatAndValidators = { |
47 "hex": (self.tr("Hex"), QRegExpValidator((QRegExp("[0-9a-f]*")))), |
50 "hex": (self.tr("Hex"), QRegExpValidator((QRegExp("[0-9a-f]*")))), |
48 "dec": (self.tr("Dec"), QRegExpValidator((QRegExp("[0-9]*")))), |
51 "dec": (self.tr("Dec"), QRegExpValidator((QRegExp("[0-9]*")))), |
49 "oct": (self.tr("Oct"), QRegExpValidator((QRegExp("[0-7]*")))), |
52 "oct": (self.tr("Oct"), QRegExpValidator((QRegExp("[0-7]*")))), |
50 "bin": (self.tr("Bin"), QRegExpValidator((QRegExp("[01]*")))), |
53 "bin": (self.tr("Bin"), QRegExpValidator((QRegExp("[01]*")))), |
51 "text": (self.tr("Text"), None), # text as latin-1 |
54 "iso-8859-1": (self.tr("Text"), None), |
52 "utf-8": (self.tr("UTF-8"), None), # text as utf-8 |
55 # text as latin-1/iso-8859-1 |
|
56 "utf-8": (self.tr("UTF-8"), None), |
|
57 # text as utf-8 |
53 } |
58 } |
54 formatOrder = ["hex", "dec", "oct", "bin", "text", "utf-8"] |
59 formatOrder = ["hex", "dec", "oct", "bin", "iso-8859-1", "utf-8"] |
55 |
60 |
56 self.__currentFindFormat = "" |
61 self.__currentFindFormat = "" |
57 self.__currentReplaceFormat = "" |
62 self.__currentReplaceFormat = "" |
58 |
63 |
59 self.__findHistory = mainWindow.getSRHistory("search") |
64 self.__findHistory = mainWindow.getSRHistory("search") |
196 history = self.__findHistory |
201 history = self.__findHistory |
197 |
202 |
198 txt = textCombo.currentText() |
203 txt = textCombo.currentText() |
199 idx = formatCombo.currentIndex() |
204 idx = formatCombo.currentIndex() |
200 format = formatCombo.itemData(idx) |
205 format = formatCombo.itemData(idx) |
201 if format == "hex": # hex format |
206 ba = self.__text2bytearray(txt, format) |
202 ba = bytearray(QByteArray.fromHex( |
|
203 bytes(txt, encoding="ascii"))) |
|
204 elif format == "dec": |
|
205 ba = self.__int2bytearray(int(txt, 10)) |
|
206 elif format == "oct": |
|
207 ba = self.__int2bytearray(int(txt, 8)) |
|
208 elif format == "bin": |
|
209 ba = self.__int2bytearray(int(txt, 2)) |
|
210 elif format == "text": |
|
211 ba = bytearray(txt, encoding="latin-1") |
|
212 elif format == "utf-8": |
|
213 ba = bytearray(txt, encoding="utf-8") |
|
214 else: |
|
215 ba = bytearray() |
|
216 |
207 |
217 # This moves any previous occurrence of this statement to the head |
208 # This moves any previous occurrence of this statement to the head |
218 # of the list and updates the combobox |
209 # of the list and updates the combobox |
219 historyEntry = (idx, txt) |
210 historyEntry = (idx, txt) |
220 if historyEntry in history: |
211 if historyEntry in history: |
498 @param newFormat format to convert to |
489 @param newFormat format to convert to |
499 @type str |
490 @type str |
500 @return converted text |
491 @return converted text |
501 @rtype str |
492 @rtype str |
502 """ |
493 """ |
503 # TODO: implement the conversion method |
494 if oldFormat and newFormat: |
|
495 # step 1: convert the text to a byte array using the old format |
|
496 byteArray = self.__text2bytearray(txt, oldFormat) |
|
497 |
|
498 # step 2: convert the byte array to text using the new format |
|
499 txt = self.__bytearray2text(byteArray, newFormat) |
|
500 |
504 return txt |
501 return txt |
505 |
502 |
506 def __int2bytearray(self, value): |
503 def __int2bytearray(self, value): |
507 """ |
504 """ |
508 Private method to convert an integer into a byte array. |
505 Private method to convert an integer to a byte array. |
509 |
506 |
510 @param value value to be converted |
507 @param value value to be converted |
511 @type int |
508 @type int |
512 @return byte array for the given value |
509 @return byte array for the given value |
513 @rtype bytearray |
510 @rtype bytearray |
531 value = 0 |
528 value = 0 |
532 for b in array: |
529 for b in array: |
533 value = value * 256 + b |
530 value = value * 256 + b |
534 |
531 |
535 return value |
532 return value |
|
533 |
|
534 def __text2bytearray(self, txt, format): |
|
535 """ |
|
536 Private method to convert a text to a byte array. |
|
537 |
|
538 @param txt text to be converted |
|
539 @type str |
|
540 @param format format of the text |
|
541 @type str |
|
542 @return converted text |
|
543 @rtype bytearray |
|
544 """ |
|
545 assert format in self.__formatAndValidators.keys() |
|
546 |
|
547 if format == "hex": # hex format |
|
548 ba = bytearray(QByteArray.fromHex( |
|
549 bytes(txt, encoding="ascii"))) |
|
550 elif format == "dec": # decimal format |
|
551 ba = self.__int2bytearray(int(txt, 10)) |
|
552 elif format == "oct": # octal format |
|
553 ba = self.__int2bytearray(int(txt, 8)) |
|
554 elif format == "bin": # binary format |
|
555 ba = self.__int2bytearray(int(txt, 2)) |
|
556 elif format == "iso-8859-1": # latin-1/iso-8859-1 text |
|
557 ba = bytearray(txt, encoding="iso-8859-1") |
|
558 elif format == "utf-8": # utf-8 text |
|
559 ba = bytearray(txt, encoding="utf-8") |
|
560 |
|
561 return ba |
|
562 |
|
563 def __bytearray2text(self, array, format): |
|
564 """ |
|
565 Private method to convert a byte array to a text. |
|
566 |
|
567 @param array byte array to be converted |
|
568 @type bytearray |
|
569 @param format format of the text |
|
570 @type str |
|
571 @return formatted text |
|
572 @rtype str |
|
573 """ |
|
574 assert format in self.__formatAndValidators.keys() |
|
575 |
|
576 if format == "hex": # hex format |
|
577 txt = "{0:x}".format(self.__bytearray2int(array)) |
|
578 elif format == "dec": # decimal format |
|
579 txt = "{0:d}".format(self.__bytearray2int(array)) |
|
580 elif format == "oct": # octal format |
|
581 txt = "{0:o}".format(self.__bytearray2int(array)) |
|
582 elif format == "bin": # binary format |
|
583 txt = "{0:b}".format(self.__bytearray2int(array)) |
|
584 elif format == "iso-8859-1": # latin-1/iso-8859-1 text |
|
585 txt = str(array, encoding="iso-8859-1") |
|
586 elif format == "utf-8": # utf-8 text |
|
587 txt = str(array, encoding="utf-8", errors="replace") |
|
588 |
|
589 return txt |