프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / MainWindow.py @ 41484c18

이력 | 보기 | 이력해설 | 다운로드 (104 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 EngineeringErrorItem import QEngineeringErrorItem
50
from AppDocData import *
51
import SymbolTreeWidget, SymbolPropertyTableWidget
52
import SymbolEditorDialog
53
import ItemTreeWidget
54
import ItemPropertyTableWidget
55
from UserInputAttribute import UserInputAttribute
56
from TextItemFactory import TextItemFactory
57
from TrainingImageListDialog import QTrainingImageListDialog
58

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

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

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

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

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

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

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

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

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

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

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

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

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

    
206
        # removedItems
207
        self.removedItems = {}
208
        self.removedItems['LINE'] = []
209
        self.removedItems['EQUIP'] = []
210
        self.removedItems['INST'] = []
211
        self.removedItems['NOTE'] = []
212

    
213
        self.delimiter = '"'
214
    
215
        self.resizeDocks({self.dockWidget}, {self.dockWidgetObjectExplorer.sizeHint().width()}, Qt.Horizontal)
216

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

    
225
        # load stylesheet file list
226
        stylesheet_name = QtWidgets.qApp.stylesheet_name
227
        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']
228
        for file in files:
229
            action = self.menuTheme.addAction(file)
230
            action.setCheckable(True)
231
            action.setChecked(True) if stylesheet_name == file else action.setChecked(False)
232
            action.triggered.connect(partial(self.load_stylesheet, file))
233
        # up to here
234

    
235
        # load language files
236
        language_name = QtWidgets.qApp.language_name
237
        files = ['en_us'] # englisgh is default language
238
        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'])
239
        for file in files:
240
            action = self.menuLanguage.addAction(file)
241
            action.setCheckable(True)
242
            action.setChecked(True) if language_name.lower() == file.lower() else action.setChecked(False)
243
            action.triggered.connect(partial(self.load_language, file))
244
        # up to here
245

    
246
        # inconsistency table
247
        self.tableWidgetInconsistency.setColumnCount(2)
248
        self.tableWidgetInconsistency.setHorizontalHeaderLabels(['Owner', 'Description'])
249
        self.tableWidgetInconsistency.itemClicked.connect(self.inconsistencyItemClickEvent)
250

    
251
    def onValidation(self):
252
        """
253
        @brief  validation check
254
        @author euisung
255
        @date   2019.04.01
256
        """
257
        if not self.graphicsView.hasImage():
258
            self.showImageSelectionMessageBox()
259
            return
260

    
261
        errors = []
262

    
263
        for item in self.graphicsView.scene.items():
264
            if type(item) is QEngineeringErrorItem:
265
                item.transfer.onRemoved.emit(item)
266
            if type(item) is QEngineeringLineItem:
267
                for error in item.validate():
268
                    errors.append(error)
269

    
270
        for error in errors:
271
            error.transfer.onRemoved.connect(self.itemRemoved)
272
            self.graphicsView.scene.addItem(error)
273

    
274
        self.tableWidgetInconsistency.clearContents()
275
        self.tableWidgetInconsistency.setRowCount(len(errors))
276
        for index in range(len(errors)):
277
            items = errors[index].makeTableRow()
278
            self.tableWidgetInconsistency.setItem(index, 0, items[0])
279
            self.tableWidgetInconsistency.setItem(index, 1, items[1])
280

    
281
    def inconsistencyItemClickEvent(self, item):
282
        """
283
        @brief  inconsistency table item clicked
284
        @author euisung
285
        @date   2019.04.02
286
        """
287
        from HighlightCommand import HighlightCommand
288

    
289
        HighlightCommand(self.graphicsView).execute(item.tag)
290
        #self.resultPropertyTableWidget.onSymbolClicked(item.tag)
291

    
292
    def load_stylesheet(self, file):
293
        """
294
        @brief  load stylesheets
295
        @author humkyung
296
        @date   2018.10.29
297
        """
298

    
299
        QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
300

    
301
        app_doc_data = AppDocData.instance()
302
        configs = [Config('app', 'stylesheet', file)]
303
        app_doc_data.saveAppConfigs(configs)
304
        
305
        for action in self.menuTheme.actions():
306
            if action.text() == file: continue
307
            action.setChecked(False)
308

    
309
    def load_language(self, file):
310
        """
311
        load language file and then apply selected language 
312
        """
313
        try:
314
            qm_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate', '{0}.qm'.format(file))
315
            QtWidgets.qApp.load_language(qm_file)
316

    
317
            app_doc_data = AppDocData.instance()
318
            configs = [Config('app', 'language', file)]
319
            app_doc_data.saveAppConfigs(configs)
320
            
321
            for action in self.menuLanguage.actions():
322
                if action.text().lower() == file.lower(): continue
323
                action.setChecked(False)
324
        finally:
325
            self.retranslateUi(self)
326
            self.propertyTableWidget.retranslateUi()
327

    
328
    '''
329
        @brief      Clear TreeWidget and Set Current PID
330
        @author     Jeongwoo
331
        @date       18.04.11
332
        @history    2018.04.26  Jeongwoo    Add Child [SYMBOLS, NOTES] into root item
333
                    2018.05.09  Jeongwoo    Change method to add default tree items
334
                    humkyung 2018.06.10 add tree item for Line No and Unknown Item
335
    '''
336
    def load_drawing_list(self):
337
        """
338
        @brief      load p&id drawing list
339
        @author     humkyung
340
        @date       18.11.02
341
        """
342

    
343
        try:
344
            appDocData = AppDocData.instance()
345
            drawings = appDocData.getDrawings()
346

    
347
            self.treeWidgetDrawingList.clear()
348
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList, [self.tr('P&ID Drawings'), ''])
349
            files = appDocData.getDrawingFileList()
350
            for file in files:
351
                drawing = [drawing for drawing in drawings if drawing[1] == file]
352
                if not drawing or not drawing[0]:
353
                    drawings.append([None, file, None])
354

    
355
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [file, drawing[0][2] if drawing and drawing[0] else ''])
356
                item.setIcon(0, QIcon(':newPrefix/image.png'))
357
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
358
                item.setCheckState(0, Qt.Unchecked)
359
            
360
            self.treeWidgetDrawingList.root.setText(0, self.tr('P&ID Drawings')+'({})'.format(self.treeWidgetDrawingList.root.childCount()))
361
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
362
            self.treeWidgetDrawingList.root.sortChildren(0, Qt.AscendingOrder)
363
            self.treeWidgetDrawingList.resizeColumnToContents(0)
364

    
365
            appDocData.saveDrawings(drawings)
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
    def open_selected_drawing(self, item, column):
371
        """
372
        @brief      open selected p&id drawing
373
        @author     humkyung
374
        @date       18.11.02
375
        """
376
        appDocData = AppDocData.instance()
377
        drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), item.text(column))
378
        self.onOpenImageDrawing(drawing)
379

    
380
    def onShowDetectSymbol(self):
381
        from DetectSymbolDialog import QDetectSymbolDialog
382

    
383
        dlgDetectSymbol = QDetectSymbolDialog(self)
384
        dlgDetectSymbol.show()
385
        dlgDetectSymbol.exec_()
386
        
387
    '''
388
        @brief      OCR Editor
389
        @author     euisung
390
        @date       2018.10.05
391
        @history    2018.10.16 euisung      no more used, Integrated with oCRTrainingClicked
392
    '''
393
    def oCRTrainingEdidorClicked(self):
394
        from TrainingEditorDialog import QTrainingEditorDialog
395

    
396
        try:
397
            dialog = QTrainingEditorDialog(self)
398
            dialog.exec_()
399
        except Exception as ex:
400
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
401
            self.addMessage.emit(MessageType.Error, message)
402
            
403
        return
404

    
405
    '''
406
        @brief      OCR Training
407
        @author     euisung
408
        @date       2018.09.27
409
        @history    euisung 2018.10.16 TrainingListDialog -> TrainingImageListDialog
410
    '''
411
    def oCRTrainingClicked(self):
412
        try:
413
            dialog = QTrainingImageListDialog(self)
414
            dialog.exec_()
415
        except Exception as ex:
416
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
417
            self.addMessage.emit(MessageType.Error, message)
418

    
419
    '''
420
        @brief      show unknownitem's count
421
        @author     kyouho
422
        @date       2018.08.27
423
    '''
424
    def findReplaceTextClicked(self):
425
        if not self.graphicsView.hasImage():
426
            self.showImageSelectionMessageBox()
427
            return
428

    
429
        from TextItemEditDialog import QTextItemEditDialog
430

    
431
        self.dlgTextItemEdit = QTextItemEditDialog(self)
432
        self.dlgTextItemEdit.show()
433
        self.dlgTextItemEdit.exec_()
434

    
435
    '''
436
        @brief      show unknownitem's count
437
        @author     humkyung
438
        @date       2018.08.23
439
        @history    humkyung 2018.08.30 display count of symbol, line, text
440
    '''
441
    def onSceneChanged(self):
442
        items = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
443
        if len(items) > 0:
444
            self.labelStatus.setText("<font color='red'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
445
        else:
446
            self.labelStatus.setText("<font color='black'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
447

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

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

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

    
457
        self.itemTreeWidget.sceneChanged(self.graphicsView.scene.items())
458

    
459
    def dbUpdate(self):
460
        '''
461
            @brief      db update when save or recognition
462
            @author     euisung
463
            @date       2018.11.12
464
            @history    2018.11.02      euisung     remove scene dependency
465
        '''
466
        from AppDocData import AppDocData
467

    
468
        try:
469
            appDocData = AppDocData.instance()
470

    
471
            titleBlockProps = appDocData.getTitleBlockProperties()
472
            #items = self.graphicsView.scene.items()
473
            items = appDocData.allItems
474
            titleBlockItems = []
475
            for item in items:
476
                #if type(item) is QEngineeringLineNoTextItem:
477
                #    item.saveLineData()
478
                if type(item) is QEngineeringTextItem:
479
                    for titleBlockProp in titleBlockProps:
480
                        if item.area == titleBlockProp[0]:
481
                            titleBlockItems.append(item)
482

    
483
            dbItems = [item for item in items if type(item) is QEngineeringInstrumentItem or type(item) is QEngineeringEquipmentItem or\
484
            type(item) is QEngineeringNoteItem or type(item) is SymbolSvgItem or type(item) is QEngineeringLineNoTextItem] + titleBlockItems
485
            appDocData.saveToDatabase(dbItems)
486
        except Exception as ex:
487
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
488
            self.addMessage.emit(MessageType.Error, message)
489

    
490
    '''
491
        @brief      action save click event
492
        @author     kyouho
493
        @date       2018.08.09
494
        @history    2018.11.02      euisung     add line data list db update
495
                    humkyung save saved time to database
496
                    2018.11.05      euisung     add note data list db update
497
                    2018.11.05      euisung     add db delete process before save
498
                    2018.11.12      euisung     db part move new method to dbUpdate
499
    '''
500
    def actionSaveCliked(self):
501
        from datetime import datetime
502
        from AppDocData import AppDocData
503

    
504
        appDocData = AppDocData.instance()
505
        if appDocData.imgName is None:
506
            self.showImageSelectionMessageBox()
507
            return
508

    
509
        appDocData.clearItemList(False)
510

    
511
        items = self.graphicsView.scene.items()
512
        for item in items:
513
            if type(item) is not QGraphicsPixmapItem:
514
                appDocData.allItems.append(item)
515
                if issubclass(type(item), QEngineeringTextItem):
516
                    appDocData.texts.append(item)
517
                #elif issubclass(type(item), SymbolSvgItem):
518
                #    appDocData.symbols.append(item)
519
        
520
        ##
521
        itemTypes = []
522
        for item in items:
523
            typeExist = False
524
            for itemType in itemTypes:
525
                if type(item) is itemType:
526
                    typeExist = True
527
                    break
528
            if not typeExist:
529
                itemTypes.append(type(item))
530
        ##
531

    
532
        self.dbUpdate()
533
        self.saveToXml(True)
534

    
535
        drawings = appDocData.getDrawings()
536
        drawing = [drawing for drawing in drawings if appDocData.imgName == os.path.splitext(drawing[1])[0]]
537
        if drawing[0]:
538
            drawing[0][2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
539
            appDocData.saveDrawings(drawing)
540

    
541
    '''
542
        @brief      save items to xml
543
        @author     kyouho
544
        @date       2018.07.31
545
    '''
546
    def saveToXml(self, alert = True):
547
        import XmlGenerator as xg
548
        from AppDocData import AppDocData
549
        docData = AppDocData.instance()
550
        if docData.imgName is None:
551
            self.showImageSelectionMessageBox()
552
            return
553
        result = xg.writeXmlOnScene(docData.imgName, docData.imgWidth, docData.imgHeight)
554
        
555
        if len(self.removedItems['LINE']):
556
            docData.deleteLineDataList_LineNo(self.removedItems['LINE'])
557
            self.removedItems['LINE'] = []
558

    
559
        if len(self.removedItems['EQUIP']):
560
            docData.deleteEquipDataList(self.removedItems['EQUIP'])
561
            self.removedItems['EQUIP'] = []
562

    
563
        if len(self.removedItems['INST']):
564
            docData.deleteInstDataList(self.removedItems['INST'])
565
            self.removedItems['INST'] = []
566

    
567
        if len(self.removedItems['NOTE']):
568
            docData.deleteNoteDataList(self.removedItems['NOTE'])
569
            self.removedItems['NOTE'] = []
570

    
571

    
572
        if alert:
573
            resultStr = '[저장 결과]'
574

    
575
            for item in result.items():
576
                itemName = str(item[0])
577
                itemSuccessCount = str(item[1][0])
578
                itemFailUidList = item[1][1]
579
                resultStr += "\r\n" + itemName + " Save Count : " + itemSuccessCount
580
                if len(itemFailUidList) > 0:
581
                    resultStr += "\r\n" + itemName + " Error List(UID)"
582
                    for uid in itemFailUidList:
583
                        resultStr += "\r\n" + uid
584

    
585
            QMessageBox.about(self.graphicsView, self.tr('Notice'), resultStr)
586

    
587
    '''
588
        @brief      refresh resultPropertyTableWidget
589
        @author     kyouho
590
        @date       2018.07.19
591
    '''
592
    def refreshResultPropertyTableWidget(self):
593
        items = self.graphicsView.scene.selectedItems()
594
        if len(items) == 1:
595
            self.resultPropertyTableWidget.showItemProperty(items[0])
596
    
597
    '''
598
        @brief      resultPropertyTableWidget Cell Click Event
599
        @author     kyouho
600
        @date       2018.08.23
601
    '''
602
    def cellClickedEvent(self, row, column):
603
        item = self.graphicsView.scene.selectedItems()
604
        if len(item) != 1:
605
            return
606
        item = item[0]
607

    
608
        cell = self.resultPropertyTableWidget.item(row, column)
609
        for valueCell, uid in self.resultPropertyTableWidget.attrValueList:
610
            if valueCell == cell and issubclass(type(item), SymbolSvgItem):
611
                for attr in item.attrs:
612
                    if attr.Attribute == uid and (issubclass(type(attr), SymbolSvgItem) or type(attr) is QEngineeringTextItem):
613
                        prevItem = item
614
                        currentItem = attr
615

    
616
                        rect = currentItem.sceneBoundingRect()
617
                        self.graphicsView.centerOn(rect.center())
618
                        self.graphicsView.zoomImage(True, QMouseEvent(QEvent.MouseButtonPress, self.graphicsView.mapFromScene(QPointF(rect.left(), rect.top())), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier), 3)
619
                        prevItem.setSelected(True)
620

    
621
                        currentItem.setHightlight()
622
                    elif (issubclass(type(attr), SymbolSvgItem) or type(attr) is QEngineeringTextItem):
623
                        attr.unsetHightlight()
624

    
625

    
626
    '''
627
        @brief  add message listwidget
628
        @author humkyung
629
        @date   2018.07.31
630
    '''
631
    def onAddMessage(self, messageType, message):
632
        from AppDocData import MessageType
633

    
634
        try:
635
            current = QDateTime.currentDateTime()
636

    
637
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
638
            if messageType == MessageType.Error:
639
                item.setBackground(Qt.red)
640

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

    
645
    '''
646
        @brief      clear log
647
        @author     humkyung
648
        @date       2018.08.01
649
    '''
650
    def onClearLog(self):
651
        self.listWidgetLog.clear()
652

    
653
    '''
654
        @brief      rotate selected symbol
655
        @author     humkyung
656
        @date       2018.08.15
657
    '''
658
    def onRotate(self, action):
659
        selected = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem)]
660
        if len(selected) == 1:
661
            selected[0].rotateSymbol()
662

    
663
    '''
664
        @brief      Area Zoom
665
        @author     Jeongwoo
666
        @date       2018.06.27
667
        @history    connect command's rejected signal
668
    '''
669
    def onAreaZoom(self, action):
670
        if self.actionZoom.isChecked():
671
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
672
            cmd.onRejected.connect(self.onCommandRejected)
673
            self.graphicsView.command = cmd
674

    
675
    '''
676
        @brief      Fit Window
677
        @author     Jeongwoo
678
        @date       2018.06.27
679
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
680
    '''
681
    def fitWindow(self, action):
682
        self.graphicsView.useDefaultCommand()
683
        self.graphicsView.zoomImageInit()
684

    
685
    def onConvertPDFToImage(self):
686
        """
687
        @brief      convert to selected pdf to image
688
        @author     humkyung 
689
        @date       2018.07.09
690
        @history    Euisung 2018.10.11 hide shell
691
        """
692
        try: 
693
            filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)) , 'bin64', 'PDF_TO_IMAGE.exe')
694
            subprocess.call(filePath, shell = False)
695
        except Exception as ex:
696
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
697

    
698
    '''
699
        @brief      selection changed
700
        @author     humkyung
701
        @date       2018.06.27
702
        @history    humkung 2018.07.08 call tree widget's findItem
703
    '''
704
    def onSelectionChanged(self):
705
        items = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem) or \
706
            type(item) is QEngineeringLineItem or type(item) is QEngineeringLineNoTextItem or type(item) is QEngineeringNoteItem or type(item) is QEngineeringUnknownItem]
707
        if items:
708
            item = items[-1]
709
            self.itemTreeWidget.findItem(item)
710
            self.resultPropertyTableWidget.showItemProperty(item)
711
        else:
712
            self.resultPropertyTableWidget.showItemProperty(None)
713
        
714
    '''
715
        @brief      Initialize scene and itemTreeWidget
716
        @author     Jeongwoo
717
        @date       2018.06.14
718
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
719
    '''
720
    def onInitializeScene(self, action):
721
        if not self.graphicsView.hasImage():
722
            self.actionEquipment.setChecked(False)
723
            self.showImageSelectionMessageBox()
724

    
725
            return
726

    
727
        msg = QMessageBox()
728
        msg.setIcon(QMessageBox.Critical)
729
        msg.setText(self.tr('선택한 인식한 항목들을 삭제하시겠습니까?\n삭제된 항목들은 복구할 수 없습니다.'))
730
        msg.setWindowTitle(self.tr("항목 삭제"))
731
        msg.setStandardButtons(QMessageBox.Ok|QMessageBox.Cancel)
732
        if QMessageBox.Ok == msg.exec_():
733

    
734
            appDocData = AppDocData.instance()
735
            appDocData.clearItemList(True)
736

    
737
            items = self.graphicsView.scene.items()
738
            for item in items:
739
                if type(item) is not QGraphicsPixmapItem:
740
                    self.graphicsView.scene.removeItem(item)
741

    
742
                    if type(item) is QEngineeringLineNoTextItem:
743
                        self.removedItems['LINE'].append(str(item.uid))
744
                    elif type(item) is QEngineeringInstrumentItem:
745
                        self.removedItems['INST'].append(str(item.uid))
746
                    elif type(item) is QEngineeringEquipmentItem:
747
                        self.removedItems['EQUIP'].append(str(item.uid))
748
                    elif type(item) is QEngineeringNoteItem:
749
                        self.removedItems['NOTE'].append(str(item.uid))
750
                    
751
            if self.path is not None:
752
                baseName = os.path.basename(self.path)
753
                self.itemTreeWidget.setCurrentPID(baseName)
754

    
755
    '''
756
        @brief      Manage Checkable Action statement
757
        @author     Jeongwoo
758
        @date       2018.05.10
759
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
760
    '''
761
    def actionGroupTriggered(self, action):
762
        if self.graphicsView.command is not None:
763
            self.graphicsView.useDefaultCommand()
764

    
765
        for _action in self.actionGroup.actions():
766
            _action.setChecked(False)
767

    
768
        action.setChecked(True)
769

    
770
    '''
771
        @brief      Create Equipment
772
        @author     Jeongwoo
773
        @date       18.05.03
774
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
775
    '''
776
    def createEquipment(self):
777
        if not self.graphicsView.hasImage():
778
            self.actionEquipment.setChecked(False)
779
            self.showImageSelectionMessageBox()
780
            return
781
        if self.actionEquipment.isChecked():
782
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget, self.dirTreeWidget)
783
        else:
784
            self.graphicsView.useDefaultCommand()
785

    
786

    
787
    '''
788
        @brief      Create Nozzle
789
        @author     Jeongwoo
790
        @date       2018.05.03
791
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
792
    '''
793
    def createNozzle(self):
794
        if not self.graphicsView.hasImage():
795
            self.actionNozzle.setChecked(False)
796
            self.showImageSelectionMessageBox()
797
            return
798
        if self.actionNozzle.isChecked():
799
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget, self.dirTreeWidget)
800
        else:
801
            self.graphicsView.useDefaultCommand()
802

    
803
    '''
804
        @brief      Area OCR
805
        @author     Jeongwoo
806
        @date       18.04.18
807
        @history    2018.05.02  Jeongwoo    Change graphicsView.command by actionOCR checked state
808
                                            Show MessageBox when imageviewer doesn't have image
809
    '''
