프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / MainWindow.py @ d6d16d45

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

1
# coding: utf-8
2

    
3
import sys
4
import os
5
import cv2
6
import numpy as np
7

    
8
from PyQt5.QtCore import *
9
from PyQt5.QtGui import *
10
from PyQt5.QtWidgets import *
11
from PyQt5.QtSvg import *
12

    
13
from PIL import Image
14

    
15
import MainWindow_UI
16
import QtImageViewer
17
from SingletonInstance import SingletonInstane
18

    
19
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Commands')
20
import CreateCommand
21
import CropCommand
22
import AreaOcrCommand
23
import CreateSymbolCommand
24
import AreaZoomCommand
25
import SelectAttributeCommand
26
import FenceCommand
27
import PlaceLineCommand
28

    
29
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Shapes')
30
from EngineeringPolylineItem import QEngineeringPolylineItem
31
from EngineeringLineItem import QEngineeringLineItem
32
from SymbolSvgItem import SymbolSvgItem
33
from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
34
from QEngineeringTextItem import QEngineeringTextItem
35
from QEngineeringLineNoTextItem import QEngineeringLineNoTextItem
36
from QEngineeringNoteItem import QEngineeringNoteItem
37
from QEngineeringSizeTextItem import QEngineeringSizeTextItem
38
from EngineeringUnknownItem import QEngineeringUnknownItem
39
from AppDocData import *
40
import SymbolTreeWidget, PropertyTableWidget
41
import SymbolEditorDialog
42
import ItemTreeWidget
43
import ItemPropertyTableWidget
44
from TextItemFactory import TextItemFactory
45

    
46
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane):
47
    '''
48
        @brief      initialize
49
        @author 
50
        @date   
51
        @history    humkyung 2018.04.12 add splitter widget
52
                    Jeongwoo 2018.04.27 Add Signal/Slot Connection 'noteNoSingleClicked'
53
                    Jeongwoo 2018.05.09 Initialize Action group
54
                    Jeongwoo 2018.05.10 Add Signal/Slot Connection 'lineNoSingleClicked'
55
                                        Add QActionGroup for managing checkable action
56
                    Jeongwoo 2018.06.27 Add Action [Zoom, Fit Window] and Add new actions into ActionGroup
57
    '''
58
    def __init__(self):
59
        super(self.__class__, self).__init__()
60
        self.setupUi(self)
61

    
62
        self.lastClickedCheckableAction = None
63

    
64
        docData = AppDocData.instance()
65
        project = docData.getCurrentProject()
66
        _translate = QCoreApplication.translate
67
        self.setWindowTitle(_translate("Digital P&ID - {}".format(project.name), "Digital P&ID - {}".format(project.name)))
68

    
69
        self.lineComboBox = QComboBox(self.toolBar)
70
        lineTypes = docData.getLineTypes()
71
        for lineType in lineTypes:
72
            self.lineComboBox.addItem(lineType)
73
        self.lineComboBox.currentIndexChanged.connect(self.onLineTypeChanged)
74

    
75
        self.toolBar.insertWidget(self.actionValidate, self.lineComboBox)
76
        self.toolBar.insertSeparator(self.actionValidate)
77
        self.graphicsView = QtImageViewer.QtImageViewer(self)
78
        self.graphicsView.setParent(self.centralwidget)
79
        self.graphicsView.useDefaultCommand() ##### USE DEFAULT COMMAND
80

    
81
        self.verticalLayout.addWidget(self.graphicsView)
82

    
83
        # Add Custom TreeWidget
84
        self.dirTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
85
        self.dirTreeWidget.header().hide()
86
        self.symbolTabVerticalLayout.addWidget(self.dirTreeWidget)
87

    
88
        # Add Custom Property TableWidget
89
        self.propertyTableWidget = PropertyTableWidget.QPropertyTableWidget()
90
        self.symbolTabVerticalLayout.addWidget(self.propertyTableWidget)
91
        self.dirTreeWidget.singleClicked.connect(self.propertyTableWidget.getClickedSymbol)
92
        # add splitter widget
93
        splitter = QSplitter(Qt.Vertical)
94
        splitter.addWidget(self.dirTreeWidget)
95
        splitter.addWidget(self.propertyTableWidget)
96
        self.symbolTabVerticalLayout.addWidget(splitter)
97
        # up to here
98

    
99
        # Add Custom Result Tree Widget (Symbol Explorer)
100
        self.resultTreeWidget = ItemTreeWidget.QItemTreeWidget(self.graphicsView)
101
        self.resultTreeWidget.header().hide()
102
        self.symbolExplorerVerticalLayout.addWidget(self.resultTreeWidget)
103

    
104
        # Add Empty Widget
105
        self.resultPropertyTableWidget = ItemPropertyTableWidget.QItemPropertyTableWidget(self)
106
        self.symbolExplorerVerticalLayout.addWidget(self.resultPropertyTableWidget)
107
        self.resultTreeWidget.singleClicked.connect(self.resultPropertyTableWidget.onSymbolClicked)
108
        self.resultTreeWidget.noteNoSingleClicked.connect(self.resultPropertyTableWidget.onNoteClicked)
109
        self.resultTreeWidget.lineNoSingleClicked.connect(self.resultPropertyTableWidget.onLineNoClicked)
110
        self.resultTreeWidget.drawingClicked.connect(self.resultPropertyTableWidget.onDrawingClicked)
111
        # add splitter widget
112
        splitter = QSplitter(Qt.Vertical)
113
        splitter.addWidget(self.resultTreeWidget)
114
        splitter.addWidget(self.resultPropertyTableWidget)
115
        self.symbolExplorerVerticalLayout.addWidget(splitter)
116
        # up to here
117

    
118
        # Initialize Action group
119
        actionGroup = QActionGroup(self)
120
        actionGroup.addAction(self.actionRecognition)
121
        actionGroup.addAction(self.actionLineRecognition)
122
        actionGroup.addAction(self.actionLine)
123
        actionGroup.addAction(self.actionGenerateOutput)
124
        actionGroup.addAction(self.actionOCR)
125
        actionGroup.addAction(self.actionZoom)
126
        actionGroup.addAction(self.actionFitWindow)
127
        actionGroup.addAction(self.actionSave)
128
        actionGroup.triggered.connect(self.actionGroupTriggered)
129

    
130
        # connect signals and slots
131
        self.actionClose.triggered.connect(self.close)
132
        self.actionOpen.triggered.connect(self.onOpenImageDrawing)
133
        self.actionLine.triggered.connect(self.onPlaceLine)
134
        self.actionRecognition.triggered.connect(self.recognize)
135
        self.actionLineRecognition.triggered.connect(self.recognizeLine)
136
        self.actionArea.triggered.connect(self.areaConfiguration)
137
        self.actionConfiguration.triggered.connect(self.configuration)
138
        self.actionOCR.triggered.connect(self.areaOcr)
139
        self.actionGenerateOutput.triggered.connect(self.generateOutput)
140
        self.pushButtonCreateSymbol.clicked.connect(self.createSymbol)
141
        self.pushButtonClearLog.clicked.connect(self.onClearLog)
