프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / MainWindow.py @ 25a69af0

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

1
# coding: utf-8
2
"""
3
This is MainWindow module
4
"""
5

    
6
import sys
7
import os
8
import subprocess
9
from functools import partial
10

    
11
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
12
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Commands')
13
import CreateCommand
14
import CropCommand
15
import AreaOcrCommand
16
import CreateSymbolCommand
17
import AreaZoomCommand
18
import FenceCommand
19
import PlaceLineCommand
20

    
21
import cv2
22
import numpy as np
23

    
24
from PyQt5.QtCore import *
25
from PyQt5.QtGui import *
26
from PyQt5.QtWidgets import *
27
from PyQt5.QtSvg import *
28

    
29
from PIL import Image
30

    
31
import MainWindow_UI
32
import QtImageViewer
33
from SingletonInstance import SingletonInstane
34

    
35
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Shapes')
36
from EngineeringPolylineItem import QEngineeringPolylineItem
37
from EngineeringLineItem import QEngineeringLineItem
38
from SymbolSvgItem import SymbolSvgItem
39
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
40
from EngineeringTextItem import QEngineeringTextItem
41
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
42
from EngineeringTextItem import QEngineeringTextItem
43
from EngineeringNoteItem import QEngineeringNoteItem
44
from QEngineeringSizeTextItem import QEngineeringSizeTextItem
45
from EngineeringUnknownItem import QEngineeringUnknownItem
46
from EngineeringEquipmentItem import QEngineeringEquipmentItem
47
from EngineeringInstrumentItem import QEngineeringInstrumentItem
48
from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
49
from AppDocData import *
50
import SymbolTreeWidget, SymbolPropertyTableWidget
51
import SymbolEditorDialog
52
import ItemTreeWidget
53
import ItemPropertyTableWidget
54
from UserInputAttribute import UserInputAttribute
55
from TextItemFactory import TextItemFactory
56
from TrainingImageListDialog import QTrainingImageListDialog
57

    
58
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane):
59
    """
60
    This is MainWindow class
61
    """
62
    addMessage = pyqtSignal(Enum, str)
63

    
64
    '''
65
        @brief      initialize
66
        @author 
67
        @date   
68
        @history    humkyung 2018.04.12 add splitter widget
69
                    Jeongwoo 2018.04.27 Add Signal/Slot Connection 'noteNoSingleClicked'
70
                    Jeongwoo 2018.05.09 Initialize Action group
71
                    Jeongwoo 2018.05.10 Add Signal/Slot Connection 'lineNoSingleClicked'
72
                                        Add QActionGroup for managing checkable action
73
                    Jeongwoo 2018.06.27 Add Action [Zoom, Fit Window] and Add new actions into ActionGroup
74
                    humkyung 2018.08.23 add labelStatus to statusbar
75
                    Euisung 2018.09.27 add OCR Training , Signal/Slot Connection 'oCRTrainingClicked'
76
                    Euisung 2018.10.05 add OCR Editor , Signal/Slot Connection 'oCRTrainingEdidorClicked'
77
                    Euisung 2018.10.22 delete Signal/Slot Connection 'oCRTrainingEdidorClicked'
78
    '''
79
    def __init__(self):
80
        super(self.__class__, self).__init__()
81
        self.setupUi(self)
82
        self.labelStatus = QLabel(self.statusbar)
83
        self.labelStatus.setText(self.tr('Unrecognition : '))
84
        self.labelSymbolStatus = QLabel(self.statusbar)
85
        self.labelSymbolStatus.setText(self.tr('Symbol : '))
86
        self.labelLineStatus = QLabel(self.statusbar)
87
        self.labelLineStatus.setText(self.tr('Line : '))
88
        self.labelTextStatus = QLabel(self.statusbar)
89
        self.labelTextStatus.setText(self.tr('Text : '))
90
        self.statusbar.addPermanentWidget(self.labelSymbolStatus)
91
        self.statusbar.addPermanentWidget(self.labelLineStatus)
92
        self.statusbar.addPermanentWidget(self.labelTextStatus)
93
        self.statusbar.addPermanentWidget(self.labelStatus) 
94

    
95
        docData = AppDocData.instance()
96
        project = docData.getCurrentProject()
97
        _translate = QCoreApplication.translate
98
        self.setWindowTitle(_translate("Digital P&ID - {}".format(project.name), "Digital P&ID - {}".format(project.name)))
99

    
100
        self.lineComboBox = QComboBox(self.toolBar)
101
        lineTypes = docData.getLineTypes()
102
        for lineType in lineTypes:
103
            self.lineComboBox.addItem(lineType)
104
        self.lineComboBox.currentIndexChanged.connect(self.onLineTypeChanged)
105

    
106
        self.toolBar.insertWidget(self.actionOCR, self.lineComboBox)
107
        self.toolBar.insertSeparator(self.actionOCR)
108
        self.graphicsView = QtImageViewer.QtImageViewer(self)
109
        self.graphicsView.setParent(self.centralwidget)
110
        self.graphicsView.useDefaultCommand() ##### USE DEFAULT COMMAND
111

    
112
        self.verticalLayout.addWidget(self.graphicsView)
113

    
114
        # Add Custom TreeWidget
115
        self.dirTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
116
        self.dirTreeWidget.header().hide()
117
        self.symbolTabVerticalLayout.addWidget(self.dirTreeWidget)
118

    
119
        # Add Custom Property TableWidget
120
        self.propertyTableWidget = SymbolPropertyTableWidget.QSymbolPropertyTableWidget()
121
        self.symbolTabVerticalLayout.addWidget(self.propertyTableWidget)
122
        self.dirTreeWidget.singleClicked.connect(self.propertyTableWidget.getClickedSymbol)
123
        # add splitter widget
124
        splitter = QSplitter(Qt.Vertical)
125
        splitter.addWidget(self.dirTreeWidget)
126
        splitter.addWidget(self.propertyTableWidget)
127
        self.symbolTabVerticalLayout.addWidget(splitter)
128
        # up to here
129

    
130
        # Add Custom Result Tree Widget (Symbol Explorer)
131
        self.itemTreeWidget = ItemTreeWidget.QItemTreeWidget(self.graphicsView)
132
        self.itemTreeWidget.header().hide()
133
        self.symbolExplorerVerticalLayout.addWidget(self.itemTreeWidget)
134

    
135
        # Add Empty Widget
136
        self.resultPropertyTableWidget = ItemPropertyTableWidget.QItemPropertyTableWidget(self)
137
        self.symbolExplorerVerticalLayout.addWidget(self.resultPropertyTableWidget)
138
        self.itemTreeWidget.singleClicked.connect(self.resultPropertyTableWidget.onSymbolClicked)
139
        self.itemTreeWidget.noteNoSingleClicked.connect(self.resultPropertyTableWidget.onNoteClicked)
140
        self.itemTreeWidget.lineNoSingleClicked.connect(self.resultPropertyTableWidget.onLineNoClicked)
141
        self.itemTreeWidget.drawingClicked.connect(self.resultPropertyTableWidget.onDrawingClicked)
142
        # add splitter widget
143
        splitter = QSplitter(Qt.Vertical)
144
        splitter.addWidget(self.itemTreeWidget)
145
        splitter.addWidget(self.resultPropertyTableWidget)
146
        self.symbolExplorerVerticalLayout.addWidget(splitter)
147
        # up to here
148

    
149
        # Initialize Action group
150
        self.actionGroup = QActionGroup(self)
151
        self.actionGroup.addAction(self.actionRecognition)
152
        self.actionGroup.addAction(self.actionLineRecognition)
153
        self.actionGroup.addAction(self.actionLine)
154
        self.actionGroup.addAction(self.actionGenerateOutput)
155
        self.actionGroup.addAction(self.actionOCR)
156
        self.actionGroup.addAction(self.actionZoom)
157
        self.actionGroup.addAction(self.actionFitWindow)
158
        self.actionGroup.addAction(self.actionSave)
159
        self.actionGroup.triggered.connect(self.actionGroupTriggered)
160

    
161
        # connect signals and slots
162
        self.actionClose.triggered.connect(self.close)
163
        self.actionOpen.triggered.connect(self.onOpenImageDrawing)
164
        self.actionLine.triggered.connect(self.onPlaceLine)
165
        self.actionRecognition.triggered.connect(self.recognize)
166
        self.pushButtonBatchRecognition.clicked.connect(self.recognizeBatch)
167
        self.pushButtonRefreshDrawings.clicked.connect(self.load_drawing_list)
168
        self.actionLineRecognition.triggered.connect(self.recognizeLine)
169
        self.actionArea.triggered.connect(self.areaConfiguration)
170
        self.actionConfiguration.triggered.connect(self.configuration)
171
        self.actionOCR.triggered.connect(self.onAreaOcr)
172
        self.actionGenerateOutput.triggered.connect(self.generateOutput)
173
        self.pushButtonCreateSymbol.clicked.connect(self.onCreateSymbolClicked)
174
        self.pushButtonClearLog.clicked.connect(self.onClearLog)
175
        self.actionHMB_DATA.triggered.connect(self.onHMBData)
176
        self.actionItem_Data_List.triggered.connect(self.showItemDataList)
177
        self.actionCodeTable.triggered.connect(self.onShowCodeTable)
178
        self.actionImage_Drawing.triggered.connect(self.onViewImageDrawing)
179
        self.actionViewText.triggered.connect(self.onViewText)
180
        self.actionViewSymbol.triggered.connect(self.onViewSymbol)
181
        self.actionViewLine.triggered.connect(self.onViewLine)
182
        self.actionViewUnknown.triggered.connect(self.onViewUnknown)
183
        self.actionRotate.triggered.connect(self.onRotate)
184
        self.actionZoom.triggered.connect(self.onAreaZoom)
185
        self.actionFitWindow.triggered.connect(self.fitWindow)
186
        self.actionpdf_to_image.triggered.connect(self.onConvertPDFToImage)
187
        self.graphicsView.scene.changed.connect(self.onSceneChanged)
188
        self.graphicsView.scene.selectionChanged.connect(self.onSelectionChanged)
189
        self.actionInitialize.triggered.connect(self.onInitializeScene)
190
        self.resultPropertyTableWidget.cellDoubleClicked.connect(self.resultPropertyTableWidget.cellDoubleClickedEvent)
191
        self.resultPropertyTableWidget.cellClicked.connect(self.cellClickedEvent)
192
        self.actionSave.triggered.connect(self.actionSaveCliked)
193
        self.addMessage.connect(self.onAddMessage)
194
        self.actionFindReplaceText.triggered.connect(self.findReplaceTextClicked)
195
        self.pushButtonDetectSymbol.clicked.connect(self.onShowDetectSymbol)
196

    
197
        configs = docData.getAppConfigs('app', 'mode')
198
        if configs and 1 == len(configs) and 'advanced' == configs[0].value:
199
            self.actionOCR_Training.triggered.connect(self.oCRTrainingClicked)
200
        else:
201
            self.actionOCR_Training.setVisible(False)
202

    
203
        # removedItems
204
        self.removedItems = {}
205
        self.removedItems['LINE'] = []
206
        self.removedItems['EQUIP'] = []
207
        self.removedItems['INST'] = []
208
        self.removedItems['NOTE'] = []
209

    
210
        self.delimiter = '"'
211
    
212
        self.resizeDocks({self.dockWidget}, {self.dockWidgetObjectExplorer.sizeHint().width()}, Qt.Horizontal)
213

    
214
        self.treeWidgetDrawingList.setHeaderHidden(False)
215
        self.treeWidgetDrawingList.header().setStretchLastSection(False)
216
        self.treeWidgetDrawingList.setHeaderLabels([self.tr('Name'), self.tr('DateTime')])
217
        self.treeWidgetDrawingList.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
218
        self.treeWidgetDrawingList.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
219
        self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing)
220
        self.load_drawing_list()
221

    
222
        # load stylesheet file list
223
        stylesheet_name = QtWidgets.qApp.stylesheet_name
224
        files = [os.path.splitext(file)[0] for file in os.listdir(os.path.dirname(os.path.realpath(__file__))) if os.path.splitext(file)[1] == '.qss']
225
        for file in files:
226
            action = self.menuTheme.addAction(file)
227
            action.setCheckable(True)
228
            action.setChecked(True) if stylesheet_name == file else action.setChecked(False)