810
    def onAreaOcr(self):
811
        if not self.graphicsView.hasImage():
812
            self.actionOCR.setChecked(False)
813
            self.showImageSelectionMessageBox()
814
            return
815

    
816
        if self.actionOCR.isChecked():
817
            cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView)
818
            cmd.onSuccess.connect(self.onRecognizeText)
819
            cmd.onRejected.connect(self.onCommandRejected)
820
            self.graphicsView.command = cmd
821
        else:
822
            self.graphicsView.useDefaultCommand()
823
    
824
    '''
825
        @brief      show text recognition dialog
826
        @author     humkyung
827
        @date       2018.08.08
828
    '''
829
    def onRecognizeText(self, x, y, width, height):
830
        from OcrResultDialog import QOcrResultDialog
831

    
832
        try:
833
            image = self.graphicsView.image().copy(x, y, width, height)
834
            dialog = QOcrResultDialog(self.graphicsView, image, QRectF(x, y, width, height))
835
            (isAccept, textInfoList) = dialog.showDialog()
836
            if isAccept:
837
                if textInfoList is not None and len(textInfoList) > 0:
838
                    docData = AppDocData.instance()
839
                    for textInfo in textInfoList:
840
                        x = textInfo.getX()
841
                        y = textInfo.getY()
842
                        angle = textInfo.getAngle()
843
                        text = textInfo.getText()
844
                        width = textInfo.getW()
845
                        height = textInfo.getH()
846
                        item = TextItemFactory.instance().createTextItem(textInfo)
847
                        if item is not None:
848
                            item.loc = (x, y)
849
                            item.size = (width, height)
850
                            item.angle = angle
851
                            item.setDefaultTextColor(Qt.blue)
852
                            item.addTextItemToScene(self.graphicsView.scene)
853
                            item.transfer.onRemoved.connect(self.itemRemoved)
854
                        else:
855
                            message = 'error occured({}) in {}:{}'.format('텍스트 생성에 실패했습니다.', sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
856
                            self.addMessage.emit(MessageType.Normal, message)
857
                else:
858
                    QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("Fail to recognize text"))
859
        except Exception as ex:
860
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
861
            self.addMessage.emit(MessageType.Error, message)
862

    
863
    '''
864
        @brief  area configuration
865
    '''
866
    def areaConfiguration(self):
867
        from ConfigurationAreaDialog import QConfigurationAreaDialog
868
        if not self.graphicsView.hasImage():
869
            self.showImageSelectionMessageBox()
870
            return
871
        self.dlgConfigurationArea = QConfigurationAreaDialog(self)
872
        self.dlgConfigurationArea.show()
873
        self.dlgConfigurationArea.exec_()
874
        self.graphicsView.useDefaultCommand()
875

    
876
    '''
877
        @brief  configuration
878
    '''
879
    def configuration(self):
880
        from ConfigurationDialog import QConfigurationDialog
881

    
882
        self.dlgConfiguration = QConfigurationDialog(self)
883
        self.dlgConfiguration.show()
884
        self.dlgConfiguration.exec_()
885

    
886
    '''
887
        @brief  show nominal diameter dialog 
888
        @author humkyung
889
        @date   2018.06.28
890
    '''
891
    def onShowCodeTable(self):
892
        from CodeTableDialog import QCodeTableDialog
893

    
894
        dlg = QCodeTableDialog(self)
895
        dlg.exec_()
896

    
897
    '''
898
        @brief  show HMB data
899
        @author humkyung
900
        @date   2018.07.11
901
    '''
902
    def onHMBData(self):
903
        from HMBDialog import QHMBDialog
904

    
905
        dlg = QHMBDialog(self)
906
        dlg.show()
907
        dlg.exec_()
908

    
909
    '''
910
        @brief  show line data list 
911
        @author humkyung
912
        @date   2018.05.03
913
    '''
914
    def showItemDataList(self):
915
        from ItemDataExportDialog import QItemDataExportDialog
916

    
917
        self.dlgLineDataList = QItemDataExportDialog(self)
918
        self.dlgLineDataList.exec_()
919

    
920
    '''
921
        @brief  Show Image Selection Guide MessageBox
922
        @author Jeongwoo
923
        @date   2018.05.02
924
    '''
925
    def showImageSelectionMessageBox(self):
926
        QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("First select image drawing"))
927
        
928
    '''
929
        @brief  change selected lines' type by selected line type
930
        @author humkyung
931
        @date   2018.06.27
932
    '''
933
    def onLineTypeChanged(self, param):
934
        lineType = self.lineComboBox.itemText(param)
935
        selected = [item for item in self.graphicsView.scene.selectedItems() if type(item) is QEngineeringLineItem]
936
        if selected:
937
            for item in selected:
938
                item.lineType = lineType
939

    
940
    '''
941
        @brief      Open image drawing file and then display it
942
        @author     humkyung
943
        @date       2018.??.??
944
        @history    18.04.23 Jeongwoo    Add AppDocData.instance().setCurrentPidSource
945
                    18.04.23 Jeongwoo    Add Store Set Current Pid Image on AppDocData
946
                    18.05.02 Jeongwoo    Add useDefaultCommand()
947
                    humkyung 2018.05.24 load recognition result file if exists
948
                    Jeongwoo 2018.05.29 load data on xml if xml file exist
949
                    humkyung 2018.08.22 clear scene before loading xml file
950
    '''
951
    def onOpenImageDrawing(self, path=None):
952
        from Drawing import Drawing
953
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
954

    
955
        try:
956
            appDocData = AppDocData.instance()
957
            project = appDocData.getCurrentProject()
958
            
959
            for item in self.graphicsView.scene.items():
960
                self.graphicsView.scene.removeItem(item)
961

    
962
            self.path = self.graphicsView.loadImageFromFile(project.getDrawingFilePath(), path if type(path) is str else '')
963
            if os.path.isfile(self.path):
964
                appDocData.clear()
965
                self.graphicsView.useDefaultCommand()
966

    
967
                appDocData.setImgFilePath(self.path)
968
                appDocData.activeDrawing = Drawing(appDocData.imgName)
969
                appDocData.setCurrentPidSource(Image.open(self.path))
970
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
971

    
972
                drawingList = self.treeWidgetDrawingList.topLevelItem(0)
973
                for childIdex in range(drawingList.childCount()):
974
                    drawingList.child(childIdex).setCheckState(0, Qt.Unchecked)
975
                for childIdex in range(drawingList.childCount()):
976
                    child = drawingList.child(childIdex)
977
                    if child.text(0).replace('.png', '') == appDocData.activeDrawing.name:
978
                        child.setCheckState(0, Qt.Checked)
979
                        break
980

    
981
                ## Load data on xml
982
                path = os.path.join(appDocData.getCurrentProject().getTempPath(), appDocData.imgName + '.xml')
983
                count = 0
984
                if os.path.isfile(path):
985
                    for child in parse(path).getroot().getchildren():
986
                        count = count + len(child.getchildren())
987
                if count > 0:
988
                    try:
989
                        self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, self) if not hasattr(self, 'progress') else self.progress
990
                        self.progress.setWindowModality(Qt.WindowModal)
991
                        self.progress.setAutoReset(True)
992
                        self.progress.setAutoClose(True)
993
                        self.progress.setMinimum(0)
994
                        self.progress.resize(600,100)
995
                        self.progress.setWindowTitle(self.tr("Reading file..."))
996
                        self.progress.show()
997

    
998
                        self.loadRecognitionResultFromXml(path)
999
                        self.checkAttribute()
1000
                    finally:
1001
                        self.progress.setValue(self.progress.maximum())
1002
                        self.progress.hide()
1003
                self.changeViewCheckedState(True)
1004
        except Exception as ex:
1005
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1006
            self.addMessage.emit(MessageType.Error, message)
1007

    
1008
        return self.path
1009

    
1010
    def changeViewCheckedState(self, checked):
1011
        '''
1012
            @brief      change view checked state
1013
            @author     euisung
1014
            @date       2019.03.06
1015
        '''
1016
        self.actionImage_Drawing.setChecked(checked)
1017
        self.actionViewText.setChecked(checked)
1018
        self.actionViewSymbol.setChecked(checked)
1019
        self.actionViewLine.setChecked(checked)
1020
        self.actionViewUnknown.setChecked(checked)
1021

    
1022
    '''
1023
        @brief  visible/invisible image drawing
1024
        @author humkyung
1025
        @date   2018.06.25
1026
    '''
1027
    def onViewImageDrawing(self, isChecked):
1028
        for item in self.graphicsView.scene.items():
1029
            if type(item) is QGraphicsPixmapItem:
1030
                item.setVisible(isChecked)
1031
                break
1032

    
1033
    '''
1034
        @brief  visible/invisible Text 
1035
        @author humkyung
1036
        @date   2018.06.28
1037
    '''
1038
    def onViewText(self, isChecked):
1039
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
1040
        for item in selected:
1041
            item.setVisible(isChecked)
1042

    
1043
    '''
1044
        @brief  visible/invisible Symbol 
1045
        @author humkyung
1046
        @date   2018.06.28
1047
    '''
1048
    def onViewSymbol(self, isChecked):
1049
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem)]
1050
        for item in selected:
1051
            item.setVisible(isChecked)
1052

    
1053
    '''
1054
        @brief  visible/invisible Line
1055
        @author humkyung
1056
        @date   2018.06.28
1057
    '''
1058
    def onViewLine(self, isChecked):
1059
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem]
1060
        for item in selected:
1061
            item.setVisible(isChecked)
1062

    
1063
    '''
1064
        @brief  visible/invisible Unknown 
1065
        @author humkyung
1066
        @date   2018.06.28
1067
    '''
1068
    def onViewUnknown(self, isChecked):
1069
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
1070
        for item in selected:
1071
            item.setVisible(isChecked)
1072

    
1073
    '''
1074
        @brief  create a symbol
1075
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
1076
                                            Add SymbolSvgItem
1077
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1078
                                            Change method to make svg and image path
1079
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
1080
    '''
1081
    def onCreateSymbolClicked(self):
1082
        cmd = FenceCommand.FenceCommand(self.graphicsView)
1083
        cmd.onSuccess.connect(self.onAreaSelected)
1084
        self.graphicsView.command = cmd
1085
        QApplication.setOverrideCursor(Qt.CrossCursor)
1086

    
1087
    '''
1088
        @brief      show SymbolEditorDialog with image selected by user
1089
        @author     humkyung
1090
        @date       2018.07.20
1091
    '''
1092
    def onAreaSelected(self, x, y, width, height):
1093
        try:
1094
            image = self.graphicsView.image()
1095
            if image is not None:
1096
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height), AppDocData.instance().getCurrentProject())
1097
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
1098
                self.dirTreeWidget.initDirTreeWidget()
1099
                if isAccepted:
1100
                    if isImmediateInsert:
1101
                        svgPath = newSym.getSvgFileFullPath()
1102
                        img = cv2.imread(newSym.getImageFileFullPath(), 1)