142
        self.actionHMB_DATA.triggered.connect(self.onHMBData)
143
        self.actionEquipment_Data_List.triggered.connect(self.showEquipmentDataList)
144
        self.actionLine_Data_List.triggered.connect(self.showLineDataList)
145
        self.actionInstrument_Data_List.triggered.connect(self.showInstrumentDataList)
146
        self.actionCodeTable.triggered.connect(self.onShowCodeTable)
147
        self.actionImage_Drawing.triggered.connect(self.onViewImageDrawing)
148
        self.actionViewText.triggered.connect(self.onViewText)
149
        self.actionViewSymbol.triggered.connect(self.onViewSymbol)
150
        self.actionViewLine.triggered.connect(self.onViewLine)
151
        self.actionViewUnknown.triggered.connect(self.onViewUnknown)
152
        self.actionZoom.triggered.connect(self.areaZoom)
153
        self.actionFitWindow.triggered.connect(self.fitWindow)
154
        self.actionpdf_to_image.triggered.connect(self.onConvertPDFToImage)
155
        self.graphicsView.scene.changed.connect(lambda: self.resultTreeWidget.sceneChanged(self.graphicsView.scene.items()))
156
        self.graphicsView.scene.selectionChanged.connect(self.onSelectionChanged)
157
        self.actionInitialize.triggered.connect(self.initializeScene)
158
        self.resultPropertyTableWidget.cellDoubleClicked.connect(self.cellDoubleClickedEvent)
159
        self.actionSave.triggered.connect(self.saveToXml)
160

    
161
    '''
162
        @brief      save items to xml
163
        @author     kyouho
164
        @date       2018.07.31
165
    '''
166
    def saveToXml(self, alert = True):
167
        import XmlGenerator as xg
168
        from AppDocData import AppDocData
169
        docData = AppDocData.instance()
170
        if docData.imgName is None:
171
            self.showImageSelectionMessageBox()
172
            return
173
        result = xg.writeXmlOnScene(docData.imgName, docData.imgWidth, docData.imgHeight, self.graphicsView.scene)
174
        
175
        if alert:
176
            resultStr = '[저장 결과]'
177

    
178
            for item in result.items():
179
                itemName = str(item[0])
180
                itemSuccessCount = str(item[1][0])
181
                itemFailUidList = item[1][1]
182
                resultStr += "\r\n" + itemName + " Save Count : " + itemSuccessCount
183
                if len(itemFailUidList) > 0:
184
                    resultStr += "\r\n" + itemName + " Error List(UID)"
185
                    for uid in itemFailUidList:
186
                        resultStr += "\r\n" + uid
187

    
188
            QMessageBox.about(self.graphicsView, "알림", resultStr)
189

    
190

    
191
    '''
192
        @brief      refresh resultPropertyTableWidget
193
        @author     kyouho
194
        @date       2018.07.19
195
    '''
196
    def refreshResultPropertyTableWidget(self):
197
        items = self.graphicsView.scene.selectedItems()
198
        if len(items) == 1:
199
            self.resultPropertyTableWidget.onSymbolClicked(items[0])
200

    
201
    '''
202
        @brief      resultPropertyTableWidget Cell Double Click Event
203
        @author     kyouho
204
        @date       2018.07.19
205
    '''
206
    def cellDoubleClickedEvent(self, row, column):
207
        if column == 1:
208
            cell = self.resultPropertyTableWidget.item(row, 0)
209
            if cell is not None and self.resultPropertyTableWidget.item(row, 0).text():
210
                cellText = self.resultPropertyTableWidget.item(row, 0).text()
211
                docData = AppDocData.instance()
212
                if docData.checkAttribute(cellText):
213
                    items = self.graphicsView.scene.selectedItems()
214
                    if items is not None and len(items) == 1:
215
                        self.graphicsView.command = SelectAttributeCommand.SelectAttributeCommand(self.graphicsView)
216
                        cursor = QCursor(Qt.PointingHandCursor)
217
                        QApplication.instance().setOverrideCursor(cursor)
218
                        self.graphicsView.currentAttribute = cellText
219
                        
220
                        # 기존 cellText를 가진 attrs 삭제
221
                        items[0].removeSelfAttr(cellText)
222

    
223
                        from PyQt5 import QtGui
224
                        cellItem = QTableWidgetItem('')
225
                        icon = QtGui.QIcon()
226
                        icon.addPixmap(QtGui.QPixmap(":/newPrefix/doubleclick.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
227
                        cellItem.setIcon(icon)
228
                        self.resultPropertyTableWidget.setItem(row, 1, cellItem)
229
    
230
    '''
231
        @brief  add message listwidget
232
        @author humkyung
233
        @date   2018.07.31
234
    '''
235
    def addMessage(self, messageType, message):
236
        from AppDocData import MessageType
237

    
238
        try:
239
            current = QDateTime.currentDateTime()
240

    
241
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
242
            if messageType == MessageType.Error:
243
                item.setBackground(Qt.red)
244

    
245
            self.listWidgetLog.insertItem(0, item)
246
        except Exception as ex:
247
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
248

    
249
    '''
250
        @brief      clear log
251
        @author     humkyung
252
        @date       2018.08.01
253
    '''
254
    def onClearLog(self):
255
        self.listWidgetLog.clear()
256

    
257
    '''
258
        @brief      Area Zoom
259
        @author     Jeongwoo
260
        @date       2018.06.27
261
    '''
262
    def areaZoom(self, action):
263
        if self.actionZoom.isChecked():
264
            self.graphicsView.command = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
265

    
266
    '''
267
        @brief      Fit Window
268
        @author     Jeongwoo
269
        @date       2018.06.27
270
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
271
    '''
272
    def fitWindow(self, action):
273
        self.graphicsView.useDefaultCommand()
274
        self.graphicsView.zoomImageInit()
275

    
276
    '''
277
        @brief      convert to selected pdf to image
278
        @author     humkyung 
279
        @date       2018.07.09
280
    '''
281
    def onConvertPDFToImage(self):
282
        try:
283
            filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)) , 'bin64', 'PDF_TO_IMAGE.exe')
284
            os.system(filePath)
285
        except Exception as ex:
286
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
287

    
288
    '''
289
        @brief      selection changed
290
        @author     humkyung
291
        @date       2018.06.27
292
        @history    humkung 2018.07.08 call tree widget's findItem
293
    '''
294
    def onSelectionChanged(self):
295
        for item in self.graphicsView.scene.selectedItems():
296
            self.resultTreeWidget.findItem(item)
297
            self.resultPropertyTableWidget.showItemProperty(item)
298
        
299
    '''
300
        @brief      Initialize scene and ResultTreeWidget
301
        @author     Jeongwoo
302
        @date       2018.06.14
303
    '''
304
    def initializeScene(self, action):
305
        if not self.graphicsView.hasImage():
306
            self.actionEquipment.setChecked(False)
307
            self.showImageSelectionMessageBox()
308
            return
309

    
310
        items = self.graphicsView.scene.items()
311
        for item in items:
312
            if type(item) is not QGraphicsPixmapItem:
