eric7/Graphics/PackageItem.py

branch
eric7
changeset 8312
800c432b34c8
parent 8295
3f5e8b0a338e
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2007 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a package item.
8 """
9
10 from PyQt5.QtGui import QFont
11 from PyQt5.QtWidgets import QGraphicsSimpleTextItem, QStyle
12
13 from .UMLItem import UMLModel, UMLItem
14
15 import Utilities
16
17
18 class PackageModel(UMLModel):
19 """
20 Class implementing the package model.
21 """
22 def __init__(self, name, moduleslist=None):
23 """
24 Constructor
25
26 @param name package name
27 @type str
28 @param moduleslist list of module names
29 @type list of str
30 """
31 super().__init__(name)
32
33 self.moduleslist = [] if moduleslist is None else moduleslist[:]
34
35 def addModule(self, modulename):
36 """
37 Public method to add a module to the package model.
38
39 @param modulename module name to be added
40 @type str
41 """
42 self.moduleslist.append(modulename)
43
44 def getModules(self):
45 """
46 Public method to retrieve the modules of the package.
47
48 @return list of module names
49 @rtype list of str
50 """
51 return self.moduleslist[:]
52
53
54 class PackageItem(UMLItem):
55 """
56 Class implementing a package item.
57 """
58 ItemType = "package"
59
60 def __init__(self, model=None, x=0, y=0, rounded=False,
61 noModules=False, colors=None, parent=None, scene=None):
62 """
63 Constructor
64
65 @param model package model containing the package data
66 @type PackageModel
67 @param x x-coordinate
68 @type int
69 @param y y-coordinate
70 @type int
71 @param rounded flag indicating a rounded corner
72 @type bool
73 @param noModules flag indicating, that no module names should be
74 shown
75 @type bool
76 @param colors tuple containing the foreground and background colors
77 @type tuple of (QColor, QColor)
78 @param parent reference to the parent object
79 @type QGraphicsItem
80 @param scene reference to the scene object
81 @type QGraphicsScene
82 """
83 UMLItem.__init__(self, model, x, y, rounded, colors, parent)
84 self.noModules = noModules
85
86 if scene:
87 scene.addItem(self)
88
89 if self.model:
90 self.__createTexts()
91 self.__calculateSize()
92
93 def __createTexts(self):
94 """
95 Private method to create the text items of the class item.
96 """
97 if self.model is None:
98 return
99
100 boldFont = QFont(self.font)
101 boldFont.setBold(True)
102
103 modules = self.model.getModules()
104
105 x = self.margin + self.rect().x()
106 y = self.margin + self.rect().y()
107 self.header = QGraphicsSimpleTextItem(self)
108 self.header.setBrush(self._colors[0])
109 self.header.setFont(boldFont)
110 self.header.setText(self.model.getName())
111 self.header.setPos(x, y)
112 y += self.header.boundingRect().height() + self.margin
113
114 if not self.noModules:
115 if modules:
116 txt = "\n".join(modules)
117 else:
118 txt = " "
119 self.modules = QGraphicsSimpleTextItem(self)
120 self.modules.setBrush(self._colors[0])
121 self.modules.setFont(self.font)
122 self.modules.setText(txt)
123 self.modules.setPos(x, y)
124 else:
125 self.modules = None
126
127 def __calculateSize(self):
128 """
129 Private method to calculate the size of the package widget.
130 """
131 if self.model is None:
132 return
133
134 width = self.header.boundingRect().width()
135 height = self.header.boundingRect().height()
136 if self.modules:
137 width = max(width, self.modules.boundingRect().width())
138 height += self.modules.boundingRect().height()
139 latchW = width / 3.0
140 latchH = min(15.0, latchW)
141 self.setSize(width + 2 * self.margin,
142 height + latchH + 2 * self.margin)
143
144 x = self.margin + self.rect().x()
145 y = self.margin + self.rect().y() + latchH
146 self.header.setPos(x, y)
147 y += self.header.boundingRect().height() + self.margin
148 if self.modules:
149 self.modules.setPos(x, y)
150
151 def setModel(self, model):
152 """
153 Public method to set the package model.
154
155 @param model package model containing the package data
156 @type PackageModel
157 """
158 self.scene().removeItem(self.header)
159 self.header = None
160 if self.modules:
161 self.scene().removeItem(self.modules)
162 self.modules = None
163 self.model = model
164 self.__createTexts()
165 self.__calculateSize()
166
167 def paint(self, painter, option, widget=None):
168 """
169 Public method to paint the item in local coordinates.
170
171 @param painter reference to the painter object
172 @type QPainter
173 @param option style options
174 @type QStyleOptionGraphicsItem
175 @param widget optional reference to the widget painted on
176 @type QWidget
177 """
178 pen = self.pen()
179 if (
180 (option.state & QStyle.StateFlag.State_Selected) ==
181 QStyle.State(QStyle.StateFlag.State_Selected)
182 ):
183 pen.setWidth(2)
184 else:
185 pen.setWidth(1)
186
187 offsetX = self.rect().x()
188 offsetY = self.rect().y()
189 w = self.rect().width()
190 latchW = w / 3.0
191 latchH = min(15.0, latchW)
192 h = self.rect().height() - latchH + 1
193
194 painter.setPen(pen)
195 painter.setBrush(self.brush())
196 painter.setFont(self.font)
197
198 painter.drawRect(offsetX, offsetY, latchW, latchH)
199 painter.drawRect(offsetX, offsetY + latchH, w, h)
200 y = self.margin + self.header.boundingRect().height() + latchH
201 painter.drawLine(offsetX, offsetY + y, offsetX + w - 1, offsetY + y)
202
203 self.adjustAssociations()
204
205 def buildItemDataString(self):
206 """
207 Public method to build a string to persist the specific item data.
208
209 This string must start with ", " and should be built like
210 "attribute=value" with pairs separated by ", ". value must not
211 contain ", " or newlines.
212
213 @return persistence data
214 @rtype str
215 """
216 entries = [
217 "no_modules={0}".format(self.noModules),
218 "name={0}".format(self.model.getName()),
219 ]
220 modules = self.model.getModules()
221 if modules:
222 entries.append("modules={0}".format("||".join(modules)))
223
224 return ", " + ", ".join(entries)
225
226 def parseItemDataString(self, version, data):
227 """
228 Public method to parse the given persistence data.
229
230 @param version version of the data
231 @type str
232 @param data persisted data to be parsed
233 @type str
234 @return flag indicating success
235 @rtype bool
236 """
237 parts = data.split(", ")
238 if len(parts) < 2:
239 return False
240
241 name = ""
242 modules = []
243
244 for part in parts:
245 key, value = part.split("=", 1)
246 if key == "no_modules":
247 self.external = Utilities.toBool(value.strip())
248 elif key == "name":
249 name = value.strip()
250 elif key == "modules":
251 modules = value.strip().split("||")
252 else:
253 return False
254
255 self.model = PackageModel(name, modules)
256 self.__createTexts()
257 self.__calculateSize()
258
259 return True
260
261 def toDict(self):
262 """
263 Public method to collect data to be persisted.
264
265 @return dictionary containing data to be persisted
266 @rtype dict
267 """
268 return {
269 "id": self.getId(),
270 "x": self.x(),
271 "y": self.y(),
272 "type": self.getItemType(),
273 "model_name": self.model.getName(),
274 "no_nodules": self.noModules,
275 "modules": self.model.getModules(),
276 }
277
278 @classmethod
279 def fromDict(cls, data, colors=None):
280 """
281 Class method to create a class item from persisted data.
282
283 @param data dictionary containing the persisted data as generated
284 by toDict()
285 @type dict
286 @param colors tuple containing the foreground and background colors
287 @type tuple of (QColor, QColor)
288 @return created class item
289 @rtype ClassItem
290 """
291 try:
292 model = PackageModel(data["model_name"],
293 data["modules"])
294 itm = cls(model,
295 x=0,
296 y=0,
297 noModules=data["no_nodules"],
298 colors=colors)
299 itm.setPos(data["x"], data["y"])
300 itm.setId(data["id"])
301 return itm
302 except KeyError:
303 return None

eric ide

mercurial