1103
                        w, h = (0, 0)
1104
                        if len(img.shape[::-1]) == 2:
1105
                            w, h = img.shape[::-1]
1106
                        else:
1107
                            _chan, w, h = img.shape[::-1]
1108
                        svg = SymbolSvgItem(svgPath)
1109
                        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)
1110

    
1111
                        svg.transfer.onRemoved.connect(self.itemTreeWidget.itemRemoved)
1112
                        svg.addSvgItemToScene(self.graphicsView.scene)
1113
                        for connector in svg.connectors:
1114
                            self.graphicsView.scene.addItem(connector)
1115
        finally:
1116
            self.graphicsView.useDefaultCommand()
1117
            QApplication.restoreOverrideCursor()
1118
    
1119
    '''
1120
        @brief      create a line
1121
        @author     humkyung
1122
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
1123
    '''
1124
    def onPlaceLine(self):        
1125
        if not self.graphicsView.hasImage():
1126
            self.actionLine.setChecked(False)
1127
            self.showImageSelectionMessageBox()
1128
            return
1129

    
1130
        self.actionLine.setChecked(True)
1131
        if not hasattr(self.actionLine, 'tag'):
1132
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
1133
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
1134
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
1135

    
1136
        self.graphicsView.command = self.actionLine.tag
1137

    
1138
    '''
1139
        @brief      add created lines to scene
1140
        @author     humkyung
1141
        @date       2018.07.23
1142
    '''
1143
    def onLineCreated(self):
1144
        from EngineeringConnectorItem import QEngineeringConnectorItem
1145

    
1146
        try:
1147
            count = len(self.actionLine.tag._polyline._vertices)
1148
            if count > 1:
1149
                items = []
1150

    
1151
                lineType = self.lineComboBox.currentText()
1152
                for index in range(count - 1):
1153
                    start = self.actionLine.tag._polyline._vertices[index]
1154
                    end  = self.actionLine.tag._polyline._vertices[index + 1]
1155
                    
1156
                    lineItem = QEngineeringLineItem(vertices=[start, end])
1157
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
1158
                    lineItem.lineType = lineType
1159
                    if items:
1160
                        lineItem.connectIfPossible(items[-1], 5)
1161
                    else:
1162
                        pt = lineItem.startPoint()
1163
                        selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
1164
                        if selected is not None and type(selected) is QEngineeringConnectorItem:
1165
                            lineItem.connectIfPossible(selected.parent, 5)
1166
                    
1167
                    items.append(lineItem)
1168
                    self.graphicsView.scene.addItem(lineItem)
1169

    
1170
                pt = items[-1].endPoint()
1171
                selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
1172
                if selected is not None and type(selected) is QEngineeringConnectorItem:
1173
                    items[-1].connectIfPossible(selected.parent, 5)
1174
        finally:
1175
            self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1176
            self.actionLine.tag.reset()
1177

    
1178
    '''
1179
        @brief      refresh scene
1180
        @author     humkyung
1181
        @date       2018.07.23
1182
    '''
1183
    def onCommandRejected(self, cmd):
1184
        try:
1185
            if type(cmd) is PlaceLineCommand.PlaceLineCommand:
1186
                self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1187
                self.graphicsView.scene.update()
1188
                self.actionLine.tag.reset()
1189

    
1190
                self.actionLine.setChecked(False)
1191
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
1192
                self.actionZoom.setChecked(False)
1193
            elif type(cmd) is AreaOcrCommand.AreaOcrCommand:
1194
                self.actionOCR.setChecked(False)
1195
        finally:
1196
            self.graphicsView.useDefaultCommand()
1197
     
1198
    '''
1199
        @brief      restore to default command when user press Escape key
1200
        @author     humkyung 
1201
        @date       2018.08.09
1202
    '''
1203
    def keyPressEvent(self, event):
1204
        try:
1205
            if event.key() == Qt.Key_Escape:
1206
                checked = self.actionGroup.checkedAction()
1207
                if checked:
1208
                    checked.setChecked(False)
1209
                    self.graphicsView.useDefaultCommand()
1210

    
1211
            QMainWindow.keyPressEvent(self, event)
1212
        except Exception as ex:
1213
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1214
            self.addMessage.emit(MessageType.Error, message)
1215
    
1216
    def recognizeBatch(self, MainWindow):
1217
        '''
1218
            @brief      batch recognize symbol, text and line
1219
            @author     euisung
1220
            @date       2018.11.23
1221
        
1222
        '''
1223
        from datetime import datetime
1224
        from RecognitionDialog import QRecognitionDialog
1225

    
1226
        appDocData = AppDocData.instance()
1227
        project = appDocData.getCurrentProject()
1228
        appDocData.needReOpening = None
1229
        currentPid = None
1230
        
1231
        if self.graphicsView.hasImage():
1232
            currentPid = appDocData.activeDrawing.name
1233

    
1234
        drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1235
        drawingCount = drawingTop.childCount()
1236
        checkedTreeItems = []
1237
        checkedDrawingPath = []
1238
        for drawing in range(drawingCount):
1239
            drawingChild = drawingTop.child(drawing)
1240
            if drawingChild.checkState(0) == 2:
1241
                checkedTreeItems.append(drawingChild)
1242
                checkedDrawingPath.append(os.path.join(project.getDrawingFilePath(), drawingChild.data(0, 0)))
1243
                if currentPid is not None and drawingChild.data(0, 0).find(currentPid) is 0:
1244
                    appDocData.needReOpening = False # later check need reopening at drawUnknownItems()
1245
                    currentPid = drawingChild.data(0, 0)
1246

    
1247
        if len(checkedDrawingPath) == 0:
1248
            self.showImageSelectionMessageBox()
1249
            return
1250

    
1251
        try:
1252
            self.onClearLog()
1253
            self.dlg = QRecognitionDialog(self, checkedDrawingPath, True)
1254
            self.dlg.exec_()
1255
            if self.dlg.isAccepted == True:
1256
                pass
1257

    
1258
            if appDocData.needReOpening == True:
1259
                drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), currentPid)
1260
                self.onOpenImageDrawing(drawing)
1261

    
1262
            # save working date-time
1263
            drawings = appDocData.getDrawings()
1264
            checkedDrawings = []
1265
            for checkedTreeItem in checkedTreeItems:
1266
                for drawing in drawings:
1267
                    if checkedTreeItem.data(0, 0) == drawing[1]:
1268
                        if drawing[0]:
1269
                            drawing[2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1270
                            checkedDrawings.append(drawing)
1271
                            checkedTreeItem.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1272
            appDocData.saveDrawings(checkedDrawings)
1273
            # up to here
1274
        except Exception as ex:
1275
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1276
            self.addMessage.emit(MessageType.Error, message)
1277

    
1278
    '''
1279
        @brief      recognize symbol and text
1280
        @author     humkyung
1281
        @date       2018.04.??
1282
        @history    2018.04.16  humkyung    execute line no tracing
1283
                    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
1284
                    2018.05.25  Jeongwoo    Add parameter on QRecognitionDialog.__init__() and Move thread to QRecognitionDialog
1285
                                            Remove codes below if self.dlg.isAccepted == True
1286
                    2018.05.29  Jeongwoo    Remove connects and comments
1287
                    humkyung 2018.11.05 save working date-time
1288
    '''
1289
    def recognize(self, MainWindow):
1290
        from datetime import datetime
1291
        from RecognitionDialog import QRecognitionDialog
1292

    
1293
        if not self.graphicsView.hasImage():
1294
            self.showImageSelectionMessageBox()
1295
            return
1296

    
1297
        try:
1298
            self.removedItems['LINE'] = []
1299
            self.removedItems['EQUIP'] = []
1300
            self.removedItems['INST'] = []
1301
            self.removedItems['NOTE'] = []
1302

    
1303
            appDocData = AppDocData.instance()
1304

    
1305
            self.onClearLog()
1306
            appDocData.needReOpening = False
1307
            drawingList = []
1308
            drawingList.append(self.path)
1309
            self.dlg = QRecognitionDialog(self, drawingList, False)
1310
            self.dlg.exec_()
1311

    
1312
            if appDocData.needReOpening == True:
1313
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
1314
                self.drawDetectedItemsToScene()
1315
                
1316
                # save working date-time
1317
                drawings = appDocData.getDrawings()
1318
                drawing = [drawing for drawing in drawings if appDocData.imgName == os.path.splitext(drawing[1])[0]]
1319
                if drawing[0]:
1320
                    drawing[0][2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1321
                    appDocData.saveDrawings(drawing)
1322

    
1323
                currentPid = appDocData.activeDrawing.name
1324

    
1325
                drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1326
                drawingCount = drawingTop.childCount()
1327
                
1328
                for drawing in range(drawingCount):
1329
                    drawingChild = drawingTop.child(drawing)
1330
                    if drawingChild.data(0, 0).find(currentPid) is 0:
1331
                        drawingChild.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1332
                self.changeViewCheckedState(True)
1333
                # up to here
1334
        except Exception as ex:
1335
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1336
            self.addMessage.emit(MessageType.Error, message)
1337

    
1338
    '''
1339
        @brief      remove item from tree widget and then remove from scene
1340
        @date       2018.05.25
1341
        @author     Jeongwoo
1342
    '''
1343
    def itemRemoved(self, item):
1344
        try:
1345
            self.itemTreeWidget.itemRemoved(item)
1346

    
1347
            if type(item) is QEngineeringLineNoTextItem:
1348
                self.removedItems['LINE'].append(str(item.uid))
1349
            elif type(item) is QEngineeringInstrumentItem:
1350
                self.removedItems['INST'].append(str(item.uid))
1351
            elif type(item) is QEngineeringEquipmentItem:
1352
                self.removedItems['EQUIP'].append(str(item.uid))
1353
            elif type(item) is QEngineeringNoteItem:
1354
                self.removedItems['NOTE'].append(str(item.uid))
1355

    
1356
            if hasattr(item, 'connectors'):
1357
                for sceneItem in self.graphicsView.scene.items():
1358
                    if hasattr(sceneItem, 'connectors'):
1359
                        for sceneConnector in sceneItem.connectors:
1360
                            if sceneConnector.connectedItem is not None and item.uid == sceneConnector.connectedItem.uid:
1361
                                sceneConnector.connectedItem = None
1362

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

    
1368
    '''
1369
        @brief      recognize line
1370
        @author     humkyung
1371
        @date       2018.04.19
1372
        @history    Jeongwoo 2018.04.26 Variable name changed (texts → lineNos)
1373
                                        TextItem type changed (QEngineeringTextItem → QEngineeringLineNoTextItem)
1374
                    humkyung 2018.04.26 remove small objects before recognizing line
1375
                    Jeongwoo 2018.05.02 Show MessageBox when imageviewer doesn't have image
1376
                    Jeongwoo 2018.05.25 Move codes about LineDetector
1377
                    humkyung 2018.06.17 show progress dialog
1378
    '''
1379
    def recognizeLine(self, MainWindow):
1380
        from LineNoTracer import LineNoTracer
1381
        from ConnectAttrDialog import QConnectAttrDialog
1382

    
1383
        if not self.graphicsView.hasImage():
1384
            self.showImageSelectionMessageBox()
1385
            return
1386

    
1387
        try:
1388
            self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView)
1389
            self.dlgConnectAttr.exec_()
1390

    
1391
            self.itemTreeWidget.InitLineNoItems()
1392

    
1393
            # construct line no item
1394
            docData = AppDocData.instance()
1395
            for lineno in docData.tracerLineNos:
1396
                item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, lineno)
