프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

hytos / HYTOS / HYTOS / MainWindow.py @ 62df6e0a

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

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

    
4
import sys
5
import os
6
import subprocess
7
from functools import partial
8

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

    
19
import cv2
20
import numpy as np
21

    
22
from PyQt5.QtCore import *
23
from PyQt5.QtGui import *
24
from PyQt5.QtWidgets import *
25
from PyQt5.QtSvg import *
26

    
27
from PIL import Image
28

    
29
import MainWindow_UI
30
import QtImageViewer
31
from SingletonInstance import SingletonInstane
32

    
33
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Shapes')
34
from EngineeringPolylineItem import QEngineeringPolylineItem
35
from EngineeringLineItem import QEngineeringLineItem
36
from SymbolSvgItem import SymbolSvgItem
37
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
38
from EngineeringTextItem import QEngineeringTextItem
39
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
40
from EngineeringNoteItem import QEngineeringNoteItem
41
from QEngineeringSizeTextItem import QEngineeringSizeTextItem
42
from EngineeringUnknownItem import QEngineeringUnknownItem
43
from EngineeringEquipmentItem import QEngineeringEquipmentItem
44
from EngineeringInstrumentItem import QEngineeringInstrumentItem
45
from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
46
from EngineeringErrorItem import QEngineeringErrorItem
47
from EngineeringVendorItem import QEngineeringVendorItem
48
from EngineeringEndBreakItem import QEngineeringEndBreakItem
49
from EngineeringReducerItem import QEngineeringReducerItem
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 TextDataListDialog import QTextDataListDialog
58
from DisplayColors import DisplayColors
59
from DisplayColors import DisplayOptions
60
import uuid
61

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

    
66
    '''
67
        @brief      initialize
68
        @author 
69
        @date   
70
        @history    humkyung 2018.04.12 add splitter widget
71
                    Jeongwoo 2018.04.27 Add Signal/Slot Connection 'noteNoSingleClicked'
72
                    Jeongwoo 2018.05.09 Initialize Action group
73
                    Jeongwoo 2018.05.10 Add Signal/Slot Connection 'lineNoSingleClicked'
74
                                        Add QActionGroup for managing checkable action
75
                    Jeongwoo 2018.06.27 Add Action [Zoom, Fit Window] and Add new actions into ActionGroup
76
                    humkyung 2018.08.23 add labelStatus to statusbar
77
                    Euisung 2018.09.27 add OCR Training , Signal/Slot Connection 'oCRTrainingClicked'
78
                    Euisung 2018.10.05 add OCR Editor , Signal/Slot Connection 'oCRTrainingEdidorClicked'
79
                    Euisung 2018.10.22 delete Signal/Slot Connection 'oCRTrainingEdidorClicked'
80
    '''
81
    def __init__(self):
82
        from LineTypeConditions import LineTypeConditions
83

    
84
        super(self.__class__, self).__init__()
85
        self.setupUi(self)
86
        self._label_mouse = QLabel(self.statusbar)
87
        self._label_mouse.setText(self.tr('mouse pos : ({},{})'.format(0,0)))
88
        self.labelStatus = QLabel(self.statusbar)
89
        self.labelStatus.setText(self.tr('Unrecognition : '))
90
        self.labelSymbolStatus = QLabel(self.statusbar)
91
        self.labelSymbolStatus.setText(self.tr('Symbol : '))
92
        self.labelLineStatus = QLabel(self.statusbar)
93
        self.labelLineStatus.setText(self.tr('Line : '))
94
        self.labelTextStatus = QLabel(self.statusbar)
95
        self.labelTextStatus.setText(self.tr('Text : '))
96
        self.statusbar.addWidget(self._label_mouse)
97
        self.statusbar.addPermanentWidget(self.labelSymbolStatus)
98
        self.statusbar.addPermanentWidget(self.labelLineStatus)
99
        self.statusbar.addPermanentWidget(self.labelTextStatus)
100
        self.statusbar.addPermanentWidget(self.labelStatus) 
101

    
102
        docData = AppDocData.instance()
103
        project = docData.getCurrentProject()
104
        _translate = QCoreApplication.translate
105
        self.setWindowTitle(_translate(App.NAME  + " - {}".format(project.name), App.NAME + " - {}".format(project.name)))
106

    
107
        self.lineComboBox = QComboBox(self.toolBar)
108
        for condition in LineTypeConditions.items():
109
            self.lineComboBox.addItem(condition.name)
110
        self.lineComboBox.currentIndexChanged.connect(self.onLineTypeChanged)
111

    
112
        self.toolBar.insertWidget(self.actionOCR, self.lineComboBox)
113
        self.toolBar.insertSeparator(self.actionOCR)
114
        
115
        self.graphicsView = QtImageViewer.QtImageViewer(self)
116
        self.graphicsView.setParent(self.centralwidget)
117
        self.graphicsView.useDefaultCommand() ##### USE DEFAULT COMMAND
118
        self.graphicsView.setMouseTracking(True)
119
        self.graphicsView.viewport().installEventFilter(self)
120

    
121
        self._display_widget = QWidget()
122
        layout = QVBoxLayout()
123
        self._by_line_no = QRadioButton()
124
        self._by_line_no.setChecked(True)
125
        self._by_line_no.setText('By Group')
126
        self._by_line_no.toggled.connect(self.display_colors)
127
        layout.addWidget(self._by_line_no)
128
        self._by_line_type = QRadioButton()
129
        self._by_line_type.setText('By Type')
130
        layout.addWidget(self._by_line_type)
131
        self._display_widget.setLayout(layout)
132
        self.EditToolbar.insertWidget(None, self._display_widget)
133
        self._by_line_no.setChecked(True) if DisplayColors.instance().option == DisplayOptions.DisplayByLineNo else self._by_line_type.setChecked(True)
134

    
135
        self.verticalLayout.addWidget(self.graphicsView)
136

    
137
        # Add Custom TreeWidget
138
        self.dirTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
139
        self.dirTreeWidget.header().hide()
140
        self.symbolTabVerticalLayout.addWidget(self.dirTreeWidget)
141

    
142
        # Add Custom Property TableWidget
143
        self.propertyTableWidget = SymbolPropertyTableWidget.QSymbolPropertyTableWidget()
144
        self.symbolTabVerticalLayout.addWidget(self.propertyTableWidget)
145
        self.dirTreeWidget.singleClicked.connect(self.propertyTableWidget.getClickedSymbol)
146
        # add splitter widget
147
        splitter = QSplitter(Qt.Vertical)
148
        splitter.addWidget(self.dirTreeWidget)
149
        splitter.addWidget(self.propertyTableWidget)
150
        self.symbolTabVerticalLayout.addWidget(splitter)
151
        # up to here
152

    
153
        # Add Custom Result Tree Widget (Symbol Explorer)
154
        self.itemTreeWidget = ItemTreeWidget.QItemTreeWidget(self.graphicsView)
155
        self.itemTreeWidget.header().hide()
156
        self.symbolExplorerVerticalLayout.addWidget(self.itemTreeWidget)
157

    
158
        # Add Empty Widget
159
        self.resultPropertyTableWidget = ItemPropertyTableWidget.QItemPropertyTableWidget(self)
160
        self.symbolExplorerVerticalLayout.addWidget(self.resultPropertyTableWidget)
161
        self.itemTreeWidget.singleClicked.connect(self.resultPropertyTableWidget.onSymbolClicked)
162
        self.itemTreeWidget.noteNoSingleClicked.connect(self.resultPropertyTableWidget.onNoteClicked)
163
        self.itemTreeWidget.lineNoSingleClicked.connect(self.resultPropertyTableWidget.onLineNoClicked)
164
        self.itemTreeWidget.drawingClicked.connect(self.resultPropertyTableWidget.onDrawingClicked)
165
        # add splitter widget
166
        splitter = QSplitter(Qt.Vertical)
167
        splitter.addWidget(self.itemTreeWidget)
168
        splitter.addWidget(self.resultPropertyTableWidget)
169
        self.symbolExplorerVerticalLayout.addWidget(splitter)
170
        # up to here
171

    
172
        # Initialize Action group
173
        self.actionGroup = QActionGroup(self)
174
        self.actionGroup.addAction(self.actionRecognition)
175
        self.actionGroup.addAction(self.actionLineRecognition)
176
        self.actionGroup.addAction(self.actionLine)
177
        self.actionGroup.addAction(self.actionGenerateOutput)
178
        self.actionGroup.addAction(self.actionOCR)
179
        self.actionGroup.addAction(self.actionZoom)
180
        self.actionGroup.addAction(self.actionFitWindow)
181
        self.actionGroup.addAction(self.actionSave)
182
        self.actionGroup.addAction(self.actionValidate)
183
        self.actionGroup.addAction(self.actionVendor)
184
        self.actionGroup.triggered.connect(self.actionGroupTriggered)
185

    
186
        # connect signals and slots
187
        self.actionClose.triggered.connect(self.close)
188
        self.actionNew.triggered.connect(self.new_drawing)
189
        self.actionOpen.triggered.connect(self.onOpenImageDrawing)
190
        self.actionLine.triggered.connect(self.onPlaceLine)
191
        self.actionRecognition.triggered.connect(self.recognize)
192
        self.actionLineRecognition.triggered.connect(self.connect_attributes)
193
        self.actionArea.triggered.connect(self.areaConfiguration)
194
        self.actionConfiguration.triggered.connect(self.configuration)
195
        self.actionOCR.triggered.connect(self.onAreaOcr)
196
        self.actionGenerateOutput.triggered.connect(self.generateOutput)
197
        self.pushButtonClearLog.clicked.connect(self.onClearLog)
198
        self.actionHMB_DATA.triggered.connect(self.onHMBData)
199
        self.actionItem_Data_List.triggered.connect(self.showItemDataList)
200
        self.actionText_Data_List.triggered.connect(self.showTextDataList)
201
        self.actionCodeTable.triggered.connect(self.onShowCodeTable)
202
        self.actionImage_Drawing.triggered.connect(self.onViewImageDrawing)
203
        self.actionDrawing_Only.triggered.connect(self.onViewDrawingOnly)
204
        self.actionValidate.triggered.connect(self.onValidation)
205
        self.actionViewText.triggered.connect(self.onViewText)
206
        self.actionViewSymbol.triggered.connect(self.onViewSymbol)
207
        self.actionViewLine.triggered.connect(self.onViewLine)
208
        self.actionViewUnknown.triggered.connect(self.onViewUnknown)
209
        self.actionViewInconsistency.triggered.connect(self.onViewInconsistency)
210
        self.actionViewVendor_Area.triggered.connect(self.onViewVendorArea)
211
        self.actionRotate.triggered.connect(self.onRotate)
212
        self.actionZoom.triggered.connect(self.onAreaZoom)
213
        self.actionVendor.triggered.connect(self.onVendor)
214
        self.actionFitWindow.triggered.connect(self.fitWindow)
215
        self.actionpdf_to_image.triggered.connect(self.onConvertPDFToImage)
216
        self.actionCreate_Symbol.triggered.connect(self.create_symbol)
217
        #self.graphicsView.scene.changed.connect(self.onSceneChanged)
218
        self.graphicsView.scene.contents_changed.connect(self.onSceneChanged)
219
        self.graphicsView.scene.selectionChanged.connect(self.onSelectionChanged)
220
        self.actionInitialize.triggered.connect(self.onInitializeScene)
221
        self.actionSave.triggered.connect(self.actionSaveCliked)
222
        self.addMessage.connect(self.onAddMessage)
223
        self.actionFindReplaceText.triggered.connect(self.findReplaceTextClicked)
224

    
225

    
226

    
227

    
228
        configs = docData.getAppConfigs('app', 'mode')
229
        if configs and 1 == len(configs) and 'advanced' == configs[0].value:
230
            self.actionOCR_Training.triggered.connect(self.oCRTrainingClicked)
231
        else:
232
            self.actionOCR_Training.setVisible(False)
233

    
234
        # removedItems
235
        '''
236
        self.removedItems = {}
237
        self.removedItems['LINE'] = []
238
        self.removedItems['EQUIP'] = []
239
        self.removedItems['INST'] = []
240
        self.removedItems['NOTE'] = []
241
        '''
242

    
243
        self.delimiter = '"'
244
    
245
        self.resizeDocks({self.dockWidget}, {self.dockWidgetObjectExplorer.sizeHint().width()}, Qt.Horizontal)
246

    
247
        self.treeWidgetDrawingList.setHeaderHidden(False)
248
        self.treeWidgetDrawingList.header().setStretchLastSection(False)
249
        self.treeWidgetDrawingList.setHeaderLabels([self.tr('Name'), self.tr('DateTime')])
250
        self.treeWidgetDrawingList.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
251
        self.treeWidgetDrawingList.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
252
        self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing)
253
        self.load_drawing_list()
254

    
255
        # load stylesheet file list
256
        stylesheet_name = QtWidgets.qApp.stylesheet_name
257
        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']
258
        for file in files:
259
            action = self.menuTheme.addAction(file)
260
            action.setCheckable(True)
261
            action.setChecked(True) if stylesheet_name == file else action.setChecked(False)
262
            action.triggered.connect(partial(self.load_stylesheet, file))
263
        # up to here
264

    
265
        # load language files
266
        language_name = QtWidgets.qApp.language_name
267
        files = ['en_us'] # englisgh is default language
268
        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'])
269
        for file in files:
270
            action = self.menuLanguage.addAction(file)
271
            action.setCheckable(True)
