프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

hytos / DTI_PID / DTI_PID / Shapes / EngineeringAbstractItem.py @ 0d810983

이력 | 보기 | 이력해설 | 다운로드 (53.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
    SELECTED_COLOR = '#FF00BF'
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
        self.sizeDepth = 0
33

    
34
        #self.refresh_count = random.randint(0, 9)
35

    
36
    @property
37
    def hover(self):
38
        """ return hover """
39
        return self._hover
40

    
41
    @hover.setter
42
    def hover(self, value):
43
        """ set hover """
44
        self._hover = value
45

    
46
    def change_color(self, value):
47
        """ change item's color """
48
        self._color = value
49

    
50
    def highlight(self, flag):
51
        pass
52

    
53
    '''
54
        @brief      Abstract method. Variable [color] is RGB hex code
55
        @author     Jeongwoo
56
        @date       2018.05.11
57
    '''
58

    
59
    def setColor(self, color):
60
        raise NotImplementedError
61

    
62
    '''
63
        @brief  return color
64
        @author Jeongwoo
65
        @date   2018.05.11
66
    '''
67

    
68
    def getColor(self):
69
        from SymbolSvgItem import SymbolSvgItem
70
        from EngineeringEquipmentItem import QEngineeringEquipmentItem
71
        from EngineeringInstrumentItem import QEngineeringInstrumentItem
72
        from AppDocData import AppDocData
73
        from DisplayColors import DisplayColors
74
        from DisplayColors import DisplayOptions
75
        from EngineeringAbstractItem import QEngineeringAbstractItem
76
        from EngineeringLineItem import QEngineeringLineItem
77

    
78
        def check_stream_no_attribute():
79
            """ return stream no if item has stream no attribute else return False """
80
            _attrs = self.getAttributes(findOwner=True)
81
            for key, value in _attrs.items():
82
                if key.Attribute == 'Stream No':
83
                    if value:
84
                        return value
85
                    elif value == '' or value == None:
86
                        return None
87
                    else:
88
                        return False
89

    
90
        try:
91
            if DisplayOptions.DisplayByStreamNo == DisplayColors.instance().option and \
92
                    (issubclass(type(self), SymbolSvgItem) or type(self) is QEngineeringLineItem):
93
                app_doc_data = AppDocData.instance()
94
                res = check_stream_no_attribute()
95
                if res and res in app_doc_data._hmbColors:
96
                    return app_doc_data._hmbColors[res]
97
                else:
98
                    return QEngineeringAbstractItem.DEFAULT_COLOR
99

    
100
            if type(self) is QEngineeringEquipmentItem:
101
                # if DisplayOptions.DisplayByLineType == DisplayColors.instance().option:
102
                if self.hover:
103
                    return SymbolSvgItem.HOVER_COLOR
104
                elif not QEngineeringEquipmentItem.EQUIP_COLOR:
105
                    app_doc_data = AppDocData.instance()
106
                    configs = app_doc_data.getConfigs('Equipment', 'Color')
107
                    QEngineeringEquipmentItem.EQUIP_COLOR = configs[
108
                        0].value if configs else QEngineeringAbstractItem.DEFAULT_COLOR
109

    
110
                return QEngineeringEquipmentItem.EQUIP_COLOR
111

    
112
            elif type(self) is QEngineeringInstrumentItem:
113
                if self.hover:
114
                        return SymbolSvgItem.HOVER_COLOR
115
                elif DisplayOptions.DisplayByLineType == DisplayColors.instance().option:
116
                    if not QEngineeringInstrumentItem.INST_COLOR:
117
                        app_doc_data = AppDocData.instance()
118
                        configs = app_doc_data.getConfigs('Instrument', 'Color')
119
                        QEngineeringInstrumentItem.INST_COLOR = configs[
120
                            0].value if configs else QEngineeringAbstractItem.DEFAULT_COLOR
121
                    return QEngineeringInstrumentItem.INST_COLOR
122
                else:
123
                    return self.owner._color if self.owner and hasattr(self.owner, '_color') else self._color
124

    
125
            elif type(self) is SymbolSvgItem:
126
                return SymbolSvgItem.HOVER_COLOR if self.hover else ( \
127
                    self.owner._color if self.owner and hasattr(self.owner, '_color') else self._color)
128

    
129
            elif type(self) is QEngineeringLineItem:
130
                if self.hover:
131
                    return QEngineeringAbstractItem.HOVER_COLOR
132
                elif self.isSelected():
133
                    return QEngineeringAbstractItem.SELECTED_COLOR
134
                elif DisplayOptions.DisplayByLineType == DisplayColors.instance().option:
135
                    if self.lineType in QEngineeringLineItem.LINE_TYPE_COLORS:
136
                        return QEngineeringLineItem.LINE_TYPE_COLORS[self.lineType]
137
                    else:
138
                        app_doc_data = AppDocData.instance()
139
                        configs = app_doc_data.getConfigs('LineTypes', self.lineType)
140
                        if configs:
141
                            tokens = configs[0].value.split(',')
142
                            QEngineeringLineItem.LINE_TYPE_COLORS[self.lineType] = tokens[0] if len(tokens) == 4 else \
143
                                QEngineeringAbstractItem.DEFAULT_COLOR
144
                            return QEngineeringLineItem.LINE_TYPE_COLORS[self.lineType]
145
                        else:
146
                            return QEngineeringAbstractItem.DEFAULT_COLOR
147
                else:
148
                    return self.owner._color if self.owner and hasattr(self.owner, '_color') else self._color
149
                    '''
150
                    if self.owner is None:
151
                        return self._color
152
                    else:
153
                        return self.owner.getColor()
154
                    '''
155
        except Exception as ex:
156
            from App import App
157
            from AppDocData import MessageType
158

    
159
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
160
                                                           sys.exc_info()[-1].tb_lineno)
161
            App.mainWnd().addMessage.emit(MessageType.Error, message)
162

    
163
            return  QEngineeringAbstractItem.DEFAULT_COLOR
164

    
165
        return QEngineeringAbstractItem.HOVER_COLOR if self.hover else (
166
            self.owner.getColor() if (self.owner and hasattr(self.owner, '_color')) else self._color)
167

    
168
    '''
169
        @brief  getter of owner
170
        @author humkyung
171
        @date   2018.05.12
172
    '''
