프로젝트

일반

사용자정보

통계
| 개정판:

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)
클립보드 이미지 추가 (최대 크기: 500 MB)