272
            action.setChecked(True) if language_name.lower() == file.lower() else action.setChecked(False)
273
            action.triggered.connect(partial(self.load_language, file))
274
        # up to here
275

    
276
        # inconsistency table
277
        self.tableWidgetInconsistency.setColumnCount(2)
278
        self.tableWidgetInconsistency.setHorizontalHeaderLabels(['Owner', 'Message'])
279
        self.tableWidgetInconsistency.setEditTriggers(QAbstractItemView.NoEditTriggers)
280
        self.tableWidgetInconsistency.itemClicked.connect(self.inconsistencyItemClickEvent)
281
        self.tableWidgetInconsistency.keyPressEvent = self.inconsistencyTableKeyPressEvent
282

    
283
    def eventFilter(self, source, event):
284
        """
285
        display mouse position of graphics view
286
        """
287
        if (event.type() == QEvent.MouseMove):
288
            pos = self.graphicsView.mapToScene(event.pos())
289
            self._label_mouse.setText('mouse pos : ({},{})'.format(round(pos.x()), round(pos.y())))
290

    
291
        return QWidget.eventFilter(self, source, event)
292

    
293
    def inconsistencyTableKeyPressEvent(self, event):
294
        try:
295
            row = self.tableWidgetInconsistency.selectedIndexes()[0].row()
296
            col = self.tableWidgetInconsistency.selectedIndexes()[0].column()
297
            from HighlightCommand import HighlightCommand
298
            if event.key() == Qt.Key_Up:
299
                if row is not 0:
300
                    errorItem = self.tableWidgetInconsistency.item(row - 1, 1).tag
301
                    HighlightCommand(self.graphicsView).execute(errorItem)
302
            elif event.key() == Qt.Key_Down:
303
                if row is not self.tableWidgetInconsistency.rowCount() - 1:
304
                    errorItem = self.tableWidgetInconsistency.item(row + 1, 1).tag
305
                    HighlightCommand(self.graphicsView).execute(errorItem)
306
        except Exception as ex:
307
            pass
308
        #finally:
309
        #    return QTableView.keyPressEvent(self.tableWidgetInconsistency, event)
310

    
311
    def onValidation(self):
312
        """
313
        @brief  validation check
314
        @author euisung
315
        @date   2019.04.01
316
        """
317
        if not self.graphicsView.hasImage():
318
            self.showImageSelectionMessageBox()
319
            return
320

    
321
        errors = []
322

    
323
        try:
324
            for item in self.graphicsView.scene.items():
325
                if type(item) is QEngineeringErrorItem:
326
                    item.transfer.onRemoved.emit(item)
327
                elif type(item) is QEngineeringLineItem or issubclass(type(item), SymbolSvgItem):
328
                    for error in item.validate():
329
                        errors.append(error)
330

    
331
            for error in errors:
332
                error.transfer.onRemoved.connect(self.itemRemoved)
333
                self.graphicsView.scene.addItem(error)
334

    
335
            self.tableWidgetInconsistency.clearContents()
336
            self.tableWidgetInconsistency.setRowCount(len(errors))
337
            for index in range(len(errors)):
338
                items = self.makeInconsistencyTableRow(errors[index])
339
                self.tableWidgetInconsistency.setItem(index, 0, items[0])
340
                self.tableWidgetInconsistency.setItem(index, 1, items[1])
341
        except Exception as ex:
342
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
343
            self.addMessage.emit(MessageType.Error, message)
344

    
345
    def makeInconsistencyTableRow(self, errorItem):
346
        '''
347
            @brief  make row data for inconsistency widget
348
            @author euisung
349
            @date   2019.04.16
350
        '''
351
        items = []
352
        if type(errorItem.parent) is QEngineeringLineItem:
353
            item = QTableWidgetItem('line')
354
            #item.setFlags(Qt.ItemIsEnabled)
355
        elif issubclass(type(errorItem.parent), SymbolSvgItem):
356
            item = QTableWidgetItem('symbol')
357
            #item.setFlags(Qt.ItemIsEnabled)
358
        #elif
359
        item.tag = errorItem
360
        items.append(item)
361

    
362
        item = QTableWidgetItem(errorItem.msg)
363
        #item.setFlags(Qt.ItemIsEnabled)
364
        item.tag = errorItem
365
        items.append(item)
366

    
367
        return items
368

    
369
    def inconsistencyItemClickEvent(self, item):
370
        """
371
        @brief  inconsistency table item clicked
372
        @author euisung
373
        @date   2019.04.02
374
        """
375
        from HighlightCommand import HighlightCommand
376

    
377
        HighlightCommand(self.graphicsView).execute(item.tag)
378

    
379
    def load_stylesheet(self, file):
380
        """
381
        @brief  load stylesheets
382
        @author humkyung
383
        @date   2018.10.29
384
        """
385

    
386
        QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
387

    
388
        app_doc_data = AppDocData.instance()
389
        configs = [Config('app', 'stylesheet', file)]
390
        app_doc_data.saveAppConfigs(configs)
391
        
392
        for action in self.menuTheme.actions():
393
            if action.text() == file: continue
394
            action.setChecked(False)
395

    
396
    def load_language(self, file):
397
        """
398
        load language file and then apply selected language 
399
        """
400
        try:
401
            qm_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate', '{0}.qm'.format(file))
402
            QtWidgets.qApp.load_language(qm_file)
403

    
404
            app_doc_data = AppDocData.instance()
405
            configs = [Config('app', 'language', file)]
406
            app_doc_data.saveAppConfigs(configs)
407
            
408
            for action in self.menuLanguage.actions():
409
                if action.text().lower() == file.lower(): continue
410
                action.setChecked(False)
411
        finally:
412
            self.retranslateUi(self)
413
            self.propertyTableWidget.retranslateUi()
414

    
415
    '''
416
        @brief      Clear TreeWidget and Set Current PID
417
        @author     Jeongwoo
418
        @date       18.04.11
419
        @history    2018.04.26  Jeongwoo    Add Child [SYMBOLS, NOTES] into root item
420
                    2018.05.09  Jeongwoo    Change method to add default tree items
421
                    humkyung 2018.06.10 add tree item for Line No and Unknown Item
422
    '''
423
    def load_drawing_list(self):
424
        """
425
        @brief      load p&id drawing list
426
        @author     humkyung
427
        @date       18.11.02
428
        """
429

    
430
        try:
431
            appDocData = AppDocData.instance()
432
            drawings = appDocData.getDrawings()
433

    
434
            self.treeWidgetDrawingList.clear()
435
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList, [self.tr('Drawings'), ''])
436
            self.treeWidgetDrawingList.root.setFlags(self.treeWidgetDrawingList.root.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
437
            self.treeWidgetDrawingList.root.setCheckState(0, Qt.Unchecked)
438
                        
439
            for drawing in drawings:               
440
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [drawing[1], drawing[2] if drawing and drawing[0] else ''])
441
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
442
                item.setCheckState(0, Qt.Unchecked)
443
            
444
            self.treeWidgetDrawingList.root.setText(0, self.tr('Drawings')+'({})'.format(self.treeWidgetDrawingList.root.childCount()))
445
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
446
            self.treeWidgetDrawingList.root.sortChildren(0, Qt.AscendingOrder)
447
            self.treeWidgetDrawingList.resizeColumnToContents(0)
448

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

    
453
    def open_selected_drawing(self, item, column):
454
        """
455
        @brief      open selected p&id drawing
456
        @author     humkyung
457
        @date       18.11.02
458
        """
459
        appDocData = AppDocData.instance()
460
        drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), item.text(0))
461
        self.onOpenImageDrawing(drawing)
462

    
463
    '''
464
        @brief      OCR Editor
465
        @author     euisung
466
        @date       2018.10.05
467
        @history    2018.10.16 euisung      no more used, Integrated with oCRTrainingClicked
468
    '''
469
    def oCRTrainingEdidorClicked(self):
470
        from TrainingEditorDialog import QTrainingEditorDialog
471

    
472
        try:
473
            dialog = QTrainingEditorDialog(self)
474
            dialog.exec_()
475
        except Exception as ex:
476
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
477
            self.addMessage.emit(MessageType.Error, message)
478
            
479
        return
480

    
481
    '''
482
        @brief      OCR Training
483
        @author     euisung
484
        @date       2018.09.27
485
        @history    euisung 2018.10.16 TrainingListDialog -> TrainingImageListDialog
486
    '''
487
    def oCRTrainingClicked(self):
488
        try:
489
            dialog = QTrainingImageListDialog(self)
490
            dialog.exec_()
491
        except Exception as ex:
492
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
493
            self.addMessage.emit(MessageType.Error, message)
494

    
495
    '''
496
        @brief      show unknownitem's count
497
        @author     kyouho
498
        @date       2018.08.27
499
    '''
500
    def findReplaceTextClicked(self):
501
        if not self.graphicsView.hasImage():
502
            self.showImageSelectionMessageBox()
503
            return
504

    
505
        from TextItemEditDialog import QTextItemEditDialog
506

    
507
        self.dlgTextItemEdit = QTextItemEditDialog(self)
508
        self.dlgTextItemEdit.show()
509
        self.dlgTextItemEdit.exec_()
510

    
511
    '''
512
        @brief      show unknownitem's count
513
        @author     humkyung
514
        @date       2018.08.23
515
        @history    humkyung 2018.08.30 display count of symbol, line, text
516
    '''
517
    def onSceneChanged(self):
518
        items = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
519
        if len(items) > 0:
520
            self.labelStatus.setText("<font color='red'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
521
        else:
522
            self.labelStatus.setText("<font color='black'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
523

    
524
        items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringErrorItem]
525
        self.labelSymbolStatus.setText("<font color='blue'>" + self.tr('Symbol') + " : {}</font>".format(len(items)))
526

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

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

    
533
        self.itemTreeWidget.sceneChanged(self.graphicsView.scene.items())
534

    
535
    def dbUpdate(self):
536
        '''
537
            @brief      db update when save or recognition
538
            @author     euisung
539
            @date       2018.11.12
540
            @history    2018.11.02      euisung     remove scene dependency
541
        '''
542
        from AppDocData import AppDocData
543

    
544
        try:
545
            appDocData = AppDocData.instance()
546

    
547
            titleBlockProps = appDocData.getTitleBlockProperties()
548
            #items = self.graphicsView.scene.items()
549
            items = appDocData.allItems
550
            titleBlockItems = []
551
            for item in items:
552
                #if type(item) is QEngineeringLineNoTextItem:
553
                #    item.saveLineData()
554
                if type(item) is QEngineeringTextItem:
555
                    for titleBlockProp in titleBlockProps:
556
                        if item.area == titleBlockProp[0]:
557
                            titleBlockItems.append(item)
558

    
559
            dbItems = [item for item in items if type(item) is QEngineeringInstrumentItem or type(item) is QEngineeringEquipmentItem or type(item) is QEngineeringReducerItem or\
560
            type(item) is QEngineeringNoteItem or type(item) is SymbolSvgItem or type(item) is QEngineeringLineNoTextItem or type(item) is QEngineeringVendorItem] + titleBlockItems
561
            appDocData.saveToDatabase(dbItems)
562
        except Exception as ex:
563
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
564
            self.addMessage.emit(MessageType.Error, message)
565

    
566
    '''
567
        @brief      action save click event
568
        @author     kyouho
569
        @date       2018.08.09
570
        @history    2018.11.02      euisung     add line data list db update
571
                    humkyung save saved time to database
572
                    2018.11.05      euisung     add note data list db update
573
                    2018.11.05      euisung     add db delete process before save
574
                    2018.11.12      euisung     db part move new method to dbUpdate
575
    '''
576
    def actionSaveCliked(self):
577
        from datetime import datetime
578
        from AppDocData import AppDocData
579
        from EngineeringAbstractItem import QEngineeringAbstractItem
580
        from SaveWorkCommand import SaveWorkCommand 
581

    
582
        try:
583
            appDocData = AppDocData.instance()
584
            if appDocData.imgName is None:
585
                self.showImageSelectionMessageBox()
586
                return
587

    
588
            appDocData.clearItemList(False)
589

    
590
            items = self.graphicsView.scene.items()
591
            for item in items:
592
                if issubclass(type(item), QEngineeringAbstractItem):
593
                    appDocData.allItems.append(item)
594
                    if issubclass(type(item), QEngineeringTextItem):
595
                        appDocData.texts.append(item)
596
            ##
597

    
598
            itemTypes = []
599
            for item in items:
600
                typeExist = False
601
                for itemType in itemTypes:
602
                    if type(item) is itemType:
603
                        typeExist = True
604
                        break
605
                if not typeExist:
606
                    itemTypes.append(type(item))
607
            ##
608

    
609
            self._save_work_cmd = SaveWorkCommand()
610
            self._save_work_cmd.display_message.connect(self.onAddMessage)
611
            self._save_work_cmd.finished.connect(self.save_finished)
612

    
613
            """ show spinner gif animation """
614
            self.label_spinner.setWindowFlags(Qt.WindowStaysOnTopHint)
615
            if not hasattr(self, '_movie'):
616
                self._movie = QMovie(':/newPrefix/spinner.gif')
617
                self.label_spinner.setMovie(self._movie)
618
            self.label_spinner.show()
619
            self._movie.start()
620

    
621
            self._save_work_cmd.start()
622

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

    
627
    def save_finished(self):
628
        """ stop movie and hide label after finishing save """
629
        self._movie.stop()
630
        self.label_spinner.hide()
631
        QMessageBox.about(self.graphicsView, self.tr('Notice'), self._save_work_cmd.resultStr)
632
        self.load_drawing_list()
633

    
634
    '''
635
        @brief      refresh resultPropertyTableWidget
636
        @author     kyouho
637
        @date       2018.07.19
638
    '''
639
    def refreshResultPropertyTableWidget(self):
640
        items = self.graphicsView.scene.selectedItems()
641
        if len(items) == 1:
642
            self.resultPropertyTableWidget.show_item_property(items[0])
643
    
644
    '''
645
        @brief  add message listwidget
646
        @author humkyung
647
        @date   2018.07.31
648
    '''
649
    def onAddMessage(self, messageType, message):
650
        from AppDocData import MessageType
651

    
652
        try:
653
            current = QDateTime.currentDateTime()
654

    
655
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
656
            if messageType == MessageType.Error:
657
                item.setBackground(Qt.red)
658

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

    
663
    '''
664
        @brief      clear log
665
        @author     humkyung
666
        @date       2018.08.01
667
    '''
668
    def onClearLog(self):
669
        self.listWidgetLog.clear()
670

    
671
    '''
672
        @brief      rotate selected symbol
673
        @author     humkyung
674
        @date       2018.08.15
675
    '''
676
    def onRotate(self, action):
677
        selected = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem)]
