src/eric7/Graphics/UMLDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
24 24
25 class UMLDialogType(enum.Enum): 25 class UMLDialogType(enum.Enum):
26 """ 26 """
27 Class defining the UML dialog types. 27 Class defining the UML dialog types.
28 """ 28 """
29
29 CLASS_DIAGRAM = 0 30 CLASS_DIAGRAM = 0
30 PACKAGE_DIAGRAM = 1 31 PACKAGE_DIAGRAM = 1
31 IMPORTS_DIAGRAM = 2 32 IMPORTS_DIAGRAM = 2
32 APPLICATION_DIAGRAM = 3 33 APPLICATION_DIAGRAM = 3
33 NO_DIAGRAM = 255 34 NO_DIAGRAM = 255
35 36
36 class UMLDialog(EricMainWindow): 37 class UMLDialog(EricMainWindow):
37 """ 38 """
38 Class implementing a dialog showing UML like diagrams. 39 Class implementing a dialog showing UML like diagrams.
39 """ 40 """
40 FileVersions = ("1.0", ) 41
41 JsonFileVersions = ("1.0", ) 42 FileVersions = ("1.0",)
42 43 JsonFileVersions = ("1.0",)
44
43 UMLDialogType2String = { 45 UMLDialogType2String = {
44 UMLDialogType.CLASS_DIAGRAM: 46 UMLDialogType.CLASS_DIAGRAM: QCoreApplication.translate(
45 QCoreApplication.translate("UMLDialog", "Class Diagram"), 47 "UMLDialog", "Class Diagram"
46 UMLDialogType.PACKAGE_DIAGRAM: 48 ),
47 QCoreApplication.translate("UMLDialog", "Package Diagram"), 49 UMLDialogType.PACKAGE_DIAGRAM: QCoreApplication.translate(
48 UMLDialogType.IMPORTS_DIAGRAM: 50 "UMLDialog", "Package Diagram"
49 QCoreApplication.translate("UMLDialog", "Imports Diagram"), 51 ),
50 UMLDialogType.APPLICATION_DIAGRAM: 52 UMLDialogType.IMPORTS_DIAGRAM: QCoreApplication.translate(
51 QCoreApplication.translate("UMLDialog", "Application Diagram"), 53 "UMLDialog", "Imports Diagram"
54 ),
55 UMLDialogType.APPLICATION_DIAGRAM: QCoreApplication.translate(
56 "UMLDialog", "Application Diagram"
57 ),
52 } 58 }
53 59
54 def __init__(self, diagramType, project, path="", parent=None, 60 def __init__(
55 initBuilder=True, **kwargs): 61 self, diagramType, project, path="", parent=None, initBuilder=True, **kwargs
62 ):
56 """ 63 """
57 Constructor 64 Constructor
58 65
59 @param diagramType type of the diagram 66 @param diagramType type of the diagram
60 @type UMLDialogType 67 @type UMLDialogType
61 @param project reference to the project object 68 @param project reference to the project object
62 @type Project 69 @type Project
63 @param path file or directory path to build the diagram from 70 @param path file or directory path to build the diagram from
70 @keyparam kwargs diagram specific data 77 @keyparam kwargs diagram specific data
71 @type dict 78 @type dict
72 """ 79 """
73 super().__init__(parent) 80 super().__init__(parent)
74 self.setObjectName("UMLDialog") 81 self.setObjectName("UMLDialog")
75 82
76 self.__project = project 83 self.__project = project
77 self.__diagramType = diagramType 84 self.__diagramType = diagramType
78 85
79 from .UMLGraphicsView import UMLGraphicsView 86 from .UMLGraphicsView import UMLGraphicsView
87
80 self.scene = QGraphicsScene(0.0, 0.0, 800.0, 600.0) 88 self.scene = QGraphicsScene(0.0, 0.0, 800.0, 600.0)
81 self.umlView = UMLGraphicsView(self.scene, parent=self) 89 self.umlView = UMLGraphicsView(self.scene, parent=self)
82 self.builder = self.__diagramBuilder( 90 self.builder = self.__diagramBuilder(self.__diagramType, path, **kwargs)
83 self.__diagramType, path, **kwargs)
84 if self.builder and initBuilder: 91 if self.builder and initBuilder:
85 self.builder.initialize() 92 self.builder.initialize()
86 93
87 self.__fileName = "" 94 self.__fileName = ""
88 95
89 self.__initActions() 96 self.__initActions()
90 self.__initToolBars() 97 self.__initToolBars()
91 98
92 self.setCentralWidget(self.umlView) 99 self.setCentralWidget(self.umlView)
93 100
94 self.umlView.relayout.connect(self.__relayout) 101 self.umlView.relayout.connect(self.__relayout)
95 102
96 self.setWindowTitle(self.__getDiagramTitel(self.__diagramType)) 103 self.setWindowTitle(self.__getDiagramTitel(self.__diagramType))
97 104
98 def __getDiagramTitel(self, diagramType): 105 def __getDiagramTitel(self, diagramType):
99 """ 106 """
100 Private method to get a textual description for the diagram type. 107 Private method to get a textual description for the diagram type.
101 108
102 @param diagramType diagram type string 109 @param diagramType diagram type string
103 @type str 110 @type str
104 @return titel of the diagram 111 @return titel of the diagram
105 @rtype str 112 @rtype str
106 """ 113 """
107 return UMLDialog.UMLDialogType2String.get( 114 return UMLDialog.UMLDialogType2String.get(
108 diagramType, self.tr("Illegal Diagram Type") 115 diagramType, self.tr("Illegal Diagram Type")
109 ) 116 )
110 117
111 def __initActions(self): 118 def __initActions(self):
112 """ 119 """
113 Private slot to initialize the actions. 120 Private slot to initialize the actions.
114 """ 121 """
115 self.closeAct = QAction( 122 self.closeAct = QAction(UI.PixmapCache.getIcon("close"), self.tr("Close"), self)
116 UI.PixmapCache.getIcon("close"),
117 self.tr("Close"), self)
118 self.closeAct.triggered.connect(self.close) 123 self.closeAct.triggered.connect(self.close)
119 124
120 self.openAct = QAction( 125 self.openAct = QAction(UI.PixmapCache.getIcon("open"), self.tr("Load"), self)
121 UI.PixmapCache.getIcon("open"),
122 self.tr("Load"), self)
123 self.openAct.triggered.connect(self.load) 126 self.openAct.triggered.connect(self.load)
124 127
125 self.saveAct = QAction( 128 self.saveAct = QAction(
126 UI.PixmapCache.getIcon("fileSave"), 129 UI.PixmapCache.getIcon("fileSave"), self.tr("Save"), self
127 self.tr("Save"), self) 130 )
128 self.saveAct.triggered.connect(self.__save) 131 self.saveAct.triggered.connect(self.__save)
129 132
130 self.saveAsAct = QAction( 133 self.saveAsAct = QAction(
131 UI.PixmapCache.getIcon("fileSaveAs"), 134 UI.PixmapCache.getIcon("fileSaveAs"), self.tr("Save As..."), self
132 self.tr("Save As..."), self) 135 )
133 self.saveAsAct.triggered.connect(self.__saveAs) 136 self.saveAsAct.triggered.connect(self.__saveAs)
134 137
135 self.saveImageAct = QAction( 138 self.saveImageAct = QAction(
136 UI.PixmapCache.getIcon("fileSavePixmap"), 139 UI.PixmapCache.getIcon("fileSavePixmap"), self.tr("Save as Image"), self
137 self.tr("Save as Image"), self) 140 )
138 self.saveImageAct.triggered.connect(self.umlView.saveImage) 141 self.saveImageAct.triggered.connect(self.umlView.saveImage)
139 142
140 self.printAct = QAction( 143 self.printAct = QAction(UI.PixmapCache.getIcon("print"), self.tr("Print"), self)
141 UI.PixmapCache.getIcon("print"),
142 self.tr("Print"), self)
143 self.printAct.triggered.connect(self.umlView.printDiagram) 144 self.printAct.triggered.connect(self.umlView.printDiagram)
144 145
145 self.printPreviewAct = QAction( 146 self.printPreviewAct = QAction(
146 UI.PixmapCache.getIcon("printPreview"), 147 UI.PixmapCache.getIcon("printPreview"), self.tr("Print Preview"), self
147 self.tr("Print Preview"), self) 148 )
148 self.printPreviewAct.triggered.connect( 149 self.printPreviewAct.triggered.connect(self.umlView.printPreviewDiagram)
149 self.umlView.printPreviewDiagram) 150
150
151 def __initToolBars(self): 151 def __initToolBars(self):
152 """ 152 """
153 Private slot to initialize the toolbars. 153 Private slot to initialize the toolbars.
154 """ 154 """
155 self.windowToolBar = QToolBar(self.tr("Window"), self) 155 self.windowToolBar = QToolBar(self.tr("Window"), self)
156 self.windowToolBar.setIconSize(UI.Config.ToolBarIconSize) 156 self.windowToolBar.setIconSize(UI.Config.ToolBarIconSize)
157 self.windowToolBar.addAction(self.closeAct) 157 self.windowToolBar.addAction(self.closeAct)
158 158
159 self.fileToolBar = QToolBar(self.tr("File"), self) 159 self.fileToolBar = QToolBar(self.tr("File"), self)
160 self.fileToolBar.setIconSize(UI.Config.ToolBarIconSize) 160 self.fileToolBar.setIconSize(UI.Config.ToolBarIconSize)
161 self.fileToolBar.addAction(self.openAct) 161 self.fileToolBar.addAction(self.openAct)
162 self.fileToolBar.addSeparator() 162 self.fileToolBar.addSeparator()
163 self.fileToolBar.addAction(self.saveAct) 163 self.fileToolBar.addAction(self.saveAct)
164 self.fileToolBar.addAction(self.saveAsAct) 164 self.fileToolBar.addAction(self.saveAsAct)
165 self.fileToolBar.addAction(self.saveImageAct) 165 self.fileToolBar.addAction(self.saveImageAct)
166 self.fileToolBar.addSeparator() 166 self.fileToolBar.addSeparator()
167 self.fileToolBar.addAction(self.printPreviewAct) 167 self.fileToolBar.addAction(self.printPreviewAct)
168 self.fileToolBar.addAction(self.printAct) 168 self.fileToolBar.addAction(self.printAct)
169 169
170 self.umlToolBar = self.umlView.initToolBar() 170 self.umlToolBar = self.umlView.initToolBar()
171 171
172 self.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.fileToolBar) 172 self.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.fileToolBar)
173 self.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.windowToolBar) 173 self.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.windowToolBar)
174 self.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.umlToolBar) 174 self.addToolBar(Qt.ToolBarArea.TopToolBarArea, self.umlToolBar)
175 175
176 def show(self, fromFile=False): 176 def show(self, fromFile=False):
177 """ 177 """
178 Public method to show the dialog. 178 Public method to show the dialog.
179 179
180 @param fromFile flag indicating, that the diagram was loaded 180 @param fromFile flag indicating, that the diagram was loaded
181 from file 181 from file
182 @type bool 182 @type bool
183 """ 183 """
184 if not fromFile and self.builder: 184 if not fromFile and self.builder:
185 self.builder.buildDiagram() 185 self.builder.buildDiagram()
186 super().show() 186 super().show()
187 187
188 def __relayout(self): 188 def __relayout(self):
189 """ 189 """
190 Private method to re-layout the diagram. 190 Private method to re-layout the diagram.
191 """ 191 """
192 if self.builder: 192 if self.builder:
193 self.builder.buildDiagram() 193 self.builder.buildDiagram()
194 194
195 def __diagramBuilder(self, diagramType, path, **kwargs): 195 def __diagramBuilder(self, diagramType, path, **kwargs):
196 """ 196 """
197 Private method to instantiate a diagram builder object. 197 Private method to instantiate a diagram builder object.
198 198
199 @param diagramType type of the diagram 199 @param diagramType type of the diagram
200 @type UMLDialogType 200 @type UMLDialogType
201 @param path file or directory path to build the diagram from 201 @param path file or directory path to build the diagram from
202 @type str 202 @type str
203 @keyparam kwargs diagram specific data 203 @keyparam kwargs diagram specific data
205 @return reference to the instantiated diagram builder 205 @return reference to the instantiated diagram builder
206 @rtype UMLDiagramBuilder 206 @rtype UMLDiagramBuilder
207 """ 207 """
208 if diagramType == UMLDialogType.CLASS_DIAGRAM: 208 if diagramType == UMLDialogType.CLASS_DIAGRAM:
209 from .UMLClassDiagramBuilder import UMLClassDiagramBuilder 209 from .UMLClassDiagramBuilder import UMLClassDiagramBuilder
210
210 return UMLClassDiagramBuilder( 211 return UMLClassDiagramBuilder(
211 self, self.umlView, self.__project, path, **kwargs) 212 self, self.umlView, self.__project, path, **kwargs
213 )
212 elif diagramType == UMLDialogType.PACKAGE_DIAGRAM: 214 elif diagramType == UMLDialogType.PACKAGE_DIAGRAM:
213 from .PackageDiagramBuilder import PackageDiagramBuilder 215 from .PackageDiagramBuilder import PackageDiagramBuilder
216
214 return PackageDiagramBuilder( 217 return PackageDiagramBuilder(
215 self, self.umlView, self.__project, path, **kwargs) 218 self, self.umlView, self.__project, path, **kwargs
219 )
216 elif diagramType == UMLDialogType.IMPORTS_DIAGRAM: 220 elif diagramType == UMLDialogType.IMPORTS_DIAGRAM:
217 from .ImportsDiagramBuilder import ImportsDiagramBuilder 221 from .ImportsDiagramBuilder import ImportsDiagramBuilder
222
218 return ImportsDiagramBuilder( 223 return ImportsDiagramBuilder(
219 self, self.umlView, self.__project, path, **kwargs) 224 self, self.umlView, self.__project, path, **kwargs
225 )
220 elif diagramType == UMLDialogType.APPLICATION_DIAGRAM: 226 elif diagramType == UMLDialogType.APPLICATION_DIAGRAM:
221 from .ApplicationDiagramBuilder import ApplicationDiagramBuilder 227 from .ApplicationDiagramBuilder import ApplicationDiagramBuilder
228
222 return ApplicationDiagramBuilder( 229 return ApplicationDiagramBuilder(
223 self, self.umlView, self.__project, **kwargs) 230 self, self.umlView, self.__project, **kwargs
231 )
224 else: 232 else:
225 return None 233 return None
226 234
227 def __save(self): 235 def __save(self):
228 """ 236 """
229 Private slot to save the diagram with the current name. 237 Private slot to save the diagram with the current name.
230 """ 238 """
231 self.__saveAs(self.__fileName) 239 self.__saveAs(self.__fileName)
232 240
233 @pyqtSlot() 241 @pyqtSlot()
234 def __saveAs(self, filename=""): 242 def __saveAs(self, filename=""):
235 """ 243 """
236 Private slot to save the diagram. 244 Private slot to save the diagram.
237 245
238 @param filename name of the file to write to 246 @param filename name of the file to write to
239 @type str 247 @type str
240 """ 248 """
241 if not filename: 249 if not filename:
242 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( 250 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter(
243 self, 251 self,
244 self.tr("Save Diagram"), 252 self.tr("Save Diagram"),
245 "", 253 "",
246 self.tr("Eric Graphics File (*.egj);;" 254 self.tr(
247 "Eric Text Graphics File (*.e5g);;" 255 "Eric Graphics File (*.egj);;"
248 "All Files (*)"), 256 "Eric Text Graphics File (*.e5g);;"
257 "All Files (*)"
258 ),
249 "", 259 "",
250 EricFileDialog.DontConfirmOverwrite) 260 EricFileDialog.DontConfirmOverwrite,
261 )
251 if not fname: 262 if not fname:
252 return 263 return
253 264
254 fpath = pathlib.Path(fname) 265 fpath = pathlib.Path(fname)
255 if not fpath.suffix: 266 if not fpath.suffix:
256 ex = selectedFilter.split("(*")[1].split(")")[0] 267 ex = selectedFilter.split("(*")[1].split(")")[0]
257 if ex: 268 if ex:
258 fpath = fpath.with_suffix(ex) 269 fpath = fpath.with_suffix(ex)
259 if fpath.exists(): 270 if fpath.exists():
260 res = EricMessageBox.yesNo( 271 res = EricMessageBox.yesNo(
261 self, 272 self,
262 self.tr("Save Diagram"), 273 self.tr("Save Diagram"),
263 self.tr("<p>The file <b>{0}</b> already exists." 274 self.tr(
264 " Overwrite it?</p>").format(fpath), 275 "<p>The file <b>{0}</b> already exists." " Overwrite it?</p>"
265 icon=EricMessageBox.Warning) 276 ).format(fpath),
277 icon=EricMessageBox.Warning,
278 )
266 if not res: 279 if not res:
267 return 280 return
268 filename = str(fpath) 281 filename = str(fpath)
269 282
270 res = self.__writeJsonGraphicsFile(filename) 283 res = self.__writeJsonGraphicsFile(filename)
271 284
272 if res: 285 if res:
273 # save the file name only in case of success 286 # save the file name only in case of success
274 self.__fileName = filename 287 self.__fileName = filename
275 288
276 # Note: remove loading of eric6 line based diagram format after 22.6 289 # Note: remove loading of eric6 line based diagram format after 22.6
277 def load(self, filename=""): 290 def load(self, filename=""):
278 """ 291 """
279 Public method to load a diagram from a file. 292 Public method to load a diagram from a file.
280 293
281 @param filename name of the file to be loaded 294 @param filename name of the file to be loaded
282 @type str 295 @type str
283 @return flag indicating success 296 @return flag indicating success
284 @rtype bool 297 @rtype bool
285 """ 298 """
286 if not filename: 299 if not filename:
287 filename = EricFileDialog.getOpenFileName( 300 filename = EricFileDialog.getOpenFileName(
288 self, 301 self,
289 self.tr("Load Diagram"), 302 self.tr("Load Diagram"),
290 "", 303 "",
291 self.tr("Eric Graphics File (*.egj);;" 304 self.tr(
292 "Eric Text Graphics File (*.e5g);;" 305 "Eric Graphics File (*.egj);;"
293 "All Files (*)")) 306 "Eric Text Graphics File (*.e5g);;"
307 "All Files (*)"
308 ),
309 )
294 if not filename: 310 if not filename:
295 # Canceled by user 311 # Canceled by user
296 return False 312 return False
297 313
298 return ( 314 return (
299 self.__readLineBasedGraphicsFile(filename) 315 self.__readLineBasedGraphicsFile(filename)
300 if filename.endswith(".e5g") else 316 if filename.endswith(".e5g")
317 else
301 # JSON format is the default 318 # JSON format is the default
302 self.__readJsonGraphicsFile(filename) 319 self.__readJsonGraphicsFile(filename)
303 ) 320 )
304 321
305 ####################################################################### 322 #######################################################################
306 ## Methods to read and write eric graphics files of the old line 323 ## Methods to read and write eric graphics files of the old line
307 ## based file format. 324 ## based file format.
308 ####################################################################### 325 #######################################################################
309 326
310 def __readLineBasedGraphicsFile(self, filename): 327 def __readLineBasedGraphicsFile(self, filename):
311 """ 328 """
312 Private method to read an eric graphics file using the old line 329 Private method to read an eric graphics file using the old line
313 based file format. 330 based file format.
314 331
315 @param filename name of the file to be read 332 @param filename name of the file to be read
316 @type str 333 @type str
317 @return flag indicating success 334 @return flag indicating success
318 @rtype bool 335 @rtype bool
319 """ 336 """
324 EricMessageBox.critical( 341 EricMessageBox.critical(
325 self, 342 self,
326 self.tr("Load Diagram"), 343 self.tr("Load Diagram"),
327 self.tr( 344 self.tr(
328 """<p>The file <b>{0}</b> could not be read.</p>""" 345 """<p>The file <b>{0}</b> could not be read.</p>"""
329 """<p>Reason: {1}</p>""").format(filename, str(err))) 346 """<p>Reason: {1}</p>"""
347 ).format(filename, str(err)),
348 )
330 return False 349 return False
331 350
332 lines = data.splitlines() 351 lines = data.splitlines()
333 if len(lines) < 3: 352 if len(lines) < 3:
334 self.__showInvalidDataMessage(filename) 353 self.__showInvalidDataMessage(filename)
335 return False 354 return False
336 355
337 try: 356 try:
338 # step 1: check version 357 # step 1: check version
339 linenum = 0 358 linenum = 0
340 key, value = lines[linenum].split(": ", 1) 359 key, value = lines[linenum].split(": ", 1)
341 if ( 360 if key.strip() != "version" or value.strip() not in UMLDialog.FileVersions:
342 key.strip() != "version" or
343 value.strip() not in UMLDialog.FileVersions
344 ):
345 self.__showInvalidDataMessage(filename, linenum) 361 self.__showInvalidDataMessage(filename, linenum)
346 return False 362 return False
347 else: 363 else:
348 version = value 364 version = value
349 365
350 # step 2: extract diagram type 366 # step 2: extract diagram type
351 linenum += 1 367 linenum += 1
352 key, value = lines[linenum].split(": ", 1) 368 key, value = lines[linenum].split(": ", 1)
353 if key.strip() != "diagram_type": 369 if key.strip() != "diagram_type":
354 self.__showInvalidDataMessage(filename, linenum) 370 self.__showInvalidDataMessage(filename, linenum)
359 except ValueError: 375 except ValueError:
360 self.__showInvalidDataMessage(filename, linenum) 376 self.__showInvalidDataMessage(filename, linenum)
361 return False 377 return False
362 self.scene.clear() 378 self.scene.clear()
363 self.builder = self.__diagramBuilder(self.__diagramType, "") 379 self.builder = self.__diagramBuilder(self.__diagramType, "")
364 380
365 # step 3: extract scene size 381 # step 3: extract scene size
366 linenum += 1 382 linenum += 1
367 key, value = lines[linenum].split(": ", 1) 383 key, value = lines[linenum].split(": ", 1)
368 if key.strip() != "scene_size": 384 if key.strip() != "scene_size":
369 self.__showInvalidDataMessage(filename, linenum) 385 self.__showInvalidDataMessage(filename, linenum)
372 width, height = [float(v.strip()) for v in value.split(";")] 388 width, height = [float(v.strip()) for v in value.split(";")]
373 except ValueError: 389 except ValueError:
374 self.__showInvalidDataMessage(filename, linenum) 390 self.__showInvalidDataMessage(filename, linenum)
375 return False 391 return False
376 self.umlView.setSceneSize(width, height) 392 self.umlView.setSceneSize(width, height)
377 393
378 # step 4: extract builder data if available 394 # step 4: extract builder data if available
379 linenum += 1 395 linenum += 1
380 key, value = lines[linenum].split(": ", 1) 396 key, value = lines[linenum].split(": ", 1)
381 if key.strip() == "builder_data": 397 if key.strip() == "builder_data":
382 ok = self.builder.parsePersistenceData(version, value) 398 ok = self.builder.parsePersistenceData(version, value)
383 if not ok: 399 if not ok:
384 self.__showInvalidDataMessage(filename, linenum) 400 self.__showInvalidDataMessage(filename, linenum)
385 return False 401 return False
386 linenum += 1 402 linenum += 1
387 403
388 # step 5: extract the graphics items 404 # step 5: extract the graphics items
389 ok, vlinenum = self.umlView.parsePersistenceData( 405 ok, vlinenum = self.umlView.parsePersistenceData(version, lines[linenum:])
390 version, lines[linenum:])
391 if not ok: 406 if not ok:
392 self.__showInvalidDataMessage(filename, linenum + vlinenum) 407 self.__showInvalidDataMessage(filename, linenum + vlinenum)
393 return False 408 return False
394 409
395 except IndexError: 410 except IndexError:
396 self.__showInvalidDataMessage(filename) 411 self.__showInvalidDataMessage(filename)
397 return False 412 return False
398 413
399 # everything worked fine, so remember the file name and set the 414 # everything worked fine, so remember the file name and set the
400 # window title 415 # window title
401 self.setWindowTitle(self.__getDiagramTitel(self.__diagramType)) 416 self.setWindowTitle(self.__getDiagramTitel(self.__diagramType))
402 self.__fileName = filename 417 self.__fileName = filename
403 418
404 return True 419 return True
405 420
406 def __showInvalidDataMessage(self, filename, linenum=-1): 421 def __showInvalidDataMessage(self, filename, linenum=-1):
407 """ 422 """
408 Private slot to show a message dialog indicating an invalid data file. 423 Private slot to show a message dialog indicating an invalid data file.
409 424
410 @param filename name of the file containing the invalid data 425 @param filename name of the file containing the invalid data
411 @type str 426 @type str
412 @param linenum number of the invalid line 427 @param linenum number of the invalid line
413 @type int 428 @type int
414 """ 429 """
415 msg = ( 430 msg = (
416 self.tr("""<p>The file <b>{0}</b> does not contain""" 431 self.tr(
417 """ valid data.</p>""").format(filename) 432 """<p>The file <b>{0}</b> does not contain""" """ valid data.</p>"""
418 if linenum < 0 else 433 ).format(filename)
419 self.tr("""<p>The file <b>{0}</b> does not contain""" 434 if linenum < 0
420 """ valid data.</p><p>Invalid line: {1}</p>""" 435 else self.tr(
421 ).format(filename, linenum + 1) 436 """<p>The file <b>{0}</b> does not contain"""
437 """ valid data.</p><p>Invalid line: {1}</p>"""
438 ).format(filename, linenum + 1)
422 ) 439 )
423 EricMessageBox.critical(self, self.tr("Load Diagram"), msg) 440 EricMessageBox.critical(self, self.tr("Load Diagram"), msg)
424 441
425 ####################################################################### 442 #######################################################################
426 ## Methods to read and write eric graphics files of the JSON based 443 ## Methods to read and write eric graphics files of the JSON based
427 ## file format. 444 ## file format.
428 ####################################################################### 445 #######################################################################
429 446
430 def __writeJsonGraphicsFile(self, filename): 447 def __writeJsonGraphicsFile(self, filename):
431 """ 448 """
432 Private method to write an eric graphics file using the JSON based 449 Private method to write an eric graphics file using the JSON based
433 file format. 450 file format.
434 451
435 @param filename name of the file to write to 452 @param filename name of the file to write to
436 @type str 453 @type str
437 @return flag indicating a successful write 454 @return flag indicating a successful write
438 @rtype bool 455 @rtype bool
439 """ 456 """
444 "width": self.scene.width(), 461 "width": self.scene.width(),
445 "height": self.scene.height(), 462 "height": self.scene.height(),
446 "builder": self.builder.toDict(), 463 "builder": self.builder.toDict(),
447 "view": self.umlView.toDict(), 464 "view": self.umlView.toDict(),
448 } 465 }
449 466
450 try: 467 try:
451 jsonString = json.dumps(data, indent=2) 468 jsonString = json.dumps(data, indent=2)
452 with open(filename, "w") as f: 469 with open(filename, "w") as f:
453 f.write(jsonString) 470 f.write(jsonString)
454 return True 471 return True
456 EricMessageBox.critical( 473 EricMessageBox.critical(
457 self, 474 self,
458 self.tr("Save Diagram"), 475 self.tr("Save Diagram"),
459 self.tr( 476 self.tr(
460 """<p>The file <b>{0}</b> could not be saved.</p>""" 477 """<p>The file <b>{0}</b> could not be saved.</p>"""
461 """<p>Reason: {1}</p>""").format(filename, str(err)) 478 """<p>Reason: {1}</p>"""
479 ).format(filename, str(err)),
462 ) 480 )
463 return False 481 return False
464 482
465 def __readJsonGraphicsFile(self, filename): 483 def __readJsonGraphicsFile(self, filename):
466 """ 484 """
467 Private method to read an eric graphics file using the JSON based 485 Private method to read an eric graphics file using the JSON based
468 file format. 486 file format.
469 487
470 @param filename name of the file to be read 488 @param filename name of the file to be read
471 @type str 489 @type str
472 @return flag indicating a successful read 490 @return flag indicating a successful read
473 @rtype bool 491 @rtype bool
474 """ 492 """
480 EricMessageBox.critical( 498 EricMessageBox.critical(
481 None, 499 None,
482 self.tr("Load Diagram"), 500 self.tr("Load Diagram"),
483 self.tr( 501 self.tr(
484 """<p>The file <b>{0}</b> could not be read.</p>""" 502 """<p>The file <b>{0}</b> could not be read.</p>"""
485 """<p>Reason: {1}</p>""").format(filename, str(err)) 503 """<p>Reason: {1}</p>"""
504 ).format(filename, str(err)),
486 ) 505 )
487 return False 506 return False
488 507
489 try: 508 try:
490 # step 1: check version 509 # step 1: check version
491 if data["version"] in UMLDialog.JsonFileVersions: 510 if data["version"] in UMLDialog.JsonFileVersions:
492 version = data["version"] 511 version = data["version"]
493 else: 512 else:
494 self.__showInvalidDataMessage(filename) 513 self.__showInvalidDataMessage(filename)
495 return False 514 return False
496 515
497 # step 2: set diagram type 516 # step 2: set diagram type
498 try: 517 try:
499 self.__diagramType = UMLDialogType(data["type"]) 518 self.__diagramType = UMLDialogType(data["type"])
500 except ValueError: 519 except ValueError:
501 self.__showInvalidDataMessage(filename) 520 self.__showInvalidDataMessage(filename)
502 return False 521 return False
503 self.scene.clear() 522 self.scene.clear()
504 self.builder = self.__diagramBuilder(self.__diagramType, "") 523 self.builder = self.__diagramBuilder(self.__diagramType, "")
505 524
506 # step 3: set scene size 525 # step 3: set scene size
507 self.umlView.setSceneSize(data["width"], data["height"]) 526 self.umlView.setSceneSize(data["width"], data["height"])
508 527
509 # step 4: extract builder data if available 528 # step 4: extract builder data if available
510 ok, msg = self.builder.fromDict(version, data["builder"]) 529 ok, msg = self.builder.fromDict(version, data["builder"])
511 if not ok: 530 if not ok:
512 if msg: 531 if msg:
513 res = EricMessageBox.warning( 532 res = EricMessageBox.warning(
514 self, 533 self,
515 self.tr("Load Diagram"), 534 self.tr("Load Diagram"),
516 msg, 535 msg,
517 EricMessageBox.Abort | EricMessageBox.Ignore, 536 EricMessageBox.Abort | EricMessageBox.Ignore,
518 EricMessageBox.Abort) 537 EricMessageBox.Abort,
538 )
519 if res == EricMessageBox.Abort: 539 if res == EricMessageBox.Abort:
520 return False 540 return False
521 else: 541 else:
522 self.umlView.setLayoutActionsEnabled(False) 542 self.umlView.setLayoutActionsEnabled(False)
523 else: 543 else:
524 self.__showInvalidDataMessage(filename) 544 self.__showInvalidDataMessage(filename)
525 return False 545 return False
526 546
527 # step 5: extract the graphics items 547 # step 5: extract the graphics items
528 ok = self.umlView.fromDict(version, data["view"]) 548 ok = self.umlView.fromDict(version, data["view"])
529 if not ok: 549 if not ok:
530 self.__showInvalidDataMessage(filename) 550 self.__showInvalidDataMessage(filename)
531 return False 551 return False
532 except KeyError: 552 except KeyError:
533 self.__showInvalidDataMessage(filename) 553 self.__showInvalidDataMessage(filename)
534 return False 554 return False
535 555
536 # everything worked fine, so remember the file name and set the 556 # everything worked fine, so remember the file name and set the
537 # window title 557 # window title
538 self.setWindowTitle(self.__getDiagramTitel(self.__diagramType)) 558 self.setWindowTitle(self.__getDiagramTitel(self.__diagramType))
539 self.__fileName = filename 559 self.__fileName = filename
540 560
541 return True 561 return True

eric ide

mercurial