src/eric7/Graphics/UMLItem.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2004 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the UMLItem base class.
8 """
9
10 from PyQt6.QtCore import Qt, QSizeF
11 from PyQt6.QtGui import QColor, QPen
12 from PyQt6.QtWidgets import QGraphicsItem, QGraphicsRectItem, QStyle
13
14 import Preferences
15
16
17 class UMLModel:
18 """
19 Class implementing the UMLModel base class.
20 """
21 def __init__(self, name):
22 """
23 Constructor
24
25 @param name package name
26 @type str
27 """
28 self.name = name
29
30 def getName(self):
31 """
32 Public method to retrieve the model name.
33
34 @return model name
35 @rtype str
36 """
37 return self.name
38
39
40 class UMLItem(QGraphicsRectItem):
41 """
42 Class implementing the UMLItem base class.
43 """
44 ItemType = "UMLItem"
45
46 def __init__(self, model=None, x=0, y=0, rounded=False, colors=None,
47 parent=None):
48 """
49 Constructor
50
51 @param model UML model containing the item data
52 @type UMLModel
53 @param x x-coordinate
54 @type int
55 @param y y-coordinate
56 @type int
57 @param rounded flag indicating a rounded corner
58 @type bool
59 @param colors tuple containing the foreground and background colors
60 @type tuple of (QColor, QColor)
61 @param parent reference to the parent object
62 @type QGraphicsItem
63 """
64 super().__init__(parent)
65 self.model = model
66
67 if colors is None:
68 self._colors = (QColor(Qt.GlobalColor.black),
69 QColor(Qt.GlobalColor.white))
70 else:
71 self._colors = colors
72 self.setPen(QPen(self._colors[0]))
73
74 self.font = Preferences.getGraphics("Font")
75 self.margin = 5
76 self.associations = []
77 self.shouldAdjustAssociations = False
78 self.__id = -1
79
80 self.setRect(x, y, 60, 30)
81
82 if rounded:
83 p = self.pen()
84 p.setCapStyle(Qt.PenCapStyle.RoundCap)
85 p.setJoinStyle(Qt.PenJoinStyle.RoundJoin)
86
87 self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True)
88 self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, True)
89 self.setFlag(
90 QGraphicsItem.GraphicsItemFlag.ItemSendsGeometryChanges, True)
91
92 def getName(self):
93 """
94 Public method to retrieve the item name.
95
96 @return item name
97 @rtype str
98 """
99 if self.model:
100 return self.model.name
101 else:
102 return ""
103
104 def setSize(self, width, height):
105 """
106 Public method to set the rectangles size.
107
108 @param width width of the rectangle
109 @type float
110 @param height height of the rectangle
111 @type float
112 """
113 rect = self.rect()
114 rect.setSize(QSizeF(width, height))
115 self.setRect(rect)
116
117 def addAssociation(self, assoc):
118 """
119 Public method to add an association to this widget.
120
121 @param assoc association to be added
122 @type AssociationWidget
123 """
124 if assoc and assoc not in self.associations:
125 self.associations.append(assoc)
126
127 def removeAssociation(self, assoc):
128 """
129 Public method to remove an association to this widget.
130
131 @param assoc association to be removed
132 @type AssociationWidget
133 """
134 if assoc and assoc in self.associations:
135 self.associations.remove(assoc)
136
137 def removeAssociations(self):
138 """
139 Public method to remove all associations of this widget.
140 """
141 for assoc in self.associations[:]:
142 assoc.unassociate()
143 assoc.hide()
144 del assoc
145
146 def adjustAssociations(self):
147 """
148 Public method to adjust the associations to widget movements.
149 """
150 if self.shouldAdjustAssociations:
151 for assoc in self.associations:
152 assoc.widgetMoved()
153 self.shouldAdjustAssociations = False
154
155 def moveBy(self, dx, dy):
156 """
157 Public overriden method to move the widget relative.
158
159 @param dx relative movement in x-direction
160 @type float
161 @param dy relative movement in y-direction
162 @type float
163 """
164 super().moveBy(dx, dy)
165 self.adjustAssociations()
166
167 def setPos(self, x, y):
168 """
169 Public overriden method to set the items position.
170
171 @param x absolute x-position
172 @type float
173 @param y absolute y-position
174 @type float
175 """
176 super().setPos(x, y)
177 self.adjustAssociations()
178
179 def itemChange(self, change, value):
180 """
181 Public method called when an items state changes.
182
183 @param change the item's change
184 @type QGraphicsItem.GraphicsItemChange
185 @param value the value of the change
186 @return adjusted values
187 """
188 if change == QGraphicsItem.GraphicsItemChange.ItemPositionChange:
189 # 1. remember to adjust associations
190 self.shouldAdjustAssociations = True
191
192 # 2. ensure the new position is inside the scene
193 scene = self.scene()
194 if scene:
195 rect = scene.sceneRect()
196 if not rect.contains(value):
197 # keep the item inside the scene
198 value.setX(min(rect.right(), max(value.x(), rect.left())))
199 value.setY(min(rect.bottom(), max(value.y(), rect.top())))
200 return value
201
202 return QGraphicsItem.itemChange(self, change, value)
203
204 def paint(self, painter, option, widget=None):
205 """
206 Public method to paint the item in local coordinates.
207
208 @param painter reference to the painter object
209 @type QPainter
210 @param option style options
211 @type QStyleOptionGraphicsItem
212 @param widget optional reference to the widget painted on
213 @type QWidget
214 """
215 pen = self.pen()
216 if (
217 (option.state & QStyle.StateFlag.State_Selected) ==
218 QStyle.StateFlag.State_Selected
219 ):
220 pen.setWidth(2)
221 else:
222 pen.setWidth(1)
223
224 painter.setPen(pen)
225 painter.setBrush(self.brush())
226 painter.drawRect(self.rect())
227 self.adjustAssociations()
228
229 def setId(self, itemId):
230 """
231 Public method to assign an ID to the item.
232
233 @param itemId assigned ID
234 @type int
235 """
236 self.__id = itemId
237
238 def getId(self):
239 """
240 Public method to get the item ID.
241
242 @return ID of the item
243 @rtype int
244 """
245 return self.__id
246
247 def getItemType(self):
248 """
249 Public method to get the item's type.
250
251 @return item type
252 @rtype str
253 """
254 return self.ItemType
255
256 def parseItemDataString(self, version, data):
257 """
258 Public method to parse the given persistence data.
259
260 @param version version of the data
261 @type str
262 @param data persisted data to be parsed
263 @type str
264 @return flag indicating success
265 @rtype bool
266 """
267 return True
268
269 def toDict(self):
270 """
271 Public method to collect data to be persisted.
272
273 @return dictionary containing data to be persisted
274 @rtype dict
275 """
276 return {
277 "id": self.getId(),
278 "x": self.x(),
279 "y": self.y(),
280 "type": self.getItemType(),
281 "model_name": self.model.getName(),
282 }
283
284 @classmethod
285 def fromDict(cls, data, colors=None):
286 """
287 Class method to create a generic UML item from persisted data.
288
289 @param data dictionary containing the persisted data as generated
290 by toDict()
291 @type dict
292 @param colors tuple containing the foreground and background colors
293 @type tuple of (QColor, QColor)
294 @return created UML item
295 @rtype UMLItem
296 """
297 try:
298 model = UMLModel(data["model_name"])
299 itm = cls(model=model,
300 x=0,
301 y=0,
302 colors=colors)
303 itm.setPos(data["x"], data["y"])
304 itm.setId(data["id"])
305 return itm
306 except KeyError:
307 return None

eric ide

mercurial