프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / MainWindow.py @ eb71581d

이력 | 보기 | 이력해설 | 다운로드 (58.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 EngineeringTextItem import QEngineeringTextItem
35
from QEngineeringLineNoTextItem import QEngineeringLineNoTextItem
36
from QEngineeringNoteItem import QEngineeringNoteItem
37
from QEngineeringSizeTextItem import QEngineeringSizeTextItem
38
from EngineeringUnknownItem import QEngineeringUnknownItem
39
from QEngineeringEquipmentItem import QEngineeringEquipmentItem
40
from AppDocData import *
41
import SymbolTreeWidget, SymbolPropertyTableWidget
42
import SymbolEditorDialog
43
import ItemTreeWidget
44
import ItemPropertyTableWidget
45
from TextItemFactory import TextItemFactory
46

    
47
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane):
48
    addMessage = pyqtSignal(Enum, str)
49

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

    
65
        self.lastClickedCheckableAction = None
66

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

    
72
        self.lineComboBox = QComboBox(self.toolBar)
73
        lineTypes = docData.getLineTypes()
74
        for lineType in lineTypes:
75
            self.lineComboBox.addItem(lineType)
76
        self.lineComboBox.currentIndexChanged.connect(self.onLineTypeChanged)
77

    
78
        self.toolBar.insertWidget(self.actionValidate, self.lineComboBox)
79
        self.toolBar.insertSeparator(self.actionValidate)
80
        self.graphicsView = QtImageViewer.QtImageViewer(self)
81
        self.graphicsView.setParent(self.centralwidget)
82
        self.graphicsView.useDefaultCommand() ##### USE DEFAULT COMMAND
83

    
84
        self.verticalLayout.addWidget(self.graphicsView)
85

    
86
        # Add Custom TreeWidget
87
        self.dirTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
88
        self.dirTreeWidget.header().hide()
89
        self.symbolTabVerticalLayout.addWidget(self.dirTreeWidget)
90

    
91
        # Add Custom Property TableWidget
92
        self.propertyTableWidget = SymbolPropertyTableWidget.QSymbolPropertyTableWidget()
93
        self.symbolTabVerticalLayout.addWidget(self.propertyTableWidget)
94
        self.dirTreeWidget.singleClicked.connect(self.propertyTableWidget.getClickedSymbol)
95
        # add splitter widget
96
        splitter = QSplitter(Qt.Vertical)
97
        splitter.addWidget(self.dirTreeWidget)
98
        splitter.addWidget(self.propertyTableWidget)
99
        self.symbolTabVerticalLayout.addWidget(splitter)
100
        # up to here
101

    
102
        # Add Custom Result Tree Widget (Symbol Explorer)
103
        self.resultTreeWidget = ItemTreeWidget.QItemTreeWidget(self.graphicsView)
104
        self.resultTreeWidget.header().hide()
105
        self.symbolExplorerVerticalLayout.addWidget(self.resultTreeWidget)
106

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

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

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

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

    
187
            for item in result.items():
188
                itemName = str(item[0])
189
                itemSuccessCount = str(item[1][0])
190
                itemFailUidList = item[1][1]
191
                resultStr += "\r\n" + itemName + " Save Count : " + itemSuccessCount
192
                if len(itemFailUidList) > 0:
193
                    resultStr += "\r\n" + itemName + " Error List(UID)"
194
                    for uid in itemFailUidList:
195
                        resultStr += "\r\n" + uid
196

    
197
            QMessageBox.about(self.graphicsView, "알림", resultStr)
198

    
199

    
200
    '''
201
        @brief      refresh resultPropertyTableWidget
202
        @author     kyouho
203
        @date       2018.07.19
204
    '''
205
    def refreshResultPropertyTableWidget(self):
206
        items = self.graphicsView.scene.selectedItems()
207
        if len(items) == 1:
208
            self.resultPropertyTableWidget.onSymbolClicked(items[0])
209

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

    
232
                        from PyQt5 import QtGui
233
                        cellItem = QTableWidgetItem('')
234
                        icon = QtGui.QIcon()
235
                        icon.addPixmap(QtGui.QPixmap(":/newPrefix/doubleclick.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
236
                        cellItem.setIcon(icon)
237
                        self.resultPropertyTableWidget.setItem(row, 1, cellItem)
238
    
239
    '''
240
        @brief  add message listwidget
241
        @author humkyung
242
        @date   2018.07.31
243
    '''
244
    def onAddMessage(self, messageType, message):
245
        from AppDocData import MessageType
246

    
247
        try:
248
            current = QDateTime.currentDateTime()
249

    
250
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
251
            if messageType == MessageType.Error:
252
                item.setBackground(Qt.red)
253

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

    
258
    '''
259
        @brief      clear log
260
        @author     humkyung
261
        @date       2018.08.01
262
    '''
263
    def onClearLog(self):
264
        self.listWidgetLog.clear()
265

    
266
    '''
267
        @brief      Area Zoom
268
        @author     Jeongwoo
269
        @date       2018.06.27
270
    '''
271
    def areaZoom(self, action):
272
        if self.actionZoom.isChecked():
273
            self.graphicsView.command = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
274

    
275
    '''
276
        @brief      Fit Window
277
        @author     Jeongwoo
278
        @date       2018.06.27
279
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
280
    '''
281
    def fitWindow(self, action):
282
        self.graphicsView.useDefaultCommand()
283
        self.graphicsView.zoomImageInit()
284

    
285
    '''
286
        @brief      convert to selected pdf to image
287
        @author     humkyung 
288
        @date       2018.07.09
289
    '''
290
    def onConvertPDFToImage(self):
291
        try:
292
            filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)) , 'bin64', 'PDF_TO_IMAGE.exe')
293
            os.system(filePath)
294
        except Exception as ex:
295
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
296

    
297
    '''
298
        @brief      selection changed
299
        @author     humkyung
300
        @date       2018.06.27
301
        @history    humkung 2018.07.08 call tree widget's findItem
302
    '''
303
    def onSelectionChanged(self):
304
        for item in self.graphicsView.scene.selectedItems():
305
            self.resultTreeWidget.findItem(item)
306
            self.resultPropertyTableWidget.showItemProperty(item)
307
        
308
    '''
309
        @brief      Initialize scene and ResultTreeWidget
310
        @author     Jeongwoo
311
        @date       2018.06.14
312
    '''
313
    def initializeScene(self, action):
314
        if not self.graphicsView.hasImage():
315
            self.actionEquipment.setChecked(False)
316
            self.showImageSelectionMessageBox()
317
            return
318

    
319
        items = self.graphicsView.scene.items()
320
        for item in items:
321
            if type(item) is not QGraphicsPixmapItem:
322
                self.graphicsView.scene.removeItem(item)
323
                
324
        if self.path is not None:
325
            baseName = os.path.basename(self.path)
326
            self.resultTreeWidget.setCurrentPID(baseName)
327

    
328
    '''
329
        @brief      Manage Checkable Action statement
330
        @author     Jeongwoo
331
        @date       2018.05.10
332
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
333
    '''
334
    def actionGroupTriggered(self, action):
335
        if self.graphicsView.command is not None:
336
            self.graphicsView.useDefaultCommand()
337
        if self.lastClickedCheckableAction is not None and self.lastClickedCheckableAction == action and action.isChecked():
338
            action.setChecked(False)
339
            self.lastClickedCheckableAction = None
340
        elif action.isCheckable():
341
            self.lastClickedCheckableAction = action
342
        else:
343
            if self.lastClickedCheckableAction is not None:
344
                self.lastClickedCheckableAction.setChecked(False)
345
            self.lastClickedCheckableAction = None
346

    
347
    '''
348
        @brief      Create Equipment
349
        @author     Jeongwoo
350
        @date       18.05.03
351
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
352
    '''
353
    def createEquipment(self):
354
        if not self.graphicsView.hasImage():
355
            self.actionEquipment.setChecked(False)
356
            self.showImageSelectionMessageBox()
357
            return
358
        if self.actionEquipment.isChecked():
359
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.resultTreeWidget, self.dirTreeWidget)
360
        else:
361
            self.graphicsView.useDefaultCommand()
362

    
363

    
364
    '''
365
        @brief      Create Nozzle
366
        @author     Jeongwoo
367
        @date       2018.05.03
368
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
369
    '''
370
    def createNozzle(self):
371
        if not self.graphicsView.hasImage():
372
            self.actionNozzle.setChecked(False)
373
            self.showImageSelectionMessageBox()
374
            return
375
        if self.actionNozzle.isChecked():
376
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.resultTreeWidget, self.dirTreeWidget)
377
        else:
378
            self.graphicsView.useDefaultCommand()
379

    
380
    '''
381
        @brief      Area OCR
382
        @author     Jeongwoo
383
        @date       18.04.18
384
        @history    2018.05.02  Jeongwoo    Change graphicsView.command by actionOCR checked state
385
                                            Show MessageBox when imageviewer doesn't have image
386
    '''
387
    def areaOcr(self):
388
        if not self.graphicsView.hasImage():
389
            self.actionOCR.setChecked(False)
390
            self.showImageSelectionMessageBox()
391
            return
392

    
393
        if self.actionOCR.isChecked():
394
            cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView)
395
            cmd.onSuccess.connect(self.onRecognizeText)
396
            self.graphicsView.command = cmd
397
        else:
398
            self.graphicsView.useDefaultCommand()
399
    
400
    '''
401
        @brief      show text recognition dialog
402
        @author     humkyung
403
        @date       2018.08.08
404
    '''
405
    def onRecognizeText(self, x, y, width, height):
406
        from OcrResultDialog import QOcrResultDialog
407

    
408
        try:
409
            image = self.graphicsView.image().copy(x, y, width, height)
410
            dialog = QOcrResultDialog(self.graphicsView, image, QRectF(x, y, width, height))
411
            (isAccept, textInfoList) = dialog.showDialog()
412
            if isAccept:
413
                if textInfoList is not None and len(textInfoList) > 0:
414
                    docData = AppDocData.instance()
415
                    configs = docData.getConfigs('Line No', 'Delimiter')
416
                    delimiter = configs[0].value if 1 == len(configs) else '-'
417
                    lineNoconfigs = docData.getConfigs('Line No', 'Configuration')
418
                    for textInfo in textInfoList:
419
                        x = textInfo.getX()
420
                        y = textInfo.getY()
421
                        angle = textInfo.getAngle()
422
                        text = textInfo.getText()
423
                        width = textInfo.getW()
424
                        height = textInfo.getH()
425
                        item = TextItemFactory.instance().createTextItem(text, delimiter, lineNoconfigs)
426
                        if item is not None:
427
                            item.loc = (x, y)
428
                            item.size = (width, height)
429
                            item.angle = angle
430
                            item.setPlainText(text)
431
                            item.setDefaultTextColor(Qt.blue)
432
                            item.addTextItemToScene(self.graphicsView.scene)
433
                        else:
434
                            message = 'error occured({}) in {}:{}'.format('텍스트 생성에 실패했습니다.', sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
435
                            self.addMessage.emit(MessageType.Normal, message)
436
                else:
437
                    QMessageBox.about(self.graphicsView, "알림", "텍스트 검출 실패")
438
        except Exception as ex:
439
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
440
            self.addMessage.emit(MessageType.Error, message)
441

    
442
    '''
443
        @brief  area configuration
444
    '''
445
    def areaConfiguration(self):
446
        from ConfigurationAreaDialog import QConfigurationAreaDialog
447

    
448
        self.dlgConfigurationArea = QConfigurationAreaDialog(self)
449
        self.dlgConfigurationArea.show()
450
        self.dlgConfigurationArea.exec_()
451

    
452
    '''
453
        @brief  configuration
454
    '''
455
    def configuration(self):
456
        from ConfigurationDialog import QConfigurationDialog
457

    
458
        self.dlgConfiguration = QConfigurationDialog(self)
459
        self.dlgConfiguration.show()
460
        self.dlgConfiguration.exec_()
461

    
462
    '''
463
        @brief  show nominal diameter dialog 
464
        @author humkyung
465
        @date   2018.06.28
466
    '''
467
    def onShowCodeTable(self):
468
        from CodeTableDialog import QCodeTableDialog
469

    
470
        dlg = QCodeTableDialog(self)
471
        dlg.exec_()
472

    
473
    '''
474
        @brief  show HMB data
475
        @author humkyung
476
        @date   2018.07.11
477
    '''
478
    def onHMBData(self):
479
        from HMBDialog import QHMBDialog
480

    
481
        dlg = QHMBDialog(self)
482
        dlg.show()
483
        dlg.exec_()
484

    
485
    '''
486
        @brief  show line data list 
487
        @author humkyung
488
        @date   2018.05.03
489
    '''
490
    def showItemDataList(self):
491
        from ItemDataExportDialog import QItemDataExportDialog
492

    
493
        self.dlgLineDataList = QItemDataExportDialog(self)
494
        self.dlgLineDataList.exec_()
495

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

    
516
    '''
517
        @brief      Open image drawing file and then display it
518
        @author     humkyung
519
        @date       2018.??.??
520
        @history    18.04.23 Jeongwoo    Add AppDocData.instance().setCurrentPidSource
521
                    18.04.23 Jeongwoo    Add Store Set Current Pid Image on AppDocData
522
                    18.05.02 Jeongwoo    Add useDefaultCommand()
523
                    humkyung 2018.05.24 load recognition result file if exists
524
                    Jeongwoo 2018.05.29 load data on xml if xml file exist
525
    '''
526
    def onOpenImageDrawing(self, MainWindow):
527
        from Drawing import Drawing
528

    
529
        try:
530
            appDocData = AppDocData.instance()
531
            project = appDocData.getCurrentProject()
532

    
533
            self.path = self.graphicsView.loadImageFromFile(project.getDrawingFilePath())
534
            if os.path.isfile(self.path):
535
                self.graphicsView.useDefaultCommand()
536

    
537
                appDocData.setImgFilePath(self.path)
538
                appDocData.activeDrawing = Drawing(appDocData.imgName)
539
                appDocData.setCurrentPidSource(Image.open(self.path))
540
                self.resultTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
541

    
542
                ## Load data on xml
543
                path = os.path.join(appDocData.getCurrentProject().getTempPath(), appDocData.imgName + '.xml')
544
                if os.path.isfile(path): self.loadRecognitionResultFromXml(path)
545
        except Exception as ex:
546
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
547
            self.addMessage.emit(MessageType.Error, message)
548

    
549
        return self.path
550

    
551
    '''
552
        @brief  visible/invisible image drawing
553
        @author humkyung
554
        @date   2018.06.25
555
    '''
556
    def onViewImageDrawing(self, isChecked):
557
        for item in self.graphicsView.scene.items():
558
            if type(item) is QGraphicsPixmapItem:
559
                item.setVisible(isChecked)
560
                break
561

    
562
    '''
563
        @brief  visible/invisible Text 
564
        @author humkyung
565
        @date   2018.06.28
566
    '''
567
    def onViewText(self, isChecked):
568
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
569
        for item in selected:
570
            item.setVisible(isChecked)
571

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

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

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

    
602
    '''
603
        @brief  create a symbol
604
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
605
                                            Add SymbolSvgItem
606
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
607
                                            Change method to make svg and image path
608
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
609
    '''
610
    def createSymbol(self):
611
        cmd = FenceCommand.FenceCommand(self.graphicsView)
612
        cmd.onSuccess.connect(self.onAreaSelected)
613
        self.graphicsView.command = cmd
614
        QApplication.setOverrideCursor(Qt.CrossCursor)
615

    
616
    '''
617
        @brief      show SymbolEditorDialog with image selected by user
618
        @author     humkyung
619
        @date       2018.07.20
620
    '''
621
    def onAreaSelected(self, x, y, width, height):
622
        try:
623
            image = self.graphicsView.image()
624
            if image is not None:
625
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height), AppDocData.instance().getCurrentProject())
626
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
627
                self.dirTreeWidget.initDirTreeWidget()
628
                if isAccepted:
629
                    if isImmediateInsert:
630
                        svgPath = newSym.getSvgFileFullPath()
631
                        img = cv2.imread(newSym.getImageFileFullPath(), 1)
632
                        w, h = (0, 0)
633
                        if len(img.shape[::-1]) == 2:
634
                            w, h = img.shape[::-1]
635
                        else:
636
                            _chan, w, h = img.shape[::-1]
637
                        svg = SymbolSvgItem(svgPath)
638
                        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)
639

    
640
                        svg.transfer.onRemoved.connect(self.resultTreeWidget.itemRemoved)
641
                        svg.addSvgItemToScene(self.graphicsView.scene)
642
                        for connector in svg.connectors:
643
                            self.graphicsView.scene.addItem(connector)
644
        finally:
645
            self.graphicsView.useDefaultCommand()
646
            QApplication.restoreOverrideCursor()
647
    
648
    '''
649
        @brief      create a line
650
        @author     humkyung
651
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
652
    '''
653
    def onPlaceLine(self):        
654
        if not self.graphicsView.hasImage():
655
            self.actionLine.setChecked(False)
656
            self.showImageSelectionMessageBox()
657
            return
658

    
659
        self.actionLine.setChecked(True)
660
        if not hasattr(self.actionLine, 'tag'):
661
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
662
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
663
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
664

    
665
        self.graphicsView.command = self.actionLine.tag
