hytos / DTI_PID / DTI_PID / Shapes / EngineeringAbstractItem.py @ ef4aed65
이력 | 보기 | 이력해설 | 다운로드 (14.9 KB)
1 |
# coding: utf-8
|
---|---|
2 |
""" This is engineering abstract item module """
|
3 |
|
4 |
import sys |
5 |
|
6 |
'''
|
7 |
@history 2018.05.15 Jeongwoo Remove Parent Object [QObject]
|
8 |
'''
|
9 |
class QEngineeringAbstractItem: |
10 |
'''
|
11 |
@history 2018.05.15 Jeongwoo Remove call super
|
12 |
2018.05.17 Jeongwoo Add DEFAULT_COLOR Variable
|
13 |
'''
|
14 |
DEFAULT_COLOR = '#0000FF'
|
15 |
HOVER_COLOR = '#BC4438'
|
16 |
|
17 |
CONNECTED_AT_PT = 0
|
18 |
CONNECTED_AT_BODY = 1
|
19 |
|
20 |
HOVER_ZVALUE = 200
|
21 |
|
22 |
def __init__(self, parent=None): |
23 |
self._color = self.DEFAULT_COLOR # default color |
24 |
self._owner = None |
25 |
self.conns = []
|
26 |
self.special_item_type = None # UID for special item type |
27 |
self._hover = False |
28 |
self._area = None |
29 |
self.connectors = []
|
30 |
self.attrs = {} # attributes |
31 |
self._associations = {'Text Item':[], 'Symbol Item':[]} # associated items |
32 |
|
33 |
@property
|
34 |
def hover(self): |
35 |
""" return hover """
|
36 |
return self._hover |
37 |
|
38 |
@hover.setter
|
39 |
def hover(self, value): |
40 |
""" set hover """
|
41 |
self._hover = value
|
42 |
|
43 |
def change_color(self, value): |
44 |
""" change item's color """
|
45 |
self._color = value
|
46 |
|
47 |
def highlight(self, flag): |
48 |
pass
|
49 |
|
50 |
'''
|
51 |
@brief Abstract method. Variable [color] is RGB hex code
|
52 |
@author Jeongwoo
|
53 |
@date 2018.05.11
|
54 |
'''
|
55 |
def setColor(self, color): |
56 |
raise NotImplementedError |
57 |
|
58 |
'''
|
59 |
@brief return color
|
60 |
@author Jeongwoo
|
61 |
@date 2018.05.11
|
62 |
'''
|
63 |
def getColor(self): |
64 |
return QEngineeringAbstractItem.HOVER_COLOR if self.hover else (self.owner.getColor() if (self.owner and hasattr(self.owner, '_color')) else self._color) |
65 |
|
66 |
'''
|
67 |
@brief getter of owner
|
68 |
@author humkyung
|
69 |
@date 2018.05.12
|
70 |
'''
|
71 |
@property
|
72 |
def owner(self): |
73 |
return self._owner |
74 |
|
75 |
'''
|
76 |
@brief setter of owner
|
77 |
@author humkyung
|
78 |
@date 2018.05.12
|
79 |
'''
|
80 |
@owner.setter
|
81 |
def owner(self, value): |
82 |
self._owner = value
|
83 |
|
84 |
@property
|
85 |
def has_connection(self): |
86 |
""" check this is connected to other """
|
87 |
for connector in self.connectors: |
88 |
if connector.connectedItem: return True |
89 |
|
90 |
return False |
91 |
|
92 |
def validate(self): |
93 |
""" validate this """
|
94 |
raise NotImplementedError('To be implemented') |
95 |
|
96 |
'''
|
97 |
@brief getter of area
|
98 |
@author humkyung
|
99 |
@date 2018.09.06
|
100 |
'''
|
101 |
@property
|
102 |
def area(self): |
103 |
return self._area if self._area is not None else 'None' |
104 |
|
105 |
'''
|
106 |
@brief setter of area
|
107 |
@author humkyung
|
108 |
@date 2018.09.06
|
109 |
'''
|
110 |
@area.setter
|
111 |
def area(self, value): |
112 |
self._area = value
|
113 |
|
114 |
'''
|
115 |
@brief write to xml
|
116 |
@author humkyung
|
117 |
@date 2018.05.16
|
118 |
'''
|
119 |
def toXml(self): |
120 |
pass
|
121 |
|
122 |
'''
|
123 |
@brief write attribute to xml
|
124 |
@author humkyung
|
125 |
@date 2018.05.16
|
126 |
'''
|
127 |
def toXmlAsAttribute(self, parent): |
128 |
pass
|
129 |
|
130 |
def toSql(self): |
131 |
"""convert to sql query"""
|
132 |
pass
|
133 |
|
134 |
def isOverlap(self, rect1, rect2): |
135 |
"""
|
136 |
@brief return true if rects have intersection, rect is QRect
|
137 |
@author euisung
|
138 |
@date 2019.09.02
|
139 |
"""
|
140 |
lt1, rb1 = (rect1.left(), rect1.top()), (rect1.right(), rect1.bottom()) |
141 |
lt2, tb2 = (rect2.left(), rect2.top()), (rect2.right(), rect2.bottom()) |
142 |
if rect1.left() > rect2.right() or rect2.left() > rect1.right(): |
143 |
return False |
144 |
if rect1.bottom() < rect2.top() or rect2.bottom() < rect1.top(): |
145 |
return False |
146 |
|
147 |
return True |
148 |
|
149 |
def associations(self): |
150 |
""" return associated instance """
|
151 |
# move to abstractitem
|
152 |
import uuid |
153 |
|
154 |
res = [] |
155 |
for key in self._associations.keys(): |
156 |
index = 0
|
157 |
for assoc in list(set(self._associations[key])): |
158 |
# find owner with uid if self.scene() is valid
|
159 |
if self.scene() and assoc and type(assoc) is uuid.UUID: |
160 |
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(assoc)] |
161 |
if matches:
|
162 |
res.append(matches[0])
|
163 |
self._associations[key][index] = matches[0] |
164 |
# up to here
|
165 |
elif assoc:
|
166 |
res.append(assoc) |
167 |
index += 1
|
168 |
|
169 |
for key in self.attrs.keys(): |
170 |
if type(key.AssocItem) is uuid.UUID: |
171 |
for assoc in res: |
172 |
if str(key.AssocItem) == str(assoc.uid): |
173 |
key.AssocItem = assoc |
174 |
|
175 |
return res
|
176 |
|
177 |
def get_assoc_item(self, assoc): |
178 |
""" get associated item of given object """
|
179 |
import uuid |
180 |
|
181 |
if assoc and type(assoc) is uuid.UUID: |
182 |
matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(assoc)] |
183 |
if matches: return matches[0] |
184 |
|
185 |
return assoc
|
186 |
|
187 |
def texts(self): |
188 |
""" return text type of associations """
|
189 |
from EngineeringTextItem import QEngineeringTextItem |
190 |
|
191 |
res = [] |
192 |
|
193 |
for text in sorted([x for x in self.associations() if issubclass(type(x), QEngineeringTextItem)], key=lambda attr: attr.loc[1]): |
194 |
consumed = False
|
195 |
for key in list(self.attrs.keys()): |
196 |
if key.AssocItem and key.AssocItem is text: |
197 |
consumed = True
|
198 |
if not consumed: |
199 |
res.append(text) |
200 |
|
201 |
return res
|
202 |
|
203 |
def symbols(self): |
204 |
""" return symbol type of associations """
|
205 |
from SymbolSvgItem import SymbolSvgItem |
206 |
|
207 |
res = [] |
208 |
for symbol in [x for x in self.associations() if issubclass(type(x), SymbolSvgItem)]: |
209 |
consumed = False
|
210 |
for key in list(self.attrs.keys()): |
211 |
if key.AssocItem and key.AssocItem is symbol: |
212 |
consumed = True
|
213 |
if not consumed: |
214 |
res.append(symbol) |
215 |
|
216 |
return res
|
217 |
|
218 |
def getAttributes(self): |
219 |
_attrs = {} |
220 |
try:
|
221 |
from AppDocData import AppDocData |
222 |
from SymbolSvgItem import SymbolSvgItem |
223 |
from EngineeringTextItem import QEngineeringTextItem |
224 |
from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem |
225 |
from EngineeringLineItem import QEngineeringLineItem |
226 |
from EngineeringVendorItem import QEngineeringVendorItem |
227 |
|
228 |
""" get attributes of item from database """
|
229 |
docData = AppDocData.instance() |
230 |
if type(self) is QEngineeringLineItem: |
231 |
symbolAttrs = docData.getSymbolAttribute('Line')
|
232 |
elif type(self) is QEngineeringVendorItem: |
233 |
symbolAttrs = docData.getSymbolAttribute('Package')
|
234 |
else:
|
235 |
symbolAttrs = docData.getSymbolAttribute(self.type)
|
236 |
targetAttrs = [] |
237 |
if type(self) is not QEngineeringLineItem: |
238 |
for attr in symbolAttrs: |
239 |
if attr.Target is None or attr.Target == 'ALL' or [target for target in attr.Target.split(',') if self.dbUid is int(target)]: |
240 |
targetAttrs.append(attr) |
241 |
else:
|
242 |
targetAttrs = symbolAttrs |
243 |
|
244 |
_texts = self.texts()
|
245 |
_symbols = self.symbols()
|
246 |
for attr in targetAttrs: |
247 |
matches = [_attr for _attr,_ in self.attrs.items() if _attr.UID == attr.UID] |
248 |
if matches:
|
249 |
attr.Freeze = matches[0].Freeze # update freeze value |
250 |
attr.AssocItem = matches[0].AssocItem
|
251 |
_attrs[attr] = self.attrs[matches[0]] # copy attribute value |
252 |
else:
|
253 |
_attrs[attr] = ''
|
254 |
|
255 |
# if attr.Freeze: continue # do not evaluate value if attribute is frozen
|
256 |
if attr.AttributeType == 'Text Item' or attr.AttributeType == 'Valve Oper Code': |
257 |
at = int(attr.AttrAt)
|
258 |
|
259 |
# Text Item can contain Valve Oper Code
|
260 |
if attr.AttributeType == 'Text Item': |
261 |
items = _texts |
262 |
else:
|
263 |
items = [text for text in _texts if QEngineeringAbstractItem.assoc_type(text) == attr.AttributeType] |
264 |
|
265 |
if not attr.AssocItem and len(items) > at and not attr.Codes.values: |
266 |
attr.AssocItem = items[at] |
267 |
item = attr.AssocItem |
268 |
_attrs[attr] = eval(attr.Expression) if attr.Expression else '' |
269 |
elif attr.AssocItem:
|
270 |
item = attr.AssocItem = self.get_assoc_item(attr.AssocItem)
|
271 |
_attrs[attr] = eval(attr.Expression) if attr.Expression else '' |
272 |
else:
|
273 |
_attrs[attr] = ''
|
274 |
elif attr.AttributeType == 'Size Text Item': |
275 |
at = int(attr.AttrAt)
|
276 |
items = [text for text in _texts if QEngineeringAbstractItem.assoc_type(text) == attr.AttributeType] |
277 |
if not attr.AssocItem and len(items) > at: |
278 |
attr.AssocItem = items[at] |
279 |
item = attr.AssocItem |
280 |
_attrs[attr] = eval(attr.Expression) if attr.Expression else '' |
281 |
else:
|
282 |
item = attr.AssocItem = self.get_assoc_item(attr.AssocItem)
|
283 |
_attrs[attr] = eval(attr.Expression) if attr.Expression and ((item and 'item' in attr.Expression) or 'self' in attr.Expression) else '' |
284 |
elif attr.AttributeType == 'Symbol Item' or attr.AttributeType == 'Line Item' or attr.AttributeType == 'Comp Item': |
285 |
at = int(attr.AttrAt)
|
286 |
if not attr.AssocItem and len(_symbols) > at: |
287 |
attr.AssocItem = _symbols[at] |
288 |
item = attr.AssocItem |
289 |
_attrs[attr] = eval(attr.Expression) if attr.Expression else '' |
290 |
elif attr.AssocItem:
|
291 |
item = attr.AssocItem = self.get_assoc_item(attr.AssocItem)
|
292 |
_attrs[attr] = eval(attr.Expression) if attr.Expression else '' |
293 |
else:
|
294 |
_attrs[attr] = ''
|
295 |
elif attr.AttributeType == 'Tag No': |
296 |
_attrs[attr] = eval(attr.Expression) if attr.Expression and not _attrs[attr] else _attrs[attr] |
297 |
elif attr.AttributeType == 'String': |
298 |
_attrs[attr] = attr.Expression if attr.Expression and not _attrs[attr] else _attrs[attr] |
299 |
|
300 |
for _attr,_value in _attrs.items(): |
301 |
if _value is None or _value == '': |
302 |
_attr.AssocItem = None
|
303 |
|
304 |
self.attrs = _attrs
|
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, sys.exc_info()[-1].tb_lineno) |
310 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
311 |
|
312 |
return self.attrs |
313 |
|
314 |
def attrib(self, name): |
315 |
""" return the value of given attribute with name """
|
316 |
matches = [(attr,value) for attr,value in self.getAttributes().items() if attr.Attribute == name] |
317 |
if matches: return matches[0][1] |
318 |
|
319 |
return None |
320 |
|
321 |
def set_attrib(self, attrib, value): |
322 |
""" set attribute with given value """
|
323 |
matches = [attr for attr,_ in self.attrs.items() if attr.UID == attrib.UID] |
324 |
if len(matches) == 1: self.attrs[matches[0]] = value |
325 |
|
326 |
@staticmethod
|
327 |
def assoc_type(item): |
328 |
""" return association type of given item """
|
329 |
from EngineeringTextItem import QEngineeringTextItem |
330 |
from SymbolSvgItem import SymbolSvgItem |
331 |
from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem |
332 |
from QEngineeringSizeTextItem import QEngineeringSizeTextItem |
333 |
from QEngineeringTagNoTextItem import QEngineeringTagNoTextItem |
334 |
from EngineeringLineItem import QEngineeringLineItem |
335 |
|
336 |
_type = None
|
337 |
|
338 |
if type(item) is QEngineeringSizeTextItem: |
339 |
_type = 'Size Text Item'
|
340 |
elif type(item) is QEngineeringValveOperCodeTextItem: |
341 |
_type = 'Valve Oper Code'
|
342 |
elif type(item) is QEngineeringTagNoTextItem: |
343 |
_type = 'Tag No'
|
344 |
elif type(item) is QEngineeringTextItem or issubclass(type(item), QEngineeringTextItem): |
345 |
_type = 'Text Item'
|
346 |
elif type(item) is SymbolSvgItem or issubclass(type(item), SymbolSvgItem): |
347 |
_type = 'Symbol Item'
|
348 |
elif type(item) is QEngineeringLineItem: |
349 |
_type = 'Line Item'
|
350 |
elif issubclass(type(item), SymbolSvgItem) or type(item) is QEngineeringLineItem: |
351 |
_type = 'Comp Item'
|
352 |
|
353 |
return _type
|
354 |
|
355 |
def clear_attr_and_assoc_item(self, force=False): |
356 |
""" clear attrs, return true if clear attrs """
|
357 |
if force:
|
358 |
self.attrs.clear()
|
359 |
self._associations.clear()
|
360 |
return True |
361 |
else:
|
362 |
freeze = False
|
363 |
for key in self.attrs.keys(): |
364 |
if key.Freeze:
|
365 |
freeze = True
|
366 |
break
|
367 |
if freeze:
|
368 |
return False |
369 |
else:
|
370 |
self.attrs.clear()
|
371 |
self._associations.clear()
|
372 |
return True |
373 |
|
374 |
def add_assoc_item(self, item, at=None, force=False): |
375 |
""" add given item to association """
|
376 |
|
377 |
from EngineeringTextItem import QEngineeringTextItem |
378 |
from SymbolSvgItem import SymbolSvgItem |
379 |
from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem |
380 |
from QEngineeringSizeTextItem import QEngineeringSizeTextItem |
381 |
|
382 |
if not force: |
383 |
for key in self.attrs.keys(): |
384 |
if key.Freeze:
|
385 |
return False |
386 |
|
387 |
_type = QEngineeringAbstractItem.assoc_type(item) |
388 |
if _type is not None: |
389 |
if not _type in self._associations: |
390 |
self._associations[_type] = []
|
391 |
|
392 |
if item in self._associations[_type]: return True |
393 |
|
394 |
if at is None: |
395 |
self._associations[_type].append(item)
|
396 |
else:
|
397 |
while len(self._associations[_type]) <= at: self._associations[_type].append(None) |
398 |
#if len(self._associations[_type]) > at and self._associations[_type][at] is not None:
|
399 |
# self._associations[_type][at].owner = None
|
400 |
self._associations[_type][at] = item
|
401 |
|
402 |
return True |
403 |
|
404 |
return False |
405 |
|
406 |
def remove_assoc_item(self, item): |
407 |
""" remove given item from association """
|
408 |
_type = QEngineeringAbstractItem.assoc_type(item) |
409 |
if _type is not None: |
410 |
if _type in self._associations and item in self._associations[_type]: |
411 |
index = self._associations[_type].index(item)
|
412 |
self._associations[_type].pop(index)
|