229
            action.triggered.connect(partial(self.load_stylesheet, file))
230
        # up to here
231

    
232
        # load language files
233
        language_name = QtWidgets.qApp.language_name
234
        files = ['en_us'] # englisgh is default language
235
        files.extend([os.path.splitext(file)[0] for file in os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate')) if os.path.splitext(file)[1] == '.qm'])
236
        for file in files:
237
            action = self.menuLanguage.addAction(file)
238
            action.setCheckable(True)
239
            action.setChecked(True) if language_name.lower() == file.lower() else action.setChecked(False)
240
            action.triggered.connect(partial(self.load_language, file))
241
        # up to here
242

    
243
    def load_stylesheet(self, file):
244
        """
245
        @brief  load stylesheets
246
        @author humkyung
247
        @date   2018.10.29
248
        """
249

    
250
        QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
251

    
252
        app_doc_data = AppDocData.instance()
253
        configs = [Config('app', 'stylesheet', file)]
254
        app_doc_data.saveAppConfigs(configs)
255
        
256
        for action in self.menuTheme.actions():
257
            if action.text() == file: continue
258
            action.setChecked(False)
259

    
260
    def load_language(self, file):
261
        """
262
        load language file and then apply selected language 
263
        """
264
        try:
265
            qm_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate', '{0}.qm'.format(file))
266
            QtWidgets.qApp.load_language(qm_file)
267

    
268
            app_doc_data = AppDocData.instance()
269
            configs = [Config('app', 'language', file)]
270
            app_doc_data.saveAppConfigs(configs)
271
            
272
            for action in self.menuLanguage.actions():
273
                if action.text().lower() == file.lower(): continue
274
                action.setChecked(False)
275
        finally:
276
            self.retranslateUi(self)
277
            self.propertyTableWidget.retranslateUi()
278

    
279
    '''
280
        @brief      Clear TreeWidget and Set Current PID
281
        @author     Jeongwoo
282
        @date       18.04.11
283
        @history    2018.04.26  Jeongwoo    Add Child [SYMBOLS, NOTES] into root item
284
                    2018.05.09  Jeongwoo    Change method to add default tree items
285
                    humkyung 2018.06.10 add tree item for Line No and Unknown Item
286
    '''
287
    def load_drawing_list(self):
288
        """
289
        @brief      load p&id drawing list
290
        @author     humkyung
291
        @date       18.11.02
292
        """
293

    
294
        try:
295
            appDocData = AppDocData.instance()
296
            drawings = appDocData.getDrawings()
297

    
298
            self.treeWidgetDrawingList.clear()
299
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList, [self.tr('P&ID Drawings'), ''])
300
            files = appDocData.getDrawingFileList()
301
            for file in files:
302
                drawing = [drawing for drawing in drawings if drawing[1] == file]
303
                if not drawing or not drawing[0]:
304
                    drawings.append([None, file, None])
305

    
306
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [file, drawing[0][2] if drawing and drawing[0] else ''])
307
                item.setIcon(0, QIcon(':newPrefix/image.png'))
308
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
309
                item.setCheckState(0, Qt.Unchecked)
310
            
311
            self.treeWidgetDrawingList.root.setText(0, self.tr('P&ID Drawings')+'({})'.format(self.treeWidgetDrawingList.root.childCount()))
312
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
313
            self.treeWidgetDrawingList.root.sortChildren(0, Qt.AscendingOrder)
314
            self.treeWidgetDrawingList.resizeColumnToContents(0)
315

    
316
            appDocData.saveDrawings(drawings)
317
        except Exception as ex:
318
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
319
            self.addMessage.emit(MessageType.Error, message)
320

    
321
    def open_selected_drawing(self, item, column):
322
        """
323
        @brief      open selected p&id drawing
324
        @author     humkyung
325
        @date       18.11.02
326
        """
327
        appDocData = AppDocData.instance()
328
        drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), item.text(column))
329
        self.onOpenImageDrawing(drawing)
330

    
331
    def onShowDetectSymbol(self):
332
        from DetectSymbolDialog import QDetectSymbolDialog
333

    
334
        dlgDetectSymbol = QDetectSymbolDialog(self)
335
        dlgDetectSymbol.show()
336
        dlgDetectSymbol.exec_()
337
        
338
    '''
339
        @brief      OCR Editor
340
        @author     euisung
341
        @date       2018.10.05
342
        @history    2018.10.16 euisung      no more used, Integrated with oCRTrainingClicked
343
    '''
344
    def oCRTrainingEdidorClicked(self):
345
        from TrainingEditorDialog import QTrainingEditorDialog
346

    
347
        try:
348
            dialog = QTrainingEditorDialog(self)
349
            dialog.exec_()
350
        except Exception as ex:
351
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
352
            self.addMessage.emit(MessageType.Error, message)
353
            
354
        return
355

    
356
    '''
357
        @brief      OCR Training
358
        @author     euisung
359
        @date       2018.09.27
360
        @history    euisung 2018.10.16 TrainingListDialog -> TrainingImageListDialog
361
    '''
362
    def oCRTrainingClicked(self):
363
        try:
364
            dialog = QTrainingImageListDialog(self)
365
            dialog.exec_()
366
        except Exception as ex:
367
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
368
            self.addMessage.emit(MessageType.Error, message)
369

    
370
    '''
371
        @brief      show unknownitem's count
372
        @author     kyouho
373
        @date       2018.08.27
374
    '''
375
    def findReplaceTextClicked(self):
376
        if not self.graphicsView.hasImage():
377
            self.showImageSelectionMessageBox()
378
            return
379

    
380
        from TextItemEditDialog import QTextItemEditDialog
381

    
382
        self.dlgTextItemEdit = QTextItemEditDialog(self)
383
        self.dlgTextItemEdit.show()
384
        self.dlgTextItemEdit.exec_()
385

    
386
    '''
387
        @brief      show unknownitem's count
388
        @author     humkyung
389
        @date       2018.08.23
390
        @history    humkyung 2018.08.30 display count of symbol, line, text
391
    '''
392
    def onSceneChanged(self):
393
        items = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
394
        if len(items) > 0:
395
            self.labelStatus.setText("<font color='red'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
396
        else:
397
            self.labelStatus.setText("<font color='black'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
398

    
399
        items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem)]
400
        self.labelSymbolStatus.setText("<font color='blue'>" + self.tr('Symbol') + " : {}</font>".format(len(items)))
401

    
402
        items = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem]
403
        self.labelLineStatus.setText("<font color='blue'>" + self.tr('Line') + " : {}</font>".format(len(items)))
404

    
405
        items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
406
        self.labelTextStatus.setText("<font color='blue'>" + self.tr('Text') + " : {}</font>".format(len(items)))
407

    
408
        self.itemTreeWidget.sceneChanged(self.graphicsView.scene.items())
409

    
410
    def dbUpdate(self):
411
        '''
412
            @brief      db update when save or recognition
413
            @author     euisung
414
            @date       2018.11.12
415
            @history    2018.11.02      euisung     remove scene dependency
416
        '''
417
        from AppDocData import AppDocData
418

    
419
        try:
420
            appDocData = AppDocData.instance()
421

    
422
            titleBlockProps = appDocData.getTitleBlockProperties()
423
            #items = self.graphicsView.scene.items()
424
            items = appDocData.allItems
425
            titleBlockItems = []
426
            for item in items:
427
                #if type(item) is QEngineeringLineNoTextItem:
428
                #    item.saveLineData()
429
                if type(item) is QEngineeringTextItem:
430
                    for titleBlockProp in titleBlockProps:
431
                        if item.area == titleBlockProp[0]:
432
                            titleBlockItems.append(item)
433

    
434
            dbItems = [item for item in items if type(item) is QEngineeringInstrumentItem or type(item) is QEngineeringEquipmentItem or\
435
            type(item) is QEngineeringNoteItem or type(item) is SymbolSvgItem or type(item) is QEngineeringLineNoTextItem] + titleBlockItems
436
            appDocData.saveToDatabase(dbItems)
437
        except Exception as ex:
438
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
439
            self.addMessage.emit(MessageType.Error, message)
440

    
441
    '''
442
        @brief      action save click event
443
        @author     kyouho
444
        @date       2018.08.09
445
        @history    2018.11.02      euisung     add line data list db update
446
                    humkyung save saved time to database
447
                    2018.11.05      euisung     add note data list db update
448
                    2018.11.05      euisung     add db delete process before save
449
                    2018.11.12      euisung     db part move new method to dbUpdate
450
    '''
451
    def actionSaveCliked(self):
452
        from datetime import datetime
453
        from AppDocData import AppDocData
454

    
455
        appDocData = AppDocData.instance()
456
        if appDocData.imgName is None:
457
            self.showImageSelectionMessageBox()
458
            return
459

    
460
        appDocData.clearItemList(False)
461

    
462
        items = self.graphicsView.scene.items()
463
        for item in items:
464
            if type(item) is not QGraphicsPixmapItem:
465
                appDocData.allItems.append(item)
466
                if issubclass(type(item), QEngineeringTextItem):
467
                    appDocData.texts.append(item)
468
                #elif issubclass(type(item), SymbolSvgItem):
469
                #    appDocData.symbols.append(item)
470
        
471
        ##
472
        itemTypes = []
473
        for item in items:
474
            typeExist = False
475
            for itemType in itemTypes:
476
                if type(item) is itemType:
477
                    typeExist = True
478
                    break
479
            if not typeExist:
480
                itemTypes.append(type(item))
481
        ##
482

    
483
        self.dbUpdate()
484
        self.saveToXml(True)
485

    
486
        drawings = appDocData.getDrawings()
487
        drawing = [drawing for drawing in drawings if appDocData.imgName == os.path.splitext(drawing[1])[0]]
488
        if drawing[0]:
489
            drawing[0][2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
490
            appDocData.saveDrawings(drawing)
491

    
492
    '''
493
        @brief      save items to xml
494
        @author     kyouho
495
        @date       2018.07.31
496
    '''
497
    def saveToXml(self, alert = True):
498
        import XmlGenerator as xg
499
        from AppDocData import AppDocData
500
        docData = AppDocData.instance()
501
        if docData.imgName is None:
502
            self.showImageSelectionMessageBox()
503
            return
504
        result = xg.writeXmlOnScene(docData.imgName, docData.imgWidth, docData.imgHeight)
505
        
506
        if len(self.removedItems['LINE']):
507
            docData.deleteLineDataList_LineNo(self.removedItems['LINE'])
508
            self.removedItems['LINE'] = []
509

    
510
        if len(self.removedItems['EQUIP']):
511
            docData.deleteEquipDataList(self.removedItems['EQUIP'])
512
            self.removedItems['EQUIP'] = []
513

    
514
        if len(self.removedItems['INST']):
515
            docData.deleteInstDataList(self.removedItems['INST'])
516
            self.removedItems['INST'] = []
517

    
518
        if len(self.removedItems['NOTE']):
519
            docData.deleteNoteDataList(self.removedItems['NOTE'])
520
            self.removedItems['NOTE'] = []
521

    
522

    
523
        if alert:
524
            resultStr = '[저장 결과]'
525

    
526
            for item in result.items():
527
                itemName = str(item[0])
528
                itemSuccessCount = str(item[1][0])
529
                itemFailUidList = item[1][1]
530
                resultStr += "\r\n" + itemName + " Save Count : " + itemSuccessCount
531
                if len(itemFailUidList) > 0:
532
                    resultStr += "\r\n" + itemName + " Error List(UID)"
533
                    for uid in itemFailUidList:
534
                        resultStr += "\r\n" + uid
535

    
536
            QMessageBox.about(self.graphicsView, self.tr('Notice'), resultStr)
537

    
538
    '''
539
        @brief      refresh resultPropertyTableWidget
540
        @author     kyouho
541
        @date       2018.07.19
542
    '''
543
    def refreshResultPropertyTableWidget(self):
544
        items = self.graphicsView.scene.selectedItems()
545
        if len(items) == 1:
546
            self.resultPropertyTableWidget.showItemProperty(items[0])
547
    
548
    '''
549
        @brief      resultPropertyTableWidget Cell Click Event
550
        @author     kyouho
551
        @date       2018.08.23
552
    '''
553
    def cellClickedEvent(self, row, column):
554
        item = self.graphicsView.scene.selectedItems()
555
        if len(item) != 1:
556
            return
557
        item = item[0]
558

    
559
        cell = self.resultPropertyTableWidget.item(row, column)
560
        for valueCell, uid in self.resultPropertyTableWidget.attrValueList:
561
            if valueCell == cell and issubclass(type(item), SymbolSvgItem):
562
                for attr in item.attrs:
563
                    if attr.Attribute == uid and (issubclass(type(attr), SymbolSvgItem) or type(attr) is QEngineeringTextItem):
564
                        prevItem = item
565
                        currentItem = attr
566

    
567
                        rect = currentItem.sceneBoundingRect()
568
                        self.graphicsView.centerOn(rect.center())
569
                        self.graphicsView.zoomImage(True, QMouseEvent(QEvent.MouseButtonPress, self.graphicsView.mapFromScene(QPointF(rect.left(), rect.top())), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier), 3)
570
                        prevItem.setSelected(True)
571

    
572
                        currentItem.setHightlight()
573
                    elif (issubclass(type(attr), SymbolSvgItem) or type(attr) is QEngineeringTextItem):
574
                        attr.unsetHightlight()
575

    
576

    
577
    '''
578
        @brief  add message listwidget
579
        @author humkyung
580
        @date   2018.07.31
581
    '''
582
    def onAddMessage(self, messageType, message):
583
        from AppDocData import MessageType
584

    
585
        try:
586
            current = QDateTime.currentDateTime()
587

    
588
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
589
            if messageType == MessageType.Error:
590
                item.setBackground(Qt.red)
591

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

    
596
    '''
597
        @brief      clear log
598
        @author     humkyung
599
        @date       2018.08.01
600
    '''
601
    def onClearLog(self):
602
        self.listWidgetLog.clear()
603

    
604
    '''
605
        @brief      rotate selected symbol
606
        @author     humkyung
607
        @date       2018.08.15
608
    '''
609
    def onRotate(self, action):
610
        selected = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem)]