313
                self.graphicsView.scene.removeItem(item)
314
                
315
        if self.path is not None:
316
            baseName = os.path.basename(self.path)
317
            self.resultTreeWidget.setCurrentPID(baseName)
318

    
319
    '''
320
        @brief      Manage Checkable Action statement
321
        @author     Jeongwoo
322
        @date       2018.05.10
323
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
324
    '''
325
    def actionGroupTriggered(self, action):
326
        if self.graphicsView.command is not None:
327
            self.graphicsView.useDefaultCommand()
328
        if self.lastClickedCheckableAction is not None and self.lastClickedCheckableAction == action and action.isChecked():
329
            action.setChecked(False)
330
            self.lastClickedCheckableAction = None
331
        elif action.isCheckable():
332
            self.lastClickedCheckableAction = action
333
        else:
334
            if self.lastClickedCheckableAction is not None:
335
                self.lastClickedCheckableAction.setChecked(False)
336
            self.lastClickedCheckableAction = None
337

    
338
    '''
339
        @brief      Create Equipment
340
        @author     Jeongwoo
341
        @date       18.05.03
342
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
343
    '''
344
    def createEquipment(self):
345
        if not self.graphicsView.hasImage():
346
            self.actionEquipment.setChecked(False)
347
            self.showImageSelectionMessageBox()
348
            return
349
        if self.actionEquipment.isChecked():
350
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.resultTreeWidget, self.dirTreeWidget)
351
        else:
352
            self.graphicsView.useDefaultCommand()
353

    
354

    
355
    '''
356
        @brief      Create Nozzle
357
        @author     Jeongwoo
358
        @date       2018.05.03
359
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
360
    '''
361
    def createNozzle(self):
362
        if not self.graphicsView.hasImage():
363
            self.actionNozzle.setChecked(False)
364
            self.showImageSelectionMessageBox()
365
            return
366
        if self.actionNozzle.isChecked():
367
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.resultTreeWidget, self.dirTreeWidget)
368
        else:
369
            self.graphicsView.useDefaultCommand()
370

    
371
    '''
372
        @brief      Area OCR
373
        @author     Jeongwoo
374
        @date       18.04.18
375
        @history    2018.05.02  Jeongwoo    Change graphicsView.command by actionOCR checked state
376
                                            Show MessageBox when imageviewer doesn't have image
377
    '''
378
    def areaOcr(self):
379
        if not self.graphicsView.hasImage():
380
            self.actionOCR.setChecked(False)
381
            self.showImageSelectionMessageBox()
382
            return
383

    
384
        if self.actionOCR.isChecked():
385
            cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView)
386
            cmd.onSuccess.connect(self.onRecognizeText)
387
            self.graphicsView.command = cmd
388
        else:
389
            self.graphicsView.useDefaultCommand()
390
    
391
    '''
392
        @brief      show text recognition dialog
393
        @author     humkyung
394
        @date       2018.08.08
395
    '''
396
    def onRecognizeText(self, x, y, width, height):
397
        from OcrResultDialog import QOcrResultDialog
398

    
399
        try:
400
            image = self.graphicsView.image().copy(x, y, width, height)
401
            dialog = QOcrResultDialog(self.graphicsView, image, QRectF(x, y, width, height))
402
            (isAccept, textInfoList) = dialog.showDialog()
403
            if isAccept:
404
                if textInfoList is not None and len(textInfoList) > 0:
405
                    docData = AppDocData.instance()
406
                    configs = docData.getConfigs('Line No', 'Delimiter')
407
                    delimiter = configs[0].value if 1 == len(configs) else '-'
408
                    lineNoconfigs = docData.getConfigs('Line No', 'Configuration')
409
                    for textInfo in textInfoList:
410
                        x = textInfo.getX()
411
                        y = textInfo.getY()
412
                        angle = textInfo.getAngle()
413
                        text = textInfo.getText()
414
                        width = textInfo.getW()
415
                        height = textInfo.getH()
416
                        item = TextItemFactory.instance().createTextItem(text, delimiter, lineNoconfigs)
417
                        item.loc = (x, y)
418
                        item.size = (width, height)
419
                        item.angle = angle
420
                        item.setPlainText(text)
421
                        item.setDefaultTextColor(Qt.blue)
422
                        item.addTextItemToScene(self.imageViewer.scene)
423
                else:
424
                    QMessageBox.about(self.graphicsView, "알림", "텍스트 검출 실패")
425
        except Exception as ex:
426
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
427
            self.addMessage(MessageType.Error, message)
428

    
429
    '''
430
        @brief  area configuration
431
    '''
432
    def areaConfiguration(self):
433
        from ConfigurationAreaDialog import QConfigurationAreaDialog
434

    
435
        self.dlgConfigurationArea = QConfigurationAreaDialog(self)
436
        self.dlgConfigurationArea.show()
437
        self.dlgConfigurationArea.exec_()
438

    
439
    '''
440
        @brief  configuration
441
    '''
442
    def configuration(self):
443
        from ConfigurationDialog import QConfigurationDialog
444

    
445
        self.dlgConfiguration = QConfigurationDialog(self)
446
        self.dlgConfiguration.show()
447
        self.dlgConfiguration.exec_()
448

    
449
    '''
450
        @brief  show nominal diameter dialog 
451
        @author humkyung
452
        @date   2018.06.28
453
    '''
454
    def onShowCodeTable(self):
455
        from CodeTableDialog import QCodeTableDialog
456

    
457
        dlg = QCodeTableDialog(self)
458
        dlg.exec_()
459

    
460
    '''
461
        @brief  show HMB data
462
        @author humkyung
463
        @date   2018.07.11
464
    '''
465
    def onHMBData(self):
466
        from HMBDialog import QHMBDialog
467

    
468
        dlg = QHMBDialog(self)
469
        dlg.show()
470
        dlg.exec_()
471

    
472
    '''
473
        @brief  show equipment data list 
474
        @author humkyung
475
        @date   2018.05.03
476
    '''
477
    def showEquipmentDataList(self):
478
        from QEquipmentDataListDialog import QEquipmentDataListDialog
479

    
480
        self.dlgEquipmentDataList = QEquipmentDataListDialog(self)
481
        self.dlgEquipmentDataList.exec_()
482

    
483
    '''
484
        @brief  show line data list 
485
        @author humkyung
486
        @date   2018.05.03
487
    '''
488
    def showLineDataList(self):
489
        from QLineDataListDialog import QLineDataListDialog
490

    
491
        self.dlgLineDataList = QLineDataListDialog(self)
492
        self.dlgLineDataList.exec_()
493

    
494
    '''
495
        @brief  show instrument data list 
496
        @author humkyung
497
        @date   2018.05.03
498
    '''
499
    def showInstrumentDataList(self):
500
        from QInstrumentDataListDialog import QInstrumentDataListDialog
501

    
502
        self.dlgInstrumentDataList = QInstrumentDataListDialog(self)
503
        self.dlgInstrumentDataList.exec_()
504

    
505
    '''
506
        @brief  Show Image Selection Guide MessageBox
507
        @author Jeongwoo
508
        @date   2018.05.02
509
    '''