173

    
174
    @property
175
    def owner(self):
176
        return self._owner
177

    
178
    '''
179
        @brief  setter of owner
180
        @author humkyung
181
        @date   2018.05.12
182
    '''
183

    
184
    @owner.setter
185
    def owner(self, value):
186
        self._owner = value
187

    
188
    @property
189
    def has_connection(self):
190
        """ check this is connected to other """
191
        for connector in self.connectors:
192
            if connector.connectedItem: return True
193

    
194
        return False
195

    
196
    def validate(self):
197
        """ validate this """
198
        raise NotImplementedError('To be implemented')
199

    
200
    '''
201
        @brief  getter of area
202
        @author humkyung
203
        @date   2018.09.06
204
    '''
205

    
206
    @property
207
    def area(self):
208
        return self._area if self._area is not None else 'None'
209

    
210
    '''
211
        @brief  setter of area
212
        @author humkyung
213
        @date   2018.09.06
214
    '''
215

    
216
    @area.setter
217
    def area(self, value):
218
        self._area = value
219

    
220
    '''
221
        @brief  write to xml
222
        @author humkyung
223
        @date   2018.05.16
224
    '''
225

    
226
    def toXml(self):
227
        pass
228

    
229
    def to_svg(self, parent=None) -> list:
230
        pass
231

    
232
    '''
233
        @brief  write attribute to xml
234
        @author humkyung
235
        @date   2018.05.16
236
    '''
237

    
238
    def toXmlAsAttribute(self, parent):
239
        pass
240

    
241
    def toSql(self):
242
        """convert to sql query"""
243
        pass
244

    
245
    def isOverlap(self, rect1, rect2):
246
        """
247
        @brief  return true if rects have intersection, rect is QRect
248
        @author euisung
249
        @date   2019.09.02
250
        """
251
        lt1, rb1 = (rect1.left(), rect1.top()), (rect1.right(), rect1.bottom())
252
        lt2, tb2 = (rect2.left(), rect2.top()), (rect2.right(), rect2.bottom())
253
        if rect1.left() > rect2.right() or rect2.left() > rect1.right():
254
            return False
255
        if rect1.bottom() < rect2.top() or rect2.bottom() < rect1.top():
256
            return False
257

    
258
        return True
259

    
260
    def associations(self):
261
        """ return associated instance """
262
        # move to abstractitem
263
        import uuid
264

    
265
        try:
266
            res = []
267
            for key in self._associations.keys():
268
                index = 0
269
                for assoc in list(self._associations[key]):
270
                    # find owner with uid if self.scene() is valid
271
                    if self.scene() and assoc and type(assoc) is uuid.UUID:
272
                        #matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(assoc)]
273
                        matches = []
274
                        for item in self.scene().items():
275
                            if hasattr(item, 'uid') and str(item.uid) == str(assoc):
276
                                matches = [item]
277
                                break
278
                        if matches:
279
                            res.append(matches[0])
280
                            self._associations[key][index] = matches[0]
281
                    # up to here
282
                    elif assoc:
283
                        res.append(assoc)
284
                    index += 1
285

    
286
            for key in self.attrs.keys():
287
                if type(key.AssocItem) is uuid.UUID:
288
                    for assoc in res:
289
                        if str(key.AssocItem) == str(assoc.uid):
290
                            key.AssocItem = assoc
291

    
292
            return res
293
        except Exception as ex:
294
            from App import App
295
            from AppDocData import MessageType
296

    
297
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
298
                                                           sys.exc_info()[-1].tb_lineno)
299
            App.mainWnd().addMessage.emit(MessageType.Error, message)
300
            return []
301

    
302
    def get_assoc_item(self, assoc):
303
        """ get associated item of given object """
304
        import uuid
305

    
306
        if assoc and type(assoc) is uuid.UUID:
307
            #matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(assoc)]
308
            matches = []
309
            for item in self.scene().items():
310
                if hasattr(item, 'uid') and str(item.uid) == str(assoc):
311
                    matches = [item]
312
                    break
313
            if matches:
314
                return matches[0]
315

    
316
        return assoc
317

    
318
    def texts(self):
319
        """ return text type of associations """
320
        res = []
321

    
322
        for text in self.texts_order():
323
            consumed = False
324
            for key in list(self.attrs.keys()):
325
                if key.AssocItem and key.AssocItem is text:
326
                    consumed = True
327
            if not consumed:
328
                res.append(text)
329

    
330
        return res
331

    
332
    def texts_order(self):
333
        from EngineeringTextItem import QEngineeringTextItem
334
        
335
        return sorted([x for x in self.associations() if issubclass(type(x), QEngineeringTextItem)],
336
                           key=lambda attr: attr.loc[1])
337

    
338
    def symbols(self, symbol_attr_number):
339
        """ return symbol type of associations """
340
        from SymbolSvgItem import SymbolSvgItem
341
        from EngineeringVendorItem import QEngineeringVendorItem
342
        from EngineeringLineItem import QEngineeringLineItem
343
        from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
344

    
345
        res = []
346
        for symbol in [x for x in self.associations() if
347
                       issubclass(type(x), SymbolSvgItem) or type(x) is QEngineeringVendorItem or type(x) is QEngineeringLineItem]:
348
            if symbol_attr_number > 1:
349
                consumed = False
350
                for key in list(self.attrs.keys()):
351
                    if key.AssocItem and key.AssocItem is symbol:
352
                        consumed = True
353
                if not consumed:
354
                    res.append(symbol)
355
            elif type(self) is not QEngineeringLineNoTextItem:
356
                res.append(symbol)
357

    
358
        return res
359

    
360
    @property
361
    def Size(self):
362
        """ return symbol's size """
363
        from QEngineeringSizeTextItem import QEngineeringSizeTextItem
364

    
365
        matches = [assoc for assoc in self.associations() if type(assoc) is QEngineeringSizeTextItem]
366
        if matches:
367
            attrs = [attr for attr in self.getTargetAttributes() if attr.AttributeType == 'Size Text Item']
368
            if attrs:
369
                return matches[0].mainSize
370

    
371
        return None
372

    
373
    @property
374
    def EvaluatedSize(self):
375
        from EngineeringReducerItem import QEngineeringReducerItem
376
        from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
377
        from SymbolSvgItem import SymbolSvgItem
