17 from E5Gui import E5MessageBox |
17 from E5Gui import E5MessageBox |
18 |
18 |
19 import UI.PixmapCache |
19 import UI.PixmapCache |
20 |
20 |
21 |
21 |
22 # TODO: add more format types (Dec, Oct, Bin) |
|
23 # TODO: change the text of the combo when the format changes |
22 # TODO: change the text of the combo when the format changes |
24 class HexEditSearchReplaceWidget(QWidget): |
23 class HexEditSearchReplaceWidget(QWidget): |
25 """ |
24 """ |
26 Class implementing a search and replace widget for the hex editor. |
25 Class implementing a search and replace widget for the hex editor. |
27 """ |
26 """ |
44 self.__editor = editor |
43 self.__editor = editor |
45 |
44 |
46 # keep this in sync with the logic in __getContent() |
45 # keep this in sync with the logic in __getContent() |
47 self.__formatAndValidators = { |
46 self.__formatAndValidators = { |
48 "hex": (self.tr("Hex"), QRegExpValidator((QRegExp("[0-9a-f]*")))), |
47 "hex": (self.tr("Hex"), QRegExpValidator((QRegExp("[0-9a-f]*")))), |
|
48 "dec": (self.tr("Dec"), QRegExpValidator((QRegExp("[0-9]*")))), |
|
49 "oct": (self.tr("Oct"), QRegExpValidator((QRegExp("[0-7]*")))), |
|
50 "bin": (self.tr("Bin"), QRegExpValidator((QRegExp("[01]*")))), |
49 "text": (self.tr("Text"), None), # text as latin-1 |
51 "text": (self.tr("Text"), None), # text as latin-1 |
50 "utf-8": (self.tr("UTF-8"), None), # text as utf-8 |
52 "utf-8": (self.tr("UTF-8"), None), # text as utf-8 |
51 } |
53 } |
52 formatOrder = ["hex", "text", "utf-8"] |
54 formatOrder = ["hex", "dec", "oct", "bin", "text", "utf-8"] |
53 |
55 |
54 self.__currentFindFormat = "" |
56 self.__currentFindFormat = "" |
55 self.__currentReplaceFormat = "" |
57 self.__currentReplaceFormat = "" |
56 |
58 |
57 self.__findHistory = mainWindow.getSRHistory("search") |
59 self.__findHistory = mainWindow.getSRHistory("search") |
124 format = self.__ui.findFormatCombo.itemData(idx) |
126 format = self.__ui.findFormatCombo.itemData(idx) |
125 |
127 |
126 if format != self.__currentFindFormat: |
128 if format != self.__currentFindFormat: |
127 txt = self.__ui.findtextCombo.currentText() |
129 txt = self.__ui.findtextCombo.currentText() |
128 newTxt = self.__convertText( |
130 newTxt = self.__convertText( |
129 self.__currentFindFormat, format, txt) |
131 txt, self.__currentFindFormat, format) |
130 self.__currentFindFormat = format |
132 self.__currentFindFormat = format |
131 |
133 |
132 self.__ui.findtextCombo.setValidator( |
134 self.__ui.findtextCombo.setValidator( |
133 self.__formatAndValidators[format][1]) |
135 self.__formatAndValidators[format][1]) |
134 |
136 |
169 @param idx index of the selected entry |
171 @param idx index of the selected entry |
170 @type int |
172 @type int |
171 """ |
173 """ |
172 if idx >= 0: |
174 if idx >= 0: |
173 formatIndex = self.__ui.findtextCombo.itemData(idx) |
175 formatIndex = self.__ui.findtextCombo.itemData(idx) |
174 self.__ui.findFormatCombo.setCurrentIndex(formatIndex) |
176 if formatIndex is not None: |
|
177 self.__ui.findFormatCombo.setCurrentIndex(formatIndex) |
175 |
178 |
176 def __getContent(self, replace=False): |
179 def __getContent(self, replace=False): |
177 """ |
180 """ |
178 Private method to get the contents of the find/replace combo as |
181 Private method to get the contents of the find/replace combo as |
179 a bytearray. |
182 a bytearray. |
196 idx = formatCombo.currentIndex() |
199 idx = formatCombo.currentIndex() |
197 format = formatCombo.itemData(idx) |
200 format = formatCombo.itemData(idx) |
198 if format == "hex": # hex format |
201 if format == "hex": # hex format |
199 ba = bytearray(QByteArray.fromHex( |
202 ba = bytearray(QByteArray.fromHex( |
200 bytes(txt, encoding="ascii"))) |
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)) |
201 elif format == "text": |
210 elif format == "text": |
202 ba = bytearray(txt, encoding="latin-1") |
211 ba = bytearray(txt, encoding="latin-1") |
203 elif format == "utf-8": |
212 elif format == "utf-8": |
204 ba = bytearray(txt, encoding="utf-8") |
213 ba = bytearray(txt, encoding="utf-8") |
205 else: |
214 else: |
291 @param idx index of the selected entry |
300 @param idx index of the selected entry |
292 @type int |
301 @type int |
293 """ |
302 """ |
294 if idx >= 0: |
303 if idx >= 0: |
295 format = self.__ui.replaceFormatCombo.itemData(idx) |
304 format = self.__ui.replaceFormatCombo.itemData(idx) |
296 self.__ui.replacetextCombo.setValidator( |
305 |
297 self.__formatAndValidators[format][1]) |
306 if format != self.__currentReplaceFormat: |
|
307 txt = self.__ui.replacetextCombo.currentText() |
|
308 newTxt = self.__convertText( |
|
309 txt, self.__currentReplaceFormat, format) |
|
310 self.__currentReplaceFormat = format |
|
311 |
|
312 self.__ui.replacetextCombo.setValidator( |
|
313 self.__formatAndValidators[format][1]) |
|
314 |
|
315 self.__ui.replacetextCombo.setEditText(newTxt) |
298 |
316 |
299 @pyqtSlot(int) |
317 @pyqtSlot(int) |
300 def on_replacetextCombo_activated(self, idx): |
318 def on_replacetextCombo_activated(self, idx): |
301 """ |
319 """ |
302 Private slot to handle a selection from the replace history. |
320 Private slot to handle a selection from the replace history. |
304 @param idx index of the selected entry |
322 @param idx index of the selected entry |
305 @type int |
323 @type int |
306 """ |
324 """ |
307 if idx >= 0: |
325 if idx >= 0: |
308 formatIndex = self.__ui.replacetextCombo.itemData(idx) |
326 formatIndex = self.__ui.replacetextCombo.itemData(idx) |
309 self.__ui.replaceFormatCombo.setCurrentIndex(formatIndex) |
327 if formatIndex is not None: |
|
328 self.__ui.replaceFormatCombo.setCurrentIndex(formatIndex) |
310 |
329 |
311 @pyqtSlot() |
330 @pyqtSlot() |
312 def on_replaceButton_clicked(self): |
331 def on_replaceButton_clicked(self): |
313 """ |
332 """ |
314 Private slot to replace one occurrence of data. |
333 Private slot to replace one occurrence of data. |
466 @type QKeyEvent |
485 @type QKeyEvent |
467 """ |
486 """ |
468 if event.key() == Qt.Key_Escape: |
487 if event.key() == Qt.Key_Escape: |
469 self.close() |
488 self.close() |
470 |
489 |
471 def __convertText(self, oldFormat, newFormat, txt): |
490 def __convertText(self, txt, oldFormat, newFormat): |
472 """ |
491 """ |
473 Private method to convert text from one format into another. |
492 Private method to convert text from one format into another. |
474 |
493 |
|
494 @param txt text to be converted |
|
495 @type str |
475 @param oldFormat current format of the text |
496 @param oldFormat current format of the text |
476 @type str |
497 @type str |
477 @param newFormat format to convert to |
498 @param newFormat format to convert to |
478 @type str |
|
479 @param txt text to be converted |
|
480 @type str |
499 @type str |
481 @return converted text |
500 @return converted text |
482 @rtype str |
501 @rtype str |
483 """ |
502 """ |
484 # TODO: implement the conversion method |
503 # TODO: implement the conversion method |
485 return txt |
504 return txt |
|
505 |
|
506 def __int2bytearray(self, value): |
|
507 """ |
|
508 Private method to convert an integer into a byte array. |
|
509 |
|
510 @param value value to be converted |
|
511 @type int |
|
512 @return byte array for the given value |
|
513 @rtype bytearray |
|
514 """ |
|
515 ba = bytearray() |
|
516 while value > 0: |
|
517 value, modulus = divmod(value, 256) |
|
518 ba.insert(0, modulus) |
|
519 |
|
520 return ba |
|
521 |
|
522 def __bytearray2int(self, array): |
|
523 """ |
|
524 Private method to convert a byte array to an integer value. |
|
525 |
|
526 @param array byte array to be converted |
|
527 @type bytearray |
|
528 @return integer value of the given array |
|
529 @rtype int |
|
530 """ |
|
531 value = 0 |
|
532 for b in array: |
|
533 value = value * 256 + b |
|
534 |
|
535 return value |