666

    
667
    '''
668
        @brief      add created lines to scene
669
        @author     humkyung
670
        @date       2018.07.23
671
    '''
672
    def onLineCreated(self):
673
        from EngineeringConnectorItem import QEngineeringConnectorItem
674

    
675
        try:
676
            count = len(self.actionLine.tag._polyline._vertices)
677
            if count > 1:
678
                items = []
679

    
680
                lineType = self.lineComboBox.currentText()
681
                for index in range(count - 1):
682
                    start = self.actionLine.tag._polyline._vertices[index]
683
                    end  = self.actionLine.tag._polyline._vertices[index + 1]
684
                    
685
                    lineItem = QEngineeringLineItem(vertices=[start, end])
686
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
687
                    lineItem.lineType = lineType
688
                    if items:
689
                        lineItem.connectIfPossible(items[-1], 5)
690
                    else:
691
                        pt = lineItem.startPoint()
692
                        selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
693
                        if selected is not None and type(selected) is QEngineeringConnectorItem:
694
                            lineItem.connectIfPossible(selected.parent, 5)
695
                    
696
                    items.append(lineItem)
697
                    self.graphicsView.scene.addItem(lineItem)
698

    
699
                pt = items[-1].endPoint()
700
                selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
701
                if selected is not None and type(selected) is QEngineeringConnectorItem:
702
                    items[-1].connectIfPossible(selected.parent, 5)
703
        finally:
704
            self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
705
            self.actionLine.tag.reset()
706

    
707
    '''
708
        @brief      refresh scene
709
        @author     humkyung
710
        @date       2018.07.23
711
    '''
712
    def onCommandRejected(self, cmd):
713
        try:
714
            if cmd is self.actionLine.tag:
715
                self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
716
                self.graphicsView.scene.update()
717
                self.actionLine.tag.reset()
718

    
719
                self.actionLine.setChecked(False)
720
        finally:
721
            self.graphicsView.useDefaultCommand()
722
     
723
    '''
724
        @brief      restore to default command when user press Escape key
725
        @author     humkyung 
726
        @date       2018.08.09
727
    '''
728
    def keyPressEvent(self, event):
729
        try:
730
            if event.key() == Qt.Key_Escape:
731
                checked = self.actionGroup.checkedAction()
732
                if checked:
733
                    checked.setChecked(False)
734
                    self.graphicsView.useDefaultCommand()
735

    
736
            QMainWindow.keyPressEvent(self, event)
737
        except Exception as ex:
738
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
739
            self.addMessage.emit(MessageType.Error, message)
740
       
741
    '''
742
        @brief      recognize symbol and text
743
        @author     humkyung
744
        @date       2018.04.??
745
        @history    2018.04.16  humkyung    execute line no tracing
746
                    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
747
                    2018.05.25  Jeongwoo    Add parameter on QRecognitionDialog.__init__() and Move thread to QRecognitionDialog
748
                                            Remove codes below if self.dlg.isAccepted == True
749
                    2018.05.29  Jeongwoo    Remove connects and comments
750
    '''
751
    def recognize(self, MainWindow):
752
        from QRecognitionDialog import QRecognitionDialog
753

    
754
        if not self.graphicsView.hasImage():
755
            self.showImageSelectionMessageBox()
756
            return
757

    
758
        try:
759
            self.onClearLog()
760
            self.dlg = QRecognitionDialog(self, self.path)
761
            self.dlg.exec_()
762
            if self.dlg.isAccepted == True:
763
                '''DO NOTHING'''
764
        except Exception as ex:
765
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
766
            self.addMessage.emit(MessageType.Error, message)
767

    
768
    '''
769
        @brief
770
        @date       2018.05.25
771
        @author     Jeongwoo
772
    '''
773
    def itemRemoved(self, item):
774
        try:
775
            self.resultTreeWidget.itemRemoved(item)
776
            if item.scene() is not None: item.scene().removeItem(item)
777
        except Exception as ex:
778
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
779

    
780
    '''
781
        @brief      recognize line
782
        @author     humkyung
783
        @date       2018.04.19
784
        @history    Jeongwoo 2018.04.26 Variable name changed (texts → lineNos)
785
                                        TextItem type changed (QEngineeringTextItem → QEngineeringLineNoTextItem)
786
                    humkyung 2018.04.26 remove small objects before recognizing line
787
                    Jeongwoo 2018.05.02 Show MessageBox when imageviewer doesn't have image
788
                    Jeongwoo 2018.05.25 Move codes about LineDetector
789
                    humkyung 2018.06.17 show progress dialog
790
    '''
791
    def recognizeLine(self, MainWindow):
792
        from LineNoTracer import LineNoTracer
793
        from QConnectAttrDialog import QConnectAttrDialog
794

    
795
        if not self.graphicsView.hasImage():
796
            self.showImageSelectionMessageBox()
797
            return
798

    
799
        try:
800
            self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView)
801
            self.dlgConnectAttr.exec_()
802

    
803
            # construct line no item
804
            docData = AppDocData.instance()
805
            for lineno in docData.lineNos:
806
                item = self.resultTreeWidget.addTreeItem(self.resultTreeWidget.root, lineno)
807
                connectedItems = lineno.getConnectedItems()
808
                for connectedItem in connectedItems:
809
                    if issubclass(type(connectedItem), SymbolSvgItem): self.resultTreeWidget.addTreeItem(item, connectedItem)
810
            # up to here
811
        except Exception as ex:
812
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
813
            self.addMessage.emit(MessageType.Error, message)
814

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

    
831
        # Update Scene
832
        self.graphicsView.scene.update(self.graphicsView.sceneRect())
833

    
834
    '''
835
        history    humkyung 2018.06.09 check length of original and connection point is 2 while parsing
836
    '''
837
    def drawDetectedSymbolItem(self, symbolList):
838
        from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
