프로젝트

일반

사용자정보

통계
| 개정판:

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)