678
        if len(selected) == 1:
679
            selected[0].rotateSymbol()
680

    
681
    '''
682
        @brief      Area Zoom
683
        @author     Jeongwoo
684
        @date       2018.06.27
685
        @history    connect command's rejected signal
686
    '''
687
    def onAreaZoom(self, action):
688
        if self.actionZoom.isChecked():
689
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
690
            cmd.onRejected.connect(self.onCommandRejected)
691
            self.graphicsView.command = cmd
692

    
693
    def onVendor(self, action):
694
        '''
695
            @brief      make vendor package area
696
            @author     euisung
697
            @date       2019.04.29
698
        '''
699
        if not self.graphicsView.hasImage():
700
            self.actionVendor.setChecked(False)
701
            self.showImageSelectionMessageBox()
702
            return
703

    
704
        self.actionVendor.setChecked(True)
705
        if not hasattr(self.actionVendor, 'tag'):
706
            self.actionVendor.tag = PlacePolygonCommand.PlacePolygonCommand(self.graphicsView)
707
            self.actionVendor.tag.onSuccess.connect(self.onVendorCreated)
708
            self.actionVendor.tag.onRejected.connect(self.onCommandRejected)
709

    
710
        self.graphicsView.command = self.actionVendor.tag
711

    
712
    def onVendorCreated(self):
713
        '''
714
            @brief      add created vendor polygon area to scene
715
            @author     euisung
716
            @date       2019.04.29
717
        '''
718
        try:
719
            count = len(self.actionVendor.tag._polyline._vertices)
720
            if count > 2:
721
                qPoints = []
722
                points = []
723
                for point in self.actionVendor.tag._polyline._vertices:
724
                    points.append([round(point[0]), round(point[1])])
725
                    qPoints.append(QPoint(round(point[0]), round(point[1])))
726
                vendorArea = QPolygonF(qPoints)
727
                vendorItem = QEngineeringVendorItem(vendorArea, points)
728
                vendorItem.area = 'Drawing'
729
                vendorItem.transfer.onRemoved.connect(self.itemRemoved)
730
                self.graphicsView.scene.addItem(vendorItem)
731
        finally:
732
            self.graphicsView.scene.removeItem(self.actionVendor.tag._polyline)
733
            self.actionVendor.tag.reset()
734

    
735
    '''
736
        @brief      Fit Window
737
        @author     Jeongwoo
738
        @date       2018.06.27
739
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
740
    '''
741
    def fitWindow(self, action):
742
        self.graphicsView.useDefaultCommand()
743
        self.graphicsView.zoomImageInit()
744

    
745
    def onConvertPDFToImage(self):
746
        """
747
        @brief      convert to selected pdf to image
748
        @author     humkyung 
749
        @date       2018.07.09
750
        @history    Euisung 2018.10.11 hide shell
751
        """
752
        try: 
753
            filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)) , 'bin64', 'PDF_TO_IMAGE.exe')
754
            subprocess.call(filePath, shell = False)
755
        except Exception as ex:
756
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
757

    
758
    '''
759
        @brief      selection changed
760
        @author     humkyung
761
        @date       2018.06.27
762
        @history    humkung 2018.07.08 call tree widget's findItem
763
    '''
764
    def onSelectionChanged(self):
765
        items = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem) or \
766
            type(item) is QEngineeringLineItem or issubclass(type(item), QEngineeringTextItem) or type(item) is QEngineeringUnknownItem or type(item) is QEngineeringVendorItem]
767
        if items:
768
            item = items[-1]
769
            self.itemTreeWidget.findItem(item)
770
            self.resultPropertyTableWidget.show_item_property(item)
771
            if type(item) is QEngineeringErrorItem:
772
                for index in range(self.tableWidgetInconsistency.rowCount()):
773
                    if self.tableWidgetInconsistency.item(index, 1).tag is item:
774
                        self.tableWidgetInconsistency.selectRow(index)
775
                        break
776
        else:
777
            self.resultPropertyTableWidget.show_item_property(None)
778
        
779
    '''
780
        @brief      Initialize scene and itemTreeWidget
781
        @author     Jeongwoo
782
        @date       2018.06.14
783
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
784
    '''
785
    def onInitializeScene(self, action):
786
        if not self.graphicsView.hasImage():
787
            self.actionEquipment.setChecked(False)
788
            self.showImageSelectionMessageBox()
789

    
790
            return
791

    
792
        try:
793
            msg = QMessageBox()
794
            msg.setIcon(QMessageBox.Critical)
795
            msg.setText(self.tr('Do you want to remove all items?\nThis work cannot be recovered.'))
796
            msg.setWindowTitle(self.tr("Initialize"))
797
            msg.setStandardButtons(QMessageBox.Ok|QMessageBox.Cancel)
798
            if QMessageBox.Ok == msg.exec_():
799

    
800
                appDocData = AppDocData.instance()
801
                appDocData.clearItemList(True)
802
            
803
                items = self.graphicsView.scene.items()
804
                for item in items:
805
                    if type(item) is not QGraphicsPixmapItem and item.scene() is not None:
806
                        #if hasattr(item, 'tranfer'):
807
                        #    item.tranfer.onRemoved.emit(item)
808
                        #else:
809
                        #    self.graphicsView.scene.removeItem(item)
810
                        self.graphicsView.scene.removeItem(item)
811

    
812
                        '''
813
                        if type(item) is QEngineeringLineNoTextItem:
814
                            self.removedItems['LINE'].append(str(item.uid))
815
                        elif type(item) is QEngineeringInstrumentItem:
816
                            self.removedItems['INST'].append(str(item.uid))
817
                        elif type(item) is QEngineeringEquipmentItem:
818
                            self.removedItems['EQUIP'].append(str(item.uid))
819
                        elif type(item) is QEngineeringNoteItem:
820
                            self.removedItems['NOTE'].append(str(item.uid))
821
                        '''
822
                    
823
                if self.path is not None:
824
                    baseName = os.path.basename(self.path)
825
                    self.itemTreeWidget.setCurrentPID(baseName)
826

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

    
831
    '''
832
        @brief      Manage Checkable Action statement
833
        @author     Jeongwoo
834
        @date       2018.05.10
835
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
836
    '''
837
    def actionGroupTriggered(self, action):
838
        if hasattr(self.actionLine, 'tag'):
839
            self.actionLine.tag.onRejected.emit(None)
840

    
841
        if hasattr(self.actionVendor, 'tag'):
842
            self.actionVendor.tag.onRejected.emit(None)
843

    
844
        if self.graphicsView.command is not None:
845
            self.graphicsView.useDefaultCommand()
846

    
847
        for _action in self.actionGroup.actions():
848
            _action.setChecked(False)
849

    
850
        action.setChecked(True)
851

    
852
    '''
853
        @brief      Create Equipment
854
        @author     Jeongwoo
855
        @date       18.05.03
856
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
857
    '''
858
    def createEquipment(self):
859
        if not self.graphicsView.hasImage():
860
            self.actionEquipment.setChecked(False)
861
            self.showImageSelectionMessageBox()
862
            return
863
        if self.actionEquipment.isChecked():
864
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget, self.dirTreeWidget)
865
        else:
866
            self.graphicsView.useDefaultCommand()
867

    
868

    
869
    '''
870
        @brief      Create Nozzle
871
        @author     Jeongwoo
872
        @date       2018.05.03
873
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
874
    '''
875
    def createNozzle(self):
876
        if not self.graphicsView.hasImage():
877
            self.actionNozzle.setChecked(False)
878
            self.showImageSelectionMessageBox()
879
            return
880
        if self.actionNozzle.isChecked():
881
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget, self.dirTreeWidget)
882
        else:
883
            self.graphicsView.useDefaultCommand()
884

    
885
    '''
886
        @brief      Area OCR
887
        @author     Jeongwoo
888
        @date       18.04.18
889
        @history    2018.05.02  Jeongwoo    Change graphicsView.command by actionOCR checked state
890
                                            Show MessageBox when imageviewer doesn't have image
891
    '''
892
    def onAreaOcr(self):
893
        if not self.graphicsView.hasImage():
894
            self.actionOCR.setChecked(False)
895
            self.showImageSelectionMessageBox()
896
            return
897

    
898
        if self.actionOCR.isChecked():
899
            cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView)
900
            cmd.onSuccess.connect(self.onRecognizeText)
901
            cmd.onRejected.connect(self.onCommandRejected)
902
            self.graphicsView.command = cmd
903
        else:
904
            self.graphicsView.useDefaultCommand()
905
    
906
    '''
907
        @brief      show text recognition dialog
908
        @author     humkyung
909
        @date       2018.08.08
910
    '''
911
    def onRecognizeText(self, x, y, width, height):
912
        from OcrResultDialog import QOcrResultDialog
913

    
914
        try:
915
            image = self.graphicsView.image().copy(x, y, width, height)
916
            dialog = QOcrResultDialog(self.graphicsView, image, QRectF(x, y, width, height))
917
            (isAccept, textInfoList) = dialog.showDialog()
918
            if isAccept:
919
                if textInfoList is not None and len(textInfoList) > 0:
920
                    docData = AppDocData.instance()
921
                    for textInfo in textInfoList:
922
                        x = textInfo.getX()
923
                        y = textInfo.getY()
924
                        angle = textInfo.getAngle()
925
                        text = textInfo.getText()
926
                        width = textInfo.getW()
927
                        height = textInfo.getH()
928
                        item = TextItemFactory.instance().createTextItem(textInfo)
929
                        if item is not None:
930
                            item.loc = (x, y)
931
                            item.size = (width, height)
932
                            item.angle = angle
933
                            item.setDefaultTextColor(Qt.blue)
934
                            item.addTextItemToScene(self.graphicsView.scene)
935
                            item.transfer.onRemoved.connect(self.itemRemoved)
936
                        else:
937
                            message = 'error occured({}) in {}:{}'.format('텍스트 생성에 실패했습니다.', sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
938
                            self.addMessage.emit(MessageType.Normal, message)
939
                else:
940
                    QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("Fail to recognize text"))
941
        except Exception as ex:
942
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
943
            self.addMessage.emit(MessageType.Error, message)
944

    
945
    '''
946
        @brief  area configuration
947
    '''
948
    def areaConfiguration(self):
949
        from ConfigurationAreaDialog import QConfigurationAreaDialog
950
        if not self.graphicsView.hasImage():
951
            self.showImageSelectionMessageBox()
952
            return
953
        self.onCommandRejected()
954
        self.dlgConfigurationArea = QConfigurationAreaDialog(self)
955
        self.dlgConfigurationArea.show()
956
        self.dlgConfigurationArea.exec_()
957

    
958
    '''
959
        @brief  configuration
960
    '''
961
    def configuration(self):
962
        from ConfigurationDialog import QConfigurationDialog
963

    
964
        self.dlgConfiguration = QConfigurationDialog(self)
965
        #self.dlgConfiguration.show()
966
        if QDialog.Accepted == self.dlgConfiguration.exec_():
967
            QEngineeringLineItem.LINE_TYPE_COLORS.clear()
968
            QEngineeringInstrumentItem.INST_COLOR = None
969

    
970
    '''
971
        @brief  show nominal diameter dialog 
972
        @author humkyung
973
        @date   2018.06.28
974
    '''
975
    def onShowCodeTable(self):
976
        from CodeTableDialog import QCodeTableDialog
977

    
978
        dlg = QCodeTableDialog(self)
979
        dlg.exec_()
980

    
981
    '''
982
        @brief  show HMB data
983
        @author humkyung
984
        @date   2018.07.11
985
    '''
986
    def onHMBData(self):
987
        from HMBDialog import QHMBDialog
988

    
989
        dlg = QHMBDialog(self)
990
        dlg.show()
991
        dlg.exec_()
992

    
993
    '''
994
        @brief  show line data list 
995
        @author humkyung
996
        @date   2018.05.03
997
    '''
998
    def showItemDataList(self):
999
        from ItemDataExportDialog import QItemDataExportDialog
1000

    
1001
        self.dlgLineDataList = QItemDataExportDialog(self)
1002
        self.dlgLineDataList.exec_()
1003

    
1004
    def showTextDataList(self):
1005
        '''
1006
            @brief      show all text item in scene
1007
            @author     euisung
1008
            @date       2019.04.18
1009
        '''