510
    def showImageSelectionMessageBox(self):
511
        QMessageBox.about(self.graphicsView, "알림", "이미지를 선택하신 후 시도해주세요.")
512
        
513
    '''
514
        @brief  change selected lines' type by selected line type
515
        @author humkyung
516
        @date   2018.06.27
517
    '''
518
    def onLineTypeChanged(self, param):
519
        lineType = self.lineComboBox.itemText(param)
520
        selected = [item for item in self.graphicsView.scene.selectedItems() if type(item) is QEngineeringLineItem]
521
        if selected:
522
            for item in selected:
523
                item.lineType = lineType
524

    
525
    '''
526
        @brief      Open image drawing file and then display it
527
        @author     humkyung
528
        @date       2018.??.??
529
        @history    18.04.23 Jeongwoo    Add AppDocData.instance().setCurrentPidSource
530
                    18.04.23 Jeongwoo    Add Store Set Current Pid Image on AppDocData
531
                    18.05.02 Jeongwoo    Add useDefaultCommand()
532
                    humkyung 2018.05.24 load recognition result file if exists
533
                    Jeongwoo 2018.05.29 load data on xml if xml file exist
534
    '''
535
    def onOpenImageDrawing(self, MainWindow):
536
        from Drawing import Drawing
537

    
538
        try:
539
            appDocData = AppDocData.instance()
540
            project = appDocData.getCurrentProject()
541

    
542
            self.path = self.graphicsView.loadImageFromFile(project.getDrawingFilePath())
543
            if os.path.isfile(self.path):
544
                self.graphicsView.useDefaultCommand()
545

    
546
                appDocData.setImgFilePath(self.path)
547
                appDocData.activeDrawing = Drawing(appDocData.imgName)
548
                appDocData.setCurrentPidSource(Image.open(self.path))
549
                self.resultTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
550

    
551
                ## Load data on xml
552
                path = os.path.join(appDocData.getCurrentProject().getTempPath(), appDocData.imgName + '.xml')
553
                if os.path.isfile(path): self.loadRecognitionResultFromXml(path)
554
        except Exception as ex:
555
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
556
            self.addMessage(MessageType.Error, message)
557

    
558
        return self.path
559

    
560
    '''
561
        @brief  visible/invisible image drawing
562
        @author humkyung
563
        @date   2018.06.25
564
    '''
565
    def onViewImageDrawing(self, isChecked):
566
        for item in self.graphicsView.scene.items():
567
            if type(item) is QGraphicsPixmapItem:
568
                item.setVisible(isChecked)
569
                break
570

    
571
    '''
572
        @brief  visible/invisible Text 
573
        @author humkyung
574
        @date   2018.06.28
575
    '''
576
    def onViewText(self, isChecked):
577
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
578
        for item in selected:
579
            item.setVisible(isChecked)
580

    
581
    '''
582
        @brief  visible/invisible Symbol 
583
        @author humkyung
584
        @date   2018.06.28
585
    '''
586
    def onViewSymbol(self, isChecked):
587
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem)]
588
        for item in selected:
589
            item.setVisible(isChecked)
590

    
591
    '''
592
        @brief  visible/invisible Line
593
        @author humkyung
594
        @date   2018.06.28
595
    '''
596
    def onViewLine(self, isChecked):
597
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem]
598
        for item in selected:
599
            item.setVisible(isChecked)
600

    
601
    '''
602
        @brief  visible/invisible Unknown 
603
        @author humkyung
604
        @date   2018.06.28
605
    '''
606
    def onViewUnknown(self, isChecked):
607
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
608
        for item in selected:
609
            item.setVisible(isChecked)
610

    
611
    '''
612
        @brief  create a symbol
613
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
614
                                            Add SymbolSvgItem
615
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
616
                                            Change method to make svg and image path
617
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
618
    '''
619
    def createSymbol(self):
620
        cmd = FenceCommand.FenceCommand(self.graphicsView)
621
        cmd.onSuccess.connect(self.onAreaSelected)
622
        self.graphicsView.command = cmd
623
        QApplication.setOverrideCursor(Qt.CrossCursor)
624

    
625
    '''
626
        @brief      show SymbolEditorDialog with image selected by user
627
        @author     humkyung
628
        @date       2018.07.20
629
    '''
630
    def onAreaSelected(self, x, y, width, height):
631
        try:
632
            image = self.graphicsView.image()
633
            if image is not None:
634
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height), AppDocData.instance().getCurrentProject())
635
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
636
                self.dirTreeWidget.initDirTreeWidget()
637
                if isAccepted:
638
                    if isImmediateInsert:
639
                        svgPath = newSym.getSvgFileFullPath()
640
                        img = cv2.imread(newSym.getImageFileFullPath(), 1)
641
                        w, h = (0, 0)
642
                        if len(img.shape[::-1]) == 2:
643
                            w, h = img.shape[::-1]
644
                        else:
645
                            _chan, w, h = img.shape[::-1]
646
                        svg = SymbolSvgItem(svgPath)
647
                        svg.buildItem(newSym.getName(), newSym.getType(), 0, [offsetX, offsetY], [w, h], [float(x) for x in newSym.getOriginalPoint().split(',')], [(float(x.split(',')[0]), float(x.split(',')[1])) for x in newSym.getConnectionPoint().split('/')], newSym.getBaseSymbol(), newSym.getAdditionalSymbol(), newSym.getHasInstrumentLabel)
648

    
649
                        svg.transfer.onRemoved.connect(self.resultTreeWidget.itemRemoved)
650
                        svg.addSvgItemToScene(self.graphicsView.scene)
651
                        for connector in svg.connectors:
652
                            self.graphicsView.scene.addItem(connector)
653
        finally:
654
            self.graphicsView.useDefaultCommand()
655
            QApplication.restoreOverrideCursor()
656
    
657
    '''
658
        @brief      create a line
659
        @author     humkyung
660
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
661
    '''
662
    def onPlaceLine(self):        
663
        if not self.graphicsView.hasImage():
664
            self.actionLine.setChecked(False)
665
            self.showImageSelectionMessageBox()
666
            return
667

    
668
        self.actionLine.setChecked(True)
669
        if not hasattr(self.actionLine, 'tag'):
670
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
671
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
672
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
673

    
674
        self.graphicsView.command = self.actionLine.tag
675

    
676
    '''
677
        @brief      add created lines to scene
678
        @author     humkyung
679
        @date       2018.07.23
680
    '''
681
    def onLineCreated(self):
682
        from EngineeringConnectorItem import QEngineeringConnectorItem
683

    
684
        try:
685
            count = len(self.actionLine.tag._polyline._vertices)
686
            if count > 1:
687
                items = []
688

    
689
                lineType = self.lineComboBox.currentText()
690
                for index in range(count - 1):
691
                    start = self.actionLine.tag._polyline._vertices[index]
692
                    end  = self.actionLine.tag._polyline._vertices[index + 1]
693
                    
694
                    lineItem = QEngineeringLineItem(vertices=[start, end])
695
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
696
                    lineItem.lineType = lineType
697
                    if items:
698
                        lineItem.connectIfPossible(items[-1], 5)
699
                    else:
700
                        pt = lineItem.startPoint()
701
                        selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
702
                        if selected is not None and type(selected) is QEngineeringConnectorItem:
703
                            lineItem.connectIfPossible(selected.parent, 5)
704
                    
705
                    items.append(lineItem)
706
                    self.graphicsView.scene.addItem(lineItem)
707

    
708
                pt = items[-1].endPoint()
709
                selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
710
                if selected is not None and type(selected) is QEngineeringConnectorItem:
711
                    items[-1].connectIfPossible(selected.parent, 5)
712
        finally:
713
            self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
714
            self.actionLine.tag.reset()
715

    
716
    '''
717
        @brief      refresh scene
718
        @author     humkyung
719
        @date       2018.07.23
720
    '''
721
    def onCommandRejected(self, cmd):
722
        try:
723
            if cmd is self.actionLine.tag:
724
                self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
725
                self.graphicsView.scene.update()
726
                self.actionLine.tag.reset()
727

    
728
                self.actionLine.setChecked(False)
729
        finally:
730
            self.graphicsView.useDefaultCommand()
731
            
732
    '''
733
        @brief      recognize symbol and text
734
        @author     humkyung
735
        @date       2018.04.??
736
        @history    2018.04.16  humkyung    execute line no tracing
737
                    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
738
                    2018.05.25  Jeongwoo    Add parameter on QRecognitionDialog.__init__() and Move thread to QRecognitionDialog
739
                                            Remove codes below if self.dlg.isAccepted == True
740
                    2018.05.29  Jeongwoo    Remove connects and comments
741
    '''
742
    def recognize(self, MainWindow):
743
        from QRecognitionDialog import QRecognitionDialog
744

    
745
        if not self.graphicsView.hasImage():
746
            self.showImageSelectionMessageBox()
747
            return
748

    
749
        try:
750
            self.onClearLog()
751
            self.dlg = QRecognitionDialog(self, self.path)
752
            self.dlg.exec_()
753
            if self.dlg.isAccepted == True:
754
                '''DO NOTHING'''
755
        except Exception as ex:
756
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
757
            self.addMessage(MessageType.Error, message)
758

    
759
    '''
760
        @brief
761
        @date       2018.05.25
762
        @author     Jeongwoo
763
    '''
764
    def itemRemoved(self, item):
765
        try:
766
            self.resultTreeWidget.itemRemoved(item)
767
            if item.scene() is not None: item.scene().removeItem(item)
768
        except Exception as ex:
769
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
770

    
771
    '''
772
        @brief      recognize line
773
        @author     humkyung
774
        @date       2018.04.19
775
        @history    Jeongwoo 2018.04.26 Variable name changed (texts → lineNos)
776
                                        TextItem type changed (QEngineeringTextItem → QEngineeringLineNoTextItem)
777
                    humkyung 2018.04.26 remove small objects before recognizing line
778
                    Jeongwoo 2018.05.02 Show MessageBox when imageviewer doesn't have image
779
                    Jeongwoo 2018.05.25 Move codes about LineDetector
780
                    humkyung 2018.06.17 show progress dialog
781
    '''
782
    def recognizeLine(self, MainWindow):
783
        from LineNoTracer import LineNoTracer
784
        from QConnectAttrDialog import QConnectAttrDialog
785

    
786
        if not self.graphicsView.hasImage():
787
            self.showImageSelectionMessageBox()
788
            return
789

    
790
        try:
791
            self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView)
792
            self.dlgConnectAttr.exec_()
793

    
794
            # construct line no item
795
            docData = AppDocData.instance()
796
            for lineno in docData.lineNos:
797
                item = self.resultTreeWidget.addTreeItem(self.resultTreeWidget.root, lineno)
798
                connectedItems = lineno.getConnectedItems()
799
                for connectedItem in connectedItems:
800
                    if issubclass(type(connectedItem), SymbolSvgItem): self.resultTreeWidget.addTreeItem(item, connectedItem)
801
            # up to here
802
        except Exception as ex:
803
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
804
            self.addMessage(MessageType.Error, message)
805

    
806
    '''
807
        @history    2018.05.25  Jeongwoo    Moved from MainWindow
808
                                            SvgItem and TextItem Connect with method in this class
809
                                            Change method to add GraphicsItem
810
                    2018.05.28  Jeongwoo    Make QGraphicsItem by symbol, text object. Not xml
811
                    2018.05.29  Jeongwoo    Change method name and Moved from QRecognitionDialog
812
                    2018.05.30  Jeongwoo    Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol)
813
                                            Change Method name and seperate each item
814
                    humkyung 2018.06.11 display difference between original and recognized image
815
                    Jeongwoo 2018.06.18 Update Scene after all item added
816
    '''
817
    def drawDetectedItems(self, symbolList, textInfoList, noteTextInfoList):
818
        self.drawDetectedSymbolItem(symbolList)
819
        self.drawDetectedTextItem(textInfoList)
820
        self.drawDetectedNoteItem(noteTextInfoList)
821

    
822
        # Update Scene
823
        self.graphicsView.scene.update(self.graphicsView.sceneRect())
824

    
825
    '''
826
        history    humkyung 2018.06.09 check length of original and connection point is 2 while parsing
827
    '''
828
    def drawDetectedSymbolItem(self, symbolList):
829
        from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
830
        from SymbolSvgItem import SymbolSvgItem
831
        import math
832

    
833
        try:
834
            project = AppDocData.instance().getCurrentProject()
835

    
836
            searchedMap = []
837
            for symbol in symbolList:
838
                pt = [float(x) for x in symbol.getSp()]
839
                size = [symbol.getWidth(), symbol.getHeight()]
840
                name = symbol.getName()
841
                angle = round(math.radians(symbol.getRotatedAngle()), 2)
842
                type = symbol.getType()
843
                origin = [0,0]
844
                if 2 == len(symbol.getOriginalPoint().split(',')):
845
                    tokens = symbol.getOriginalPoint().split(',')
846
                    origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
847
                connPts = []
848
                if symbol.getConnectionPoint() is not None:
849
                    connPts = [(pt[0] + float(x.split(',')[0]), pt[1] + float(x.split(',')[1])) for x in symbol.getConnectionPoint().split('/') if 2 == len(x.split(','))]
850
                parentSymbol = symbol.getBaseSymbol()
851
                childSymbol = symbol.getAdditionalSymbol()
852
                hasInstrumentLabel = symbol.getHasInstrumentLabel()
853

    
854
                svgFilePath = os.path.join(project.getSvgFilePath(), type, name + '.svg')
855
                if os.path.isfile(svgFilePath):
856
                    svg = SymbolSvgItem.createItem(type, svgFilePath)
857
                    svg.buildItem(name, type, angle, pt, size, origin, connPts, parentSymbol, childSymbol, hasInstrumentLabel)
858
                    svg.reCalculationRotatedItem()
859

    
860
                    # set owner - 2018.07.20 added by humkyung                   
861
                    matches = [searched for searched in searchedMap if searched[0] == symbol.owner]