839
        from SymbolSvgItem import SymbolSvgItem
840
        import math
841

    
842
        try:
843
            project = AppDocData.instance().getCurrentProject()
844

    
845
            searchedMap = []
846
            for symbol in symbolList:
847
                pt = [float(x) for x in symbol.getSp()]
848
                size = [symbol.getWidth(), symbol.getHeight()]
849
                name = symbol.getName()
850
                angle = round(math.radians(symbol.getRotatedAngle()), 2)
851
                type = symbol.getType()
852
                origin = [0,0]
853
                if 2 == len(symbol.getOriginalPoint().split(',')):
854
                    tokens = symbol.getOriginalPoint().split(',')
855
                    origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
856
                connPts = []
857
                if symbol.getConnectionPoint() is not None:
858
                    connPts = [(pt[0] + float(x.split(',')[0]), pt[1] + float(x.split(',')[1])) for x in symbol.getConnectionPoint().split('/') if 2 == len(x.split(','))]
859
                parentSymbol = symbol.getBaseSymbol()
860
                childSymbol = symbol.getAdditionalSymbol()
861
                hasInstrumentLabel = symbol.getHasInstrumentLabel()
862

    
863
                svgFilePath = os.path.join(project.getSvgFilePath(), type, name + '.svg')
864
                if os.path.isfile(svgFilePath):
865
                    svg = SymbolSvgItem.createItem(type, svgFilePath)
866
                    svg.buildItem(name, type, angle, pt, size, origin, connPts, parentSymbol, childSymbol, hasInstrumentLabel)
867
                    svg.reCalculationRotatedItem()
868

    
869
                    # set owner - 2018.07.20 added by humkyung                   
870
                    matches = [searched for searched in searchedMap if searched[0] == symbol.owner]
871
                    if len(matches) == 1:
872
                        svg.owner = matches[0][1]
873
                    searchedMap.append((symbol, svg))
874
                    # up to here
875

    
876
                    svg.transfer.onRemoved.connect(self.itemRemoved)
877
                    self.addSvgItemToScene(svg)
878
                else:
879
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
880
                    item.isSymbol = True
881
                    item.angle = angle
882
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
883
                    self.graphicsView.scene.addItem(item)
884

    
885
                # Equipment Item 경우 저장
886
                if type(item) is QEngineeringEquipmentItem:
887
                    item.saveEquipData()
888
            # up to here
889
        except Exception as ex:
890
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
891
            self.addMessage.emit(MessageType.Error, message)
892

    
893
    '''
894
        @history    2018.06.08  Jeongwoo    Add parameter on round method
895
    '''
896
    def drawDetectedTextItem(self, textInfoList):
897
        from TextItemFactory import TextItemFactory
898
        import math
899
        try:
900
            docData = AppDocData.instance()
901
            configs = docData.getConfigs('Line No', 'Delimiter')
902
            delimiter = configs[0].value if 1 == len(configs) else '-'
903
            lineNoconfigs = docData.getConfigs('Line No', 'Configuration')
904
            #
905
            linePropertyData = {}
906
            linePropertyData['NominalDiameter'] = docData.getNomialPipeSizeData(True)
907
            linePropertyData['FluidCode'] = docData.getCodeTable('FluidCode', True)
908
            linePropertyData['UnitNumber'] = docData.getCodeTable('UnitNumber', True)
909
            linePropertyData['PnIDNumber'] = docData.getCodeTable('PnIDNumber', True)
910
            linePropertyData['PipingMaterialsClass'] = docData.getCodeTable('PipingMaterialsClass', True)
911
            linePropertyData['InsulationPurpose'] = docData.getCodeTable('InsulationPurpose', True)
912
            #
913
            configs = docData.getConfigs('Line No Tag Rule', 'Tag Seq No')
914
            tagSeqNoPattern = configs[0].value if 1 == len(configs) else None
915

    
916
            # parse texts
917
            for textInfo in textInfoList:
918
                x = textInfo.getX()
919
                y = textInfo.getY()
920
                width = textInfo.getW()
921
                height = textInfo.getH()
922
                angle = round(math.radians(textInfo.getAngle()), 2)
923
                text = textInfo.getText()
924
                item = TextItemFactory.instance().createTextItem(text, delimiter, lineNoconfigs, linePropertyData, tagSeqNoPattern)
925

    
926
                if item is not None:
927
                    item.loc = (x, y)
928
                    item.size = (width, height)
929
                    item.angle = angle
930
                    item.setPlainText(text)
931
                    item.transfer.onRemoved.connect(self.itemRemoved)
932
                    self.addTextItemToScene(item)
933

    
934
                    # Line No Text Item 경우 저장
935
                    if type(item) is QEngineeringLineNoTextItem:
936
                        item.saveLineData()
937

    
938
        except Exception as ex:
939
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
940
            self.addMessage.emit(MessageType.Error, message)
941

    
942
    def drawDetectedNoteItem(self, noteTextInfoList):
943
        from TextItemFactory import TextItemFactory
944
        import math
945
        try:
946
            # parse notes
947
            for note in noteTextInfoList:
948
                x = note.getX()
949
                y = note.getY()
950
                width = note.getW()
951
                height = note.getH()
952
                angle = round(math.radians(note.getAngle()))
953
                text = note.getText()
954
                item = TextItemFactory.instance().createTextItem(text)
955
                item.loc = (x, y)
956
                item.size = (width, height)
957
                item.angle = angle
958
                item.setPlainText(text)
959
                self.addTextItemToScene(item)
960
        except Exception as ex:
961
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
962
            self.addMessage.emit(MessageType.Error, message)
963

    
964
    '''
965
        @brief  draw unknown items 
966
        @author humkyung
967
        @date   2018.06.12
968
        @history    2018.06.14  Jeongwoo    Change method to add unknown item
969
                    2018.06.18  Jeongwoo    Add connect on unknown item
970
                                            Add [transfer] for using pyqtSignal
971
    '''
