19 |
19 |
20 class HexEditSearchReplaceWidget(QWidget): |
20 class HexEditSearchReplaceWidget(QWidget): |
21 """ |
21 """ |
22 Class implementing a search and replace widget for the hex editor. |
22 Class implementing a search and replace widget for the hex editor. |
23 """ |
23 """ |
|
24 |
24 def __init__(self, editor, mainWindow, replace=False, parent=None): |
25 def __init__(self, editor, mainWindow, replace=False, parent=None): |
25 """ |
26 """ |
26 Constructor |
27 Constructor |
27 |
28 |
28 @param editor reference to the hex editor widget |
29 @param editor reference to the hex editor widget |
29 @type HexEditWidget |
30 @type HexEditWidget |
30 @param mainWindow reference to the main window |
31 @param mainWindow reference to the main window |
31 @type HexEditMainWindow |
32 @type HexEditMainWindow |
32 @param replace flag indicating a replace widget |
33 @param replace flag indicating a replace widget |
33 @type bool |
34 @type bool |
34 @param parent reference to the parent widget |
35 @param parent reference to the parent widget |
35 @type QWidget |
36 @type QWidget |
36 """ |
37 """ |
37 super().__init__(parent) |
38 super().__init__(parent) |
38 |
39 |
39 self.__replace = replace |
40 self.__replace = replace |
40 self.__editor = editor |
41 self.__editor = editor |
41 |
42 |
42 # keep this in sync with the logic in __getContent() |
43 # keep this in sync with the logic in __getContent() |
43 self.__formatAndValidators = { |
44 self.__formatAndValidators = { |
44 "hex": (self.tr("Hex"), QRegularExpressionValidator( |
45 "hex": ( |
45 QRegularExpression("[0-9a-f]*"))), |
46 self.tr("Hex"), |
46 "dec": (self.tr("Dec"), QRegularExpressionValidator( |
47 QRegularExpressionValidator(QRegularExpression("[0-9a-f]*")), |
47 QRegularExpression("[0-9]*"))), |
48 ), |
48 "oct": (self.tr("Oct"), QRegularExpressionValidator( |
49 "dec": ( |
49 QRegularExpression("[0-7]*"))), |
50 self.tr("Dec"), |
50 "bin": (self.tr("Bin"), QRegularExpressionValidator( |
51 QRegularExpressionValidator(QRegularExpression("[0-9]*")), |
51 QRegularExpression("[01]*"))), |
52 ), |
|
53 "oct": ( |
|
54 self.tr("Oct"), |
|
55 QRegularExpressionValidator(QRegularExpression("[0-7]*")), |
|
56 ), |
|
57 "bin": ( |
|
58 self.tr("Bin"), |
|
59 QRegularExpressionValidator(QRegularExpression("[01]*")), |
|
60 ), |
52 "iso-8859-1": (self.tr("Text"), None), |
61 "iso-8859-1": (self.tr("Text"), None), |
53 # text as latin-1/iso-8859-1 |
62 # text as latin-1/iso-8859-1 |
54 "utf-8": (self.tr("UTF-8"), None), |
63 "utf-8": (self.tr("UTF-8"), None), |
55 # text as utf-8 |
64 # text as utf-8 |
56 } |
65 } |
57 formatOrder = ["hex", "dec", "oct", "bin", "iso-8859-1", "utf-8"] |
66 formatOrder = ["hex", "dec", "oct", "bin", "iso-8859-1", "utf-8"] |
58 |
67 |
59 self.__currentFindFormat = "" |
68 self.__currentFindFormat = "" |
60 self.__currentReplaceFormat = "" |
69 self.__currentReplaceFormat = "" |
61 |
70 |
62 self.__findHistory = mainWindow.getSRHistory("search") |
71 self.__findHistory = mainWindow.getSRHistory("search") |
63 if replace: |
72 if replace: |
64 from .Ui_HexEditReplaceWidget import Ui_HexEditReplaceWidget |
73 from .Ui_HexEditReplaceWidget import Ui_HexEditReplaceWidget |
|
74 |
65 self.__replaceHistory = mainWindow.getSRHistory("replace") |
75 self.__replaceHistory = mainWindow.getSRHistory("replace") |
66 self.__ui = Ui_HexEditReplaceWidget() |
76 self.__ui = Ui_HexEditReplaceWidget() |
67 else: |
77 else: |
68 from .Ui_HexEditSearchWidget import Ui_HexEditSearchWidget |
78 from .Ui_HexEditSearchWidget import Ui_HexEditSearchWidget |
|
79 |
69 self.__ui = Ui_HexEditSearchWidget() |
80 self.__ui = Ui_HexEditSearchWidget() |
70 self.__ui.setupUi(self) |
81 self.__ui.setupUi(self) |
71 |
82 |
72 self.__ui.closeButton.setIcon(UI.PixmapCache.getIcon("close")) |
83 self.__ui.closeButton.setIcon(UI.PixmapCache.getIcon("close")) |
73 self.__ui.findPrevButton.setIcon( |
84 self.__ui.findPrevButton.setIcon(UI.PixmapCache.getIcon("1leftarrow")) |
74 UI.PixmapCache.getIcon("1leftarrow")) |
85 self.__ui.findNextButton.setIcon(UI.PixmapCache.getIcon("1rightarrow")) |
75 self.__ui.findNextButton.setIcon( |
86 |
76 UI.PixmapCache.getIcon("1rightarrow")) |
|
77 |
|
78 if replace: |
87 if replace: |
79 self.__ui.replaceButton.setIcon( |
88 self.__ui.replaceButton.setIcon(UI.PixmapCache.getIcon("editReplace")) |
80 UI.PixmapCache.getIcon("editReplace")) |
|
81 self.__ui.replaceSearchButton.setIcon( |
89 self.__ui.replaceSearchButton.setIcon( |
82 UI.PixmapCache.getIcon("editReplaceSearch")) |
90 UI.PixmapCache.getIcon("editReplaceSearch") |
83 self.__ui.replaceAllButton.setIcon( |
91 ) |
84 UI.PixmapCache.getIcon("editReplaceAll")) |
92 self.__ui.replaceAllButton.setIcon(UI.PixmapCache.getIcon("editReplaceAll")) |
85 |
93 |
86 for dataFormat in formatOrder: |
94 for dataFormat in formatOrder: |
87 formatStr, validator = self.__formatAndValidators[dataFormat] |
95 formatStr, validator = self.__formatAndValidators[dataFormat] |
88 self.__ui.findFormatCombo.addItem(formatStr, dataFormat) |
96 self.__ui.findFormatCombo.addItem(formatStr, dataFormat) |
89 if replace: |
97 if replace: |
90 for dataFormat in formatOrder: |
98 for dataFormat in formatOrder: |
91 formatStr, validator = self.__formatAndValidators[dataFormat] |
99 formatStr, validator = self.__formatAndValidators[dataFormat] |
92 self.__ui.replaceFormatCombo.addItem(formatStr, dataFormat) |
100 self.__ui.replaceFormatCombo.addItem(formatStr, dataFormat) |
93 |
101 |
94 self.__ui.findtextCombo.setCompleter(None) |
102 self.__ui.findtextCombo.setCompleter(None) |
95 self.__ui.findtextCombo.lineEdit().returnPressed.connect( |
103 self.__ui.findtextCombo.lineEdit().returnPressed.connect( |
96 self.__findByReturnPressed) |
104 self.__findByReturnPressed |
|
105 ) |
97 if replace: |
106 if replace: |
98 self.__ui.replacetextCombo.setCompleter(None) |
107 self.__ui.replacetextCombo.setCompleter(None) |
99 self.__ui.replacetextCombo.lineEdit().returnPressed.connect( |
108 self.__ui.replacetextCombo.lineEdit().returnPressed.connect( |
100 self.on_replaceButton_clicked) |
109 self.on_replaceButton_clicked |
101 |
110 ) |
|
111 |
102 self.findNextAct = EricAction( |
112 self.findNextAct = EricAction( |
103 self.tr('Find Next'), |
113 self.tr("Find Next"), |
104 self.tr('Find Next'), |
114 self.tr("Find Next"), |
105 0, 0, self, 'hexEditor_search_widget_find_next') |
115 0, |
|
116 0, |
|
117 self, |
|
118 "hexEditor_search_widget_find_next", |
|
119 ) |
106 self.findNextAct.triggered.connect(self.on_findNextButton_clicked) |
120 self.findNextAct.triggered.connect(self.on_findNextButton_clicked) |
107 self.findNextAct.setEnabled(False) |
121 self.findNextAct.setEnabled(False) |
108 self.__ui.findtextCombo.addAction(self.findNextAct) |
122 self.__ui.findtextCombo.addAction(self.findNextAct) |
109 |
123 |
110 self.findPrevAct = EricAction( |
124 self.findPrevAct = EricAction( |
111 self.tr('Find Prev'), |
125 self.tr("Find Prev"), |
112 self.tr('Find Prev'), |
126 self.tr("Find Prev"), |
113 0, 0, self, 'hexEditor_search_widget_find_prev') |
127 0, |
|
128 0, |
|
129 self, |
|
130 "hexEditor_search_widget_find_prev", |
|
131 ) |
114 self.findPrevAct.triggered.connect(self.on_findPrevButton_clicked) |
132 self.findPrevAct.triggered.connect(self.on_findPrevButton_clicked) |
115 self.findPrevAct.setEnabled(False) |
133 self.findPrevAct.setEnabled(False) |
116 self.__ui.findtextCombo.addAction(self.findPrevAct) |
134 self.__ui.findtextCombo.addAction(self.findPrevAct) |
117 |
135 |
118 self.__havefound = False |
136 self.__havefound = False |
119 |
137 |
120 @pyqtSlot(int) |
138 @pyqtSlot(int) |
121 def on_findFormatCombo_currentIndexChanged(self, idx): |
139 def on_findFormatCombo_currentIndexChanged(self, idx): |
122 """ |
140 """ |
123 Private slot to handle a selection from the find format. |
141 Private slot to handle a selection from the find format. |
124 |
142 |
125 @param idx index of the selected entry |
143 @param idx index of the selected entry |
126 @type int |
144 @type int |
127 """ |
145 """ |
128 if idx >= 0: |
146 if idx >= 0: |
129 findFormat = self.__ui.findFormatCombo.itemData(idx) |
147 findFormat = self.__ui.findFormatCombo.itemData(idx) |
130 |
148 |
131 if findFormat != self.__currentFindFormat: |
149 if findFormat != self.__currentFindFormat: |
132 txt = self.__ui.findtextCombo.currentText() |
150 txt = self.__ui.findtextCombo.currentText() |
133 newTxt = self.__convertText( |
151 newTxt = self.__convertText(txt, self.__currentFindFormat, findFormat) |
134 txt, self.__currentFindFormat, findFormat) |
|
135 self.__currentFindFormat = findFormat |
152 self.__currentFindFormat = findFormat |
136 |
153 |
137 self.__ui.findtextCombo.setValidator( |
154 self.__ui.findtextCombo.setValidator( |
138 self.__formatAndValidators[findFormat][1]) |
155 self.__formatAndValidators[findFormat][1] |
139 |
156 ) |
|
157 |
140 self.__ui.findtextCombo.setEditText(newTxt) |
158 self.__ui.findtextCombo.setEditText(newTxt) |
141 |
159 |
142 @pyqtSlot(str) |
160 @pyqtSlot(str) |
143 def on_findtextCombo_editTextChanged(self, txt): |
161 def on_findtextCombo_editTextChanged(self, txt): |
144 """ |
162 """ |
145 Private slot to enable/disable the find buttons. |
163 Private slot to enable/disable the find buttons. |
146 |
164 |
147 @param txt text of the find text combo |
165 @param txt text of the find text combo |
148 @type str |
166 @type str |
149 """ |
167 """ |
150 if not txt: |
168 if not txt: |
151 self.__ui.findNextButton.setEnabled(False) |
169 self.__ui.findNextButton.setEnabled(False) |
195 history = self.__replaceHistory |
213 history = self.__replaceHistory |
196 else: |
214 else: |
197 textCombo = self.__ui.findtextCombo |
215 textCombo = self.__ui.findtextCombo |
198 formatCombo = self.__ui.findFormatCombo |
216 formatCombo = self.__ui.findFormatCombo |
199 history = self.__findHistory |
217 history = self.__findHistory |
200 |
218 |
201 txt = textCombo.currentText() |
219 txt = textCombo.currentText() |
202 idx = formatCombo.currentIndex() |
220 idx = formatCombo.currentIndex() |
203 findFormat = formatCombo.itemData(idx) |
221 findFormat = formatCombo.itemData(idx) |
204 ba = self.__text2bytearray(txt, findFormat) |
222 ba = self.__text2bytearray(txt, findFormat) |
205 |
223 |
206 # This moves any previous occurrence of this statement to the head |
224 # This moves any previous occurrence of this statement to the head |
207 # of the list and updates the combobox |
225 # of the list and updates the combobox |
208 historyEntry = (idx, txt) |
226 historyEntry = (idx, txt) |
209 if historyEntry in history: |
227 if historyEntry in history: |
210 history.remove(historyEntry) |
228 history.remove(historyEntry) |
211 history.insert(0, historyEntry) |
229 history.insert(0, historyEntry) |
212 textCombo.clear() |
230 textCombo.clear() |
213 for index, text in history: |
231 for index, text in history: |
214 textCombo.addItem(text, index) |
232 textCombo.addItem(text, index) |
215 |
233 |
216 return ba, txt |
234 return ba, txt |
217 |
235 |
218 @pyqtSlot() |
236 @pyqtSlot() |
219 def on_findNextButton_clicked(self): |
237 def on_findNextButton_clicked(self): |
220 """ |
238 """ |
221 Private slot to find the next occurrence. |
239 Private slot to find the next occurrence. |
222 """ |
240 """ |
223 self.findPrevNext(False) |
241 self.findPrevNext(False) |
224 |
242 |
225 @pyqtSlot() |
243 @pyqtSlot() |
226 def on_findPrevButton_clicked(self): |
244 def on_findPrevButton_clicked(self): |
227 """ |
245 """ |
228 Private slot to find the previous occurrence. |
246 Private slot to find the previous occurrence. |
229 """ |
247 """ |
230 self.findPrevNext(True) |
248 self.findPrevNext(True) |
231 |
249 |
232 def findPrevNext(self, prev=False): |
250 def findPrevNext(self, prev=False): |
233 """ |
251 """ |
234 Public slot to find the next occurrence of the search term. |
252 Public slot to find the next occurrence of the search term. |
235 |
253 |
236 @param prev flag indicating a backwards search |
254 @param prev flag indicating a backwards search |
237 @type bool |
255 @type bool |
238 @return flag indicating a successful search |
256 @return flag indicating a successful search |
239 @rtype bool |
257 @rtype bool |
240 """ |
258 """ |
241 if not self.__havefound or not self.__ui.findtextCombo.currentText(): |
259 if not self.__havefound or not self.__ui.findtextCombo.currentText(): |
242 self.show() |
260 self.show() |
243 return False |
261 return False |
244 |
262 |
245 self.__findBackwards = prev |
263 self.__findBackwards = prev |
246 ba, txt = self.__getContent() |
264 ba, txt = self.__getContent() |
247 |
265 |
248 idx = -1 |
266 idx = -1 |
249 if len(ba) > 0: |
267 if len(ba) > 0: |
250 startIndex = self.__editor.cursorPosition() // 2 |
268 startIndex = self.__editor.cursorPosition() // 2 |
251 if prev: |
269 if prev: |
252 if ( |
270 if ( |
253 self.__editor.hasSelection() and |
271 self.__editor.hasSelection() |
254 startIndex == self.__editor.getSelectionEnd() |
272 and startIndex == self.__editor.getSelectionEnd() |
255 ): |
273 ): |
256 # skip to the selection start |
274 # skip to the selection start |
257 startIndex = self.__editor.getSelectionBegin() |
275 startIndex = self.__editor.getSelectionBegin() |
258 idx = self.__editor.lastIndexOf(ba, startIndex) |
276 idx = self.__editor.lastIndexOf(ba, startIndex) |
259 else: |
277 else: |
260 if ( |
278 if ( |
261 self.__editor.hasSelection() and |
279 self.__editor.hasSelection() |
262 startIndex == self.__editor.getSelectionBegin() - 1 |
280 and startIndex == self.__editor.getSelectionBegin() - 1 |
263 ): |
281 ): |
264 # skip to the selection end |
282 # skip to the selection end |
265 startIndex = self.__editor.getSelectionEnd() |
283 startIndex = self.__editor.getSelectionEnd() |
266 idx = self.__editor.indexOf(ba, startIndex) |
284 idx = self.__editor.indexOf(ba, startIndex) |
267 |
285 |
268 if idx >= 0: |
286 if idx >= 0: |
269 if self.__replace: |
287 if self.__replace: |
270 self.__ui.replaceButton.setEnabled(True) |
288 self.__ui.replaceButton.setEnabled(True) |
271 self.__ui.replaceSearchButton.setEnabled(True) |
289 self.__ui.replaceSearchButton.setEnabled(True) |
272 else: |
290 else: |
273 EricMessageBox.information( |
291 EricMessageBox.information( |
274 self, self.windowTitle(), |
292 self, self.windowTitle(), self.tr("'{0}' was not found.").format(txt) |
275 self.tr("'{0}' was not found.").format(txt)) |
293 ) |
276 |
294 |
277 return idx >= 0 |
295 return idx >= 0 |
278 |
296 |
279 def __findByReturnPressed(self): |
297 def __findByReturnPressed(self): |
280 """ |
298 """ |
281 Private slot to handle a return pressed in the find combo. |
299 Private slot to handle a return pressed in the find combo. |
282 """ |
300 """ |
283 if self.__findBackwards: |
301 if self.__findBackwards: |
284 self.findPrevNext(True) |
302 self.findPrevNext(True) |
285 else: |
303 else: |
286 self.findPrevNext(False) |
304 self.findPrevNext(False) |
287 |
305 |
288 @pyqtSlot(int) |
306 @pyqtSlot(int) |
289 def on_replaceFormatCombo_currentIndexChanged(self, idx): |
307 def on_replaceFormatCombo_currentIndexChanged(self, idx): |
290 """ |
308 """ |
291 Private slot to handle a selection from the replace format. |
309 Private slot to handle a selection from the replace format. |
292 |
310 |
293 @param idx index of the selected entry |
311 @param idx index of the selected entry |
294 @type int |
312 @type int |
295 """ |
313 """ |
296 if idx >= 0: |
314 if idx >= 0: |
297 replaceFormat = self.__ui.replaceFormatCombo.itemData(idx) |
315 replaceFormat = self.__ui.replaceFormatCombo.itemData(idx) |
298 |
316 |
299 if replaceFormat != self.__currentReplaceFormat: |
317 if replaceFormat != self.__currentReplaceFormat: |
300 txt = self.__ui.replacetextCombo.currentText() |
318 txt = self.__ui.replacetextCombo.currentText() |
301 newTxt = self.__convertText( |
319 newTxt = self.__convertText( |
302 txt, self.__currentReplaceFormat, replaceFormat) |
320 txt, self.__currentReplaceFormat, replaceFormat |
|
321 ) |
303 self.__currentReplaceFormat = replaceFormat |
322 self.__currentReplaceFormat = replaceFormat |
304 |
323 |
305 self.__ui.replacetextCombo.setValidator( |
324 self.__ui.replacetextCombo.setValidator( |
306 self.__formatAndValidators[replaceFormat][1]) |
325 self.__formatAndValidators[replaceFormat][1] |
307 |
326 ) |
|
327 |
308 self.__ui.replacetextCombo.setEditText(newTxt) |
328 self.__ui.replacetextCombo.setEditText(newTxt) |
309 |
329 |
310 @pyqtSlot(int) |
330 @pyqtSlot(int) |
311 def on_replacetextCombo_activated(self, idx): |
331 def on_replacetextCombo_activated(self, idx): |
312 """ |
332 """ |
313 Private slot to handle a selection from the replace history. |
333 Private slot to handle a selection from the replace history. |
314 |
334 |
315 @param idx index of the selected entry |
335 @param idx index of the selected entry |
316 @type int |
336 @type int |
317 """ |
337 """ |
318 if idx >= 0: |
338 if idx >= 0: |
319 formatIndex = self.__ui.replacetextCombo.itemData(idx) |
339 formatIndex = self.__ui.replacetextCombo.itemData(idx) |
324 def on_replaceButton_clicked(self): |
344 def on_replaceButton_clicked(self): |
325 """ |
345 """ |
326 Private slot to replace one occurrence of data. |
346 Private slot to replace one occurrence of data. |
327 """ |
347 """ |
328 self.__doReplace(False) |
348 self.__doReplace(False) |
329 |
349 |
330 @pyqtSlot() |
350 @pyqtSlot() |
331 def on_replaceSearchButton_clicked(self): |
351 def on_replaceSearchButton_clicked(self): |
332 """ |
352 """ |
333 Private slot to replace one occurrence of data and search for the next |
353 Private slot to replace one occurrence of data and search for the next |
334 one. |
354 one. |
335 """ |
355 """ |
336 self.__doReplace(True) |
356 self.__doReplace(True) |
337 |
357 |
338 def __doReplace(self, searchNext): |
358 def __doReplace(self, searchNext): |
339 """ |
359 """ |
340 Private method to replace one occurrence of data. |
360 Private method to replace one occurrence of data. |
341 |
361 |
342 @param searchNext flag indicating to search for the next occurrence |
362 @param searchNext flag indicating to search for the next occurrence |
343 @type bool |
363 @type bool |
344 """ |
364 """ |
345 # Check enabled status due to dual purpose usage of this method |
365 # Check enabled status due to dual purpose usage of this method |
346 if ( |
366 if ( |
347 not self.__ui.replaceButton.isEnabled() and |
367 not self.__ui.replaceButton.isEnabled() |
348 not self.__ui.replaceSearchButton.isEnabled() |
368 and not self.__ui.replaceSearchButton.isEnabled() |
349 ): |
369 ): |
350 return |
370 return |
351 |
371 |
352 fba, ftxt = self.__getContent(False) |
372 fba, ftxt = self.__getContent(False) |
353 rba, rtxt = self.__getContent(True) |
373 rba, rtxt = self.__getContent(True) |
354 |
374 |
355 ok = False |
375 ok = False |
356 if self.__editor.hasSelection(): |
376 if self.__editor.hasSelection(): |
357 # we did a successful search before |
377 # we did a successful search before |
358 startIdx = self.__editor.getSelectionBegin() |
378 startIdx = self.__editor.getSelectionBegin() |
359 self.__editor.replaceByteArray(startIdx, len(fba), rba) |
379 self.__editor.replaceByteArray(startIdx, len(fba), rba) |
360 |
380 |
361 if searchNext: |
381 if searchNext: |
362 ok = self.findPrevNext(self.__findBackwards) |
382 ok = self.findPrevNext(self.__findBackwards) |
363 |
383 |
364 if not ok: |
384 if not ok: |
365 self.__ui.replaceButton.setEnabled(False) |
385 self.__ui.replaceButton.setEnabled(False) |
366 self.__ui.replaceSearchButton.setEnabled(False) |
386 self.__ui.replaceSearchButton.setEnabled(False) |
367 |
387 |
368 @pyqtSlot() |
388 @pyqtSlot() |
369 def on_replaceAllButton_clicked(self): |
389 def on_replaceAllButton_clicked(self): |
370 """ |
390 """ |
371 Private slot to replace all occurrences of data. |
391 Private slot to replace all occurrences of data. |
372 """ |
392 """ |
373 replacements = 0 |
393 replacements = 0 |
374 |
394 |
375 cursorPosition = self.__editor.cursorPosition() |
395 cursorPosition = self.__editor.cursorPosition() |
376 |
396 |
377 fba, ftxt = self.__getContent(False) |
397 fba, ftxt = self.__getContent(False) |
378 rba, rtxt = self.__getContent(True) |
398 rba, rtxt = self.__getContent(True) |
379 |
399 |
380 idx = 0 |
400 idx = 0 |
381 while idx >= 0: |
401 while idx >= 0: |
382 idx = self.__editor.indexOf(fba, idx) |
402 idx = self.__editor.indexOf(fba, idx) |
383 if idx >= 0: |
403 if idx >= 0: |
384 self.__editor.replaceByteArray(idx, len(fba), rba) |
404 self.__editor.replaceByteArray(idx, len(fba), rba) |
385 idx += len(rba) |
405 idx += len(rba) |
386 replacements += 1 |
406 replacements += 1 |
387 |
407 |
388 if replacements: |
408 if replacements: |
389 EricMessageBox.information( |
409 EricMessageBox.information( |
390 self, self.windowTitle(), |
410 self, |
391 self.tr("Replaced {0} occurrences.") |
411 self.windowTitle(), |
392 .format(replacements)) |
412 self.tr("Replaced {0} occurrences.").format(replacements), |
|
413 ) |
393 else: |
414 else: |
394 EricMessageBox.information( |
415 EricMessageBox.information( |
395 self, self.windowTitle(), |
416 self, |
396 self.tr("Nothing replaced because '{0}' was not found.") |
417 self.windowTitle(), |
397 .format(ftxt)) |
418 self.tr("Nothing replaced because '{0}' was not found.").format(ftxt), |
398 |
419 ) |
|
420 |
399 self.__editor.setCursorPosition(cursorPosition) |
421 self.__editor.setCursorPosition(cursorPosition) |
400 self.__editor.ensureVisible() |
422 self.__editor.ensureVisible() |
401 |
423 |
402 def __showFind(self, text=''): |
424 def __showFind(self, text=""): |
403 """ |
425 """ |
404 Private method to display this widget in find mode. |
426 Private method to display this widget in find mode. |
405 |
427 |
406 @param text hex encoded text to be shown in the findtext edit |
428 @param text hex encoded text to be shown in the findtext edit |
407 @type str |
429 @type str |
408 """ |
430 """ |
409 self.__replace = False |
431 self.__replace = False |
410 |
432 |
411 self.__ui.findtextCombo.clear() |
433 self.__ui.findtextCombo.clear() |
412 for index, txt in self.__findHistory: |
434 for index, txt in self.__findHistory: |
413 self.__ui.findtextCombo.addItem(txt, index) |
435 self.__ui.findtextCombo.addItem(txt, index) |
414 self.__ui.findFormatCombo.setCurrentIndex(0) # 0 is always Hex |
436 self.__ui.findFormatCombo.setCurrentIndex(0) # 0 is always Hex |
415 self.on_findFormatCombo_currentIndexChanged(0) |
437 self.on_findFormatCombo_currentIndexChanged(0) |
416 self.__ui.findtextCombo.setEditText(text) |
438 self.__ui.findtextCombo.setEditText(text) |
417 self.__ui.findtextCombo.lineEdit().selectAll() |
439 self.__ui.findtextCombo.lineEdit().selectAll() |
418 self.__ui.findtextCombo.setFocus() |
440 self.__ui.findtextCombo.setFocus() |
419 self.on_findtextCombo_editTextChanged(text) |
441 self.on_findtextCombo_editTextChanged(text) |
420 |
442 |
421 self.__havefound = True |
443 self.__havefound = True |
422 self.__findBackwards = False |
444 self.__findBackwards = False |
423 |
445 |
424 def __showReplace(self, text=''): |
446 def __showReplace(self, text=""): |
425 """ |
447 """ |
426 Private slot to display this widget in replace mode. |
448 Private slot to display this widget in replace mode. |
427 |
449 |
428 @param text hex encoded text to be shown in the findtext edit |
450 @param text hex encoded text to be shown in the findtext edit |
429 @type str |
451 @type str |
430 """ |
452 """ |
431 self.__replace = True |
453 self.__replace = True |
432 |
454 |
433 self.__ui.findtextCombo.clear() |
455 self.__ui.findtextCombo.clear() |
434 for index, txt in self.__findHistory: |
456 for index, txt in self.__findHistory: |
435 self.__ui.findtextCombo.addItem(txt, index) |
457 self.__ui.findtextCombo.addItem(txt, index) |
436 self.__ui.findFormatCombo.setCurrentIndex(0) # 0 is always Hex |
458 self.__ui.findFormatCombo.setCurrentIndex(0) # 0 is always Hex |
437 self.on_findFormatCombo_currentIndexChanged(0) |
459 self.on_findFormatCombo_currentIndexChanged(0) |
438 self.__ui.findtextCombo.setEditText(text) |
460 self.__ui.findtextCombo.setEditText(text) |
439 self.__ui.findtextCombo.lineEdit().selectAll() |
461 self.__ui.findtextCombo.lineEdit().selectAll() |
440 self.__ui.findtextCombo.setFocus() |
462 self.__ui.findtextCombo.setFocus() |
441 self.on_findtextCombo_editTextChanged(text) |
463 self.on_findtextCombo_editTextChanged(text) |
442 |
464 |
443 self.__ui.replacetextCombo.clear() |
465 self.__ui.replacetextCombo.clear() |
444 for index, txt in self.__replaceHistory: |
466 for index, txt in self.__replaceHistory: |
445 self.__ui.replacetextCombo.addItem(txt, index) |
467 self.__ui.replacetextCombo.addItem(txt, index) |
446 self.__ui.replaceFormatCombo.setCurrentIndex(0) # 0 is always Hex |
468 self.__ui.replaceFormatCombo.setCurrentIndex(0) # 0 is always Hex |
447 self.on_replaceFormatCombo_currentIndexChanged(0) |
469 self.on_replaceFormatCombo_currentIndexChanged(0) |
448 self.__ui.replacetextCombo.setEditText('') |
470 self.__ui.replacetextCombo.setEditText("") |
449 |
471 |
450 self.__havefound = True |
472 self.__havefound = True |
451 self.__findBackwards = False |
473 self.__findBackwards = False |
452 |
474 |
453 def show(self, text=''): |
475 def show(self, text=""): |
454 """ |
476 """ |
455 Public slot to show the widget. |
477 Public slot to show the widget. |
456 |
478 |
457 @param text hex encoded text to be shown in the findtext edit |
479 @param text hex encoded text to be shown in the findtext edit |
458 @type str |
480 @type str |
459 """ |
481 """ |
460 if self.__replace: |
482 if self.__replace: |
461 self.__showReplace(text) |
483 self.__showReplace(text) |
462 else: |
484 else: |
463 self.__showFind(text) |
485 self.__showFind(text) |
464 super().show() |
486 super().show() |
465 self.activateWindow() |
487 self.activateWindow() |
466 |
488 |
467 @pyqtSlot() |
489 @pyqtSlot() |
468 def on_closeButton_clicked(self): |
490 def on_closeButton_clicked(self): |
469 """ |
491 """ |
470 Private slot to close the widget. |
492 Private slot to close the widget. |
471 """ |
493 """ |
496 @rtype str |
518 @rtype str |
497 """ |
519 """ |
498 if txt and oldFormat and newFormat and oldFormat != newFormat: |
520 if txt and oldFormat and newFormat and oldFormat != newFormat: |
499 # step 1: convert the text to a byte array using the old format |
521 # step 1: convert the text to a byte array using the old format |
500 byteArray = self.__text2bytearray(txt, oldFormat) |
522 byteArray = self.__text2bytearray(txt, oldFormat) |
501 |
523 |
502 # step 2: convert the byte array to text using the new format |
524 # step 2: convert the byte array to text using the new format |
503 txt = self.__bytearray2text(byteArray, newFormat) |
525 txt = self.__bytearray2text(byteArray, newFormat) |
504 |
526 |
505 return txt |
527 return txt |
506 |
528 |
507 def __int2bytearray(self, value): |
529 def __int2bytearray(self, value): |
508 """ |
530 """ |
509 Private method to convert an integer to a byte array. |
531 Private method to convert an integer to a byte array. |
510 |
532 |
511 @param value value to be converted |
533 @param value value to be converted |
512 @type int |
534 @type int |
513 @return byte array for the given value |
535 @return byte array for the given value |
514 @rtype bytearray |
536 @rtype bytearray |
515 """ |
537 """ |
516 ba = bytearray() |
538 ba = bytearray() |
517 while value > 0: |
539 while value > 0: |
518 value, modulus = divmod(value, 256) |
540 value, modulus = divmod(value, 256) |
519 ba.insert(0, modulus) |
541 ba.insert(0, modulus) |
520 |
542 |
521 return ba |
543 return ba |
522 |
544 |
523 def __bytearray2int(self, array): |
545 def __bytearray2int(self, array): |
524 """ |
546 """ |
525 Private method to convert a byte array to an integer value. |
547 Private method to convert a byte array to an integer value. |
526 |
548 |
527 @param array byte array to be converted |
549 @param array byte array to be converted |
528 @type bytearray |
550 @type bytearray |
529 @return integer value of the given array |
551 @return integer value of the given array |
530 @rtype int |
552 @rtype int |
531 """ |
553 """ |
532 value = 0 |
554 value = 0 |
533 for b in array: |
555 for b in array: |
534 value = value * 256 + b |
556 value = value * 256 + b |
535 |
557 |
536 return value |
558 return value |
537 |
559 |
538 def __text2bytearray(self, txt, dataFormat): |
560 def __text2bytearray(self, txt, dataFormat): |
539 """ |
561 """ |
540 Private method to convert a text to a byte array. |
562 Private method to convert a text to a byte array. |
541 |
563 |
542 @param txt text to be converted |
564 @param txt text to be converted |
543 @type str |
565 @type str |
544 @param dataFormat format of the text |
566 @param dataFormat format of the text |
545 @type str |
567 @type str |
546 @return converted text |
568 @return converted text |
548 @exception ValueError raised to indicate an invalid dataFormat |
570 @exception ValueError raised to indicate an invalid dataFormat |
549 parameter |
571 parameter |
550 """ |
572 """ |
551 if dataFormat not in self.__formatAndValidators.keys(): |
573 if dataFormat not in self.__formatAndValidators.keys(): |
552 raise ValueError("Bad value for 'dataFormat' parameter.") |
574 raise ValueError("Bad value for 'dataFormat' parameter.") |
553 |
575 |
554 if dataFormat == "hex": # hex format |
576 if dataFormat == "hex": # hex format |
555 ba = bytearray(QByteArray.fromHex( |
577 ba = bytearray(QByteArray.fromHex(bytes(txt, encoding="ascii"))) |
556 bytes(txt, encoding="ascii"))) |
578 elif dataFormat == "dec": # decimal format |
557 elif dataFormat == "dec": # decimal format |
|
558 ba = self.__int2bytearray(int(txt, 10)) |
579 ba = self.__int2bytearray(int(txt, 10)) |
559 elif dataFormat == "oct": # octal format |
580 elif dataFormat == "oct": # octal format |
560 ba = self.__int2bytearray(int(txt, 8)) |
581 ba = self.__int2bytearray(int(txt, 8)) |
561 elif dataFormat == "bin": # binary format |
582 elif dataFormat == "bin": # binary format |
562 ba = self.__int2bytearray(int(txt, 2)) |
583 ba = self.__int2bytearray(int(txt, 2)) |
563 elif dataFormat == "iso-8859-1": # latin-1/iso-8859-1 text |
584 elif dataFormat == "iso-8859-1": # latin-1/iso-8859-1 text |
564 ba = bytearray(txt, encoding="iso-8859-1") |
585 ba = bytearray(txt, encoding="iso-8859-1") |
565 elif dataFormat == "utf-8": # utf-8 text |
586 elif dataFormat == "utf-8": # utf-8 text |
566 ba = bytearray(txt, encoding="utf-8") |
587 ba = bytearray(txt, encoding="utf-8") |
567 |
588 |
568 return ba |
589 return ba |
569 |
590 |
570 def __bytearray2text(self, array, dataFormat): |
591 def __bytearray2text(self, array, dataFormat): |
571 """ |
592 """ |
572 Private method to convert a byte array to a text. |
593 Private method to convert a byte array to a text. |
573 |
594 |
574 @param array byte array to be converted |
595 @param array byte array to be converted |
575 @type bytearray |
596 @type bytearray |
576 @param dataFormat format of the text |
597 @param dataFormat format of the text |
577 @type str |
598 @type str |
578 @return formatted text |
599 @return formatted text |