862
                    if len(matches) == 1:
863
                        svg.owner = matches[0][1]
864
                    searchedMap.append((symbol, svg))
865
                    # up to here
866

    
867
                    svg.transfer.onRemoved.connect(self.itemRemoved)
868
                    self.addSvgItemToScene(svg)
869
                else:
870
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
871
                    item.isSymbol = True
872
                    item.angle = angle
873
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
874
                    self.graphicsView.scene.addItem(item)
875
            # up to here
876
        except Exception as ex:
877
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
878
            self.addMessage(MessageType.Error, message)
879

    
880
    '''
881
        @history    2018.06.08  Jeongwoo    Add parameter on round method
882
    '''
883
    def drawDetectedTextItem(self, textInfoList):
884
        from TextItemFactory import TextItemFactory
885
        import math
886
        try:
887
            docData = AppDocData.instance()
888
            configs = docData.getConfigs('Line No', 'Delimiter')
889
            delimiter = configs[0].value if 1 == len(configs) else '-'
890
            lineNoconfigs = docData.getConfigs('Line No', 'Configuration')
891
            #
892
            linePropertyData = {}
893
            linePropertyData['NominalDiameter'] = docData.getNomialPipeSizeData(True)
894
            linePropertyData['FluidCode'] = docData.getCodeTable('FluidCode', True)
895
            linePropertyData['UnitNumber'] = docData.getCodeTable('UnitNumber', True)
896
            linePropertyData['PnIDNumber'] = docData.getCodeTable('PnIDNumber', True)
897
            linePropertyData['PipingMaterialsClass'] = docData.getCodeTable('PipingMaterialsClass', True)
898
            linePropertyData['InsulationPurpose'] = docData.getCodeTable('InsulationPurpose', True)
899
            #
900
            configs = docData.getConfigs('Line No Tag Rule', 'Tag Seq No')
901
            tagSeqNoPattern = configs[0].value if 1 == len(configs) else None
902

    
903
            # parse texts
904
            for textInfo in textInfoList:
905
                x = textInfo.getX()
906
                y = textInfo.getY()
907
                width = textInfo.getW()
908
                height = textInfo.getH()
909
                angle = round(math.radians(textInfo.getAngle()), 2)
910
                text = textInfo.getText()
911
                item = TextItemFactory.instance().createTextItem(text, delimiter, lineNoconfigs, linePropertyData, tagSeqNoPattern)
912
                if item is not None:
913
                    item.loc = (x, y)
914
                    item.size = (width, height)
915
                    item.angle = angle
916
                    item.setPlainText(text)
917
                    item.transfer.onRemoved.connect(self.itemRemoved)
918
                    self.addTextItemToScene(item)
919
        except Exception as ex:
920
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
921
            self.addMessage(MessageType.Error, message)
922

    
923
    def drawDetectedNoteItem(self, noteTextInfoList):
924
        from TextItemFactory import TextItemFactory
925
        import math
926
        try:
927
            # parse notes
928
            for note in noteTextInfoList:
929
                x = note.getX()
930
                y = note.getY()
931
                width = note.getW()
932
                height = note.getH()
933
                angle = round(math.radians(note.getAngle()))
934
                text = note.getText()
935
                item = TextItemFactory.instance().createTextItem(text)
936
                item.loc = (x, y)
937
                item.size = (width, height)
938
                item.angle = angle
939
                item.setPlainText(text)
940
                self.addTextItemToScene(item)
941
        except Exception as ex:
942
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
943
            self.addMessage(MessageType.Error, message)
944

    
945
    '''
946
        @brief  draw unknown items 
947
        @author humkyung
948
        @date   2018.06.12
949
        @history    2018.06.14  Jeongwoo    Change method to add unknown item
950
                    2018.06.18  Jeongwoo    Add connect on unknown item
951
                                            Add [transfer] for using pyqtSignal
952
    '''
953
    def drawUnknownItems(self):
954
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem 
955
        from EngineeringLineItem import QEngineeringLineItem
956
        from EngineeringUnknownItem import QEngineeringUnknownItem
957

    
958
        try:
959
            docData = AppDocData.instance()
960
            project = docData.getCurrentProject()
961
            windowSize = docData.getSlidingWindowSize()
962
            thickness = int(windowSize[1])
963

    
964
            diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(self.path))
965
            if os.path.isfile(diffFilePath):
966
                imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1]
967

    
968
                lines = [item for item in self.graphicsView.scene.items() if (type(item) is QEngineeringLineItem)]
969
                for line in lines:
970
                    line.drawToImage(imgDiff, 255, thickness)
971
                cv2.imwrite(diffFilePath, imgDiff)
972

    
973
                imgNot = np.ones(imgDiff.shape, np.uint8)
974
                cv2.bitwise_not(imgDiff, imgNot)
975
                imgNot = cv2.dilate(imgNot, np.ones((8,8), np.uint8))
976

    
977
                image, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
978
                for contour in contours:
979
                    [x, y, w, h] = cv2.boundingRect(contour)
980

    
981
                    # remove too small one
982
                    if (w < 10 or h < 10): continue
983

    
984
                    # create unknown item
985
                    epsilon = cv2.arcLength(contour, True)*0.001
986
                    approx = cv2.approxPolyDP(contour, epsilon, True)
987
                    approx = [pt[0] for pt in approx]
988
                    item = QEngineeringUnknownItem(approx)
989
                    item.transfer.onRemoved.connect(self.itemRemoved)
990
                    self.addUnknownItemToScene(item)
991
                    # up to here
992

    
993
                notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(self.path))
994
                cv2.imwrite(notFilePath, imgNot)
995
            else:
996
                message = 'can\'t found {}'.format(diffFilePath)
997
                self.addMessage(MessageType.Normal, message)
998
        except Exception as ex:
999
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1000
            self.addMessage(MessageType.Error, message)
1001

    
1002
    '''
1003
        @brief      load recognition result
1004
        @author     humkyung
1005
        @date       2018.04.??
1006
        @history    humkyung 2018.01.12 parse originalpoint and connectionpoint
1007
                    Jeongwoo 2018.04.17 add QGraphicItem with Rotated text
1008
                    Jeongwoo 2018.04.23 Change to Draw texts on QEngineeringTextItem
1009
                    humkyung 2018.04.23 connect item remove slot to result tree
1010
                    Jeongwoo 2018.04.25 Add if state with QEngineeringNoteItem
1011
                    Jeongwoo 2018.04.26 Change method to create TextItem object with TextItemFactory
1012
                    Jeongwoo 2018.05.03 Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1013
                    Jeongwoo 2018.05.29 Change method name / Change method to add item / Add Line item
1014
                    Jeongwoo 2018.05.30 Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol) / Change method name / Change XML NODE NAMES
1015
                    Jeongwoo 2018.06.12 Add LineNoTextItem from LINE_NO
1016
                    Jeongwoo 2018.06.14 Add UnknownItem from UNKNOWN
1017
                    Jeongwoo 2018.06.18 Update Scene after all item added
1018
                                        Add connect on unknown item
1019
                                        Add [transfer] for using pyqtSignal
1020
                    kyouho  2018.07.12  Add line property logic
1021
    '''