972
    def drawUnknownItems(self):
973
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem 
974
        from EngineeringLineItem import QEngineeringLineItem
975
        from EngineeringUnknownItem import QEngineeringUnknownItem
976

    
977
        try:
978
            docData = AppDocData.instance()
979
            project = docData.getCurrentProject()
980
            windowSize = docData.getSlidingWindowSize()
981
            thickness = int(windowSize[1])
982

    
983
            diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(self.path))
984
            if os.path.isfile(diffFilePath):
985
                imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1]
986

    
987
                lines = [item for item in self.graphicsView.scene.items() if (type(item) is QEngineeringLineItem)]
988
                for line in lines:
989
                    line.drawToImage(imgDiff, 255, thickness)
990
                cv2.imwrite(diffFilePath, imgDiff)
991

    
992
                imgNot = np.ones(imgDiff.shape, np.uint8)
993
                cv2.bitwise_not(imgDiff, imgNot)
994
                imgNot = cv2.dilate(imgNot, np.ones((8,8), np.uint8))
995

    
996
                image, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
997
                for contour in contours:
998
                    [x, y, w, h] = cv2.boundingRect(contour)
999

    
1000
                    # remove too small one
1001
                    if (w < 10 or h < 10): continue
1002

    
1003
                    # create unknown item
1004
                    epsilon = cv2.arcLength(contour, True)*0.001
1005
                    approx = cv2.approxPolyDP(contour, epsilon, True)
1006
                    approx = [pt[0] for pt in approx]
1007
                    item = QEngineeringUnknownItem(approx)
1008
                    item.transfer.onRemoved.connect(self.itemRemoved)
1009
                    self.addUnknownItemToScene(item)
1010
                    # up to here
1011

    
1012
                notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(self.path))
1013
                cv2.imwrite(notFilePath, imgNot)
1014
            else:
1015
                message = 'can\'t found {}'.format(diffFilePath)
1016
                self.addMessage.emit(MessageType.Normal, message)
1017
        except Exception as ex:
1018
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1019
            self.addMessage.emit(MessageType.Error, message)
1020

    
1021
    '''
1022
        @brief      load recognition result
1023
        @author     humkyung
1024
        @date       2018.04.??
1025
        @history    humkyung 2018.01.12 parse originalpoint and connectionpoint
1026
                    Jeongwoo 2018.04.17 add QGraphicItem with Rotated text
1027
                    Jeongwoo 2018.04.23 Change to Draw texts on QEngineeringTextItem
1028
                    humkyung 2018.04.23 connect item remove slot to result tree
1029
                    Jeongwoo 2018.04.25 Add if state with QEngineeringNoteItem
1030
                    Jeongwoo 2018.04.26 Change method to create TextItem object with TextItemFactory
1031
                    Jeongwoo 2018.05.03 Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1032
                    Jeongwoo 2018.05.29 Change method name / Change method to add item / Add Line item
1033
                    Jeongwoo 2018.05.30 Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol) / Change method name / Change XML NODE NAMES
1034
                    Jeongwoo 2018.06.12 Add LineNoTextItem from LINE_NO
1035
                    Jeongwoo 2018.06.14 Add UnknownItem from UNKNOWN
1036
                    Jeongwoo 2018.06.18 Update Scene after all item added
1037
                                        Add connect on unknown item
1038
                                        Add [transfer] for using pyqtSignal
1039
                    kyouho  2018.07.12  Add line property logic
1040
    '''
1041
    def loadRecognitionResultFromXml(self, xmlPath):
1042
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
1043

    
1044
        try:
1045
            symbols = []
1046

    
1047
            xml = parse(xmlPath)
1048
            root = xml.getroot()
1049
            for symbol in root.iter('SYMBOL'):
1050
                item = SymbolSvgItem.fromXml(symbol)
1051
                if item[0] is not None:
1052
                    item[0].transfer.onRemoved.connect(self.itemRemoved)
1053
                    symbols.append(item)
1054
                else:
1055
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
1056
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
1057
                    angle = float(symbol.find('ANGLE').text)
1058
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
1059
                    item.isSymbol = True
1060
                    item.angle = angle
1061
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
1062
                    self.graphicsView.scene.addItem(item)
1063

    
1064
            # set symbol's owner
1065
            childItems = [item for item in symbols if item[1] is not None]
1066
            for item in childItems:
1067
                matches = [param for param in symbols if str(param[0].uid) == item[1]]
1068
                if len(matches) == 1:
1069
                    item[0].owner = matches[0][0]
1070
            # up to here
1071
           
1072
            for item in symbols:
1073
                self.addSvgItemToScene(item[0])
1074

    
1075
            docData = AppDocData.instance()
1076
            configs = docData.getConfigs('Line No', 'Delimiter')
1077
            delimiter = configs[0].value if 1 == len(configs) else '-'
1078
            lineNoconfigs = docData.getConfigs('Line No', 'Configuration')
1079
            #
1080
            linePropertyData = {}
1081
            linePropertyData['NominalDiameter'] = docData.getNomialPipeSizeData(True)
1082
            linePropertyData['FluidCode'] = docData.getCodeTable('FluidCode', True)
1083
            linePropertyData['UnitNumber'] = docData.getCodeTable('UnitNumber', True)
1084
            linePropertyData['PnIDNumber'] = docData.getCodeTable('PnIDNumber', True)
1085
            linePropertyData['PipingMaterialsClass'] = docData.getCodeTable('PipingMaterialsClass', True)
1086
            linePropertyData['InsulationPurpose'] = docData.getCodeTable('InsulationPurpose', True)
1087
            #
1088
            configs = docData.getConfigs('Line No Tag Rule', 'Tag Seq No')
1089
            tagSeqNoPattern = configs[0].value if 1 == len(configs) else None
1090

    
1091
            # parse texts
