eric7/Sessions/SessionFile.py

branch
eric7
changeset 8312
800c432b34c8
parent 8240
93b8a353c4bf
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a class representing the session JSON file.
8 """
9
10 import json
11 import time
12
13 from PyQt5.QtCore import QObject
14
15 from E5Gui import E5MessageBox
16 from E5Gui.E5OverrideCursor import E5OverridenCursor
17 from E5Gui.E5Application import e5App
18
19 import Preferences
20
21
22 class SessionFile(QObject):
23 """
24 Class representing the session JSON file.
25 """
26 def __init__(self, isGlobal: bool, parent: QObject = None):
27 """
28 Constructor
29
30 @param isGlobal flag indicating a file for a global session
31 @type bool
32 @param parent reference to the parent object (defaults to None)
33 @type QObject (optional)
34 """
35 super().__init__(parent)
36
37 self.__isGlobal = isGlobal
38
39 def writeFile(self, filename: str) -> bool:
40 """
41 Public method to write the session data to a session JSON file.
42
43 @param filename name of the session file
44 @type str
45 @return flag indicating a successful write
46 @rtype bool
47 """
48 # get references to objects we need
49 project = e5App().getObject("Project")
50 projectBrowser = e5App().getObject("ProjectBrowser")
51 multiProject = e5App().getObject("MultiProject")
52 vm = e5App().getObject("ViewManager")
53 dbg = e5App().getObject("DebugUI")
54 dbs = e5App().getObject("DebugServer")
55
56 # prepare the session data dictionary
57 # step 0: header
58 sessionDict = {}
59 sessionDict["header"] = {}
60 if not self.__isGlobal:
61 sessionDict["header"]["comment"] = (
62 "eric session file for project {0}"
63 .format(project.getProjectName())
64 )
65 sessionDict["header"]["warning"] = (
66 "This file was generated automatically, do not edit."
67 )
68
69 if Preferences.getProject("TimestampFile") or self.__isGlobal:
70 sessionDict["header"]["saved"] = (
71 time.strftime('%Y-%m-%d, %H:%M:%S')
72 )
73
74 # step 1: open multi project and project for global session
75 sessionDict["MultiProject"] = ""
76 sessionDict["Project"] = ""
77 if self.__isGlobal:
78 if multiProject.isOpen():
79 sessionDict["MultiProject"] = (
80 multiProject.getMultiProjectFile()
81 )
82 if project.isOpen():
83 sessionDict["Project"] = project.getProjectFile()
84
85 # step 2: all open (project) filenames and the active editor
86 if vm.canSplit():
87 sessionDict["ViewManagerSplits"] = {
88 "Count": vm.splitCount(),
89 "Orientation": vm.getSplitOrientation(),
90 }
91 else:
92 sessionDict["ViewManagerSplits"] = {
93 "Count": 0,
94 "Orientation": 1,
95 }
96
97 editorsDict = {} # remember editors by file name to detect clones
98 sessionDict["Editors"] = []
99 allOpenEditorLists = vm.getOpenEditorsForSession()
100 for splitIndex, openEditorList in enumerate(allOpenEditorLists):
101 for editorIndex, editor in enumerate(openEditorList):
102 fileName = editor.getFileName()
103 if self.__isGlobal or project.isProjectFile(fileName):
104 if fileName in editorsDict:
105 isClone = editorsDict[fileName].isClone(editor)
106 else:
107 isClone = False
108 editorsDict[fileName] = editor
109 editorDict = {
110 "Filename": fileName,
111 "Cursor": editor.getCursorPosition(),
112 "Folds": editor.contractedFolds(),
113 "Zoom": editor.getZoom(),
114 "Clone": isClone,
115 "Splitindex": splitIndex,
116 "Editorindex": editorIndex,
117 }
118 sessionDict["Editors"].append(editorDict)
119
120 aw = vm.getActiveName()
121 sessionDict["ActiveWindow"] = {}
122 if aw and (self.__isGlobal or project.isProjectFile(aw)):
123 ed = vm.getOpenEditor(aw)
124 sessionDict["ActiveWindow"] = {
125 "Filename": aw,
126 "Cursor": ed.getCursorPosition(),
127 }
128
129 # step 3: breakpoints
130 allBreaks = Preferences.getProject("SessionAllBreakpoints")
131 projectFiles = project.getSources(True)
132 bpModel = dbs.getBreakPointModel()
133 if self.__isGlobal or allBreaks:
134 sessionDict["Breakpoints"] = bpModel.getAllBreakpoints()
135 else:
136 sessionDict["Breakpoints"] = [
137 bp
138 for bp in bpModel.getAllBreakpoints()
139 if bp[0] in projectFiles
140 ]
141
142 # step 4: watch expressions
143 wpModel = dbs.getWatchPointModel()
144 sessionDict["Watchpoints"] = wpModel.getAllWatchpoints()
145
146 # step 5: debug info
147 if self.__isGlobal:
148 if len(dbg.argvHistory):
149 dbgCmdline = dbg.argvHistory[0]
150 else:
151 dbgCmdline = ""
152 if len(dbg.wdHistory):
153 dbgWd = dbg.wdHistory[0]
154 else:
155 dbgWd = ""
156 if len(dbg.envHistory):
157 dbgEnv = dbg.envHistory[0]
158 else:
159 dbgEnv = ""
160 if len(dbg.multiprocessNoDebugHistory):
161 dbgMultiprocessNoDebug = (
162 dbg.multiprocessNoDebugHistory[0]
163 )
164 else:
165 dbgMultiprocessNoDebug = ""
166 sessionDict["DebugInfo"] = {
167 "VirtualEnv": dbg.lastUsedVenvName,
168 "CommandLine": dbgCmdline,
169 "WorkingDirectory": dbgWd,
170 "Environment": dbgEnv,
171 "ReportExceptions": dbg.exceptions,
172 "Exceptions": dbg.excList,
173 "IgnoredExceptions": dbg.excIgnoreList,
174 "AutoClearShell": dbg.autoClearShell,
175 "TracePython": dbg.tracePython,
176 "AutoContinue": dbg.autoContinue,
177 "EnableMultiprocess": dbg.enableMultiprocess,
178 "MultiprocessNoDebug": dbgMultiprocessNoDebug,
179 "GlobalConfigOverride": dbg.overrideGlobalConfig,
180 }
181 else:
182 sessionDict["DebugInfo"] = {
183 "VirtualEnv": project.dbgVirtualEnv,
184 "CommandLine": project.dbgCmdline,
185 "WorkingDirectory": project.dbgWd,
186 "Environment": project.dbgEnv,
187 "ReportExceptions": project.dbgReportExceptions,
188 "Exceptions": project.dbgExcList,
189 "IgnoredExceptions": project.dbgExcIgnoreList,
190 "AutoClearShell": project.dbgAutoClearShell,
191 "TracePython": project.dbgTracePython,
192 "AutoContinue": project.dbgAutoContinue,
193 "EnableMultiprocess": project.dbgEnableMultiprocess,
194 "MultiprocessNoDebug": project.dbgMultiprocessNoDebug,
195 "GlobalConfigOverride": project.dbgGlobalConfigOverride,
196 }
197
198 # step 6: bookmarks
199 bookmarksList = []
200 for fileName in editorsDict:
201 if self.__isGlobal or project.isProjectFile(fileName):
202 editor = editorsDict[fileName]
203 bookmarks = editor.getBookmarks()
204 if bookmarks:
205 bookmarksList.append({
206 "Filename": fileName,
207 "Lines": bookmarks,
208 })
209 sessionDict["Bookmarks"] = bookmarksList
210
211 # step 7: state of the various project browsers
212 browsersList = []
213 for browserName in projectBrowser.getProjectBrowserNames():
214 expandedItems = (
215 projectBrowser.getProjectBrowser(browserName)
216 .getExpandedItemNames()
217 )
218 if expandedItems:
219 browsersList.append({
220 "Name": browserName,
221 "ExpandedItems": expandedItems,
222 })
223 sessionDict["ProjectBrowserStates"] = browsersList
224
225 try:
226 jsonString = json.dumps(sessionDict, indent=2)
227 with open(filename, "w") as f:
228 f.write(jsonString)
229 except (TypeError, OSError) as err:
230 with E5OverridenCursor():
231 E5MessageBox.critical(
232 None,
233 self.tr("Save Session"),
234 self.tr(
235 "<p>The session file <b>{0}</b> could not be"
236 " written.</p><p>Reason: {1}</p>"
237 ).format(filename, str(err))
238 )
239 return False
240
241 return True
242
243 def readFile(self, filename: str) -> bool:
244 """
245 Public method to read the session data from a session JSON file.
246
247 @param filename name of the project file
248 @type str
249 @return flag indicating a successful read
250 @rtype bool
251 """
252 try:
253 with open(filename, "r") as f:
254 jsonString = f.read()
255 sessionDict = json.loads(jsonString)
256 except (OSError, json.JSONDecodeError) as err:
257 E5MessageBox.critical(
258 None,
259 self.tr("Read Session"),
260 self.tr(
261 "<p>The session file <b>{0}</b> could not be read.</p>"
262 "<p>Reason: {1}</p>"
263 ).format(filename, str(err))
264 )
265 return False
266
267 # get references to objects we need
268 project = e5App().getObject("Project")
269 projectBrowser = e5App().getObject("ProjectBrowser")
270 multiProject = e5App().getObject("MultiProject")
271 vm = e5App().getObject("ViewManager")
272 dbg = e5App().getObject("DebugUI")
273 dbs = e5App().getObject("DebugServer")
274
275 # step 1: multi project and project
276 # =================================
277 if sessionDict["MultiProject"]:
278 multiProject.openMultiProject(sessionDict["MultiProject"], False)
279 if sessionDict["Project"]:
280 project.openProject(sessionDict["Project"], False)
281
282 # step 2: (project) filenames and the active editor
283 # =================================================
284 vm.setSplitOrientation(sessionDict["ViewManagerSplits"]["Orientation"])
285 vm.setSplitCount(sessionDict["ViewManagerSplits"]["Count"])
286
287 editorsDict = {}
288 for editorDict in sessionDict["Editors"]:
289 if editorDict["Clone"] and editorDict["Filename"] in editorsDict:
290 editor = editorsDict[editorDict["Filename"]]
291 ed = vm.newEditorView(
292 editorDict["Filename"], editor, editor.getFileType(),
293 indexes=(editorDict["Splitindex"],
294 editorDict["Editorindex"])
295 )
296 else:
297 ed = vm.openSourceFile(
298 editorDict["Filename"],
299 indexes=(editorDict["Splitindex"],
300 editorDict["Editorindex"])
301 )
302 editorsDict[editorDict["Filename"]] = ed
303 if ed is not None:
304 ed.zoomTo(editorDict["Zoom"])
305 if editorDict["Folds"]:
306 ed.recolor()
307 ed.setContractedFolds(editorDict["Folds"])
308 ed.setCursorPosition(*editorDict["Cursor"])
309
310 # step 3: breakpoints
311 # ===================
312 bpModel = dbs.getBreakPointModel()
313 bpModel.addBreakPoints(sessionDict["Breakpoints"])
314
315 # step 4: watch expressions
316 # =========================
317 wpModel = dbs.getWatchPointModel()
318 wpModel.addWatchPoints(sessionDict["Watchpoints"])
319
320 # step 5: debug info
321 # ==================
322 debugInfoDict = sessionDict["DebugInfo"]
323
324 # adjust for newer session types
325 if "GlobalConfigOverride" not in debugInfoDict:
326 debugInfoDict["GlobalConfigOverride"] = {
327 "enable": False,
328 "redirect": True,
329 }
330
331 dbg.lastUsedVenvName = debugInfoDict["VirtualEnv"]
332 dbg.setArgvHistory(debugInfoDict["CommandLine"])
333 dbg.setWdHistory(debugInfoDict["WorkingDirectory"])
334 dbg.setEnvHistory(debugInfoDict["Environment"])
335 dbg.setExceptionReporting(debugInfoDict["ReportExceptions"])
336 dbg.setExcList(debugInfoDict["Exceptions"])
337 dbg.setExcIgnoreList(debugInfoDict["IgnoredExceptions"])
338 dbg.setAutoClearShell(debugInfoDict["AutoClearShell"])
339 dbg.setTracePython(debugInfoDict["TracePython"])
340 dbg.setAutoContinue(debugInfoDict["AutoContinue"])
341 dbg.setEnableMultiprocess(debugInfoDict["EnableMultiprocess"])
342 dbg.setMultiprocessNoDebugHistory(debugInfoDict["MultiprocessNoDebug"])
343 dbg.setEnableGlobalConfigOverride(
344 debugInfoDict["GlobalConfigOverride"])
345 if not self.__isGlobal:
346 project.setDbgInfo(
347 debugInfoDict["VirtualEnv"],
348 debugInfoDict["CommandLine"],
349 debugInfoDict["WorkingDirectory"],
350 debugInfoDict["Environment"],
351 debugInfoDict["ReportExceptions"],
352 debugInfoDict["Exceptions"],
353 debugInfoDict["IgnoredExceptions"],
354 debugInfoDict["AutoClearShell"],
355 debugInfoDict["TracePython"],
356 debugInfoDict["AutoContinue"],
357 debugInfoDict["EnableMultiprocess"],
358 debugInfoDict["MultiprocessNoDebug"],
359 debugInfoDict["GlobalConfigOverride"],
360 )
361
362 # step 6: bookmarks
363 # =================
364 for bookmark in sessionDict["Bookmarks"]:
365 editor = vm.getOpenEditor(bookmark["Filename"])
366 if editor is not None:
367 for lineno in bookmark["Lines"]:
368 editor.toggleBookmark(lineno)
369
370 # step 7: state of the various project browsers
371 # =============================================
372 for browserState in sessionDict["ProjectBrowserStates"]:
373 browser = projectBrowser.getProjectBrowser(browserState["Name"])
374 if browser is not None:
375 browser.expandItemsByName(browserState["ExpandedItems"])
376
377 # step 8: active window
378 # =====================
379 if sessionDict["ActiveWindow"]:
380 vm.openFiles(sessionDict["ActiveWindow"]["Filename"])
381 ed = vm.getOpenEditor(sessionDict["ActiveWindow"]["Filename"])
382 if ed is not None:
383 ed.setCursorPosition(*sessionDict["ActiveWindow"]["Cursor"])
384 ed.ensureCursorVisible()
385
386 return True

eric ide

mercurial