프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / Shapes / EngineeringLineNoTextItem.py @ fceaf69c

이력 | 보기 | 이력해설 | 다운로드 (63.3 KB)

1
# coding: utf-8
2
""" This is engineering line no text item module """
3

    
4
import os.path
5
import sys
6
import copy
7

    
8
from EngineeringFromMarkItem import EngineeringFromMarkItem
9
from EngineeringToMarkItem import EngineeringToMarkItem
10

    
11
try:
12
    from PyQt5.QtCore import *
13
    from PyQt5.QtGui import *
14
    from PyQt5.QtWidgets import *
15
except ImportError:
16
    try:
17
        from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QRect
18
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QFont
19
    except ImportError:
20
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
21

    
22
#from UserInputAttribute import UserInputAttribute
23
from OcrResultDialog import QOcrResultDialog
24
from AppDocData import AppDocData
25
from EngineeringTextItem import QEngineeringTextItem
26
from TextInfo import TextInfo
27

    
28
lineColumnList = ['UID', 'LINE_SIZE', 'LINE_SYMBOL', 'LINE_NO', 'LINE_CLASS', 'LINE_ROUTING_FROM', 'LINE_ROUTING_TO',
29
                  'SERVICE_FLUID', 'SERVICE_DENSITY', 'SERVICE_STATE', 'OPERATION_CONDITION_TEMP',
30
                  'OPERATION_CONDITION_PRESS', 'DESIGN_CONDITION_TEMP', 'DESIGN_CONDITION_PRESS', 'TEST_CONDITION_TEMP',
31
                  'TEST_CONDITION_PRESS', 'INSUL_CODE', 'PAINT_CODE', 'NDE_CODE', 'PWHT', 'PNID_NO']
32

    
33

    
34
class QEngineeringLineNoTextItem(QEngineeringTextItem):
35
    '''
36
        @history    18.05.14    Jeongwoo    Add variable self.runs
37
                    humkyung 2018.07.09 add stream no
38
    '''
39

    
40
    def __init__(self, uid=None, parent=None):
41
        from SymbolAttr import SymbolProp
42
        from EngineeringFreezeItem import QEngineeringFreezeItem
43

    
44
        QEngineeringTextItem.__init__(self, uid, parent)
45

    
46
        self._properties = { SymbolProp(None, 'From', 'Comp Item'): None, \
47
                                SymbolProp(None, 'To', 'Comp Item'): None, \
48
                                SymbolProp(None, 'Config', 'String'): None }  # , SymbolProp(None, 'Freeze', 'Boolean'):False}
49
        self._runs = []
50

    
51
        self.lineNoFromToIndicator = []
52
        self.lineNoFromToIndicatorShowFlag = False
53

    
54
        """ create freeze control """
55
        # self.freeze_item = QEngineeringFreezeItem(-QEngineeringFreezeItem.FREEZE_SIZE*0.5, -QEngineeringFreezeItem.FREEZE_SIZE*0.5, QEngineeringFreezeItem.FREEZE_SIZE, QEngineeringFreezeItem.FREEZE_SIZE)
56
        # self.freeze_item.setParentItem(self)
57
        # self.freeze_item.setZValue(self.zValue() + 1)
58
        # self.freeze_item.setPen(Qt.black)
59

    
60
    @property
61
    def Size(self):
62
        """ return line no's size """
63
        attrs = self.getAttributes()
64
        matches = [value for attr, value in attrs.items() if attr.Attribute.upper() == 'NOMINALDIAMETER']
65
        return matches[0] if matches else ''
66

    
67
    def empty(self):
68
        """ return True if run is empty else return False """
69
        return False if self._runs else True
70

    
71
    #def setVisible(self, visible):
72
    #    """ override visible value """
73
    #    super(QEngineeringTextItem, self).setVisible(visible)
74
    #    for run in self.runs:
75
    #        run.visible = visible
76

    
77
    @property
78
    def connected_line(self):
79
        """return connected line"""
80
        if self.conns:
81
            if type(self.conns[0]) is str:
82
                matches = [x for x in self.scene().items() if hasattr(x, 'uid') and str(x.uid) == str(self.conns[0])]
83
                if matches:
84
                    self.conns[0] = matches[0]
85

    
86
            return self.conns[0]
87

    
88
        return None
89

    
90
    '''
91
        @brief  getter of runs
92
        @author humkyung
93
        @date   2018.05.11
94
    '''
95

    
96
    @property
97
    def runs(self):
98
        return self._runs
99

    
100
    '''
101
        @brief  setter of runs
102
        @author humkyung
103
        @date   2018.05.11
104
    '''
105

    
106
    @runs.setter
107
    def runs(self, value):
108
        self._runs = value
109

    
110
    def hoverEnterEvent(self, event):
111
        """ highlight line no text and run's item """
112
        from App import App
113

    
114
        try:
115
            self.hover = True
116
            self.update()
117

    
118
            for run in self.runs:
119
                for item in run.items:
120
                    item.hoverEnterEvent(event, True)
121

    
122
                    # display from / to indicator
123
                    if not self.lineNoFromToIndicatorShowFlag:
124
                        if not self.lineNoFromToIndicator or len(self.lineNoFromToIndicator) < 2:
125
                            if run is self.runs[0] and (item is run.items[0] or item is run.items[-1]):
126
                                _label = EngineeringFromMarkItem(10, color=self._color) \
127
                                    if not self.lineNoFromToIndicator else EngineeringToMarkItem(10, color=self._color)
128
                                _label.setZValue(500)
129
                                self.scene().addItem(_label)
130
                                #_label.setParentItem(self)
131
                                _label.setPos(QPointF(item.origin[0], item.origin[1]))
132
                                self.lineNoFromToIndicator.append(_label)
133
                        elif self.lineNoFromToIndicator:
134
                            if run is self.runs[0] and (item is run.items[0]):
135
                                self.lineNoFromToIndicator[0].setPos(QPointF(item.origin[0], item.origin[1]))
136
                                self.lineNoFromToIndicator[0].setVisible(True)
137
                            elif run is self.runs[0] and (item is run.items[-1]):
138
                                self.lineNoFromToIndicator[1].setPos(QPointF(item.origin[0], item.origin[1]))
139
                                self.lineNoFromToIndicator[1].setVisible(True)
140

    
141
            if not self.runs:
142
                _from = self.prop('From')
143
                _to = self.prop('To')
144
                if _from and _to:
145
                    for item in [_from, _to]:
146
                    # display from / to indicator
147
                        if not self.lineNoFromToIndicator or len(self.lineNoFromToIndicator) < 2:
148
                            _label = EngineeringFromMarkItem(10, color=self._color) \
149
                                if not self.lineNoFromToIndicator else EngineeringToMarkItem(10, color=self._color)
150
                            _label.setZValue(500)
151
                            self.scene().addItem(_label)
152
                            _label.setPos(QPointF(item.origin[0], item.origin[1]))
153
                            self.lineNoFromToIndicator.append(_label)
154
                        elif self.lineNoFromToIndicator:
155
                            if item is _from:
156
                                self.lineNoFromToIndicator[0].setPos(QPointF(item.origin[0], item.origin[1]))
157
                                self.lineNoFromToIndicator[0].setVisible(True)
158
                            elif item is _to:
159
                                self.lineNoFromToIndicator[1].setPos(QPointF(item.origin[0], item.origin[1]))
160
                                self.lineNoFromToIndicator[1].setVisible(True)
161

    
162
        except Exception as ex:
163
            from App import App
164
            from AppDocData import MessageType
165

    
166
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
167
                                                           sys.exc_info()[-1].tb_lineno)
168
            App.mainWnd().addMessage.emit(MessageType.Error, message)
169

    
170
    def contextMenuEvent(self, event):
171
        items = self.scene().selectedItems()
