16 |
16 |
from EngineeringAbstractItem import QEngineeringAbstractItem
|
17 |
17 |
from EngineeringConnectorItem import QEngineeringConnectorItem
|
18 |
18 |
from UserInputAttribute import UserInputAttribute
|
|
19 |
from Resizer import Resizer
|
19 |
20 |
|
20 |
21 |
class SymbolSvgItem(QGraphicsSvgItem, QEngineeringAbstractItem):
|
21 |
22 |
""" This is symbolsvgitem class """
|
... | ... | |
55 |
56 |
self.flip = flip
|
56 |
57 |
# attributeType uid
|
57 |
58 |
self.attribute = ''
|
58 |
|
#self._properties = {SymbolProp(None, 'Size', 'Size Text Item', Expression='self.EvaluatedSize'):None, SymbolProp(None, 'Supplied By', 'String'):None}
|
59 |
59 |
self._properties = {SymbolProp(None, 'Supplied By', 'String'):None}
|
60 |
60 |
|
61 |
61 |
self.setAcceptDrops(True)
|
... | ... | |
83 |
83 |
|
84 |
84 |
self.setZValue(SymbolSvgItem.ZVALUE)
|
85 |
85 |
|
86 |
|
app_doc_data = AppDocData.instance()
|
87 |
|
configs = app_doc_data.getConfigs('Symbol Style', 'Opacity')
|
88 |
|
self.setOpacity(float(configs[0].value)/100 if configs else 0.5)
|
89 |
|
|
90 |
86 |
def __str__(self):
|
91 |
87 |
""" return string represent uuid """
|
92 |
88 |
return str(self.uid)
|
... | ... | |
164 |
160 |
|
165 |
161 |
return None
|
166 |
162 |
|
167 |
|
'''
|
168 |
|
def attrib(self, name):
|
169 |
|
""" return the value of given attribute with name """
|
170 |
|
matches = [(attr,value) for attr,value in self.getAttributes().items() if attr.Attribute == name]
|
171 |
|
if matches: return matches[0][1]
|
172 |
|
|
173 |
|
return None
|
174 |
|
|
175 |
|
def set_attrib(self, attrib, value):
|
176 |
|
""" set attribute with given value """
|
177 |
|
matches = [attr for attr,_ in self.attrs.items() if attr.UID == attrib.UID]
|
178 |
|
if len(matches) == 1: self.attrs[matches[0]] = value
|
179 |
|
'''
|
180 |
|
|
181 |
163 |
@property
|
182 |
164 |
def Size(self):
|
183 |
165 |
""" return valve's size """
|
... | ... | |
189 |
171 |
else:
|
190 |
172 |
return None
|
191 |
173 |
|
192 |
|
@property
|
193 |
|
def EvaluatedSize(self):
|
194 |
|
from EngineeringReducerItem import QEngineeringReducerItem
|
195 |
|
try:
|
196 |
|
if self.Size: return self.Size
|
197 |
|
if self.owner:
|
198 |
|
matches = [run for run in self.owner.runs if self in run.items]
|
199 |
|
if matches:
|
200 |
|
at = matches[0].items.index(self)
|
201 |
|
upstream = matches[0].items[:at]
|
202 |
|
upstream.reverse()
|
203 |
|
prev = self
|
204 |
|
for item in upstream:
|
205 |
|
if type(item) is QEngineeringReducerItem:
|
206 |
|
if item.connectors[0].connectedItem is prev: ### Main Size
|
207 |
|
if item.MainSize: return item.MainSize
|
208 |
|
elif item.connectors[1].connectedItem is prev: ### Sub Size
|
209 |
|
if item.SubSize: return item.SubSize
|
210 |
|
else:
|
211 |
|
if item.Size: return item.Size
|
212 |
|
prev = item
|
213 |
|
|
214 |
|
downstream = matches[0].items[at:]
|
215 |
|
prev = self
|
216 |
|
for item in downstream:
|
217 |
|
if type(item) is QEngineeringReducerItem:
|
218 |
|
if item.connectors[0].connectedItem is prev: ### Main Size
|
219 |
|
if item.MainSize: return item.MainSize
|
220 |
|
elif item.connectors[1].connectedItem is prev: ### Sub Size
|
221 |
|
if item.SubSize: return item.SubSize
|
222 |
|
else:
|
223 |
|
if item.Size: return item.Size
|
224 |
|
prev = item
|
225 |
|
|
226 |
|
if 'Drain' == matches[0].Type: return AppDocData.instance().drain_size
|
227 |
|
|
228 |
|
return self.owner.Size
|
229 |
|
|
230 |
|
return None
|
231 |
|
except Exception as ex:
|
232 |
|
from App import App
|
233 |
|
from AppDocData import MessageType
|
234 |
|
|
235 |
|
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
|
236 |
|
App.mainWnd().addMessage.emit(MessageType.Error, message)
|
237 |
|
|
238 |
|
def validate(self):
|
239 |
|
'''
|
240 |
|
@brief validation check : flow
|
241 |
|
@author euisung
|
242 |
|
@date 2019.04.16
|
243 |
|
'''
|
244 |
|
from EngineeringLineItem import QEngineeringLineItem
|
245 |
|
from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
|
246 |
|
errors = []
|
247 |
|
if type(self) is QEngineeringSpecBreakItem:
|
248 |
|
return errors
|
249 |
|
docdata = AppDocData.instance()
|
250 |
|
dataPath = docdata.getErrorItemSvgPath()
|
251 |
|
origin = [int(pt) for pt in docdata.getAppConfigs('app', 'error origin point')[0].value.split(',')]
|
252 |
|
|
253 |
|
# check flow for 2 connection point symbol
|
254 |
|
if len(self.connectors) is 2:
|
255 |
|
if type(self.connectors[0].connectedItem) is QEngineeringLineItem and type(self.connectors[1].connectedItem) is QEngineeringLineItem:
|
256 |
|
if self.includes(self.connectors[0].connectedItem.startPoint(), 5) is not self.includes(self.connectors[1].connectedItem.endPoint(), 5):
|
257 |
|
#print(self.sceneBoundingRect())
|
258 |
|
error = SymbolSvgItem.createItem('Error', dataPath)
|
259 |
|
error.parent = self
|
260 |
|
error.msg = 'flow error'
|
261 |
|
error.setToolTip(error.msg)
|
262 |
|
error.area = 'Drawing'
|
263 |
|
error.name = 'Error'
|
264 |
|
errors.append(error)
|
265 |
|
|
266 |
|
# check disconnected point
|
267 |
|
disconnect = False
|
268 |
|
if len(self.connectors) is not 0:
|
269 |
|
disconnect = True
|
270 |
|
for connector in self.connectors:
|
271 |
|
if connector.connectedItem is not None:
|
272 |
|
disconnect = False
|
273 |
|
break
|
274 |
|
|
275 |
|
if disconnect:
|
276 |
|
error = SymbolSvgItem.createItem('Error', dataPath)
|
277 |
|
error.parent = self
|
278 |
|
error.msg = 'disconnected'
|
279 |
|
error.setToolTip(error.msg)
|
280 |
|
error.area = 'Drawing'
|
281 |
|
error.name = 'Error'
|
282 |
|
errors.append(error)
|
283 |
|
|
284 |
|
# set error position
|
285 |
|
#denominator = len(errors) + 1
|
286 |
|
#molecule = 1
|
287 |
|
for error in errors:
|
288 |
|
error.setPosition([self.sceneBoundingRect().center().x(), self.sceneBoundingRect().center().y()], origin)
|
289 |
|
#molecule = molecule + 1
|
290 |
|
|
291 |
|
return errors
|
292 |
|
|
293 |
174 |
def includes(self, pt, margin=0):
|
294 |
|
"""
|
295 |
|
return True if symbol contains given point else return False
|
296 |
|
"""
|
|
175 |
""" return True if symbol contains given point else return False """
|
297 |
176 |
rect = self.sceneBoundingRect()
|
298 |
177 |
allowed_error = 0.1
|
299 |
178 |
|
... | ... | |
464 |
343 |
|
465 |
344 |
return False
|
466 |
345 |
|
467 |
|
def canBeSecondary(self, line):
|
468 |
|
""" check given line is not connected(ex: 0-1, 2-3) """
|
469 |
|
preItem = None
|
470 |
|
|
471 |
|
item = [item.connectedItem for item in self.connectors if item.connectedItem is not None and item.connectedItem.owner is not None]
|
472 |
|
if item:
|
473 |
|
preItem = item[0]
|
474 |
|
|
475 |
|
if preItem is not None and not self.next_connected(line, preItem):
|
476 |
|
return True
|
477 |
|
else:
|
478 |
|
return False
|
479 |
|
|
480 |
346 |
'''
|
481 |
347 |
@brief connect line and symbol is able to be connected and return line
|
482 |
348 |
@author humkyung
|
... | ... | |
565 |
431 |
@date 2018.05.02
|
566 |
432 |
'''
|
567 |
433 |
def hoverEnterEvent(self, event):
|
|
434 |
from Resizer import Resizer
|
|
435 |
|
568 |
436 |
self.highlight(True)
|
569 |
437 |
|
|
438 |
""" create a resizer """
|
|
439 |
resizer = Resizer.instance()
|
|
440 |
resizer.connected = self
|
|
441 |
resizerWidth = resizer.rect.width() / 2
|
|
442 |
rect = self.sceneBoundingRect()
|
|
443 |
resizerOffset = QPointF(resizerWidth, resizerWidth)
|
|
444 |
resizer.setPos(rect.bottomRight() - resizerOffset)
|
|
445 |
if resizer.receivers(resizer.resizeSignal) > 0: resizer.resizeSignal.disconnect()
|
|
446 |
resizer.resizeSignal.connect(self.resize)
|
|
447 |
try:
|
|
448 |
self.transfer.on_pos_changed.disconnect(resizer.on_symbol_pos_changed)
|
|
449 |
except Exception as ex:
|
|
450 |
pass
|
|
451 |
self.transfer.on_pos_changed.connect(resizer.on_symbol_pos_changed)
|
|
452 |
resizer.setVisible(True)
|
|
453 |
if not resizer.scene(): self.scene().addItem(resizer)
|
|
454 |
|
570 |
455 |
'''
|
571 |
456 |
@brief unhighlight connector and attribute
|
572 |
457 |
@author humkyung
|
... | ... | |
654 |
539 |
del self.attrs[attr]
|
655 |
540 |
|
656 |
541 |
'''
|
657 |
|
@brief Find TextItem contain Point
|
658 |
|
@author kyouho
|
659 |
|
@date 18.07.17
|
660 |
|
'''
|
661 |
|
def findTextItemInPoint(self, point):
|
662 |
|
from EngineeringTextItem import QEngineeringTextItem
|
663 |
|
|
664 |
|
scene = self.scene()
|
665 |
|
|
666 |
|
for item in scene.items():
|
667 |
|
if type(item) is QEngineeringTextItem:
|
668 |
|
if self.isOverlapItemAndPoint(item, point):
|
669 |
|
return (True, item)
|
670 |
|
|
671 |
|
return (False,)
|
672 |
|
|
673 |
|
'''
|
674 |
542 |
@brief Check Overlap
|
675 |
543 |
@author kyouho
|
676 |
544 |
@date 18.07.17
|
... | ... | |
1248 |
1116 |
'''
|
1249 |
1117 |
def addSvgItemToScene(self, scene):
|
1250 |
1118 |
transform = QTransform()
|
1251 |
|
#print(self.symbolOrigin)
|
1252 |
1119 |
|
1253 |
1120 |
transform.translate(self.loc[0] + self.symbolOrigin[0], self.loc[1] + self.symbolOrigin[1])
|
1254 |
1121 |
transform.rotateRadians(-self.angle)
|
... | ... | |
1449 |
1316 |
|
1450 |
1317 |
self.loc = [self.loc[0] + self.origin[0] - goPoint.x(), self.loc[1] + self.origin[1] - goPoint.y()]
|
1451 |
1318 |
|
|
1319 |
def resize(self, change):
|
|
1320 |
""" resize item """
|
|
1321 |
# Get the smaller side of the rect
|
|
1322 |
rect = self.sceneBoundingRect()
|
|
1323 |
loc = QPointF(rect.x(), rect.y())
|
|
1324 |
self.resetTransform()
|
|
1325 |
rect = self.sceneBoundingRect()
|
|
1326 |
scale = [(change.width() - loc.x())/rect.width(), (change.height() - loc.y())/rect.height()]
|
|
1327 |
#scale the item
|
|
1328 |
if scale[0] > 0 and scale[1] > 0:
|
|
1329 |
self.setPos(loc)
|
|
1330 |
trans = QTransform()
|
|
1331 |
trans.scale(scale[0] if scale[0] < scale[1] else scale[1],scale[0] if scale[0] < scale[1] else scale[1])
|
|
1332 |
self.setTransform(trans);
|
|
1333 |
self.prepareGeometryChange()
|
|
1334 |
self.update()
|
|
1335 |
|
|
1336 |
self.transfer.on_size_changed.emit(self)
|
|
1337 |
|
|
1338 |
def moveto(self, to, timeLine = 5000, rotation = 0):
|
|
1339 |
"""Move the item from one position to one other."""
|
|
1340 |
|
|
1341 |
anim = QPropertyAnimation(self, b'pos')
|
|
1342 |
rect = self.sceneBoundingRect()
|
|
1343 |
anim.setStartValue(QPointF(0, 0))
|
|
1344 |
anim.setEndValue(QPointF(100,10))
|
|
1345 |
anim.setDuration(10000)
|
|
1346 |
anim.start()
|
1452 |
1347 |
|
1453 |
1348 |
def recursiveChangeAttributes(node, attName, attValue):
|
1454 |
1349 |
while not node.isNull():
|
... | ... | |
1469 |
1364 |
'''
|
1470 |
1365 |
class Transfer(QObject):
|
1471 |
1366 |
on_pos_changed = pyqtSignal(QGraphicsItem)
|
|
1367 |
on_size_changed = pyqtSignal(QGraphicsItem)
|
1472 |
1368 |
onRemoved = pyqtSignal(QGraphicsItem)
|
1473 |
1369 |
|
1474 |
1370 |
def __init__(self, parent = None):
|