1010
        try:
1011
            if not self.graphicsView.hasImage():
1012
                self.showImageSelectionMessageBox()
1013
                return
1014

    
1015
            self.onCommandRejected()
1016
            dialog = QTextDataListDialog(self)
1017
            dialog.show()
1018
            dialog.exec_()
1019
        except Exception as ex:
1020
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1021
            self.addMessage.emit(MessageType.Error, message)
1022

    
1023
    '''
1024
        @brief  Show Image Selection Guide MessageBox
1025
        @author Jeongwoo
1026
        @date   2018.05.02
1027
    '''
1028
    def showImageSelectionMessageBox(self):
1029
        QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("First select image drawing"))
1030
        
1031
    '''
1032
        @brief  change selected lines' type by selected line type
1033
        @author humkyung
1034
        @date   2018.06.27
1035
    '''
1036
    def onLineTypeChanged(self, param):
1037
        lineType = self.lineComboBox.itemText(param)
1038
        selected = [item for item in self.graphicsView.scene.selectedItems() if type(item) is QEngineeringLineItem]
1039
        if selected:
1040
            for item in selected:
1041
                item.lineType = lineType
1042

    
1043
    def display_colors(self, value):
1044
        """ display colors """
1045
        from DisplayColors import DisplayColors
1046
        from DisplayColors import DisplayOptions
1047

    
1048
        DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value == True else DisplayOptions.DisplayByLineType
1049
        if hasattr(self, 'graphicsView'):
1050
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1051
            DisplayColors.instance().save_data()
1052
    '''
1053
        @brief      create new drawing
1054
        @author     yeonjin
1055
        @date       2019.07.03
1056
    '''
1057
    def new_drawing(self):
1058
        from QDrawingDialog import QDrawingDialog
1059

    
1060
        dlg = QDrawingDialog(self)
1061
        res = dlg.showDialog()
1062
        if res:
1063
            self.load_drawing_list()
1064

    
1065
    '''
1066
        @brief      Open image drawing file and then display it
1067
        @author     humkyung
1068
        @date       2018.??.??
1069
        @history    18.04.23 Jeongwoo    Add AppDocData.instance().setCurrentPidSource
1070
                    18.04.23 Jeongwoo    Add Store Set Current Pid Image on AppDocData
1071
                    18.05.02 Jeongwoo    Add useDefaultCommand()
1072
                    humkyung 2018.05.24 load recognition result file if exists
1073
                    Jeongwoo 2018.05.29 load data on xml if xml file exist
1074
                    humkyung 2018.08.22 clear scene before loading xml file
1075
    '''
1076
    def onOpenImageDrawing(self, path=None):
1077
        from Drawing import Drawing
1078
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
1079

    
1080
        try:
1081
            appDocData = AppDocData.instance()
1082
            project = appDocData.getCurrentProject()
1083
            
1084
            #for item in self.graphicsView.scene.items():
1085
            #    self.graphicsView.scene.removeItem(item)
1086

    
1087
            self.path = self.graphicsView.loadImageFromFile(project.getDrawingFilePath(), path if type(path) is str else '')
1088
            if os.path.isfile(self.path):
1089
                appDocData.clear()
1090
                self.onCommandRejected()
1091

    
1092
                appDocData.setImgFilePath(self.path)
1093
                appDocData.activeDrawing = Drawing(appDocData.imgName)
1094
                appDocData.setCurrentPidSource(Image.open(self.path))
1095
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
1096

    
1097
                drawingList = self.treeWidgetDrawingList.topLevelItem(0)
1098
                for childIdex in range(drawingList.childCount()):
1099
                    drawingList.child(childIdex).setCheckState(0, Qt.Unchecked)
1100
                for childIdex in range(drawingList.childCount()):
1101
                    child = drawingList.child(childIdex)
1102
                    if child.text(0).replace('.png', '') == appDocData.activeDrawing.name:
1103
                        child.setCheckState(0, Qt.Checked)
1104
                        break
1105

    
1106
                ## Load data on xml
1107
                path = os.path.join(appDocData.getCurrentProject().getTempPath(), appDocData.imgName + '.xml')
1108
                count = 0
1109
                if os.path.isfile(path):
1110
                    for child in parse(path).getroot().getchildren():
1111
                        count = count + len(child.getchildren())
1112
                if count > 0:
1113
                    try:
1114
                        self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, self) if not hasattr(self, 'progress') else self.progress
1115
                        self.progress.setWindowModality(Qt.WindowModal)
1116
                        self.progress.setAutoReset(True)
1117
                        self.progress.setAutoClose(True)
1118
                        self.progress.setMinimum(0)
1119
                        self.progress.resize(600,100)
1120
                        self.progress.setWindowTitle(self.tr("Reading file..."))
1121
                        self.progress.show()
1122

    
1123
                        self.loadRecognitionResultFromXml(path)
1124
                        #self.checkAttribute()
1125
                    finally:
1126
                        self.progress.setValue(self.progress.maximum())
1127
                        self.progress.hide()
1128
                self.changeViewCheckedState(True)
1129
        except Exception as ex:
1130
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1131
            self.addMessage.emit(MessageType.Error, message)
1132

    
1133
        return self.path
1134

    
1135
    def changeViewCheckedState(self, checked, clear=True):
1136
        '''
1137
            @brief      change view checked state
1138
            @author     euisung
1139
            @date       2019.03.06
1140
        '''
1141
        #self.actionImage_Drawing.setChecked(checked)
1142
        self.actionViewText.setChecked(checked)
1143
        self.actionViewSymbol.setChecked(checked)
1144
        self.actionViewLine.setChecked(checked)
1145
        self.actionViewUnknown.setChecked(checked)
1146
        self.actionViewInconsistency.setChecked(checked)
1147
        self.actionViewVendor_Area.setChecked(not checked)
1148
        self.actionDrawing_Only.setChecked(not checked)
1149
        if clear:
1150
            self.tableWidgetInconsistency.clearContents()
1151
            self.tableWidgetInconsistency.setRowCount(0)
1152

    
1153
    def onViewDrawingOnly(self, isChecked):
1154
        '''
1155
            @brief  visible/invisible except image drawing
1156
            @author euisung
1157
            @date   2019.04.22
1158
        '''
1159
        self.changeViewCheckedState(not isChecked, False)
1160
        for item in self.graphicsView.scene.items():
1161
            if type(item) is not QGraphicsPixmapItem:
1162
                item.setVisible(not isChecked)
1163

    
1164
    '''
1165
        @brief  visible/invisible image drawing
1166
        @author humkyung
1167
        @date   2018.06.25
1168
    '''
1169
    def onViewImageDrawing(self, isChecked):
1170
        for item in self.graphicsView.scene.items():
1171
            if type(item) is QGraphicsPixmapItem:
1172
                item.setVisible(isChecked)
1173
                break
1174

    
1175
    '''
1176
        @brief  visible/invisible Text 
1177
        @author humkyung
1178
        @date   2018.06.28
1179
    '''
1180
    def onViewText(self, isChecked):
1181
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
1182
        for item in selected:
1183
            item.setVisible(isChecked)
1184

    
1185
    '''
1186
        @brief  visible/invisible Symbol 
1187
        @author humkyung
1188
        @date   2018.06.28
1189
    '''
1190
    def onViewSymbol(self, isChecked):
1191
        selected = [item for item in self.graphicsView.scene.items() if (issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringErrorItem)]
1192
        for item in selected:
1193
            item.setVisible(isChecked)
1194

    
1195
    '''
1196
        @brief  visible/invisible Line
1197
        @author humkyung
1198
        @date   2018.06.28
1199
    '''
1200
    def onViewLine(self, isChecked):
1201
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem]
1202
        for item in selected:
1203
            item.setVisible(isChecked)
1204

    
1205
    def onViewInconsistency(self, isChecked):
1206
        '''
1207
            @brief  visible/invisible Inconsistency
1208
            @author euisung
1209
            @date   2019.04.03
1210
        '''
1211
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringErrorItem]
1212
        for item in selected:
1213
            item.setVisible(isChecked)
1214

    
1215
    '''
1216
        @brief  visible/invisible Unknown 
1217
        @author humkyung
1218
        @date   2018.06.28
1219
    '''
1220
    def onViewUnknown(self, isChecked):
1221
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
1222
        for item in selected:
1223
            item.setVisible(isChecked)
1224

    
1225
    def onViewVendorArea(self, isChecked):
1226
        '''
1227
            @brief  visible/invisible Vendor Area
1228
            @author euisung
1229
            @date   2019.04.29
1230
        '''
1231
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringVendorItem]
1232
        for item in selected:
1233
            item.setVisible(isChecked)
1234

    
1235

    
1236
    '''
1237
        @brief  create a symbol
1238
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
1239
                                            Add SymbolSvgItem
1240
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1241
                                            Change method to make svg and image path
1242
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
1243
    '''
1244
    def onCreateSymbolClicked(self):
1245
        cmd = FenceCommand.FenceCommand(self.graphicsView)
1246
        cmd.onSuccess.connect(self.onAreaSelected)
1247
        self.graphicsView.command = cmd
1248
        QApplication.setOverrideCursor(Qt.CrossCursor)        
1249

    
1250
        
1251
       
1252
    '''
1253
        @brief      show SymbolEditorDialog with image selected by user
1254
        @author     humkyung
1255
        @date       2018.07.20
1256
    '''
1257
    def onAreaSelected(self, x, y, width, height):
1258
        try:
1259
            image = self.graphicsView.image()
1260
            if image is not None:
1261
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height), AppDocData.instance().getCurrentProject())
1262
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
1263
                self.dirTreeWidget.initDirTreeWidget()
1264
                if isAccepted:
1265
                    if isImmediateInsert:
1266
                        svgPath = newSym.getSvgFileFullPath()
1267
                        img = cv2.imread(newSym.getImageFileFullPath(), 1)
1268
                        w, h = (0, 0)
1269
                        if len(img.shape[::-1]) == 2:
1270
                            w, h = img.shape[::-1]
1271
                        else:
1272
                            _chan, w, h = img.shape[::-1]
1273
                        svg = SymbolSvgItem(svgPath)
1274
                        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)
1275

    
1276
                        svg.transfer.onRemoved.connect(self.itemTreeWidget.itemRemoved)
1277
                        svg.addSvgItemToScene(self.graphicsView.scene)
1278
                        for connector in svg.connectors:
1279
                            self.graphicsView.scene.addItem(connector)
1280
        finally:
1281
            self.onCommandRejected()
1282
            QApplication.restoreOverrideCursor()
1283
    
1284
    '''
1285
        @brief      create a line
1286
        @author     humkyung
1287
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
1288
    '''
1289
    def onPlaceLine(self):        
1290
        import PlaceStreamlineCommand
1291

    
1292
        """
1293
        if not self.graphicsView.hasImage():
1294
            self.actionLine.setChecked(False)
1295
            self.showImageSelectionMessageBox()
1296
            return
1297
        """
1298

    
1299
        self.actionLine.setChecked(True)
1300
        if not hasattr(self.actionLine, 'tag'):
1301
            self.actionLine.tag = PlaceStreamlineCommand.PlaceStreamlineCommand(self.graphicsView)
1302
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
1303
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
1304

    
1305
        self.graphicsView.command = self.actionLine.tag
1306

    
1307
    '''
1308
        @brief      add created lines to scene
1309
        @author     humkyung
1310
        @date       2018.07.23
1311
    '''
1312
    def onLineCreated(self):
1313
        from EngineeringConnectorItem import QEngineeringConnectorItem
1314

    
1315
        try:
1316
            count = len(self.actionLine.tag._polyline._vertices)
1317
            if count > 1:
1318
                items = []
1319

    
1320
                lineType = self.lineComboBox.currentText()
1321
                for index in range(count - 1):
1322
                    start = self.actionLine.tag._polyline._vertices[index]
1323
                    end  = self.actionLine.tag._polyline._vertices[index + 1]
1324
                    
1325
                    lineItem = QEngineeringLineItem(vertices=[start, end])
1326
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
1327
                    lineItem.lineType = lineType
1328
                    if items:
1329
                        lineItem.connect_if_possible(items[-1], 5)
1330
                    else:
1331
                        pt = lineItem.startPoint()
1332
                        selected = [item for item in self.graphicsView.scene.items(QPointF(pt[0], pt[1])) if type(item) is QEngineeringConnectorItem or type(item) is QEngineeringLineItem]
1333
                        if selected:
1334
                            lineItem.connect_if_possible(selected[0].parent if type(selected[0]) is QEngineeringConnectorItem else selected[0], 5)
1335
                    
1336
                    items.append(lineItem)
1337
                    self.graphicsView.scene.addItem(lineItem)
1338

    
1339
                pt = items[-1].endPoint()
1340
                selected = [item for item in self.graphicsView.scene.items(QPointF(pt[0], pt[1])) if type(item) is QEngineeringConnectorItem and item.parent is not items[-1]]
1341
                if selected:
1342
                    items[-1].connect_if_possible(selected[0].parent, 5)
1343

    
1344
        finally:
1345
            self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1346
            self.actionLine.tag.reset()
1347

    
1348
    '''
1349
        @brief      refresh scene
1350
        @author     humkyung
1351
        @date       2018.07.23
1352
    '''
1353
    def onCommandRejected(self, cmd=None):
1354
        try:
1355
            if type(cmd) is PlaceLineCommand.PlaceLineCommand:
1356
                if self.actionLine.tag._polyline:
1357
                    self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1358
                self.graphicsView.scene.update()
1359
                self.actionLine.tag.reset()
1360

    
1361
                self.actionLine.setChecked(False)
1362
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
1363
                self.actionZoom.setChecked(False)
1364
            elif type(cmd) is AreaOcrCommand.AreaOcrCommand:
1365
                self.actionOCR.setChecked(False)
1366
            elif type(cmd) is PlacePolygonCommand.PlacePolygonCommand:
1367
                self.actionVendor.setChecked(False)
1368
            else:
1369
                if hasattr(self.actionLine, 'tag') and self.actionLine.tag._polyline:
1370
                    self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1371
                    self.graphicsView.scene.update()
1372
                    self.actionLine.tag.reset()
1373
                if hasattr(self.actionVendor, 'tag') and self.actionVendor.tag._polyline:
1374
                    self.graphicsView.scene.removeItem(self.actionVendor.tag._polyline)
1375
                    self.graphicsView.scene.update()
1376
                    self.actionVendor.tag.reset()
1377
                self.actionLine.setChecked(False)
1378
                self.actionZoom.setChecked(False)
1379
                self.actionOCR.setChecked(False)
1380
                self.actionVendor.setChecked(False)
1381
        finally:
1382
            self.graphicsView.useDefaultCommand()
1383
     
1384
    '''
1385
        @brief      restore to default command when user press Escape key
1386
        @author     humkyung 
1387
        @date       2018.08.09
1388
        
1389
    '''
1390
    def keyPressEvent(self, event):
1391
        try:
1392
            if event.key() == Qt.Key_Escape:
1393
                # already catched in command
1394
                pass
1395
                #checked = self.actionGroup.checkedAction()
1396
                #if checked:
1397
                #    checked.setChecked(False)
1398
                #    self.graphicsView.useDefaultCommand()
1399
            elif event.key() == Qt.Key_1:
1400
                if self.actionImage_Drawing.isChecked():
1401
                    self.onViewImageDrawing(False)
1402
                    self.actionImage_Drawing.setChecked(False)
1403
                else:
1404
                    self.onViewImageDrawing(True)
1405
                    self.actionImage_Drawing.setChecked(True)
1406
            elif event.key() == Qt.Key_2:
1407
                if self.actionViewText.isChecked():
1408
                    self.onViewText(False)
1409
                    self.actionViewText.setChecked(False)
1410
                else:
1411
                    self.onViewText(True)
1412
                    self.actionViewText.setChecked(True)
1413
            elif event.key() == Qt.Key_3:
1414
                if self.actionViewSymbol.isChecked():
1415
                    self.onViewSymbol(False)
1416
                    self.actionViewSymbol.setChecked(False)
1417
                else:
1418
                    self.onViewSymbol(True)
1419
                    self.actionViewSymbol.setChecked(True)
1420
            elif event.key() == Qt.Key_4:
1421
                if self.actionViewLine.isChecked():
1422
                    self.onViewLine(False)
1423
                    self.actionViewLine.setChecked(False)
1424
                else:
1425
                    self.onViewLine(True)
1426
                    self.actionViewLine.setChecked(True)
1427
            elif event.key() == Qt.Key_5:
1428
                if self.actionViewUnknown.isChecked():
1429
                    self.onViewUnknown(False)
1430
                    self.actionViewUnknown.setChecked(False)
1431
                else:
1432
                    self.onViewUnknown(True)
1433
                    self.actionViewUnknown.setChecked(True)
1434
            elif event.key() == Qt.Key_6:
1435
                if self.actionViewInconsistency.isChecked():
1436
                    self.onViewInconsistency(False)
1437
                    self.actionViewInconsistency.setChecked(False)
1438
                else:
1439
                    self.onViewInconsistency(True)
1440
                    self.actionViewInconsistency.setChecked(True)
1441
            elif event.key() == Qt.Key_7:
1442
                if self.actionViewVendor_Area.isChecked():
1443
                    self.onViewVendorArea(False)
1444
                    self.actionViewVendor_Area.setChecked(False)
1445
                else:
1446
                    self.onViewVendorArea(True)
1447
                    self.actionViewVendor_Area.setChecked(True)
1448
            elif event.key() == 96: # '`' key
1449
                if self.actionDrawing_Only.isChecked():
1450
                    self.onViewDrawingOnly(False)
1451
                    self.actionDrawing_Only.setChecked(False)
1452
                else:
1453
                    self.onViewDrawingOnly(True)
1454
                    self.actionDrawing_Only.setChecked(True)
1455
                    
1456
            QMainWindow.keyPressEvent(self, event)
1457
        except Exception as ex:
1458
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1459
            self.addMessage.emit(MessageType.Error, message)
1460
        
1461
    '''
1462
        @brief      recognize symbol and text
1463
        @author     humkyung
1464
        @date       2018.04.??
1465
        @history    2018.04.16  humkyung    execute line no tracing
1466
                    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
1467
                    2018.05.25  Jeongwoo    Add parameter on QRecognitionDialog.__init__() and Move thread to QRecognitionDialog
1468
                                            Remove codes below if self.dlg.isAccepted == True
1469
                    2018.05.29  Jeongwoo    Remove connects and comments
1470
                    humkyung 2018.11.05 save working date-time
1471
    '''
1472
    def recognize(self, MainWindow):
1473
        from datetime import datetime
1474
        from RecognitionDialog import QRecognitionDialog
1475

    
1476
        if not self.graphicsView.hasImage():
1477
            self.showImageSelectionMessageBox()
1478
            return
1479

    
1480
        try:
1481
            '''
1482
            self.removedItems['LINE'] = []
1483
            self.removedItems['EQUIP'] = []
1484
            self.removedItems['INST'] = []
1485
            self.removedItems['NOTE'] = []
1486
            '''
1487

    
1488
            appDocData = AppDocData.instance()
1489

    
1490
            self.onClearLog()
1491
            appDocData.needReOpening = False
1492
            drawingList = []
1493
            drawingList.append(self.path)
1494
            self.dlg = QRecognitionDialog(self, drawingList, False)
1495
            self.dlg.exec_()
1496

    
1497
            if appDocData.needReOpening == True:
1498
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
1499
                self.drawDetectedItemsToScene()
1500
                
1501
                # save working date-time
1502
                drawings = appDocData.getDrawings()
1503
                drawing = [drawing for drawing in drawings if appDocData.imgName == os.path.splitext(drawing[1])[0]]
1504
                if drawing[0]:
1505
                    drawing[0][2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1506
                    appDocData.saveDrawings(drawing)
1507

    
1508
                currentPid = appDocData.activeDrawing.name
1509

    
1510
                drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1511
                drawingCount = drawingTop.childCount()
1512
                
1513
                for drawing in range(drawingCount):
1514
                    drawingChild = drawingTop.child(drawing)
1515
                    if drawingChild.data(0, 0).find(currentPid) is 0:
1516
                        drawingChild.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1517
                self.changeViewCheckedState(True)
1518
                # up to here
1519
        except Exception as ex:
1520
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1521
            self.addMessage.emit(MessageType.Error, message)
1522

    
1523
    '''
1524
        @brief      remove item from tree widget and then remove from scene
1525
        @date       2018.05.25
1526
        @author     Jeongwoo
1527
    '''
1528
    def itemRemoved(self, item):
1529
        try:
1530
            self.itemTreeWidget.itemRemoved(item)
1531

    
1532
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'connectors') and [connector for connector in _item.connectors if connector.connectedItem is item]]
1533
            for match in matches:
1534
                for connector in match.connectors:
1535
                    if connector.connectedItem is item: connector.connectedItem = None
1536

    
1537
            #matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'remove_assoc_item')]
1538
            #for _item in matches:
1539
            #    _item.remove_assoc_item(item)
1540

    
1541
            matches = [_item for _item in self.graphicsView.scene.items() if type(_item) is QEngineeringLineNoTextItem]
1542
            for match in matches:
1543
                if item is match.prop('From'):
1544
                    match.set_property('From', None)
1545
                elif item is match.prop('To'):
1546
                    match.set_property('To', None)
1547

    
1548
                for run in match.runs:
1549
                    if item in run.items:
1550
                        index = run.items.index(item)
1551
                        run.items.pop(index)
1552

    
1553
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'owner')]
1554
            for match in matches:
1555
                if match.owner is item:
1556
                    match.owner = None
1557

    
1558
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'attrs')]
1559
            done = False
1560
            for match in matches:
1561
                for assoc in match.associations():
1562
                    if item is assoc:
1563
                        match.remove_assoc_item(item)
1564
                        for attr in match.attrs.keys():
1565
                            if str(item.uid) == str(attr.AssocItem.uid):
1566
                                attr.AssocItem = None
1567
                                match.attrs[attr] = ''
1568
                                done = True
1569
                                break
1570
                        break
1571
                if done: break
1572

    
1573
            if type(item) is QEngineeringFlowMarkItem and item.parentItem():
1574
                if item in item.parentItem()._flowMark:
1575
                    item.parentItem()._flowMark.pop(item.parentItem()._flowMark.index(item))
1576

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

    
1582
    '''
1583
        @brief      recognize line
1584
        @author     humkyung
1585
        @date       2018.04.19
1586
        @history    Jeongwoo 2018.04.26 Variable name changed (texts → lineNos)
1587
                                        TextItem type changed (QEngineeringTextItem → QEngineeringLineNoTextItem)
1588
                    humkyung 2018.04.26 remove small objects before recognizing line
1589
                    Jeongwoo 2018.05.02 Show MessageBox when imageviewer doesn't have image
1590
                    Jeongwoo 2018.05.25 Move codes about LineDetector
1591
                    humkyung 2018.06.17 show progress dialog
1592
    '''
1593
    def connect_attributes(self, MainWindow):
1594
        from LineNoTracer import LineNoTracer
1595
        from ConnectAttrDialog import QConnectAttrDialog
1596

    
1597
        if not self.graphicsView.hasImage():
1598
            self.showImageSelectionMessageBox()
1599
            return
1600

    
1601
        try:
1602
            self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView)
1603
            if QDialog.Accepted == self.dlgConnectAttr.exec_():
1604
                self.itemTreeWidget.InitLineNoItems()
1605

    
1606
                # construct line no item
1607
                line_nos = AppDocData.instance().tracerLineNos
1608
                for line_no in line_nos:
1609
                    item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
1610
                    connectedItems = line_no.getConnectedItems()
1611
                    for connectedItem in connectedItems:
1612
                        if issubclass(type(connectedItem), SymbolSvgItem): 
1613
                            self.itemTreeWidget.addTreeItem(item, connectedItem)
1614
                # up to here
1615

    
1616
                self.graphicsView.invalidateScene()
1617
        except Exception as ex:
1618
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1619
            self.addMessage.emit(MessageType.Error, message)
1620

    
1621
    '''
1622
        @history    2018.05.25  Jeongwoo    Moved from MainWindow
1623
                                            SvgItem and TextItem Connect with method in this class
1624
                                            Change method to add GraphicsItem
1625
                    2018.05.28  Jeongwoo    Make QGraphicsItem by symbol, text object. Not xml
1626
                    2018.05.29  Jeongwoo    Change method name and Moved from QRecognitionDialog
1627
                    2018.05.30  Jeongwoo    Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol)
1628
                                            Change Method name and seperate each item
1629
                    humkyung 2018.06.11     display difference between original and recognized image
1630
                    Jeongwoo 2018.06.18     Update Scene after all item added
1631
                    2018.11.05  euisung     add save note item because of dependency
1632
                    2018.11.05  euisung     add db delete process before save
1633
                    2018.11.12  euisung     add title block properties
1634
                    2018.11.12  euisung     db part move new method to dbUpdate
1635
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1636
                    2018.11.29  euisung     change name drawDetectedItems() -> createDetectedItems
1637
    '''
1638
    def createDetectedItems(self, symbolList, textInfoList, otherTextInfoList, titleBlockTextInfoList):
1639
        try:
1640
            appDocData = AppDocData.instance()
1641

    
1642
            QApplication.processEvents()
1643
            self.createDetectedSymbolItem(symbolList)
1644
            QApplication.processEvents()
1645
            self.createDetectedTextItem(textInfoList)
1646
            QApplication.processEvents()
1647
            self.createDetectedOtherTextItem(otherTextInfoList)
1648
            QApplication.processEvents()
1649
            self.createDetectedTitleBlockTextItem(titleBlockTextInfoList)
1650

    
1651
            self.dbUpdate()
1652

    
1653
            # update scene
1654
            #self.graphicsView.scene.update(self.graphicsView.sceneRect())
1655
        except Exception as ex:
1656
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1657
            self.addMessage.emit(MessageType.Error, message)
1658

    
1659
    def drawDetectedItemsToScene(self):
1660
        '''
1661
            @brief  add detected items to scene
1662
            @author euisung
1663
            @date   2018.11.26
1664
        '''
1665
        appDocData = AppDocData.instance()
1666

    
1667
        try:
1668
            for symbol in appDocData.symbols:
1669
                if issubclass(type(symbol), SymbolSvgItem):
1670
                    self.addSvgItemToScene(symbol)
1671
                else:
1672
                    self.graphicsView.scene.addItem(symbol)
1673

    
1674
            for text in appDocData.texts:
1675
                self.addTextItemToScene(text)
1676

    
1677
            for lineNo in appDocData.tracerLineNos:
1678
                self.addTextItemToScene(lineNo)
1679

    
1680
            for line in appDocData.lines:
1681
                self.graphicsView.scene.addItem(line)
1682
                line.transfer.onRemoved.connect(self.itemRemoved)
1683
                for conn in line.connectors:
1684
                    conn.transfer.onPosChanged.connect(line.onConnectorPosChaned)
1685

    
1686
            for unknown in appDocData.unknowns + appDocData.lineIndicators:
1687
                self.graphicsView.scene.addItem(unknown)
1688
        finally:
1689
            # update scene
1690
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1691

    
1692
    def postDetectLineProcess(self):
1693
        '''
1694
            @brief  check allowables among undetected items
1695
            @author euisung
1696
            @date   2018.11.15
1697
            @history    2018.11.15  euisung    no more used, moved to TextItemFactoy isLineNo()
1698
        '''
1699
        from AppDocData import AppDocData
1700
        from TextItemFactory import TextItemFactory
1701

    
1702
        appDocData = AppDocData.instance()
1703

    
1704
        tableNames = ["Fluid Code", "Insulation Purpose", "PnID Number", "Piping Materials Class", "Unit Number"]
1705
        tableDatas = []
1706
        for tableName in tableNames:
1707
            tableNameFormat = tableName.replace(' ','').replace('&&', 'n')
1708
            tableDatas.append(appDocData.getCodeTable(tableNameFormat))
1709

    
1710
        items = self.graphicsView.scene.items()
1711
        for item in items:
1712
            if type(item) is not QEngineeringTextItem:
1713
                continue
1714
            text = item.text()
1715
            for tableData in tableDatas:
1716
                for data in tableData:
1717
                    if data[3] == '':
1718
                        continue
1719
                    else:
1720
                        allows = data[3].split(',')
1721
                        for allow in allows:
1722
                            text = text.replace(allow, data[1])
1723

    
1724
            lineItem = TextItemFactory.instance().createTextItem(text)
1725
            if type(lineItem) is QEngineeringLineNoTextItem:
1726
                lineItem.loc = item.loc
1727
                lineItem.size = item.size
1728
                lineItem.angle = item.angle
1729
                lineItem.area = item.area
1730
                #lineItem.addTextItemToScene(self.graphicsView.scene)
1731
                lineItem.transfer.onRemoved.connect(self.itemRemoved)
1732
                item.transfer.onRemoved.emit(item)
1733
                appDocData.lineNos.append(lineItem)
1734
                
1735
    def createDetectedTitleBlockTextItem(self, textInfoList):
1736
        '''
1737
            @brief  draw title block
1738
            @author euisung
1739
            @date   2018.11.12
1740
            @history    2018.11.26  euisung     remove scene dependency
1741
                        2018.11.29  euisung     change name drawDetectedTitleBlockTextItem() -> createDetectedTitleBlockTextItem
1742
        '''
1743
        from TextItemFactory import TextItemFactory
1744
        import math
1745

    
1746
        try:
1747
            appDocData = AppDocData.instance()
1748

    
1749
            # parse texts
1750
            for textInfo in textInfoList:
1751
                if len(textInfo[1]) is 0:
1752
                    continue
1753
                x = textInfo[1][0].getX()
1754
                y = textInfo[1][0].getY()
1755
                width = textInfo[1][0].getW()
1756
                height = textInfo[1][0].getH()
1757
                angle = round(math.radians(textInfo[1][0].getAngle()), 2)
1758
                text = textInfo[1][0].getText()
1759
                item = TextItemFactory.instance().createTextItem(textInfo)
1760

    
1761
                if item is not None:
1762
                    item.loc = (x, y)
1763
                    item.size = (width, height)
1764
                    item.angle = angle
1765
                    item.area = textInfo[0]
1766
                    #self.addTextItemToScene(item)
1767
                    #appDocData.texts.append(item)
1768
                    appDocData.allItems.append(item)
1769
        except Exception as ex:
1770
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1771
            self.addMessage.emit(MessageType.Error, message)
1772

    
1773
    '''
1774
        @brief      
1775
        @author     humkyung
1776
        @date       2018.08.23
1777
        @history    2018.11.26  euisung     remove scene dependency
1778
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1779
                    2018.11.    euisung     no more used
1780
                    2018.11.29  euisung     change name drawDetectedLines() -> createDetectedLines
1781
    '''
1782
    def createDetectedLines(self, lineList, worker):
1783
        appDocData = AppDocData.instance()
1784
        area = appDocData.getArea('Drawing')
1785

    
1786
        for pts in lineList:
1787
            processLine = QEngineeringLineItem(vertices=[(area.x + param[0], area.y + param[1]) for param in pts])
1788
            processLine.area = 'Drawing'
1789
            #self.graphicsView.scene.addItem(processLine)
1790
            appDocData.lines.append(processLine)
1791
            appDocData.allItems.append(processLine)
1792

    
1793
            if processLine.length() > 100: # TODO: check critical length
1794
                processLine.addFlowArrow()
1795
        
1796
        # re-order process line's start,end according to flow mark
1797
        #worker.arrangeLinePosition(lines, symbols, listWidget)
1798
        # up to here
1799

    
1800
    '''
1801
        history     2018.06.09  humkyung    check length of original and connection point is 2 while parsing
1802
                    2018.11.26  euisung     remove scene dependency
1803
                    2018.11.29  euisung     change name drawDetectedSymbolItem() -> createDetectedSymbolItem
1804
    '''
1805
    def createDetectedSymbolItem(self, symbolList):
1806
        from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
1807
        from SymbolSvgItem import SymbolSvgItem
1808
        import math
1809

    
1810
        try:
1811
            appDocData = AppDocData.instance()
1812
            project = appDocData.getCurrentProject()
1813

    
1814
            searchedMap = []
1815
            for symbol in symbolList:
1816
                pt = [float(x) for x in symbol.getSp()]
1817
                size = [symbol.getWidth(), symbol.getHeight()]
1818
                name = symbol.getName()
1819
                angle = round(math.radians(symbol.getRotatedAngle()), 2)
1820
                _type = symbol.getType()
1821
                flip = symbol.getDetectFlip()
1822
                origin = [0,0]
1823
                if 2 == len(symbol.getOriginalPoint().split(',')):
1824
                    tokens = symbol.getOriginalPoint().split(',')
1825
                    origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
1826
                connPts = []
1827
                if symbol.getConnectionPoint() is not None and symbol.getConnectionPoint() != '':
1828
                    for param in symbol.getConnectionPoint().split('/'):
1829
                        tokens = param.split(',')
1830
                        connPts.append(('AUTO', pt[0] + float(tokens[0]), pt[1] + float(tokens[1]), '0') if len(tokens) == 2 else \
1831
                                       (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), '0') if len(tokens) == 3 else \
1832
                                       (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), tokens[3]) if len(tokens) == 4 else None)
1833

    
1834
                parentSymbol = symbol.getBaseSymbol()
1835
                childSymbol = symbol.getAdditionalSymbol()
1836
                hasInstrumentLabel = symbol.getHasInstrumentLabel()
1837

    
1838
                svgFilePath = os.path.join(project.getSvgFilePath(), _type, name + '.svg')
1839
                if os.path.isfile(svgFilePath):
1840
                    svg = SymbolSvgItem.createItem(_type, svgFilePath, owner=None, flip=flip)
1841
                    #print(pt)
1842
                    #print(origin)
1843
                    svg.buildItem(name, _type, angle, pt, size, origin, connPts, parentSymbol, childSymbol, hasInstrumentLabel)
1844
                    svg.reCalculationRotatedItem()
1845
                    svg.area = 'Drawing'
1846

    
1847
                    # set owner - 2018.07.20 added by humkyung                   
1848
                    matches = [searched for searched in searchedMap if searched[0] == symbol.owner]
1849
                    if len(matches) == 1:
1850
                        svg.owner = matches[0][1]
1851
                    searchedMap.append((symbol, svg))
1852
                    # up to here
1853

    
1854
                    svg.transfer.onRemoved.connect(self.itemRemoved)
1855
                    #self.addSvgItemToScene(svg)
1856
                    appDocData.symbols.append(svg)
1857
                    appDocData.allItems.append(svg)
1858
                else:
1859
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
1860
                    item.isSymbol = True
1861
                    item.angle = angle
1862
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
1863
                    #self.graphicsView.scene.addItem(item)
1864
                    #appDocData.symbols.append(item)
1865
                    appDocData.allItems.append(item)
1866
            # up to here
1867
        except Exception as ex:
1868
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1869
            self.addMessage.emit(MessageType.Error, message)
1870

    
1871
    '''
1872
        @history    2018.06.08  Jeongwoo    Add parameter on round method
1873
        @history    2018.11.02  euisung     Add save note text item
1874
        @history    2018.11.05  euisung     delete save note text item and move to drawDetectedItems()
1875
                    2018.11.26  euisung     remove scene dependency
1876
                    2018.11.29  euisung     change name drawDetectedTextItem() -> createDetectedTextItem
1877
    '''
1878
    def createDetectedTextItem(self, textInfoList):
1879
        from TextItemFactory import TextItemFactory
1880
        import math
1881

    
1882
        try:
1883
            appDocData = AppDocData.instance()
1884

    
1885
            # parse texts
1886
            for textInfo in textInfoList:
1887
                x = textInfo.getX()
1888
                y = textInfo.getY()
1889
                width = textInfo.getW()
1890
                height = textInfo.getH()
1891
                angle = round(math.radians(textInfo.getAngle()), 2)
1892
                text = textInfo.getText()
1893
                if not text: continue
1894

    
1895
                item = TextItemFactory.instance().createTextItem(textInfo)
1896
                if item is not None:
1897
                    item.loc = (x, y)
1898
                    item.size = (width, height)
1899
                    item.angle = angle
1900
                    item.area = 'Drawing'
1901
                    item.transfer.onRemoved.connect(self.itemRemoved)
1902
                    #self.addTextItemToScene(item)
1903
                    #appDocData.texts.append(item)
1904
                    appDocData.allItems.append(item)
1905
        except Exception as ex:
1906
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1907
            self.addMessage.emit(MessageType.Error, message)
1908

    
1909
    '''
1910
        @brief      draw detected texts except which in drawing area
1911
        @history    2018.11.29  euisung     change name drawDetectedOtherTextItem() -> createDetectedOtherTextItem
1912
    '''
1913
    def createDetectedOtherTextItem(self, otherTextInfoList):
1914
        from TextItemFactory import TextItemFactory
1915
        import math
1916

    
1917
        try:
1918
            appDocData = AppDocData.instance()
1919

    
1920
            # parse notes
1921
            for textInfoMap in otherTextInfoList:
1922
                if textInfoMap[0]=='Note':
1923
                    pass
1924

    
1925
                for textInfo in textInfoMap[1]:
1926
                    x = textInfo.getX()
1927
                    y = textInfo.getY()
1928
                    width = textInfo.getW()
1929
                    height = textInfo.getH()
1930
                    angle = round(math.radians(textInfo.getAngle()))
1931
                    text = textInfo.getText()
1932

    
1933
                    item = TextItemFactory.instance().createTextItem(textInfo)
1934

    
1935
                    item.loc = (x, y)
1936
                    item.size = (width, height)
1937
                    item.angle = angle
1938
                    item.area = textInfoMap[0]
1939
                    item.transfer.onRemoved.connect(self.itemRemoved)
1940
                    #appDocData.texts.append(item)
1941
                    appDocData.allItems.append(item)
1942
        except Exception as ex:
1943
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1944
            self.addMessage.emit(MessageType.Error, message)
1945

    
1946
    '''
1947
        @brief  draw unknown items 
1948
        @author humkyung
1949
        @date   2018.06.12
1950
        @history    2018.06.14  Jeongwoo    Change method to add unknown item
1951
                    2018.06.18  Jeongwoo    Add connect on unknown item
1952
                                            Add [transfer] for using pyqtSignal
1953
                    2018.11.26  euisung     remove scene dependency
1954
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1955
                    2018.11.27  euisung     add save to xml
1956
                    2018.11.29  euisung     change name drawUnknownItems() -> createUnknownItems
1957
    '''
1958
    def createUnknownItems(self, path):
1959
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem 
1960
        from EngineeringLineItem import QEngineeringLineItem
1961
        from EngineeringUnknownItem import QEngineeringUnknownItem
1962
        from SaveWorkCommand import SaveWorkCommand
1963

    
1964
        try:
1965
            docData = AppDocData.instance()
1966
            project = docData.getCurrentProject()
1967
            windowSize = docData.getSlidingWindowSize()
1968

    
1969
            thickness = int(windowSize[1])
1970

    
1971
            if docData.needReOpening is not None:
1972
                docData.needReOpening = True
1973

    
1974
            diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(path))
1975
            if os.path.isfile(diffFilePath):
1976
                imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1]
1977

    
1978
                ## remove line
1979
                lines = docData.lines
1980
                for line in lines:
1981
                    line.drawToImage(imgDiff, 255, thickness) if line.thickness is None else line.drawToImage(imgDiff, 255, line.thickness)
1982
                cv2.imwrite(diffFilePath, imgDiff)
1983
                ## up to here
1984

    
1985
                imgNot = np.ones(imgDiff.shape, np.uint8)
1986
                cv2.bitwise_not(imgDiff, imgNot)
1987
                imgNot = cv2.dilate(imgNot, np.ones((8,8), np.uint8))
1988

    
1989
                image, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
1990

    
1991
                ##
1992
                idx = 0
1993
                ##
1994
                smallContours = []
1995
                minimumSize = docData.getConfigs('Filter', 'MinimumSize')