378
        from EngineeringLineItem import QEngineeringLineItem
379
        from EngineeringInstrumentItem import QEngineeringInstrumentItem
380
        from AppDocData import AppDocData
381

    
382
        try:
383
            if self.Size:
384
                self.sizeDepth = 0
385
                return self.Size
386
            if self.owner and issubclass(type(self.owner), QEngineeringLineNoTextItem):
387
                matches = [run for run in self.owner.runs if self in run.items]
388
                if matches:
389
                    at = matches[0].items.index(self)
390
                    upstream = matches[0].items[:at]
391
                    upstream.reverse()
392
                    prev = self
393
                    for item in upstream:
394
                        if type(item) is QEngineeringReducerItem:
395
                            if item.connectors[0].connectedItem is prev:  ### Main Size
396
                                if item.mainSubSize and item.mainSubSize[0]:
397
                                    self.sizeDepth = 0
398
                                    return item.mainSubSize[0]
399
                            elif item.connectors[1].connectedItem is prev:  ### Sub Size
400
                                if item.mainSubSize and item.mainSubSize[1]:
401
                                    self.sizeDepth = 0
402
                                    return item.mainSubSize[1]
403
                        elif type(item) is QEngineeringInstrumentItem and item.iType == 22: # Relief Valve -> upstream always false
404
                            if item.mainSubSize and item.mainSubSize[0]:
405
                                self.sizeDepth = 0
406
                                return item.mainSubSize[0]
407
                        else:
408
                            if item.Size:
409
                                self.sizeDepth = 0
410
                                return item.Size
411
                        prev = item
412

    
413
                    downstream = matches[0].items[at:]
414
                    prev = self
415
                    for item in downstream:
416
                        if type(item) is QEngineeringReducerItem:
417
                            if item.connectors[0].connectedItem is prev:  ### Main Size
418
                                if item.mainSubSize and item.mainSubSize[0]:
419
                                    self.sizeDepth = 0
420
                                    return item.mainSubSize[0]
421
                            elif item.connectors[1].connectedItem is prev:  ### Sub Size
422
                                if item.mainSubSize and item.mainSubSize[1]:
423
                                    self.sizeDepth = 0
424
                                    return item.mainSubSize[1]
425
                        elif type(item) is QEngineeringInstrumentItem and item.iType == 22: # Relief Valve
426
                            if item.mainSubSize and item.mainSubSize[1]:
427
                                self.sizeDepth = 0
428
                                return item.mainSubSize[1]
429
                        else:
430
                            if item.Size:
431
                                self.sizeDepth = 0
432
                                return item.Size
433
                        prev = item
434

    
435
                    #if 'Drain' == matches[0].Type:
436
                    #    self.sizeDepth = 0
437
                    #    return ''
438
                    #    #return AppDocData.instance().drain_size
439

    
440
                if self.owner.runs and self in self.owner.runs[0].items:
441
                    self.sizeDepth = 0
442
                    return self.owner.Size 
443
                elif self.sizeDepth < 2:
444
                    matches = [run for run in self.owner.runs if self in run.items]
445
                    if matches:
446
                        if type(matches[0].items[0]) is QEngineeringLineItem:
447
                            _item = matches[0].items[0]
448
                            connectedItems = [conn.connectedItem for conn in _item.connectors if conn._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT and \
449
                                                                                                            conn.connectedItem and conn.connectedItem not in matches[0].items]
450
                            if connectedItems:
451
                                connectedItems[0].sizeDepth = self.sizeDepth + 1
452
                                res  = connectedItems[0].EvaluatedSize
453
                                if res:
454
                                    self.sizeDepth = 0
455
                                    return res
456
                        if type(matches[0].items[-1]) is QEngineeringLineItem:
457
                            _item = matches[0].items[-1]
458
                            connectedItems = [conn.connectedItem for conn in _item.connectors if conn._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT and \
459
                                                                                                            conn.connectedItem and conn.connectedItem not in matches[0].items]
460
                            if connectedItems:
461
                                connectedItems[0].sizeDepth = self.sizeDepth + 1
462
                                res  = connectedItems[0].EvaluatedSize
463
                                if res:
464
                                    self.sizeDepth = 0
465
                                    return res
466
                        if issubclass(type(matches[0].items[0]), SymbolSvgItem):
467
                            _item = matches[0].items[0]
468
                            connectedItems = [_item.connectors[index].connectedItem for index in range(len(_item.conn_type)) if (_item.conn_type[index] == 'Secondary' or _item.conn_type[index] == 'Primary') and \
469
                                                                                                            _item.connectors[index].connectedItem and _item.connectors[index].connectedItem not in matches[0].items]
470
                            if connectedItems:
471
                                connectedItems[0].sizeDepth = self.sizeDepth + 1
472
                                res  = connectedItems[0].EvaluatedSize
473
                                if res:
474
                                    self.sizeDepth = 0
475
                                    return res
476
                        if issubclass(type(matches[0].items[-1]), SymbolSvgItem):
477
                            _item = matches[0].items[-1]
478
                            connectedItems = [_item.connectors[index].connectedItem for index in range(len(_item.conn_type)) if (_item.conn_type[index] == 'Secondary' or _item.conn_type[index] == 'Primary') and \
479
                                                                                                            _item.connectors[index].connectedItem and _item.connectors[index].connectedItem not in matches[0].items]
480
                            if connectedItems:
481
                                connectedItems[0].sizeDepth = self.sizeDepth + 1
482
                                res  = connectedItems[0].EvaluatedSize
483
                                if res:
484
                                    self.sizeDepth = 0
485
                                    return res
486
                        '''
487
                        if type(matches[0].items[0]) is QEngineeringLineItem and type(matches[0].items[-1]) is QEngineeringLineItem:
488
                            res1 = None
489
                            res2 = None
490

491
                            _item = matches[0].items[0]
492
                            connectedItems = [conn.connectedItem for conn in _item.connectors if conn.connectedItem and conn.connectedItem not in matches[0].items]
493
                            if connectedItems:
494
                                connectedItems[0].sizeDepth = self.sizeDepth + 1
495
                                res1  = connectedItems[0].EvaluatedSize
496
                                
497
                            _item = matches[0].items[-1]
498
                            connectedItems = [conn.connectedItem for conn in _item.connectors if conn.connectedItem and conn.connectedItem not in matches[0].items]
499
                            connectedItems.reverse()
500
                            if connectedItems:
501
                                connectedItems[0].sizeDepth = self.sizeDepth + 1
502
                                res2  = connectedItems[0].EvaluatedSize
503
                                if res1 and res2:
504
                                    self.sizeDepth = 0
505
                                    return res1 if self.inch_to_number(res1) <= self.inch_to_number(res2) else res2
506
                        '''