1022
    def loadRecognitionResultFromXml(self, xmlPath):
1023
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
1024

    
1025
        try:
1026
            symbols = []
1027

    
1028
            xml = parse(xmlPath)
1029
            root = xml.getroot()
1030
            for symbol in root.iter('SYMBOL'):
1031
                item = SymbolSvgItem.fromXml(symbol)
1032
                if item[0] is not None:
1033
                    item[0].transfer.onRemoved.connect(self.itemRemoved)
1034
                    symbols.append(item)
1035
                else:
1036
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
1037
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
1038
                    angle = float(symbol.find('ANGLE').text)
1039
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
1040
                    item.isSymbol = True
1041
                    item.angle = angle
1042
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
1043
                    self.graphicsView.scene.addItem(item)
1044

    
1045
            # set symbol's owner
1046
            childItems = [item for item in symbols if item[1] is not None]
1047
            for item in childItems:
1048
                matches = [param for param in symbols if str(param[0].uid) == item[1]]
1049
                if len(matches) == 1:
1050
                    item[0].owner = matches[0][0]
1051
            # up to here
1052
           
1053
            for item in symbols:
1054
                self.addSvgItemToScene(item[0])
1055

    
1056
            docData = AppDocData.instance()
1057
            configs = docData.getConfigs('Line No', 'Delimiter')
1058
            delimiter = configs[0].value if 1 == len(configs) else '-'
1059
            lineNoconfigs = docData.getConfigs('Line No', 'Configuration')
1060
            #
1061
            linePropertyData = {}
1062
            linePropertyData['NominalDiameter'] = docData.getNomialPipeSizeData(True)
1063
            linePropertyData['FluidCode'] = docData.getCodeTable('FluidCode', True)
1064
            linePropertyData['UnitNumber'] = docData.getCodeTable('UnitNumber', True)
1065
            linePropertyData['PnIDNumber'] = docData.getCodeTable('PnIDNumber', True)
1066
            linePropertyData['PipingMaterialsClass'] = docData.getCodeTable('PipingMaterialsClass', True)
1067
            linePropertyData['InsulationPurpose'] = docData.getCodeTable('InsulationPurpose', True)
1068
            #
1069
            configs = docData.getConfigs('Line No Tag Rule', 'Tag Seq No')
1070
            tagSeqNoPattern = configs[0].value if 1 == len(configs) else None
1071

    
1072
            # parse texts
1073
            for text in root.iter('ATTRIBUTE'):
1074
                location = text.find('LOCATION').text if text.find('LOCATION') is not None else '0,0'
1075
                x = float(location.split(',')[0])
1076
                y = float(location.split(',')[1])
1077
                width = float(text.find('WIDTH').text) if text.find('WIDTH') is not None else 0
1078
                height = float(text.find('HEIGHT').text) if text.find('HEIGHT') is not None else 0
1079
                angle = float(text.find('ANGLE').text) if text.find('ANGLE') is not None else 0
1080
                value = text.find('VALUE').text
1081
                uid = text.find('UID')
1082
                attributeValue = text.find('ATTRIBUTEVALUE')
1083
                name = text.find('NAME').text
1084
                if name == 'TEXT':
1085
                    item = TextItemFactory.instance().createTextItem(value, delimiter, lineNoconfigs, linePropertyData, tagSeqNoPattern)
1086
                    if item is not None:
1087
                        item.loc = (x, y)
1088
                        item.size = (width, height)
1089
                        item.angle = angle
1090
                        item.setPlainText(value)
1091
                        item.transfer.onRemoved.connect(self.itemRemoved)
1092
                        self.addTextItemToScene(item)
1093
                        if uid is not None and attributeValue is not None:
1094
                            item.uid = uid.text
1095
                            item.attribute = attributeValue.text
1096
                elif name == 'NOTE':
1097
                    item = TextItemFactory.instance().createTextItem(value)
1098
                    if item is not None:
1099
                        item.loc = (x, y)
1100
                        item.size = (width, height)
1101
                        item.angle = angle
1102
                        item.setPlainText(value)
1103
                        self.addTextItemToScene(item)
1104
                        if uid is not None:
1105
                            item.uid = uid.text
1106
                
1107

    
1108
            for lineNo in root.iter('LINE_NO'):
1109
                location = lineNo.find('LOCATION').text if lineNo.find('LOCATION') is not None else '0,0'
1110
                x = float(location.split(',')[0])
1111
                y = float(location.split(',')[1])
1112
                width = float(lineNo.find('WIDTH').text) if lineNo.find('WIDTH') is not None else 0
1113
                height = float(lineNo.find('HEIGHT').text) if lineNo.find('HEIGHT') is not None else 0
1114
                angle = float(lineNo.find('ANGLE').text) if lineNo.find('ANGLE') is not None else 0
1115
                text = lineNo.find('TEXT').text
1116

    
1117
                item = TextItemFactory.instance().createTextItem(text, delimiter, lineNoconfigs, linePropertyData, tagSeqNoPattern)
1118
                if item is not None:
1119
                    item.loc = (x, y)
1120
                    item.size = (width, height)
1121
                    item.angle = angle
1122
                    item.setPlainText(text)
1123
                    item.transfer.onRemoved.connect(self.itemRemoved)
1124
                    self.addTextItemToScene(item)
1125

    
1126
            for line in root.iter('LINE'):
1127
                item = QEngineeringLineItem.fromXml(line)
1128
                item.transfer.onRemoved.connect(self.itemRemoved)
1129
                if item: self.addLineItemToScene(item)
1130

    
1131
            for unknown in root.iter('UNKNOWN'):
1132
                item = QEngineeringUnknownItem.fromXml(unknown)
1133
                item.transfer.onRemoved.connect(self.itemRemoved)
1134
                if item is not None:
1135
                    item.transfer.onRemoved.connect(self.itemRemoved)
1136
                    self.addUnknownItemToScene(item)
1137
            # up to here
1138

    
1139

    
1140
            # set symbol's connectItem
1141
            from EngineeringConnectorItem import QEngineeringConnectorItem
1142
            connectors = [item for item in self.graphicsView.scene.items() if type(item) == QEngineeringConnectorItem and item.connectedItem is not None]
1143
            for connector in connectors:
1144
                # 처음에는 UID가 connectedItem에 String으로 들어가있기 때문에
1145
                connector.connectedItem = self.graphicsView.findItemByUid(connector.connectedItem)
1146

    
1147
            symbols = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and len(item.attrs) > 0]
1148
            for symbol in symbols:
1149
                # 처음에는 attrs의 uid가 connectedItem에 String으로 들어가있기 때문에
1150
                for index in range(len(symbol.attrs)):
1151
                    symbol.attrs[index] = self.graphicsView.findItemByUid(symbol.attrs[index])
1152
                        
1153

    
1154
            # Update Scene
1155
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1156
        except Exception as ex:
1157
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1158
            self.addMessage(MessageType.Error, message)
1159

    
1160
    '''
1161
        @brief      Remove added item on same place and Add GraphicsItem
1162
        @author     Jeongwoo
1163
        @date       2018.05.25
1164
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
1165
                    2018.06.18  Jeongwoo    Set Z-index
1166
    '''