1996
                for contour in contours:
1997
                    [x, y, w, h] = cv2.boundingRect(contour)
1998

    
1999
                    # remove too small one
2000
                    if len(minimumSize) is 1:
2001
                        if (w * h < int(minimumSize[0].value) * int(minimumSize[0].value)):
2002
                            smallContours.append(contour)
2003
                            idx += 1
2004
                            continue
2005

    
2006
                    '''
2007
                    rect = QRectF(x, y, w, h)
2008
                    items = [item for item in diffItems if item.boundingRect().contains(rect)]
2009
                    if len(items) > 0: continue
2010
                    
2011
                    items = [item for item in diffItems if rect.contains(item.boundingRect())]
2012
                    for item in items:
2013
                        diffItems.remove(item)
2014
                    '''
2015

    
2016
                    # create unknown item
2017
                    epsilon = cv2.arcLength(contour, True)*0.001
2018
                    approx = cv2.approxPolyDP(contour, epsilon, True)
2019
                    approx = [pt[0] for pt in approx]
2020
                    resultStr, resultList = self.determineRemainObject(idx, contours, imgNot)
2021
                    if resultStr == 'LineIndicator':
2022
                        item = QEngineeringUnknownItem(approx, 'True', resultList[0], resultList[1])
2023
                        docData.lineIndicators.append(item)
2024
                    elif resultStr == 'MissingLine':
2025
                        pass
2026
                    elif resultStr == 'Unknown':
2027
                        item = QEngineeringUnknownItem(approx, 'False')
2028
                        docData.unknowns.append(item)
2029
                    item.area = 'Drawing'
2030
                    docData.allItems.append(item)
2031
                    item.transfer.onRemoved.connect(self.itemRemoved)
2032
                    idx += 1
2033
                    # up to here                    
2034

    
2035
                imgNotRemoveSmall = cv2.drawContours(imgNot, smallContours, -1, 0, -1)
2036
                notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(path))
2037
                cv2.imwrite(notFilePath, imgNotRemoveSmall)
2038
            else:
2039
                message = 'can\'t found {}'.format(diffFilePath)
2040
                self.addMessage.emit(MessageType.Normal, message)
2041

    
2042
            SaveWorkCommand.save_to_xml()
2043
        except Exception as ex:
2044
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2045
            self.addMessage.emit(MessageType.Error, message)
2046

    
2047
    def determineRemainObject(self, idx, contours, imgNot):
2048
        '''
2049
            @brief      determine remain objects -> line no indicator or unknown
2050
            @author     euisung
2051
            @date       2018.12.26
2052
            @history    2019.03.25  euisung    Change name isLineNoIndicator -> determineRemainObject
2053
        '''
2054
        import math
2055
        [x, y, w, h] = cv2.boundingRect(contours[idx])
2056
        
2057
        if (w < 250 and h < 250):
2058
            return ('Unknown', [])
2059
        
2060
        fLines = []
2061
        maxDifAngle = 3
2062
        mask = np.zeros_like(imgNot)
2063
        cv2.drawContours(mask, contours, idx, 123, -1) # Draw filled contour in mask
2064
        out = np.zeros_like(imgNot) # Extract out the object and place into output image
2065
        out[mask == 123] = imgNot[mask == 123]
2066

    
2067
        # Now crop
2068
        ##print(out)
2069
        (x, y) = np.where(mask == 123)
2070
        (topx, topy) = (np.min(x), np.min(y))
2071
        (bottomx, bottomy) = (np.max(x), np.max(y))
2072
        out = out[topx:bottomx+1, topy:bottomy+1]
2073
        h, w = out.shape[0], out.shape[1]
2074
        maxDifH, maxDifW = math.ceil(math.tan(4 * math.pi / 180) / 2 * w), math.ceil(math.tan(4 * math.pi / 180) / 2 * h)
2075

    
2076
        # detection lines
2077
        edged2 = cv2.Canny(out, 100, 200)
2078
        lines = cv2.HoughLinesP(image=edged2, rho=1, theta=np.pi/180, threshold=25, minLineLength=30, maxLineGap=25)
2079
        #lines = cv2.HoughLines(edged2, 1, np.pi/180, 60)
2080
        if lines is None:
2081
            return ('Unknown', [])
2082
        for line in lines:
2083
            #r, theta = line[0]
2084
            #a, b = np.cos(theta), np.sin(theta)
2085
            #x0, y0 = a * r, b * r
2086
            #x1, y1 = int(x0 + 1000 * (-b)), int(y0 + 1000 * a)
2087
            #x2, y2 = int(x0 - 1000 * (-b)), int(y0 - 1000 * a)
2088
            #cv2.line(out, (x1, y1), (x2, y2), (0, 255, 0), 3)
2089
            x1, y1, x2, y2 = line[0]
2090
            degree = math.atan2(y2 - y1, x2 - x1) * 180 / math.pi
2091
            fLine = [x1, y1, x2, y2, degree]
2092
            #print(fLine)
2093
            fLines.append(fLine)
2094
        
2095
        horLines = []
2096
        verLines = []
2097
        otherLines = []
2098
        isVH = None
2099
        for fLine in fLines:
2100
            degree = math.fabs(fLine[4])
2101
            if degree >= 90 - maxDifAngle:
2102
                verLines.append(fLine)
2103
            elif degree <= maxDifAngle:
2104
                horLines.append(fLine)
2105
            else:
2106
                otherLines.append(fLine)
2107

    
2108
        baseLines = []
2109
        baseDifV = 0
2110
        if len(horLines):
2111
            x, y = w / 2, 0
2112
            baseDifV = maxDifH
2113
            for horLine in horLines:
2114
                x1, y1, x2, y2 = horLine[0], horLine[1], horLine[2], horLine[3]
2115
                y = ((y2-y1)/(x2-x1))*x + y1 - ((y2-y1)/(x2-x1))*x1
2116
                horLine.append(y)
2117
            baseLines = horLines
2118
            isVH = 'H'
2119
        if len(verLines):
2120
            x, y = 0, h / 2
2121
            baseDifV = maxDifW
2122
            for verLine in verLines:
2123
                x1, y1, x2, y2 = verLine[0], verLine[1], verLine[2], verLine[3]
2124
                x = ((x2-x1)/(y2-y1))*y + x1 - ((x2-x1)/(y2-y1))*y1
2125
                verLine.append(x)
2126
            baseLines = verLines
2127
            isVH = 'V'
2128

    
2129
        for otherLine in otherLines:
2130
            x, y = w / 2, 0
2131
            x1, y1, x2, y2 = otherLine[0], otherLine[1], otherLine[2], otherLine[3]
2132
            y = ((y2-y1)/(x2-x1))*x + y1 - ((y2-y1)/(x2-x1))*x1
2133
            otherLine.append(y)
2134

    
2135
        # determine line no indicator 
2136
        if not ((len(horLines) > 0 and len(verLines) > 0) or len(otherLines) is 0 or (len(horLines) == 0 and len(verLines) == 0)):    
2137
            result, mergedOtherLine = self.isLineNoIndicator(w, h, maxDifAngle, baseDifV, baseLines, otherLines)
2138
            if result:
2139
                #print(fLines)
2140
                return ('LineIndicator', [isVH, mergedOtherLine])
2141

    
2142
        return ('Unknown', [])
2143

    
2144
    def isLineNoIndicator(self, w, h, maxDifAngle, baseDifV, baseLines, otherLines):
2145
        '''
2146
            @brief      determine line no indicator
2147
            @author     euisung
2148
            @date       2019.03.25
2149
        '''
2150
        import math
2151

    
2152
        if (w < 250 and h < 250):
2153
            return (False, None)
2154

    
2155
        isSameLine = True
2156
        i = 0
2157
        for baseLine in baseLines:
2158
            if not isSameLine: break
2159
            j = 0
2160
            for baseLinee in baseLines:
2161
                if i == j:
2162
                    j += 1
2163
                    continue
2164
                difV = math.fabs(baseLine[5] - baseLinee[5])
2165
                if difV > baseDifV:
2166
                   isSameLine = False
2167
                   break
2168
                j += 1
2169
            i += 1
2170
        if not isSameLine:
2171
            return (False, None)
2172

    
2173
        isSameLine = True
2174
        i = 0
2175
        maxY = 0
2176
        for otherLine in otherLines:
2177
            y = otherLine[5]
2178
            if math.fabs(y) > maxY:
2179
                maxY = math.fabs(y)
2180
            if not isSameLine: break
2181
            j = 0
2182
            for otherLinee in otherLines:
2183
                if i == j:
2184
                    j += 1
2185
                    continue
2186
                difV = math.fabs(otherLine[4] - otherLinee[4])
2187
                if difV > maxDifAngle:
2188
                   isSameLine = False
2189
                   break
2190
                j += 1
2191
            i += 1
2192
        if not isSameLine:
2193
            return (False, None)
2194
                
2195
        isSameLine = True
2196
        mergedOtherLine = [0, 0, 0, 0]
2197
        i = 0
2198
        maxDif = math.ceil(math.tan(4 * math.pi / 180) * maxY)
2199
        for otherLine in otherLines:
2200
            if not isSameLine: break
2201
            j = 0
2202
            for otherLinee in otherLines:
2203
                if i == j:
2204
                    j += 1
2205
                    continue
2206
                angle = math.fabs(otherLine[4] + otherLinee[4]) / 2
2207
                difV = math.fabs(otherLine[5] - otherLinee[5])
2208
                dist = math.sin((90 - angle) * math.pi / 180) * difV 
2209
                if dist > maxDif:
2210
                   isSameLine = False
2211
                   break
2212
                j += 1
2213
            i += 1
2214
            mergedOtherLine[0] += otherLine[0]
2215
            mergedOtherLine[1] += otherLine[1]
2216
            mergedOtherLine[2] += otherLine[2]
2217
            mergedOtherLine[3] += otherLine[3]
2218
        if not isSameLine:
2219
            (False, None)
2220
                        
2221
        # Show the output image
2222
        #print('line no indicator')
2223
        mergedOtherLine[0] = round(mergedOtherLine[0] / len(otherLines))
2224
        mergedOtherLine[1] = round(mergedOtherLine[1] / len(otherLines))
2225
        mergedOtherLine[2] = round(mergedOtherLine[2] / len(otherLines))
2226
        mergedOtherLine[3] = round(mergedOtherLine[3] / len(otherLines))
2227
        #cv2.line(out, (mergedOtherLine[0], mergedOtherLine[1]), (mergedOtherLine[2], mergedOtherLine[3]), (255, 255, 255), 3)
2228
        #cv2.imshow('Output', out)
2229
        #cv2.waitKey(0)
2230
        #cv2.destroyAllWindows()
2231
        return (True, mergedOtherLine)
2232

    
2233
    '''
2234
        @brief      load recognition result
2235
        @author     humkyung
2236
        @date       2018.04.??
2237
        @history    humkyung 2018.01.12 parse originalpoint and connectionpoint
2238
                    Jeongwoo 2018.04.17 add QGraphicItem with Rotated text
2239
                    Jeongwoo 2018.04.23 Change to Draw texts on QEngineeringTextItem
2240
                    humkyung 2018.04.23 connect item remove slot to result tree
2241
                    Jeongwoo 2018.04.25 Add if state with QEngineeringNoteItem
2242
                    Jeongwoo 2018.04.26 Change method to create TextItem object with TextItemFactory
2243
                    Jeongwoo 2018.05.03 Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
2244
                    Jeongwoo 2018.05.29 Change method name / Change method to add item / Add Line item
2245
                    Jeongwoo 2018.05.30 Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol) / Change method name / Change XML NODE NAMES
2246
                    Jeongwoo 2018.06.12 Add LineNoTextItem from LINE_NO
2247
                    Jeongwoo 2018.06.14 Add UnknownItem from UNKNOWN
2248
                    Jeongwoo 2018.06.18 Update Scene after all item added
2249
                                        Add connect on unknown item
2250
                                        Add [transfer] for using pyqtSignal
2251
                    kyouho  2018.07.12  Add line property logic
2252
                    humkyung 2018.08.22 show progress while loading xml file
2253
                    2018.11.22      euisung     fix note road
2254
    '''
2255
    def loadRecognitionResultFromXml(self, xmlPath):
2256
        docData = AppDocData.instance()
2257
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
2258
        from EngineeringRunItem import QEngineeringRunItem
2259
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2260

    
2261
        try:
2262
            #self.graphicsView.scene.blockSignals(True)
2263

    
2264
            symbols = []
2265
            lines = []
2266

    
2267
            xml = parse(xmlPath)
2268
            root = xml.getroot()
2269
            
2270
            maxValue = 0
2271
            maxValue = maxValue + len(list(root.iter('SYMBOL')))
2272
            maxValue = maxValue + len(list(root.iter('ATTRIBUTE')))
2273
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
2274
            maxValue = maxValue + len(list(root.iter('LINE')))
2275
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
2276
            maxValue = maxValue + len(list(root.iter('SIZETEXT')))
2277
            maxValue = maxValue + len(list(root.iter('TRIM_LINE_NO')))
2278
            self.progress.setMaximum(maxValue)
2279

    
2280
            """ parsing all symbols """
2281
            for symbol in root.find('SYMBOLS').iter('SYMBOL'):
2282
                item = SymbolSvgItem.fromXml(symbol)
2283
                if item is not None:
2284
                    item.transfer.onRemoved.connect(self.itemRemoved)
2285
                    symbols.append(item)
2286
                    docData.symbols.append(item)