611
        if len(selected) == 1:
612
            selected[0].rotateSymbol()
613

    
614
    '''
615
        @brief      Area Zoom
616
        @author     Jeongwoo
617
        @date       2018.06.27
618
        @history    connect command's rejected signal
619
    '''
620
    def onAreaZoom(self, action):
621
        if self.actionZoom.isChecked():
622
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
623
            cmd.onRejected.connect(self.onCommandRejected)
624
            self.graphicsView.command = cmd
625

    
626
    '''
627
        @brief      Fit Window
628
        @author     Jeongwoo
629
        @date       2018.06.27
630
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
631
    '''
632
    def fitWindow(self, action):
633
        self.graphicsView.useDefaultCommand()
634
        self.graphicsView.zoomImageInit()
635

    
636
    def onConvertPDFToImage(self):
637
        """
638
        @brief      convert to selected pdf to image
639
        @author     humkyung 
640
        @date       2018.07.09
641
        @history    Euisung 2018.10.11 hide shell
642
        """
643
        try: 
644
            filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)) , 'bin64', 'PDF_TO_IMAGE.exe')
645
            subprocess.call(filePath, shell = False)
646
        except Exception as ex:
647
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
648

    
649
    '''
650
        @brief      selection changed
651
        @author     humkyung
652
        @date       2018.06.27
653
        @history    humkung 2018.07.08 call tree widget's findItem
654
    '''
655
    def onSelectionChanged(self):
656
        items = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem) or \
657
            type(item) is QEngineeringLineItem or type(item) is QEngineeringLineNoTextItem or type(item) is QEngineeringNoteItem or type(item) is QEngineeringUnknownItem]
658
        if items:
659
            item = items[-1]
660
            self.itemTreeWidget.findItem(item)
661
            self.resultPropertyTableWidget.showItemProperty(item)
662
        else:
663
            self.resultPropertyTableWidget.showItemProperty(None)
664
        
665
    '''
666
        @brief      Initialize scene and itemTreeWidget
667
        @author     Jeongwoo
668
        @date       2018.06.14
669
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
670
    '''
671
    def onInitializeScene(self, action):
672
        if not self.graphicsView.hasImage():
673
            self.actionEquipment.setChecked(False)
674
            self.showImageSelectionMessageBox()
675

    
676
            return
677

    
678
        msg = QMessageBox()
679
        msg.setIcon(QMessageBox.Critical)
680
        msg.setText(self.tr('선택한 인식한 항목들을 삭제하시겠습니까?\n삭제된 항목들은 복구할 수 없습니다.'))
681
        msg.setWindowTitle(self.tr("항목 삭제"))
682
        msg.setStandardButtons(QMessageBox.Ok|QMessageBox.Cancel)
683
        if QMessageBox.Ok == msg.exec_():
684

    
685
            appDocData = AppDocData.instance()
686
            appDocData.clearItemList(True)
687

    
688
            items = self.graphicsView.scene.items()
689
            for item in items:
690
                if type(item) is not QGraphicsPixmapItem:
691
                    self.graphicsView.scene.removeItem(item)
692

    
693
                    if type(item) is QEngineeringLineNoTextItem:
694
                        self.removedItems['LINE'].append(str(item.uid))
695
                    elif type(item) is QEngineeringInstrumentItem:
696
                        self.removedItems['INST'].append(str(item.uid))
697
                    elif type(item) is QEngineeringEquipmentItem:
698
                        self.removedItems['EQUIP'].append(str(item.uid))
699
                    elif type(item) is QEngineeringNoteItem:
700
                        self.removedItems['NOTE'].append(str(item.uid))
701
                    
702
            if self.path is not None:
703
                baseName = os.path.basename(self.path)
704
                self.itemTreeWidget.setCurrentPID(baseName)
705

    
706
    '''
707
        @brief      Manage Checkable Action statement
708
        @author     Jeongwoo
709
        @date       2018.05.10
710
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
711
    '''
712
    def actionGroupTriggered(self, action):
713
        if self.graphicsView.command is not None:
714
            self.graphicsView.useDefaultCommand()
715

    
716
        for _action in self.actionGroup.actions():
717
            _action.setChecked(False)
718

    
719
        action.setChecked(True)
720

    
721
    '''
722
        @brief      Create Equipment
723
        @author     Jeongwoo
724
        @date       18.05.03
725
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
726
    '''
727
    def createEquipment(self):
728
        if not self.graphicsView.hasImage():
729
            self.actionEquipment.setChecked(False)
730
            self.showImageSelectionMessageBox()
731
            return
732
        if self.actionEquipment.isChecked():
733
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget, self.dirTreeWidget)
734
        else:
735
            self.graphicsView.useDefaultCommand()
736

    
737

    
738
    '''
739
        @brief      Create Nozzle
740
        @author     Jeongwoo
741
        @date       2018.05.03
742
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
743
    '''
744
    def createNozzle(self):
745
        if not self.graphicsView.hasImage():
746
            self.actionNozzle.setChecked(False)
747
            self.showImageSelectionMessageBox()
748
            return
749
        if self.actionNozzle.isChecked():
750
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget, self.dirTreeWidget)
751
        else:
752
            self.graphicsView.useDefaultCommand()
753

    
754
    '''
755
        @brief      Area OCR
756
        @author     Jeongwoo
757
        @date       18.04.18
758
        @history    2018.05.02  Jeongwoo    Change graphicsView.command by actionOCR checked state
759
                                            Show MessageBox when imageviewer doesn't have image
760
    '''
761
    def onAreaOcr(self):
762
        if not self.graphicsView.hasImage():
763
            self.actionOCR.setChecked(False)
764
            self.showImageSelectionMessageBox()
765
            return
766

    
767
        if self.actionOCR.isChecked():
768
            cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView)
769
            cmd.onSuccess.connect(self.onRecognizeText)
770
            cmd.onRejected.connect(self.onCommandRejected)
771
            self.graphicsView.command = cmd
772
        else:
773
            self.graphicsView.useDefaultCommand()
774
    
775
    '''
776
        @brief      show text recognition dialog
777
        @author     humkyung
778
        @date       2018.08.08
779
    '''
780
    def onRecognizeText(self, x, y, width, height):
781
        from OcrResultDialog import QOcrResultDialog
782

    
783
        try:
784
            image = self.graphicsView.image().copy(x, y, width, height)
785
            dialog = QOcrResultDialog(self.graphicsView, image, QRectF(x, y, width, height))
786
            (isAccept, textInfoList) = dialog.showDialog()
787
            if isAccept:
788
                if textInfoList is not None and len(textInfoList) > 0:
789
                    docData = AppDocData.instance()
790
                    for textInfo in textInfoList:
791
                        x = textInfo.getX()
792
                        y = textInfo.getY()
793
                        angle = textInfo.getAngle()
794
                        text = textInfo.getText()
795
                        width = textInfo.getW()
796
                        height = textInfo.getH()
797
                        item = TextItemFactory.instance().createTextItem(textInfo)
798
                        if item is not None:
799
                            item.loc = (x, y)
800
                            item.size = (width, height)
801
                            item.angle = angle
802
                            item.setDefaultTextColor(Qt.blue)
803
                            item.addTextItemToScene(self.graphicsView.scene)
804
                            item.transfer.onRemoved.connect(self.itemRemoved)
805
                        else:
806
                            message = 'error occured({}) in {}:{}'.format('텍스트 생성에 실패했습니다.', sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
807
                            self.addMessage.emit(MessageType.Normal, message)
808
                else:
809
                    QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("Fail to recognize text"))
810
        except Exception as ex:
811
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
812
            self.addMessage.emit(MessageType.Error, message)
813

    
814
    '''
815
        @brief  area configuration
816
    '''
817
    def areaConfiguration(self):
818
        from ConfigurationAreaDialog import QConfigurationAreaDialog
819
        if not self.graphicsView.hasImage():
820
            self.showImageSelectionMessageBox()
821
            return
822
        self.dlgConfigurationArea = QConfigurationAreaDialog(self)
823
        self.dlgConfigurationArea.show()
824
        self.dlgConfigurationArea.exec_()
825
        self.graphicsView.useDefaultCommand()
826

    
827
    '''
828
        @brief  configuration
829
    '''
830
    def configuration(self):
831
        from ConfigurationDialog import QConfigurationDialog
832

    
833
        self.dlgConfiguration = QConfigurationDialog(self)
834
        self.dlgConfiguration.show()
835
        self.dlgConfiguration.exec_()
836

    
837
    '''
838
        @brief  show nominal diameter dialog 
839
        @author humkyung
840
        @date   2018.06.28
841
    '''
842
    def onShowCodeTable(self):
843
        from CodeTableDialog import QCodeTableDialog
844

    
845
        dlg = QCodeTableDialog(self)
846
        dlg.exec_()
847

    
848
    '''
849
        @brief  show HMB data
850
        @author humkyung
851
        @date   2018.07.11
852
    '''
853
    def onHMBData(self):
854
        from HMBDialog import QHMBDialog
855

    
856
        dlg = QHMBDialog(self)
857
        dlg.show()
858
        dlg.exec_()
859

    
860
    '''
861
        @brief  show line data list 
862
        @author humkyung
863
        @date   2018.05.03
864
    '''
865
    def showItemDataList(self):
866
        from ItemDataExportDialog import QItemDataExportDialog
867

    
868
        self.dlgLineDataList = QItemDataExportDialog(self)
869
        self.dlgLineDataList.exec_()
870

    
871
    '''
872
        @brief  Show Image Selection Guide MessageBox
873
        @author Jeongwoo
874
        @date   2018.05.02
875
    '''
876
    def showImageSelectionMessageBox(self):
877
        QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("First select image drawing"))
878
        
879
    '''
880
        @brief  change selected lines' type by selected line type
881
        @author humkyung
882
        @date   2018.06.27
883
    '''
884
    def onLineTypeChanged(self, param):
885
        lineType = self.lineComboBox.itemText(param)
886
        selected = [item for item in self.graphicsView.scene.selectedItems() if type(item) is QEngineeringLineItem]
887
        if selected:
888
            for item in selected:
889
                item.lineType = lineType
