1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2004 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the writer class for writing an XML session file. |
|
8 """ |
|
9 |
|
10 import time |
|
11 |
|
12 from E5Gui.E5Application import e5App |
|
13 |
|
14 from .XMLStreamWriterBase import XMLStreamWriterBase |
|
15 from .Config import sessionFileFormatVersion |
|
16 |
|
17 import Preferences |
|
18 |
|
19 |
|
20 class SessionWriter(XMLStreamWriterBase): |
|
21 """ |
|
22 Class implementing the writer class for writing an XML session file. |
|
23 """ |
|
24 def __init__(self, device, projectName): |
|
25 """ |
|
26 Constructor |
|
27 |
|
28 @param device reference to the I/O device to write to |
|
29 @type QIODevice |
|
30 @param projectName name of the project or None for the |
|
31 global session |
|
32 @type str or None |
|
33 """ |
|
34 XMLStreamWriterBase.__init__(self, device) |
|
35 |
|
36 self.name = projectName |
|
37 self.project = e5App().getObject("Project") |
|
38 self.projectBrowser = e5App().getObject("ProjectBrowser") |
|
39 self.multiProject = e5App().getObject("MultiProject") |
|
40 self.vm = e5App().getObject("ViewManager") |
|
41 self.dbg = e5App().getObject("DebugUI") |
|
42 self.dbs = e5App().getObject("DebugServer") |
|
43 |
|
44 def writeXML(self): |
|
45 """ |
|
46 Public method to write the XML to the file. |
|
47 """ |
|
48 isGlobal = self.name is None |
|
49 |
|
50 XMLStreamWriterBase.writeXML(self) |
|
51 |
|
52 self.writeDTD('<!DOCTYPE Session SYSTEM "Session-{0}.dtd">'.format( |
|
53 sessionFileFormatVersion)) |
|
54 |
|
55 # add some generation comments |
|
56 if not isGlobal: |
|
57 self.writeComment( |
|
58 " eric session file for project {0} ".format(self.name)) |
|
59 self.writeComment( |
|
60 " This file was generated automatically, do not edit. ") |
|
61 if Preferences.getProject("TimestampFile") or isGlobal: |
|
62 self.writeComment( |
|
63 " Saved: {0} ".format(time.strftime('%Y-%m-%d, %H:%M:%S'))) |
|
64 |
|
65 # add the main tag |
|
66 self.writeStartElement("Session") |
|
67 self.writeAttribute("version", sessionFileFormatVersion) |
|
68 |
|
69 # step 0: save open multi project and project for the global session |
|
70 if isGlobal: |
|
71 if self.multiProject.isOpen(): |
|
72 self.writeTextElement( |
|
73 "MultiProject", self.multiProject.getMultiProjectFile()) |
|
74 if self.project.isOpen(): |
|
75 self.writeTextElement("Project", self.project.getProjectFile()) |
|
76 |
|
77 # step 1: save all open (project) filenames and the active window |
|
78 if self.vm.canSplit(): |
|
79 self.writeEmptyElement("ViewManagerSplits") |
|
80 self.writeAttribute("count", str(self.vm.splitCount())) |
|
81 self.writeAttribute("orientation", |
|
82 str(self.vm.getSplitOrientation())) |
|
83 |
|
84 allOpenEditorLists = self.vm.getOpenEditorsForSession() |
|
85 editorDict = {} # remember editors by file name to detect clones |
|
86 self.writeStartElement("Filenames") |
|
87 for splitIndex, openEditorList in enumerate(allOpenEditorLists): |
|
88 for editorIndex, editor in enumerate(openEditorList): |
|
89 fileName = editor.getFileName() |
|
90 if isGlobal or self.project.isProjectFile(fileName): |
|
91 line, index = editor.getCursorPosition() |
|
92 folds = ','.join( |
|
93 [str(i + 1) for i in editor.contractedFolds()]) |
|
94 zoom = editor.getZoom() |
|
95 if fileName in editorDict: |
|
96 isClone = int(editorDict[fileName].isClone(editor)) |
|
97 else: |
|
98 isClone = 0 |
|
99 editorDict[fileName] = editor |
|
100 self.writeStartElement("Filename") |
|
101 self.writeAttribute("cline", str(line)) |
|
102 self.writeAttribute("cindex", str(index)) |
|
103 self.writeAttribute("folds", folds) |
|
104 self.writeAttribute("zoom", str(zoom)) |
|
105 self.writeAttribute("cloned", str(isClone)) |
|
106 self.writeAttribute("splitindex", str(splitIndex)) |
|
107 self.writeAttribute("editorindex", str(editorIndex)) |
|
108 self.writeCharacters(fileName) |
|
109 self.writeEndElement() |
|
110 self.writeEndElement() |
|
111 |
|
112 aw = self.vm.getActiveName() |
|
113 if aw and (isGlobal or self.project.isProjectFile(aw)): |
|
114 ed = self.vm.getOpenEditor(aw) |
|
115 line, index = ed.getCursorPosition() |
|
116 self.writeStartElement("ActiveWindow") |
|
117 self.writeAttribute("cline", str(line)) |
|
118 self.writeAttribute("cindex", str(index)) |
|
119 self.writeCharacters(aw) |
|
120 self.writeEndElement() |
|
121 |
|
122 # step 2a: save all breakpoints |
|
123 allBreaks = Preferences.getProject("SessionAllBreakpoints") |
|
124 projectFiles = self.project.getSources(True) |
|
125 bpModel = self.dbs.getBreakPointModel() |
|
126 self.writeStartElement("Breakpoints") |
|
127 for row in range(bpModel.rowCount()): |
|
128 index = bpModel.index(row, 0) |
|
129 fname, lineno, cond, temp, enabled, count = ( |
|
130 bpModel.getBreakPointByIndex(index)[:6] |
|
131 ) |
|
132 if isGlobal or allBreaks or fname in projectFiles: |
|
133 self.writeStartElement("Breakpoint") |
|
134 self.writeTextElement("BpFilename", fname) |
|
135 self.writeEmptyElement("Linenumber") |
|
136 self.writeAttribute("value", str(lineno)) |
|
137 self.writeTextElement("Condition", str(cond)) |
|
138 self.writeEmptyElement("Temporary") |
|
139 self.writeAttribute("value", str(temp)) |
|
140 self.writeEmptyElement("Enabled") |
|
141 self.writeAttribute("value", str(enabled)) |
|
142 self.writeEmptyElement("Count") |
|
143 self.writeAttribute("value", str(count)) |
|
144 self.writeEndElement() |
|
145 self.writeEndElement() |
|
146 |
|
147 # step 2b: save all watch expressions |
|
148 self.writeStartElement("Watchexpressions") |
|
149 wpModel = self.dbs.getWatchPointModel() |
|
150 for row in range(wpModel.rowCount()): |
|
151 index = wpModel.index(row, 0) |
|
152 cond, special, temp, enabled, count = ( |
|
153 wpModel.getWatchPointByIndex(index)[:5] |
|
154 ) |
|
155 self.writeStartElement("Watchexpression") |
|
156 self.writeTextElement("Condition", str(cond)) |
|
157 self.writeEmptyElement("Temporary") |
|
158 self.writeAttribute("value", str(temp)) |
|
159 self.writeEmptyElement("Enabled") |
|
160 self.writeAttribute("value", str(enabled)) |
|
161 self.writeEmptyElement("Count") |
|
162 self.writeAttribute("value", str(count)) |
|
163 self.writeTextElement("Special", special) |
|
164 self.writeEndElement() |
|
165 self.writeEndElement() |
|
166 |
|
167 # step 3: save the debug info |
|
168 self.writeStartElement("DebugInfo") |
|
169 if isGlobal: |
|
170 if len(self.dbg.argvHistory): |
|
171 dbgCmdline = str(self.dbg.argvHistory[0]) |
|
172 else: |
|
173 dbgCmdline = "" |
|
174 if len(self.dbg.wdHistory): |
|
175 dbgWd = self.dbg.wdHistory[0] |
|
176 else: |
|
177 dbgWd = "" |
|
178 if len(self.dbg.envHistory): |
|
179 dbgEnv = self.dbg.envHistory[0] |
|
180 else: |
|
181 dbgEnv = "" |
|
182 if len(self.dbg.multiprocessNoDebugHistory): |
|
183 dbgMultiprocessNoDebug = self.dbg.multiprocessNoDebugHistory[0] |
|
184 else: |
|
185 dbgMultiprocessNoDebug = "" |
|
186 |
|
187 self.writeTextElement("VirtualEnv", self.dbg.lastUsedVenvName) |
|
188 self.writeTextElement("CommandLine", dbgCmdline) |
|
189 self.writeTextElement("WorkingDirectory", dbgWd) |
|
190 self.writeTextElement("Environment", dbgEnv) |
|
191 self.writeEmptyElement("ReportExceptions") |
|
192 self.writeAttribute("value", str(self.dbg.exceptions)) |
|
193 self.writeStartElement("Exceptions") |
|
194 for exc in self.dbg.excList: |
|
195 self.writeTextElement("Exception", exc) |
|
196 self.writeEndElement() |
|
197 self.writeStartElement("IgnoredExceptions") |
|
198 for iexc in self.dbg.excIgnoreList: |
|
199 self.writeTextElement("IgnoredException", iexc) |
|
200 self.writeEndElement() |
|
201 self.writeEmptyElement("AutoClearShell") |
|
202 self.writeAttribute("value", str(self.dbg.autoClearShell)) |
|
203 self.writeEmptyElement("TracePython") |
|
204 self.writeAttribute("value", str(self.dbg.tracePython)) |
|
205 self.writeEmptyElement("AutoContinue") |
|
206 self.writeAttribute("value", str(self.dbg.autoContinue)) |
|
207 self.writeEmptyElement("EnableMultiprocess") |
|
208 self.writeAttribute("value", str(self.dbg.enableMultiprocess)) |
|
209 self.writeTextElement("MultiprocessNoDebug", |
|
210 dbgMultiprocessNoDebug) |
|
211 self.writeEmptyElement("CovexcPattern") # kept for compatibility |
|
212 self.writeEmptyElement("GlobalConfigOverride") |
|
213 self.writeAttribute( |
|
214 "enable", str(self.dbg.overrideGlobalConfig["enable"])) |
|
215 self.writeAttribute( |
|
216 "redirect", str(self.dbg.overrideGlobalConfig["redirect"])) |
|
217 else: |
|
218 self.writeTextElement("VirtualEnv", self.project.dbgVirtualEnv) |
|
219 self.writeTextElement("CommandLine", self.project.dbgCmdline) |
|
220 self.writeTextElement("WorkingDirectory", self.project.dbgWd) |
|
221 self.writeTextElement("Environment", self.project.dbgEnv) |
|
222 self.writeEmptyElement("ReportExceptions") |
|
223 self.writeAttribute("value", str(self.project.dbgReportExceptions)) |
|
224 self.writeStartElement("Exceptions") |
|
225 for exc in self.project.dbgExcList: |
|
226 self.writeTextElement("Exception", exc) |
|
227 self.writeEndElement() |
|
228 self.writeStartElement("IgnoredExceptions") |
|
229 for iexc in self.project.dbgExcIgnoreList: |
|
230 self.writeTextElement("IgnoredException", iexc) |
|
231 self.writeEndElement() |
|
232 self.writeEmptyElement("AutoClearShell") |
|
233 self.writeAttribute("value", str(self.project.dbgAutoClearShell)) |
|
234 self.writeEmptyElement("TracePython") |
|
235 self.writeAttribute("value", str(self.project.dbgTracePython)) |
|
236 self.writeEmptyElement("AutoContinue") |
|
237 self.writeAttribute("value", str(self.project.dbgAutoContinue)) |
|
238 self.writeEmptyElement("EnableMultiprocess") |
|
239 self.writeAttribute("value", |
|
240 str(self.project.dbgEnableMultiprocess)) |
|
241 self.writeTextElement("MultiprocessNoDebug", |
|
242 self.project.dbgMultiprocessNoDebug) |
|
243 self.writeEmptyElement("CovexcPattern") # kept for compatibility |
|
244 self.writeEmptyElement("GlobalConfigOverride") |
|
245 self.writeAttribute( |
|
246 "enable", str(self.project.dbgGlobalConfigOverride["enable"])) |
|
247 self.writeAttribute( |
|
248 "redirect", |
|
249 str(self.project.dbgGlobalConfigOverride["redirect"])) |
|
250 self.writeEndElement() |
|
251 |
|
252 # step 4: save bookmarks of all open (project) files |
|
253 self.writeStartElement("Bookmarks") |
|
254 for fileName in editorDict: |
|
255 if isGlobal or self.project.isProjectFile(fileName): |
|
256 editor = editorDict[fileName] |
|
257 for bookmark in editor.getBookmarks(): |
|
258 self.writeStartElement("Bookmark") |
|
259 self.writeTextElement("BmFilename", fileName) |
|
260 self.writeEmptyElement("Linenumber") |
|
261 self.writeAttribute("value", str(bookmark)) |
|
262 self.writeEndElement() |
|
263 self.writeEndElement() |
|
264 |
|
265 # step 5: save state of the various project browsers |
|
266 if not isGlobal: |
|
267 self.writeStartElement("ProjectBrowserStates") |
|
268 for browserName in self.projectBrowser.getProjectBrowserNames(): |
|
269 self.writeStartElement("ProjectBrowserState") |
|
270 self.writeAttribute("name", browserName) |
|
271 # get the names of expanded files and directories |
|
272 names = self.projectBrowser.getProjectBrowser( |
|
273 browserName).getExpandedItemNames() |
|
274 for name in names: |
|
275 self.writeTextElement("ExpandedItemName", name) |
|
276 self.writeEndElement() |
|
277 self.writeEndElement() |
|
278 |
|
279 # add the main end tag |
|
280 self.writeEndElement() |
|
281 self.writeEndDocument() |
|