src/eric7/Graphics/ClassItem.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
18 18
19 class ClassModel(UMLModel): 19 class ClassModel(UMLModel):
20 """ 20 """
21 Class implementing the class model. 21 Class implementing the class model.
22 """ 22 """
23 def __init__(self, name, methods=None, instanceAttributes=None, 23
24 classAttributes=None): 24 def __init__(
25 self, name, methods=None, instanceAttributes=None, classAttributes=None
26 ):
25 """ 27 """
26 Constructor 28 Constructor
27 29
28 @param name the class name 30 @param name the class name
29 @type str 31 @type str
30 @param methods list of method names of the class 32 @param methods list of method names of the class
31 @type list of str 33 @type list of str
32 @param instanceAttributes list of instance attribute names of the class 34 @param instanceAttributes list of instance attribute names of the class
33 @type list of str 35 @type list of str
34 @param classAttributes list of class attribute names of the class 36 @param classAttributes list of class attribute names of the class
35 @type list of str 37 @type list of str
36 """ 38 """
37 super().__init__(name) 39 super().__init__(name)
38 40
39 self.methods = [] if methods is None else methods[:] 41 self.methods = [] if methods is None else methods[:]
40 self.instanceAttributes = ( 42 self.instanceAttributes = (
41 [] 43 [] if instanceAttributes is None else instanceAttributes[:]
42 if instanceAttributes is None else
43 instanceAttributes[:]
44 ) 44 )
45 self.classAttributes = ( 45 self.classAttributes = [] if classAttributes is None else classAttributes[:]
46 [] 46
47 if classAttributes is None else
48 classAttributes[:]
49 )
50
51 def addMethod(self, method): 47 def addMethod(self, method):
52 """ 48 """
53 Public method to add a method to the class model. 49 Public method to add a method to the class model.
54 50
55 @param method method name to be added 51 @param method method name to be added
56 @type str 52 @type str
57 """ 53 """
58 self.methods.append(method) 54 self.methods.append(method)
59 55
60 def addInstanceAttribute(self, attribute): 56 def addInstanceAttribute(self, attribute):
61 """ 57 """
62 Public method to add an instance attribute to the class model. 58 Public method to add an instance attribute to the class model.
63 59
64 @param attribute instance attribute name to be added 60 @param attribute instance attribute name to be added
65 @type str 61 @type str
66 """ 62 """
67 self.instanceAttributes.append(attribute) 63 self.instanceAttributes.append(attribute)
68 64
69 def addClassAttribute(self, attribute): 65 def addClassAttribute(self, attribute):
70 """ 66 """
71 Public method to add a class attribute to the class model. 67 Public method to add a class attribute to the class model.
72 68
73 @param attribute class attribute name to be added 69 @param attribute class attribute name to be added
74 @type str 70 @type str
75 """ 71 """
76 self.classAttributes.append(attribute) 72 self.classAttributes.append(attribute)
77 73
78 def getMethods(self): 74 def getMethods(self):
79 """ 75 """
80 Public method to retrieve the methods of the class. 76 Public method to retrieve the methods of the class.
81 77
82 @return list of class methods 78 @return list of class methods
83 @rtype list of str 79 @rtype list of str
84 """ 80 """
85 return self.methods[:] 81 return self.methods[:]
86 82
87 def getInstanceAttributes(self): 83 def getInstanceAttributes(self):
88 """ 84 """
89 Public method to retrieve the attributes of the class. 85 Public method to retrieve the attributes of the class.
90 86
91 @return list of instance attributes 87 @return list of instance attributes
92 @rtype list of str 88 @rtype list of str
93 """ 89 """
94 return self.instanceAttributes[:] 90 return self.instanceAttributes[:]
95 91
96 def getClassAttributes(self): 92 def getClassAttributes(self):
97 """ 93 """
98 Public method to retrieve the global attributes of the class. 94 Public method to retrieve the global attributes of the class.
99 95
100 @return list of class attributes 96 @return list of class attributes
101 @rtype list of str 97 @rtype list of str
102 """ 98 """
103 return self.classAttributes[:] 99 return self.classAttributes[:]
104 100
105 101
106 class ClassItem(UMLItem): 102 class ClassItem(UMLItem):
107 """ 103 """
108 Class implementing an UML like class item. 104 Class implementing an UML like class item.
109 """ 105 """
106
110 ItemType = "class" 107 ItemType = "class"
111 108
112 def __init__(self, model=None, external=False, x=0, y=0, 109 def __init__(
113 rounded=False, noAttrs=False, colors=None, parent=None, 110 self,
114 scene=None): 111 model=None,
112 external=False,
113 x=0,
114 y=0,
115 rounded=False,
116 noAttrs=False,
117 colors=None,
118 parent=None,
119 scene=None,
120 ):
115 """ 121 """
116 Constructor 122 Constructor
117 123
118 @param model class model containing the class data 124 @param model class model containing the class data
119 @type ClassModel 125 @type ClassModel
120 @param external flag indicating a class defined outside our scope 126 @param external flag indicating a class defined outside our scope
121 @type boolean 127 @type boolean
122 @param x x-coordinate 128 @param x x-coordinate
133 @type QGraphicsItem 139 @type QGraphicsItem
134 @param scene reference to the scene object 140 @param scene reference to the scene object
135 @type QGraphicsScene 141 @type QGraphicsScene
136 """ 142 """
137 UMLItem.__init__(self, model, x, y, rounded, colors, parent) 143 UMLItem.__init__(self, model, x, y, rounded, colors, parent)
138 144
139 self.external = external 145 self.external = external
140 self.noAttrs = noAttrs 146 self.noAttrs = noAttrs
141 147
142 if scene: 148 if scene:
143 scene.addItem(self) 149 scene.addItem(self)
144 150
145 if self.model: 151 if self.model:
146 self.__createTexts() 152 self.__createTexts()
147 self.__calculateSize() 153 self.__calculateSize()
148 154
149 def __createTexts(self): 155 def __createTexts(self):
150 """ 156 """
151 Private method to create the text items of the class item. 157 Private method to create the text items of the class item.
152 """ 158 """
153 if self.model is None: 159 if self.model is None:
154 return 160 return
155 161
156 boldFont = QFont(self.font) 162 boldFont = QFont(self.font)
157 boldFont.setBold(True) 163 boldFont.setBold(True)
158 boldFont.setUnderline(True) 164 boldFont.setUnderline(True)
159 165
160 classAttributes = self.model.getClassAttributes() 166 classAttributes = self.model.getClassAttributes()
161 attrs = self.model.getInstanceAttributes() 167 attrs = self.model.getInstanceAttributes()
162 meths = self.model.getMethods() 168 meths = self.model.getMethods()
163 169
164 x = self.margin + int(self.rect().x()) 170 x = self.margin + int(self.rect().x())
165 y = self.margin + int(self.rect().y()) 171 y = self.margin + int(self.rect().y())
166 self.header = QGraphicsSimpleTextItem(self) 172 self.header = QGraphicsSimpleTextItem(self)
167 self.header.setBrush(self._colors[0]) 173 self.header.setBrush(self._colors[0])
168 self.header.setFont(boldFont) 174 self.header.setFont(boldFont)
169 self.header.setText(self.model.getName()) 175 self.header.setText(self.model.getName())
170 self.header.setPos(x, y) 176 self.header.setPos(x, y)
171 y += int(self.header.boundingRect().height()) + self.margin 177 y += int(self.header.boundingRect().height()) + self.margin
172 178
173 if self.external: 179 if self.external:
174 self.classAttributes = None 180 self.classAttributes = None
175 else: 181 else:
176 txt = QCoreApplication.translate( 182 txt = QCoreApplication.translate("ClassItem", "Class Attributes:\n ")
177 "ClassItem", "Class Attributes:\n ")
178 txt += ( 183 txt += (
179 "\n ".join(classAttributes) 184 "\n ".join(classAttributes)
180 if globals else 185 if globals
181 " " + QCoreApplication.translate("ClassItem", "none") 186 else " " + QCoreApplication.translate("ClassItem", "none")
182 ) 187 )
183 self.classAttributes = QGraphicsSimpleTextItem(self) 188 self.classAttributes = QGraphicsSimpleTextItem(self)
184 self.classAttributes.setBrush(self._colors[0]) 189 self.classAttributes.setBrush(self._colors[0])
185 self.classAttributes.setFont(self.font) 190 self.classAttributes.setFont(self.font)
186 self.classAttributes.setText(txt) 191 self.classAttributes.setText(txt)
187 self.classAttributes.setPos(x, y) 192 self.classAttributes.setPos(x, y)
188 y += (int(self.classAttributes.boundingRect().height()) + 193 y += int(self.classAttributes.boundingRect().height()) + self.margin
189 self.margin) 194
190
191 if not self.noAttrs and not self.external: 195 if not self.noAttrs and not self.external:
192 txt = QCoreApplication.translate( 196 txt = QCoreApplication.translate("ClassItem", "Instance Attributes:\n ")
193 "ClassItem", "Instance Attributes:\n ")
194 txt += ( 197 txt += (
195 "\n ".join(attrs) 198 "\n ".join(attrs)
196 if attrs else 199 if attrs
197 " " + QCoreApplication.translate("ClassItem", "none") 200 else " " + QCoreApplication.translate("ClassItem", "none")
198 ) 201 )
199 self.attrs = QGraphicsSimpleTextItem(self) 202 self.attrs = QGraphicsSimpleTextItem(self)
200 self.attrs.setBrush(self._colors[0]) 203 self.attrs.setBrush(self._colors[0])
201 self.attrs.setFont(self.font) 204 self.attrs.setFont(self.font)
202 self.attrs.setText(txt) 205 self.attrs.setText(txt)
203 self.attrs.setPos(x, y) 206 self.attrs.setPos(x, y)
204 y += int(self.attrs.boundingRect().height()) + self.margin 207 y += int(self.attrs.boundingRect().height()) + self.margin
205 else: 208 else:
206 self.attrs = None 209 self.attrs = None
207 210
208 if self.external: 211 if self.external:
209 txt = " " 212 txt = " "
210 else: 213 else:
211 txt = QCoreApplication.translate("ClassItem", "Methods:\n ") 214 txt = QCoreApplication.translate("ClassItem", "Methods:\n ")
212 txt += ( 215 txt += (
213 "\n ".join(meths) 216 "\n ".join(meths)
214 if meths else 217 if meths
215 " " + QCoreApplication.translate("ClassItem", "none") 218 else " " + QCoreApplication.translate("ClassItem", "none")
216 ) 219 )
217 self.meths = QGraphicsSimpleTextItem(self) 220 self.meths = QGraphicsSimpleTextItem(self)
218 self.meths.setBrush(self._colors[0]) 221 self.meths.setBrush(self._colors[0])
219 self.meths.setFont(self.font) 222 self.meths.setFont(self.font)
220 self.meths.setText(txt) 223 self.meths.setText(txt)
221 self.meths.setPos(x, y) 224 self.meths.setPos(x, y)
222 225
223 def __calculateSize(self): 226 def __calculateSize(self):
224 """ 227 """
225 Private method to calculate the size of the class item. 228 Private method to calculate the size of the class item.
226 """ 229 """
227 if self.model is None: 230 if self.model is None:
228 return 231 return
229 232
230 width = int(self.header.boundingRect().width()) 233 width = int(self.header.boundingRect().width())
231 height = int(self.header.boundingRect().height()) 234 height = int(self.header.boundingRect().height())
232 if self.classAttributes: 235 if self.classAttributes:
233 width = max(width, 236 width = max(width, int(self.classAttributes.boundingRect().width()))
234 int(self.classAttributes.boundingRect().width())) 237 height += int(self.classAttributes.boundingRect().height()) + self.margin
235 height += (
236 int(self.classAttributes.boundingRect().height()) + self.margin
237 )
238 if self.attrs: 238 if self.attrs:
239 width = max(width, 239 width = max(width, int(self.attrs.boundingRect().width()))
240 int(self.attrs.boundingRect().width())) 240 height = height + int(self.attrs.boundingRect().height()) + self.margin
241 height = (
242 height + int(self.attrs.boundingRect().height()) + self.margin
243 )
244 if self.meths: 241 if self.meths:
245 width = max(width, 242 width = max(width, int(self.meths.boundingRect().width()))
246 int(self.meths.boundingRect().width()))
247 height += int(self.meths.boundingRect().height()) 243 height += int(self.meths.boundingRect().height())
248 244
249 self.setSize(width + 2 * self.margin, height + 2 * self.margin) 245 self.setSize(width + 2 * self.margin, height + 2 * self.margin)
250 246
251 def setModel(self, model): 247 def setModel(self, model):
252 """ 248 """
253 Public method to set the class model. 249 Public method to set the class model.
254 250
255 @param model class model containing the class data 251 @param model class model containing the class data
256 @type ClassModel 252 @type ClassModel
257 """ 253 """
258 self.scene().removeItem(self.header) 254 self.scene().removeItem(self.header)
259 self.header = None 255 self.header = None
267 self.scene().removeItem(self.meths) 263 self.scene().removeItem(self.meths)
268 self.meths = None 264 self.meths = None
269 self.model = model 265 self.model = model
270 self.__createTexts() 266 self.__createTexts()
271 self.__calculateSize() 267 self.__calculateSize()
272 268
273 def paint(self, painter, option, widget=None): 269 def paint(self, painter, option, widget=None):
274 """ 270 """
275 Public method to paint the item in local coordinates. 271 Public method to paint the item in local coordinates.
276 272
277 @param painter reference to the painter object 273 @param painter reference to the painter object
278 @type QPainter 274 @type QPainter
279 @param option style options 275 @param option style options
280 @type QStyleOptionGraphicsItem 276 @type QStyleOptionGraphicsItem
281 @param widget optional reference to the widget painted on 277 @param widget optional reference to the widget painted on
282 @type QWidget 278 @type QWidget
283 """ 279 """
284 pen = self.pen() 280 pen = self.pen()
285 if ( 281 if (
286 (option.state & QStyle.StateFlag.State_Selected) == 282 option.state & QStyle.StateFlag.State_Selected
287 QStyle.StateFlag.State_Selected 283 ) == QStyle.StateFlag.State_Selected:
288 ):
289 pen.setWidth(2) 284 pen.setWidth(2)
290 else: 285 else:
291 pen.setWidth(1) 286 pen.setWidth(1)
292 287
293 painter.setPen(pen) 288 painter.setPen(pen)
294 painter.setBrush(self.brush()) 289 painter.setBrush(self.brush())
295 painter.setFont(self.font) 290 painter.setFont(self.font)
296 291
297 offsetX = int(self.rect().x()) 292 offsetX = int(self.rect().x())
298 offsetY = int(self.rect().y()) 293 offsetY = int(self.rect().y())
299 w = int(self.rect().width()) 294 w = int(self.rect().width())
300 h = int(self.rect().height()) 295 h = int(self.rect().height())
301 296
302 painter.drawRect(offsetX, offsetY, w, h) 297 painter.drawRect(offsetX, offsetY, w, h)
303 y = self.margin + int(self.header.boundingRect().height()) 298 y = self.margin + int(self.header.boundingRect().height())
304 painter.drawLine(offsetX, offsetY + y, offsetX + w - 1, offsetY + y) 299 painter.drawLine(offsetX, offsetY + y, offsetX + w - 1, offsetY + y)
305 if self.classAttributes: 300 if self.classAttributes:
306 y += ( 301 y += self.margin + int(self.classAttributes.boundingRect().height())
307 self.margin + 302 painter.drawLine(offsetX, offsetY + y, offsetX + w - 1, offsetY + y)
308 int(self.classAttributes.boundingRect().height())
309 )
310 painter.drawLine(offsetX, offsetY + y,
311 offsetX + w - 1, offsetY + y)
312 if self.attrs: 303 if self.attrs:
313 y += self.margin + int(self.attrs.boundingRect().height()) 304 y += self.margin + int(self.attrs.boundingRect().height())
314 painter.drawLine(offsetX, offsetY + y, 305 painter.drawLine(offsetX, offsetY + y, offsetX + w - 1, offsetY + y)
315 offsetX + w - 1, offsetY + y) 306
316
317 self.adjustAssociations() 307 self.adjustAssociations()
318 308
319 def isExternal(self): 309 def isExternal(self):
320 """ 310 """
321 Public method returning the external state. 311 Public method returning the external state.
322 312
323 @return external state 313 @return external state
324 @rtype bool 314 @rtype bool
325 """ 315 """
326 return self.external 316 return self.external
327 317
328 def parseItemDataString(self, version, data): 318 def parseItemDataString(self, version, data):
329 """ 319 """
330 Public method to parse the given persistence data. 320 Public method to parse the given persistence data.
331 321
332 @param version version of the data 322 @param version version of the data
333 @type str 323 @type str
334 @param data persisted data to be parsed 324 @param data persisted data to be parsed
335 @type str 325 @type str
336 @return flag indicating success 326 @return flag indicating success
337 @rtype bool 327 @rtype bool
338 """ 328 """
339 parts = data.split(", ") 329 parts = data.split(", ")
340 if len(parts) < 3: 330 if len(parts) < 3:
341 return False 331 return False
342 332
343 name = "" 333 name = ""
344 instanceAttributes = [] 334 instanceAttributes = []
345 methods = [] 335 methods = []
346 classAttributes = [] 336 classAttributes = []
347 337
348 for part in parts: 338 for part in parts:
349 key, value = part.split("=", 1) 339 key, value = part.split("=", 1)
350 if key == "is_external": 340 if key == "is_external":
351 self.external = Utilities.toBool(value.strip()) 341 self.external = Utilities.toBool(value.strip())
352 elif key == "no_attributes": 342 elif key == "no_attributes":
359 methods = value.strip().split("||") 349 methods = value.strip().split("||")
360 elif key == "class_attributes": 350 elif key == "class_attributes":
361 classAttributes = value.strip().split("||") 351 classAttributes = value.strip().split("||")
362 else: 352 else:
363 return False 353 return False
364 354
365 self.model = ClassModel(name, methods, instanceAttributes, 355 self.model = ClassModel(name, methods, instanceAttributes, classAttributes)
366 classAttributes)
367 self.__createTexts() 356 self.__createTexts()
368 self.__calculateSize() 357 self.__calculateSize()
369 358
370 return True 359 return True
371 360
372 def toDict(self): 361 def toDict(self):
373 """ 362 """
374 Public method to collect data to be persisted. 363 Public method to collect data to be persisted.
375 364
376 @return dictionary containing data to be persisted 365 @return dictionary containing data to be persisted
377 @rtype dict 366 @rtype dict
378 """ 367 """
379 return { 368 return {
380 "id": self.getId(), 369 "id": self.getId(),
386 "model_name": self.model.getName(), 375 "model_name": self.model.getName(),
387 "attributes": self.model.getInstanceAttributes(), 376 "attributes": self.model.getInstanceAttributes(),
388 "methods": self.model.getMethods(), 377 "methods": self.model.getMethods(),
389 "class_attributes": self.model.getClassAttributes(), 378 "class_attributes": self.model.getClassAttributes(),
390 } 379 }
391 380
392 @classmethod 381 @classmethod
393 def fromDict(cls, data, colors=None): 382 def fromDict(cls, data, colors=None):
394 """ 383 """
395 Class method to create a class item from persisted data. 384 Class method to create a class item from persisted data.
396 385
397 @param data dictionary containing the persisted data as generated 386 @param data dictionary containing the persisted data as generated
398 by toDict() 387 by toDict()
399 @type dict 388 @type dict
400 @param colors tuple containing the foreground and background colors 389 @param colors tuple containing the foreground and background colors
401 @type tuple of (QColor, QColor) 390 @type tuple of (QColor, QColor)
402 @return created class item 391 @return created class item
403 @rtype ClassItem 392 @rtype ClassItem
404 """ 393 """
405 try: 394 try:
406 model = ClassModel(data["model_name"], 395 model = ClassModel(
407 data["methods"], 396 data["model_name"],
408 data["attributes"], 397 data["methods"],
409 data["class_attributes"]) 398 data["attributes"],
410 itm = cls(model=model, 399 data["class_attributes"],
411 external=data["is_external"], 400 )
412 x=0, 401 itm = cls(
413 y=0, 402 model=model,
414 noAttrs=data["no_attributes"], 403 external=data["is_external"],
415 colors=colors) 404 x=0,
405 y=0,
406 noAttrs=data["no_attributes"],
407 colors=colors,
408 )
416 itm.setPos(data["x"], data["y"]) 409 itm.setPos(data["x"], data["y"])
417 itm.setId(data["id"]) 410 itm.setId(data["id"])
418 return itm 411 return itm
419 except KeyError: 412 except KeyError:
420 return None 413 return None

eric ide

mercurial