890

    
891
    '''
892
        @brief      Open image drawing file and then display it
893
        @author     humkyung
894
        @date       2018.??.??
895
        @history    18.04.23 Jeongwoo    Add AppDocData.instance().setCurrentPidSource
896
                    18.04.23 Jeongwoo    Add Store Set Current Pid Image on AppDocData
897
                    18.05.02 Jeongwoo    Add useDefaultCommand()
898
                    humkyung 2018.05.24 load recognition result file if exists
899
                    Jeongwoo 2018.05.29 load data on xml if xml file exist
900
                    humkyung 2018.08.22 clear scene before loading xml file
901
    '''
902
    def onOpenImageDrawing(self, path=None):
903
        from Drawing import Drawing
904
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
905

    
906
        try:
907
            appDocData = AppDocData.instance()
908
            project = appDocData.getCurrentProject()
909
            
910
            for item in self.graphicsView.scene.items():
911
                self.graphicsView.scene.removeItem(item)
912

    
913
            self.path = self.graphicsView.loadImageFromFile(project.getDrawingFilePath(), path if type(path) is str else '')
914
            if os.path.isfile(self.path):
915
                appDocData.clear()
916
                self.graphicsView.useDefaultCommand()
917

    
918
                appDocData.setImgFilePath(self.path)
919
                appDocData.activeDrawing = Drawing(appDocData.imgName)
920
                appDocData.setCurrentPidSource(Image.open(self.path))
921
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
922

    
923
                drawingList = self.treeWidgetDrawingList.topLevelItem(0)
924
                for childIdex in range(drawingList.childCount()):
925
                    drawingList.child(childIdex).setCheckState(0, Qt.Unchecked)
926
                for childIdex in range(drawingList.childCount()):
927
                    child = drawingList.child(childIdex)
928
                    if child.text(0).replace('.png', '') == appDocData.activeDrawing.name:
929
                        child.setCheckState(0, Qt.Checked)
930
                        break
931

    
932
                ## Load data on xml
933
                path = os.path.join(appDocData.getCurrentProject().getTempPath(), appDocData.imgName + '.xml')
934
                count = 0
935
                if os.path.isfile(path):
936
                    for child in parse(path).getroot().getchildren():
937
                        count = count + len(child.getchildren())
938
                if count > 0:
939
                    try:
940
                        self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, self) if not hasattr(self, 'progress') else self.progress
941
                        self.progress.setWindowModality(Qt.WindowModal)
942
                        self.progress.setAutoReset(True)
943
                        self.progress.setAutoClose(True)
944
                        self.progress.setMinimum(0)
945
                        self.progress.resize(600,100)
946
                        self.progress.setWindowTitle(self.tr("Reading file..."))
947
                        self.progress.show()
948

    
949
                        self.loadRecognitionResultFromXml(path)
950
                        self.checkAttribute()
951
                    finally:
952
                        self.progress.setValue(self.progress.maximum())
953
                        self.progress.hide()
954
                self.changeViewCheckedState(True)
955
        except Exception as ex:
956
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
957
            self.addMessage.emit(MessageType.Error, message)
958

    
959
        return self.path
960

    
961
    def changeViewCheckedState(self, checked):
962
        '''
963
            @brief      change view checked state
964
            @author     euisung
965
            @date       2019.03.06
966
        '''
967
        self.actionImage_Drawing.setChecked(checked)
968
        self.actionViewText.setChecked(checked)
969
        self.actionViewSymbol.setChecked(checked)
970
        self.actionViewLine.setChecked(checked)
971
        self.actionViewUnknown.setChecked(checked)
972

    
973
    '''
974
        @brief  visible/invisible image drawing
975
        @author humkyung
976
        @date   2018.06.25
977
    '''
978
    def onViewImageDrawing(self, isChecked):
979
        for item in self.graphicsView.scene.items():
980
            if type(item) is QGraphicsPixmapItem:
981
                item.setVisible(isChecked)
982
                break
983

    
984
    '''
985
        @brief  visible/invisible Text 
986
        @author humkyung
987
        @date   2018.06.28
988
    '''
989
    def onViewText(self, isChecked):
990
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
991
        for item in selected:
992
            item.setVisible(isChecked)
993

    
994
    '''
995
        @brief  visible/invisible Symbol 
996
        @author humkyung
997
        @date   2018.06.28
998
    '''
999
    def onViewSymbol(self, isChecked):
1000
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem)]
1001
        for item in selected:
1002
            item.setVisible(isChecked)
1003

    
1004
    '''
1005
        @brief  visible/invisible Line
1006
        @author humkyung
1007
        @date   2018.06.28
1008
    '''
1009
    def onViewLine(self, isChecked):
1010
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem]
1011
        for item in selected:
1012
            item.setVisible(isChecked)
1013

    
1014
    '''
1015
        @brief  visible/invisible Unknown 
1016
        @author humkyung
1017
        @date   2018.06.28
1018
    '''
1019
    def onViewUnknown(self, isChecked):
1020
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
1021
        for item in selected:
1022
            item.setVisible(isChecked)
1023

    
1024
    '''
1025
        @brief  create a symbol
1026
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
1027
                                            Add SymbolSvgItem
1028
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1029
                                            Change method to make svg and image path
1030
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
1031
    '''
1032
    def onCreateSymbolClicked(self):
1033
        cmd = FenceCommand.FenceCommand(self.graphicsView)
1034
        cmd.onSuccess.connect(self.onAreaSelected)
1035
        self.graphicsView.command = cmd
1036
        QApplication.setOverrideCursor(Qt.CrossCursor)
1037

    
1038
    '''
1039
        @brief      show SymbolEditorDialog with image selected by user
1040
        @author     humkyung
1041
        @date       2018.07.20
1042
    '''
1043
    def onAreaSelected(self, x, y, width, height):
1044
        try:
1045
            image = self.graphicsView.image()
1046
            if image is not None:
1047
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height), AppDocData.instance().getCurrentProject())
1048
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
1049
                self.dirTreeWidget.initDirTreeWidget()
1050
                if isAccepted:
1051
                    if isImmediateInsert:
1052
                        svgPath = newSym.getSvgFileFullPath()
1053
                        img = cv2.imread(newSym.getImageFileFullPath(), 1)
1054
                        w, h = (0, 0)
1055
                        if len(img.shape[::-1]) == 2:
1056
                            w, h = img.shape[::-1]
1057
                        else:
1058
                            _chan, w, h = img.shape[::-1]
1059
                        svg = SymbolSvgItem(svgPath)
1060
                        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)
1061

    
1062
                        svg.transfer.onRemoved.connect(self.itemTreeWidget.itemRemoved)
1063
                        svg.addSvgItemToScene(self.graphicsView.scene)
1064
                        for connector in svg.connectors:
1065
                            self.graphicsView.scene.addItem(connector)
1066
        finally:
1067
            self.graphicsView.useDefaultCommand()
1068
            QApplication.restoreOverrideCursor()
1069
    
1070
    '''
1071
        @brief      create a line
1072
        @author     humkyung
1073
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
1074
    '''
1075
    def onPlaceLine(self):        
1076
        if not self.graphicsView.hasImage():
1077
            self.actionLine.setChecked(False)
1078
            self.showImageSelectionMessageBox()
1079
            return
1080

    
1081
        self.actionLine.setChecked(True)
1082
        if not hasattr(self.actionLine, 'tag'):
1083
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
1084
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
1085
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
1086

    
1087
        self.graphicsView.command = self.actionLine.tag
1088

    
1089
    '''
1090
        @brief      add created lines to scene
1091
        @author     humkyung
1092
        @date       2018.07.23
1093
    '''
1094
    def onLineCreated(self):
1095
        from EngineeringConnectorItem import QEngineeringConnectorItem
1096

    
1097
        try:
1098
            count = len(self.actionLine.tag._polyline._vertices)
1099
            if count > 1:
1100
                items = []
1101

    
1102
                lineType = self.lineComboBox.currentText()
1103
                for index in range(count - 1):
1104
                    start = self.actionLine.tag._polyline._vertices[index]
1105
                    end  = self.actionLine.tag._polyline._vertices[index + 1]
1106
                    
1107
                    lineItem = QEngineeringLineItem(vertices=[start, end])
1108
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
1109
                    lineItem.lineType = lineType
1110
                    if items:
1111
                        lineItem.connectIfPossible(items[-1], 5)
1112
                    else:
1113
                        pt = lineItem.startPoint()
1114
                        selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
1115
                        if selected is not None and type(selected) is QEngineeringConnectorItem:
1116
                            lineItem.connectIfPossible(selected.parent, 5)
1117
                    
1118
                    items.append(lineItem)
1119
                    self.graphicsView.scene.addItem(lineItem)
1120

    
1121
                pt = items[-1].endPoint()
1122
                selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
1123
                if selected is not None and type(selected) is QEngineeringConnectorItem:
1124
                    items[-1].connectIfPossible(selected.parent, 5)
1125
        finally:
1126
            self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1127
            self.actionLine.tag.reset()
1128

    
1129
    '''
1130
        @brief      refresh scene
1131
        @author     humkyung
1132
        @date       2018.07.23
1133
    '''
1134
    def onCommandRejected(self, cmd):
1135
        try:
1136
            if type(cmd) is PlaceLineCommand.PlaceLineCommand:
1137
                self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1138
                self.graphicsView.scene.update()
1139
                self.actionLine.tag.reset()
1140

    
1141
                self.actionLine.setChecked(False)
1142
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
1143
                self.actionZoom.setChecked(False)
1144
            elif type(cmd) is AreaOcrCommand.AreaOcrCommand:
1145
                self.actionOCR.setChecked(False)
1146
        finally:
1147
            self.graphicsView.useDefaultCommand()
1148
     
1149
    '''
1150
        @brief      restore to default command when user press Escape key
1151
        @author     humkyung 
1152
        @date       2018.08.09
1153
    '''
1154
    def keyPressEvent(self, event):
1155
        try:
1156
            if event.key() == Qt.Key_Escape:
1157
                checked = self.actionGroup.checkedAction()
1158
                if checked:
1159
                    checked.setChecked(False)
1160
                    self.graphicsView.useDefaultCommand()
1161

    
1162
            QMainWindow.keyPressEvent(self, event)
1163
        except Exception as ex:
1164
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1165
            self.addMessage.emit(MessageType.Error, message)
1166
    
1167
    def recognizeBatch(self, MainWindow):
1168
        '''
1169
            @brief      batch recognize symbol, text and line
1170
            @author     euisung
1171
            @date       2018.11.23
1172
        
1173
        '''
1174
        from datetime import datetime
1175
        from RecognitionDialog import QRecognitionDialog
1176

    
1177
        appDocData = AppDocData.instance()
1178
        project = appDocData.getCurrentProject()
1179
        appDocData.needReOpening = None
1180
        currentPid = None
1181
        
1182
        if self.graphicsView.hasImage():
1183
            currentPid = appDocData.activeDrawing.name
1184

    
1185
        drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1186
        drawingCount = drawingTop.childCount()
1187
        checkedTreeItems = []
1188
        checkedDrawingPath = []
1189
        for drawing in range(drawingCount):
1190
            drawingChild = drawingTop.child(drawing)
1191
            if drawingChild.checkState(0) == 2:
1192
                checkedTreeItems.append(drawingChild)
1193
                checkedDrawingPath.append(os.path.join(project.getDrawingFilePath(), drawingChild.data(0, 0)))
1194
                if currentPid is not None and drawingChild.data(0, 0).find(currentPid) is 0:
1195
                    appDocData.needReOpening = False # later check need reopening at drawUnknownItems()
1196
                    currentPid = drawingChild.data(0, 0)
1197

    
1198
        if len(checkedDrawingPath) == 0:
1199
            self.showImageSelectionMessageBox()
1200
            return
1201

    
1202
        try:
1203
            self.onClearLog()
1204
            self.dlg = QRecognitionDialog(self, checkedDrawingPath, True)
1205
            self.dlg.exec_()
1206
            if self.dlg.isAccepted == True:
1207
                pass
1208

    
1209
            if appDocData.needReOpening == True:
1210
                drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), currentPid)
1211
                self.onOpenImageDrawing(drawing)
1212

    
1213
            # save working date-time
1214
            drawings = appDocData.getDrawings()
1215
            checkedDrawings = []
1216
            for checkedTreeItem in checkedTreeItems:
1217
                for drawing in drawings:
1218
                    if checkedTreeItem.data(0, 0) == drawing[1]:
1219
                        if drawing[0]:
1220
                            drawing[2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1221
                            checkedDrawings.append(drawing)
1222
                            checkedTreeItem.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1223
            appDocData.saveDrawings(checkedDrawings)
1224
            # up to here
1225
        except Exception as ex:
1226
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1227
            self.addMessage.emit(MessageType.Error, message)
1228

    
1229
    '''
1230
        @brief      recognize symbol and text
1231
        @author     humkyung
1232
        @date       2018.04.??
1233
        @history    2018.04.16  humkyung    execute line no tracing
1234
                    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
1235
                    2018.05.25  Jeongwoo    Add parameter on QRecognitionDialog.__init__() and Move thread to QRecognitionDialog
1236
                                            Remove codes below if self.dlg.isAccepted == True
1237
                    2018.05.29  Jeongwoo    Remove connects and comments
1238
                    humkyung 2018.11.05 save working date-time
1239
    '''
1240
    def recognize(self, MainWindow):
1241
        from datetime import datetime
1242
        from RecognitionDialog import QRecognitionDialog
1243

    
1244
        if not self.graphicsView.hasImage():
1245
            self.showImageSelectionMessageBox()
1246
            return
1247

    
1248
        try:
1249
            self.removedItems['LINE'] = []
1250
            self.removedItems['EQUIP'] = []
1251
            self.removedItems['INST'] = []
1252
            self.removedItems['NOTE'] = []
1253

    
1254
            appDocData = AppDocData.instance()
1255

    
1256
            self.onClearLog()
1257
            appDocData.needReOpening = False
1258
            drawingList = []
1259
            drawingList.append(self.path)
1260
            self.dlg = QRecognitionDialog(self, drawingList, False)
1261
            self.dlg.exec_()
1262

    
1263
            if appDocData.needReOpening == True:
1264
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
1265
                self.drawDetectedItemsToScene()
1266
                
1267
                # save working date-time
1268
                drawings = appDocData.getDrawings()
1269
                drawing = [drawing for drawing in drawings if appDocData.imgName == os.path.splitext(drawing[1])[0]]
1270
                if drawing[0]:
1271
                    drawing[0][2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1272
                    appDocData.saveDrawings(drawing)
1273

    
1274
                currentPid = appDocData.activeDrawing.name
1275

    
1276
                drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1277
                drawingCount = drawingTop.childCount()
1278
                
1279
                for drawing in range(drawingCount):
1280
                    drawingChild = drawingTop.child(drawing)
1281
                    if drawingChild.data(0, 0).find(currentPid) is 0:
1282
                        drawingChild.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1283
                self.changeViewCheckedState(True)
1284
                # up to here
1285
        except Exception as ex:
1286
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1287
            self.addMessage.emit(MessageType.Error, message)
1288

    
1289
    '''
1290
        @brief      remove item from tree widget and then remove from scene
1291
        @date       2018.05.25
1292
        @author     Jeongwoo
1293
    '''
1294
    def itemRemoved(self, item):
1295
        try:
1296
            self.itemTreeWidget.itemRemoved(item)
1297

    
1298
            if type(item) is QEngineeringLineNoTextItem:
1299
                self.removedItems['LINE'].append(str(item.uid))
1300
            elif type(item) is QEngineeringInstrumentItem:
1301
                self.removedItems['INST'].append(str(item.uid))
1302
            elif type(item) is QEngineeringEquipmentItem:
1303
                self.removedItems['EQUIP'].append(str(item.uid))
1304
            elif type(item) is QEngineeringNoteItem:
1305
                self.removedItems['NOTE'].append(str(item.uid))
1306

    
1307
            if hasattr(item, 'connectors'):
1308
                for sceneItem in self.graphicsView.scene.items():
1309
                    if hasattr(sceneItem, 'connectors'):
1310
                        for sceneConnector in sceneItem.connectors:
1311
                            if sceneConnector.connectedItem is not None and item.uid == sceneConnector.connectedItem.uid:
1312
                                sceneConnector.connectedItem = None
1313

    
1314
            if item.scene() is not None: item.scene().removeItem(item)
1315
        except Exception as ex:
1316
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1317
            self.addMessage.emit(MessageType.Error, message)
1318

    
1319
    '''
1320
        @brief      recognize line
1321
        @author     humkyung
1322
        @date       2018.04.19
1323
        @history    Jeongwoo 2018.04.26 Variable name changed (texts → lineNos)
1324
                                        TextItem type changed (QEngineeringTextItem → QEngineeringLineNoTextItem)
1325
                    humkyung 2018.04.26 remove small objects before recognizing line
1326
                    Jeongwoo 2018.05.02 Show MessageBox when imageviewer doesn't have image
1327
                    Jeongwoo 2018.05.25 Move codes about LineDetector
1328
                    humkyung 2018.06.17 show progress dialog
1329
    '''
1330
    def recognizeLine(self, MainWindow):
1331
        from LineNoTracer import LineNoTracer
1332
        from ConnectAttrDialog import QConnectAttrDialog
1333

    
1334
        if not self.graphicsView.hasImage():
1335
            self.showImageSelectionMessageBox()
1336
            return
1337

    
1338
        try:
1339
            self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView)
1340
            self.dlgConnectAttr.exec_()
1341

    
1342
            self.itemTreeWidget.InitLineNoItems()
1343

    
1344
            # construct line no item
1345
            docData = AppDocData.instance()
1346
            for lineno in docData.tracerLineNos:
1347
                item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, lineno)
1348
                connectedItems = lineno.getConnectedItems()
1349
                for connectedItem in connectedItems:
1350
                    if issubclass(type(connectedItem), SymbolSvgItem): 
1351
                        self.itemTreeWidget.addTreeItem(item, connectedItem)
1352
            # up to here
1353
        except Exception as ex:
1354
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1355
            self.addMessage.emit(MessageType.Error, message)
1356

    
1357
    '''
1358
        @history    2018.05.25  Jeongwoo    Moved from MainWindow
1359
                                            SvgItem and TextItem Connect with method in this class
1360
                                            Change method to add GraphicsItem
1361
                    2018.05.28  Jeongwoo    Make QGraphicsItem by symbol, text object. Not xml
1362
                    2018.05.29  Jeongwoo    Change method name and Moved from QRecognitionDialog
1363
                    2018.05.30  Jeongwoo    Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol)
1364
                                            Change Method name and seperate each item
1365
                    humkyung 2018.06.11     display difference between original and recognized image
1366
                    Jeongwoo 2018.06.18     Update Scene after all item added
1367
                    2018.11.05  euisung     add save note item because of dependency
1368
                    2018.11.05  euisung     add db delete process before save
1369
                    2018.11.12  euisung     add title block properties
1370
                    2018.11.12  euisung     db part move new method to dbUpdate
1371
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1372
                    2018.11.29  euisung     change name drawDetectedItems() -> createDetectedItems
1373
    '''
1374
    def createDetectedItems(self, symbolList, textInfoList, otherTextInfoList, titleBlockTextInfoList):
1375
        try:
1376
            appDocData = AppDocData.instance()
1377

    
1378
            QApplication.processEvents()
1379
            self.createDetectedSymbolItem(symbolList)
1380
            QApplication.processEvents()
1381
            self.createDetectedTextItem(textInfoList)
1382
            QApplication.processEvents()
1383
            self.createDetectedOtherTextItem(otherTextInfoList)
1384
            QApplication.processEvents()
1385
            self.createDetectedTitleBlockTextItem(titleBlockTextInfoList)
1386

    
1387
            self.dbUpdate()
1388
            #self.saveToXml(False)
1389

    
1390
            # update scene
1391
            #self.graphicsView.scene.update(self.graphicsView.sceneRect())
1392
        except Exception as ex:
1393
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1394
            self.addMessage.emit(MessageType.Error, message)
1395

    
1396
    def drawDetectedItemsToScene(self):
1397
        '''
1398
            @brief  add detected items to scene
1399
            @author euisung
1400
            @date   2018.11.26
1401
        '''
1402
        appDocData = AppDocData.instance()
1403

    
1404
        try:
1405
            for symbol in appDocData.symbols:
1406
                if issubclass(type(symbol), SymbolSvgItem):
1407
                    self.addSvgItemToScene(symbol)
1408
                else:
1409
                    self.graphicsView.scene.addItem(symbol)
1410

    
1411
            for text in appDocData.texts:
1412
                self.addTextItemToScene(text)
1413

    
1414
            for line in appDocData.lines:
1415
                self.graphicsView.scene.addItem(line)
1416
                for conn in line.connectors:
1417
                    conn.transfer.onPosChanged.connect(line.onConnectorPosChaned)
1418

    
1419
            for unknown in appDocData.unknowns + appDocData.lineIndicators:
1420
                self.addUnknownItemToScene(unknown)
1421
        finally:
1422
            # update scene
1423
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1424

    
1425
    def postDetectLineProcess(self):
1426
        '''
1427
            @brief  check allowables among undetected items
1428
            @author euisung
1429
            @date   2018.11.15
1430
            @history    2018.11.15  euisung    no more used, moved to TextItemFactoy isLineNo()
1431
        '''
1432
        from AppDocData import AppDocData
1433
        from TextItemFactory import TextItemFactory
1434

    
1435
        appDocData = AppDocData.instance()
1436

    
1437
        tableNames = ["Fluid Code", "Insulation Purpose", "PnID Number", "Piping Materials Class", "Unit Number"]
1438
        tableDatas = []
1439
        for tableName in tableNames:
1440
            tableNameFormat = tableName.replace(' ','').replace('&&', 'n')
1441
            tableDatas.append(appDocData.getCodeTable(tableNameFormat))
1442

    
1443
        items = self.graphicsView.scene.items()
1444
        for item in items:
1445
            if type(item) is not QEngineeringTextItem:
1446
                continue
1447
            text = item.text()
1448
            for tableData in tableDatas:
1449
                for data in tableData:
1450
                    if data[3] == '':
1451
                        continue
1452
                    else:
1453
                        allows = data[3].split(',')
1454
                        for allow in allows:
1455
                            text = text.replace(allow, data[1])
1456

    
1457
            lineItem = TextItemFactory.instance().createTextItem(text)
1458
            if type(lineItem) is QEngineeringLineNoTextItem:
1459
                lineItem.loc = item.loc
1460
                lineItem.size = item.size
1461
                lineItem.angle = item.angle
1462
                lineItem.area = item.area
1463
                #lineItem.addTextItemToScene(self.graphicsView.scene)
1464
                lineItem.transfer.onRemoved.connect(self.itemRemoved)
1465
                item.transfer.onRemoved.emit(item)
1466
                appDocData.lineNos.append(lineItem)
1467
                
1468
    def createDetectedTitleBlockTextItem(self, textInfoList):
1469
        '''
1470
            @brief  draw title block
1471
            @author euisung
1472
            @date   2018.11.12
1473
            @history    2018.11.26  euisung     remove scene dependency
1474
                        2018.11.29  euisung     change name drawDetectedTitleBlockTextItem() -> createDetectedTitleBlockTextItem
1475
        '''
1476
        from TextItemFactory import TextItemFactory
1477
        import math
1478

    
1479
        try:
1480
            appDocData = AppDocData.instance()
1481

    
1482
            # parse texts
1483
            for textInfo in textInfoList:
1484
                if len(textInfo[1]) is 0:
1485
                    continue
1486
                x = textInfo[1][0].getX()
1487
                y = textInfo[1][0].getY()
1488
                width = textInfo[1][0].getW()
1489
                height = textInfo[1][0].getH()
1490
                angle = round(math.radians(textInfo[1][0].getAngle()), 2)
1491
                text = textInfo[1][0].getText()
1492
                item = TextItemFactory.instance().createTextItem(textInfo)
1493

    
1494
                if item is not None:
1495
                    item.loc = (x, y)
1496
                    item.size = (width, height)
1497
                    item.angle = angle
1498
                    item.area = textInfo[0]
1499
                    #self.addTextItemToScene(item)
1500
                    appDocData.texts.append(item)
1501
                    appDocData.allItems.append(item)
1502
        except Exception as ex:
1503
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1504
            self.addMessage.emit(MessageType.Error, message)
1505

    
1506
    '''
1507
        @brief      
1508
        @author     humkyung
1509
        @date       2018.08.23
1510
        @history    2018.11.26  euisung     remove scene dependency
1511
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1512
                    2018.11.    euisung     no more used
1513
                    2018.11.29  euisung     change name drawDetectedLines() -> createDetectedLines
1514
    '''
