eric6/HexEdit/HexEditMainWindow.py

branch
maintenance
changeset 8273
698ae46f40a4
parent 8176
31965986ecd1
parent 8265
0090cfa83159
equal deleted inserted replaced
8190:fb0ef164f536 8273:698ae46f40a4
6 """ 6 """
7 Module implementing the hex editor main window. 7 Module implementing the hex editor main window.
8 """ 8 """
9 9
10 import os 10 import os
11 import contextlib
11 12
12 from PyQt5.QtCore import ( 13 from PyQt5.QtCore import (
13 pyqtSignal, pyqtSlot, QFile, QFileInfo, QSize, QCoreApplication, QLocale 14 pyqtSignal, pyqtSlot, QFile, QFileInfo, QSize, QCoreApplication, QLocale
14 ) 15 )
15 from PyQt5.QtGui import QKeySequence 16 from PyQt5.QtGui import QKeySequence
55 @param parent parent widget of this window (QWidget) 56 @param parent parent widget of this window (QWidget)
56 @param fromEric flag indicating whether it was called from within 57 @param fromEric flag indicating whether it was called from within
57 eric (boolean) 58 eric (boolean)
58 @param project reference to the project object (Project) 59 @param project reference to the project object (Project)
59 """ 60 """
60 super(HexEditMainWindow, self).__init__(parent) 61 super().__init__(parent)
61 self.setObjectName("eric6_hex_editor") 62 self.setObjectName("eric6_hex_editor")
62 63
63 self.__srHistory = { 64 self.__srHistory = {
64 "search": [], 65 "search": [],
65 # list of recent searches (tuple of format type index and 66 # list of recent searches (tuple of format type index and
917 state = self.saveState() 918 state = self.saveState()
918 Preferences.setHexEditor("HexEditorState", state) 919 Preferences.setHexEditor("HexEditorState", state)
919 920
920 Preferences.setGeometry("HexEditorGeometry", self.saveGeometry()) 921 Preferences.setGeometry("HexEditorGeometry", self.saveGeometry())
921 922
922 try: 923 with contextlib.suppress(ValueError):
923 if self.__fromEric or len(self.__class__.windows) > 1: 924 if self.__fromEric or len(self.__class__.windows) > 1:
924 del self.__class__.windows[ 925 del self.__class__.windows[
925 self.__class__.windows.index(self)] 926 self.__class__.windows.index(self)]
926 except ValueError:
927 pass
928 927
929 if not self.__fromEric: 928 if not self.__fromEric:
930 Preferences.syncPreferences() 929 Preferences.syncPreferences()
931 930
932 self.__saveRecent() 931 self.__saveRecent()
938 937
939 def __openHexFileNewWindow(self): 938 def __openHexFileNewWindow(self):
940 """ 939 """
941 Private slot called to open a binary file in new hex editor window. 940 Private slot called to open a binary file in new hex editor window.
942 """ 941 """
943 if not self.__lastOpenPath: 942 if (
944 if self.__project and self.__project.isOpen(): 943 not self.__lastOpenPath and
945 self.__lastOpenPath = self.__project.getProjectPath() 944 self.__project is not None and
945 self.__project.isOpen()
946 ):
947 self.__lastOpenPath = self.__project.getProjectPath()
946 948
947 fileName = E5FileDialog.getOpenFileName( 949 fileName = E5FileDialog.getOpenFileName(
948 self, 950 self,
949 self.tr("Open binary file in new window"), 951 self.tr("Open binary file in new window"),
950 self.__lastOpenPath, 952 self.__lastOpenPath,
1010 def __openHexFile(self): 1012 def __openHexFile(self):
1011 """ 1013 """
1012 Private slot to open a binary file. 1014 Private slot to open a binary file.
1013 """ 1015 """
1014 if self.__maybeSave(): 1016 if self.__maybeSave():
1015 if not self.__lastOpenPath: 1017 if (
1016 if self.__project and self.__project.isOpen(): 1018 not self.__lastOpenPath and
1017 self.__lastOpenPath = self.__project.getProjectPath() 1019 self.__project is not None and
1020 self.__project.isOpen()
1021 ):
1022 self.__lastOpenPath = self.__project.getProjectPath()
1018 1023
1019 fileName = E5FileDialog.getOpenFileName( 1024 fileName = E5FileDialog.getOpenFileName(
1020 self, 1025 self,
1021 self.tr("Open binary file"), 1026 self.tr("Open binary file"),
1022 self.__lastOpenPath, 1027 self.__lastOpenPath,
1038 Private method to save a binary file. 1043 Private method to save a binary file.
1039 1044
1040 @return flag indicating success 1045 @return flag indicating success
1041 @rtype bool 1046 @rtype bool
1042 """ 1047 """
1043 if not self.__fileName: 1048 ok = (
1044 ok = self.__saveHexFileAs() 1049 self.__saveHexDataFile(self.__fileName)
1045 else: 1050 if self.__fileName else
1046 ok = self.__saveHexDataFile(self.__fileName) 1051 self.__saveHexFileAs()
1052 )
1047 1053
1048 if ok: 1054 if ok:
1049 self.__editor.undoStack().setClean() 1055 self.__editor.undoStack().setClean()
1050 1056
1051 return ok 1057 return ok
1055 Private method to save the data to a new file. 1061 Private method to save the data to a new file.
1056 1062
1057 @return flag indicating success 1063 @return flag indicating success
1058 @rtype bool 1064 @rtype bool
1059 """ 1065 """
1060 if not self.__lastSavePath: 1066 if (
1061 if self.__project and self.__project.isOpen(): 1067 not self.__lastSavePath and
1062 self.__lastSavePath = self.__project.getProjectPath() 1068 self.__project is not None and
1069 self.__project.isOpen()
1070 ):
1071 self.__lastSavePath = self.__project.getProjectPath()
1063 if not self.__lastSavePath and self.__lastOpenPath: 1072 if not self.__lastSavePath and self.__lastOpenPath:
1064 self.__lastSavePath = self.__lastOpenPath 1073 self.__lastSavePath = self.__lastOpenPath
1065 1074
1066 fileName = E5FileDialog.getSaveFileName( 1075 fileName = E5FileDialog.getSaveFileName(
1067 self, 1076 self,
1134 1143
1135 @param selectionOnly flag indicating to save the selection only 1144 @param selectionOnly flag indicating to save the selection only
1136 @type bool 1145 @type bool
1137 """ 1146 """
1138 savePath = self.__lastSavePath 1147 savePath = self.__lastSavePath
1139 if not savePath: 1148 if (
1140 if self.__project and self.__project.isOpen(): 1149 not savePath and
1141 savePath = self.__project.getProjectPath() 1150 self.__project is not None and
1151 self.__project.isOpen()
1152 ):
1153 savePath = self.__project.getProjectPath()
1142 if not savePath and self.__lastOpenPath: 1154 if not savePath and self.__lastOpenPath:
1143 savePath = self.__lastOpenPath 1155 savePath = self.__lastOpenPath
1144 1156
1145 fileName, selectedFilter = E5FileDialog.getSaveFileNameAndFilter( 1157 fileName, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
1146 self, 1158 self,
1173 self, self.tr("eric Hex Editor"), 1185 self, self.tr("eric Hex Editor"),
1174 self.tr("Cannot write file '{0}:\n{1}.") 1186 self.tr("Cannot write file '{0}:\n{1}.")
1175 .format(fileName, file.errorString())) 1187 .format(fileName, file.errorString()))
1176 return 1188 return
1177 1189
1178 if selectionOnly: 1190 readableData = (
1179 readableData = self.__editor.selectionToReadableString() 1191 self.__editor.selectionToReadableString()
1180 else: 1192 if selectionOnly else
1181 readableData = self.__editor.toReadableString() 1193 self.__editor.toReadableString()
1194 )
1182 res = file.write(readableData.encode("latin1")) != -1 1195 res = file.write(readableData.encode("latin1")) != -1
1183 file.close() 1196 file.close()
1184 1197
1185 if not res: 1198 if not res:
1186 E5MessageBox.warning( 1199 E5MessageBox.warning(
1222 """ 1235 """
1223 self.__fileName = fileName 1236 self.__fileName = fileName
1224 # insert filename into list of recently opened files 1237 # insert filename into list of recently opened files
1225 self.__addToRecentList(fileName) 1238 self.__addToRecentList(fileName)
1226 1239
1227 if not self.__fileName: 1240 shownName = (
1228 shownName = self.tr("Untitled") 1241 self.tr("Untitled")
1229 else: 1242 if not self.__fileName else
1230 shownName = self.__strippedName(self.__fileName) 1243 self.__strippedName(self.__fileName)
1244 )
1231 1245
1232 self.setWindowTitle(self.tr("{0}[*] - {1}") 1246 self.setWindowTitle(self.tr("{0}[*] - {1}")
1233 .format(shownName, self.tr("Hex Editor"))) 1247 .format(shownName, self.tr("Hex Editor")))
1234 1248
1235 self.setWindowModified(self.__editor.isModified()) 1249 self.setWindowModified(self.__editor.isModified())
1307 """ 1321 """
1308 Private method to handle the search action. 1322 Private method to handle the search action.
1309 """ 1323 """
1310 self.__replaceWidget.hide() 1324 self.__replaceWidget.hide()
1311 self.__gotoWidget.hide() 1325 self.__gotoWidget.hide()
1312 if self.__editor.hasSelection(): 1326 txt = (
1313 txt = self.__editor.selectionToHexString() 1327 self.__editor.selectionToHexString()
1314 else: 1328 if self.__editor.hasSelection() else
1315 txt = "" 1329 ""
1330 )
1316 self.__searchWidget.show(txt) 1331 self.__searchWidget.show(txt)
1317 1332
1318 def __replace(self): 1333 def __replace(self):
1319 """ 1334 """
1320 Private method to handle the replace action. 1335 Private method to handle the replace action.
1321 """ 1336 """
1322 self.__searchWidget.hide() 1337 self.__searchWidget.hide()
1323 self.__gotoWidget.hide() 1338 self.__gotoWidget.hide()
1324 if self.__editor.hasSelection(): 1339 txt = (
1325 txt = self.__editor.selectionToHexString() 1340 self.__editor.selectionToHexString()
1326 else: 1341 if self.__editor.hasSelection() else
1327 txt = "" 1342 ""
1343 )
1328 self.__replaceWidget.show(txt) 1344 self.__replaceWidget.show(txt)
1329 1345
1330 def __goto(self): 1346 def __goto(self):
1331 """ 1347 """
1332 Private method to handle the goto action. 1348 Private method to handle the goto action.
1363 1379
1364 def __showPreferences(self): 1380 def __showPreferences(self):
1365 """ 1381 """
1366 Private slot to set the preferences. 1382 Private slot to set the preferences.
1367 """ 1383 """
1368 from Preferences.ConfigurationDialog import ConfigurationDialog 1384 from Preferences.ConfigurationDialog import (
1385 ConfigurationDialog, ConfigurationMode
1386 )
1369 dlg = ConfigurationDialog( 1387 dlg = ConfigurationDialog(
1370 None, 'Configuration', True, fromEric=True, 1388 None, 'Configuration', True, fromEric=True,
1371 displayMode=ConfigurationDialog.HexEditorMode) 1389 displayMode=ConfigurationMode.HEXEDITORMODE)
1372 dlg.preferencesChanged.connect( 1390 dlg.preferencesChanged.connect(
1373 self.__preferencesChangedByLocalPreferencesDialog) 1391 self.__preferencesChangedByLocalPreferencesDialog)
1374 dlg.show() 1392 dlg.show()
1375 dlg.showConfigurationPageByName("hexEditorPage") 1393 dlg.showConfigurationPageByName("hexEditorPage")
1376 dlg.exec() 1394 dlg.exec()
1415 """ 1433 """
1416 self.__loadRecent() 1434 self.__loadRecent()
1417 1435
1418 self.__recentMenu.clear() 1436 self.__recentMenu.clear()
1419 1437
1420 idx = 1 1438 for idx, rs in enumerate(self.__recent, start=1):
1421 for rs in self.__recent: 1439 formatStr = '&{0:d}. {1}' if idx < 10 else '{0:d}. {1}'
1422 if idx < 10:
1423 formatStr = '&{0:d}. {1}'
1424 else:
1425 formatStr = '{0:d}. {1}'
1426 act = self.__recentMenu.addAction( 1440 act = self.__recentMenu.addAction(
1427 formatStr.format( 1441 formatStr.format(
1428 idx, 1442 idx,
1429 Utilities.compactPath( 1443 Utilities.compactPath(
1430 rs, HexEditMainWindow.maxMenuFilePathLen))) 1444 rs, HexEditMainWindow.maxMenuFilePathLen)))
1431 act.setData(rs) 1445 act.setData(rs)
1432 act.setEnabled(QFileInfo(rs).exists()) 1446 act.setEnabled(QFileInfo(rs).exists())
1433 idx += 1
1434 1447
1435 self.__recentMenu.addSeparator() 1448 self.__recentMenu.addSeparator()
1436 self.__recentMenu.addAction(self.tr('&Clear'), self.__clearRecent) 1449 self.__recentMenu.addAction(self.tr('&Clear'), self.__clearRecent)
1437 1450
1438 @pyqtSlot(QAction) 1451 @pyqtSlot(QAction)

eric ide

mercurial