172
        menu = QMenu()
173
        if len(items) == 1 and self in items:
174
            '''
175
            explodeAction = QAction('Explode', None)
176
            explodeAction.triggered.connect(self.contextExplode)
177
            menu.addAction(explodeAction)
178

179
            explodeKeepAction = QAction('Explode(keep from, to)', None)
180
            explodeKeepAction.triggered.connect(self.contextExplodeKeep)
181
            menu.addAction(explodeKeepAction)
182
            '''
183

    
184
            explodeAction = QAction('Explode', None)
185
            explodeAction.triggered.connect(self.contextExplode)
186
            menu.addAction(explodeAction)
187

    
188
            explodeKeepAction = QAction('Explode(keep from, to)', None)
189
            explodeKeepAction.triggered.connect(self.contextExplodeKeep)
190
            menu.addAction(explodeKeepAction)
191

    
192
            freezeAction = QAction("Freeze Attributes of All Child Items" , None)
193
            freezeAction.triggered.connect(lambda: self.freeze_attriute(True))
194
            menu.addAction(freezeAction)
195

    
196
            unfreezeAction = QAction("Un-Freeze Attributes of All Child Items" , None)
197
            unfreezeAction.triggered.connect(lambda: self.freeze_attriute(False))
198
            menu.addAction(unfreezeAction)
199

    
200
            fromAction = QAction('Set From(S)', None)
201
            fromAction.triggered.connect(self.contextFrom)
202
            menu.addAction(fromAction)
203

    
204
            toAction = QAction('Set To(D)', None)
205
            toAction.triggered.connect(self.contextTo)
206
            menu.addAction(toAction)
207

    
208
            showAction = QAction('Show From, To(H)', None) if not self.lineNoFromToIndicatorShowFlag else QAction('Hide From, To(H)', None)
209
            showAction.triggered.connect(self.contextShow)
210
            menu.addAction(showAction)
211

    
212
            allAction = QAction('Select All in View(A)', None)
213
            allAction.triggered.connect(self.contextSelectAll)
214
            menu.addAction(allAction)
215

    
216
            searchAction = QAction('Search All Duplicate Line No', None)
217
            searchAction.triggered.connect(self.contextSearch)
218
            menu.addAction(searchAction)
219

    
220
            highlightAction = QAction('Highlight', None)
221
            highlightAction.triggered.connect(lambda: self.contextHighlight(self))
222
            menu.addAction(highlightAction)
223

    
224
            actions = []
225
            for index in range(len(self.runs)):
226
                actions.append(QAction('Highlight Run ' + str(index + 1), None))
227

    
228
            binding = [lambda index=index: actions[index].triggered.connect(lambda: self.contextHighlight(self.runs[index])) for index in range(len(self.runs))]
229
    
230
            for index in range(len(actions)):
231
                binding[index]()
232
                menu.addAction(actions[index])
233

    
234
            editAction = QAction('Edit(Return)', None)
235
            editAction.triggered.connect(self.contextEdit)
236
            menu.addAction(editAction)
237

    
238
            rotateAction = QAction('Rotate(R)', None)
239
            rotateAction.triggered.connect(self.contextRotate)
240
            menu.addAction(rotateAction)
241

    
242
            deleteAction = QAction('Delete(E)', None)
243
            deleteAction.triggered.connect(self.contextDelete)
244
            menu.addAction(deleteAction)
245
        else:
246
            alignAction = QAction('Resize Selected Texts with This ', None)
247
            alignAction.triggered.connect(self.contextResizeText)
248
            menu.addAction(alignAction)
249

    
250
        menu.exec_(event.screenPos())
251

    
252
    def contextResizeText(self):
253
        textItems = [item for item in self.scene().selectedItems() if item is not self and type(item) is QEngineeringLineNoTextItem]
254
        allowed_error = 0.01
255

    
256
        for text in textItems:
257
            if abs(self.angle - text.angle) < allowed_error:
258
                dx = round(self.size[0] - text.size[0])
259
                dy = round(self.size[1] - text.size[1])
260
            else:
261
                dx = round(self.size[1] - text.size[0])
262
                dy = round(self.size[0] - text.size[1])
263

    
264
            text.size[1] = text.size[1] + dy
265
            if abs(text.angle - 1.57) < allowed_error or abs(text.angle - 3.14) < allowed_error:
266
                text.loc[1] = text.loc[1] - dy
267

    
268
            text.size[0] = text.size[0] + dx
269
            if abs(text.angle - 4.71) < allowed_error or abs(text.angle - 4.71) < allowed_error or abs(text.angle - 3.14) < allowed_error:
270
                text.loc[0] = text.loc[0] - dx
271

    
272
            text.update_font()
273
            text.update()
274

    
275
    def contextSearch(self):
276
        from App import App
277
        from TextItemEditDialog import QTextItemEditDialog
278

    
279
        dlgTextItemEdit = QTextItemEditDialog(App.mainWnd(), 'Line No')
280
        dlgTextItemEdit.show()
281
        dlgTextItemEdit.exec_()
282

    
283
    def contextSelectAll(self):
284
        from App import App
285
        
286
        rect = App.mainWnd().graphicsView.viewport().rect()
287
        view_rect = App.mainWnd().graphicsView.mapToScene(rect).boundingRect()
288
        lineNos = [item for item in self.scene().items() if type(item) is QEngineeringLineNoTextItem and view_rect.contains(item.sceneBoundingRect().center())]
289
        for lineNo in lineNos:
290
            lineNo.setSelected(True)
291

    
292
    def freeze_attriute(self, freeze):
293
        for run in self.runs:
294
            for item in run.items:
295
                item.freeze_attriute(freeze)
296

    
297
    def contextShow(self):
298
        self.lineNoFromToIndicatorShowFlag = not self.lineNoFromToIndicatorShowFlag
299
        if self.lineNoFromToIndicatorShowFlag:
300
            if self.runs and self.runs[0].items:
301
                for item in [self.runs[0].items[0], self.runs[0].items[-1]]:
302
                    # display from / to indicator
303
                    if not self.lineNoFromToIndicator or len(self.lineNoFromToIndicator) < 2:
304
                        _label = EngineeringFromMarkItem(10, color=self._color) \
305
                            if not self.lineNoFromToIndicator else EngineeringToMarkItem(10, color=self._color)
306
                        _label.setZValue(500)
307
                        self.scene().addItem(_label)
308
                        _label.setPos(QPointF(item.origin[0], item.origin[1]))
309
                        self.lineNoFromToIndicator.append(_label)
310
                    elif self.lineNoFromToIndicator:
311
                        if item is self.runs[0].items[0]:
312
                            self.lineNoFromToIndicator[0].setPos(QPointF(item.origin[0], item.origin[1]))
313
                            self.lineNoFromToIndicator[0].setVisible(True)
314
                        elif item is self.runs[0].items[-1]:
315
                            self.lineNoFromToIndicator[1].setPos(QPointF(item.origin[0], item.origin[1]))
316
                            self.lineNoFromToIndicator[1].setVisible(True)
317
            elif not self.runs:
318
                _from = self.prop('From')
319
                _to = self.prop('To')
320
                if _from and _to:
321
                    for item in [_from, _to]:
322
                    # display from / to indicator
323
                        if not self.lineNoFromToIndicator or len(self.lineNoFromToIndicator) < 2:
324
                            _label = EngineeringFromMarkItem(10, color=self._color) \
325
                                if not self.lineNoFromToIndicator else EngineeringToMarkItem(10, color=self._color)
326
                            _label.setZValue(500)
327
                            self.scene().addItem(_label)
328
                            _label.setPos(QPointF(item.origin[0], item.origin[1]))
329
                            self.lineNoFromToIndicator.append(_label)
330
                        elif self.lineNoFromToIndicator:
331
                            if item is _from:
332
                                self.lineNoFromToIndicator[0].setPos(QPointF(item.origin[0], item.origin[1]))
333
                                self.lineNoFromToIndicator[0].setVisible(True)
334
                            elif item is _to:
335
                                self.lineNoFromToIndicator[1].setPos(QPointF(item.origin[0], item.origin[1]))
336
                                self.lineNoFromToIndicator[1].setVisible(True)
337
        else:
338
            if self.lineNoFromToIndicator:
339
                for _label in self.lineNoFromToIndicator:
340
                    _label.setVisible(False)            
341

    
342
    def contextFrom(self):
343
        from App import App
344
        import SelectAttributeCommand
345
        _from = None
346
        for prop, value in self.properties.items():
347
            if prop.Attribute == 'From':
348
                _from = prop
349
                break
350
        cmd = SelectAttributeCommand.SelectAttributeCommand(self, _from, App.mainWnd().graphicsView)
351
        cmd.onSuccess.connect(App.mainWnd().resultPropertyTableWidget.onSuccessSelectAttribute)
352
        App.mainWnd().graphicsView.command = cmd
353

    
354
    def contextTo(self):
355
        from App import App
356
        import SelectAttributeCommand
357
        _to = None
358
        for prop, value in self.properties.items():
359
            if prop.Attribute == 'To':
360
                _to = prop
361
                break
362
        cmd = SelectAttributeCommand.SelectAttributeCommand(self, _to, App.mainWnd().graphicsView)
363
        cmd.onSuccess.connect(App.mainWnd().resultPropertyTableWidget.onSuccessSelectAttribute)
364
        App.mainWnd().graphicsView.command = cmd
365

    
366
    def contextHighlight(self, item):
367
        from App import App
368
        from HighlightCommand import HighlightCommand
369
        HighlightCommand(App.mainWnd().graphicsView).execute(item)
370

    
371
    def contextExplode(self):
372
        from App import App
373
        App.mainWnd().itemTreeWidget.explode_line_no_from_context(self)
374

    
375
    def contextExplodeKeep(self):
376
        from App import App
377
        App.mainWnd().itemTreeWidget.explode_line_no_from_context(self, True)
378

    
379
    def contextReverse(self):
380
        self.reverse()
381

    
382
    def contextDelete(self):
383
        event = QKeyEvent(QEvent.KeyPress, Qt.Key_Delete, Qt.NoModifier)
384
        self.scene().keyPressEvent(event)
385

    
386
    def contextEdit(self):
387
        event = QKeyEvent(QEvent.KeyPress, Qt.Key_Return, Qt.NoModifier)
388
        self.keyPressEvent(event)
389

    
390
    def contextRotate(self):
391
        event = QKeyEvent(QEvent.KeyPress, Qt.Key_R, Qt.NoModifier)
392
        self.keyPressEvent(event)
393

    
394
    def hoverLeaveEvent(self, event):
395
        """ unhighlight line no text and run's item """
396
        try:
397
            self.hover = False
398
            self.update()
399

    
400
            for run in self.runs:
401
                for item in run.items:
402
                    item.hoverLeaveEvent(event, True)
403

    
404
            if not self.lineNoFromToIndicatorShowFlag:
405
                if self.lineNoFromToIndicator:
406
                    for _label in self.lineNoFromToIndicator:
407
                        _label.setVisible(False)
408
        except Exception as ex:
409
            from App import App
410
            from AppDocData import MessageType
411

    
412
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
413
                                                           sys.exc_info()[-1].tb_lineno)
414
            App.mainWnd().addMessage.emit(MessageType.Error, message)
415

    
416

    
417
    def keyPressEvent(self, event):
418
        """ reverse line routine when user press 'C' key """
419
        if event.key() == Qt.Key_C:
420
            self.reverse()
421
        elif event.key() == Qt.Key_S:
422
            self.contextFrom()
423
        elif event.key() == Qt.Key_D:
424
            self.contextTo()
425
        elif event.key() == Qt.Key_H:
426
            self.contextShow()
427
        elif event.key() == Qt.Key_A:
428
            self.contextSelectAll()
429

    
430
        QEngineeringTextItem.keyPressEvent(self, event)
431

    
432
    def update_flow_mark(self, position, minLength):
433
        """ update line flow mark """
434
        import math
435
        from EngineeringLineItem import QEngineeringLineItem
436

    
437
        allowed_error_radian = 0.09
438

    
439
        try:
440
            for run in self.runs:
441
                pre = None
442
                preRadian = None
443
                for item in run.items:
444
                    if pre is None and type(item) is QEngineeringLineItem and item.is_piping(True) and item.length() > minLength:
445
                        pre = item
446
                        start = item.line().p1()
447
                        end = item.line().p2()
448
                        _dir = [(end.x() - start.x()) / item.length(), (end.y() - start.y()) / item.length()]
449
                        radian = math.atan2(_dir[1], _dir[0]) - math.pi / 2
450
                        preRadian = radian if radian >= 0 else radian + 2 * math.pi
451
                        preRadian = abs(preRadian - math.pi)
452

    
453
                    elif pre and type(pre) is QEngineeringLineItem and type(item) is QEngineeringLineItem and item.is_piping(True):
454
                        start = item.line().p1()
455
                        end = item.line().p2()
456
                        _dir = [(end.x() - start.x()) / item.length(), (end.y() - start.y()) / item.length()]
457
                        radian = math.atan2(_dir[1], _dir[0]) - math.pi / 2
458
                        currRadian = radian if radian >= 0 else radian + 2 * math.pi
459
                        currRadian = abs(currRadian - math.pi)
460
                        if abs(currRadian - preRadian) > allowed_error_radian:
461
                            # insert flow mark at pre line
462
                            if pre.length() > minLength:
463
                                # if str(pre.uid) == '62edfbe5-29fd-49af-840b-6dce051e04d1':
464
                                # print(math.atan2(preDir[0], preDir[1]) - math.pi / 2)
465
                                # print(currRadian)
466
                                # print(preRadian)
467
                                pre.flowMark = position
468
                                pre.update_arrow()
469

    
470
                            pre = item
471
                            preRadian = currRadian
472

    
473
                if pre and type(item) is QEngineeringLineItem and item.is_piping(True) and item.length() > minLength:
474
                    pre.flowMark = position
475
                    pre.update_arrow()
476

    
477
        except Exception as ex:
478
            from App import App
479
            from AppDocData import MessageType
480

    
481
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
482
                                                           sys.exc_info()[-1].tb_lineno)
483
            App.mainWnd().addMessage.emit(MessageType.Error, message)
484

    
485
    """
486
    def paint(self, painter, options=None, widget=None):
487
        QEngineeringTextItem.paint(self, painter, options, widget)
488
        if self.freeze_item is None:
489
            from EngineeringFreezeItem import QEngineeringFreezeItem
490

491
            self.freeze_item = QEngineeringFreezeItem(0, 0, QEngineeringFreezeItem.FREEZE_SIZE, QEngineeringFreezeItem.FREEZE_SIZE)
492
            self.freeze_item.setParentItem(self)
493
            self.freeze_item.setZValue(self.zValue() + 1)
494
            self.freeze_item.setPen(Qt.black)
495
    """
496

    
497
    def reverse(self):
498
        """ reverse line routine """
499

    
500
        if self.runs:
501
            self.runs[0].reverse()
502
            _from = self.prop('From')
503
            _to = self.prop('To')
504
            self.set_property('From', _to)
505
            self.set_property('To', _from)
506

    
507
    def getLongestTwoPoints(self, pts):
508
        import math
509
        res = [None, None]
510

    
511
        maxDistance = None
512
        for i in range(len(pts)):
513
            for j in range(i + 1, len(pts)):