507
                        if type(matches[0].items[0]) is QEngineeringLineItem:
508
                            _item = matches[0].items[0]
509
                            connectedItems = [conn.connectedItem for conn in _item.connectors if conn.connectedItem and conn.connectedItem not in matches[0].items]
510
                            if connectedItems:
511
                                connectedItems[0].sizeDepth = self.sizeDepth + 1
512
                                res  = connectedItems[0].EvaluatedSize
513
                                if res:
514
                                    self.sizeDepth = 0
515
                                    return res
516
                        if type(matches[0].items[-1]) is QEngineeringLineItem:
517
                            _item = matches[0].items[-1]
518
                            connectedItems = [conn.connectedItem for conn in _item.connectors if conn.connectedItem and conn.connectedItem not in matches[0].items]
519
                            if connectedItems:
520
                                connectedItems[0].sizeDepth = self.sizeDepth + 1
521
                                res  = connectedItems[0].EvaluatedSize
522
                                if res:
523
                                    self.sizeDepth = 0
524
                                    return res
525

    
526
            self.sizeDepth = 0
527
            return ''
528
        except Exception as ex:
529
            from App import App
530
            from AppDocData import MessageType
531

    
532
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
533
                                                          sys.exc_info()[-1].tb_lineno)
534
            #App.mainWnd().addMessage.emit(MessageType.Error, str(self.uid) + self.name + message)
535
            App.mainWnd().addMessage.emit(MessageType.Error, message)
536

    
537
            return ''
538

    
539
    def EvaluatedTable(self, old_code, table_name):
540
        """ return new attribute code """
541
        from AppDocData import AppDocData
542
        from CodeTables import CodeTable
543

    
544
        try:
545
            found = CodeTable.instance(table_name).find_match_exactly(old_code)
546

    
547
            return found if found else ''
548
        except Exception as ex:
549
            from App import App
550
            from AppDocData import MessageType
551

    
552
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
553
                                                          sys.exc_info()[-1].tb_lineno)
554
            App.mainWnd().addMessage.emit(MessageType.Error, message)
555

    
556
    def EvaluatedLineNo(self, prop):
557
        """ return line no attr """
558
        from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
559

    
560
        if self.owner and type(self.owner) is QEngineeringLineNoTextItem:
561
            attrs = self.owner.getAttributes()
562
            for attr, value in attrs.items():
563
                if prop == attr.Attribute:
564
                    return value
565

    
566
        return ''
567

    
568
    def EvaluatedDrawing(self, prop=None):
569
        """ return text item that is in prop"""
570
        from EngineeringTextItem import QEngineeringTextItem
571
        from AppDocData import AppDocData
572

    
573
        if prop is not None:
574
            scene = self.scene()
575
            if scene:
576
                items = [item for item in scene.items() if issubclass(type(item), QEngineeringTextItem) and item.area == prop]
577
                if items:
578
                    return items[0]
579
            return QEngineeringTextItem()
580
        else:
581
            app_doc_data = AppDocData.instance()
582
            drawing_name = app_doc_data.activeDrawing.name
583
            drawing_text_item = QEngineeringTextItem()
584
            drawing_text_item.setPlainText(drawing_name)
585
            return drawing_text_item
586

    
587
    def EvaluatedLabel(self, prop):
588
        """ return label symbol's attribute """
589
        from SymbolSvgItem import SymbolSvgItem
590

    
591
        scene = self.scene()
592
        if not scene:
593
            return ''
594
            
595
        labels = [item for item in scene.items() if issubclass(type(item), SymbolSvgItem) and (item.iType == 19 or item.iType == 29 or item.iType == 30)]
596
        if labels:
597
            labels = [label for label in labels if label.EvaluatedAttribute('OWNERSYMBOL') == self]
598
            if labels and len(labels) == 1:
599
                return labels[0].EvaluatedAttribute(prop)
600
            else:
601
                for label in labels:
602
                    value = label.EvaluatedAttribute(prop)
603
                    if value and value != 'None':
604
                        return value
605

    
606
        return ''
607

    
608
    def EvaluatedAttribute(self, prop, cache=False):
609
        """ return item's attribute """
610
        attrs = self.getAttributes(findOwner=cache)
611
        if attrs:
612
            for key, value in attrs.items():
613
                if key.Attribute == prop:
614
                    return value
615

    
616
        return ''
617

    
618
    @property
619
    def stream_no(self):
620
        matches = [attr for attr in self.attrs if attr.Attribute.upper() == 'STREAM NO']
621
        if matches:
622
            return self.attrs[matches[0]]
623

    
624
        return ''
625

    
626
    @property
627
    def case(self):
628
        matches = [attr for attr in self.attrs if attr.Attribute.upper() == 'CASE']
629
        if matches:
630
            return self.attrs[matches[0]]
631

    
632
        return ''
633

    
634
    '''
635
    @stream_no.setter
636
    def stream_no(self, value):
637
        from AppDocData import AppDocData
638

639
        matches = [attr for attr in self.attrs if attr.Attribute.upper() == 'STREAM NO']
640
        if matches:
641
            self.attrs[matches[0]] = value
642
            """reset attributes for hmb with given stream no"""
643

644
            app_doc_data = AppDocData.instance()
645
            stream_data = app_doc_data.hmbTable.dataOfStreamNo(value)
646
            for attr in self.attrs:
647
                if attr.AttributeType == 'HMB':
648
                    matches = [data for data in stream_data if data.name == attr.Attribute]
649
                    if matches:
650
                        self.attrs[attr] = matches[0].value
651
                    else:
652
                        self.attrs[attr] = ''
653
    '''
654

    
655
    def try_eval(self, item, expression):
656
        try:
657
            return eval(expression)
658
        except Exception as ex:
659
            from App import App
660
            from AppDocData import MessageType
661

    
662
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
663
                                                           sys.exc_info()[-1].tb_lineno) + ' Item UID : ' + str(self.uid)