1092
            for text in root.iter('ATTRIBUTE'):
1093
                location = text.find('LOCATION').text if text.find('LOCATION') is not None else '0,0'
1094
                x = float(location.split(',')[0])
1095
                y = float(location.split(',')[1])
1096
                width = float(text.find('WIDTH').text) if text.find('WIDTH') is not None else 0
1097
                height = float(text.find('HEIGHT').text) if text.find('HEIGHT') is not None else 0
1098
                angle = float(text.find('ANGLE').text) if text.find('ANGLE') is not None else 0
1099
                value = text.find('VALUE').text
1100
                uid = text.find('UID')
1101
                attributeValue = text.find('ATTRIBUTEVALUE')
1102
                name = text.find('NAME').text
1103
                if name == 'TEXT':
1104
                    item = TextItemFactory.instance().createTextItem(value, delimiter, lineNoconfigs, linePropertyData, tagSeqNoPattern)
1105
                    if item is not None:
1106
                        item.loc = (x, y)
1107
                        item.size = (width, height)
1108
                        item.angle = angle
1109
                        item.setPlainText(value)
1110
                        item.transfer.onRemoved.connect(self.itemRemoved)
1111
                        self.addTextItemToScene(item)
1112
                        if uid is not None and attributeValue is not None:
1113
                            item.uid = uid.text
1114
                            item.attribute = attributeValue.text
1115
                elif name == 'NOTE':
1116
                    item = TextItemFactory.instance().createTextItem(value)
1117
                    if item is not None:
1118
                        item.loc = (x, y)
1119
                        item.size = (width, height)
1120
                        item.angle = angle
1121
                        item.setPlainText(value)
1122
                        self.addTextItemToScene(item)
1123
                        if uid is not None:
1124
                            item.uid = uid.text
1125
                
1126

    
1127
            for lineNo in root.iter('LINE_NO'):
1128
                location = lineNo.find('LOCATION').text if lineNo.find('LOCATION') is not None else '0,0'
1129
                x = float(location.split(',')[0])
1130
                y = float(location.split(',')[1])
1131
                width = float(lineNo.find('WIDTH').text) if lineNo.find('WIDTH') is not None else 0
1132
                height = float(lineNo.find('HEIGHT').text) if lineNo.find('HEIGHT') is not None else 0
1133
                angle = float(lineNo.find('ANGLE').text) if lineNo.find('ANGLE') is not None else 0
1134
                text = lineNo.find('TEXT').text
1135

    
1136
                item = TextItemFactory.instance().createTextItem(text, delimiter, lineNoconfigs, linePropertyData, tagSeqNoPattern)
1137
                if item is not None:
1138
                    item.loc = (x, y)
1139
                    item.size = (width, height)
1140
                    item.angle = angle
1141
                    item.setPlainText(text)
1142
                    item.transfer.onRemoved.connect(self.itemRemoved)
1143
                    self.addTextItemToScene(item)
1144

    
1145
            for line in root.iter('LINE'):
1146
                item = QEngineeringLineItem.fromXml(line)
1147
                item.transfer.onRemoved.connect(self.itemRemoved)
1148
                if item: self.addLineItemToScene(item)
1149

    
1150
            for unknown in root.iter('UNKNOWN'):
1151
                item = QEngineeringUnknownItem.fromXml(unknown)
1152
                item.transfer.onRemoved.connect(self.itemRemoved)
1153
                if item is not None:
1154
                    item.transfer.onRemoved.connect(self.itemRemoved)
1155
                    self.addUnknownItemToScene(item)
1156
            # up to here
1157

    
1158

    
1159
            # set symbol's connectItem
1160
            from EngineeringConnectorItem import QEngineeringConnectorItem
1161
            connectors = [item for item in self.graphicsView.scene.items() if type(item) == QEngineeringConnectorItem and item.connectedItem is not None]
1162
            for connector in connectors:
1163
                # 처음에는 UID가 connectedItem에 String으로 들어가있기 때문에
1164
                connector.connectedItem = self.graphicsView.findItemByUid(connector.connectedItem)
1165

    
1166
            symbols = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and len(item.attrs) > 0]
1167
            for symbol in symbols:
1168
                # 처음에는 attrs의 uid가 connectedItem에 String으로 들어가있기 때문에
1169
                for index in range(len(symbol.attrs)):
1170
                    symbol.attrs[index] = self.graphicsView.findItemByUid(symbol.attrs[index])
1171
                        
1172

    
1173
            # Update Scene
1174
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1175
        except Exception as ex:
1176
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1177
            self.addMessage.emit(MessageType.Error, message)
1178

    
1179
    '''
1180
        @brief      Remove added item on same place and Add GraphicsItem
1181
        @author     Jeongwoo
1182
        @date       2018.05.25
1183
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
1184
                    2018.06.18  Jeongwoo    Set Z-index
1185
    '''
1186
    def addSvgItemToScene(self, svgItem):
1187
        '''
1188
        svgRect = svgItem.boundingRectOnScene()
1189
        items = self.graphicsView.scene.items(svgRect)
1190
        if items is not None:
1191
            for item in items:
1192
                if issubclass(type(item), SymbolSvgItem):
1193
                    itemRect = item.boundingRectOnScene()
1194
                    if itemRect.topLeft() == svgRect.topLeft() and itemRect.size() == svgRect.size(): # Equal
1195
                        item.deleteSvgItemFromScene()
1196
        '''
1197
        svgItem.setZValue(10)
1198
        svgItem.addSvgItemToScene(self.graphicsView.scene)
1199
        
1200
    '''
1201
        @brief      Remove added item on same place and Add GraphicsItem
1202
        @author     Jeongwoo
1203
        @date       2018.05.25
1204
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
1205
                    2018.06.05  Jeongwoo    Remove Size condition
1206
                    2018.06.18  Jeongwoo    Set Z-index
1207
    '''