1515
    def createDetectedLines(self, lineList, worker):
1516
        appDocData = AppDocData.instance()
1517
        area = appDocData.getArea('Drawing')
1518

    
1519
        for pts in lineList:
1520
            processLine = QEngineeringLineItem(vertices=[(area.x + param[0], area.y + param[1]) for param in pts])
1521
            processLine.area = 'Drawing'
1522
            #self.graphicsView.scene.addItem(processLine)
1523
            appDocData.lines.append(processLine)
1524
            appDocData.allItems.append(processLine)
1525

    
1526
            if processLine.length() > 100: # TODO: check critical length
1527
                processLine.addFlowArrow()
1528
        
1529
        # re-order process line's start,end according to flow mark
1530
        #worker.arrangeLinePosition(lines, symbols, listWidget)
1531
        # up to here
1532

    
1533
    '''
1534
        history     2018.06.09  humkyung    check length of original and connection point is 2 while parsing
1535
                    2018.11.26  euisung     remove scene dependency
1536
                    2018.11.29  euisung     change name drawDetectedSymbolItem() -> createDetectedSymbolItem
1537
    '''
1538
    def createDetectedSymbolItem(self, symbolList):
1539
        from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
1540
        from SymbolSvgItem import SymbolSvgItem
1541
        import math
1542

    
1543
        try:
1544
            appDocData = AppDocData.instance()
1545
            project = appDocData.getCurrentProject()
1546

    
1547
            searchedMap = []
1548
            for symbol in symbolList:
1549
                pt = [float(x) for x in symbol.getSp()]
1550
                size = [symbol.getWidth(), symbol.getHeight()]
1551
                name = symbol.getName()
1552
                angle = round(math.radians(symbol.getRotatedAngle()), 2)
1553
                _type = symbol.getType()
1554
                origin = [0,0]
1555
                if 2 == len(symbol.getOriginalPoint().split(',')):
1556
                    tokens = symbol.getOriginalPoint().split(',')
1557
                    origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
1558
                connPts = []
1559
                if symbol.getConnectionPoint() is not None and symbol.getConnectionPoint() != '':
1560
                    for param in symbol.getConnectionPoint().split('/'):
1561
                        tokens = param.split(',')
1562
                        connPts.append(('AUTO', pt[0] + float(tokens[0]), pt[1] + float(tokens[1]), '0') if len(tokens) == 2 else \
1563
                                       (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), '0') if len(tokens) == 3 else \
1564
                                       (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), tokens[3]) if len(tokens) == 4 else None)
1565

    
1566
                parentSymbol = symbol.getBaseSymbol()
1567
                childSymbol = symbol.getAdditionalSymbol()
1568
                hasInstrumentLabel = symbol.getHasInstrumentLabel()
1569

    
1570
                svgFilePath = os.path.join(project.getSvgFilePath(), _type, name + '.svg')
1571
                if os.path.isfile(svgFilePath):
1572
                    svg = SymbolSvgItem.createItem(_type, svgFilePath)
1573
                    svg.buildItem(name, _type, angle, pt, size, origin, connPts, parentSymbol, childSymbol, hasInstrumentLabel)
1574
                    svg.reCalculationRotatedItem()
1575
                    svg.area = 'Drawing'
1576

    
1577
                    # set owner - 2018.07.20 added by humkyung                   
1578
                    matches = [searched for searched in searchedMap if searched[0] == symbol.owner]
1579
                    if len(matches) == 1:
1580
                        svg.owner = matches[0][1]
1581
                    searchedMap.append((symbol, svg))
1582
                    # up to here
1583

    
1584
                    svg.transfer.onRemoved.connect(self.itemRemoved)
1585
                    #self.addSvgItemToScene(svg)
1586
                    appDocData.symbols.append(svg)
1587
                    appDocData.allItems.append(svg)
1588
                else:
1589
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
1590
                    item.isSymbol = True
1591
                    item.angle = angle
1592
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
1593
                    #self.graphicsView.scene.addItem(item)
1594
                    appDocData.symbols.append(item)
1595
                    appDocData.allItems.append(item)
1596
            # up to here
1597
        except Exception as ex:
1598
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1599
            self.addMessage.emit(MessageType.Error, message)
1600

    
1601
    '''
1602
        @history    2018.06.08  Jeongwoo    Add parameter on round method
1603
        @history    2018.11.02  euisung     Add save note text item
1604
        @history    2018.11.05  euisung     delete save note text item and move to drawDetectedItems()
1605
                    2018.11.26  euisung     remove scene dependency
1606
                    2018.11.29  euisung     change name drawDetectedTextItem() -> createDetectedTextItem
1607
    '''
1608
    def createDetectedTextItem(self, textInfoList):
1609
        from TextItemFactory import TextItemFactory
1610
        import math
1611

    
1612
        try:
1613
            appDocData = AppDocData.instance()
1614

    
1615
            # parse texts
1616
            for textInfo in textInfoList:
1617
                x = textInfo.getX()
1618
                y = textInfo.getY()
1619
                width = textInfo.getW()
1620
                height = textInfo.getH()
1621
                angle = round(math.radians(textInfo.getAngle()), 2)
1622
                text = textInfo.getText()
1623
                if not text: continue
1624

    
1625
                item = TextItemFactory.instance().createTextItem(textInfo)
1626
                if item is not None:
1627
                    item.loc = (x, y)
1628
                    item.size = (width, height)
1629
                    item.angle = angle
1630
                    item.area = 'Drawing'
1631
                    item.transfer.onRemoved.connect(self.itemRemoved)
1632
                    #self.addTextItemToScene(item)
1633
                    appDocData.texts.append(item)
1634
                    appDocData.allItems.append(item)
1635
        except Exception as ex:
1636
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1637
            self.addMessage.emit(MessageType.Error, message)
1638

    
1639
    '''
1640
        @brief      draw detected texts except which in drawing area
1641
        @history    2018.11.29  euisung     change name drawDetectedOtherTextItem() -> createDetectedOtherTextItem
1642
    '''
1643
    def createDetectedOtherTextItem(self, otherTextInfoList):
1644
        from TextItemFactory import TextItemFactory
1645
        import math
1646

    
1647
        try:
1648
            appDocData = AppDocData.instance()
1649

    
1650
            # parse notes
1651
            for textInfoMap in otherTextInfoList:
1652
                if textInfoMap[0]=='Note':
1653
                    pass
1654

    
1655
                for textInfo in textInfoMap[1]:
1656
                    x = textInfo.getX()
1657
                    y = textInfo.getY()
1658
                    width = textInfo.getW()
1659
                    height = textInfo.getH()
1660
                    angle = round(math.radians(textInfo.getAngle()))
1661
                    text = textInfo.getText()
1662

    
1663
                    item = TextItemFactory.instance().createTextItem(textInfo)
1664

    
1665
                    item.loc = (x, y)
1666
                    item.size = (width, height)
1667
                    item.angle = angle
1668
                    item.area = textInfoMap[0]
1669
                    item.transfer.onRemoved.connect(self.itemRemoved)
1670
                    appDocData.texts.append(item)
1671
                    appDocData.allItems.append(item)
1672
        except Exception as ex:
1673
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1674
            self.addMessage.emit(MessageType.Error, message)
1675

    
1676
    '''
1677
        @brief  draw unknown items 
1678
        @author humkyung
1679
        @date   2018.06.12
1680
        @history    2018.06.14  Jeongwoo    Change method to add unknown item
1681
                    2018.06.18  Jeongwoo    Add connect on unknown item
1682
                                            Add [transfer] for using pyqtSignal
1683
                    2018.11.26  euisung     remove scene dependency
1684
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1685
                    2018.11.27  euisung     add save to xml
1686
                    2018.11.29  euisung     change name drawUnknownItems() -> createUnknownItems
1687
    '''
1688
    def createUnknownItems(self, path):
1689
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem 
1690
        from EngineeringLineItem import QEngineeringLineItem
1691
        from EngineeringUnknownItem import QEngineeringUnknownItem
1692

    
1693
        try:
1694
            docData = AppDocData.instance()
1695
            project = docData.getCurrentProject()
1696
            windowSize = docData.getSlidingWindowSize()
1697
            thickness = int(windowSize[1])
1698

    
1699
            if docData.needReOpening is not None:
1700
                docData.needReOpening = True
1701

    
1702
            diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(path))
1703
            if os.path.isfile(diffFilePath):
1704
                imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1]
1705

    
1706
                ## remove line
1707
                lines = docData.lines
1708
                for line in lines:
1709
                    line.drawToImage(imgDiff, 255, thickness) if line.thickness is None else line.drawToImage(imgDiff, 255, line.thickness)
1710
                cv2.imwrite(diffFilePath, imgDiff)
1711
                ## up to here
1712

    
1713
                imgNot = np.ones(imgDiff.shape, np.uint8)
1714
                cv2.bitwise_not(imgDiff, imgNot)
1715
                imgNot = cv2.dilate(imgNot, np.ones((8,8), np.uint8))
1716

    
1717
                image, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
1718

    
1719
                ##
1720
                idx = 0
1721
                ##
1722
                smallContours = []
1723
                minimumSize = docData.getConfigs('Filter', 'MinimumSize')
1724
                for contour in contours:
1725
                    [x, y, w, h] = cv2.boundingRect(contour)
1726

    
1727
                    # remove too small one
1728
                    if len(minimumSize) is 1:
1729
                        if (w * h < int(minimumSize[0].value) * int(minimumSize[0].value)):
1730
                            smallContours.append(contour)
1731
                            idx += 1
1732
                            continue
1733

    
1734
                    '''
1735
                    rect = QRectF(x, y, w, h)
1736
                    items = [item for item in diffItems if item.boundingRect().contains(rect)]
1737
                    if len(items) > 0: continue
1738
                    
1739
                    items = [item for item in diffItems if rect.contains(item.boundingRect())]
1740
                    for item in items:
1741
                        diffItems.remove(item)
1742
                    '''
1743

    
1744
                    # create unknown item
1745
                    epsilon = cv2.arcLength(contour, True)*0.001
1746
                    approx = cv2.approxPolyDP(contour, epsilon, True)
1747
                    approx = [pt[0] for pt in approx]
1748
                    resultStr, resultList = self.determineRemainObject(idx, contours, imgNot)
1749
                    if resultStr == 'LineIndicator':
1750
                        item = QEngineeringUnknownItem(approx, 'True', resultList[0], resultList[1])
1751
                        docData.lineIndicators.append(item)
1752
                    elif resultStr == 'MissingLine':
1753
                        pass
1754
                    elif resultStr == 'Unknown':
1755
                        item = QEngineeringUnknownItem(approx, 'False')
1756
                        docData.unknowns.append(item)
1757
                    item.area = 'Drawing'
1758
                    docData.allItems.append(item)
1759
                    item.transfer.onRemoved.connect(self.itemRemoved)
1760
                    idx += 1
1761
                    # up to here                    
1762

    
1763
                imgNotRemoveSmall = cv2.drawContours(imgNot, smallContours, -1, 0, -1)
1764
                notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(path))
1765
                cv2.imwrite(notFilePath, imgNotRemoveSmall)
1766
            else:
1767
                message = 'can\'t found {}'.format(diffFilePath)
1768
                self.addMessage.emit(MessageType.Normal, message)
1769

    
1770
            self.saveToXml(False)
1771
        except Exception as ex:
1772
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1773
            self.addMessage.emit(MessageType.Error, message)
1774

    
1775
    def determineRemainObject(self, idx, contours, imgNot):
1776
        '''
1777
            @brief      determine remain objects -> line no indicator, missing line or unknown
1778
            @author     euisung
1779
            @date       2018.12.26
1780
            @history    2019.03.25  euisung    Change name isLineNoIndicator -> determineRemainObject
1781
        '''
1782
        import math
1783
        [x, y, w, h] = cv2.boundingRect(contours[idx])
1784
        
1785
        if (w < 250 and h < 250):
1786
            return ('Unknown', [])
1787
        
1788
        fLines = []
1789
        maxDifAngle = 3
1790
        mask = np.zeros_like(imgNot)
1791
        cv2.drawContours(mask, contours, idx, 123, -1) # Draw filled contour in mask