664
            App.mainWnd().addMessage.emit(MessageType.Error, message)
665
        
666
        return ''
667

    
668
    def getTargetAttributes(self):
669
        """get target attributes"""
670
        from AppDocData import AppDocData
671
        from EngineeringLineItem import QEngineeringLineItem
672
        from EngineeringVendorItem import QEngineeringVendorItem
673
        from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
674
        from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
675
        from QEngineeringTagNoTextItem import QEngineeringTagNoTextItem
676

    
677
        """ get attributes of item from database """
678
        app_doc_data = AppDocData.instance()
679
        if type(self) is QEngineeringLineItem:
680
            symbolAttrs = app_doc_data.getSymbolAttribute('Line')
681
        elif type(self) is QEngineeringVendorItem:
682
            symbolAttrs = app_doc_data.getSymbolAttribute('Package')
683
        elif type(self) is QEngineeringLineNoTextItem:
684
            symbolAttrs = app_doc_data.getSymbolAttribute('Line No')
685
            self.getLineNoAttributes(_attrs)
686
        elif type(self) is QEngineeringTagNoTextItem:
687
            self.getTagNoAttributes(_attrs)
688
            self.attrs = _attrs
689
            return self.attrs
690
        else:
691
            symbolAttrs = app_doc_data.getSymbolAttribute(self.type)
692

    
693
        targetAttrs = []
694
        if not (type(self) is QEngineeringLineItem or type(self) is QEngineeringVendorItem or
695
                type(self) is QEngineeringLineNoTextItem or type(self) is QEngineeringTagNoTextItem):
696
            for attr in symbolAttrs:
697
                if not attr.Target and not type(self) is QEngineeringSpecBreakItem:
698
                    continue
699
                if attr.Target is None or attr.Target == 'ALL' or \
700
                        type(self) is QEngineeringSpecBreakItem or \
701
                            [target for target in attr.Target.split(',') if self.dbUid == int(target)]:
702
                    targetAttrs.append(attr)
703
        else:
704
            targetAttrs = symbolAttrs
705
        
706
        return targetAttrs
707

    
708
    def getAttributes(self, findOwner=False):
709
        """calculate all attributes of item"""
710
        import re
711

    
712
        if findOwner and not hasattr(self, '_skip'):
713
            self._skip = False
714
        elif findOwner and self._skip:
715
            return self.attrs
716
        elif findOwner:
717
            self._skip = True
718
        else:
719
            self._skip = False
720

    
721
        _attrs = {}
722
        try:
723
            from AppDocData import AppDocData
724
            from EngineeringLineItem import QEngineeringLineItem
725
            from EngineeringVendorItem import QEngineeringVendorItem
726
            from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
727
            from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
728
            from QEngineeringTagNoTextItem import QEngineeringTagNoTextItem
729
            from ItemDataExportDialog import QItemDataExportDialog
730

    
731
            """ get attributes of item from database """
732
            app_doc_data = AppDocData.instance()
733
            if type(self) is QEngineeringLineItem:
734
                symbolAttrs = app_doc_data.getSymbolAttribute('Line')
735
            elif type(self) is QEngineeringVendorItem:
736
                symbolAttrs = app_doc_data.getSymbolAttribute('Package')
737
            elif type(self) is QEngineeringLineNoTextItem:
738
                symbolAttrs = app_doc_data.getSymbolAttribute('Line No')
739
                self.getLineNoAttributes(_attrs)
740
            elif type(self) is QEngineeringTagNoTextItem:
741
                self.getTagNoAttributes(_attrs)
742
                self.attrs = _attrs
743
                return self.attrs
744
            else:
745
                symbolAttrs = app_doc_data.getSymbolAttribute(self.type)
746

    
747
            targetAttrs = []
748
            symbol_attr_number = 0
749
            if not (type(self) is QEngineeringLineItem or type(self) is QEngineeringVendorItem or
750
                    type(self) is QEngineeringLineNoTextItem or type(self) is QEngineeringTagNoTextItem):
751
                for attr in symbolAttrs:
752
                    if not attr.Target and not type(self) is QEngineeringSpecBreakItem:
753
                        continue
754
                    if attr.Target is None or attr.Target == 'ALL' or \
755
                            type(self) is QEngineeringSpecBreakItem or \
756
                                [target for target in attr.Target.split(',') if self.dbUid == int(target)]:
757
                        targetAttrs.append(attr)
758
                        if attr.AttributeType == 'Symbol Item' or attr.AttributeType == 'Line Item' or attr.AttributeType == 'EQ Item' or attr.AttributeType == 'Comp Item':
759
                            symbol_attr_number = max(symbol_attr_number, int(attr.AttrAt))
760
            else:
761
                targetAttrs = symbolAttrs
762

    
763
            _texts = self.texts()
764
            _symbols = self.symbols(symbol_attr_number + 1)
765

    
766
            # copy old values
767
            for attr in targetAttrs:
768
                #matches = [_attr for _attr, _ in self.attrs.items() if _attr.UID == attr.UID]
769
                matches = []
770
                for _attr, _ in self.attrs.items():
771
                    if _attr.UID == attr.UID:
772
                        matches = [_attr]
773
                        break
774
                if matches:
775
                    if matches[0].AttributeType == 'Spec' and not self.attrs[matches[0]]:
776
                        continue
777
                    attr.Freeze = matches[0].Freeze  # update freeze value
778
                    attr.AssocItem = matches[0].AssocItem
779
                    _attrs[attr] = self.attrs[matches[0]]  # copy attribute value
780
                else:
781
                    if attr.AttributeType != 'Spec':
782
                        _attrs[attr] = ''
783
            self.attrs = _attrs
784

    
785
            for attr in [_attr for _attr in sorted(self.attrs.keys(), key=lambda param:int(param.Index)) \
786
                            if _attr.AttributeType != 'Combined' and _attr.AttributeType != 'Reference' and _attr.AttributeType != 'HMB']:
787
                # if attr.Freeze: continue    # do not evaluate value if attribute is frozen
788
                if attr.AttributeType == 'Text Item' or attr.AttributeType == 'Valve Oper Code':
789
                    at = int(attr.AttrAt)
790

    
791
                    # Text Item can contain Valve Oper Code
792
                    if attr.AttributeType == 'Text Item':
793
                        items = _texts
794
                    else:
795
                        items = [text for text in _texts if
796
                                 QEngineeringAbstractItem.assoc_type(text) == attr.AttributeType]
797

    
798
                    if not attr.AssocItem and len(items) > at and not attr.Codes.values:
799
                        attr.AssocItem = items[at]
800
                        item = attr.AssocItem
801
                        _attrs[attr] = self.try_eval(item, attr.Expression) if attr.Expression else ''
802
                    elif attr.AssocItem:
803
                        item = attr.AssocItem = self.get_assoc_item(attr.AssocItem)
804
                        _attrs[attr] = self.try_eval(item, attr.Expression) if attr.Expression else ''
805
                    else:
806
                        _attrs[attr] = ''
807
                elif attr.AttributeType == 'Size Text Item' or attr.AttributeType == 'Tag No':
808
                    at = int(attr.AttrAt)
809
                    items = [text for text in _texts if QEngineeringAbstractItem.assoc_type(text) == attr.AttributeType]
810
                    if not attr.AssocItem and len(items) > at:
811
                        attr.AssocItem = items[at]
812
                        item = attr.AssocItem
813
                        _attrs[attr] = self.try_eval(item, attr.Expression) if attr.Expression else ''
814
                    else:
815
                        item = attr.AssocItem = self.get_assoc_item(attr.AssocItem)
816
                        _attrs[attr] = self.try_eval(item, attr.Expression) if attr.Expression and (
817
                                (item and 'item' in attr.Expression) or 'self' in attr.Expression) else ''
818
                elif attr.AttributeType == 'Symbol Item' or attr.AttributeType == 'Line Item' or \
819
                        attr.AttributeType == 'Comp Item' or attr.AttributeType == 'EQ Item':
820
                    at = int(attr.AttrAt)
821
                    if not attr.AssocItem and len(_symbols) > at:
822
                        attr.AssocItem = _symbols[at]
823
                        item = attr.AssocItem
824
                        _attrs[attr] = self.try_eval(item, attr.Expression) if attr.Expression else ''
825
                    elif attr.AssocItem:
826
                        item = attr.AssocItem = self.get_assoc_item(attr.AssocItem)
827
                        _attrs[attr] = self.try_eval(item, attr.Expression) if attr.Expression else ''
828
                    else:
829
                        _attrs[attr] = ''
830
                elif attr.AttributeType == 'String':
831
                    #_attrs[attr] = attr.Expression if attr.Expression and not _attrs[attr] else _attrs[attr]
832
                    _attrs[attr] = self.try_eval(None, attr.Expression) if attr.Expression else _attrs[attr]
833

    
834
            """calculate attribute value for HMB type"""
835
            configs = app_doc_data.getConfigs('Line List', 'Use Stream No')
836
            if configs and int(configs[0].value) == 1:
837
                matches = [_attr for _attr in _attrs if _attr.Attribute.upper() == 'STREAM NO']
838
                matches_case = [_attr for _attr in _attrs if _attr.Attribute.upper() == 'CASE']
839
                hmb_attrs = [_attr for _attr in targetAttrs if _attr.AttributeType == 'HMB']
840
                hmb_datas = app_doc_data.get_hmb_data(None) if hmb_attrs else None
841
                if hmb_datas and hmb_attrs and matches and _attrs[matches[0]] and _attrs[matches[0]] != 'None':
842
                    stream_no = _attrs[matches[0]]
843
                    names = []
844
                    for data in hmb_datas[0].datas[0]:
845
                        if data.name not in names:
846
                            names.append(data.name)
847

    
848
                    matches = [hmb_data for hmb_data in hmb_datas if hmb_data.stream_no == stream_no]
849
                    if matches:
850
                        data = {}
851
                        if matches_case:
852
                            data['Case'] = _attrs[matches_case[0]]
853
                        hmb_data = matches[0]
854
                        data = QItemDataExportDialog.make_hmb_data(data, hmb_data, names)
855
                        for _attr in hmb_attrs:
856
                            if _attr.Attribute in data:
857
                                _attrs[_attr] = data[_attr.Attribute]
858
                            else:
859
                                _attrs[_attr] = ''
860
            """up to here"""
861

    
862
            """calculate attribute value for combined type"""
863
            p = re.compile('{[A-Za-z0-9_ ]+}')
864
            for attr in [_attr for _attr in targetAttrs if _attr.AttributeType == 'Combined']:
865
                value, pos = '', 0
866

    
867
                matches = p.finditer(attr.Expression)
868
                for match in matches:
869
                    attr_name = attr.Expression[(match.start() + 1):(match.end() - 1)]
870
                    values = [value for key, value in _attrs.items() if key.Attribute == attr_name]
871
                    if not values:
872
                        values = [""]
873
                    value += attr.Expression[pos:match.start()] + values[0]
874
                    pos = match.end()
875

    
876
                value += attr.Expression[pos:len(attr.Expression)]
877
                _attrs[attr] = value
878
            """up to here"""
879

    
880
            """calculate attribute value for Reference type"""
881
            for attr in [_attr for _attr in targetAttrs if _attr.AttributeType == 'Reference']:
882
                value, pos = '', 0
883

    
884
                matches = p.finditer(attr.Expression)
885
                for match in matches:
886
                    attr_name = attr.Expression[(match.start() + 1):(match.end() - 1)]
887
                    values = [value for key, value in _attrs.items() if key.Attribute == attr_name]
888
                    if not values:
889
                        values = []
890
                    value += attr.Expression[pos:match.start()] + '\'' + values[0] + '\''
891
                    pos = match.end()
892

    
893
                value += attr.Expression[pos:len(attr.Expression)]
894
                _attrs[attr] = self.try_eval(None, value) if attr.Expression else ''
895
            """up to here"""
896

    
897
            for _attr, _value in _attrs.items():
898
                if _value is None or _value == '':
899
                    _attr.AssocItem = None
900
        except Exception as ex:
901
            from App import App
902
            from AppDocData import MessageType
903

    
904
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
905
                                                           sys.exc_info()[-1].tb_lineno) + ' Item UID : ' + str(self.uid)
906
            App.mainWnd().addMessage.emit(MessageType.Error, message)
907

    
908
        return self.attrs
909

    
910
    def attrib(self, name):
911
        """ return the value of given attribute with name """