1397
                connectedItems = lineno.getConnectedItems()
1398
                for connectedItem in connectedItems:
1399
                    if issubclass(type(connectedItem), SymbolSvgItem): 
1400
                        self.itemTreeWidget.addTreeItem(item, connectedItem)
1401
            # up to here
1402
        except Exception as ex:
1403
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1404
            self.addMessage.emit(MessageType.Error, message)
1405

    
1406
    '''
1407
        @history    2018.05.25  Jeongwoo    Moved from MainWindow
1408
                                            SvgItem and TextItem Connect with method in this class
1409
                                            Change method to add GraphicsItem
1410
                    2018.05.28  Jeongwoo    Make QGraphicsItem by symbol, text object. Not xml
1411
                    2018.05.29  Jeongwoo    Change method name and Moved from QRecognitionDialog
1412
                    2018.05.30  Jeongwoo    Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol)
1413
                                            Change Method name and seperate each item
1414
                    humkyung 2018.06.11     display difference between original and recognized image
1415
                    Jeongwoo 2018.06.18     Update Scene after all item added
1416
                    2018.11.05  euisung     add save note item because of dependency
1417
                    2018.11.05  euisung     add db delete process before save
1418
                    2018.11.12  euisung     add title block properties
1419
                    2018.11.12  euisung     db part move new method to dbUpdate
1420
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1421
                    2018.11.29  euisung     change name drawDetectedItems() -> createDetectedItems
1422
    '''
1423
    def createDetectedItems(self, symbolList, textInfoList, otherTextInfoList, titleBlockTextInfoList):
1424
        try:
1425
            appDocData = AppDocData.instance()
1426

    
1427
            QApplication.processEvents()
1428
            self.createDetectedSymbolItem(symbolList)
1429
            QApplication.processEvents()
1430
            self.createDetectedTextItem(textInfoList)
1431
            QApplication.processEvents()
1432
            self.createDetectedOtherTextItem(otherTextInfoList)
1433
            QApplication.processEvents()
1434
            self.createDetectedTitleBlockTextItem(titleBlockTextInfoList)
1435

    
1436
            self.dbUpdate()
1437
            #self.saveToXml(False)
1438

    
1439
            # update scene
1440
            #self.graphicsView.scene.update(self.graphicsView.sceneRect())
1441
        except Exception as ex:
1442
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1443
            self.addMessage.emit(MessageType.Error, message)
1444

    
1445
    def drawDetectedItemsToScene(self):
1446
        '''
1447
            @brief  add detected items to scene
1448
            @author euisung
1449
            @date   2018.11.26
1450
        '''
1451
        appDocData = AppDocData.instance()
1452

    
1453
        try:
1454
            for symbol in appDocData.symbols:
1455
                if issubclass(type(symbol), SymbolSvgItem):
1456
                    self.addSvgItemToScene(symbol)
1457
                else:
1458
                    self.graphicsView.scene.addItem(symbol)
1459

    
1460
            for text in appDocData.texts:
1461
                self.addTextItemToScene(text)
1462

    
1463
            for line in appDocData.lines:
1464
                self.graphicsView.scene.addItem(line)
1465
                for conn in line.connectors:
1466
                    conn.transfer.onPosChanged.connect(line.onConnectorPosChaned)
1467

    
1468
            for unknown in appDocData.unknowns + appDocData.lineIndicators:
1469
                self.addUnknownItemToScene(unknown)
1470
        finally:
1471
            # update scene
1472
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1473

    
1474
    def postDetectLineProcess(self):
1475
        '''
1476
            @brief  check allowables among undetected items
1477
            @author euisung
1478
            @date   2018.11.15
1479
            @history    2018.11.15  euisung    no more used, moved to TextItemFactoy isLineNo()
1480
        '''
1481
        from AppDocData import AppDocData
1482
        from TextItemFactory import TextItemFactory
1483

    
1484
        appDocData = AppDocData.instance()
1485

    
1486
        tableNames = ["Fluid Code", "Insulation Purpose", "PnID Number", "Piping Materials Class", "Unit Number"]
1487
        tableDatas = []
1488
        for tableName in tableNames:
1489
            tableNameFormat = tableName.replace(' ','').replace('&&', 'n')
1490
            tableDatas.append(appDocData.getCodeTable(tableNameFormat))
1491

    
1492
        items = self.graphicsView.scene.items()
1493
        for item in items:
1494
            if type(item) is not QEngineeringTextItem:
1495
                continue
1496
            text = item.text()
1497
            for tableData in tableDatas:
1498
                for data in tableData:
1499
                    if data[3] == '':
1500
                        continue
1501
                    else:
1502
                        allows = data[3].split(',')
1503
                        for allow in allows:
1504
                            text = text.replace(allow, data[1])
1505

    
1506
            lineItem = TextItemFactory.instance().createTextItem(text)
1507
            if type(lineItem) is QEngineeringLineNoTextItem:
1508
                lineItem.loc = item.loc
1509
                lineItem.size = item.size
1510
                lineItem.angle = item.angle
1511
                lineItem.area = item.area
1512
                #lineItem.addTextItemToScene(self.graphicsView.scene)
1513
                lineItem.transfer.onRemoved.connect(self.itemRemoved)
1514
                item.transfer.onRemoved.emit(item)
1515
                appDocData.lineNos.append(lineItem)
1516
                
1517
    def createDetectedTitleBlockTextItem(self, textInfoList):
1518
        '''
1519
            @brief  draw title block
1520
            @author euisung
1521
            @date   2018.11.12
1522
            @history    2018.11.26  euisung     remove scene dependency
1523
                        2018.11.29  euisung     change name drawDetectedTitleBlockTextItem() -> createDetectedTitleBlockTextItem
1524
        '''
1525
        from TextItemFactory import TextItemFactory
1526
        import math
1527

    
1528
        try:
1529
            appDocData = AppDocData.instance()
1530

    
1531
            # parse texts
1532
            for textInfo in textInfoList:
1533
                if len(textInfo[1]) is 0:
1534
                    continue
1535
                x = textInfo[1][0].getX()
1536
                y = textInfo[1][0].getY()
1537
                width = textInfo[1][0].getW()
1538
                height = textInfo[1][0].getH()
1539
                angle = round(math.radians(textInfo[1][0].getAngle()), 2)
1540
                text = textInfo[1][0].getText()
1541
                item = TextItemFactory.instance().createTextItem(textInfo)
1542

    
1543
                if item is not None:
1544
                    item.loc = (x, y)
1545
                    item.size = (width, height)
1546
                    item.angle = angle
1547
                    item.area = textInfo[0]
1548
                    #self.addTextItemToScene(item)
1549
                    appDocData.texts.append(item)
1550
                    appDocData.allItems.append(item)
1551
        except Exception as ex:
1552
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1553
            self.addMessage.emit(MessageType.Error, message)
1554

    
1555
    '''
1556
        @brief      
1557
        @author     humkyung
1558
        @date       2018.08.23
1559
        @history    2018.11.26  euisung     remove scene dependency
1560
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1561
                    2018.11.    euisung     no more used
1562
                    2018.11.29  euisung     change name drawDetectedLines() -> createDetectedLines
1563
    '''
1564
    def createDetectedLines(self, lineList, worker):
1565
        appDocData = AppDocData.instance()
1566
        area = appDocData.getArea('Drawing')
1567

    
1568
        for pts in lineList:
1569
            processLine = QEngineeringLineItem(vertices=[(area.x + param[0], area.y + param[1]) for param in pts])
1570
            processLine.area = 'Drawing'
1571
            #self.graphicsView.scene.addItem(processLine)
1572
            appDocData.lines.append(processLine)
1573
            appDocData.allItems.append(processLine)
1574

    
1575
            if processLine.length() > 100: # TODO: check critical length
1576
                processLine.addFlowArrow()
1577
        
1578
        # re-order process line's start,end according to flow mark
1579
        #worker.arrangeLinePosition(lines, symbols, listWidget)
1580
        # up to here
1581

    
1582
    '''
1583
        history     2018.06.09  humkyung    check length of original and connection point is 2 while parsing
1584
                    2018.11.26  euisung     remove scene dependency
1585
                    2018.11.29  euisung     change name drawDetectedSymbolItem() -> createDetectedSymbolItem
1586
    '''
1587
    def createDetectedSymbolItem(self, symbolList):
1588
        from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
1589
        from SymbolSvgItem import SymbolSvgItem
1590
        import math
1591

    
1592
        try:
1593
            appDocData = AppDocData.instance()
1594
            project = appDocData.getCurrentProject()
1595

    
1596
            searchedMap = []
1597
            for symbol in symbolList:
1598
                pt = [float(x) for x in symbol.getSp()]
1599
                size = [symbol.getWidth(), symbol.getHeight()]
1600
                name = symbol.getName()
1601
                angle = round(math.radians(symbol.getRotatedAngle()), 2)
1602
                _type = symbol.getType()
1603
                origin = [0,0]
1604
                if 2 == len(symbol.getOriginalPoint().split(',')):
1605
                    tokens = symbol.getOriginalPoint().split(',')
1606
                    origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
1607
                connPts = []
1608
                if symbol.getConnectionPoint() is not None and symbol.getConnectionPoint() != '':
1609
                    for param in symbol.getConnectionPoint().split('/'):
1610
                        tokens = param.split(',')
1611
                        connPts.append(('AUTO', pt[0] + float(tokens[0]), pt[1] + float(tokens[1]), '0') if len(tokens) == 2 else \
1612
                                       (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), '0') if len(tokens) == 3 else \
1613
                                       (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), tokens[3]) if len(tokens) == 4 else None)
1614

    
1615
                parentSymbol = symbol.getBaseSymbol()
1616
                childSymbol = symbol.getAdditionalSymbol()
1617
                hasInstrumentLabel = symbol.getHasInstrumentLabel()
1618

    
1619
                svgFilePath = os.path.join(project.getSvgFilePath(), _type, name + '.svg')
1620
                if os.path.isfile(svgFilePath):
1621
                    svg = SymbolSvgItem.createItem(_type, svgFilePath)
1622
                    svg.buildItem(name, _type, angle, pt, size, origin, connPts, parentSymbol, childSymbol, hasInstrumentLabel)
1623
                    svg.reCalculationRotatedItem()
1624
                    svg.area = 'Drawing'
1625

    
1626
                    # set owner - 2018.07.20 added by humkyung                   
1627
                    matches = [searched for searched in searchedMap if searched[0] == symbol.owner]
1628
                    if len(matches) == 1:
1629
                        svg.owner = matches[0][1]