514
                dx = pts[i][0] - pts[j][0]
515
                dy = pts[i][1] - pts[j][1]
516
                dist = math.sqrt(dx * dx + dy * dy)
517
                if (maxDistance is None) or (maxDistance < dist):
518
                    maxDistance = dist
519
                    res[0] = pts[i]
520
                    res[1] = pts[j]
521

    
522
        return res
523

    
524
    '''
525
        @brief      set attribute
526
        @author     humkyung
527
        @date       2018.07.20
528
    '''
529

    
530
    def set_attrib(self, attrib, value):
531
        matches = [attr for attr in self.attrs if attr.UID == attrib.UID]
532
        if len(matches) == 1:
533
            self.attrs[matches[0]] = value
534
        else:
535
            self.attrs[attrib] = value
536

    
537
    def removeSelfAttr(self, attributeName):
538
        pass
539

    
540
    '''
541
        @brief      get attribute
542
        @author     kyouho
543
        @date       2018.09.06
544
    '''
545
    def getLineNoAttributes(self, _attrs=None):
546
        from SymbolAttr import SymbolAttr
547
        from Configs import LineNoConfig
548
        import csv
549

    
550
        if _attrs is None:
551
            _attrs = {}
552

    
553
        try:
554
            docData = AppDocData.instance()
555

    
556
            line_no_configs = LineNoConfig.instance()
557
            config = None
558
            if line_no_configs:
559
                for line_no_config in line_no_configs:
560
                    item = line_no_config.parse(self.text())
561
                    if item[0]:
562
                        config = line_no_config
563
                        break
564
            else:
565
                item = (False,)
566

    
567
            if item[0]:
568
                # Line No 부분
569
                attr = SymbolAttr()
570
                attr.Attribute = 'LINE NO'
571
                attr.DisplayAttribute = 'Line No'
572
                attr.AttributeType = 'String'
573
                attr.IsProp = 5
574
                attr.Index = -1
575
                _attrs[attr] = self.text()
576

    
577
                result = item[1]
578
                configs = list(csv.reader([config.value], delimiter=self.delimiter, escapechar='^'))[0]
579
                props = docData.getLineProperties()
580
                for prop in props:
581
                    if prop.UID in configs:
582
                        for i in range(len(configs)):
583
                            if prop.UID == configs[i]:
584
                                _attrs[prop] = result[i]
585
                                break
586
                    else:
587
                        matches = [attr for attr in self.attrs if attr.UID == prop.UID]
588
                        if len(matches) == 1:
589
                            _attrs[matches[0]] = self.attrs[matches[0]]
590
                        # else:
591
                        #    _attrs[prop] = ''
592
        except Exception as ex:
593
            from App import App
594
            from AppDocData import MessageType
595

    
596
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
597
                                                           sys.exc_info()[-1].tb_lineno)
598
            App.mainWnd().addMessage.emit(MessageType.Error, message)
599

    
600
        return _attrs
601

    
602
    @staticmethod
603
    def from_database(component):
604
        """ get line no item from database """
605
        import uuid
606
        from AppDocData import AppDocData
607
        from TextItemFactory import TextItemFactory
608
        from SymbolAttr import SymbolAttr
609

    
610
        item = None
611

    
612
        try:
613
            x = float(component['X'])
614
            y = float(component['Y'])
615
            width = float(component['Width']) if component['Width'] is not None else 0
616
            height = float(component['Height']) if component['Height'] is not None else 0
617
            angle = float(component['Rotation']) if component['Rotation'] is not None else 0
618
            text = component['Value']
619

    
620
            configs = AppDocData.instance().getConfigs('Data', 'Grid')
621
            grid = int(configs[0].value) if 1 == len(configs) else -1
622
            if grid == 1:
623
                x = round(x)
624
                y = round(y)
625
                width = round(width)
626
                height = round(height)
627
                
628
            textInfo = TextInfo(text, x, y, width, height, angle)
629
            connline = component['Connected'] if component['Connected'] is not None else None
630

    
631
            item = TextItemFactory.instance().createTextItem(textInfo)
632
            if item is not None:
633
                item.setVisible(False)
634
                for key in item._properties.keys():
635
                    if key.Attribute != 'Config':
636
                        item._properties[key] = key.parse_value(component[key.Attribute])
637

    
638
                app_doc_data = AppDocData.instance()
639

    
640
                # get associations 
641
                associations = app_doc_data.get_component_associations(component['UID'])
642
                if associations:
643
                    for assoc in associations:
644
                        _attrType = assoc['Type']
645
                        if not _attrType in item._associations:
646
                            item._associations[_attrType] = []
647
                        item._associations[_attrType].append(
648
                            uuid.UUID(assoc['Association']) if assoc['Association'] != 'None' else None)
649
                # up to here
650

    
651
                '''
652
                # get associations 
653
                associations = app_doc_data.get_component_associations(component['UID'])
654
                if associations:
655
                    for assoc in associations:
656
                        _attrType = assoc['Type']
657
                        if not _attrType in item._associations:
658
                            item._associations[_attrType] = []
659
                        item._associations[_attrType].append(
660
                            uuid.UUID(assoc['Association']) if assoc['Association'] != 'None' else None)
661
                # up to here
662
                '''
663

    
664
                attrs = app_doc_data.get_component_attributes(component['UID'])
665
                for _attr in attrs:
666
                    attr = SymbolAttr.from_record(_attr)
667
                    item.attrs[attr] = _attr['Value']
668

    
669
                item.uid = uuid.UUID(component['UID'])
670
                item.loc = [x, y]
671
                item.size = [width, height]
672
                item.angle = angle
673
                item.setToolTip('<b>{}</b><br>LINE NO={}'.format(str(item.uid), text))
674

    
675
                """ apply freeze value """
676
                # item.freeze_item.update_freeze(item.prop('Freeze'))
677

    
678
                if connline is not None:
679
                    item.conns.append(connline)
680
        except Exception as ex:
681
            from App import App
682
            from AppDocData import MessageType
683

    
684
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
685
                                                           sys.exc_info()[-1].tb_lineno)
686
            App.mainWnd().addMessage.emit(MessageType.Error, message)
687
            return None
688

    
689
        return item
690

    
691
    @staticmethod
692
    def fromXml(node):
693
        """ generate EngineeringLineNoTextItem from xml node """
694
        import uuid
695
        from TextItemFactory import TextItemFactory
696
        from SymbolAttr import SymbolAttr
697

    
698
        item = None
699

    
700
        try:
701
            location = node.find('LOCATION').text if node.find('LOCATION') is not None else '0,0'
702
            x = float(location.split(',')[0])
703
            y = float(location.split(',')[1])
704
            width = float(node.find('WIDTH').text) if node.find('WIDTH') is not None else 0
705
            height = float(node.find('HEIGHT').text) if node.find('HEIGHT') is not None else 0
706
            angle = float(node.find('ANGLE').text) if node.find('ANGLE') is not None else 0
707
            text = node.find('TEXT').text
708

    
709
            configs = AppDocData.instance().getConfigs('Data', 'Grid')
710
            grid = int(configs[0].value) if 1 == len(configs) else -1
711
            if grid == 1:
712
                x = round(x)
713
                y = round(y)
714
                width = round(width)
715
                height = round(height)
716

    
717
            textInfo = TextInfo(text, x, y, width, height, angle)
718
            connline = node.find('CONNLINE').text if node.find('CONNLINE') is not None else None
719

    
720
            configs = AppDocData.instance().getConfigs('Data', 'Grid')
721
            grid = int(configs[0].value) if 1 == len(configs) else -1
722
            if grid == 1:
723
                x = round(x)
724
                y = round(y)
725
                width = round(width)
726
                height = round(height)
727

    
728
            matches = [prop_node for prop_node in node.iter('PROPERTY') if prop_node.attrib['Attribute'] == 'Config']