1792
        out = np.zeros_like(imgNot) # Extract out the object and place into output image
1793
        out[mask == 123] = imgNot[mask == 123]
1794

    
1795
        # Now crop
1796
        ##print(out)
1797
        (x, y) = np.where(mask == 123)
1798
        (topx, topy) = (np.min(x), np.min(y))
1799
        (bottomx, bottomy) = (np.max(x), np.max(y))
1800
        out = out[topx:bottomx+1, topy:bottomy+1]
1801
        h, w = out.shape[0], out.shape[1]
1802
        maxDifH, maxDifW = math.ceil(math.tan(4 * math.pi / 180) / 2 * w), math.ceil(math.tan(4 * math.pi / 180) / 2 * h)
1803

    
1804
        # detection lines
1805
        edged2 = cv2.Canny(out, 100, 200)
1806
        lines = cv2.HoughLinesP(image=edged2, rho=1, theta=np.pi/180, threshold=25, minLineLength=30, maxLineGap=25)
1807
        #lines = cv2.HoughLines(edged2, 1, np.pi/180, 60)
1808
        if lines is None:
1809
            return ('Unknown', [])
1810
        for line in lines:
1811
            #r, theta = line[0]
1812
            #a, b = np.cos(theta), np.sin(theta)
1813
            #x0, y0 = a * r, b * r
1814
            #x1, y1 = int(x0 + 1000 * (-b)), int(y0 + 1000 * a)
1815
            #x2, y2 = int(x0 - 1000 * (-b)), int(y0 - 1000 * a)
1816
            #cv2.line(out, (x1, y1), (x2, y2), (0, 255, 0), 3)
1817
            x1, y1, x2, y2 = line[0]
1818
            degree = math.atan2(y2 - y1, x2 - x1) * 180 / math.pi
1819
            fLine = [x1, y1, x2, y2, degree]
1820
            #print(fLine)
1821
            fLines.append(fLine)
1822
        
1823
        horLines = []
1824
        verLines = []
1825
        otherLines = []
1826
        isVH = None
1827
        for fLine in fLines:
1828
            degree = math.fabs(fLine[4])
1829
            if degree >= 90 - maxDifAngle:
1830
                verLines.append(fLine)
1831
            elif degree <= maxDifAngle:
1832
                horLines.append(fLine)
1833
            else:
1834
                otherLines.append(fLine)
1835

    
1836
        baseLines = []
1837
        baseDifV = 0
1838
        if len(horLines):
1839
            x, y = w / 2, 0
1840
            baseDifV = maxDifH
1841
            for horLine in horLines:
1842
                x1, y1, x2, y2 = horLine[0], horLine[1], horLine[2], horLine[3]
1843
                y = ((y2-y1)/(x2-x1))*x + y1 - ((y2-y1)/(x2-x1))*x1
1844
                horLine.append(y)
1845
            baseLines = horLines
1846
            isVH = 'H'
1847
        if len(verLines):
1848
            x, y = 0, h / 2
1849
            baseDifV = maxDifW
1850
            for verLine in verLines:
1851
                x1, y1, x2, y2 = verLine[0], verLine[1], verLine[2], verLine[3]
1852
                x = ((x2-x1)/(y2-y1))*y + x1 - ((x2-x1)/(y2-y1))*y1
1853
                verLine.append(x)
1854
            baseLines = verLines
1855
            isVH = 'V'
1856

    
1857
        for otherLine in otherLines:
1858
            x, y = w / 2, 0
1859
            x1, y1, x2, y2 = otherLine[0], otherLine[1], otherLine[2], otherLine[3]
1860
            y = ((y2-y1)/(x2-x1))*x + y1 - ((y2-y1)/(x2-x1))*x1
1861
            otherLine.append(y)
1862

    
1863
        # determine line no indicator 
1864
        if not ((len(horLines) > 0 and len(verLines) > 0) or len(otherLines) is 0 or (len(horLines) == 0 and len(verLines) == 0)):    
1865
            result, mergedOtherLine = self.isLineNoIndicator(w, h, maxDifAngle, baseDifV, baseLines, otherLines)
1866
            if result:
1867
                #print(fLines)
1868
                return ('LineIndicator', [isVH, mergedOtherLine])
1869

    
1870
        return ('Unknown', [])
1871

    
1872
    def isLineNoIndicator(self, w, h, maxDifAngle, baseDifV, baseLines, otherLines):
1873
        '''
1874
            @brief      determine line no indicator
1875
            @author     euisung
1876
            @date       2019.03.25
1877
        '''
1878
        import math
1879

    
1880
        if (w < 250 and h < 250):
1881
            return (False, None)
1882

    
1883
        isSameLine = True
1884
        i = 0
1885
        for baseLine in baseLines:
1886
            if not isSameLine: break
1887
            j = 0
1888
            for baseLinee in baseLines:
1889
                if i == j:
1890
                    j += 1
1891
                    continue
1892
                difV = math.fabs(baseLine[5] - baseLinee[5])
1893
                if difV > baseDifV:
1894
                   isSameLine = False
1895
                   break
1896
                j += 1
1897
            i += 1
1898
        if not isSameLine:
1899
            return (False, None)
1900

    
1901
        isSameLine = True
1902
        i = 0
1903
        maxY = 0
1904
        for otherLine in otherLines:
1905
            y = otherLine[5]
1906
            if math.fabs(y) > maxY:
1907
                maxY = math.fabs(y)
1908
            if not isSameLine: break
1909
            j = 0
1910
            for otherLinee in otherLines:
1911
                if i == j:
1912
                    j += 1
1913
                    continue
1914
                difV = math.fabs(otherLine[4] - otherLinee[4])
1915
                if difV > maxDifAngle:
1916
                   isSameLine = False
1917
                   break
1918
                j += 1
1919
            i += 1
1920
        if not isSameLine:
1921
            return (False, None)
1922
                
1923
        isSameLine = True
1924
        mergedOtherLine = [0, 0, 0, 0]
1925
        i = 0
1926
        maxDif = math.ceil(math.tan(4 * math.pi / 180) * maxY)
1927
        for otherLine in otherLines:
1928
            if not isSameLine: break
1929
            j = 0
1930
            for otherLinee in otherLines:
1931
                if i == j:
1932
                    j += 1
1933
                    continue
1934
                angle = math.fabs(otherLine[4] + otherLinee[4]) / 2
1935
                difV = math.fabs(otherLine[5] - otherLinee[5])
1936
                dist = math.sin((90 - angle) * math.pi / 180) * difV 
1937
                if dist > maxDif:
1938
                   isSameLine = False
1939
                   break
1940
                j += 1
1941
            i += 1
1942
            mergedOtherLine[0] += otherLine[0]
1943
            mergedOtherLine[1] += otherLine[1]
1944
            mergedOtherLine[2] += otherLine[2]
1945
            mergedOtherLine[3] += otherLine[3]
1946
        if not isSameLine:
1947
            (False, None)
1948
                        
1949
        # Show the output image
1950
        #print('line no indicator')
1951
        mergedOtherLine[0] = round(mergedOtherLine[0] / len(otherLines))
1952
        mergedOtherLine[1] = round(mergedOtherLine[1] / len(otherLines))
1953
        mergedOtherLine[2] = round(mergedOtherLine[2] / len(otherLines))
1954
        mergedOtherLine[3] = round(mergedOtherLine[3] / len(otherLines))
1955
        #cv2.line(out, (mergedOtherLine[0], mergedOtherLine[1]), (mergedOtherLine[2], mergedOtherLine[3]), (255, 255, 255), 3)
1956
        #cv2.imshow('Output', out)
1957
        #cv2.waitKey(0)
1958
        #cv2.destroyAllWindows()
1959
        return (True, mergedOtherLine)
1960

    
1961
    '''
1962
        @brief      load recognition result
1963
        @author     humkyung
1964
        @date       2018.04.??
1965
        @history    humkyung 2018.01.12 parse originalpoint and connectionpoint
1966
                    Jeongwoo 2018.04.17 add QGraphicItem with Rotated text
1967
                    Jeongwoo 2018.04.23 Change to Draw texts on QEngineeringTextItem
1968
                    humkyung 2018.04.23 connect item remove slot to result tree
1969
                    Jeongwoo 2018.04.25 Add if state with QEngineeringNoteItem
1970
                    Jeongwoo 2018.04.26 Change method to create TextItem object with TextItemFactory
1971
                    Jeongwoo 2018.05.03 Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1972
                    Jeongwoo 2018.05.29 Change method name / Change method to add item / Add Line item
1973
                    Jeongwoo 2018.05.30 Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol) / Change method name / Change XML NODE NAMES
1974
                    Jeongwoo 2018.06.12 Add LineNoTextItem from LINE_NO
1975
                    Jeongwoo 2018.06.14 Add UnknownItem from UNKNOWN
1976
                    Jeongwoo 2018.06.18 Update Scene after all item added
1977
                                        Add connect on unknown item
1978
                                        Add [transfer] for using pyqtSignal
1979
                    kyouho  2018.07.12  Add line property logic
1980
                    humkyung 2018.08.22 show progress while loading xml file
1981
                    2018.11.22      euisung     fix note road
1982
    '''
1983
    def loadRecognitionResultFromXml(self, xmlPath):
1984
        docData = AppDocData.instance()
1985
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
1986
        from EngineeringRunItem import QEngineeringRunItem
1987
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
1988

    
1989
        try:
1990
            symbols = []
1991

    
1992
            xml = parse(xmlPath)
1993
            root = xml.getroot()
1994
            
1995
            maxValue = 0
1996
            maxValue = maxValue + len(list(root.iter('SYMBOL')))
1997
            maxValue = maxValue + len(list(root.iter('ATTRIBUTE')))
1998
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
1999
            maxValue = maxValue + len(list(root.iter('LINE')))
2000
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
2001
            maxValue = maxValue + len(list(root.iter('SIZETEXT')))
2002
            self.progress.setMaximum(maxValue)
2003

    
2004
            for symbol in root.find('SYMBOLS').iter('SYMBOL'):
2005
                item = SymbolSvgItem.fromXml(symbol)
2006
                if item[0] is not None:
2007
                    item[0].transfer.onRemoved.connect(self.itemRemoved)
2008
                    symbols.append(item)                    
2009
                else:
2010
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2011
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2012
                    angle = float(symbol.find('ANGLE').text)
2013
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2014
                    item.isSymbol = True
2015
                    item.angle = angle
2016
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2017
                    self.graphicsView.scene.addItem(item)
2018

    
2019
                self.progress.setValue(self.progress.value() + 1)
2020
                
2021
            QApplication.processEvents()
2022

    
2023
            # set symbol's owner
2024
            childItems = [item for item in symbols if item[1] is not None]
2025
            for item in childItems:
2026
                matches = [param for param in symbols if str(param[0].uid) == item[1]]
2027
                if len(matches) == 1:
2028
                    item[0].owner = matches[0][0]
2029
            # up to here
2030
           
2031
            for item in symbols:
2032
                self.addSvgItemToScene(item[0])
2033
                docData.symbols.append(item[0])
2034

    
2035
            # parse texts
2036
            for text in root.find('TEXTINFOS').iter('ATTRIBUTE'):
2037
                item = QEngineeringTextItem.fromXml(text)
2038
                if item is not None:
2039
                    uid = text.find('UID')
2040
                    attributeValue = text.find('ATTRIBUTEVALUE')
2041
                    name = text.find('NAME').text
2042
                    item.transfer.onRemoved.connect(self.itemRemoved)
2043
                    self.addTextItemToScene(item)
2044
                    docData.texts.append(item)
2045

    
2046
                    if name == 'TEXT':
2047
                        if uid is not None and attributeValue is not None:
2048
                            item.uid = uid.text
2049
                            item.attribute = attributeValue.text
2050

    
2051
                self.progress.setValue(self.progress.value() + 1)
2052
                
2053
            QApplication.processEvents()
2054

    
2055
            # note
2056
            for text in root.find('NOTES').iter('ATTRIBUTE'):
2057
                item = QEngineeringTextItem.fromXml(text)
2058
                if item is not None:
2059
                    uid = text.find('UID')
2060
                    attributeValue = text.find('ATTRIBUTEVALUE')
2061
                    name = text.find('NAME').text
2062
                    item.transfer.onRemoved.connect(self.itemRemoved)
2063
                    self.addTextItemToScene(item)