1630
                    searchedMap.append((symbol, svg))
1631
                    # up to here
1632

    
1633
                    svg.transfer.onRemoved.connect(self.itemRemoved)
1634
                    #self.addSvgItemToScene(svg)
1635
                    appDocData.symbols.append(svg)
1636
                    appDocData.allItems.append(svg)
1637
                else:
1638
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
1639
                    item.isSymbol = True
1640
                    item.angle = angle
1641
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
1642
                    #self.graphicsView.scene.addItem(item)
1643
                    appDocData.symbols.append(item)
1644
                    appDocData.allItems.append(item)
1645
            # up to here
1646
        except Exception as ex:
1647
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1648
            self.addMessage.emit(MessageType.Error, message)
1649

    
1650
    '''
1651
        @history    2018.06.08  Jeongwoo    Add parameter on round method
1652
        @history    2018.11.02  euisung     Add save note text item
1653
        @history    2018.11.05  euisung     delete save note text item and move to drawDetectedItems()
1654
                    2018.11.26  euisung     remove scene dependency
1655
                    2018.11.29  euisung     change name drawDetectedTextItem() -> createDetectedTextItem
1656
    '''
1657
    def createDetectedTextItem(self, textInfoList):
1658
        from TextItemFactory import TextItemFactory
1659
        import math
1660

    
1661
        try:
1662
            appDocData = AppDocData.instance()
1663

    
1664
            # parse texts
1665
            for textInfo in textInfoList:
1666
                x = textInfo.getX()
1667
                y = textInfo.getY()
1668
                width = textInfo.getW()
1669
                height = textInfo.getH()
1670
                angle = round(math.radians(textInfo.getAngle()), 2)
1671
                text = textInfo.getText()
1672
                if not text: continue
1673

    
1674
                item = TextItemFactory.instance().createTextItem(textInfo)
1675
                if item is not None:
1676
                    item.loc = (x, y)
1677
                    item.size = (width, height)
1678
                    item.angle = angle
1679
                    item.area = 'Drawing'
1680
                    item.transfer.onRemoved.connect(self.itemRemoved)
1681
                    #self.addTextItemToScene(item)
1682
                    appDocData.texts.append(item)
1683
                    appDocData.allItems.append(item)
1684
        except Exception as ex:
1685
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1686
            self.addMessage.emit(MessageType.Error, message)
1687

    
1688
    '''
1689
        @brief      draw detected texts except which in drawing area
1690
        @history    2018.11.29  euisung     change name drawDetectedOtherTextItem() -> createDetectedOtherTextItem
1691
    '''
1692
    def createDetectedOtherTextItem(self, otherTextInfoList):
1693
        from TextItemFactory import TextItemFactory
1694
        import math
1695

    
1696
        try:
1697
            appDocData = AppDocData.instance()
1698

    
1699
            # parse notes
1700
            for textInfoMap in otherTextInfoList:
1701
                if textInfoMap[0]=='Note':
1702
                    pass
1703

    
1704
                for textInfo in textInfoMap[1]:
1705
                    x = textInfo.getX()
1706
                    y = textInfo.getY()
1707
                    width = textInfo.getW()
1708
                    height = textInfo.getH()
1709
                    angle = round(math.radians(textInfo.getAngle()))
1710
                    text = textInfo.getText()
1711

    
1712
                    item = TextItemFactory.instance().createTextItem(textInfo)
1713

    
1714
                    item.loc = (x, y)
1715
                    item.size = (width, height)
1716
                    item.angle = angle
1717
                    item.area = textInfoMap[0]
1718
                    item.transfer.onRemoved.connect(self.itemRemoved)
1719
                    appDocData.texts.append(item)
1720
                    appDocData.allItems.append(item)
1721
        except Exception as ex:
1722
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1723
            self.addMessage.emit(MessageType.Error, message)
1724

    
1725
    '''
1726
        @brief  draw unknown items 
1727
        @author humkyung
1728
        @date   2018.06.12
1729
        @history    2018.06.14  Jeongwoo    Change method to add unknown item
1730
                    2018.06.18  Jeongwoo    Add connect on unknown item
1731
                                            Add [transfer] for using pyqtSignal
1732
                    2018.11.26  euisung     remove scene dependency
1733
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1734
                    2018.11.27  euisung     add save to xml
1735
                    2018.11.29  euisung     change name drawUnknownItems() -> createUnknownItems
1736
    '''
1737
    def createUnknownItems(self, path):
1738
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem 
1739
        from EngineeringLineItem import QEngineeringLineItem
1740
        from EngineeringUnknownItem import QEngineeringUnknownItem
1741

    
1742
        try:
1743
            docData = AppDocData.instance()
1744
            project = docData.getCurrentProject()
1745
            windowSize = docData.getSlidingWindowSize()
1746
            thickness = int(windowSize[1])
1747

    
1748
            if docData.needReOpening is not None:
1749
                docData.needReOpening = True
1750

    
1751
            diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(path))
1752
            if os.path.isfile(diffFilePath):
1753
                imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1]
1754

    
1755
                ## remove line
1756
                lines = docData.lines
1757
                for line in lines:
1758
                    line.drawToImage(imgDiff, 255, thickness) if line.thickness is None else line.drawToImage(imgDiff, 255, line.thickness)
1759
                cv2.imwrite(diffFilePath, imgDiff)
1760
                ## up to here
1761

    
1762
                imgNot = np.ones(imgDiff.shape, np.uint8)
1763
                cv2.bitwise_not(imgDiff, imgNot)
1764
                imgNot = cv2.dilate(imgNot, np.ones((8,8), np.uint8))
1765

    
1766
                image, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
1767

    
1768
                ##
1769
                idx = 0
1770
                ##
1771
                smallContours = []
1772
                minimumSize = docData.getConfigs('Filter', 'MinimumSize')
1773
                for contour in contours:
1774
                    [x, y, w, h] = cv2.boundingRect(contour)
1775

    
1776
                    # remove too small one
1777
                    if len(minimumSize) is 1:
1778
                        if (w * h < int(minimumSize[0].value) * int(minimumSize[0].value)):
1779
                            smallContours.append(contour)
1780
                            idx += 1
1781
                            continue
1782

    
1783
                    '''
1784
                    rect = QRectF(x, y, w, h)
1785
                    items = [item for item in diffItems if item.boundingRect().contains(rect)]
1786
                    if len(items) > 0: continue
1787
                    
1788
                    items = [item for item in diffItems if rect.contains(item.boundingRect())]
1789
                    for item in items:
1790
                        diffItems.remove(item)
1791
                    '''
1792

    
1793
                    # create unknown item
1794
                    epsilon = cv2.arcLength(contour, True)*0.001
1795
                    approx = cv2.approxPolyDP(contour, epsilon, True)
1796
                    approx = [pt[0] for pt in approx]
1797
                    resultStr, resultList = self.determineRemainObject(idx, contours, imgNot)
1798
                    if resultStr == 'LineIndicator':
1799
                        item = QEngineeringUnknownItem(approx, 'True', resultList[0], resultList[1])
1800
                        docData.lineIndicators.append(item)
1801
                    elif resultStr == 'MissingLine':
1802
                        pass
1803
                    elif resultStr == 'Unknown':
1804
                        item = QEngineeringUnknownItem(approx, 'False')
1805
                        docData.unknowns.append(item)
1806
                    item.area = 'Drawing'
1807
                    docData.allItems.append(item)
1808
                    item.transfer.onRemoved.connect(self.itemRemoved)
1809
                    idx += 1
1810
                    # up to here                    
1811

    
1812
                imgNotRemoveSmall = cv2.drawContours(imgNot, smallContours, -1, 0, -1)
1813
                notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(path))
1814
                cv2.imwrite(notFilePath, imgNotRemoveSmall)
1815
            else:
1816
                message = 'can\'t found {}'.format(diffFilePath)
1817
                self.addMessage.emit(MessageType.Normal, message)
1818

    
1819
            self.saveToXml(False)
1820
        except Exception as ex:
1821
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1822
            self.addMessage.emit(MessageType.Error, message)
1823

    
1824
    def determineRemainObject(self, idx, contours, imgNot):
1825
        '''
1826
            @brief      determine remain objects -> line no indicator or unknown
1827
            @author     euisung
1828
            @date       2018.12.26
1829
            @history    2019.03.25  euisung    Change name isLineNoIndicator -> determineRemainObject
1830
        '''
1831
        import math
1832
        [x, y, w, h] = cv2.boundingRect(contours[idx])
1833
        
1834
        if (w < 250 and h < 250):
1835
            return ('Unknown', [])
1836
        
1837
        fLines = []
1838
        maxDifAngle = 3
1839
        mask = np.zeros_like(imgNot)
1840
        cv2.drawContours(mask, contours, idx, 123, -1) # Draw filled contour in mask
1841
        out = np.zeros_like(imgNot) # Extract out the object and place into output image
1842
        out[mask == 123] = imgNot[mask == 123]
1843

    
1844
        # Now crop
1845
        ##print(out)
1846
        (x, y) = np.where(mask == 123)
1847
        (topx, topy) = (np.min(x), np.min(y))
1848
        (bottomx, bottomy) = (np.max(x), np.max(y))
1849
        out = out[topx:bottomx+1, topy:bottomy+1]
1850
        h, w = out.shape[0], out.shape[1]
1851
        maxDifH, maxDifW = math.ceil(math.tan(4 * math.pi / 180) / 2 * w), math.ceil(math.tan(4 * math.pi / 180) / 2 * h)
1852

    
1853
        # detection lines
1854
        edged2 = cv2.Canny(out, 100, 200)
1855
        lines = cv2.HoughLinesP(image=edged2, rho=1, theta=np.pi/180, threshold=25, minLineLength=30, maxLineGap=25)
1856
        #lines = cv2.HoughLines(edged2, 1, np.pi/180, 60)
1857
        if lines is None:
1858
            return ('Unknown', [])
1859
        for line in lines:
1860
            #r, theta = line[0]
1861
            #a, b = np.cos(theta), np.sin(theta)
1862
            #x0, y0 = a * r, b * r
1863
            #x1, y1 = int(x0 + 1000 * (-b)), int(y0 + 1000 * a)
1864
            #x2, y2 = int(x0 - 1000 * (-b)), int(y0 - 1000 * a)
1865
            #cv2.line(out, (x1, y1), (x2, y2), (0, 255, 0), 3)
1866
            x1, y1, x2, y2 = line[0]
1867
            degree = math.atan2(y2 - y1, x2 - x1) * 180 / math.pi
1868
            fLine = [x1, y1, x2, y2, degree]
1869
            #print(fLine)
1870
            fLines.append(fLine)
1871
        
1872
        horLines = []
1873
        verLines = []
1874
        otherLines = []
1875
        isVH = None
1876
        for fLine in fLines:
1877
            degree = math.fabs(fLine[4])
1878
            if degree >= 90 - maxDifAngle:
1879
                verLines.append(fLine)
1880
            elif degree <= maxDifAngle:
1881
                horLines.append(fLine)
1882
            else:
1883
                otherLines.append(fLine)
1884

    
1885
        baseLines = []
1886
        baseDifV = 0
1887
        if len(horLines):
1888
            x, y = w / 2, 0
1889
            baseDifV = maxDifH
1890
            for horLine in horLines:
1891
                x1, y1, x2, y2 = horLine[0], horLine[1], horLine[2], horLine[3]
1892
                y = ((y2-y1)/(x2-x1))*x + y1 - ((y2-y1)/(x2-x1))*x1
1893
                horLine.append(y)
1894
            baseLines = horLines
1895
            isVH = 'H'
1896
        if len(verLines):
1897
            x, y = 0, h / 2
1898
            baseDifV = maxDifW
1899
            for verLine in verLines:
1900
                x1, y1, x2, y2 = verLine[0], verLine[1], verLine[2], verLine[3]
1901
                x = ((x2-x1)/(y2-y1))*y + x1 - ((x2-x1)/(y2-y1))*y1
1902
                verLine.append(x)
1903
            baseLines = verLines
1904
            isVH = 'V'
1905

    
1906
        for otherLine in otherLines:
1907
            x, y = w / 2, 0
1908
            x1, y1, x2, y2 = otherLine[0], otherLine[1], otherLine[2], otherLine[3]
1909
            y = ((y2-y1)/(x2-x1))*x + y1 - ((y2-y1)/(x2-x1))*x1
1910
            otherLine.append(y)
1911

    
1912
        # determine line no indicator 
1913
        if not ((len(horLines) > 0 and len(verLines) > 0) or len(otherLines) is 0 or (len(horLines) == 0 and len(verLines) == 0)):    
1914
            result, mergedOtherLine = self.isLineNoIndicator(w, h, maxDifAngle, baseDifV, baseLines, otherLines)
1915
            if result:
1916
                #print(fLines)
1917
                return ('LineIndicator', [isVH, mergedOtherLine])
1918

    
1919
        return ('Unknown', [])
1920

    
1921
    def isLineNoIndicator(self, w, h, maxDifAngle, baseDifV, baseLines, otherLines):
1922
        '''
1923
            @brief      determine line no indicator
1924
            @author     euisung
1925
            @date       2019.03.25
1926
        '''
1927
        import math
1928

    
1929
        if (w < 250 and h < 250):
1930
            return (False, None)
1931

    
1932
        isSameLine = True
1933
        i = 0
1934
        for baseLine in baseLines:
1935
            if not isSameLine: break
1936
            j = 0
1937
            for baseLinee in baseLines:
1938
                if i == j:
1939
                    j += 1
1940
                    continue
1941
                difV = math.fabs(baseLine[5] - baseLinee[5])
1942
                if difV > baseDifV:
1943
                   isSameLine = False
1944
                   break
1945
                j += 1
1946
            i += 1
1947
        if not isSameLine:
1948
            return (False, None)
1949

    
1950
        isSameLine = True
1951
        i = 0
1952
        maxY = 0
1953
        for otherLine in otherLines:
1954
            y = otherLine[5]
1955
            if math.fabs(y) > maxY:
1956
                maxY = math.fabs(y)
1957
            if not isSameLine: break
1958
            j = 0
1959
            for otherLinee in otherLines:
1960
                if i == j:
1961
                    j += 1
1962
                    continue
1963
                difV = math.fabs(otherLine[4] - otherLinee[4])
1964
                if difV > maxDifAngle:
1965
                   isSameLine = False
1966
                   break
1967
                j += 1
1968
            i += 1
1969
        if not isSameLine:
1970
            return (False, None)
1971
                
1972
        isSameLine = True
1973
        mergedOtherLine = [0, 0, 0, 0]
1974
        i = 0
1975
        maxDif = math.ceil(math.tan(4 * math.pi / 180) * maxY)
1976
        for otherLine in otherLines:
1977
            if not isSameLine: break
1978
            j = 0
1979
            for otherLinee in otherLines:
1980
                if i == j:
1981
                    j += 1
1982
                    continue
1983
                angle = math.fabs(otherLine[4] + otherLinee[4]) / 2
1984
                difV = math.fabs(otherLine[5] - otherLinee[5])
1985
                dist = math.sin((90 - angle) * math.pi / 180) * difV 
1986
                if dist > maxDif:
1987
                   isSameLine = False
1988
                   break
1989
                j += 1
1990
            i += 1
1991
            mergedOtherLine[0] += otherLine[0]
1992
            mergedOtherLine[1] += otherLine[1]
1993
            mergedOtherLine[2] += otherLine[2]
1994
            mergedOtherLine[3] += otherLine[3]
1995
        if not isSameLine:
1996
            (False, None)
1997
                        
1998
        # Show the output image
1999
        #print('line no indicator')
2000
        mergedOtherLine[0] = round(mergedOtherLine[0] / len(otherLines))
2001
        mergedOtherLine[1] = round(mergedOtherLine[1] / len(otherLines))
2002
        mergedOtherLine[2] = round(mergedOtherLine[2] / len(otherLines))
2003
        mergedOtherLine[3] = round(mergedOtherLine[3] / len(otherLines))
2004
        #cv2.line(out, (mergedOtherLine[0], mergedOtherLine[1]), (mergedOtherLine[2], mergedOtherLine[3]), (255, 255, 255), 3)
2005
        #cv2.imshow('Output', out)
2006
        #cv2.waitKey(0)
2007
        #cv2.destroyAllWindows()
2008
        return (True, mergedOtherLine)
2009

    
2010
    '''
2011
        @brief      load recognition result
2012
        @author     humkyung
2013
        @date       2018.04.??
2014
        @history    humkyung 2018.01.12 parse originalpoint and connectionpoint
2015
                    Jeongwoo 2018.04.17 add QGraphicItem with Rotated text
2016
                    Jeongwoo 2018.04.23 Change to Draw texts on QEngineeringTextItem
2017
                    humkyung 2018.04.23 connect item remove slot to result tree
2018
                    Jeongwoo 2018.04.25 Add if state with QEngineeringNoteItem
2019
                    Jeongwoo 2018.04.26 Change method to create TextItem object with TextItemFactory
2020
                    Jeongwoo 2018.05.03 Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
2021
                    Jeongwoo 2018.05.29 Change method name / Change method to add item / Add Line item
2022
                    Jeongwoo 2018.05.30 Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol) / Change method name / Change XML NODE NAMES
2023
                    Jeongwoo 2018.06.12 Add LineNoTextItem from LINE_NO
2024
                    Jeongwoo 2018.06.14 Add UnknownItem from UNKNOWN
2025
                    Jeongwoo 2018.06.18 Update Scene after all item added
2026
                                        Add connect on unknown item
2027
                                        Add [transfer] for using pyqtSignal
2028
                    kyouho  2018.07.12  Add line property logic
2029
                    humkyung 2018.08.22 show progress while loading xml file
2030
                    2018.11.22      euisung     fix note road
2031
    '''
2032
    def loadRecognitionResultFromXml(self, xmlPath):
2033
        docData = AppDocData.instance()
2034
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
2035
        from EngineeringRunItem import QEngineeringRunItem
2036
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2037

    
2038
        try:
2039
            symbols = []
2040

    
2041
            xml = parse(xmlPath)
2042
            root = xml.getroot()
2043
            
2044
            maxValue = 0
2045
            maxValue = maxValue + len(list(root.iter('SYMBOL')))
2046
            maxValue = maxValue + len(list(root.iter('ATTRIBUTE')))
2047
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
2048
            maxValue = maxValue + len(list(root.iter('LINE')))
2049
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
2050
            maxValue = maxValue + len(list(root.iter('SIZETEXT')))
2051
            self.progress.setMaximum(maxValue)
2052

    
2053
            for symbol in root.find('SYMBOLS').iter('SYMBOL'):
2054
                item = SymbolSvgItem.fromXml(symbol)
2055
                if item[0] is not None:
2056
                    item[0].transfer.onRemoved.connect(self.itemRemoved)
2057
                    symbols.append(item)                    
2058
                else:
2059
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2060
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2061
                    angle = float(symbol.find('ANGLE').text)
2062
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2063
                    item.isSymbol = True
2064
                    item.angle = angle
2065
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2066
                    self.graphicsView.scene.addItem(item)
2067

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

    
2072
            # set symbol's owner
2073
            childItems = [item for item in symbols if item[1] is not None]
2074
            for item in childItems:
2075
                matches = [param for param in symbols if str(param[0].uid) == item[1]]
2076
                if len(matches) == 1:
2077
                    item[0].owner = matches[0][0]
2078
            # up to here
2079
           
2080
            for item in symbols:
2081
                self.addSvgItemToScene(item[0])
2082
                docData.symbols.append(item[0])
2083

    
2084
            # parse texts
2085
            for text in root.find('TEXTINFOS').iter('ATTRIBUTE'):
2086
                item = QEngineeringTextItem.fromXml(text)
2087
                if item is not None:
2088
                    uid = text.find('UID')
2089
                    attributeValue = text.find('ATTRIBUTEVALUE')
2090
                    name = text.find('NAME').text
2091
                    item.transfer.onRemoved.connect(self.itemRemoved)
2092
                    self.addTextItemToScene(item)
2093
                    docData.texts.append(item)
2094

    
2095
                    if name == 'TEXT':
2096
                        if uid is not None and attributeValue is not None:
2097
                            item.uid = uid.text
2098
                            item.attribute = attributeValue.text
2099

    
2100
                self.progress.setValue(self.progress.value() + 1)
2101
                
2102
            QApplication.processEvents()
2103

    
2104
            # note
2105
            for text in root.find('NOTES').iter('ATTRIBUTE'):
2106
                item = QEngineeringTextItem.fromXml(text)
2107
                if item is not None:
2108
                    uid = text.find('UID')
2109
                    attributeValue = text.find('ATTRIBUTEVALUE')
2110
                    name = text.find('NAME').text
2111
                    item.transfer.onRemoved.connect(self.itemRemoved)
2112
                    self.addTextItemToScene(item)
2113

    
2114
                    if name == 'NOTE':
2115
                        if uid is not None:
2116
                            item.uid = uid.text
2117

    
2118
                self.progress.setValue(self.progress.value() + 1)
2119
                
2120
            QApplication.processEvents()
2121

    
2122
            for line in root.find('LINEINFOS').iter('LINE'):
2123
                item = QEngineeringLineItem.fromXml(line)
2124
                item.transfer.onRemoved.connect(self.itemRemoved)
2125
                if item: self.addLineItemToScene(item)
2126

    
2127
                #errors = item.validate()
2128
                #for error in errors: self.graphicsView.scene.addItem(error)
2129

    
2130
                self.progress.setValue(self.progress.value() + 1)
2131
                
2132
            QApplication.processEvents()
2133

    
2134
            for unknown in root.iter('UNKNOWN'):
2135
                item = QEngineeringUnknownItem.fromXml(unknown)
2136
                item.transfer.onRemoved.connect(self.itemRemoved)
2137
                if item is not None:
2138
                    item.transfer.onRemoved.connect(self.itemRemoved)