729
            if matches:
730
                item = TextItemFactory.instance().createTextItem(textInfo, matches[0].text)
731
            else:
732
                item = TextItemFactory.instance().createTextItem(textInfo)
733

    
734
            if item is not None:
735
                item.setVisible(False)
736
                for prop_node in node.iter('PROPERTY'):
737
                    matches = [prop for prop in item._properties.keys() if
738
                               prop.Attribute == prop_node.attrib['Attribute'] and prop.Attribute != 'Config']
739
                    if matches:
740
                        item._properties[matches[0]] = matches[0].parse_value(prop_node.text)
741

    
742
                for attr_node in node.iterfind('ATTRIBUTE'):
743
                    attr = SymbolAttr.fromXml(attr_node)
744
                    item.attrs[attr] = attr_node.text
745

    
746
                item.uid = uuid.UUID(node.find('UID').text)
747
                item.loc = [x, y]
748
                item.size = [width, height]
749
                item.angle = angle
750
                item.setToolTip('<b>{}</b><br>LINE NO={}'.format(str(item.uid), text))
751

    
752
                # get associations 
753
                attributeValue = node.find('ASSOCIATIONS')
754
                if attributeValue is not None:
755
                    for assoc in attributeValue.iter('ASSOCIATION'):
756
                        _attrType = assoc.attrib['TYPE']
757
                        if not _attrType in item._associations:
758
                            item._associations[_attrType] = []
759
                        item._associations[_attrType].append(uuid.UUID(assoc.text) if assoc.text != 'None' else None)
760
                # up to here
761

    
762
                """ apply freeze value """
763
                # item.freeze_item.update_freeze(item.prop('Freeze'))
764

    
765
                if connline is not None:
766
                    item.conns.append(connline)
767
        except Exception as ex:
768
            from App import App
769
            from AppDocData import MessageType
770

    
771
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
772
                                                           sys.exc_info()[-1].tb_lineno)
773
            App.mainWnd().addMessage.emit(MessageType.Error, message)
774
            return None
775

    
776
        return item
777

    
778
    '''
779
        @brief      generate xml code
780
        @author     humkyung
781
        @date       2018.04.23
782
        @history    humkyung 2018.05.02 write symbol's attribute
783
                    humkyung 2018.05.16 write run information to xml
784
    '''
785

    
786
    def toXml(self):
787
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree
788
        from EngineeringLineItem import QEngineeringLineItem
789
        from SymbolSvgItem import SymbolSvgItem
790

    
791
        try:
792
            #docData = AppDocData.instance()
793
            #configs = docData.getConfigs('Line No', 'Delimiter')
794
            #delimiter = configs[0].value if 1 == len(configs) else '-'
795
            #lineNoconfigs = docData.getConfigs('Line No', 'Configuration')
796

    
797
            node = Element('LINE_NO')
798
            uidNode = Element('UID')
799
            uidNode.text = str(self.uid)
800
            node.append(uidNode)
801

    
802
            textNode = Element('TEXT')
803
            textNode.text = self.text()
804
            node.append(textNode)
805

    
806
            locNode = Element('LOCATION')
807
            locNode.text = '{},{}'.format(self.loc[0], self.loc[1])
808
            node.append(locNode)
809

    
810
            widthNode = Element('WIDTH')
811
            widthNode.text = str(self.size[0])
812
            node.append(widthNode)
813

    
814
            heightNode = Element('HEIGHT')
815
            heightNode.text = str(self.size[1])
816
            node.append(heightNode)
817

    
818
            angleNode = Element('ANGLE')
819
            angleNode.text = str(self.angle)
820
            node.append(angleNode)
821

    
822
            areaNode = Element('AREA')
823
            areaNode.text = self.area
824
            node.append(areaNode)
825

    
826
            for run in self.runs:
827
                if run and run.items:
828
                    node.append(run.toXml())
829
            
830
            attributeValueNode = Element('ASSOCIATIONS')
831
            for key, value in self._associations.items():
832
                for assoc in value:
833
                    assoc_node = Element('ASSOCIATION')
834
                    assoc_node.attrib['TYPE'] = str(key)
835
                    assoc_node.text = str(assoc)
836
                    attributeValueNode.append(assoc_node)
837
            node.append(attributeValueNode)
838

    
839
            properties_node = Element('PROPERTIES')
840
            for prop, value in self.properties.items():
841
                prop_node = prop.toXml()
842
                prop_node.text = str(value) if value else ''
843
                properties_node.append(prop_node)
844
            node.append(properties_node)
845

    
846
            _attrs = self.getAttributes()
847
            for key in _attrs.keys():
848
                if key.UID is not None:
849
                    attrNode = key.toXml()
850
                    attrNode.text = str(_attrs[key])
851
                    node.append(attrNode)
852

    
853
            if self.conns:
854
                connNode = Element('CONNLINE')
855
                connNode.text = str(self.conns[0].uid) if hasattr(self.conns[0], 'uid') else str(self.conns[0])
856
                node.append(connNode)
857

    
858
            sceneNode = Element('SCENE')
859
            sceneNode.text = str(self.sceneBoundingRect()).replace('PyQt5.QtCore.QRectF(', '').replace(' ', '').replace(
860
                ')', '') if self.scene() else '{},{},{},{}'.format(self.loc[0], self.loc[1], self.size[0], self.size[1])
861
            node.append(sceneNode)
862

    
863
        except Exception as ex:
864
            from App import App
865
            from AppDocData import MessageType
866

    
867
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
868
                                                           sys.exc_info()[-1].tb_lineno)
869
            App.mainWnd().addMessage.emit(MessageType.Error, message)
870

    
871
            return None
872

    
873
        return node
874

    
875
    def to_svg(self, parent) -> list:
876
        """convert line no item to svg"""
877
        import re
878
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree
879
        from App import App
880

    
881
        res = []
882
        try:
883
            app_doc_data = AppDocData.instance()
884
            prj = app_doc_data.getCurrentProject()
885

    
886
            node = Element('g')
887
            node.attrib['id'] = str(self.uid)
888
            node.attrib['class'] = 'Pipe'
889
            node.attrib['data-tag-name'] = self.toPlainText()
890
            node.attrib['font-family'] = self.font().family()
891
            node.attrib['font-size'] = str(self.boundingRect().height())  # str(self.font().pointSizeF())
892
            node.attrib['font-weight'] = str(self.font().weight())
893

    
894
            except_pattern = re.compile('[^a-zA-Z0-9-_]')
895
            for attr, value in self.getAttributes().items():
896
                node.attrib[re.sub(except_pattern, '_', attr.Attribute)] = value if value else ''
897
            trans = self.sceneTransform()
898
            node.attrib['transform'] = f"matrix(" \
899
                                       f"{trans.m11()},{trans.m12()}," \
900
                                       f"{trans.m21()},{trans.m22()}," \
901
                                       f"{trans.m31()},{trans.m32()}" \
902
                                       f")"
903

    
904
            text = Element('text')
905
            text.text = self.toPlainText()
906
            text.attrib['textLength'] = str(self.boundingRect().width())
907
            text.attrib['lengthAdjust'] = 'spacingAndGlyphs'
908
            text.attrib['alignment-baseline'] = 'hanging'  # align left-top corner
909
            node.append(text)
910

    
911
            connected_line = self.connected_line
912
            if connected_line:
913
                conn_node = connected_line.to_svg(self)
914
                if conn_node:
915
                    node.extend(conn_node)
916

    
917
            res.append(node)
918
        except Exception as ex:
919
            from App import App
920
            from AppDocData import MessageType
921
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
922
                                                           sys.exc_info()[-1].tb_lineno)
923
            App.mainWnd().addMessage.emit(MessageType.Error, message)
