src/eric7/Graphics/UMLGraphicsView.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
7 Module implementing a subclass of EricGraphicsView for our diagrams. 7 Module implementing a subclass of EricGraphicsView for our diagrams.
8 """ 8 """
9 9
10 import pathlib 10 import pathlib
11 11
12 from PyQt6.QtCore import ( 12 from PyQt6.QtCore import pyqtSignal, Qt, QSignalMapper, QEvent, QRectF, QMarginsF
13 pyqtSignal, Qt, QSignalMapper, QEvent, QRectF, QMarginsF
14 )
15 from PyQt6.QtGui import QAction, QPageLayout 13 from PyQt6.QtGui import QAction, QPageLayout
16 from PyQt6.QtWidgets import QGraphicsView, QToolBar, QDialog 14 from PyQt6.QtWidgets import QGraphicsView, QToolBar, QDialog
17 from PyQt6.QtPrintSupport import QPrinter, QPrintDialog 15 from PyQt6.QtPrintSupport import QPrinter, QPrintDialog
18 16
19 from EricGraphics.EricGraphicsView import EricGraphicsView 17 from EricGraphics.EricGraphicsView import EricGraphicsView
30 28
31 29
32 class UMLGraphicsView(EricGraphicsView): 30 class UMLGraphicsView(EricGraphicsView):
33 """ 31 """
34 Class implementing a specialized EricGraphicsView for our diagrams. 32 Class implementing a specialized EricGraphicsView for our diagrams.
35 33
36 @signal relayout() emitted to indicate a relayout of the diagram 34 @signal relayout() emitted to indicate a relayout of the diagram
37 is requested 35 is requested
38 """ 36 """
37
39 relayout = pyqtSignal() 38 relayout = pyqtSignal()
40 39
41 def __init__(self, scene, parent=None): 40 def __init__(self, scene, parent=None):
42 """ 41 """
43 Constructor 42 Constructor
44 43
45 @param scene reference to the scene object 44 @param scene reference to the scene object
46 @type QGraphicsScene 45 @type QGraphicsScene
47 @param parent parent widget of the view 46 @param parent parent widget of the view
48 @type QWidget 47 @type QWidget
49 """ 48 """
50 EricGraphicsView.__init__(self, scene, parent) 49 EricGraphicsView.__init__(self, scene, parent)
51 self.setObjectName("UMLGraphicsView") 50 self.setObjectName("UMLGraphicsView")
52 self.setViewportUpdateMode( 51 self.setViewportUpdateMode(QGraphicsView.ViewportUpdateMode.FullViewportUpdate)
53 QGraphicsView.ViewportUpdateMode.FullViewportUpdate) 52
54
55 self.diagramName = "Unnamed" 53 self.diagramName = "Unnamed"
56 self.__itemId = -1 54 self.__itemId = -1
57 55
58 self.border = 10 56 self.border = 10
59 self.deltaSize = 100.0 57 self.deltaSize = 100.0
60 58
61 self.__zoomWidget = EricZoomWidget( 59 self.__zoomWidget = EricZoomWidget(
62 UI.PixmapCache.getPixmap("zoomOut"), 60 UI.PixmapCache.getPixmap("zoomOut"),
63 UI.PixmapCache.getPixmap("zoomIn"), 61 UI.PixmapCache.getPixmap("zoomIn"),
64 UI.PixmapCache.getPixmap("zoomReset"), self) 62 UI.PixmapCache.getPixmap("zoomReset"),
63 self,
64 )
65 parent.statusBar().addPermanentWidget(self.__zoomWidget) 65 parent.statusBar().addPermanentWidget(self.__zoomWidget)
66 self.__zoomWidget.setMapping( 66 self.__zoomWidget.setMapping(
67 EricGraphicsView.ZoomLevels, EricGraphicsView.ZoomLevelDefault) 67 EricGraphicsView.ZoomLevels, EricGraphicsView.ZoomLevelDefault
68 )
68 self.__zoomWidget.valueChanged.connect(self.setZoom) 69 self.__zoomWidget.valueChanged.connect(self.setZoom)
69 self.zoomValueChanged.connect(self.__zoomWidget.setValue) 70 self.zoomValueChanged.connect(self.__zoomWidget.setValue)
70 71
71 self.__initActions() 72 self.__initActions()
72 73
73 scene.changed.connect(self.__sceneChanged) 74 scene.changed.connect(self.__sceneChanged)
74 75
75 self.grabGesture(Qt.GestureType.PinchGesture) 76 self.grabGesture(Qt.GestureType.PinchGesture)
76 77
77 def __initActions(self): 78 def __initActions(self):
78 """ 79 """
79 Private method to initialize the view actions. 80 Private method to initialize the view actions.
80 """ 81 """
81 self.alignMapper = QSignalMapper(self) 82 self.alignMapper = QSignalMapper(self)
82 try: 83 try:
83 self.alignMapper.mappedInt.connect(self.__alignShapes) 84 self.alignMapper.mappedInt.connect(self.__alignShapes)
84 except AttributeError: 85 except AttributeError:
85 # pre Qt 5.15 86 # pre Qt 5.15
86 self.alignMapper.mapped[int].connect(self.__alignShapes) 87 self.alignMapper.mapped[int].connect(self.__alignShapes)
87 88
88 self.deleteShapeAct = QAction( 89 self.deleteShapeAct = QAction(
89 UI.PixmapCache.getIcon("deleteShape"), 90 UI.PixmapCache.getIcon("deleteShape"), self.tr("Delete shapes"), self
90 self.tr("Delete shapes"), self) 91 )
91 self.deleteShapeAct.triggered.connect(self.__deleteShape) 92 self.deleteShapeAct.triggered.connect(self.__deleteShape)
92 93
93 self.incWidthAct = QAction( 94 self.incWidthAct = QAction(
94 UI.PixmapCache.getIcon("sceneWidthInc"), 95 UI.PixmapCache.getIcon("sceneWidthInc"),
95 self.tr("Increase width by {0} points").format( 96 self.tr("Increase width by {0} points").format(self.deltaSize),
96 self.deltaSize), 97 self,
97 self) 98 )
98 self.incWidthAct.triggered.connect(self.__incWidth) 99 self.incWidthAct.triggered.connect(self.__incWidth)
99 100
100 self.incHeightAct = QAction( 101 self.incHeightAct = QAction(
101 UI.PixmapCache.getIcon("sceneHeightInc"), 102 UI.PixmapCache.getIcon("sceneHeightInc"),
102 self.tr("Increase height by {0} points").format( 103 self.tr("Increase height by {0} points").format(self.deltaSize),
103 self.deltaSize), 104 self,
104 self) 105 )
105 self.incHeightAct.triggered.connect(self.__incHeight) 106 self.incHeightAct.triggered.connect(self.__incHeight)
106 107
107 self.decWidthAct = QAction( 108 self.decWidthAct = QAction(
108 UI.PixmapCache.getIcon("sceneWidthDec"), 109 UI.PixmapCache.getIcon("sceneWidthDec"),
109 self.tr("Decrease width by {0} points").format( 110 self.tr("Decrease width by {0} points").format(self.deltaSize),
110 self.deltaSize), 111 self,
111 self) 112 )
112 self.decWidthAct.triggered.connect(self.__decWidth) 113 self.decWidthAct.triggered.connect(self.__decWidth)
113 114
114 self.decHeightAct = QAction( 115 self.decHeightAct = QAction(
115 UI.PixmapCache.getIcon("sceneHeightDec"), 116 UI.PixmapCache.getIcon("sceneHeightDec"),
116 self.tr("Decrease height by {0} points").format( 117 self.tr("Decrease height by {0} points").format(self.deltaSize),
117 self.deltaSize), 118 self,
118 self) 119 )
119 self.decHeightAct.triggered.connect(self.__decHeight) 120 self.decHeightAct.triggered.connect(self.__decHeight)
120 121
121 self.setSizeAct = QAction( 122 self.setSizeAct = QAction(
122 UI.PixmapCache.getIcon("sceneSize"), 123 UI.PixmapCache.getIcon("sceneSize"), self.tr("Set size"), self
123 self.tr("Set size"), self) 124 )
124 self.setSizeAct.triggered.connect(self.__setSize) 125 self.setSizeAct.triggered.connect(self.__setSize)
125 126
126 self.rescanAct = QAction( 127 self.rescanAct = QAction(
127 UI.PixmapCache.getIcon("rescan"), 128 UI.PixmapCache.getIcon("rescan"), self.tr("Re-Scan"), self
128 self.tr("Re-Scan"), self) 129 )
129 self.rescanAct.triggered.connect(self.__rescan) 130 self.rescanAct.triggered.connect(self.__rescan)
130 131
131 self.relayoutAct = QAction( 132 self.relayoutAct = QAction(
132 UI.PixmapCache.getIcon("relayout"), 133 UI.PixmapCache.getIcon("relayout"), self.tr("Re-Layout"), self
133 self.tr("Re-Layout"), self) 134 )
134 self.relayoutAct.triggered.connect(self.__relayout) 135 self.relayoutAct.triggered.connect(self.__relayout)
135 136
136 self.alignLeftAct = QAction( 137 self.alignLeftAct = QAction(
137 UI.PixmapCache.getIcon("shapesAlignLeft"), 138 UI.PixmapCache.getIcon("shapesAlignLeft"), self.tr("Align Left"), self
138 self.tr("Align Left"), self) 139 )
139 self.alignMapper.setMapping( 140 self.alignMapper.setMapping(self.alignLeftAct, Qt.AlignmentFlag.AlignLeft)
140 self.alignLeftAct, Qt.AlignmentFlag.AlignLeft)
141 self.alignLeftAct.triggered.connect(self.alignMapper.map) 141 self.alignLeftAct.triggered.connect(self.alignMapper.map)
142 142
143 self.alignHCenterAct = QAction( 143 self.alignHCenterAct = QAction(
144 UI.PixmapCache.getIcon("shapesAlignHCenter"), 144 UI.PixmapCache.getIcon("shapesAlignHCenter"),
145 self.tr("Align Center Horizontal"), self) 145 self.tr("Align Center Horizontal"),
146 self.alignMapper.setMapping( 146 self,
147 self.alignHCenterAct, Qt.AlignmentFlag.AlignHCenter) 147 )
148 self.alignMapper.setMapping(self.alignHCenterAct, Qt.AlignmentFlag.AlignHCenter)
148 self.alignHCenterAct.triggered.connect(self.alignMapper.map) 149 self.alignHCenterAct.triggered.connect(self.alignMapper.map)
149 150
150 self.alignRightAct = QAction( 151 self.alignRightAct = QAction(
151 UI.PixmapCache.getIcon("shapesAlignRight"), 152 UI.PixmapCache.getIcon("shapesAlignRight"), self.tr("Align Right"), self
152 self.tr("Align Right"), self) 153 )
153 self.alignMapper.setMapping( 154 self.alignMapper.setMapping(self.alignRightAct, Qt.AlignmentFlag.AlignRight)
154 self.alignRightAct, Qt.AlignmentFlag.AlignRight)
155 self.alignRightAct.triggered.connect(self.alignMapper.map) 155 self.alignRightAct.triggered.connect(self.alignMapper.map)
156 156
157 self.alignTopAct = QAction( 157 self.alignTopAct = QAction(
158 UI.PixmapCache.getIcon("shapesAlignTop"), 158 UI.PixmapCache.getIcon("shapesAlignTop"), self.tr("Align Top"), self
159 self.tr("Align Top"), self) 159 )
160 self.alignMapper.setMapping( 160 self.alignMapper.setMapping(self.alignTopAct, Qt.AlignmentFlag.AlignTop)
161 self.alignTopAct, Qt.AlignmentFlag.AlignTop)
162 self.alignTopAct.triggered.connect(self.alignMapper.map) 161 self.alignTopAct.triggered.connect(self.alignMapper.map)
163 162
164 self.alignVCenterAct = QAction( 163 self.alignVCenterAct = QAction(
165 UI.PixmapCache.getIcon("shapesAlignVCenter"), 164 UI.PixmapCache.getIcon("shapesAlignVCenter"),
166 self.tr("Align Center Vertical"), self) 165 self.tr("Align Center Vertical"),
167 self.alignMapper.setMapping( 166 self,
168 self.alignVCenterAct, Qt.AlignmentFlag.AlignVCenter) 167 )
168 self.alignMapper.setMapping(self.alignVCenterAct, Qt.AlignmentFlag.AlignVCenter)
169 self.alignVCenterAct.triggered.connect(self.alignMapper.map) 169 self.alignVCenterAct.triggered.connect(self.alignMapper.map)
170 170
171 self.alignBottomAct = QAction( 171 self.alignBottomAct = QAction(
172 UI.PixmapCache.getIcon("shapesAlignBottom"), 172 UI.PixmapCache.getIcon("shapesAlignBottom"), self.tr("Align Bottom"), self
173 self.tr("Align Bottom"), self) 173 )
174 self.alignMapper.setMapping( 174 self.alignMapper.setMapping(self.alignBottomAct, Qt.AlignmentFlag.AlignBottom)
175 self.alignBottomAct, Qt.AlignmentFlag.AlignBottom)
176 self.alignBottomAct.triggered.connect(self.alignMapper.map) 175 self.alignBottomAct.triggered.connect(self.alignMapper.map)
177 176
178 def setLayoutActionsEnabled(self, enable): 177 def setLayoutActionsEnabled(self, enable):
179 """ 178 """
180 Public method to enable or disable the layout related actions. 179 Public method to enable or disable the layout related actions.
181 180
182 @param enable flag indicating the desired enable state 181 @param enable flag indicating the desired enable state
183 @type bool 182 @type bool
184 """ 183 """
185 self.rescanAct.setEnabled(enable) 184 self.rescanAct.setEnabled(enable)
186 self.relayoutAct.setEnabled(enable) 185 self.relayoutAct.setEnabled(enable)
187 186
188 def __checkSizeActions(self): 187 def __checkSizeActions(self):
189 """ 188 """
190 Private slot to set the enabled state of the size actions. 189 Private slot to set the enabled state of the size actions.
191 """ 190 """
192 diagramSize = self._getDiagramSize(10) 191 diagramSize = self._getDiagramSize(10)
197 self.decWidthAct.setEnabled(True) 196 self.decWidthAct.setEnabled(True)
198 if (sceneRect.height() - self.deltaSize) < diagramSize.height(): 197 if (sceneRect.height() - self.deltaSize) < diagramSize.height():
199 self.decHeightAct.setEnabled(False) 198 self.decHeightAct.setEnabled(False)
200 else: 199 else:
201 self.decHeightAct.setEnabled(True) 200 self.decHeightAct.setEnabled(True)
202 201
203 def __sceneChanged(self, areas): 202 def __sceneChanged(self, areas):
204 """ 203 """
205 Private slot called when the scene changes. 204 Private slot called when the scene changes.
206 205
207 @param areas list of rectangles that contain changes 206 @param areas list of rectangles that contain changes
208 @type list of QRectF 207 @type list of QRectF
209 """ 208 """
210 if len(self.scene().selectedItems()) > 0: 209 if len(self.scene().selectedItems()) > 0:
211 self.deleteShapeAct.setEnabled(True) 210 self.deleteShapeAct.setEnabled(True)
212 else: 211 else:
213 self.deleteShapeAct.setEnabled(False) 212 self.deleteShapeAct.setEnabled(False)
214 213
215 sceneRect = self.scene().sceneRect() 214 sceneRect = self.scene().sceneRect()
216 newWidth = width = sceneRect.width() 215 newWidth = width = sceneRect.width()
217 newHeight = height = sceneRect.height() 216 newHeight = height = sceneRect.height()
218 rect = self.scene().itemsBoundingRect() 217 rect = self.scene().itemsBoundingRect()
219 # calculate with 10 pixel border on each side 218 # calculate with 10 pixel border on each side
220 if sceneRect.right() - 10 < rect.right(): 219 if sceneRect.right() - 10 < rect.right():
221 newWidth = rect.right() + 10 220 newWidth = rect.right() + 10
222 if sceneRect.bottom() - 10 < rect.bottom(): 221 if sceneRect.bottom() - 10 < rect.bottom():
223 newHeight = rect.bottom() + 10 222 newHeight = rect.bottom() + 10
224 223
225 if newHeight != height or newWidth != width: 224 if newHeight != height or newWidth != width:
226 self.setSceneSize(newWidth, newHeight) 225 self.setSceneSize(newWidth, newHeight)
227 self.__checkSizeActions() 226 self.__checkSizeActions()
228 227
229 def initToolBar(self): 228 def initToolBar(self):
230 """ 229 """
231 Public method to populate a toolbar with our actions. 230 Public method to populate a toolbar with our actions.
232 231
233 @return the populated toolBar 232 @return the populated toolBar
234 @rtype QToolBar 233 @rtype QToolBar
235 """ 234 """
236 toolBar = QToolBar(self.tr("Graphics"), self) 235 toolBar = QToolBar(self.tr("Graphics"), self)
237 toolBar.setIconSize(UI.Config.ToolBarIconSize) 236 toolBar.setIconSize(UI.Config.ToolBarIconSize)
250 toolBar.addAction(self.decHeightAct) 249 toolBar.addAction(self.decHeightAct)
251 toolBar.addAction(self.setSizeAct) 250 toolBar.addAction(self.setSizeAct)
252 toolBar.addSeparator() 251 toolBar.addSeparator()
253 toolBar.addAction(self.rescanAct) 252 toolBar.addAction(self.rescanAct)
254 toolBar.addAction(self.relayoutAct) 253 toolBar.addAction(self.relayoutAct)
255 254
256 return toolBar 255 return toolBar
257 256
258 def filteredItems(self, items, itemType=UMLItem): 257 def filteredItems(self, items, itemType=UMLItem):
259 """ 258 """
260 Public method to filter a list of items. 259 Public method to filter a list of items.
261 260
262 @param items list of items as returned by the scene object 261 @param items list of items as returned by the scene object
263 @type QGraphicsItem 262 @type QGraphicsItem
264 @param itemType type to be filtered 263 @param itemType type to be filtered
265 @type class 264 @type class
266 @return list of interesting collision items 265 @return list of interesting collision items
267 @rtype QGraphicsItem 266 @rtype QGraphicsItem
268 """ 267 """
269 return [itm for itm in items if isinstance(itm, itemType)] 268 return [itm for itm in items if isinstance(itm, itemType)]
270 269
271 def selectItems(self, items): 270 def selectItems(self, items):
272 """ 271 """
273 Public method to select the given items. 272 Public method to select the given items.
274 273
275 @param items list of items to be selected 274 @param items list of items to be selected
276 @type list of QGraphicsItemItem 275 @type list of QGraphicsItemItem
277 """ 276 """
278 # step 1: deselect all items 277 # step 1: deselect all items
279 self.unselectItems() 278 self.unselectItems()
280 279
281 # step 2: select all given items 280 # step 2: select all given items
282 for itm in items: 281 for itm in items:
283 if isinstance(itm, UMLItem): 282 if isinstance(itm, UMLItem):
284 itm.setSelected(True) 283 itm.setSelected(True)
285 284
286 def selectItem(self, item): 285 def selectItem(self, item):
287 """ 286 """
288 Public method to select an item. 287 Public method to select an item.
289 288
290 @param item item to be selected 289 @param item item to be selected
291 @type QGraphicsItemItem 290 @type QGraphicsItemItem
292 """ 291 """
293 if isinstance(item, UMLItem): 292 if isinstance(item, UMLItem):
294 item.setSelected(not item.isSelected()) 293 item.setSelected(not item.isSelected())
295 294
296 def __deleteShape(self): 295 def __deleteShape(self):
297 """ 296 """
298 Private method to delete the selected shapes from the display. 297 Private method to delete the selected shapes from the display.
299 """ 298 """
300 for item in self.scene().selectedItems(): 299 for item in self.scene().selectedItems():
301 item.removeAssociations() 300 item.removeAssociations()
302 item.setSelected(False) 301 item.setSelected(False)
303 self.scene().removeItem(item) 302 self.scene().removeItem(item)
304 del item 303 del item
305 304
306 def __incWidth(self): 305 def __incWidth(self):
307 """ 306 """
308 Private method to handle the increase width context menu entry. 307 Private method to handle the increase width context menu entry.
309 """ 308 """
310 self.resizeScene(self.deltaSize, True) 309 self.resizeScene(self.deltaSize, True)
311 self.__checkSizeActions() 310 self.__checkSizeActions()
312 311
313 def __incHeight(self): 312 def __incHeight(self):
314 """ 313 """
315 Private method to handle the increase height context menu entry. 314 Private method to handle the increase height context menu entry.
316 """ 315 """
317 self.resizeScene(self.deltaSize, False) 316 self.resizeScene(self.deltaSize, False)
318 self.__checkSizeActions() 317 self.__checkSizeActions()
319 318
320 def __decWidth(self): 319 def __decWidth(self):
321 """ 320 """
322 Private method to handle the decrease width context menu entry. 321 Private method to handle the decrease width context menu entry.
323 """ 322 """
324 self.resizeScene(-self.deltaSize, True) 323 self.resizeScene(-self.deltaSize, True)
325 self.__checkSizeActions() 324 self.__checkSizeActions()
326 325
327 def __decHeight(self): 326 def __decHeight(self):
328 """ 327 """
329 Private method to handle the decrease height context menu entry. 328 Private method to handle the decrease height context menu entry.
330 """ 329 """
331 self.resizeScene(-self.deltaSize, False) 330 self.resizeScene(-self.deltaSize, False)
332 self.__checkSizeActions() 331 self.__checkSizeActions()
333 332
334 def __setSize(self): 333 def __setSize(self):
335 """ 334 """
336 Private method to handle the set size context menu entry. 335 Private method to handle the set size context menu entry.
337 """ 336 """
338 from .UMLSceneSizeDialog import UMLSceneSizeDialog 337 from .UMLSceneSizeDialog import UMLSceneSizeDialog
338
339 rect = self._getDiagramRect(10) 339 rect = self._getDiagramRect(10)
340 sceneRect = self.scene().sceneRect() 340 sceneRect = self.scene().sceneRect()
341 dlg = UMLSceneSizeDialog(sceneRect.width(), sceneRect.height(), 341 dlg = UMLSceneSizeDialog(
342 rect.width(), rect.height(), self) 342 sceneRect.width(), sceneRect.height(), rect.width(), rect.height(), self
343 )
343 if dlg.exec() == QDialog.DialogCode.Accepted: 344 if dlg.exec() == QDialog.DialogCode.Accepted:
344 width, height = dlg.getData() 345 width, height = dlg.getData()
345 self.setSceneSize(width, height) 346 self.setSceneSize(width, height)
346 self.__checkSizeActions() 347 self.__checkSizeActions()
347 348
348 def autoAdjustSceneSize(self, limit=False): 349 def autoAdjustSceneSize(self, limit=False):
349 """ 350 """
350 Public method to adjust the scene size to the diagram size. 351 Public method to adjust the scene size to the diagram size.
351 352
352 @param limit flag indicating to limit the scene to the 353 @param limit flag indicating to limit the scene to the
353 initial size 354 initial size
354 @type bool 355 @type bool
355 """ 356 """
356 super().autoAdjustSceneSize(limit=limit) 357 super().autoAdjustSceneSize(limit=limit)
357 self.__checkSizeActions() 358 self.__checkSizeActions()
358 359
359 def saveImage(self): 360 def saveImage(self):
360 """ 361 """
361 Public method to handle the save context menu entry. 362 Public method to handle the save context menu entry.
362 """ 363 """
363 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( 364 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter(
364 self, 365 self,
365 self.tr("Save Diagram"), 366 self.tr("Save Diagram"),
366 "", 367 "",
367 self.tr("Portable Network Graphics (*.png);;" 368 self.tr(
368 "Scalable Vector Graphics (*.svg)"), 369 "Portable Network Graphics (*.png);;" "Scalable Vector Graphics (*.svg)"
370 ),
369 "", 371 "",
370 EricFileDialog.DontConfirmOverwrite) 372 EricFileDialog.DontConfirmOverwrite,
373 )
371 if fname: 374 if fname:
372 fpath = pathlib.Path(fname) 375 fpath = pathlib.Path(fname)
373 if not fpath.suffix: 376 if not fpath.suffix:
374 ex = selectedFilter.split("(*")[1].split(")")[0] 377 ex = selectedFilter.split("(*")[1].split(")")[0]
375 if ex: 378 if ex:
376 fpath = fpath.with_suffix(ex) 379 fpath = fpath.with_suffix(ex)
377 if fpath.exists(): 380 if fpath.exists():
378 res = EricMessageBox.yesNo( 381 res = EricMessageBox.yesNo(
379 self, 382 self,
380 self.tr("Save Diagram"), 383 self.tr("Save Diagram"),
381 self.tr("<p>The file <b>{0}</b> already exists." 384 self.tr(
382 " Overwrite it?</p>").format(fpath), 385 "<p>The file <b>{0}</b> already exists." " Overwrite it?</p>"
383 icon=EricMessageBox.Warning) 386 ).format(fpath),
387 icon=EricMessageBox.Warning,
388 )
384 if not res: 389 if not res:
385 return 390 return
386 391
387 success = super().saveImage( 392 success = super().saveImage(str(fpath), fpath.suffix.upper())
388 str(fpath), fpath.suffix.upper())
389 if not success: 393 if not success:
390 EricMessageBox.critical( 394 EricMessageBox.critical(
391 self, 395 self,
392 self.tr("Save Diagram"), 396 self.tr("Save Diagram"),
393 self.tr( 397 self.tr(
394 """<p>The file <b>{0}</b> could not be saved.</p>""") 398 """<p>The file <b>{0}</b> could not be saved.</p>"""
395 .format(fpath)) 399 ).format(fpath),
396 400 )
401
397 def __relayout(self): 402 def __relayout(self):
398 """ 403 """
399 Private slot to handle the re-layout context menu entry. 404 Private slot to handle the re-layout context menu entry.
400 """ 405 """
401 self.__itemId = -1 406 self.__itemId = -1
402 self.scene().clear() 407 self.scene().clear()
403 self.relayout.emit() 408 self.relayout.emit()
404 409
405 def __rescan(self): 410 def __rescan(self):
406 """ 411 """
407 Private slot to handle the re-scan context menu entry. 412 Private slot to handle the re-scan context menu entry.
408 """ 413 """
409 # 1. save positions of all items and names of selected items 414 # 1. save positions of all items and names of selected items
413 name = item.getName() 418 name = item.getName()
414 if name: 419 if name:
415 itemPositions[name] = (item.x(), item.y()) 420 itemPositions[name] = (item.x(), item.y())
416 if item.isSelected(): 421 if item.isSelected():
417 selectedItems.append(name) 422 selectedItems.append(name)
418 423
419 # 2. save 424 # 2. save
420 425
421 # 2. re-layout the diagram 426 # 2. re-layout the diagram
422 self.__relayout() 427 self.__relayout()
423 428
424 # 3. move known items to the saved positions 429 # 3. move known items to the saved positions
425 for item in self.filteredItems(self.scene().items(), UMLItem): 430 for item in self.filteredItems(self.scene().items(), UMLItem):
426 name = item.getName() 431 name = item.getName()
427 if name in itemPositions: 432 if name in itemPositions:
428 item.setPos(*itemPositions[name]) 433 item.setPos(*itemPositions[name])
429 if name in selectedItems: 434 if name in selectedItems:
430 item.setSelected(True) 435 item.setSelected(True)
431 436
432 def printDiagram(self): 437 def printDiagram(self):
433 """ 438 """
434 Public slot called to print the diagram. 439 Public slot called to print the diagram.
435 """ 440 """
436 printer = QPrinter(mode=QPrinter.PrinterMode.PrinterResolution) 441 printer = QPrinter(mode=QPrinter.PrinterMode.PrinterResolution)
441 printer.setColorMode(QPrinter.ColorMode.GrayScale) 446 printer.setColorMode(QPrinter.ColorMode.GrayScale)
442 if Preferences.getPrinter("FirstPageFirst"): 447 if Preferences.getPrinter("FirstPageFirst"):
443 printer.setPageOrder(QPrinter.PageOrder.FirstPageFirst) 448 printer.setPageOrder(QPrinter.PageOrder.FirstPageFirst)
444 else: 449 else:
445 printer.setPageOrder(QPrinter.PageOrder.LastPageFirst) 450 printer.setPageOrder(QPrinter.PageOrder.LastPageFirst)
446 printer.setPageMargins(QMarginsF( 451 printer.setPageMargins(
447 Preferences.getPrinter("LeftMargin") * 10, 452 QMarginsF(
448 Preferences.getPrinter("TopMargin") * 10, 453 Preferences.getPrinter("LeftMargin") * 10,
449 Preferences.getPrinter("RightMargin") * 10, 454 Preferences.getPrinter("TopMargin") * 10,
450 Preferences.getPrinter("BottomMargin") * 10), 455 Preferences.getPrinter("RightMargin") * 10,
451 QPageLayout.Unit.Millimeter 456 Preferences.getPrinter("BottomMargin") * 10,
457 ),
458 QPageLayout.Unit.Millimeter,
452 ) 459 )
453 printerName = Preferences.getPrinter("PrinterName") 460 printerName = Preferences.getPrinter("PrinterName")
454 if printerName: 461 if printerName:
455 printer.setPrinterName(printerName) 462 printer.setPrinterName(printerName)
456 463
457 printDialog = QPrintDialog(printer, self) 464 printDialog = QPrintDialog(printer, self)
458 if printDialog.exec(): 465 if printDialog.exec():
459 super().printDiagram( 466 super().printDiagram(printer, self.diagramName)
460 printer, self.diagramName) 467
461
462 def printPreviewDiagram(self): 468 def printPreviewDiagram(self):
463 """ 469 """
464 Public slot called to show a print preview of the diagram. 470 Public slot called to show a print preview of the diagram.
465 """ 471 """
466 from PyQt6.QtPrintSupport import QPrintPreviewDialog 472 from PyQt6.QtPrintSupport import QPrintPreviewDialog
467 473
468 printer = QPrinter(mode=QPrinter.PrinterMode.PrinterResolution) 474 printer = QPrinter(mode=QPrinter.PrinterMode.PrinterResolution)
469 printer.setFullPage(True) 475 printer.setFullPage(True)
470 if Preferences.getPrinter("ColorMode"): 476 if Preferences.getPrinter("ColorMode"):
471 printer.setColorMode(QPrinter.ColorMode.Color) 477 printer.setColorMode(QPrinter.ColorMode.Color)
472 else: 478 else:
473 printer.setColorMode(QPrinter.ColorMode.GrayScale) 479 printer.setColorMode(QPrinter.ColorMode.GrayScale)
474 if Preferences.getPrinter("FirstPageFirst"): 480 if Preferences.getPrinter("FirstPageFirst"):
475 printer.setPageOrder(QPrinter.PageOrder.FirstPageFirst) 481 printer.setPageOrder(QPrinter.PageOrder.FirstPageFirst)
476 else: 482 else:
477 printer.setPageOrder(QPrinter.PageOrder.LastPageFirst) 483 printer.setPageOrder(QPrinter.PageOrder.LastPageFirst)
478 printer.setPageMargins(QMarginsF( 484 printer.setPageMargins(
479 Preferences.getPrinter("LeftMargin") * 10, 485 QMarginsF(
480 Preferences.getPrinter("TopMargin") * 10, 486 Preferences.getPrinter("LeftMargin") * 10,
481 Preferences.getPrinter("RightMargin") * 10, 487 Preferences.getPrinter("TopMargin") * 10,
482 Preferences.getPrinter("BottomMargin") * 10), 488 Preferences.getPrinter("RightMargin") * 10,
483 QPageLayout.Unit.Millimeter 489 Preferences.getPrinter("BottomMargin") * 10,
490 ),
491 QPageLayout.Unit.Millimeter,
484 ) 492 )
485 printerName = Preferences.getPrinter("PrinterName") 493 printerName = Preferences.getPrinter("PrinterName")
486 if printerName: 494 if printerName:
487 printer.setPrinterName(printerName) 495 printer.setPrinterName(printerName)
488 496
489 preview = QPrintPreviewDialog(printer, self) 497 preview = QPrintPreviewDialog(printer, self)
490 preview.paintRequested[QPrinter].connect(self.__printPreviewPrint) 498 preview.paintRequested[QPrinter].connect(self.__printPreviewPrint)
491 preview.exec() 499 preview.exec()
492 500
493 def __printPreviewPrint(self, printer): 501 def __printPreviewPrint(self, printer):
494 """ 502 """
495 Private slot to generate a print preview. 503 Private slot to generate a print preview.
496 504
497 @param printer reference to the printer object 505 @param printer reference to the printer object
498 @type QPrinter 506 @type QPrinter
499 """ 507 """
500 super().printDiagram(printer, self.diagramName) 508 super().printDiagram(printer, self.diagramName)
501 509
502 def setDiagramName(self, name): 510 def setDiagramName(self, name):
503 """ 511 """
504 Public slot to set the diagram name. 512 Public slot to set the diagram name.
505 513
506 @param name diagram name 514 @param name diagram name
507 @type str 515 @type str
508 """ 516 """
509 self.diagramName = name 517 self.diagramName = name
510 518
511 def __alignShapes(self, alignment): 519 def __alignShapes(self, alignment):
512 """ 520 """
513 Private slot to align the selected shapes. 521 Private slot to align the selected shapes.
514 522
515 @param alignment alignment type 523 @param alignment alignment type
516 @type Qt.AlignmentFlag 524 @type Qt.AlignmentFlag
517 """ 525 """
518 # step 1: get all selected items 526 # step 1: get all selected items
519 items = self.scene().selectedItems() 527 items = self.scene().selectedItems()
520 if len(items) <= 1: 528 if len(items) <= 1:
521 return 529 return
522 530
523 # step 2: find the index of the item to align in relation to 531 # step 2: find the index of the item to align in relation to
524 amount = None 532 amount = None
525 for i, item in enumerate(items): 533 for i, item in enumerate(items):
526 rect = item.sceneBoundingRect() 534 rect = item.sceneBoundingRect()
527 if alignment == Qt.AlignmentFlag.AlignLeft: 535 if alignment == Qt.AlignmentFlag.AlignLeft:
548 # __IGNORE_WARNING_Y102__ 556 # __IGNORE_WARNING_Y102__
549 if amount is None or rect.height() > amount: 557 if amount is None or rect.height() > amount:
550 amount = rect.height() 558 amount = rect.height()
551 index = i 559 index = i
552 rect = items[index].sceneBoundingRect() 560 rect = items[index].sceneBoundingRect()
553 561
554 # step 3: move the other items 562 # step 3: move the other items
555 for i, item in enumerate(items): 563 for i, item in enumerate(items):
556 if i == index: 564 if i == index:
557 continue 565 continue
558 itemrect = item.sceneBoundingRect() 566 itemrect = item.sceneBoundingRect()
559 xOffset = yOffset = 0 567 xOffset = yOffset = 0
560 if alignment == Qt.AlignmentFlag.AlignLeft: 568 if alignment == Qt.AlignmentFlag.AlignLeft:
561 xOffset = rect.x() - itemrect.x() 569 xOffset = rect.x() - itemrect.x()
562 elif alignment == Qt.AlignmentFlag.AlignRight: 570 elif alignment == Qt.AlignmentFlag.AlignRight:
563 xOffset = ( 571 xOffset = (rect.x() + rect.width()) - (itemrect.x() + itemrect.width())
564 (rect.x() + rect.width()) -
565 (itemrect.x() + itemrect.width())
566 )
567 elif alignment == Qt.AlignmentFlag.AlignHCenter: 572 elif alignment == Qt.AlignmentFlag.AlignHCenter:
568 xOffset = ( 573 xOffset = (rect.x() + rect.width() // 2) - (
569 (rect.x() + rect.width() // 2) - 574 itemrect.x() + itemrect.width() // 2
570 (itemrect.x() + itemrect.width() // 2)
571 ) 575 )
572 elif alignment == Qt.AlignmentFlag.AlignTop: 576 elif alignment == Qt.AlignmentFlag.AlignTop:
573 yOffset = rect.y() - itemrect.y() 577 yOffset = rect.y() - itemrect.y()
574 elif alignment == Qt.AlignmentFlag.AlignBottom: 578 elif alignment == Qt.AlignmentFlag.AlignBottom:
575 yOffset = ( 579 yOffset = (rect.y() + rect.height()) - (
576 (rect.y() + rect.height()) - 580 itemrect.y() + itemrect.height()
577 (itemrect.y() + itemrect.height())
578 ) 581 )
579 elif alignment == Qt.AlignmentFlag.AlignVCenter: 582 elif alignment == Qt.AlignmentFlag.AlignVCenter:
580 yOffset = ( 583 yOffset = (rect.y() + rect.height() // 2) - (
581 (rect.y() + rect.height() // 2) - 584 itemrect.y() + itemrect.height() // 2
582 (itemrect.y() + itemrect.height() // 2)
583 ) 585 )
584 item.moveBy(xOffset, yOffset) 586 item.moveBy(xOffset, yOffset)
585 587
586 self.scene().update() 588 self.scene().update()
587 589
588 def __itemsBoundingRect(self, items): 590 def __itemsBoundingRect(self, items):
589 """ 591 """
590 Private method to calculate the bounding rectangle of the given items. 592 Private method to calculate the bounding rectangle of the given items.
591 593
592 @param items list of items to operate on 594 @param items list of items to operate on
593 @type list of UMLItem 595 @type list of UMLItem
594 @return bounding rectangle 596 @return bounding rectangle
595 @rtype QRectF 597 @rtype QRectF
596 """ 598 """
604 left = min(rect.left(), left) 606 left = min(rect.left(), left)
605 right = max(rect.right(), right) 607 right = max(rect.right(), right)
606 top = min(rect.top(), top) 608 top = min(rect.top(), top)
607 bottom = max(rect.bottom(), bottom) 609 bottom = max(rect.bottom(), bottom)
608 return QRectF(left, top, right - left, bottom - top) 610 return QRectF(left, top, right - left, bottom - top)
609 611
610 def keyPressEvent(self, evt): 612 def keyPressEvent(self, evt):
611 """ 613 """
612 Protected method handling key press events. 614 Protected method handling key press events.
613 615
614 @param evt reference to the key event 616 @param evt reference to the key event
615 @type QKeyEvent 617 @type QKeyEvent
616 """ 618 """
617 key = evt.key() 619 key = evt.key()
618 if key in [Qt.Key.Key_Up, Qt.Key.Key_Down, Qt.Key.Key_Left, 620 if key in [Qt.Key.Key_Up, Qt.Key.Key_Down, Qt.Key.Key_Left, Qt.Key.Key_Right]:
619 Qt.Key.Key_Right]:
620 items = self.filteredItems(self.scene().selectedItems()) 621 items = self.filteredItems(self.scene().selectedItems())
621 if items: 622 if items:
622 if evt.modifiers() & Qt.KeyboardModifier.ControlModifier: 623 if evt.modifiers() & Qt.KeyboardModifier.ControlModifier:
623 stepSize = 50 624 stepSize = 50
624 else: 625 else:
637 dy = 0 638 dy = 0
638 for item in items: 639 for item in items:
639 item.moveBy(dx, dy) 640 item.moveBy(dx, dy)
640 evt.accept() 641 evt.accept()
641 return 642 return
642 643
643 super().keyPressEvent(evt) 644 super().keyPressEvent(evt)
644 645
645 def wheelEvent(self, evt): 646 def wheelEvent(self, evt):
646 """ 647 """
647 Protected method to handle wheel events. 648 Protected method to handle wheel events.
648 649
649 @param evt reference to the wheel event 650 @param evt reference to the wheel event
650 @type QWheelEvent 651 @type QWheelEvent
651 """ 652 """
652 if evt.modifiers() & Qt.KeyboardModifier.ControlModifier: 653 if evt.modifiers() & Qt.KeyboardModifier.ControlModifier:
653 delta = evt.angleDelta().y() 654 delta = evt.angleDelta().y()
655 self.zoomOut() 656 self.zoomOut()
656 elif delta > 0: 657 elif delta > 0:
657 self.zoomIn() 658 self.zoomIn()
658 evt.accept() 659 evt.accept()
659 return 660 return
660 661
661 super().wheelEvent(evt) 662 super().wheelEvent(evt)
662 663
663 def event(self, evt): 664 def event(self, evt):
664 """ 665 """
665 Public method handling events. 666 Public method handling events.
666 667
667 @param evt reference to the event 668 @param evt reference to the event
668 @type QEvent 669 @type QEvent
669 @return flag indicating, if the event was handled 670 @return flag indicating, if the event was handled
670 @rtype bool 671 @rtype bool
671 """ 672 """
672 if evt.type() == QEvent.Type.Gesture: 673 if evt.type() == QEvent.Type.Gesture:
673 self.gestureEvent(evt) 674 self.gestureEvent(evt)
674 return True 675 return True
675 676
676 return super().event(evt) 677 return super().event(evt)
677 678
678 def gestureEvent(self, evt): 679 def gestureEvent(self, evt):
679 """ 680 """
680 Protected method handling gesture events. 681 Protected method handling gesture events.
681 682
682 @param evt reference to the gesture event 683 @param evt reference to the gesture event
683 @type QGestureEvent 684 @type QGestureEvent
684 """ 685 """
685 pinch = evt.gesture(Qt.GestureType.PinchGesture) 686 pinch = evt.gesture(Qt.GestureType.PinchGesture)
686 if pinch: 687 if pinch:
687 if pinch.state() == Qt.GestureState.GestureStarted: 688 if pinch.state() == Qt.GestureState.GestureStarted:
688 pinch.setTotalScaleFactor(self.zoom() / 100.0) 689 pinch.setTotalScaleFactor(self.zoom() / 100.0)
689 elif pinch.state() == Qt.GestureState.GestureUpdated: 690 elif pinch.state() == Qt.GestureState.GestureUpdated:
690 self.setZoom(int(pinch.totalScaleFactor() * 100)) 691 self.setZoom(int(pinch.totalScaleFactor() * 100))
691 evt.accept() 692 evt.accept()
692 693
693 def getItemId(self): 694 def getItemId(self):
694 """ 695 """
695 Public method to get the ID to be assigned to an item. 696 Public method to get the ID to be assigned to an item.
696 697
697 @return item ID 698 @return item ID
698 @rtype int 699 @rtype int
699 """ 700 """
700 self.__itemId += 1 701 self.__itemId += 1
701 return self.__itemId 702 return self.__itemId
702 703
703 def findItem(self, itemId): 704 def findItem(self, itemId):
704 """ 705 """
705 Public method to find an UML item based on the ID. 706 Public method to find an UML item based on the ID.
706 707
707 @param itemId of the item to search for 708 @param itemId of the item to search for
708 @type int 709 @type int
709 @return item found or None 710 @return item found or None
710 @rtype UMLItem 711 @rtype UMLItem
711 """ 712 """
713 try: 714 try:
714 if item.getId() == itemId: 715 if item.getId() == itemId:
715 return item 716 return item
716 except AttributeError: 717 except AttributeError:
717 continue 718 continue
718 719
719 return None 720 return None
720 721
721 def findItemByName(self, name): 722 def findItemByName(self, name):
722 """ 723 """
723 Public method to find an UML item based on its name. 724 Public method to find an UML item based on its name.
724 725
725 @param name name to look for 726 @param name name to look for
726 @type str 727 @type str
727 @return item found or None 728 @return item found or None
728 @rtype UMLItem 729 @rtype UMLItem
729 """ 730 """
731 try: 732 try:
732 if item.getName() == name: 733 if item.getName() == name:
733 return item 734 return item
734 except AttributeError: 735 except AttributeError:
735 continue 736 continue
736 737
737 return None 738 return None
738 739
739 def parsePersistenceData(self, version, data): 740 def parsePersistenceData(self, version, data):
740 """ 741 """
741 Public method to parse persisted data. 742 Public method to parse persisted data.
742 743
743 @param version version of the data 744 @param version version of the data
744 @type str 745 @type str
745 @param data persisted data to be parsed 746 @param data persisted data to be parsed
746 @type list of str 747 @type list of str
747 @return tuple of flag indicating success (boolean) and faulty line 748 @return tuple of flag indicating success (boolean) and faulty line
748 number 749 number
749 @rtype int 750 @rtype int
750 """ 751 """
751 umlItems = {} 752 umlItems = {}
752 753
753 if not data[0].startswith("diagram_name:"): 754 if not data[0].startswith("diagram_name:"):
754 return False, 0 755 return False, 0
755 self.diagramName = data[0].split(": ", 1)[1].strip() 756 self.diagramName = data[0].split(": ", 1)[1].strip()
756 757
757 from .ClassItem import ClassItem 758 from .ClassItem import ClassItem
758 from .ModuleItem import ModuleItem 759 from .ModuleItem import ModuleItem
759 from .PackageItem import PackageItem 760 from .PackageItem import PackageItem
760 from .AssociationItem import AssociationItem 761 from .AssociationItem import AssociationItem
761 762
762 for linenum, line in enumerate(data[1:], start=1): 763 for linenum, line in enumerate(data[1:], start=1):
763 if not line.startswith(("item:", "association:")): 764 if not line.startswith(("item:", "association:")):
764 return False, linenum 765 return False, linenum
765 766
766 key, value = line.split(": ", 1) 767 key, value = line.split(": ", 1)
767 if key == "item": 768 if key == "item":
768 itemId, x, y, itemType, itemData = value.split(", ", 4) 769 itemId, x, y, itemType, itemData = value.split(", ", 4)
769 try: 770 try:
770 itemId = int(itemId.split("=", 1)[1].strip()) 771 itemId = int(itemId.split("=", 1)[1].strip())
771 x = float(x.split("=", 1)[1].strip()) 772 x = float(x.split("=", 1)[1].strip())
772 y = float(y.split("=", 1)[1].strip()) 773 y = float(y.split("=", 1)[1].strip())
773 itemType = itemType.split("=", 1)[1].strip() 774 itemType = itemType.split("=", 1)[1].strip()
774 if itemType == ClassItem.ItemType: 775 if itemType == ClassItem.ItemType:
775 itm = ClassItem(x=0, y=0, scene=self.scene(), 776 itm = ClassItem(
776 colors=self.getDrawingColors()) 777 x=0, y=0, scene=self.scene(), colors=self.getDrawingColors()
778 )
777 elif itemType == ModuleItem.ItemType: 779 elif itemType == ModuleItem.ItemType:
778 itm = ModuleItem(x=0, y=0, scene=self.scene(), 780 itm = ModuleItem(
779 colors=self.getDrawingColors()) 781 x=0, y=0, scene=self.scene(), colors=self.getDrawingColors()
782 )
780 elif itemType == PackageItem.ItemType: 783 elif itemType == PackageItem.ItemType:
781 itm = PackageItem(x=0, y=0, scene=self.scene(), 784 itm = PackageItem(
782 colors=self.getDrawingColors()) 785 x=0, y=0, scene=self.scene(), colors=self.getDrawingColors()
786 )
783 itm.setPos(x, y) 787 itm.setPos(x, y)
784 itm.setId(itemId) 788 itm.setId(itemId)
785 umlItems[itemId] = itm 789 umlItems[itemId] = itm
786 if not itm.parseItemDataString(version, itemData): 790 if not itm.parseItemDataString(version, itemData):
787 return False, linenum 791 return False, linenum
788 except ValueError: 792 except ValueError:
789 return False, linenum 793 return False, linenum
790 elif key == "association": 794 elif key == "association":
791 srcId, dstId, assocType, topToBottom = ( 795 (
792 AssociationItem.parseAssociationItemDataString( 796 srcId,
793 value.strip()) 797 dstId,
798 assocType,
799 topToBottom,
800 ) = AssociationItem.parseAssociationItemDataString(value.strip())
801 assoc = AssociationItem(
802 umlItems[srcId], umlItems[dstId], assocType, topToBottom
794 ) 803 )
795 assoc = AssociationItem(umlItems[srcId], umlItems[dstId],
796 assocType, topToBottom)
797 self.scene().addItem(assoc) 804 self.scene().addItem(assoc)
798 805
799 return True, -1 806 return True, -1
800 807
801 def toDict(self): 808 def toDict(self):
802 """ 809 """
803 Public method to collect data to be persisted. 810 Public method to collect data to be persisted.
804 811
805 @return dictionary containing data to be persisted 812 @return dictionary containing data to be persisted
806 @rtype dict 813 @rtype dict
807 """ 814 """
808 items = [ 815 items = [
809 item.toDict() 816 item.toDict() for item in self.filteredItems(self.scene().items(), UMLItem)
810 for item in self.filteredItems(self.scene().items(), UMLItem)
811 ] 817 ]
812 818
813 from .AssociationItem import AssociationItem 819 from .AssociationItem import AssociationItem
820
814 associations = [ 821 associations = [
815 assoc.toDict() 822 assoc.toDict()
816 for assoc in self.filteredItems(self.scene().items(), 823 for assoc in self.filteredItems(self.scene().items(), AssociationItem)
817 AssociationItem)
818 ] 824 ]
819 825
820 data = { 826 data = {
821 "diagram_name": self.diagramName, 827 "diagram_name": self.diagramName,
822 "items": items, 828 "items": items,
823 "associations": associations, 829 "associations": associations,
824 } 830 }
825 831
826 return data 832 return data
827 833
828 def fromDict(self, version, data): 834 def fromDict(self, version, data):
829 """ 835 """
830 Public method to populate the class with data persisted by 'toDict()'. 836 Public method to populate the class with data persisted by 'toDict()'.
831 837
832 @param version version of the data 838 @param version version of the data
833 @type str 839 @type str
834 @param data dictionary containing the persisted data 840 @param data dictionary containing the persisted data
835 @type dict 841 @type dict
836 @return flag indicating success 842 @return flag indicating success
839 from .UMLItem import UMLItem 845 from .UMLItem import UMLItem
840 from .ClassItem import ClassItem 846 from .ClassItem import ClassItem
841 from .ModuleItem import ModuleItem 847 from .ModuleItem import ModuleItem
842 from .PackageItem import PackageItem 848 from .PackageItem import PackageItem
843 from .AssociationItem import AssociationItem 849 from .AssociationItem import AssociationItem
844 850
845 umlItems = {} 851 umlItems = {}
846 852
847 try: 853 try:
848 self.diagramName = data["diagram_name"] 854 self.diagramName = data["diagram_name"]
849 for itemData in data["items"]: 855 for itemData in data["items"]:
850 if itemData["type"] == UMLItem.ItemType: 856 if itemData["type"] == UMLItem.ItemType:
851 itm = UMLItem.fromDict( 857 itm = UMLItem.fromDict(itemData, colors=self.getDrawingColors())
852 itemData, colors=self.getDrawingColors())
853 elif itemData["type"] == ClassItem.ItemType: 858 elif itemData["type"] == ClassItem.ItemType:
854 itm = ClassItem.fromDict( 859 itm = ClassItem.fromDict(itemData, colors=self.getDrawingColors())
855 itemData, colors=self.getDrawingColors())
856 elif itemData["type"] == ModuleItem.ItemType: 860 elif itemData["type"] == ModuleItem.ItemType:
857 itm = ModuleItem.fromDict( 861 itm = ModuleItem.fromDict(itemData, colors=self.getDrawingColors())
858 itemData, colors=self.getDrawingColors())
859 elif itemData["type"] == PackageItem.ItemType: 862 elif itemData["type"] == PackageItem.ItemType:
860 itm = PackageItem.fromDict( 863 itm = PackageItem.fromDict(itemData, colors=self.getDrawingColors())
861 itemData, colors=self.getDrawingColors())
862 if itm is not None: 864 if itm is not None:
863 umlItems[itm.getId()] = itm 865 umlItems[itm.getId()] = itm
864 self.scene().addItem(itm) 866 self.scene().addItem(itm)
865 867
866 for assocData in data["associations"]: 868 for assocData in data["associations"]:
867 assoc = AssociationItem.fromDict( 869 assoc = AssociationItem.fromDict(
868 assocData, umlItems, colors=self.getDrawingColors()) 870 assocData, umlItems, colors=self.getDrawingColors()
871 )
869 self.scene().addItem(assoc) 872 self.scene().addItem(assoc)
870 873
871 return True 874 return True
872 except KeyError: 875 except KeyError:
873 return False 876 return False

eric ide

mercurial