2139
                    self.addUnknownItemToScene(item)
2140

    
2141
                self.progress.setValue(self.progress.value() + 1)
2142
                
2143
            QApplication.processEvents()
2144

    
2145
            for line_no in root.find('LINENOS').iter('LINE_NO'):
2146
                item = QEngineeringLineNoTextItem.fromXml(line_no)
2147
                if item is not None:
2148
                    item.transfer.onRemoved.connect(self.itemRemoved)
2149
                    self.addTextItemToScene(item)
2150

    
2151
                connLine = line_no.find('CONNLINE')
2152
                if connLine is not None:
2153
                    lineUID = connLine.text
2154
                    connLine = self.graphicsView.findItemByUid(lineUID)
2155
                    if connLine is not None:
2156
                        item.conns.append(connLine)
2157

    
2158
                run = line_no.find('RUN')
2159
                if run is not None:
2160
                    lineRunItem = QEngineeringRunItem()
2161
                    for child in run:
2162
                        uidElement = child.find('UID')
2163
                        if uidElement is not None:
2164
                            uid = uidElement.text
2165
                            runItem = self.graphicsView.findItemByUid(uid)
2166
                            if runItem is not None:
2167
                                lineRunItem.items.append(runItem)
2168

    
2169
                    item.runs.append(lineRunItem)
2170
                    treeItem = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2171
                    for connectedItem in lineRunItem.items:
2172
                        if issubclass(type(connectedItem), SymbolSvgItem): self.itemTreeWidget.addTreeItem(treeItem, connectedItem)
2173
                    docData.tracerLineNos.append(item)
2174

    
2175
                self.progress.setValue(self.progress.value() + 1)
2176
            QApplication.processEvents()
2177

    
2178
            for trimLineNo in root.iter('TRIM_LINE_NO'):
2179
                item = QEngineeringTrimLineNoTextItem()
2180
                item.uid = trimLineNo.find('UID')
2181

    
2182
                run = trimLineNo.find('RUN')
2183
                if run is not None:
2184
                    lineRunItem = QEngineeringRunItem()
2185
                    for child in run:
2186
                        uidElement = child.find('UID')
2187
                        if uidElement is not None:
2188
                            uid = uidElement.text
2189
                            runItem = self.graphicsView.findItemByUid(uid)
2190
                            if runItem is not None:
2191
                                lineRunItem.items.append(runItem)
2192

    
2193
                    item.runs.append(lineRunItem)
2194
                    treeItem = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2195
                    for connectedItem in lineRunItem.items:
2196
                        if issubclass(type(connectedItem), SymbolSvgItem): self.itemTreeWidget.addTreeItem(treeItem, connectedItem)
2197
                    docData.tracerLineNos.append(item)
2198
            # up to here
2199

    
2200
            # set symbol's connectItem
2201
            from EngineeringConnectorItem import QEngineeringConnectorItem
2202
            connectors = [item for item in self.graphicsView.scene.items() if type(item) == QEngineeringConnectorItem and item.connectedItem is not None]
2203
            for connector in connectors:
2204
                # 처음에는 UID가 connectedItem에 String으로 들어가있기 때문에
2205
                connector.connectedItem = self.graphicsView.findItemByUid(connector.connectedItem)
2206

    
2207
            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]
2208
            for symbol in symbols:
2209
                # 처음에는 attrs의 uid가 connectedItem에 String으로 들어가있기 때문에
2210
                for key in symbol.attrs.keys():
2211
                    if type(symbol.attrs[key]) is not UserInputAttribute and type(symbol.attrs[key]) is not tuple:
2212
                        symbol.attrs[key] = self.graphicsView.findItemByUid(symbol.attrs[key])
2213
                        
2214
            # Update Scene
2215
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2216
            for item in self.graphicsView.scene.items():
2217
                item.setVisible(True)
2218

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

    
2223
    '''
2224
        @brief      Remove added item on same place and Add GraphicsItem
2225
        @author     Jeongwoo
2226
        @date       2018.05.25
2227
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2228
                    2018.06.18  Jeongwoo    Set Z-index
2229
    '''
2230
    def addSvgItemToScene(self, svgItem):
2231
        svgItem.addSvgItemToScene(self.graphicsView.scene)
2232
        
2233
    '''
2234
        @brief      Remove added item on same place and Add GraphicsItem
2235
        @author     Jeongwoo
2236
        @date       2018.05.25
2237
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2238
                    2018.06.05  Jeongwoo    Remove Size condition
2239
                    2018.06.18  Jeongwoo    Set Z-index
2240
    '''
2241
    def addTextItemToScene(self, textItem):
2242
        textItem.addTextItemToScene(self.graphicsView.scene)
2243
        
2244
    '''
2245
        @brief      Remove added item on same place and Add GraphicsItem
2246
        @author     Jeongwoo
2247
        @date       2018.05.29
2248
        @history    2018.06.18  Jeongwoo    Set Z-index
2249
    '''
2250
    def addLineItemToScene(self, lineItem):
2251
        self.graphicsView.scene.addItem(lineItem)
2252

    
2253
    '''
2254
        @brief      Remove added item on same place and Add Unknown Item
2255
        @author     Jeongwoo
2256
        @date       2018.06.14
2257
        @history    2018.06.18  Jeongwoo    Set Z-index
2258
    '''
2259
    def addUnknownItemToScene(self, unknownItem):
2260
        try:
2261
            unknownItem.addUnknownItemToScene(self.graphicsView.scene)
2262
        except Exception as ex:
2263
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2264
            self.addMessage.emit(MessageType.Error, message)
2265

    
2266
    '''
2267
        @brief      generate output xml file
2268
        @author     humkyung
2269
        @date       2018.04.23
2270
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
2271
    '''
2272
    def generateOutput(self):
2273
        import XmlGenerator as xg
2274

    
2275
        if not self.graphicsView.hasImage():
2276
            self.showImageSelectionMessageBox()
2277
            return
2278

    
2279
        try:
2280
            appDocData = AppDocData.instance()
2281

    
2282
            ## collect items
2283
            appDocData.lines.clear()
2284
            appDocData.lines = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem and item.owner is None]
2285

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

    
2289
            appDocData.equipments.clear()
2290
            for item in self.graphicsView.scene.items():
2291
                if type(item) is QEngineeringEquipmentItem:
2292
                    appDocData.equipments.append(item)
2293

    
2294
            appDocData.texts.clear()
2295
            appDocData.texts = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem) and type(item) is not QEngineeringLineNoTextItem]
2296
            ## up to here
2297

    
2298
            appDocData.imgOutput = np.ones((appDocData.imgHeight, appDocData.imgWidth), np.uint8)*255
2299
            xg.writeOutputXml(appDocData.imgName, appDocData.imgWidth, appDocData.imgHeight) # TODO: check
2300
            project = appDocData.getCurrentProject()
2301
            cv2.imwrite(os.path.join(project.getTempPath() , 'OUTPUT.png') , appDocData.imgOutput)
2302
        except Exception as ex:
2303
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2304
            self.addMessage.emit(MessageType.Error, message)
2305

    
2306
    '''
2307
        @brief      resetting attribute at secne
2308
        @author     kyoyho
2309
        @date       2018.08.21
2310
    '''
2311
    def checkAttribute(self):
2312
        try:
2313

    
2314
            docData = AppDocData.instance()
2315
            if not self.graphicsView.hasImage():
2316
                return
2317

    
2318
            # symbol 경우
2319
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringSpecBreakItem]
2320
            for item in items:
2321
                attrs = item.attrs
2322
                
2323
                removeAttrList = []
2324
                for attr in attrs:
2325
                    if type(attr) is tuple:
2326
                        continue
2327

    
2328
                    if attr is None:
2329
                        removeAttrList.append(attr)
2330
                        continue
2331

    
2332
                    attrInfo = docData.getSymbolAttributeByUID(attr.UID)
2333
                    if attrInfo is None:
2334
                        removeAttrList.append(attr)
2335
                    # 해당 attribute가 맞는지 확인
2336
                    else:
2337
                        attrType = attrInfo.AttributeType
2338
                        _type = type(attr)
2339
                        if attrType == 'Symbol Item':
2340
                            if not issubclass(_type, SymbolSvgItem):
2341
                                removeAttrList.append(attr)
2342
                        elif attrType == 'Text Item':
2343
                            if _type is not QEngineeringTextItem:
2344
                                removeAttrList.append(attr)
2345
                        elif attrType == 'Int':
2346
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
2347
                                removeAttrList.append(attr)
2348
                        elif attrType == 'String':
2349
                            if _type is not UserInputAttribute:
2350
                                removeAttrList.append(attr)
2351

    
2352
                for attr in removeAttrList:
2353
                    del attrs[attr]
2354

    
2355
            # Line No Text Item의 경우
2356
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringLineNoTextItem)]
2357
            for item in items:
2358
                attrs = item.attrs
2359
                
2360
                removeAttrList = []
2361
                for attr in attrs:
2362
                    if type(attr) is UserInputAttribute:
2363
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
2364
                        if attrInfo is None:
2365
                            removeAttrList.append(attr)
2366

    
2367
                for attr in removeAttrList:
2368
                    del attrs[attr]
2369

    
2370
        except Exception as ex:
2371
                message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2372
                self.addMessage.emit(MessageType.Error, message)
2373
    '''
2374
        @brief      Check Number
2375
        @author     kyouho
2376
        @date       2018.08.20
2377
    '''
2378
    def isNumber(self, num):
2379
        p = re.compile('(^[0-9]+$)')
2380
        result = p.match(num)
2381

    
2382
        if result:
2383
            return True
2384
        else:
2385
            return False
2386

    
2387
    '''
2388
        @brief      find overlap Connector
2389
        @author     kyouho
2390
        @date       2018.08.28
2391
    '''
2392
    def findOverlapConnector(self, connectorItem):
2393
        from shapely.geometry import Point
2394
        from EngineeringConnectorItem import QEngineeringConnectorItem
2395
        itemList = []
2396
        
2397
        x = connectorItem.center()[0]
2398
        y = connectorItem.center()[1]
2399

    
2400
        connectors = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringConnectorItem and item != connectorItem]
2401
        for connector in connectors:
2402
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
2403
                itemList.append(connector.parent)
2404

    
2405
        return itemList
2406

    
2407
if __name__ == '__main__':
2408
    import locale
2409
    from PyQt5.QtCore import QTranslator
2410
    from License import QLicenseDialog
2411
    from ProjectDialog import Ui_Dialog
2412
    from App import App 
2413

    
2414
    app = App(sys.argv)
2415
    try:
2416
        if True == QLicenseDialog.check_license_key():
2417
            dlg = Ui_Dialog()
2418
            selectedProject = dlg.showDialog()
2419
            if selectedProject is not None:
2420
                AppDocData.instance().setCurrentProject(selectedProject)
2421
                app._mainWnd = MainWindow.instance()
2422
                app._mainWnd.show()
2423
                sys.exit(app.exec_())
2424
    except Exception as ex:
2425
        print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
2426
    finally:
2427
        pass
2428