25 |
25 |
26 from eric7 import Preferences |
26 from eric7 import Preferences |
27 from eric7.EricGui import EricPixmapCache |
27 from eric7.EricGui import EricPixmapCache |
28 from eric7.EricGui.EricAction import EricAction |
28 from eric7.EricGui.EricAction import EricAction |
29 from eric7.EricWidgets import EricFileDialog, EricMessageBox |
29 from eric7.EricWidgets import EricFileDialog, EricMessageBox |
|
30 from eric7.EricWidgets.EricApplication import ericApp |
30 from eric7.EricWidgets.EricClickableLabel import EricClickableLabel |
31 from eric7.EricWidgets.EricClickableLabel import EricClickableLabel |
31 from eric7.EricWidgets.EricMainWindow import EricMainWindow |
32 from eric7.EricWidgets.EricMainWindow import EricMainWindow |
32 from eric7.Globals import recentNameHexFiles, strGroup |
33 from eric7.Globals import recentNameHexFiles, strGroup |
|
34 from eric7.RemoteServerInterface import EricServerFileDialog |
33 from eric7.SystemUtilities import FileSystemUtilities |
35 from eric7.SystemUtilities import FileSystemUtilities |
34 |
36 |
35 from .HexEditGotoWidget import HexEditGotoWidget |
37 from .HexEditGotoWidget import HexEditGotoWidget |
36 from .HexEditSearchReplaceWidget import HexEditSearchReplaceWidget |
38 from .HexEditSearchReplaceWidget import HexEditSearchReplaceWidget |
37 from .HexEditWidget import HexEditWidget |
39 from .HexEditWidget import HexEditWidget |
79 self.__fromEric = fromEric |
81 self.__fromEric = fromEric |
80 self.setWindowIcon(EricPixmapCache.getIcon("hexEditor")) |
82 self.setWindowIcon(EricPixmapCache.getIcon("hexEditor")) |
81 |
83 |
82 if not self.__fromEric: |
84 if not self.__fromEric: |
83 self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) |
85 self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) |
|
86 |
|
87 self.__remotefsInterface =( |
|
88 ericApp().getObject("EricServer").getServiceInterface("FileSystem") |
|
89 if self.__fromEric |
|
90 else None |
|
91 ) |
84 |
92 |
85 self.__editor = HexEditWidget() |
93 self.__editor = HexEditWidget() |
86 self.__searchWidget = HexEditSearchReplaceWidget(self.__editor, self, False) |
94 self.__searchWidget = HexEditSearchReplaceWidget(self.__editor, self, False) |
87 self.__replaceWidget = HexEditSearchReplaceWidget(self.__editor, self, True) |
95 self.__replaceWidget = HexEditSearchReplaceWidget(self.__editor, self, True) |
88 self.__gotoWidget = HexEditGotoWidget(self.__editor) |
96 self.__gotoWidget = HexEditGotoWidget(self.__editor) |
1054 and self.__project is not None |
1062 and self.__project is not None |
1055 and self.__project.isOpen() |
1063 and self.__project.isOpen() |
1056 ): |
1064 ): |
1057 self.__lastOpenPath = self.__project.getProjectPath() |
1065 self.__lastOpenPath = self.__project.getProjectPath() |
1058 |
1066 |
1059 fileName = EricFileDialog.getOpenFileName( |
1067 fileName = ( |
1060 self, |
1068 EricServerFileDialog.getOpenFileName( |
1061 self.tr("Open binary file in new window"), |
1069 self, |
1062 self.__lastOpenPath, |
1070 self.tr("Open binary file"), |
1063 self.tr("All Files (*)"), |
1071 self.__lastOpenPath, |
|
1072 self.tr("All Files (*)"), |
|
1073 ) |
|
1074 if FileSystemUtilities.isRemoteFileName(self.__lastOpenPath) |
|
1075 else EricFileDialog.getOpenFileName( |
|
1076 self, |
|
1077 self.tr("Open binary file in new window"), |
|
1078 self.__lastOpenPath, |
|
1079 self.tr("All Files (*)"), |
|
1080 ) |
1064 ) |
1081 ) |
1065 if fileName: |
1082 if fileName: |
1066 he = HexEditMainWindow( |
1083 he = HexEditMainWindow( |
1067 fileName=fileName, |
1084 fileName=fileName, |
1068 parent=self.parent(), |
1085 parent=self.parent(), |
1095 Private method to load a binary file. |
1112 Private method to load a binary file. |
1096 |
1113 |
1097 @param fileName name of the binary file to load |
1114 @param fileName name of the binary file to load |
1098 @type str |
1115 @type str |
1099 """ |
1116 """ |
1100 if not os.path.exists(fileName): |
|
1101 EricMessageBox.warning( |
|
1102 self, |
|
1103 self.tr("eric Hex Editor"), |
|
1104 self.tr("The file '{0}' does not exist.").format(fileName), |
|
1105 ) |
|
1106 return |
|
1107 |
|
1108 try: |
1117 try: |
1109 with open(fileName, "rb") as f: |
1118 if FileSystemUtilities.isRemoteFileName(fileName): |
1110 data = f.read() |
1119 data = self.__remotefsInterface.readFile(fileName) |
|
1120 else: |
|
1121 with open(fileName, "rb") as f: |
|
1122 data = f.read() |
1111 except OSError as err: |
1123 except OSError as err: |
1112 EricMessageBox.warning( |
1124 EricMessageBox.warning( |
1113 self, |
1125 self, |
1114 self.tr("eric Hex Editor"), |
1126 self.tr("eric Hex Editor"), |
1115 self.tr("<p>Cannot read file <b>{0}</b>.</p><p>Reason: {1}</p>").format( |
1127 self.tr("<p>Cannot read file <b>{0}</b>.</p><p>Reason: {1}</p>").format( |
1116 fileName, str(err) |
1128 fileName, str(err) |
1117 ), |
1129 ), |
1118 ) |
1130 ) |
1119 return |
1131 return |
1120 |
1132 |
1121 self.__lastOpenPath = os.path.dirname(fileName) |
1133 self.__lastOpenPath = ( |
|
1134 self.__remotefsInterface.dirname(fileName) |
|
1135 if FileSystemUtilities.isRemoteFileName(fileName) |
|
1136 else os.path.dirname(fileName) |
|
1137 ) |
1122 self.__editor.setData(data) |
1138 self.__editor.setData(data) |
1123 self.__setCurrentFile(fileName) |
1139 self.__setCurrentFile(fileName) |
1124 |
1140 |
1125 self.__editor.setReadOnly(Preferences.getHexEditor("OpenReadOnly")) |
1141 self.__editor.setReadOnly(Preferences.getHexEditor("OpenReadOnly")) |
1126 |
1142 |
1136 and self.__project is not None |
1152 and self.__project is not None |
1137 and self.__project.isOpen() |
1153 and self.__project.isOpen() |
1138 ): |
1154 ): |
1139 self.__lastOpenPath = self.__project.getProjectPath() |
1155 self.__lastOpenPath = self.__project.getProjectPath() |
1140 |
1156 |
1141 fileName = EricFileDialog.getOpenFileName( |
1157 fileName = ( |
1142 self, |
1158 EricServerFileDialog.getOpenFileName( |
1143 self.tr("Open binary file"), |
1159 self, |
1144 self.__lastOpenPath, |
1160 self.tr("Open binary file"), |
1145 self.tr("All Files (*)"), |
1161 self.__lastOpenPath, |
|
1162 self.tr("All Files (*)"), |
|
1163 ) |
|
1164 if FileSystemUtilities.isRemoteFileName(self.__lastOpenPath) |
|
1165 else EricFileDialog.getOpenFileName( |
|
1166 self, |
|
1167 self.tr("Open binary file"), |
|
1168 self.__lastOpenPath, |
|
1169 self.tr("All Files (*)"), |
|
1170 ) |
1146 ) |
1171 ) |
1147 if fileName: |
1172 if fileName: |
1148 self.__loadHexFile(fileName) |
1173 self.__loadHexFile(fileName) |
1149 self.__checkActions() |
1174 self.__checkActions() |
1150 |
1175 |
1188 ): |
1213 ): |
1189 self.__lastSavePath = self.__project.getProjectPath() |
1214 self.__lastSavePath = self.__project.getProjectPath() |
1190 if not self.__lastSavePath and self.__lastOpenPath: |
1215 if not self.__lastSavePath and self.__lastOpenPath: |
1191 self.__lastSavePath = self.__lastOpenPath |
1216 self.__lastSavePath = self.__lastOpenPath |
1192 |
1217 |
1193 fileName = EricFileDialog.getSaveFileName( |
1218 fileName = ( |
1194 self, |
1219 EricServerFileDialog.getSaveFileName( |
1195 self.tr("Save binary file"), |
1220 self, |
1196 self.__lastSavePath, |
1221 self.tr("Save binary file"), |
1197 self.tr("All Files (*)"), |
1222 self.__lastSavePath, |
1198 options=EricFileDialog.DontConfirmOverwrite, |
1223 self.tr("All Files (*)"), |
|
1224 ) |
|
1225 if FileSystemUtilities.isRemoteFileName(self.__lastSavePath) |
|
1226 else EricFileDialog.getSaveFileName( |
|
1227 self, |
|
1228 self.tr("Save binary file"), |
|
1229 self.__lastSavePath, |
|
1230 self.tr("All Files (*)"), |
|
1231 options=EricFileDialog.DontConfirmOverwrite, |
|
1232 ) |
1199 ) |
1233 ) |
1200 if not fileName: |
1234 if not fileName: |
1201 return False |
1235 return False |
1202 |
1236 |
1203 if pathlib.Path(fileName).exists(): |
1237 if ( |
|
1238 ( |
|
1239 FileSystemUtilities.isRemoteFileName(fileName) |
|
1240 and self.__remotefsInterface.exists(fileName) |
|
1241 ) |
|
1242 or ( |
|
1243 FileSystemUtilities.isPlainFileName(fileName) |
|
1244 and pathlib.Path(fileName).exists() |
|
1245 ) |
|
1246 ): |
1204 res = EricMessageBox.yesNo( |
1247 res = EricMessageBox.yesNo( |
1205 self, |
1248 self, |
1206 self.tr("Save binary file"), |
1249 self.tr("Save binary file"), |
1207 self.tr( |
1250 self.tr( |
1208 "<p>The file <b>{0}</b> already exists. Overwrite it?</p>" |
1251 "<p>The file <b>{0}</b> already exists. Overwrite it?</p>" |
1224 @type str |
1267 @type str |
1225 @return flag indicating success |
1268 @return flag indicating success |
1226 @rtype bool |
1269 @rtype bool |
1227 """ |
1270 """ |
1228 try: |
1271 try: |
1229 with open(fileName, "wb") as f: |
1272 data = self.__editor.data() |
1230 f.write(self.__editor.data()) |
1273 if FileSystemUtilities.isRemoteFileName(fileName): |
|
1274 self.__remotefsInterface.writeFile(fileName, data) |
|
1275 else: |
|
1276 with open(fileName, "wb") as f: |
|
1277 f.write(data) |
1231 except OSError as err: |
1278 except OSError as err: |
1232 EricMessageBox.warning( |
1279 EricMessageBox.warning( |
1233 self, |
1280 self, |
1234 self.tr("eric Hex Editor"), |
1281 self.tr("eric Hex Editor"), |
1235 self.tr( |
1282 self.tr( |
1259 if not savePath and self.__project is not None and self.__project.isOpen(): |
1306 if not savePath and self.__project is not None and self.__project.isOpen(): |
1260 savePath = self.__project.getProjectPath() |
1307 savePath = self.__project.getProjectPath() |
1261 if not savePath and self.__lastOpenPath: |
1308 if not savePath and self.__lastOpenPath: |
1262 savePath = self.__lastOpenPath |
1309 savePath = self.__lastOpenPath |
1263 |
1310 |
1264 fileName, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( |
1311 if FileSystemUtilities.isRemoteFileName(savePath): |
1265 self, |
1312 fileName, selectedFilter = EricServerFileDialog.getSaveFileNameAndFilter( |
1266 self.tr("Save to readable file"), |
1313 self, |
1267 savePath, |
1314 self.tr("Save to readable file"), |
1268 self.tr("Text Files (*.txt);;All Files (*)"), |
1315 savePath, |
1269 self.tr("Text Files (*.txt)"), |
1316 self.tr("Text Files (*.txt);;All Files (*)"), |
1270 EricFileDialog.DontConfirmOverwrite, |
1317 self.tr("Text Files (*.txt)"), |
1271 ) |
1318 ) |
1272 if not fileName: |
1319 if not fileName: |
1273 return |
1320 return |
1274 |
1321 |
1275 fpath = pathlib.Path(fileName) |
1322 ext = self.__remotefsInterface.splitext(fileName)[1] |
1276 if not fpath.suffix: |
1323 if not ext: |
1277 ex = selectedFilter.split("(*")[1].split(")")[0] |
1324 ex = selectedFilter.split("(*")[1].split(")")[0] |
1278 if ex: |
1325 if ex: |
1279 fpath = fpath.with_suffix(ex) |
1326 fileName += ex |
1280 if fpath.exists(): |
1327 fileExists = self.__remotefsInterface.exists(fileName) |
|
1328 else: |
|
1329 fileName, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( |
|
1330 self, |
|
1331 self.tr("Save to readable file"), |
|
1332 savePath, |
|
1333 self.tr("Text Files (*.txt);;All Files (*)"), |
|
1334 self.tr("Text Files (*.txt)"), |
|
1335 EricFileDialog.DontConfirmOverwrite, |
|
1336 ) |
|
1337 if not fileName: |
|
1338 return |
|
1339 |
|
1340 fpath = pathlib.Path(fileName) |
|
1341 if not fpath.suffix: |
|
1342 ex = selectedFilter.split("(*")[1].split(")")[0] |
|
1343 if ex: |
|
1344 fpath = fpath.with_suffix(ex) |
|
1345 fileExists = fpath.exists() |
|
1346 fileName = str(fpath) |
|
1347 |
|
1348 if fileExists: |
1281 res = EricMessageBox.yesNo( |
1349 res = EricMessageBox.yesNo( |
1282 self, |
1350 self, |
1283 self.tr("Save to readable file"), |
1351 self.tr("Save to readable file"), |
1284 self.tr( |
1352 self.tr( |
1285 "<p>The file <b>{0}</b> already exists. Overwrite it?</p>" |
1353 "<p>The file <b>{0}</b> already exists. Overwrite it?</p>" |
1286 ).format(fpath), |
1354 ).format(fileName), |
1287 icon=EricMessageBox.Warning, |
1355 icon=EricMessageBox.Warning, |
1288 ) |
1356 ) |
1289 if not res: |
1357 if not res: |
1290 return |
1358 return |
1291 |
1359 |
1293 self.__editor.selectionToReadableString() |
1361 self.__editor.selectionToReadableString() |
1294 if selectionOnly |
1362 if selectionOnly |
1295 else self.__editor.toReadableString() |
1363 else self.__editor.toReadableString() |
1296 ) |
1364 ) |
1297 try: |
1365 try: |
1298 with fpath.open("w", encoding="latin1") as f: |
1366 if FileSystemUtilities.isRemoteFileName(fileName): |
1299 f.write(readableData) |
1367 self.__remotefsInterface.writeFile( |
|
1368 fileName, readableData.encode("latin1") |
|
1369 ) |
|
1370 else: |
|
1371 with open(fileName, "w", encoding="latin1") as f: |
|
1372 f.write(readableData) |
1300 except OSError as err: |
1373 except OSError as err: |
1301 EricMessageBox.warning( |
1374 EricMessageBox.warning( |
1302 self, |
1375 self, |
1303 self.tr("eric Hex Editor"), |
1376 self.tr("eric Hex Editor"), |
1304 self.tr( |
1377 self.tr( |
1532 Private slot to set up the recent files menu. |
1605 Private slot to set up the recent files menu. |
1533 """ |
1606 """ |
1534 self.__loadRecent() |
1607 self.__loadRecent() |
1535 |
1608 |
1536 self.__recentMenu.clear() |
1609 self.__recentMenu.clear() |
|
1610 |
|
1611 connected = ( |
|
1612 self.__fromEric and ericApp().getObject("EricServer").isServerConnected() |
|
1613 ) |
1537 |
1614 |
1538 for idx, rs in enumerate(self.__recent, start=1): |
1615 for idx, rs in enumerate(self.__recent, start=1): |
1539 formatStr = "&{0:d}. {1}" if idx < 10 else "{0:d}. {1}" |
1616 formatStr = "&{0:d}. {1}" if idx < 10 else "{0:d}. {1}" |
1540 act = self.__recentMenu.addAction( |
1617 act = self.__recentMenu.addAction( |
1541 formatStr.format( |
1618 formatStr.format( |
1544 rs, HexEditMainWindow.maxMenuFilePathLen |
1621 rs, HexEditMainWindow.maxMenuFilePathLen |
1545 ), |
1622 ), |
1546 ) |
1623 ) |
1547 ) |
1624 ) |
1548 act.setData(rs) |
1625 act.setData(rs) |
1549 act.setEnabled(pathlib.Path(rs).exists()) |
1626 act.setEnabled( |
|
1627 (FileSystemUtilities.isRemoteFileName(rs) and connected) |
|
1628 or pathlib.Path(rs).exists() |
|
1629 ) |
1550 |
1630 |
1551 self.__recentMenu.addSeparator() |
1631 self.__recentMenu.addSeparator() |
1552 self.__recentMenu.addAction(self.tr("&Clear"), self.__clearRecent) |
1632 self.__recentMenu.addAction(self.tr("&Clear"), self.__clearRecent) |
1553 |
1633 |
1554 @pyqtSlot(QAction) |
1634 @pyqtSlot(QAction) |
1579 self.__recent = [] |
1659 self.__recent = [] |
1580 Preferences.Prefs.rsettings.sync() |
1660 Preferences.Prefs.rsettings.sync() |
1581 rs = Preferences.Prefs.rsettings.value(recentNameHexFiles) |
1661 rs = Preferences.Prefs.rsettings.value(recentNameHexFiles) |
1582 if rs is not None: |
1662 if rs is not None: |
1583 for f in Preferences.toList(rs): |
1663 for f in Preferences.toList(rs): |
1584 if pathlib.Path(f).exists(): |
1664 if FileSystemUtilities.isRemoteFileName(f) or pathlib.Path(f).exists(): |
1585 self.__recent.append(f) |
1665 self.__recent.append(f) |
1586 |
1666 |
1587 def __saveRecent(self): |
1667 def __saveRecent(self): |
1588 """ |
1668 """ |
1589 Private method to save the list of recently opened files. |
1669 Private method to save the list of recently opened files. |