1208
    def addTextItemToScene(self, textItem):
1209
        textRect = textItem.boundingRectOnScene()
1210
        items = self.graphicsView.scene.items(textRect)
1211
        if items is not None:
1212
            for item in items:
1213
                if issubclass(type(item), QEngineeringTextItem):
1214
                    itemRect = item.boundingRectOnScene()
1215
                    if itemRect.topLeft() == textRect.topLeft() and item.text() == textItem.text(): # Equal
1216
                        item.deleteTextItemFromScene()
1217
        textItem.setZValue(10)
1218
        textItem.addTextItemToScene(self.graphicsView.scene)
1219
        
1220
    '''
1221
        @brief      Remove added item on same place and Add GraphicsItem
1222
        @author     Jeongwoo
1223
        @date       2018.05.29
1224
        @history    2018.06.18  Jeongwoo    Set Z-index
1225
    '''
1226
    def addLineItemToScene(self, lineItem):
1227
        '''
1228
        lineRect = lineItem.boundingRectOnScene()
1229
        items = self.graphicsView.scene.items(lineRect)
1230
        if items is not None:
1231
            for item in items:
1232
                if issubclass(type(item), QEngineeringLineItem):
1233
                    itemRect = item.boundingRectOnScene()
1234
                    if item.startPoint() == lineItem.startPoint() and item.endPoint() == lineItem.endPoint(): # Equal
1235
                        item.deleteLineItemFromScene()
1236
        lineItem.setZValue(10)
1237
        '''
1238
        lineItem.addLineItemToScene(self.graphicsView.scene)
1239

    
1240
    '''
1241
        @brief      Remove added item on same place and Add Unknown Item
1242
        @author     Jeongwoo
1243
        @date       2018.06.14
1244
        @history    2018.06.18  Jeongwoo    Set Z-index
1245
    '''
1246
    def addUnknownItemToScene(self, unknownItem):
1247
        try:
1248
            unknownRect = unknownItem.boundingRectOnScene()
1249
            items = self.graphicsView.scene.items(unknownRect)
1250
            if items is not None:
1251
                for item in items:
1252
                    if issubclass(type(item), QEngineeringUnknownItem):
1253
                        itemRect = item.boundingRectOnScene()
1254
                        if itemRect.topLeft() == unknownRect.topLeft() and itemRect.size() == unknownRect.size(): # Equal
1255
                            item.deleteUnknownItemFromScene()
1256
            unknownItem.setZValue(-10)
1257
            unknownItem.addUnknownItemToScene(self.graphicsView.scene)
1258
        except Exception as ex:
1259
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1260
            self.addMessage.emit(MessageType.Error, message)
1261

    
1262
    '''
1263
        @brief      generate output xml file
1264
        @author     humkyung
1265
        @date       2018.04.23
1266
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
1267
    '''
1268
    def generateOutput(self):
1269
        import XmlGenerator as xg
1270
        from QEngineeringEquipmentItem import QEngineeringEquipmentItem
1271

    
1272
        if not self.graphicsView.hasImage():
1273
            self.showImageSelectionMessageBox()
1274
            return
1275

    
1276
        try:
1277
            docData = AppDocData.instance()
1278

    
1279
            docData.lines.clear()
1280
            docData.lines = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem and item.owner is None]
1281

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

    
1285
            docData.equipments.clear()
1286
            for item in self.graphicsView.scene.items():
1287
                if type(item) is QEngineeringEquipmentItem:
1288
                    docData.equipments.append(item)
1289

    
1290
            docData.imgOutput = np.ones((docData.imgHeight, docData.imgWidth), np.uint8)*255
1291
            xg.writeOutputXml(docData.imgName, docData.imgWidth, docData.imgHeight) # TODO: check
1292
            project = docData.getCurrentProject()
1293
            cv2.imwrite(os.path.join(project.getTempPath() , 'OUTPUT.png') , docData.imgOutput)
1294
        except Exception as ex:
1295
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1296
            self.addMessage.emit(MessageType.Error, message)
1297
            
1298
if __name__ == '__main__':
1299
    '''
1300
    diffFilePath = 'd:/Projects/DTIPID/PC-K/Temp/diff_PC-K-2203_P1_800DPI.png'
1301
    imgDiff = cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY)
1302
    ret, mask = cv2.threshold(imgDiff, 127, 255, cv2.THRESH_BINARY)
1303
    imgDiff = cv2.bitwise_not(mask)
1304
    imgDiff = cv2.dilate(imgDiff, np.ones((8, 8), np.uint8))
1305
    image, contours, hierarchy = cv2.findContours(imgDiff, cv2.RETR_LIST , cv2.CHAIN_APPROX_SIMPLE)
1306
    for contour in contours:
1307
        epsilon = cv2.arcLength(contour, True)*0.01
1308
        approx = cv2.approxPolyDP(contour, epsilon, True)
1309
        for i in range(0, len(approx)-1):
1310
            cv2.line(imgDiff, (approx[i][0][0], approx[i][0][1]), (approx[i+1][0][0], approx[i+1][0][1]), 255, 1)
1311

1312
    notFilePath = 'd:/Projects/DTIPID/PC-K/Temp/not_PC-K-2203_P1_800DPI.png'
1313
    cv2.imwrite(notFilePath, imgDiff)
1314
    '''
1315

    
1316
    from ProjectDialog import Ui_Dialog
1317
    from App import App 
1318

    
1319
    app = App(sys.argv)
1320
    try:
1321
        dlg = Ui_Dialog()
1322
        selectedProject = dlg.showDialog()
1323
        if selectedProject is not None:
1324
            AppDocData.instance().setCurrentProject(selectedProject)
1325
            app._mainWnd = MainWindow.instance()
1326
            app._mainWnd.show()
1327
    except Exception as ex:
1328
        print('에러가 발생했습니다.\n', ex)
1329

    
1330
    sys.exit(app.exec_())