2287
                    self.addSvgItemToScene(item)
2288
                else:
2289
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2290
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2291
                    angle = float(symbol.find('ANGLE').text)
2292
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2293
                    item.isSymbol = True
2294
                    item.angle = angle
2295
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2296
                    self.graphicsView.scene.addItem(item)
2297

    
2298
                self.progress.setValue(self.progress.value() + 1)
2299
                
2300
            QApplication.processEvents()
2301

    
2302
            # parse texts
2303
            for text in root.find('TEXTINFOS').iter('ATTRIBUTE'):
2304
                item = QEngineeringTextItem.fromXml(text)
2305
                if item is not None:
2306
                    uid = text.find('UID')
2307
                    attributeValue = text.find('ATTRIBUTEVALUE')
2308
                    name = text.find('NAME').text
2309
                    item.transfer.onRemoved.connect(self.itemRemoved)
2310
                    self.addTextItemToScene(item)
2311
                    #docData.texts.append(item)
2312

    
2313
                    if name == 'TEXT':
2314
                        if uid is not None and attributeValue is not None:
2315
                            item.uid = uid.text
2316
                            item.attribute = attributeValue.text
2317

    
2318
                self.progress.setValue(self.progress.value() + 1)
2319
                
2320
            QApplication.processEvents()
2321

    
2322
            # note
2323
            for text in root.find('NOTES').iter('ATTRIBUTE'):
2324
                item = QEngineeringTextItem.fromXml(text)
2325
                if item is not None:
2326
                    uid = text.find('UID')
2327
                    attributeValue = text.find('ATTRIBUTEVALUE')
2328
                    name = text.find('NAME').text
2329
                    item.transfer.onRemoved.connect(self.itemRemoved)
2330
                    self.addTextItemToScene(item)
2331

    
2332
                    if name == 'NOTE':
2333
                        if uid is not None:
2334
                            item.uid = uid.text
2335

    
2336
                self.progress.setValue(self.progress.value() + 1)
2337
                
2338
            QApplication.processEvents()
2339

    
2340
            for line in root.find('LINEINFOS').iter('LINE'):
2341
                item = QEngineeringLineItem.fromXml(line)
2342
                if item:
2343
                    item.transfer.onRemoved.connect(self.itemRemoved)
2344
                    self.graphicsView.scene.addItem(item)
2345
                    lines.append(item)
2346

    
2347
                self.progress.setValue(self.progress.value() + 1)
2348
                
2349
            QApplication.processEvents()
2350

    
2351
            for unknown in root.iter('UNKNOWN'):
2352
                item = QEngineeringUnknownItem.fromXml(unknown)
2353
                item.transfer.onRemoved.connect(self.itemRemoved)
2354
                if item is not None:
2355
                    item.transfer.onRemoved.connect(self.itemRemoved)
2356
                    self.graphicsView.scene.addItem(item)
2357

    
2358
                self.progress.setValue(self.progress.value() + 1)
2359
                
2360
            QApplication.processEvents()
2361

    
2362
            #""" add tree widget """
2363
            #for item in symbols:
2364
            #    docData.symbols.append(item)
2365
            #    self.addSvgItemToScene(item)
2366
            #    self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2367

    
2368
            for line_no_node in root.find('LINENOS').iter('LINE_NO'):
2369
                line_no = QEngineeringLineNoTextItem.fromXml(line_no_node)
2370
                if line_no is None: continue
2371

    
2372
                line_no.transfer.onRemoved.connect(self.itemRemoved)
2373
                self.addTextItemToScene(line_no)
2374
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2375

    
2376
                runs_node = line_no_node.findall('RUN')
2377
                if runs_node is None: continue
2378

    
2379
                for run_node in runs_node:
2380
                    line_run = QEngineeringRunItem()
2381
                    for child_node in run_node:
2382
                        uidElement = child_node.find('UID')
2383
                        if uidElement is not None:
2384
                            uid = uidElement.text
2385
                            run_item = self.graphicsView.findItemByUid(uid)
2386
                            if run_item is not None:
2387
                                run_item._owner = line_no
2388
                                line_run.items.append(run_item)
2389
                    line_run.owner = line_no
2390
                    line_no.runs.append(line_run)
2391

    
2392
                    for run_item in line_run.items:
2393
                        if issubclass(type(run_item), SymbolSvgItem): self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2394

    
2395
                #docData.tracerLineNos.append(line_no)
2396

    
2397
                self.progress.setValue(self.progress.value() + 1)
2398
            QApplication.processEvents()
2399

    
2400
            for trimLineNo in root.iter('TRIM_LINE_NO'):
2401
                line_no = QEngineeringTrimLineNoTextItem()
2402
                line_no.uid = uuid.UUID(trimLineNo.find('UID').text, version=4)
2403

    
2404
                run = trimLineNo.find('RUN')
2405
                if run is not None:
2406
                    line_run = QEngineeringRunItem()
2407
                    for child in run:
2408
                        uidElement = child.find('UID')
2409
                        if uidElement is not None:
2410
                            uid = uidElement.text
2411
                            run_item = self.graphicsView.findItemByUid(uid)
2412
                            if run_item is not None:
2413
                                run_item.owner = line_no
2414
                                line_run.items.append(run_item)
2415
                    line_no.runs.append(line_run)
2416
                    line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2417
                    
2418
                    for run_item in line_run.items:
2419
                        if issubclass(type(run_item), SymbolSvgItem): self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2420

    
2421
                    docData.tracerLineNos.append(line_no)
2422

    
2423
                self.progress.setValue(self.progress.value() + 1)
2424

    
2425
            if root.find('VENDORS') is not None:
2426
                for vendor in root.find('VENDORS').iter('VENDOR'):
2427
                    item = QEngineeringVendorItem.fromXml(vendor)
2428
                    item.transfer.onRemoved.connect(self.itemRemoved)
2429
                    self.graphicsView.scene.addItem(item)
2430

    
2431
            # connect flow item to line
2432
            for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
2433
                for line in lines:
2434
                    if flowMark.owner is line:
2435
                        line._flowMark.append(flowMark)
2436
                        flowMark.setParentItem(line)
2437
            # up to here
2438

    
2439
            """ update scene """
2440
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2441
            for item in self.graphicsView.scene.items():
2442
                item.setVisible(True)
2443

    
2444
            
2445

    
2446
        except Exception as ex:
2447
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2448
            self.addMessage.emit(MessageType.Error, message)
2449
        finally:
2450
            pass
2451
            #self.graphicsView.scene.blockSignals(False)
2452

    
2453
    '''
2454
        @brief      Remove added item on same place and Add GraphicsItem
2455
        @author     Jeongwoo
2456
        @date       2018.05.25
2457
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2458
                    2018.06.18  Jeongwoo    Set Z-index
2459
    '''
2460
    def addSvgItemToScene(self, svgItem):
2461
        svgItem.addSvgItemToScene(self.graphicsView.scene)
2462
        
2463
    '''
2464
        @brief      Remove added item on same place and Add GraphicsItem
2465
        @author     Jeongwoo
2466
        @date       2018.05.25
2467
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2468
                    2018.06.05  Jeongwoo    Remove Size condition
2469
                    2018.06.18  Jeongwoo    Set Z-index
2470
    '''
2471
    def addTextItemToScene(self, textItem):
2472
        textItem.addTextItemToScene(self.graphicsView.scene)
2473
        
2474
    '''
2475
        @brief      Remove added item on same place and Add GraphicsItem
2476
        @author     Jeongwoo
2477
        @date       2018.05.29
2478
        @history    2018.06.18  Jeongwoo    Set Z-index
2479
    '''
2480
    def addLineItemToScene(self, lineItem):
2481
        self.graphicsView.scene.addItem(lineItem)
2482

    
2483
    '''
2484
        @brief      generate output xml file
2485
        @author     humkyung
2486
        @date       2018.04.23
2487
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
2488
    '''
2489
    def generateOutput(self):
2490
        import XmlGenerator as xg
2491

    
2492
        if not self.graphicsView.hasImage():
2493
            self.showImageSelectionMessageBox()
2494
            return
2495

    
2496
        try:
2497
            appDocData = AppDocData.instance()
2498

    
2499
            ## collect items
2500
            appDocData.lines.clear()
2501
            appDocData.lines = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem and item.owner is None]
2502

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

    
2506
            appDocData.equipments.clear()
2507
            for item in self.graphicsView.scene.items():
2508
                if type(item) is QEngineeringEquipmentItem:
2509
                    appDocData.equipments.append(item)
2510

    
2511
            appDocData.texts.clear()
2512
            appDocData.texts = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem) and type(item) is not QEngineeringLineNoTextItem]
2513
            ## up to here
2514

    
2515
            appDocData.imgOutput = np.ones((appDocData.imgHeight, appDocData.imgWidth), np.uint8)*255
2516
            xg.writeOutputXml(appDocData.imgName, appDocData.imgWidth, appDocData.imgHeight) # TODO: check
2517
            project = appDocData.getCurrentProject()
2518
            cv2.imwrite(os.path.join(project.getTempPath() , 'OUTPUT.png') , appDocData.imgOutput)
2519
        except Exception as ex:
2520
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2521
            self.addMessage.emit(MessageType.Error, message)
2522

    
2523
    '''
2524
        @brief      resetting attribute at secne
2525
        @author     kyoyho
2526
        @date       2018.08.21
2527
    '''
2528
    """
2529
    def checkAttribute(self):
2530
        try:
2531

2532
            docData = AppDocData.instance()
2533
            if not self.graphicsView.hasImage():
2534
                return
2535

2536
            # symbol 경우
2537
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringSpecBreakItem and type(item) is not QEngineeringEndBreakItem]
2538
            for item in items:
2539
                attrs = item.attrs
2540
                
2541
                removeAttrList = []
2542
                for attr in attrs:
2543
                    if type(attr) is tuple:
2544
                        continue
2545

2546
                    if attr is None:
2547
                        removeAttrList.append(attr)
2548
                        continue
2549

2550
                    attrInfo = docData.getSymbolAttributeByUID(attr.UID)
2551
                    if attrInfo is None:
2552
                        removeAttrList.append(attr)
2553
                    # 해당 attribute가 맞는지 확인
2554
                    else:
2555
                        attrType = attrInfo.AttributeType
2556
                        _type = type(attr)
2557
                        if attrType == 'Symbol Item':
2558
                            if not issubclass(_type, SymbolSvgItem):
2559
                                removeAttrList.append(attr)
2560
                        elif attrType == 'Text Item':
2561
                            if _type is not QEngineeringTextItem:
2562
                                removeAttrList.append(attr)
2563
                        elif attrType == 'Int':
2564
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
2565
                                removeAttrList.append(attr)
2566
                        elif attrType == 'String':
2567
                            if _type is not UserInputAttribute:
2568
                                removeAttrList.append(attr)
2569

2570
                for attr in removeAttrList:
2571
                    del attrs[attr]
2572

2573
            # Line No Text Item의 경우
2574
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringLineNoTextItem)]
2575
            for item in items:
2576
                attrs = item.attrs
2577
                
2578
                removeAttrList = []
2579
                for attr in attrs:
2580
                    if type(attr) is UserInputAttribute:
2581
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
2582
                        if attrInfo is None:
2583
                            removeAttrList.append(attr)
2584

2585
                for attr in removeAttrList:
2586
                    del attrs[attr]
2587

2588
        except Exception as ex:
2589
                message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2590
                self.addMessage.emit(MessageType.Error, message)
2591
    """
2592
    '''
2593
        @brief      Check Number
2594
        @author     kyouho
2595
        @date       2018.08.20
2596
    '''
2597
    def isNumber(self, num):
2598
        p = re.compile('(^[0-9]+$)')
2599
        result = p.match(num)
2600

    
2601
        if result:
2602
            return True
2603
        else:
2604
            return False
2605

    
2606
    '''
2607
        @brief      find overlap Connector
2608
        @author     kyouho
2609
        @date       2018.08.28
2610
    '''
2611
    def findOverlapConnector(self, connectorItem):
2612
        from shapely.geometry import Point
2613
        from EngineeringConnectorItem import QEngineeringConnectorItem
2614
        itemList = []
2615
        
2616
        x = connectorItem.center()[0]
2617
        y = connectorItem.center()[1]
2618

    
2619
        connectors = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringConnectorItem and item != connectorItem]
2620
        for connector in connectors:
2621
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
2622
                itemList.append(connector.parent)
2623

    
2624
        return itemList
2625

    
2626
    def create_symbol(self):        
2627
        symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, None, AppDocData.instance().getCurrentProject())
2628
        (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()        
2629
        self.dirTreeWidget.initDirTreeWidget()        
2630
            
2631

    
2632
if __name__ == '__main__':
2633
    import locale
2634
    from PyQt5.QtCore import QTranslator
2635
    from License import QLicenseDialog
2636
    from ProjectDialog import Ui_Dialog
2637
    from App import App 
2638

    
2639
    app = App(sys.argv)
2640
    try:
2641
        if True == QLicenseDialog.check_license_key():
2642
            dlg = Ui_Dialog()
2643
            selectedProject = dlg.showDialog()
2644
            if selectedProject is not None:
2645
                AppDocData.instance().setCurrentProject(selectedProject)
2646
                app._mainWnd = MainWindow.instance()
2647
                app._mainWnd.show()
2648
                sys.exit(app.exec_())
2649
    except Exception as ex:
2650
        print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
2651
    finally:
2652
        pass
클립보드 이미지 추가 (최대 크기: 500 MB)