912
        matches = [(attr, value) for attr, value in self.getAttributes().items() if attr.Attribute == name]
913
        if matches: return matches[0][1]
914

    
915
        return None
916

    
917
    def set_attrib(self, attrib, value):
918
        """ set attribute with given value """
919
        matches = [attr for attr, _ in self.attrs.items() if attr.UID == attrib.UID]
920
        if len(matches) == 1: self.attrs[matches[0]] = value
921

    
922
    @staticmethod
923
    def assoc_type(item):
924
        """ return association type of given item """
925
        from EngineeringTextItem import QEngineeringTextItem
926
        from SymbolSvgItem import SymbolSvgItem
927
        from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem
928
        from QEngineeringSizeTextItem import QEngineeringSizeTextItem
929
        from QEngineeringTagNoTextItem import QEngineeringTagNoTextItem
930
        from EngineeringLineItem import QEngineeringLineItem
931
        from EngineeringEquipmentItem import QEngineeringEquipmentItem
932
        from EngineeringVendorItem import QEngineeringVendorItem
933

    
934
        _type = None
935

    
936
        if type(item) is QEngineeringSizeTextItem:
937
            _type = 'Size Text Item'
938
        elif type(item) is QEngineeringValveOperCodeTextItem:
939
            _type = 'Valve Oper Code'
940
        elif type(item) is QEngineeringTagNoTextItem:
941
            _type = 'Tag No'
942
        elif type(item) is QEngineeringTextItem or issubclass(type(item), QEngineeringTextItem):
943
            _type = 'Text Item'
944
        elif type(item) is QEngineeringEquipmentItem or type(item) is QEngineeringVendorItem:
945
            _type = 'EQ Item'
946
        elif type(item) is SymbolSvgItem or issubclass(type(item), SymbolSvgItem):
947
            _type = 'Symbol Item'
948
        elif type(item) is QEngineeringLineItem:
949
            _type = 'Line Item'
950
        elif issubclass(type(item), SymbolSvgItem) or type(item) is QEngineeringLineItem:
951
            _type = 'Comp Item'
952

    
953
        return _type
954

    
955
    def clear_attr_and_assoc_item(self, force=False):
956
        """ clear attrs, return true if clear attrs """
957
        if force:
958
            self.attrs.clear()
959
            self._associations.clear()
960
            return True
961
        else:
962
            freeze = False
963
            for key in self.attrs.keys():
964
                if key.Freeze:
965
                    freeze = True
966
                    break
967
            if freeze:
968
                return False
969
            else:
970
                self.attrs.clear()
971
                self._associations.clear()
972
                return True
973

    
974
    def add_assoc_item(self, item, at=None, force=False):
975
        """ add given item to association """
976

    
977
        from EngineeringTextItem import QEngineeringTextItem
978
        from SymbolSvgItem import SymbolSvgItem
979
        from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem
980
        from QEngineeringSizeTextItem import QEngineeringSizeTextItem
981

    
982
        if not force:
983
            for key in self.attrs.keys():
984
                if key.Freeze:
985
                    return False
986

    
987
        _type = QEngineeringAbstractItem.assoc_type(item)
988
        if _type is not None:
989
            if not _type in self._associations:
990
                self._associations[_type] = []
991

    
992
            if item in self._associations[_type]: return True
993

    
994
            if at is None:
995
                self._associations[_type].append(item)
996
            else:
997
                while len(self._associations[_type]) <= at: self._associations[_type].append(None)
998
                # if len(self._associations[_type]) > at and self._associations[_type][at] is not None:
999
                #    self._associations[_type][at].owner = None
1000
                self._associations[_type][at] = item
1001

    
1002
            return True
1003

    
1004
        return False
1005

    
1006
    def remove_assoc_item(self, item):
1007
        """ remove given item from association """
1008
        _type = QEngineeringAbstractItem.assoc_type(item)
1009
        if _type is not None:
1010
            if _type in self._associations and item in self._associations[_type]:
1011
                index = self._associations[_type].index(item)
1012
                self._associations[_type].pop(index)
1013

    
1014
    @property
1015
    def properties(self):
1016
        """ getter of properties """
1017
        import uuid
1018
        from SymbolSvgItem import SymbolSvgItem
1019
        from EngineeringLineItem import QEngineeringLineItem
1020
        from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
1021
        from EngineeringVendorItem import QEngineeringVendorItem
1022

    
1023
        if type(self) is QEngineeringLineNoTextItem:
1024
            for prop, value in self._properties.items():
1025
                if prop.is_selectable and type(value) is uuid.UUID and self.scene():
1026
                    #matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(value)]
1027
                    matches = []
1028
                    for item in self.scene().items():
1029
                        if hasattr(item, 'uid') and str(item.uid) == str(value):
1030
                            matches = [item]
1031
                            break
1032
                    if matches:
1033
                        self._properties[prop] = matches[0]
1034

    
1035
        elif type(self) is QEngineeringLineItem:
1036
            for prop, value in self._properties.items():
1037
                if prop.is_selectable and type(value) is uuid.UUID and self.scene():
1038
                    #matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(value)]
1039
                    matches = []
1040
                    for item in self.scene().items():
1041
                        if hasattr(item, 'uid') and str(item.uid) == str(value):
1042
                            matches = [item]
1043
                            break
1044
                    if matches:
1045
                        self._properties[prop] = matches[0]
1046

    
1047
                if prop.Expression: self._properties[prop] = eval(prop.Expression)
1048

    
1049
        elif issubclass(type(self), SymbolSvgItem):
1050
            for prop, value in self._properties.items():
1051
                try:
1052
                    if prop.is_selectable and type(value) is uuid.UUID and self.scene():
1053
                        #matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(value)]
1054
                        matches = []
1055
                        for item in self.scene().items():
1056
                            if hasattr(item, 'uid') and str(item.uid) == str(value):
1057
                                matches = [item]
1058
                                break
1059
                        if matches:
1060
                            self._properties[prop] = matches[0]
1061

    
1062
                    if prop.Expression:
1063
                        item = self._properties[prop]  # assign item
1064
                        self._properties[prop] = eval(prop.Expression)
1065
                except Exception as ex:
1066
                    from App import App
1067
                    from AppDocData import MessageType
1068
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1069
                                                                   sys.exc_info()[-1].tb_lineno)