2064

    
2065
                    if name == 'NOTE':
2066
                        if uid is not None:
2067
                            item.uid = uid.text
2068

    
2069
                self.progress.setValue(self.progress.value() + 1)
2070
                
2071
            QApplication.processEvents()
2072

    
2073
            for line in root.find('LINEINFOS').iter('LINE'):
2074
                item = QEngineeringLineItem.fromXml(line)
2075
                item.transfer.onRemoved.connect(self.itemRemoved)
2076
                if item: self.addLineItemToScene(item)
2077

    
2078
                errors = item.validate()
2079
                for error in errors: self.graphicsView.scene.addItem(error)
2080

    
2081
                self.progress.setValue(self.progress.value() + 1)
2082
                
2083
            QApplication.processEvents()
2084

    
2085
            for unknown in root.iter('UNKNOWN'):
2086
                item = QEngineeringUnknownItem.fromXml(unknown)
2087
                item.transfer.onRemoved.connect(self.itemRemoved)
2088
                if item is not None:
2089
                    item.transfer.onRemoved.connect(self.itemRemoved)
2090
                    self.addUnknownItemToScene(item)
2091

    
2092
                self.progress.setValue(self.progress.value() + 1)
2093
                
2094
            QApplication.processEvents()
2095

    
2096
            for line_no in root.find('LINENOS').iter('LINE_NO'):
2097
                item = QEngineeringLineNoTextItem.fromXml(line_no)
2098
                if item is not None:
2099
                    item.transfer.onRemoved.connect(self.itemRemoved)
2100
                    self.addTextItemToScene(item)
2101

    
2102
                connLine = line_no.find('CONNLINE')
2103
                if connLine is not None:
2104
                    lineUID = connLine.text
2105
                    connLine = self.graphicsView.findItemByUid(lineUID)
2106
                    if connLine is not None:
2107
                        item.conns.append(connLine)
2108

    
2109
                run = line_no.find('RUN')
2110
                if run is not None:
2111
                    lineRunItem = QEngineeringRunItem()
2112
                    for child in run:
2113
                        uidElement = child.find('UID')
2114
                        if uidElement is not None:
2115
                            uid = uidElement.text
2116
                            runItem = self.graphicsView.findItemByUid(uid)
2117
                            if runItem is not None:
2118
                                lineRunItem.items.append(runItem)
2119

    
2120
                    item.runs.append(lineRunItem)
2121
                    treeItem = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2122
                    for connectedItem in lineRunItem.items:
2123
                        if issubclass(type(connectedItem), SymbolSvgItem): self.itemTreeWidget.addTreeItem(treeItem, connectedItem)
2124
                    docData.tracerLineNos.append(item)
2125

    
2126
                self.progress.setValue(self.progress.value() + 1)
2127
            QApplication.processEvents()
2128

    
2129
            for trimLineNo in root.iter('TRIM_LINE_NO'):
2130
                item = QEngineeringTrimLineNoTextItem()
2131
                item.uid = trimLineNo.find('UID')
2132

    
2133
                run = trimLineNo.find('RUN')
2134
                if run is not None:
2135
                    lineRunItem = QEngineeringRunItem()
2136
                    for child in run:
2137
                        uidElement = child.find('UID')
2138
                        if uidElement is not None:
2139
                            uid = uidElement.text
2140
                            runItem = self.graphicsView.findItemByUid(uid)
2141
                            if runItem is not None:
2142
                                lineRunItem.items.append(runItem)
2143

    
2144
                    item.runs.append(lineRunItem)
2145
                    treeItem = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2146
                    for connectedItem in lineRunItem.items:
2147
                        if issubclass(type(connectedItem), SymbolSvgItem): self.itemTreeWidget.addTreeItem(treeItem, connectedItem)
2148
                    docData.tracerLineNos.append(item)
2149
            # up to here
2150

    
2151
            # set symbol's connectItem
2152
            from EngineeringConnectorItem import QEngineeringConnectorItem
2153
            connectors = [item for item in self.graphicsView.scene.items() if type(item) == QEngineeringConnectorItem and item.connectedItem is not None]
2154
            for connector in connectors:
2155
                # 처음에는 UID가 connectedItem에 String으로 들어가있기 때문에
2156
                connector.connectedItem = self.graphicsView.findItemByUid(connector.connectedItem)
2157

    
2158
            symbols = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and len(item.attrs) > 0 and type(item) is not QEngineeringSpecBreakItem]
2159
            for symbol in symbols:
2160
                # 처음에는 attrs의 uid가 connectedItem에 String으로 들어가있기 때문에
2161
                for key in symbol.attrs.keys():
2162
                    if type(symbol.attrs[key]) is not UserInputAttribute and type(symbol.attrs[key]) is not tuple:
2163
                        symbol.attrs[key] = self.graphicsView.findItemByUid(symbol.attrs[key])
2164
                        
2165
            # Update Scene
2166
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2167
            for item in self.graphicsView.scene.items():
2168
                item.setVisible(True)
2169

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

    
2174
    '''
2175
        @brief      Remove added item on same place and Add GraphicsItem
2176
        @author     Jeongwoo
2177
        @date       2018.05.25
2178
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2179
                    2018.06.18  Jeongwoo    Set Z-index
2180
    '''
2181
    def addSvgItemToScene(self, svgItem):
2182
        svgItem.addSvgItemToScene(self.graphicsView.scene)
2183
        
2184
    '''
2185
        @brief      Remove added item on same place and Add GraphicsItem
2186
        @author     Jeongwoo
2187
        @date       2018.05.25
2188
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2189
                    2018.06.05  Jeongwoo    Remove Size condition
2190
                    2018.06.18  Jeongwoo    Set Z-index
2191
    '''
2192
    def addTextItemToScene(self, textItem):
2193
        textItem.addTextItemToScene(self.graphicsView.scene)
2194
        
2195
    '''
2196
        @brief      Remove added item on same place and Add GraphicsItem
2197
        @author     Jeongwoo
2198
        @date       2018.05.29
2199
        @history    2018.06.18  Jeongwoo    Set Z-index
2200
    '''
2201
    def addLineItemToScene(self, lineItem):
2202
        self.graphicsView.scene.addItem(lineItem)
2203

    
2204
    '''
2205
        @brief      Remove added item on same place and Add Unknown Item
2206
        @author     Jeongwoo
2207
        @date       2018.06.14
2208
        @history    2018.06.18  Jeongwoo    Set Z-index
2209
    '''
2210
    def addUnknownItemToScene(self, unknownItem):
2211
        try:
2212
            unknownItem.addUnknownItemToScene(self.graphicsView.scene)
2213
        except Exception as ex:
2214
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2215
            self.addMessage.emit(MessageType.Error, message)
2216

    
2217
    '''
2218
        @brief      generate output xml file
2219
        @author     humkyung
2220
        @date       2018.04.23
2221
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
2222
    '''
2223
    def generateOutput(self):
2224
        import XmlGenerator as xg
2225

    
2226
        if not self.graphicsView.hasImage():
2227
            self.showImageSelectionMessageBox()
2228
            return
2229

    
2230
        try:
2231
            appDocData = AppDocData.instance()
2232

    
2233
            ## collect items
2234
            appDocData.lines.clear()
2235
            appDocData.lines = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem and item.owner is None]
2236

    
2237
            appDocData.symbols.clear()
2238
            appDocData.symbols = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and item.owner is None]
2239

    
2240
            appDocData.equipments.clear()
2241
            for item in self.graphicsView.scene.items():
2242
                if type(item) is QEngineeringEquipmentItem:
2243
                    appDocData.equipments.append(item)
2244

    
2245
            appDocData.texts.clear()
2246
            appDocData.texts = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem) and type(item) is not QEngineeringLineNoTextItem]
2247
            ## up to here
2248

    
2249
            appDocData.imgOutput = np.ones((appDocData.imgHeight, appDocData.imgWidth), np.uint8)*255
2250
            xg.writeOutputXml(appDocData.imgName, appDocData.imgWidth, appDocData.imgHeight) # TODO: check
2251
            project = appDocData.getCurrentProject()
2252
            cv2.imwrite(os.path.join(project.getTempPath() , 'OUTPUT.png') , appDocData.imgOutput)
2253
        except Exception as ex:
2254
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2255
            self.addMessage.emit(MessageType.Error, message)
2256

    
2257
    '''
2258
        @brief      resetting attribute at secne
2259
        @author     kyoyho
2260
        @date       2018.08.21
2261
    '''
2262
    def checkAttribute(self):
2263
        try:
2264

    
2265
            docData = AppDocData.instance()
2266
            if not self.graphicsView.hasImage():
2267
                return
2268

    
2269
            # symbol 경우
2270
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringSpecBreakItem]
2271
            for item in items:
2272
                attrs = item.attrs
2273
                
2274
                removeAttrList = []
2275
                for attr in attrs:
2276
                    if type(attr) is tuple:
2277
                        continue
2278

    
2279
                    if attr is None:
2280
                        removeAttrList.append(attr)
2281
                        continue
2282

    
2283
                    attrInfo = docData.getSymbolAttributeByUID(attr.UID)
2284
                    if attrInfo is None:
2285
                        removeAttrList.append(attr)
2286
                    # 해당 attribute가 맞는지 확인
2287
                    else:
2288
                        attrType = attrInfo.AttributeType
2289
                        _type = type(attr)
2290
                        if attrType == 'Symbol Item':
2291
                            if not issubclass(_type, SymbolSvgItem):
2292
                                removeAttrList.append(attr)
2293
                        elif attrType == 'Text Item':
2294
                            if _type is not QEngineeringTextItem:
2295
                                removeAttrList.append(attr)
2296
                        elif attrType == 'Int':
2297
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
2298
                                removeAttrList.append(attr)
2299
                        elif attrType == 'String':
2300
                            if _type is not UserInputAttribute:
2301
                                removeAttrList.append(attr)
2302

    
2303
                for attr in removeAttrList:
2304
                    del attrs[attr]
2305

    
2306
            # Line No Text Item의 경우
2307
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringLineNoTextItem)]
2308
            for item in items:
2309
                attrs = item.attrs
2310
                
2311
                removeAttrList = []
2312
                for attr in attrs:
2313
                    if type(attr) is UserInputAttribute:
2314
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
2315
                        if attrInfo is None:
2316
                            removeAttrList.append(attr)
2317

    
2318
                for attr in removeAttrList:
2319
                    del attrs[attr]
2320

    
2321
        except Exception as ex:
2322
                message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2323
                self.addMessage.emit(MessageType.Error, message)
2324
    '''
2325
        @brief      Check Number
2326
        @author     kyouho
2327
        @date       2018.08.20
2328
    '''
2329
    def isNumber(self, num):
2330
        p = re.compile('(^[0-9]+$)')
2331
        result = p.match(num)
2332

    
2333
        if result:
2334
            return True
2335
        else:
2336
            return False
2337

    
2338
    '''
2339
        @brief      find overlap Connector
2340
        @author     kyouho
2341
        @date       2018.08.28
2342
    '''
2343
    def findOverlapConnector(self, connectorItem):
2344
        from shapely.geometry import Point
2345
        from EngineeringConnectorItem import QEngineeringConnectorItem
2346
        itemList = []
2347
        
2348
        x = connectorItem.center()[0]
2349
        y = connectorItem.center()[1]
2350

    
2351
        connectors = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringConnectorItem and item != connectorItem]
2352
        for connector in connectors:
2353
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
2354
                itemList.append(connector.parent)
2355

    
2356
        return itemList
2357

    
2358
if __name__ == '__main__':
2359
    import locale
2360
    from PyQt5.QtCore import QTranslator
2361
    from License import QLicenseDialog
2362
    from ProjectDialog import Ui_Dialog
2363
    from App import App 
2364

    
2365
    app = App(sys.argv)
2366
    try:
2367
        if True == QLicenseDialog.check_license_key():
2368
            dlg = Ui_Dialog()
2369
            selectedProject = dlg.showDialog()
2370
            if selectedProject is not None:
2371
                AppDocData.instance().setCurrentProject(selectedProject)
2372
                app._mainWnd = MainWindow.instance()
2373
                app._mainWnd.show()
2374
                sys.exit(app.exec_())
2375
    except Exception as ex:
2376
        print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
2377
    finally:
2378
        pass
2379