924

    
925
        return res
926

    
927
    def end_break(self):
928
        '''
929
            @brief  end break check
930
            @author euisung
931
            @date   2019.05.07
932
            @history    2019.05.19  euisung    can cover at both end that contact other line's middle
933
                        2019.05.19  euisung    no more used integrated with linetracer
934
        '''
935
        from EngineeringLineItem import QEngineeringLineItem
936
        from SymbolSvgItem import SymbolSvgItem
937
        from AppDocData import AppDocData
938
        end_breaks = []
939

    
940
        try:
941
            docdata = AppDocData.instance()
942

    
943
            line_from = self.prop('From')
944
            line_to = self.prop('To')
945

    
946
            end_break_names = docdata.getSymbolListByType('type', 'End Break')
947
            if len(end_break_names) is 0:
948
                return end_breaks
949

    
950
            svgFileName = end_break_names[0].sName
951
            symbol = AppDocData.instance().getSymbolByQuery('name', svgFileName)
952
            svgFilePath = os.path.join(AppDocData.instance().getCurrentProject().getSvgFilePath(), symbol.getType(),
953
                                       svgFileName + '.svg')
954

    
955
            for line_end in [line_from, line_to]:
956
                for connector in line_end.connectors:
957
                    if connector.connectedItem is not None and connector.connectedItem.owner is not self:
958
                        end_break = SymbolSvgItem.createItem(symbol.getType(), None, svgFilePath)
959
                        pt = [connector.center()[0] - float(symbol.getOriginalPoint().split(',')[0]),
960
                              connector.center()[1] - float(symbol.getOriginalPoint().split(',')[1])]
961
                        origin = [0, 0]
962
                        if 2 == len(symbol.getOriginalPoint().split(',')):
963
                            tokens = symbol.getOriginalPoint().split(',')
964
                            origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
965
                        end_break.buildItem(svgFileName, symbol.getType(), 5.7, pt,
966
                                            [end_break.boundingRect().width(), end_break.boundingRect().height()],
967
                                            origin, [], symbol.getBaseSymbol(), symbol.getAdditionalSymbol(),
968
                                            symbol.getHasInstrumentLabel())
969

    
970
                        end_break.set_property('Connected Item', connector.connectedItem)
971
                        end_break.setToolTip('owner : ' + str(line_end))
972
                        end_break.area = 'Drawing'
973
                        end_break.owner = line_end
974
                        end_breaks.append(end_break)
975
        except Exception as ex:
976
            from App import App
977
            from AppDocData import MessageType
978

    
979
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
980
                                                           sys.exc_info()[-1].tb_lineno)
981
            App.mainWnd().addMessage.emit(MessageType.Error, message)
982

    
983
        return end_breaks
984

    
985
    '''
986
        @Override (QEngineeringTextItem)
987
        @brief  get connected items
988
        @author Jeongwoo
989
        @date   2018.05.15
990
    '''
991

    
992
    def getConnectedItems(self):
993
        visited = []
994

    
995
        try:
996
            for run in self.runs:
997
                visited.extend(run.items)
998
        except Exception as ex:
999
            from App import App
1000
            from AppDocData import MessageType
1001

    
1002
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1003
                                                           sys.exc_info()[-1].tb_lineno)
1004
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1005

    
1006
        return visited
1007

    
1008
    def explode(self, remainFromTo=False):
1009
        """ explode line no """
1010

    
1011
        # if False == self.prop('Freeze'):
1012
        try:
1013
            for index in reversed(range(len(self.runs))):
1014
                self.runs[index].explode()
1015
        except Exception as ex:
1016
            from App import App
1017
            from AppDocData import MessageType
1018

    
1019
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1020
                                                           sys.exc_info()[-1].tb_lineno) + ' Item UID : ' + str(self.uid)
1021
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1022
        finally:
1023
            self.runs.clear()
1024
            if not remainFromTo:
1025
                self.set_property('From', None)
1026
                self.set_property('To', None)
1027

    
1028
            if hasattr(self, 'lineNoFromToIndicator') and self.lineNoFromToIndicator:
1029
                self.lineNoFromToIndicatorShowFlag = False
1030
                if self.scene():
1031
                    self.lineNoFromToIndicator[0].setVisible(False)
1032
                    if len(self.lineNoFromToIndicator) == 2:
1033
                        self.lineNoFromToIndicator[1].setVisible(False)
1034

    
1035
    '''
1036
        @brief      generate sql phrase to save to database(Notice: Line No's symbol is is 1)
1037
        @author     humkyung
1038
        @date       2018.08.14
1039
    '''
1040
    def toSql_return_separately(self):
1041
        import uuid
1042
        from EngineeringAbstractItem import QEngineeringAbstractItem
1043

    
1044
        res = []
1045
        resLater = []
1046

    
1047
        app_doc_data = AppDocData.instance()
1048
        cols = ['UID', 'Drawings_UID', 'Symbol_UID', 'X', 'Y', 'Width', 'Height', 'Rotation', 'Value', 'Connected',
1049
                '[From]', '[To]']
1050
        if type(self) is QEngineeringLineNoTextItem:
1051
            values = ['?', '?', "(select UID from Symbol where Name='Line NO' and SymbolType_UID=-1)", '?', '?', '?',
1052
                      '?', '?', '?', '?', '?', '?']
1053
        else:
1054
            values = ['?', '?', "(select UID from Symbol where Name='Trim Line NO' and SymbolType_UID=-1)", '?', '?',
1055
                      '?', '?', '?', '?', '?', '?', '?']
1056
        _from = self.prop('From')
1057
        if not _from:
1058
            _from = ''
1059
        _to = self.prop('To')
1060
        if not _to:
1061
            _to = ''
1062
        params = [(str(self.uid), str(app_doc_data.activeDrawing.UID), self.loc[0], self.loc[1], self.size[0],
1063
                   self.size[1], str(self.angle), \
1064
                   self.text(), str(self.conns[0]) if self.conns else None, str(_from), str(_to))]
1065
        sql = 'insert into Components({}) values({})'.format(','.join(cols), ','.join(values))
1066
        res.append((sql, tuple(params)))
1067

    
1068
        cols = ['UID', 'Components_UID', 'LineProperties_UID', 'Value']
1069
        values = ['?', '?', '?', '?']
1070
        params = []
1071
        attrs = self.getAttributes()
1072
        for key, value in attrs.items():
1073
            if key.Attribute == 'LINE NO':  # or key.IsProp != 5:
1074
                continue
1075
            params.append((str(uuid.uuid4()), str(self.uid), str(key.UID), str(value)))
1076
        sql = 'insert into LineNoAttributes({}) values({})'.format(','.join(cols), ','.join(values))
1077
        resLater.append((sql, tuple(params)))
1078

    
1079
        if self.associations():
1080
            cols = ['UID', '[Type]', 'Components_UID', 'Association']
1081
            values = ['?', '?', '?', '?']
1082
            params = []
1083
            for assoc in self.associations():
1084
                params.append(
1085
                    (str(uuid.uuid4()), QEngineeringAbstractItem.assoc_type(assoc), str(self.uid), str(assoc.uid)))
1086
            sql = 'insert into Associations({}) values({})'.format(','.join(cols), ','.join(values))
1087
            resLater.append((sql, tuple(params)))
1088

    
1089
        # insert line no's Attributes
1090
        cols = ['UID', 'Components_UID', 'SymbolAttribute_UID', 'Value', 'Association_UID', 'Freeze']
1091
        values = ['?', '?', '?', '?', '?', '?']
1092
        params = []
1093
        for key in attrs.keys():
1094
            if key.IsProp != 5:
1095
                params.append((str(uuid.uuid4()), str(self.uid), str(key.UID), str(attrs[key]), str(key.AssocItem),
1096
                               str(key.Freeze)))