1070
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
1071

    
1072
        elif type(self) is QEngineeringVendorItem:
1073
            for prop, value in self._properties.items():
1074
                try:
1075
                    if prop.is_selectable and type(value) is uuid.UUID and self.scene():
1076
                        #matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(value)]
1077
                        matches = []
1078
                        for item in self.scene().items():
1079
                            if hasattr(item, 'uid') and str(item.uid) == str(value):
1080
                                matches = [item]
1081
                                break
1082
                        if matches:
1083
                            self._properties[prop] = matches[0]
1084

    
1085
                    if prop.Expression:
1086
                        item = self._properties[prop]  # assign item
1087
                        self._properties[prop] = eval(prop.Expression)
1088
                except Exception as ex:
1089
                    from App import App
1090
                    from AppDocData import MessageType
1091
                    message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1092
                                                                   sys.exc_info()[-1].tb_lineno)
1093
                    App.mainWnd().addMessage.emit(MessageType.Error, message)
1094

    
1095
        return self._properties
1096

    
1097
    @properties.setter
1098
    def properties(self, value):
1099
        """ setter of properties """
1100
        self._properties = value
1101

    
1102
    def prop(self, name):
1103
        """ return property with given value """
1104
        from SymbolSvgItem import SymbolSvgItem
1105
        from EngineeringLineItem import QEngineeringLineItem
1106
        from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
1107
        from EngineeringVendorItem import QEngineeringVendorItem
1108

    
1109
        if type(self) is QEngineeringLineNoTextItem:
1110
            #matches = [prop for prop, _ in self.properties.items() if prop.Attribute == name]
1111
            matches = []
1112
            for prop, _ in self.properties.items():
1113
                if prop.Attribute == name:
1114
                    matches = [prop]
1115
                    break
1116
            return self.properties[matches[0]] if matches else None
1117

    
1118
        elif type(self) is QEngineeringLineItem:
1119
            #matches = [(prop, value) for prop, value in self.properties.items() if prop.Attribute == name]
1120
            #if matches: return matches[0][1]
1121
            #return None
1122
            matches = []
1123
            for prop, value in self.properties.items():
1124
                if prop.Attribute == name:
1125
                    matches = [value]
1126
                    break
1127
            
1128
            return matches[0] if matches else None
1129

    
1130
        elif issubclass(type(self), SymbolSvgItem):
1131
            #matches = [(prop, value) for prop, value in self.properties.items() if prop.Attribute == name]
1132
            #if matches: return matches[0][1]
1133
            #return None
1134
            matches = []
1135
            for prop, value in self.properties.items():
1136
                if prop.Attribute == name:
1137
                    matches = [value]
1138
                    break
1139
            
1140
            return matches[0] if matches else None
1141

    
1142
        elif type(self) is QEngineeringVendorItem:
1143
            #matches = [(prop, value) for prop, value in self.properties.items() if prop.Attribute == name]
1144
            #if matches: return matches[0][1]
1145
            matches = []
1146
            for prop, value in self.properties.items():
1147
                if prop.Attribute == name:
1148
                    matches = [value]
1149
                    break
1150
            
1151
            return matches[0] if matches else None
1152

    
1153
    def set_property(self, property, value):
1154
        """ set property with given value """
1155
        from SymbolSvgItem import SymbolSvgItem
1156
        from EngineeringLineItem import QEngineeringLineItem
1157
        from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
1158
        from EngineeringVendorItem import QEngineeringVendorItem
1159

    
1160
        if type(self) is QEngineeringLineNoTextItem:
1161
            matches = [prop for prop, _ in self._properties.items() if prop.Attribute == property]
1162
            if matches: self._properties[matches[0]] = value
1163

    
1164
        elif type(self) is QEngineeringLineItem:
1165
            if issubclass(type(value), QEngineeringAbstractItem): self.add_assoc_item(value, 0)
1166
            matches = [prop for prop, _ in self._properties.items() if prop.Attribute == property]
1167
            if matches: self._properties[matches[0]] = value
1168

    
1169
        elif issubclass(type(self), SymbolSvgItem):
1170
            if issubclass(type(value), QEngineeringAbstractItem): self.add_assoc_item(value, 0)
1171
            matches = [prop for prop, _ in self._properties.items() if prop.Attribute == property]
1172
            if matches: self._properties[matches[0]] = value
1173

    
1174
        elif type(self) is QEngineeringVendorItem:
1175
            if issubclass(type(value), QEngineeringAbstractItem):
1176
                self.add_assoc_item(value, 0)
1177
            matches = [prop for prop, _ in self._properties.items() if prop.Attribute == property]
1178
            if matches: self._properties[matches[0]] = value
1179

    
1180
    def center(self):
1181
        return self.sceneBoundingRect().center()
1182
    
1183
    def inch_to_number(self, inch_str):
1184
        from AppDocData import AppDocData
1185
        
1186
        app_doc_data = AppDocData.instance()
1187
        configs = app_doc_data.getConfigs('Size', 'Symbol')
1188
        size_symbols = configs[0].value.replace(' ', '').split(',') if 1 == len(configs) else ['"']
1189

    
1190
        inch_str = str(inch_str)
1191
        for symbol in size_symbols:
1192
            inchs = inch_str.replace(symbol, '')
1193
        inchs = inchs.replace('"', '').split('-')
1194

    
1195
        number = 0
1196
        for inch in inchs:
1197
            if '/' not in inch:
1198
                number += float(inch)
1199
            else:
1200
                fraction = inch.split('/')
1201
                number += float(fraction[0]) / float(fraction[1])
1202

    
1203
        return number
1204

    
1205

    
1206
if __name__ == '__main__':
1207
    import re
1208

    
1209
    p = re.compile('{[A-Za-z0-9]+}')
1210
    value, pos = '', 0
1211

    
1212
    _attrs = {'a': '~', 'b': '!', 'C': '+'}
1213
    expression = 'XXXXXXX{a}-{b}-{C}----'
1214
    matches = p.finditer(expression)
1215
    for match in matches:
1216
        attr_name = expression[(match.start() + 1):(match.end() - 1)]
1217
        value += expression[pos:match.start()] + _attrs[attr_name]
1218
        pos = match.end()
1219

    
1220
    value += expression[pos:len(expression)]
1221
    print(value)
클립보드 이미지 추가 (최대 크기: 500 MB)