hytos / DTI_PID / DTI_PID / Shapes / EngineeringAbstractItem.py @ 73d15184
이력 | 보기 | 이력해설 | 다운로드 (30.8 KB)
1 |
# coding: utf-8
|
---|---|
2 |
""" This is engineering abstract item module """
|
3 | |
4 |
import sys |
5 |
#import random
|
6 | |
7 | |
8 |
class QEngineeringAbstractItem: |
9 |
'''
|
10 |
@history 2018.05.15 Jeongwoo Remove call super
|
11 |
2018.05.17 Jeongwoo Add DEFAULT_COLOR Variable
|
12 |
'''
|
13 |
DEFAULT_COLOR = '#0000FF'
|
14 |
HOVER_COLOR = '#BC4438'
|
15 | |
16 |
CONNECTED_AT_PT = 0
|
17 |
CONNECTED_AT_BODY = 1
|
18 | |
19 |
HOVER_ZVALUE = 200
|
20 | |
21 |
def __init__(self, parent=None): |
22 |
self._color = self.DEFAULT_COLOR # default color |
23 |
self._owner = None |
24 |
self.conns = []
|
25 |
self.special_item_type = None # UID for special item type |
26 |
self._hover = False |
27 |
self._area = None |
28 |
self.connectors = []
|
29 |
self.attrs = {} # attributes |
30 |
self._associations = {'Text Item': [], 'Symbol Item': []} # associated items |
31 | |
32 |
#self.refresh_count = random.randint(0, 9)
|
33 | |
34 |
@property
|
35 |
def hover(self): |
36 |
""" return hover """
|
37 |
return self._hover |
38 | |
39 |
@hover.setter
|
40 |
def hover(self, value): |
41 |
""" set hover """
|
42 |
self._hover = value
|
43 | |
44 |
def change_color(self, value): |
45 |
""" change item's color """
|
46 |
self._color = value
|
47 | |
48 |
def highlight(self, flag): |
49 |
pass
|
50 | |
51 |
'''
|
52 |
@brief Abstract method. Variable [color] is RGB hex code
|
53 |
@author Jeongwoo
|
54 |
@date 2018.05.11
|
55 |
'''
|
56 | |
57 |
def setColor(self, color): |
58 |
raise NotImplementedError |
59 | |
60 |
'''
|
61 |
@brief return color
|
62 |
@author Jeongwoo
|
63 |
@date 2018.05.11
|
64 |
'''
|
65 | |
66 |
def getColor(self): |
67 |
return QEngineeringAbstractItem.HOVER_COLOR if self.hover else ( |
68 |
self.owner.getColor() if (self.owner and hasattr(self.owner, '_color')) else self._color) |
69 | |
70 |
'''
|
71 |
@brief getter of owner
|
72 |
@author humkyung
|
73 |
@date 2018.05.12
|
74 |
'''
|
75 | |
76 |
@property
|
77 |
def owner(self): |
78 |
return self._owner |
79 | |
80 |
'''
|
81 |
@brief setter of owner
|
82 |
@author humkyung
|
83 |
@date 2018.05.12
|
84 |
'''
|
85 | |
86 |
@owner.setter
|
87 |
def owner(self, value): |
88 |
self._owner = value
|
89 | |
90 |
@property
|
91 |
def has_connection(self): |
92 |
""" check this is connected to other """
|
93 |
for connector in self.connectors: |
94 |
if connector.connectedItem: return True |
95 | |
96 |
return False |
97 | |
98 |
def validate(self): |
99 |
""" validate this """
|
100 |
raise NotImplementedError('To be implemented') |
101 | |
102 |
'''
|
103 |
@brief getter of area
|
104 |
@author humkyung
|
105 |
@date 2018.09.06
|
106 |
'''
|
107 | |
108 |
@property
|
109 |
def area(self): |
110 |
return self._area if self._area is not None else 'None' |
111 | |
112 |
'''
|
113 |
@brief setter of area
|
114 |
@author humkyung
|
115 |
@date 2018.09.06
|
116 |
'''
|
117 | |
118 |
@area.setter
|
119 |
def area(self, value): |
120 |
self._area = value
|
121 | |
122 |
'''
|
123 |
@brief write to xml
|
124 |
@author humkyung
|
125 |
@date 2018.05.16
|
126 |
'''
|
127 | |
128 |
def toXml(self): |
129 |
pass
|
130 | |
131 |
def to_svg(self, parent=None) -> list: |
132 |
pass
|
133 | |
134 |
'''
|
135 |
@brief write attribute to xml
|
136 |
@author humkyung
|
137 |
@date 2018.05.16
|
138 |
'''
|
139 | |
140 |
def toXmlAsAttribute(self, parent): |
141 |
pass
|
142 | |
143 |
def toSql(self): |
144 |
"""convert to sql query"""
|
145 |
pass
|
146 | |
147 |
def isOverlap(self, rect1, rect2): |
148 |
"""
|
149 |
@brief return true if rects have intersection, rect is QRect
|
150 |
@author euisung
|
151 |
@date 2019.09.02
|
152 |
"""
|
153 |
lt1, rb1 = (rect1.left(), rect1.top()), (rect1.right(), rect1.bottom()) |
154 |
lt2, tb2 = (rect2.left(), rect2.top()), (rect2.right(), rect2.bottom()) |
155 |
if rect1.left() > rect2.right() or rect2.left() > rect1.right(): |
156 |
return False |
157 |
if rect1.bottom() < rect2.top() or rect2.bottom() < rect1.top(): |
158 |
return False |
159 | |
160 |
return True |
161 | |
162 |
def associations(self): |
163 |
""" return associated instance """
|
164 |
# move to abstractitem
|
165 |
import uuid |
166 | |
167 |
try:
|
168 |
res = [] |
169 |
for key in self._associations.keys(): |
170 |
index = 0
|
171 |
for assoc in list(self._associations[key]): |
172 |
# find owner with uid if self.scene() is valid
|
173 |
if self.scene() and assoc and type(assoc) is uuid.UUID: |
174 |
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(assoc)] |
175 |
if matches:
|
176 |
res.append(matches[0])
|
177 |
self._associations[key][index] = matches[0] |
178 |
# up to here
|
179 |
elif assoc:
|
180 |
res.append(assoc) |
181 |
index += 1
|
182 | |
183 |
for key in self.attrs.keys(): |
184 |
if type(key.AssocItem) is uuid.UUID: |
185 |
for assoc in res: |
186 |
if str(key.AssocItem) == str(assoc.uid): |
187 |
key.AssocItem = assoc |
188 | |
189 |
return res
|
190 |
except Exception as ex: |
191 |
from App import App |
192 |
from AppDocData import MessageType |
193 | |
194 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
195 |
sys.exc_info()[-1].tb_lineno)
|
196 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
197 |
return []
|
198 | |
199 |
def get_assoc_item(self, assoc): |
200 |
""" get associated item of given object """
|
201 |
import uuid |
202 | |
203 |
if assoc and type(assoc) is uuid.UUID: |
204 |
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(assoc)] |
205 |
if matches: return matches[0] |
206 | |
207 |
return assoc
|
208 | |
209 |
def texts(self): |
210 |
""" return text type of associations """
|
211 |
res = [] |
212 | |
213 |
for text in self.texts_order(): |
214 |
consumed = False
|
215 |
for key in list(self.attrs.keys()): |
216 |
if key.AssocItem and key.AssocItem is text: |
217 |
consumed = True
|
218 |
if not consumed: |
219 |
res.append(text) |
220 | |
221 |
return res
|
222 | |
223 |
def texts_order(self): |
224 |
from EngineeringTextItem import QEngineeringTextItem |
225 |
|
226 |
return sorted([x for x in self.associations() if issubclass(type(x), QEngineeringTextItem)], |
227 |
key=lambda attr: attr.loc[1]) |
228 | |
229 |
def symbols(self, symbol_attr_number): |
230 |
""" return symbol type of associations """
|
231 |
from SymbolSvgItem import SymbolSvgItem |
232 |
from EngineeringVendorItem import QEngineeringVendorItem |
233 |
from EngineeringLineItem import QEngineeringLineItem |
234 | |
235 |
res = [] |
236 |
for symbol in [x for x in self.associations() if |
237 |
issubclass(type(x), SymbolSvgItem) or type(x) is QEngineeringVendorItem or type(x) is QEngineeringLineItem]: |
238 |
if symbol_attr_number > 1: |
239 |
consumed = False
|
240 |
for key in list(self.attrs.keys()): |
241 |
if key.AssocItem and key.AssocItem is symbol: |
242 |
consumed = True
|
243 |
if not consumed: |
244 |
res.append(symbol) |
245 |
else:
|
246 |
res.append(symbol) |
247 | |
248 |
return res
|
249 | |
250 |
@property
|
251 |
def Size(self): |
252 |
""" return symbol's size """
|
253 |
from QEngineeringSizeTextItem import QEngineeringSizeTextItem |
254 | |
255 |
matches = [assoc for assoc in self.associations() if type(assoc) is QEngineeringSizeTextItem] |
256 |
if matches:
|
257 |
return matches[0].mainSize |
258 |
else:
|
259 |
return None |
260 | |
261 |
@property
|
262 |
def EvaluatedSize(self): |
263 |
from EngineeringReducerItem import QEngineeringReducerItem |
264 |
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem |
265 |
from AppDocData import AppDocData |
266 | |
267 |
try:
|
268 |
if self.Size: return self.Size |
269 |
if self.owner and issubclass(type(self.owner), QEngineeringLineNoTextItem): |
270 |
matches = [run for run in self.owner.runs if self in run.items] |
271 |
if matches:
|
272 |
at = matches[0].items.index(self) |
273 |
upstream = matches[0].items[:at]
|
274 |
upstream.reverse() |
275 |
prev = self
|
276 |
for item in upstream: |
277 |
if type(item) is QEngineeringReducerItem: |
278 |
if item.connectors[0].connectedItem is prev: ### Main Size |
279 |
if item.mainSubSize: return item.mainSubSize[0] |
280 |
elif item.connectors[1].connectedItem is prev: ### Sub Size |
281 |
if item.mainSubSize: return item.mainSubSize[1] |
282 |
else:
|
283 |
if item.Size: return item.Size |
284 |
prev = item |
285 | |
286 |
downstream = matches[0].items[at:]
|
287 |
prev = self
|
288 |
for item in downstream: |
289 |
if type(item) is QEngineeringReducerItem: |
290 |
if item.connectors[0].connectedItem is prev: ### Main Size |
291 |
if item.mainSubSize: return item.mainSubSize[0] |
292 |
elif item.connectors[1].connectedItem is prev: ### Sub Size |
293 |
if item.mainSubSize: return item.mainSubSize[1] |
294 |
else:
|
295 |
if item.Size: return item.Size |
296 |
prev = item |
297 | |
298 |
if 'Drain' == matches[0].Type: |
299 |
return None |
300 |
#return AppDocData.instance().drain_size
|
301 | |
302 |
return self.owner.Size |
303 | |
304 |
return None |
305 |
except Exception as ex: |
306 |
from App import App |
307 |
from AppDocData import MessageType |
308 | |
309 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
310 |
sys.exc_info()[-1].tb_lineno)
|
311 |
#App.mainWnd().addMessage.emit(MessageType.Error, str(self.uid) + self.name + message)
|
312 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
313 | |
314 |
def EvaluatedTable(self, old_code, table_name): |
315 |
""" return new attribute code """
|
316 |
from AppDocData import AppDocData |
317 |
from CodeTables import CodeTable |
318 | |
319 |
try:
|
320 |
found = CodeTable.instance(table_name).find_match_exactly(old_code) |
321 | |
322 |
return found if found else '' |
323 |
except Exception as ex: |
324 |
from App import App |
325 |
from AppDocData import MessageType |
326 | |
327 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
328 |
sys.exc_info()[-1].tb_lineno)
|
329 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
330 | |
331 |
def EvaluatedLineNo(self, prop): |
332 |
""" return line no attr """
|
333 |
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem |
334 | |
335 |
if self.owner and type(self.owner) is QEngineeringLineNoTextItem: |
336 |
attrs = self.owner.getAttributes()
|
337 |
for attr, value in attrs.items(): |
338 |
if prop == attr.Attribute:
|
339 |
return value
|
340 | |
341 |
return None |
342 | |
343 |
def EvaluatedDrawing(self, prop): |
344 |
""" return text item that is in prop"""
|
345 |
from EngineeringTextItem import QEngineeringTextItem |
346 | |
347 |
scene = self.scene()
|
348 |
if scene:
|
349 |
items = [item for item in scene.items() if issubclass(type(item), QEngineeringTextItem) and item.area == prop] |
350 |
if items:
|
351 |
return items[0] |
352 |
|
353 |
return QEngineeringTextItem()
|
354 | |
355 |
def EvaluatedAttribute(self, prop): |
356 |
""" return item's attribute """
|
357 |
attrs = self.getAttributes()
|
358 |
if attrs:
|
359 |
for key, value in attrs.items(): |
360 |
if key.Attribute == prop:
|
361 |
return value
|
362 | |
363 |
return '' |
364 | |
365 |
def getAttributes(self, findOwner=False): |
366 |
"""calculate all attributes of item"""
|
367 |
import re |
368 | |
369 |
if findOwner and self._skip: |
370 |
return self.attrs |
371 |
elif findOwner:
|
372 |
self._skip = True |
373 |
else:
|
374 |
self._skip = False |
375 | |
376 |
_attrs = {} |
377 |
try:
|
378 |
from AppDocData import AppDocData |
379 |
from SymbolSvgItem import SymbolSvgItem |
380 |
from EngineeringTextItem import QEngineeringTextItem |
381 |
from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem |
382 |
from EngineeringLineItem import QEngineeringLineItem |
383 |
from EngineeringVendorItem import QEngineeringVendorItem |
384 |
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem |
385 |
from EngineeringSpecBreakItem import QEngineeringSpecBreakItem |
386 |
from QEngineeringTagNoTextItem import QEngineeringTagNoTextItem |
387 | |
388 |
""" get attributes of item from database """
|
389 |
app_doc_data = AppDocData.instance() |
390 |
if type(self) is QEngineeringLineItem: |
391 |
symbolAttrs = app_doc_data.getSymbolAttribute('Line')
|
392 |
elif type(self) is QEngineeringVendorItem: |
393 |
symbolAttrs = app_doc_data.getSymbolAttribute('Package')
|
394 |
elif type(self) is QEngineeringLineNoTextItem: |
395 |
symbolAttrs = app_doc_data.getSymbolAttribute('Line No')
|
396 |
self.getLineNoAttributes(_attrs)
|
397 |
elif type(self) is QEngineeringTagNoTextItem: |
398 |
self.getTagNoAttributes(_attrs)
|
399 |
self.attrs = _attrs
|
400 |
return self.attrs |
401 |
else:
|
402 |
symbolAttrs = app_doc_data.getSymbolAttribute(self.type)
|
403 | |
404 |
targetAttrs = [] |
405 |
symbol_attr_number = 0
|
406 |
if not (type(self) is QEngineeringLineItem or type(self) is QEngineeringVendorItem or |
407 |
type(self) is QEngineeringLineNoTextItem or type(self) is QEngineeringTagNoTextItem): |
408 |
for attr in symbolAttrs: |
409 |
if not attr.Target and not type(self) is QEngineeringSpecBreakItem: |
410 |
continue
|
411 |
if attr.Target is None or attr.Target == 'ALL' or \ |
412 |
type(self) is QEngineeringSpecBreakItem or \ |
413 |
[target for target in attr.Target.split(',') if self.dbUid is int(target)]: |
414 |
targetAttrs.append(attr) |
415 |
if attr.AttributeType == 'Symbol Item' or attr.AttributeType == 'Line Item' or attr.AttributeType == 'EQ Item' or attr.AttributeType == 'Comp Item': |
416 |
symbol_attr_number = max(symbol_attr_number, int(attr.AttrAt)) |
417 |
else:
|
418 |
targetAttrs = symbolAttrs |
419 | |
420 |
_texts = self.texts()
|
421 |
_symbols = self.symbols(symbol_attr_number + 1) |
422 | |
423 |
# copy old values
|
424 |
for attr in targetAttrs: |
425 |
matches = [_attr for _attr, _ in self.attrs.items() if _attr.UID == attr.UID] |
426 |
if matches:
|
427 |
if matches[0].AttributeType == 'Spec' and not self.attrs[matches[0]]: |
428 |
continue
|
429 |
attr.Freeze = matches[0].Freeze # update freeze value |
430 |
attr.AssocItem = matches[0].AssocItem
|
431 |
_attrs[attr] = self.attrs[matches[0]] # copy attribute value |
432 |
else:
|
433 |
if attr.AttributeType != 'Spec': |
434 |
_attrs[attr] = ''
|
435 |
self.attrs = _attrs
|
436 | |
437 |
for attr in [_attr for _attr in sorted(self.attrs.keys(), key=lambda param:int(param.Index)) \ |
438 |
if _attr.AttributeType != 'Combined' and _attr.AttributeType != 'Reference']: |
439 |
# if attr.Freeze: continue # do not evaluate value if attribute is frozen
|
440 |
if attr.AttributeType == 'Text Item' or attr.AttributeType == 'Valve Oper Code': |
441 |
at = int(attr.AttrAt)
|
442 | |
443 |
# Text Item can contain Valve Oper Code
|
444 |
if attr.AttributeType == 'Text Item': |
445 |
items = _texts |
446 |
else:
|
447 |
items = [text for text in _texts if |
448 |
QEngineeringAbstractItem.assoc_type(text) == attr.AttributeType] |
449 | |
450 |
if not attr.AssocItem and len(items) > at and not attr.Codes.values: |
451 |
attr.AssocItem = items[at] |
452 |
item = attr.AssocItem |
453 |
_attrs[attr] = eval(attr.Expression) if attr.Expression else '' |
454 |
elif attr.AssocItem:
|
455 |
item = attr.AssocItem = self.get_assoc_item(attr.AssocItem)
|
456 |
_attrs[attr] = eval(attr.Expression) if attr.Expression else '' |
457 |
else:
|
458 |
_attrs[attr] = ''
|
459 |
elif attr.AttributeType == 'Size Text Item' or attr.AttributeType == 'Tag No': |
460 |
at = int(attr.AttrAt)
|
461 |
items = [text for text in _texts if QEngineeringAbstractItem.assoc_type(text) == attr.AttributeType] |
462 |
if not attr.AssocItem and len(items) > at: |
463 |
attr.AssocItem = items[at] |
464 |
item = attr.AssocItem |
465 |
_attrs[attr] = eval(attr.Expression) if attr.Expression else '' |
466 |
else:
|
467 |
item = attr.AssocItem = self.get_assoc_item(attr.AssocItem)
|
468 |
_attrs[attr] = eval(attr.Expression) if attr.Expression and ( |
469 |
(item and 'item' in attr.Expression) or 'self' in attr.Expression) else '' |
470 |
elif attr.AttributeType == 'Symbol Item' or attr.AttributeType == 'Line Item' or \ |
471 |
attr.AttributeType == 'Comp Item' or attr.AttributeType == 'EQ Item': |
472 |
at = int(attr.AttrAt)
|
473 |
if not attr.AssocItem and len(_symbols) > at: |
474 |
attr.AssocItem = _symbols[at] |
475 |
item = attr.AssocItem |
476 |
_attrs[attr] = eval(attr.Expression) if attr.Expression else '' |
477 |
elif attr.AssocItem:
|
478 |
item = attr.AssocItem = self.get_assoc_item(attr.AssocItem)
|
479 |
_attrs[attr] = eval(attr.Expression) if attr.Expression else '' |
480 |
else:
|
481 |
_attrs[attr] = ''
|
482 |
elif attr.AttributeType == 'String': |
483 |
#_attrs[attr] = attr.Expression if attr.Expression and not _attrs[attr] else _attrs[attr]
|
484 |
_attrs[attr] = eval(attr.Expression) if attr.Expression else _attrs[attr] |
485 | |
486 |
"""calculate attribute value for combined type"""
|
487 |
p = re.compile('{[A-Za-z0-9_ ]+}')
|
488 |
for attr in [_attr for _attr in targetAttrs if _attr.AttributeType == 'Combined']: |
489 |
value, pos = '', 0 |
490 | |
491 |
matches = p.finditer(attr.Expression) |
492 |
for match in matches: |
493 |
attr_name = attr.Expression[(match.start() + 1):(match.end() - 1)] |
494 |
values = [value for key, value in _attrs.items() if key.Attribute == attr_name] |
495 |
if not values: |
496 |
values = ['\'\'']
|
497 |
value += attr.Expression[pos:match.start()] + values[0]
|
498 |
pos = match.end() |
499 | |
500 |
value += attr.Expression[pos:len(attr.Expression)]
|
501 |
_attrs[attr] = value |
502 |
"""up to here"""
|
503 | |
504 |
"""calculate attribute value for Reference type"""
|
505 |
for attr in [_attr for _attr in targetAttrs if _attr.AttributeType == 'Reference']: |
506 |
value, pos = '', 0 |
507 | |
508 |
matches = p.finditer(attr.Expression) |
509 |
for match in matches: |
510 |
attr_name = attr.Expression[(match.start() + 1):(match.end() - 1)] |
511 |
values = [value for key, value in _attrs.items() if key.Attribute == attr_name] |
512 |
if not values: |
513 |
values = [] |
514 |
value += attr.Expression[pos:match.start()] + '\'' + values[0] + '\'' |
515 |
pos = match.end() |
516 | |
517 |
value += attr.Expression[pos:len(attr.Expression)]
|
518 |
_attrs[attr] = eval(value) if attr.Expression else '' |
519 |
"""up to here"""
|
520 | |
521 |
for _attr, _value in _attrs.items(): |
522 |
if _value is None or _value == '': |
523 |
_attr.AssocItem = None
|
524 |
except Exception as ex: |
525 |
from App import App |
526 |
from AppDocData import MessageType |
527 | |
528 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
529 |
sys.exc_info()[-1].tb_lineno)
|
530 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
531 | |
532 |
return self.attrs |
533 | |
534 |
def attrib(self, name): |
535 |
""" return the value of given attribute with name """
|
536 |
matches = [(attr, value) for attr, value in self.getAttributes().items() if attr.Attribute == name] |
537 |
if matches: return matches[0][1] |
538 | |
539 |
return None |
540 | |
541 |
def set_attrib(self, attrib, value): |
542 |
""" set attribute with given value """
|
543 |
matches = [attr for attr, _ in self.attrs.items() if attr.UID == attrib.UID] |
544 |
if len(matches) == 1: self.attrs[matches[0]] = value |
545 | |
546 |
@staticmethod
|
547 |
def assoc_type(item): |
548 |
""" return association type of given item """
|
549 |
from EngineeringTextItem import QEngineeringTextItem |
550 |
from SymbolSvgItem import SymbolSvgItem |
551 |
from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem |
552 |
from QEngineeringSizeTextItem import QEngineeringSizeTextItem |
553 |
from QEngineeringTagNoTextItem import QEngineeringTagNoTextItem |
554 |
from EngineeringLineItem import QEngineeringLineItem |
555 |
from EngineeringEquipmentItem import QEngineeringEquipmentItem |
556 |
from EngineeringVendorItem import QEngineeringVendorItem |
557 | |
558 |
_type = None
|
559 | |
560 |
if type(item) is QEngineeringSizeTextItem: |
561 |
_type = 'Size Text Item'
|
562 |
elif type(item) is QEngineeringValveOperCodeTextItem: |
563 |
_type = 'Valve Oper Code'
|
564 |
elif type(item) is QEngineeringTagNoTextItem: |
565 |
_type = 'Tag No'
|
566 |
elif type(item) is QEngineeringTextItem or issubclass(type(item), QEngineeringTextItem): |
567 |
_type = 'Text Item'
|
568 |
elif type(item) is QEngineeringEquipmentItem or type(item) is QEngineeringVendorItem: |
569 |
_type = 'EQ Item'
|
570 |
elif type(item) is SymbolSvgItem or issubclass(type(item), SymbolSvgItem): |
571 |
_type = 'Symbol Item'
|
572 |
elif type(item) is QEngineeringLineItem: |
573 |
_type = 'Line Item'
|
574 |
elif issubclass(type(item), SymbolSvgItem) or type(item) is QEngineeringLineItem: |
575 |
_type = 'Comp Item'
|
576 | |
577 |
return _type
|
578 | |
579 |
def clear_attr_and_assoc_item(self, force=False): |
580 |
""" clear attrs, return true if clear attrs """
|
581 |
if force:
|
582 |
self.attrs.clear()
|
583 |
self._associations.clear()
|
584 |
return True |
585 |
else:
|
586 |
freeze = False
|
587 |
for key in self.attrs.keys(): |
588 |
if key.Freeze:
|
589 |
freeze = True
|
590 |
break
|
591 |
if freeze:
|
592 |
return False |
593 |
else:
|
594 |
self.attrs.clear()
|
595 |
self._associations.clear()
|
596 |
return True |
597 | |
598 |
def add_assoc_item(self, item, at=None, force=False): |
599 |
""" add given item to association """
|
600 | |
601 |
from EngineeringTextItem import QEngineeringTextItem |
602 |
from SymbolSvgItem import SymbolSvgItem |
603 |
from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem |
604 |
from QEngineeringSizeTextItem import QEngineeringSizeTextItem |
605 | |
606 |
if not force: |
607 |
for key in self.attrs.keys(): |
608 |
if key.Freeze:
|
609 |
return False |
610 | |
611 |
_type = QEngineeringAbstractItem.assoc_type(item) |
612 |
if _type is not None: |
613 |
if not _type in self._associations: |
614 |
self._associations[_type] = []
|
615 | |
616 |
if item in self._associations[_type]: return True |
617 | |
618 |
if at is None: |
619 |
self._associations[_type].append(item)
|
620 |
else:
|
621 |
while len(self._associations[_type]) <= at: self._associations[_type].append(None) |
622 |
# if len(self._associations[_type]) > at and self._associations[_type][at] is not None:
|
623 |
# self._associations[_type][at].owner = None
|
624 |
self._associations[_type][at] = item
|
625 | |
626 |
return True |
627 | |
628 |
return False |
629 | |
630 |
def remove_assoc_item(self, item): |
631 |
""" remove given item from association """
|
632 |
_type = QEngineeringAbstractItem.assoc_type(item) |
633 |
if _type is not None: |
634 |
if _type in self._associations and item in self._associations[_type]: |
635 |
index = self._associations[_type].index(item)
|
636 |
self._associations[_type].pop(index)
|
637 | |
638 |
@property
|
639 |
def properties(self): |
640 |
""" getter of properties """
|
641 |
import uuid |
642 |
from SymbolSvgItem import SymbolSvgItem |
643 |
from EngineeringLineItem import QEngineeringLineItem |
644 |
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem |
645 |
from EngineeringVendorItem import QEngineeringVendorItem |
646 | |
647 |
if type(self) is QEngineeringLineNoTextItem: |
648 |
for prop, value in self._properties.items(): |
649 |
if prop.is_selectable and type(value) is uuid.UUID and self.scene(): |
650 |
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(value)] |
651 |
if matches: self._properties[prop] = matches[0] |
652 | |
653 |
elif type(self) is QEngineeringLineItem: |
654 |
for prop, value in self._properties.items(): |
655 |
if prop.is_selectable and type(value) is uuid.UUID and self.scene(): |
656 |
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(value)] |
657 |
if matches: self._properties[prop] = matches[0] |
658 | |
659 |
if prop.Expression: self._properties[prop] = eval(prop.Expression) |
660 | |
661 |
elif issubclass(type(self), SymbolSvgItem): |
662 |
for prop, value in self._properties.items(): |
663 |
try:
|
664 |
if prop.is_selectable and type(value) is uuid.UUID and self.scene(): |
665 |
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(value)] |
666 |
if matches: self._properties[prop] = matches[0] |
667 | |
668 |
if prop.Expression:
|
669 |
item = self._properties[prop] # assign item |
670 |
self._properties[prop] = eval(prop.Expression) |
671 |
except Exception as ex: |
672 |
from App import App |
673 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
674 |
sys.exc_info()[-1].tb_lineno)
|
675 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
676 | |
677 |
elif type(self) is QEngineeringVendorItem: |
678 |
for prop, value in self._properties.items(): |
679 |
try:
|
680 |
if prop.is_selectable and type(value) is uuid.UUID and self.scene(): |
681 |
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(value)] |
682 |
if matches: self._properties[prop] = matches[0] |
683 | |
684 |
if prop.Expression:
|
685 |
item = self._properties[prop] # assign item |
686 |
self._properties[prop] = eval(prop.Expression) |
687 |
except Exception as ex: |
688 |
from App import App |
689 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
690 |
sys.exc_info()[-1].tb_lineno)
|
691 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
692 | |
693 |
return self._properties |
694 | |
695 |
@properties.setter
|
696 |
def properties(self, value): |
697 |
""" setter of properties """
|
698 |
self._properties = value
|
699 | |
700 |
def prop(self, name): |
701 |
""" return property with given value """
|
702 |
from SymbolSvgItem import SymbolSvgItem |
703 |
from EngineeringLineItem import QEngineeringLineItem |
704 |
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem |
705 |
from EngineeringVendorItem import QEngineeringVendorItem |
706 | |
707 |
if type(self) is QEngineeringLineNoTextItem: |
708 |
matches = [prop for prop, _ in self.properties.items() if prop.Attribute == name] |
709 |
return self.properties[matches[0]] if matches else None |
710 | |
711 |
elif type(self) is QEngineeringLineItem: |
712 |
matches = [(prop, value) for prop, value in self.properties.items() if prop.Attribute == name] |
713 |
if matches: return matches[0][1] |
714 | |
715 |
return None |
716 | |
717 |
elif issubclass(type(self), SymbolSvgItem): |
718 |
matches = [(prop, value) for prop, value in self.properties.items() if prop.Attribute == name] |
719 |
if matches: return matches[0][1] |
720 | |
721 |
return None |
722 | |
723 |
elif type(self) is QEngineeringVendorItem: |
724 |
matches = [(prop, value) for prop, value in self.properties.items() if prop.Attribute == name] |
725 |
if matches: return matches[0][1] |
726 | |
727 |
def set_property(self, property, value): |
728 |
""" set property with given value """
|
729 |
from SymbolSvgItem import SymbolSvgItem |
730 |
from EngineeringLineItem import QEngineeringLineItem |
731 |
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem |
732 |
from EngineeringVendorItem import QEngineeringVendorItem |
733 | |
734 |
if type(self) is QEngineeringLineNoTextItem: |
735 |
matches = [prop for prop, _ in self._properties.items() if prop.Attribute == property] |
736 |
if matches: self._properties[matches[0]] = value |
737 | |
738 |
elif type(self) is QEngineeringLineItem: |
739 |
if issubclass(type(value), QEngineeringAbstractItem): self.add_assoc_item(value, 0) |
740 |
matches = [prop for prop, _ in self._properties.items() if prop.Attribute == property] |
741 |
if matches: self._properties[matches[0]] = value |
742 | |
743 |
elif issubclass(type(self), SymbolSvgItem): |
744 |
if issubclass(type(value), QEngineeringAbstractItem): self.add_assoc_item(value, 0) |
745 |
matches = [prop for prop, _ in self._properties.items() if prop.Attribute == property] |
746 |
if matches: self._properties[matches[0]] = value |
747 | |
748 |
elif type(self) is QEngineeringVendorItem: |
749 |
if issubclass(type(value), QEngineeringAbstractItem): |
750 |
self.add_assoc_item(value, 0) |
751 |
matches = [prop for prop, _ in self._properties.items() if prop.Attribute == property] |
752 |
if matches: self._properties[matches[0]] = value |
753 | |
754 |
def center(self): |
755 |
return self.sceneBoundingRect().center() |
756 | |
757 | |
758 |
if __name__ == '__main__': |
759 |
import re |
760 | |
761 |
p = re.compile('{[A-Za-z0-9]+}')
|
762 |
value, pos = '', 0 |
763 | |
764 |
_attrs = {'a': '~', 'b': '!', 'C': '+'} |
765 |
expression = 'XXXXXXX{a}-{b}-{C}----'
|
766 |
matches = p.finditer(expression) |
767 |
for match in matches: |
768 |
attr_name = expression[(match.start() + 1):(match.end() - 1)] |
769 |
value += expression[pos:match.start()] + _attrs[attr_name] |
770 |
pos = match.end() |
771 | |
772 |
value += expression[pos:len(expression)]
|
773 |
print(value) |