1097
        sql = 'insert into Attributes({}) values({})'.format(','.join(cols), ','.join(values))
1098
        res.append((sql, tuple(params)))
1099

    
1100
        if self.associations():
1101
            cols = ['UID', '[Type]', 'Components_UID', 'Association']
1102
            values = ['?', '?', '?', '?']
1103
            params = []
1104
            for assoc in self.associations():
1105
                params.append(
1106
                    (str(uuid.uuid4()), QEngineeringAbstractItem.assoc_type(assoc), str(self.uid), str(assoc.uid)))
1107
            sql = 'insert into Associations({}) values({})'.format(','.join(cols), ','.join(values))
1108
            resLater.append((sql, tuple(params)))
1109

    
1110
        _index = 0
1111
        for run in self.runs:
1112
            if run and run.items:
1113
                resLater.extend(run.to_sql(_index, self))
1114
                _index += 1
1115

    
1116
        return res, resLater
1117

    
1118
    '''
1119
        @brief      return Line Data List
1120
        @author     kyouho
1121
        @date       2018.08.14
1122
        @ no more used
1123
    '''
1124
    def getLineDataList(self):
1125
        dataList = []
1126
        '''
1127
        try:
1128
            import uuid
1129
            global lineColumnList
1130

1131
            docData = AppDocData.instance()
1132
            attrs = self.getAttributes()
1133
            for index in range(len(lineColumnList)):
1134
                dataList.append('')
1135

1136
            dataList[20] = docData.imgName
1137

1138
            for key in attrs.keys():
1139
                if type(key) is not UserInputAttribute:
1140
                    lineProp = docData.getLinePropertiesByUID(key.UID)
1141
                    if lineProp:
1142
                        attrName = lineProp[0].Attribute.upper().replace(' ', '')
1143
                    else:
1144
                        attrName = key.Attribute.upper().replace(' ', '')
1145

1146
                    data = attrs[key]
1147
                    if attrName == 'NOMINALDIAMETER':
1148
                        dataList[1] = data
1149
                    elif attrName == 'FLUIDCODE':
1150
                        dataList[2] = data
1151
                        dataList[7] = data
1152
                    elif attrName == 'TAGSEQNO':
1153
                        pass
1154
                    elif attrName == 'INSULATIONPURPOSE':
1155
                        dataList[16] = data
1156
                    elif attrName == 'STREAMNO':
1157
                        pass
1158
                    elif attrName == 'LINENO' or attrName == 'LINE NO':
1159
                        dataList[3] = data
1160
                    elif attrName == 'PNIDNUMBER':
1161
                        pass
1162
                    elif attrName == 'PIPINGMATERIALSCLASS':
1163
                        dataList[4] = data
1164
                    elif attrName == '':
1165
                        pass
1166
                else:
1167
                    typeUID = key.Attribute
1168
                    value = key.text
1169
                    lineAttr = docData.getLinePropertiesByUID(key.UD)
1170

1171
                    for index in range(len(lineColumnList)):
1172
                        if lineColumnList[index] == lineAttr[0].Attribute:
1173
                            dataList[index] = value
1174
        except Exception as ex:
1175
            from App import App
1176
            from AppDocData import MessageType
1177

1178
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1179
                                                           sys.exc_info()[-1].tb_lineno)
1180
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1181

1182
        if dataList[0] == '':
1183
            dataList[0] = str(uuid.uuid4())
1184
        '''
1185

    
1186
        return dataList
1187

    
1188
    def EvaluatedEQ(self):
1189
        ''' evaluate line no's From / To equipment '''
1190

    
1191
        from EngineeringNozzleItem import QEngineeringNozzleItem
1192
        from EngineeringVendorItem import QEngineeringVendorItem
1193
        from EngineeringEquipmentItem import QEngineeringEquipmentItem
1194
        from EngineeringLineItem import QEngineeringLineItem
1195

    
1196
        pool = []
1197
        visited = []
1198
        if self.runs and self.runs[0]:
1199
            pool.append(self)
1200
            _attrs = self.getAttributes()
1201

    
1202
        from_found = False
1203
        to_found = False
1204

    
1205
        
1206
        try:
1207
            while pool:
1208
                lineNo = pool.pop()
1209
                if lineNo not in visited:
1210
                    visited.append(lineNo)
1211
                else:
1212
                    continue
1213

    
1214
                if lineNo.runs and lineNo.runs[0]:
1215
                    items = lineNo.runs[0].items
1216
                    if len(items) > 2:
1217
                        if type(items[0]) is QEngineeringNozzleItem and not from_found:
1218
                            for connector in items[0].connectors:
1219
                                # From
1220
                                if (type(connector.connectedItem) is QEngineeringVendorItem or type(
1221
                                        connector.connectedItem) is QEngineeringEquipmentItem) and \
1222
                                        connector.connectedItem not in items:
1223
                                    for _attr in _attrs:
1224
                                        if _attr.Attribute == 'From_eq' and self.add_assoc_item(connector.connectedItem,
1225
                                                                                                at=_attr.AttrAt):
1226
                                            _attr.AssocItem = connector.connectedItem
1227
                                            from_found = True
1228
                                            break
1229
                                    break
1230
                        elif not from_found:
1231
                            if type(items[0]) is QEngineeringLineItem and items[0].connectors[0].connectedItem and items[0].connectors[0].connectedItem.owner:
1232
                                pool.append(items[0].connectors[0].connectedItem.owner)
1233
                            else:
1234
                                next_items = [connector.connectedItem for connector in items[0].connectors if connector.connectedItem and \
1235
                                        connector.connectedItem is not items[1] and items[0].next_connected(items[1], connector.connectedItem)]
1236
                                if next_items and next_items[0].owner:
1237
                                    pool.append(next_items[0].owner)
1238

    
1239
                        if type(items[-1]) is QEngineeringNozzleItem and not to_found:
1240
                            for connector in items[-1].connectors:
1241
                                # To
1242
                                if (type(connector.connectedItem) is QEngineeringVendorItem or type(
1243
                                        connector.connectedItem) is QEngineeringEquipmentItem) and \
1244
                                        connector.connectedItem not in items:
1245
                                    for _attr in _attrs:
1246
                                        if _attr.Attribute == 'To_eq' and self.add_assoc_item(connector.connectedItem,
1247
                                                                                            at=_attr.AttrAt):
1248
                                            _attr.AssocItem = connector.connectedItem
1249
                                            to_found = True
1250
                                            break
1251
                                    break
1252
                        elif not to_found:
1253
                            if type(items[-1]) is QEngineeringLineItem and items[-1].connectors[1].connectedItem and items[-1].connectors[1].connectedItem.owner:
1254
                                pool.append(items[-1].connectors[1].connectedItem.owner)
1255
                            else:
1256
                                next_items = [connector.connectedItem for connector in items[-1].connectors if connector.connectedItem and \
1257
                                        connector.connectedItem is not items[-2] and items[-1].next_connected(items[-2], connector.connectedItem)]
1258
                                if next_items and next_items[0].owner:
1259
                                    pool.append(next_items[0].owner)
1260
        except Exception as ex:
1261
            from App import App
1262
            from AppDocData import MessageType
1263

    
1264
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1265
                                                           sys.exc_info()[-1].tb_lineno)
1266
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1267

    
1268
    def sort_order_text(self):
1269
        """ return true if line no same"""
1270

    
1271
        app_doc_data = AppDocData.instance()
1272
        
1273
        configs = app_doc_data.getConfigs('Sort', 'LineNoKeys')
1274
        targets = configs[0].value.split(',') if configs else []
1275

    
1276
        if targets:
1277
            attrs = self.getAttributes(True)
1278
            matches = []
1279

    
1280
            for key in targets:
1281
                _matches = [_key for _key in list(attrs.keys()) if str(_key.UID) == key]
1282
                if _matches:
1283
                    matches.append(attrs[_matches[0]])
1284
        else:
1285
            matches = [self.text()]
1286

    
1287
        return '_'.join(matches)
1288
    
1289
    def validate(self, rules):
1290
        """ validation check """
1291

    
1292
        from SymbolSvgItem import SymbolSvgItem
1293
        from AppDocData import AppDocData
1294
        from EngineeringReducerItem import QEngineeringReducerItem
1295
        from EngineeringLineItem import QEngineeringLineItem
1296
        from EngineeringAbstractItem import QEngineeringAbstractItem
1297
        from ValidateCommand import LineNoValidation
1298

    
1299
        errors = []
1300

    
1301
        try:
1302
            _translate = QCoreApplication.translate
1303

    
1304
            docdata = AppDocData.instance()
1305
            dataPath = docdata.getErrorItemSvgPath()
1306

    
1307
            lineNoError = False
1308

    
1309
            _error = super().validate(rules)
1310
            errors.extend(_error)
1311

    
1312
            _from = self.prop('From')
1313
            _to = self.prop('To')
1314

    
1315
            if not _from or not _to:
1316
                lineNoError = True
1317
            elif self.runs:
1318
                if self.runs[0].items[0] is not _from:
1319
                    lineNoError = True
1320
                elif self.runs[0].items[-1] is not _to:
1321
                    lineNoError = True
1322
            else:
1323
                return errors
1324

    
1325
            if LineNoValidation.BranchSizeError in rules or LineNoValidation.SizeChangeError in rules:
1326
                size_errors = []
1327
                branch_errors = []
1328
                for run in self.runs:
1329
                    sizes = []
1330
                    for item in run.items:
1331
                        item_size = None
1332
                        attrs = item.getAttributes()
1333
                        for prop, value in attrs.items():
1334
                            if prop.Attribute.upper() == 'Size'.upper() or prop.Attribute.upper() == 'NominalDiameter'.upper():
1335
                                if value and value != 'None':
1336
                                    item_size = value
1337
                                    if type(item) is QEngineeringReducerItem or (issubclass(type(item), SymbolSvgItem) and item.iType == 22): # Relief Valve
1338
                                        sizes.append([item, item.mainSubSize[0], item.mainSubSize[1]])
1339
                                        break
1340
                                    else:
1341
                                        sizes.append([item, value, value])
1342
                                        break
1343

    
1344
                        if item_size and type(item) is QEngineeringLineItem:
1345
                            for conn in item.connectors:
1346
                                if conn.connectedItem and type(conn.connectedItem) is QEngineeringLineItem and \
1347
                                    conn._connected_at == QEngineeringAbstractItem.CONNECTED_AT_BODY:
1348
                                    _item_size = None
1349
                                    attrs = conn.connectedItem.getAttributes()
1350
                                    for prop, value in attrs.items():
1351
                                        if prop.Attribute.upper() == 'Size'.upper() or prop.Attribute.upper() == 'NominalDiameter'.upper():
1352
                                            if value and value != 'None':
1353
                                                _item_size = value
1354
                                                break
1355
                                
1356
                                    if _item_size and self.inch_to_number(item_size) > self.inch_to_number(_item_size):
1357
                                        branch_errors.append(item)
1358
                                        branch_errors.append(conn.connectedItem)
1359

    
1360
                    if len(sizes) > 1:
1361
                        for index in range(len(sizes) - 1):
1362
                            if sizes[index][2] != sizes[index + 1][1] and \
1363
                                type(sizes[index][0]) is not QEngineeringReducerItem and type(sizes[index + 1][0]) is not QEngineeringReducerItem \
1364
                                and (hasattr(sizes[index][0], 'iType') and sizes[index][0].iType != 22) and \
1365
                                (hasattr(sizes[index + 1][0], 'iType') and sizes[index + 1][0].iType != 22):
1366
                                    size_errors.append(sizes[index][0])
1367
                                    size_errors.append(sizes[index + 1][0])
1368
                            elif sizes[index][1] not in sizes[index + 1] and sizes[index][2] not in sizes[index + 1]:
1369
                                    size_errors.append(sizes[index][0])
1370
                                    size_errors.append(sizes[index + 1][0])
1371

    
1372
                if LineNoValidation.SizeChangeError in rules:
1373
                    for size in size_errors:
1374
                        error = SymbolSvgItem.createItem('Error', None, dataPath)
1375
                        error.setPosition([size.sceneBoundingRect().center().x(), size.sceneBoundingRect().center().y()])
1376
                        error.parent = size
1377
                        error.msg = _translate('Size change error', 'Size change error')
1378
                        error.setToolTip(error.msg)
1379
                        error.area = 'Drawing'
1380
                        error.name = 'Error'
1381
                        errors.append(error)
1382

    
1383
                if LineNoValidation.BranchSizeError in rules:
1384
                    for size in branch_errors:
1385
                        error = SymbolSvgItem.createItem('Error', None, dataPath)
1386
                        error.setPosition([size.sceneBoundingRect().center().x(), size.sceneBoundingRect().center().y()])
1387
                        error.parent = size
1388
                        error.msg = _translate('Branch size error', 'Branch size error')
1389
                        error.setToolTip(error.msg)
1390
                        error.area = 'Drawing'
1391
                        error.name = 'Error'
1392
                        errors.append(error)
1393

    
1394
            if LineNoValidation.MainRunSizeWarning in rules:
1395
                if self.runs and self.runs[0].items:
1396
                    _size = self.Size
1397
                    found = False
1398
                    if _size:
1399
                        for item in self.runs[0].items:
1400
                            if type(item) is QEngineeringReducerItem or (issubclass(type(item), SymbolSvgItem) and item.iType == 22):
1401
                                continue
1402
                            _size2 = item.EvaluatedSize
1403
                            if _size2 and _size2 != 'None' and _size2 == _size:
1404
                                found = True
1405
                                break
1406

    
1407
                            #attrs = item.getAttributes()
1408
                            #for prop, value in attrs.items():
1409
                            #    if prop.Attribute.upper() == 'Size'.upper() or prop.Attribute.upper() == 'NominalDiameter'.upper():
1410
                            #        if value and value != 'None' and _size != value:
1411
                            #            found = True
1412
                            #            break
1413
                            
1414
                            if found:
1415
                                break
1416
                    
1417
                    if not found:
1418
                        error = SymbolSvgItem.createItem('Error', None, dataPath)
1419
                        error.setPosition([self.sceneBoundingRect().center().x(), self.sceneBoundingRect().center().y()])
1420
                        error.parent = self
1421
                        error.msg = _translate('Main run size warning', 'Main run size warning')
1422
                        error.setToolTip(error.msg)
1423
                        error.area = 'Drawing'
1424
                        error.name = 'Warning'
1425
                        errors.append(error)
1426

    
1427
            if LineNoValidation.FromToError in rules:
1428
                if lineNoError:
1429
                    error = SymbolSvgItem.createItem('Error', None, dataPath)
1430
                    error.setPosition([self.sceneBoundingRect().center().x(), self.sceneBoundingRect().center().y()])
1431
                    error.parent = self
1432
                    error.msg = _translate('From/ To error', 'From/ To error')
1433
                    error.setToolTip(error.msg)
1434
                    error.area = 'Drawing'
1435
                    error.name = 'Error'
1436
                    errors.append(error)
1437

    
1438
        except Exception as ex:
1439
            from App import App
1440
            from AppDocData import MessageType
1441

    
1442
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1443
                                                           sys.exc_info()[-1].tb_lineno)
1444
            App.mainWnd().addMessage.emit(MessageType.Error, message)
1445

    
1446
        return errors
클립보드 이미지 추가 (최대 크기: 500 MB)