1167
    def addSvgItemToScene(self, svgItem):
1168
        '''
1169
        svgRect = svgItem.boundingRectOnScene()
1170
        items = self.graphicsView.scene.items(svgRect)
1171
        if items is not None:
1172
            for item in items:
1173
                if issubclass(type(item), SymbolSvgItem):
1174
                    itemRect = item.boundingRectOnScene()
1175
                    if itemRect.topLeft() == svgRect.topLeft() and itemRect.size() == svgRect.size(): # Equal
1176
                        item.deleteSvgItemFromScene()
1177
        '''
1178
        svgItem.setZValue(10)
1179
        svgItem.addSvgItemToScene(self.graphicsView.scene)
1180
        
1181
    '''
1182
        @brief      Remove added item on same place and Add GraphicsItem
1183
        @author     Jeongwoo
1184
        @date       2018.05.25
1185
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
1186
                    2018.06.05  Jeongwoo    Remove Size condition
1187
                    2018.06.18  Jeongwoo    Set Z-index
1188
    '''
1189
    def addTextItemToScene(self, textItem):
1190
        textRect = textItem.boundingRectOnScene()
1191
        items = self.graphicsView.scene.items(textRect)
1192
        if items is not None:
1193
            for item in items:
1194
                if issubclass(type(item), QEngineeringTextItem):
1195
                    itemRect = item.boundingRectOnScene()
1196
                    if itemRect.topLeft() == textRect.topLeft() and item.text() == textItem.text(): # Equal
1197
                        item.deleteTextItemFromScene()
1198
        textItem.setZValue(10)
1199
        textItem.addTextItemToScene(self.graphicsView.scene)
1200
        
1201
    '''
1202
        @brief      Remove added item on same place and Add GraphicsItem
1203
        @author     Jeongwoo
1204
        @date       2018.05.29
1205
        @history    2018.06.18  Jeongwoo    Set Z-index
1206
    '''
1207
    def addLineItemToScene(self, lineItem):
1208
        '''
1209
        lineRect = lineItem.boundingRectOnScene()
1210
        items = self.graphicsView.scene.items(lineRect)
1211
        if items is not None:
1212
            for item in items:
1213
                if issubclass(type(item), QEngineeringLineItem):
1214
                    itemRect = item.boundingRectOnScene()
1215
                    if item.startPoint() == lineItem.startPoint() and item.endPoint() == lineItem.endPoint(): # Equal
1216
                        item.deleteLineItemFromScene()
1217
        lineItem.setZValue(10)
1218
        '''
1219
        lineItem.addLineItemToScene(self.graphicsView.scene)
1220

    
1221
    '''
1222
        @brief      Remove added item on same place and Add Unknown Item
1223
        @author     Jeongwoo
1224
        @date       2018.06.14
1225
        @history    2018.06.18  Jeongwoo    Set Z-index
1226
    '''
1227
    def addUnknownItemToScene(self, unknownItem):
1228
        try:
1229
            unknownRect = unknownItem.boundingRectOnScene()
1230
            items = self.graphicsView.scene.items(unknownRect)
1231
            if items is not None:
1232
                for item in items:
1233
                    if issubclass(type(item), QEngineeringUnknownItem):
1234
                        itemRect = item.boundingRectOnScene()
1235
                        if itemRect.topLeft() == unknownRect.topLeft() and itemRect.size() == unknownRect.size(): # Equal
1236
                            item.deleteUnknownItemFromScene()
1237
            unknownItem.setZValue(-10)
1238
            unknownItem.addUnknownItemToScene(self.graphicsView.scene)
1239
        except Exception as ex:
1240
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1241
            self.addMessage(MessageType.Error, message)
1242

    
1243
    '''
1244
        @brief      generate output xml file
1245
        @author     humkyung
1246
        @date       2018.04.23
1247
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
1248
    '''
1249
    def generateOutput(self):
1250
        import XmlGenerator as xg
1251
        from QEngineeringEquipmentItem import QEngineeringEquipmentItem
1252

    
1253
        if not self.graphicsView.hasImage():
1254
            self.showImageSelectionMessageBox()
1255
            return
1256

    
1257
        try:
1258
            docData = AppDocData.instance()
1259

    
1260
            docData.lines.clear()
1261
            docData.lines = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem and item.owner is None]
1262

    
1263
            docData.symbols.clear()
1264
            docData.symbols = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and item.owner is None]
1265

    
1266
            docData.equipments.clear()
1267
            for item in self.graphicsView.scene.items():
1268
                if type(item) is QEngineeringEquipmentItem:
1269
                    docData.equipments.append(item)
1270

    
1271
            docData.imgOutput = np.ones((docData.imgHeight, docData.imgWidth), np.uint8)*255
1272
            xg.writeOutputXml(docData.imgName, docData.imgWidth, docData.imgHeight) # TODO: check
1273
            project = docData.getCurrentProject()
1274
            cv2.imwrite(os.path.join(project.getTempPath() , 'OUTPUT.png') , docData.imgOutput)
1275
        except Exception as ex:
1276
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1277
            self.addMessage(MessageType.Error, message)
1278
            
1279
if __name__ == '__main__':
1280
    '''
1281
    diffFilePath = 'd:/Projects/DTIPID/PC-K/Temp/diff_PC-K-2203_P1_800DPI.png'
1282
    imgDiff = cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY)
1283
    ret, mask = cv2.threshold(imgDiff, 127, 255, cv2.THRESH_BINARY)
1284
    imgDiff = cv2.bitwise_not(mask)
1285
    imgDiff = cv2.dilate(imgDiff, np.ones((8, 8), np.uint8))
1286
    image, contours, hierarchy = cv2.findContours(imgDiff, cv2.RETR_LIST , cv2.CHAIN_APPROX_SIMPLE)
1287
    for contour in contours:
1288
        epsilon = cv2.arcLength(contour, True)*0.01
1289
        approx = cv2.approxPolyDP(contour, epsilon, True)
1290
        for i in range(0, len(approx)-1):
1291
            cv2.line(imgDiff, (approx[i][0][0], approx[i][0][1]), (approx[i+1][0][0], approx[i+1][0][1]), 255, 1)
1292

1293
    notFilePath = 'd:/Projects/DTIPID/PC-K/Temp/not_PC-K-2203_P1_800DPI.png'
1294
    cv2.imwrite(notFilePath, imgDiff)
1295
    '''
1296

    
1297
    from ProjectDialog import Ui_Dialog
1298
    from App import App 
1299

    
1300
    app = App(sys.argv)
1301
    try:
1302
        dlg = Ui_Dialog()
1303
        selectedProject = dlg.showDialog()
1304
        if selectedProject is not None:
1305
            AppDocData.instance().setCurrentProject(selectedProject)
1306
            app._mainWnd = MainWindow.instance()
1307
            app._mainWnd.show()
1308
    except Exception as ex:
1309
        print('에러가 발생했습니다.\n', ex)
1310

    
1311
    sys.exit(app.exec_())