프로젝트

일반

사용자정보

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

hytos / DTI_PID / DTI_PID / MainWindow.py @ 94302d85

이력 | 보기 | 이력해설 | 다운로드 (117 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 AreaOcrCommand
14
import CreateSymbolCommand
15
import AreaZoomCommand
16
import FenceCommand
17
import PlaceLineCommand
18
import PlacePolygonCommand
19

    
20
import cv2
21
import numpy as np
22

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

    
28
from PIL import Image
29

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

    
34
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Shapes')
35
from EngineeringPolylineItem import QEngineeringPolylineItem
36
from EngineeringLineItem import QEngineeringLineItem
37
from SymbolSvgItem import SymbolSvgItem
38
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
39
from EngineeringTextItem import QEngineeringTextItem
40
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
41
from EngineeringNoteItem import QEngineeringNoteItem
42
from QEngineeringSizeTextItem import QEngineeringSizeTextItem
43
from EngineeringUnknownItem import QEngineeringUnknownItem
44
from EngineeringEquipmentItem import QEngineeringEquipmentItem
45
from EngineeringInstrumentItem import QEngineeringInstrumentItem
46
from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
47
from EngineeringErrorItem import QEngineeringErrorItem
48
from EngineeringVendorItem import QEngineeringVendorItem
49
from EngineeringEndBreakItem import QEngineeringEndBreakItem
50
from EngineeringReducerItem import QEngineeringReducerItem
51
from EngineeringFlowMarkItem import QEngineeringFlowMarkItem
52
from AppDocData import *
53
import SymbolTreeWidget, SymbolPropertyTableWidget
54
import SymbolEditorDialog
55
import ItemTreeWidget
56
import ItemPropertyTableWidget
57
from UserInputAttribute import UserInputAttribute
58
from TextItemFactory import TextItemFactory
59
from TrainingImageListDialog import QTrainingImageListDialog
60
from TextDataListDialog import QTextDataListDialog
61
from DisplayColors import DisplayColors
62
from DisplayColors import DisplayOptions
63
import uuid
64

    
65
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane):
66
    """ This is MainWindow class """
67
    addMessage = pyqtSignal(Enum, str)
68

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

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

    
105
        docData = AppDocData.instance()
106
        project = docData.getCurrentProject()
107
        _translate = QCoreApplication.translate
108
        self.setWindowTitle(_translate("Digital P&ID - {}".format(project.name), "Digital P&ID - {}".format(project.name)))
109

    
110
        self.lineComboBox = QComboBox(self.toolBar)
111
        for condition in LineTypeConditions.items():
112
            self.lineComboBox.addItem(condition.name)
113
        self.lineComboBox.currentIndexChanged.connect(self.onLineTypeChanged)
114

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

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

    
138
        self.verticalLayout.addWidget(self.graphicsView)
139

    
140
        # Add Custom TreeWidget
141
        self.dirTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
142
        self.dirTreeWidget.header().hide()
143
        self.symbolTabVerticalLayout.addWidget(self.dirTreeWidget)
144

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

    
156
        # Add Custom Result Tree Widget (Symbol Explorer)
157
        self.itemTreeWidget = ItemTreeWidget.QItemTreeWidget(self.graphicsView)
158
        self.itemTreeWidget.header().hide()
159
        self.symbolExplorerVerticalLayout.addWidget(self.itemTreeWidget)
160

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

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

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

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

    
238
        # removedItems
239
        '''
240
        self.removedItems = {}
241
        self.removedItems['LINE'] = []
242
        self.removedItems['EQUIP'] = []
243
        self.removedItems['INST'] = []
244
        self.removedItems['NOTE'] = []
245
        '''
246

    
247
        self.delimiter = '"'
248
    
249
        self.resizeDocks({self.dockWidget}, {self.dockWidgetObjectExplorer.sizeHint().width()}, Qt.Horizontal)
250

    
251
        self.treeWidgetDrawingList.setHeaderHidden(False)
252
        self.treeWidgetDrawingList.header().setStretchLastSection(False)
253
        self.treeWidgetDrawingList.setHeaderLabels([self.tr('Name'), self.tr('DateTime')])
254
        self.treeWidgetDrawingList.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
255
        self.treeWidgetDrawingList.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
256
        self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing)
257
        self.load_drawing_list()
258

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

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

    
280
        # inconsistency table
281
        self.tableWidgetInconsistency.setColumnCount(2)
282
        self.tableWidgetInconsistency.setHorizontalHeaderLabels(['Owner', 'Message'])
283
        self.tableWidgetInconsistency.setEditTriggers(QAbstractItemView.NoEditTriggers)
284
        self.tableWidgetInconsistency.itemClicked.connect(self.inconsistencyItemClickEvent)
285
        self.tableWidgetInconsistency.keyPressEvent = self.inconsistencyTableKeyPressEvent
286

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

    
295
        return QWidget.eventFilter(self, source, event)
296

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

    
315
    def onValidation(self):
316
        """
317
        @brief  validation check
318
        @author euisung
319
        @date   2019.04.01
320
        """
321
        if not self.graphicsView.hasImage():
322
            self.showImageSelectionMessageBox()
323
            return
324

    
325
        errors = []
326

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

    
335
            for error in errors:
336
                error.transfer.onRemoved.connect(self.itemRemoved)
337
                self.graphicsView.scene.addItem(error)
338

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

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

    
366
        item = QTableWidgetItem(errorItem.msg)
367
        #item.setFlags(Qt.ItemIsEnabled)
368
        item.tag = errorItem
369
        items.append(item)
370

    
371
        return items
372

    
373
    def inconsistencyItemClickEvent(self, item):
374
        """
375
        @brief  inconsistency table item clicked
376
        @author euisung
377
        @date   2019.04.02
378
        """
379
        from HighlightCommand import HighlightCommand
380

    
381
        HighlightCommand(self.graphicsView).execute(item.tag)
382

    
383
    def load_stylesheet(self, file):
384
        """
385
        @brief  load stylesheets
386
        @author humkyung
387
        @date   2018.10.29
388
        """
389

    
390
        QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
391

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

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

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

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

    
434
        try:
435
            appDocData = AppDocData.instance()
436
            drawings = appDocData.getDrawings()
437

    
438
            self.treeWidgetDrawingList.clear()
439
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList, [self.tr('P&ID Drawings'), ''])
440
            self.treeWidgetDrawingList.root.setFlags(self.treeWidgetDrawingList.root.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
441
            self.treeWidgetDrawingList.root.setCheckState(0, Qt.Unchecked)
442
            files = appDocData.getDrawingFileList()
443
            for file in files:
444
                drawing = [drawing for drawing in drawings if drawing[1] == file]
445
                if not drawing or not drawing[0]:
446
                    drawings.append([None, file, None])
447

    
448
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [file, drawing[0][2] if drawing and drawing[0] else ''])
449
                item.setIcon(0, QIcon(':newPrefix/image.png'))
450
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
451
                item.setCheckState(0, Qt.Unchecked)
452
            
453
            self.treeWidgetDrawingList.root.setText(0, self.tr('P&ID Drawings')+'({})'.format(self.treeWidgetDrawingList.root.childCount()))
454
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
455
            self.treeWidgetDrawingList.root.sortChildren(0, Qt.AscendingOrder)
456
            self.treeWidgetDrawingList.resizeColumnToContents(0)
457

    
458
            appDocData.saveDrawings(drawings)
459
        except Exception as ex:
460
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
461
            self.addMessage.emit(MessageType.Error, message)
462

    
463
    def open_selected_drawing(self, item, column):
464
        """
465
        @brief      open selected p&id drawing
466
        @author     humkyung
467
        @date       18.11.02
468
        """
469
        appDocData = AppDocData.instance()
470
        drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), item.text(0))
471
        self.onOpenImageDrawing(drawing)
472

    
473
    def onShowDetectSymbol(self):
474
        from DetectSymbolDialog import QDetectSymbolDialog
475

    
476
        dlgDetectSymbol = QDetectSymbolDialog(self)
477
        dlgDetectSymbol.show()
478
        dlgDetectSymbol.exec_()
479
        
480
    '''
481
        @brief      OCR Editor
482
        @author     euisung
483
        @date       2018.10.05
484
        @history    2018.10.16 euisung      no more used, Integrated with oCRTrainingClicked
485
    '''
486
    def oCRTrainingEdidorClicked(self):
487
        from TrainingEditorDialog import QTrainingEditorDialog
488

    
489
        try:
490
            dialog = QTrainingEditorDialog(self)
491
            dialog.exec_()
492
        except Exception as ex:
493
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
494
            self.addMessage.emit(MessageType.Error, message)
495
            
496
        return
497

    
498
    '''
499
        @brief      OCR Training
500
        @author     euisung
501
        @date       2018.09.27
502
        @history    euisung 2018.10.16 TrainingListDialog -> TrainingImageListDialog
503
    '''
504
    def oCRTrainingClicked(self):
505
        try:
506
            dialog = QTrainingImageListDialog(self)
507
            dialog.exec_()
508
        except Exception as ex:
509
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
510
            self.addMessage.emit(MessageType.Error, message)
511

    
512
    '''
513
        @brief      show unknownitem's count
514
        @author     kyouho
515
        @date       2018.08.27
516
    '''
517
    def findReplaceTextClicked(self):
518
        if not self.graphicsView.hasImage():
519
            self.showImageSelectionMessageBox()
520
            return
521

    
522
        from TextItemEditDialog import QTextItemEditDialog
523

    
524
        self.dlgTextItemEdit = QTextItemEditDialog(self)
525
        self.dlgTextItemEdit.show()
526
        self.dlgTextItemEdit.exec_()
527

    
528
    '''
529
        @brief      show unknownitem's count
530
        @author     humkyung
531
        @date       2018.08.23
532
        @history    humkyung 2018.08.30 display count of symbol, line, text
533
    '''
534
    def onSceneChanged(self):
535
        items = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
536
        if len(items) > 0:
537
            self.labelStatus.setText("<font color='red'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
538
        else:
539
            self.labelStatus.setText("<font color='black'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
540

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

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

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

    
550
        self.itemTreeWidget.sceneChanged(self.graphicsView.scene.items())
551

    
552
    def dbUpdate(self):
553
        '''
554
            @brief      db update when save or recognition
555
            @author     euisung
556
            @date       2018.11.12
557
            @history    2018.11.02      euisung     remove scene dependency
558
        '''
559
        from AppDocData import AppDocData
560

    
561
        try:
562
            appDocData = AppDocData.instance()
563

    
564
            titleBlockProps = appDocData.getTitleBlockProperties()
565
            #items = self.graphicsView.scene.items()
566
            items = appDocData.allItems
567
            titleBlockItems = []
568
            for item in items:
569
                #if type(item) is QEngineeringLineNoTextItem:
570
                #    item.saveLineData()
571
                if type(item) is QEngineeringTextItem:
572
                    for titleBlockProp in titleBlockProps:
573
                        if item.area == titleBlockProp[0]:
574
                            titleBlockItems.append(item)
575

    
576
            dbItems = [item for item in items if type(item) is QEngineeringInstrumentItem or type(item) is QEngineeringEquipmentItem or type(item) is QEngineeringReducerItem or\
577
            type(item) is QEngineeringNoteItem or type(item) is SymbolSvgItem or type(item) is QEngineeringLineNoTextItem or type(item) is QEngineeringVendorItem] + titleBlockItems
578
            appDocData.saveToDatabase(dbItems)
579
        except Exception as ex:
580
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
581
            self.addMessage.emit(MessageType.Error, message)
582

    
583
    '''
584
        @brief      action save click event
585
        @author     kyouho
586
        @date       2018.08.09
587
        @history    2018.11.02      euisung     add line data list db update
588
                    humkyung save saved time to database
589
                    2018.11.05      euisung     add note data list db update
590
                    2018.11.05      euisung     add db delete process before save
591
                    2018.11.12      euisung     db part move new method to dbUpdate
592
    '''
593
    def actionSaveCliked(self):
594
        from datetime import datetime
595
        from AppDocData import AppDocData
596
        from EngineeringAbstractItem import QEngineeringAbstractItem
597
        from SaveWorkCommand import SaveWorkCommand 
598

    
599
        try:
600
            appDocData = AppDocData.instance()
601
            if appDocData.imgName is None:
602
                self.showImageSelectionMessageBox()
603
                return
604

    
605
            appDocData.clearItemList(False)
606

    
607
            items = self.graphicsView.scene.items()
608
            for item in items:
609
                if issubclass(type(item), QEngineeringAbstractItem):
610
                    appDocData.allItems.append(item)
611
                    if issubclass(type(item), QEngineeringTextItem):
612
                        appDocData.texts.append(item)
613
            ##
614

    
615
            itemTypes = []
616
            for item in items:
617
                typeExist = False
618
                for itemType in itemTypes:
619
                    if type(item) is itemType:
620
                        typeExist = True
621
                        break
622
                if not typeExist:
623
                    itemTypes.append(type(item))
624
            ##
625

    
626
            self._save_work_cmd = SaveWorkCommand()
627
            self._save_work_cmd.display_message.connect(self.onAddMessage)
628
            self._save_work_cmd.finished.connect(self.save_finished)
629

    
630
            """ show spinner gif animation """
631
            self.label_spinner.setWindowFlags(Qt.WindowStaysOnTopHint)
632
            if not hasattr(self, '_movie'):
633
                self._movie = QMovie(':/newPrefix/spinner.gif')
634
                self.label_spinner.setMovie(self._movie)
635
            self.label_spinner.show()
636
            self._movie.start()
637

    
638
            self._save_work_cmd.start()
639

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

    
644
    def save_finished(self):
645
        """ stop movie and hide label after finishing save """
646
        self._movie.stop()
647
        self.label_spinner.hide()
648
        QMessageBox.about(self.graphicsView, self.tr('Notice'), self._save_work_cmd.resultStr)
649
        self.load_drawing_list()
650

    
651
    '''
652
        @brief      refresh resultPropertyTableWidget
653
        @author     kyouho
654
        @date       2018.07.19
655
    '''
656
    def refreshResultPropertyTableWidget(self):
657
        items = self.graphicsView.scene.selectedItems()
658
        if len(items) == 1:
659
            self.resultPropertyTableWidget.show_item_property(items[0])
660
    
661
    '''
662
        @brief  add message listwidget
663
        @author humkyung
664
        @date   2018.07.31
665
    '''
666
    def onAddMessage(self, messageType, message):
667
        from AppDocData import MessageType
668

    
669
        try:
670
            current = QDateTime.currentDateTime()
671

    
672
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
673
            if messageType == MessageType.Error:
674
                item.setBackground(Qt.red)
675

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

    
680
    '''
681
        @brief      clear log
682
        @author     humkyung
683
        @date       2018.08.01
684
    '''
685
    def onClearLog(self):
686
        self.listWidgetLog.clear()
687

    
688
    '''
689
        @brief      rotate selected symbol
690
        @author     humkyung
691
        @date       2018.08.15
692
    '''
693
    def onRotate(self, action):
694
        selected = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem)]
695
        if len(selected) == 1:
696
            selected[0].rotateSymbol()
697

    
698
    '''
699
        @brief      Area Zoom
700
        @author     Jeongwoo
701
        @date       2018.06.27
702
        @history    connect command's rejected signal
703
    '''
704
    def onAreaZoom(self, action):
705
        if self.actionZoom.isChecked():
706
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
707
            cmd.onRejected.connect(self.onCommandRejected)
708
            self.graphicsView.command = cmd
709

    
710
    def onVendor(self, action):
711
        '''
712
            @brief      make vendor package area
713
            @author     euisung
714
            @date       2019.04.29
715
        '''
716
        if not self.graphicsView.hasImage():
717
            self.actionVendor.setChecked(False)
718
            self.showImageSelectionMessageBox()
719
            return
720

    
721
        self.actionVendor.setChecked(True)
722
        if not hasattr(self.actionVendor, 'tag'):
723
            self.actionVendor.tag = PlacePolygonCommand.PlacePolygonCommand(self.graphicsView)
724
            self.actionVendor.tag.onSuccess.connect(self.onVendorCreated)
725
            self.actionVendor.tag.onRejected.connect(self.onCommandRejected)
726

    
727
        self.graphicsView.command = self.actionVendor.tag
728

    
729
    def onVendorCreated(self):
730
        '''
731
            @brief      add created vendor polygon area to scene
732
            @author     euisung
733
            @date       2019.04.29
734
        '''
735
        try:
736
            count = len(self.actionVendor.tag._polyline._vertices)
737
            if count > 2:
738
                qPoints = []
739
                points = []
740
                for point in self.actionVendor.tag._polyline._vertices:
741
                    points.append([round(point[0]), round(point[1])])
742
                    qPoints.append(QPoint(round(point[0]), round(point[1])))
743
                vendorArea = QPolygonF(qPoints)
744
                vendorItem = QEngineeringVendorItem(vendorArea, points)
745
                vendorItem.area = 'Drawing'
746
                vendorItem.transfer.onRemoved.connect(self.itemRemoved)
747
                self.graphicsView.scene.addItem(vendorItem)
748
        finally:
749
            self.graphicsView.scene.removeItem(self.actionVendor.tag._polyline)
750
            self.actionVendor.tag.reset()
751

    
752
    '''
753
        @brief      Fit Window
754
        @author     Jeongwoo
755
        @date       2018.06.27
756
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
757
    '''
758
    def fitWindow(self, action):
759
        self.graphicsView.useDefaultCommand()
760
        self.graphicsView.zoomImageInit()
761

    
762
    def onConvertPDFToImage(self):
763
        """
764
        @brief      convert to selected pdf to image
765
        @author     humkyung 
766
        @date       2018.07.09
767
        @history    Euisung 2018.10.11 hide shell
768
        """
769
        try: 
770
            filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)) , 'bin64', 'PDF_TO_IMAGE.exe')
771
            subprocess.call(filePath, shell = False)
772
        except Exception as ex:
773
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
774

    
775
    '''
776
        @brief      selection changed
777
        @author     humkyung
778
        @date       2018.06.27
779
        @history    humkung 2018.07.08 call tree widget's findItem
780
    '''
781
    def onSelectionChanged(self):
782
        items = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem) or \
783
            type(item) is QEngineeringLineItem or issubclass(type(item), QEngineeringTextItem) or type(item) is QEngineeringUnknownItem or type(item) is QEngineeringVendorItem]
784
        if items:
785
            item = items[-1]
786
            self.itemTreeWidget.findItem(item)
787
            self.resultPropertyTableWidget.show_item_property(item)
788
            if type(item) is QEngineeringErrorItem:
789
                for index in range(self.tableWidgetInconsistency.rowCount()):
790
                    if self.tableWidgetInconsistency.item(index, 1).tag is item:
791
                        self.tableWidgetInconsistency.selectRow(index)
792
                        break
793
        else:
794
            self.resultPropertyTableWidget.show_item_property(None)
795
        
796
    '''
797
        @brief      Initialize scene and itemTreeWidget
798
        @author     Jeongwoo
799
        @date       2018.06.14
800
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
801
    '''
802
    def onInitializeScene(self, action):
803
        if not self.graphicsView.hasImage():
804
            self.actionEquipment.setChecked(False)
805
            self.showImageSelectionMessageBox()
806

    
807
            return
808

    
809
        try:
810
            msg = QMessageBox()
811
            msg.setIcon(QMessageBox.Critical)
812
            msg.setText(self.tr('Do you want to remove all items?\nThis work cannot be recovered.'))
813
            msg.setWindowTitle(self.tr("Initialize"))
814
            msg.setStandardButtons(QMessageBox.Ok|QMessageBox.Cancel)
815
            if QMessageBox.Ok == msg.exec_():
816

    
817
                appDocData = AppDocData.instance()
818
                appDocData.clearItemList(True)
819
            
820
                items = self.graphicsView.scene.items()
821
                for item in items:
822
                    if type(item) is not QGraphicsPixmapItem and item.scene() is not None:
823
                        #if hasattr(item, 'tranfer'):
824
                        #    item.tranfer.onRemoved.emit(item)
825
                        #else:
826
                        #    self.graphicsView.scene.removeItem(item)
827
                        self.graphicsView.scene.removeItem(item)
828

    
829
                        '''
830
                        if type(item) is QEngineeringLineNoTextItem:
831
                            self.removedItems['LINE'].append(str(item.uid))
832
                        elif type(item) is QEngineeringInstrumentItem:
833
                            self.removedItems['INST'].append(str(item.uid))
834
                        elif type(item) is QEngineeringEquipmentItem:
835
                            self.removedItems['EQUIP'].append(str(item.uid))
836
                        elif type(item) is QEngineeringNoteItem:
837
                            self.removedItems['NOTE'].append(str(item.uid))
838
                        '''
839
                    
840
                if self.path is not None:
841
                    baseName = os.path.basename(self.path)
842
                    self.itemTreeWidget.setCurrentPID(baseName)
843

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

    
848
    '''
849
        @brief      Manage Checkable Action statement
850
        @author     Jeongwoo
851
        @date       2018.05.10
852
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
853
    '''
854
    def actionGroupTriggered(self, action):
855
        if hasattr(self.actionLine, 'tag'):
856
            self.actionLine.tag.onRejected.emit(None)
857

    
858
        if hasattr(self.actionVendor, 'tag'):
859
            self.actionVendor.tag.onRejected.emit(None)
860

    
861
        if self.graphicsView.command is not None:
862
            self.graphicsView.useDefaultCommand()
863

    
864
        for _action in self.actionGroup.actions():
865
            _action.setChecked(False)
866

    
867
        action.setChecked(True)
868

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

    
885

    
886
    '''
887
        @brief      Create Nozzle
888
        @author     Jeongwoo
889
        @date       2018.05.03
890
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
891
    '''
892
    def createNozzle(self):
893
        if not self.graphicsView.hasImage():
894
            self.actionNozzle.setChecked(False)
895
            self.showImageSelectionMessageBox()
896
            return
897
        if self.actionNozzle.isChecked():
898
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget, self.dirTreeWidget)
899
        else:
900
            self.graphicsView.useDefaultCommand()
901

    
902
    '''
903
        @brief      Area OCR
904
        @author     Jeongwoo
905
        @date       18.04.18
906
        @history    2018.05.02  Jeongwoo    Change graphicsView.command by actionOCR checked state
907
                                            Show MessageBox when imageviewer doesn't have image
908
    '''
909
    def onAreaOcr(self):
910
        if not self.graphicsView.hasImage():
911
            self.actionOCR.setChecked(False)
912
            self.showImageSelectionMessageBox()
913
            return
914

    
915
        if self.actionOCR.isChecked():
916
            cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView)
917
            cmd.onSuccess.connect(self.onRecognizeText)
918
            cmd.onRejected.connect(self.onCommandRejected)
919
            self.graphicsView.command = cmd
920
        else:
921
            self.graphicsView.useDefaultCommand()
922
    
923
    '''
924
        @brief      show text recognition dialog
925
        @author     humkyung
926
        @date       2018.08.08
927
    '''
928
    def onRecognizeText(self, x, y, width, height):
929
        from OcrResultDialog import QOcrResultDialog
930

    
931
        try:
932
            image = self.graphicsView.image().copy(x, y, width, height)
933
            dialog = QOcrResultDialog(self.graphicsView, image, QRectF(x, y, width, height))
934
            (isAccept, textInfoList) = dialog.showDialog()
935
            if isAccept:
936
                if textInfoList is not None and len(textInfoList) > 0:
937
                    docData = AppDocData.instance()
938
                    for textInfo in textInfoList:
939
                        x = textInfo.getX()
940
                        y = textInfo.getY()
941
                        angle = textInfo.getAngle()
942
                        text = textInfo.getText()
943
                        width = textInfo.getW()
944
                        height = textInfo.getH()
945
                        item = TextItemFactory.instance().createTextItem(textInfo)
946
                        if item is not None:
947
                            item.loc = (x, y)
948
                            item.size = (width, height)
949
                            item.angle = angle
950
                            item.setDefaultTextColor(Qt.blue)
951
                            item.addTextItemToScene(self.graphicsView.scene)
952
                            item.transfer.onRemoved.connect(self.itemRemoved)
953
                        else:
954
                            message = 'error occured({}) in {}:{}'.format('텍스트 생성에 실패했습니다.', sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
955
                            self.addMessage.emit(MessageType.Normal, message)
956
                else:
957
                    QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("Fail to recognize text"))
958
        except Exception as ex:
959
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
960
            self.addMessage.emit(MessageType.Error, message)
961

    
962
    '''
963
        @brief  area configuration
964
    '''
965
    def areaConfiguration(self):
966
        from ConfigurationAreaDialog import QConfigurationAreaDialog
967
        if not self.graphicsView.hasImage():
968
            self.showImageSelectionMessageBox()
969
            return
970
        self.onCommandRejected()
971
        self.dlgConfigurationArea = QConfigurationAreaDialog(self)
972
        self.dlgConfigurationArea.show()
973
        self.dlgConfigurationArea.exec_()
974

    
975
    '''
976
        @brief  configuration
977
    '''
978
    def configuration(self):
979
        from ConfigurationDialog import QConfigurationDialog
980

    
981
        self.dlgConfiguration = QConfigurationDialog(self)
982
        #self.dlgConfiguration.show()
983
        if QDialog.Accepted == self.dlgConfiguration.exec_():
984
            QEngineeringLineItem.LINE_TYPE_COLORS.clear()
985
            QEngineeringInstrumentItem.INST_COLOR = None
986

    
987
    '''
988
        @brief  show nominal diameter dialog 
989
        @author humkyung
990
        @date   2018.06.28
991
    '''
992
    def onShowCodeTable(self):
993
        from CodeTableDialog import QCodeTableDialog
994

    
995
        dlg = QCodeTableDialog(self)
996
        dlg.exec_()
997

    
998
    '''
999
        @brief  show HMB data
1000
        @author humkyung
1001
        @date   2018.07.11
1002
    '''
1003
    def onHMBData(self):
1004
        from HMBDialog import QHMBDialog
1005

    
1006
        dlg = QHMBDialog(self)
1007
        dlg.show()
1008
        dlg.exec_()
1009

    
1010
    '''
1011
        @brief  show line data list 
1012
        @author humkyung
1013
        @date   2018.05.03
1014
    '''
1015
    def showItemDataList(self):
1016
        from ItemDataExportDialog import QItemDataExportDialog
1017

    
1018
        self.dlgLineDataList = QItemDataExportDialog(self)
1019
        self.dlgLineDataList.exec_()
1020

    
1021
    def showTextDataList(self):
1022
        '''
1023
            @brief      show all text item in scene
1024
            @author     euisung
1025
            @date       2019.04.18
1026
        '''
1027
        try:
1028
            if not self.graphicsView.hasImage():
1029
                self.showImageSelectionMessageBox()
1030
                return
1031

    
1032
            self.onCommandRejected()
1033
            dialog = QTextDataListDialog(self)
1034
            dialog.show()
1035
            dialog.exec_()
1036
        except Exception as ex:
1037
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1038
            self.addMessage.emit(MessageType.Error, message)
1039

    
1040
    '''
1041
        @brief  Show Image Selection Guide MessageBox
1042
        @author Jeongwoo
1043
        @date   2018.05.02
1044
    '''
1045
    def showImageSelectionMessageBox(self):
1046
        QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("First select image drawing"))
1047
        
1048
    '''
1049
        @brief  change selected lines' type by selected line type
1050
        @author humkyung
1051
        @date   2018.06.27
1052
    '''
1053
    def onLineTypeChanged(self, param):
1054
        lineType = self.lineComboBox.itemText(param)
1055
        selected = [item for item in self.graphicsView.scene.selectedItems() if type(item) is QEngineeringLineItem]
1056
        if selected:
1057
            for item in selected:
1058
                item.lineType = lineType
1059

    
1060
    def display_colors(self, value):
1061
        """ display colors """
1062
        from DisplayColors import DisplayColors
1063
        from DisplayColors import DisplayOptions
1064

    
1065
        DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value == True else DisplayOptions.DisplayByLineType
1066
        if hasattr(self, 'graphicsView'):
1067
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1068
            DisplayColors.instance().save_data()
1069

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

    
1085
        try:
1086
            appDocData = AppDocData.instance()
1087
            project = appDocData.getCurrentProject()
1088
            
1089
            #for item in self.graphicsView.scene.items():
1090
            #    self.graphicsView.scene.removeItem(item)
1091

    
1092
            self.path = self.graphicsView.loadImageFromFile(project.getDrawingFilePath(), path if type(path) is str else '')
1093
            if os.path.isfile(self.path):
1094
                appDocData.clear()
1095
                self.onCommandRejected()
1096

    
1097
                appDocData.setImgFilePath(self.path)
1098
                appDocData.activeDrawing = Drawing(appDocData.imgName)
1099
                appDocData.setCurrentPidSource(Image.open(self.path))
1100
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
1101

    
1102
                drawingList = self.treeWidgetDrawingList.topLevelItem(0)
1103
                for childIdex in range(drawingList.childCount()):
1104
                    drawingList.child(childIdex).setCheckState(0, Qt.Unchecked)
1105
                for childIdex in range(drawingList.childCount()):
1106
                    child = drawingList.child(childIdex)
1107
                    if child.text(0).replace('.png', '') == appDocData.activeDrawing.name:
1108
                        child.setCheckState(0, Qt.Checked)
1109
                        break
1110

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

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

    
1138
        return self.path
1139

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

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

    
1169
    '''
1170
        @brief  visible/invisible image drawing
1171
        @author humkyung
1172
        @date   2018.06.25
1173
    '''
1174
    def onViewImageDrawing(self, isChecked):
1175
        for item in self.graphicsView.scene.items():
1176
            if type(item) is QGraphicsPixmapItem:
1177
                item.setVisible(isChecked)
1178
                break
1179

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

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

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

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

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

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

    
1240

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

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

    
1279
                        svg.transfer.onRemoved.connect(self.itemTreeWidget.itemRemoved)
1280
                        svg.addSvgItemToScene(self.graphicsView.scene)
1281
                        for connector in svg.connectors:
1282
                            self.graphicsView.scene.addItem(connector)
1283
        finally:
1284
            self.onCommandRejected()
1285
            QApplication.restoreOverrideCursor()
1286
    
1287
    '''
1288
        @brief      create a line
1289
        @author     humkyung
1290
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
1291
    '''
1292
    def onPlaceLine(self):        
1293
        if not self.graphicsView.hasImage():
1294
            self.actionLine.setChecked(False)
1295
            self.showImageSelectionMessageBox()
1296
            return
1297

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

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

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

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

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

    
1338
                pt = items[-1].endPoint()
1339
                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]]
1340
                if selected:
1341
                    items[-1].connect_if_possible(selected[0].parent, 5)
1342

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

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

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

    
1470
        appDocData = AppDocData.instance()
1471
        project = appDocData.getCurrentProject()
1472
        appDocData.needReOpening = None
1473
        currentPid = None
1474
        
1475
        if self.graphicsView.hasImage():
1476
            currentPid = appDocData.activeDrawing.name
1477

    
1478
        drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1479
        drawingCount = drawingTop.childCount()
1480
        checkedTreeItems = []
1481
        checkedDrawingPath = []
1482
        for drawing in range(drawingCount):
1483
            drawingChild = drawingTop.child(drawing)
1484
            if drawingChild.checkState(0) == 2:
1485
                checkedTreeItems.append(drawingChild)
1486
                checkedDrawingPath.append(os.path.join(project.getDrawingFilePath(), drawingChild.data(0, 0)))
1487
                if currentPid is not None and drawingChild.data(0, 0).find(currentPid) is 0:
1488
                    appDocData.needReOpening = False # later check need reopening at drawUnknownItems()
1489
                    currentPid = drawingChild.data(0, 0)
1490

    
1491
        if len(checkedDrawingPath) == 0:
1492
            self.showImageSelectionMessageBox()
1493
            return
1494

    
1495
        try:
1496
            self.onClearLog()
1497
            self.dlg = QRecognitionDialog(self, checkedDrawingPath, True)
1498
            self.dlg.exec_()
1499
            if self.dlg.isAccepted == True:
1500
                pass
1501

    
1502
            if appDocData.needReOpening == True:
1503
                drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), currentPid)
1504
                self.onOpenImageDrawing(drawing)
1505

    
1506
            # save working date-time
1507
            drawings = appDocData.getDrawings()
1508
            checkedDrawings = []
1509
            for checkedTreeItem in checkedTreeItems:
1510
                for drawing in drawings:
1511
                    if checkedTreeItem.data(0, 0) == drawing[1]:
1512
                        if drawing[0]:
1513
                            drawing[2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1514
                            checkedDrawings.append(drawing)
1515
                            checkedTreeItem.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1516
            appDocData.saveDrawings(checkedDrawings)
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      recognize symbol and text
1525
        @author     humkyung
1526
        @date       2018.04.??
1527
        @history    2018.04.16  humkyung    execute line no tracing
1528
                    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
1529
                    2018.05.25  Jeongwoo    Add parameter on QRecognitionDialog.__init__() and Move thread to QRecognitionDialog
1530
                                            Remove codes below if self.dlg.isAccepted == True
1531
                    2018.05.29  Jeongwoo    Remove connects and comments
1532
                    humkyung 2018.11.05 save working date-time
1533
    '''
1534
    def recognize(self, MainWindow):
1535
        from datetime import datetime
1536
        from RecognitionDialog import QRecognitionDialog
1537

    
1538
        if not self.graphicsView.hasImage():
1539
            self.showImageSelectionMessageBox()
1540
            return
1541

    
1542
        try:
1543
            '''
1544
            self.removedItems['LINE'] = []
1545
            self.removedItems['EQUIP'] = []
1546
            self.removedItems['INST'] = []
1547
            self.removedItems['NOTE'] = []
1548
            '''
1549

    
1550
            appDocData = AppDocData.instance()
1551

    
1552
            self.onClearLog()
1553
            appDocData.needReOpening = False
1554
            drawingList = []
1555
            drawingList.append(self.path)
1556
            self.dlg = QRecognitionDialog(self, drawingList, False)
1557
            self.dlg.exec_()
1558

    
1559
            if appDocData.needReOpening == True:
1560
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
1561
                self.drawDetectedItemsToScene()
1562
                
1563
                # save working date-time
1564
                drawings = appDocData.getDrawings()
1565
                drawing = [drawing for drawing in drawings if appDocData.imgName == os.path.splitext(drawing[1])[0]]
1566
                if drawing[0]:
1567
                    drawing[0][2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1568
                    appDocData.saveDrawings(drawing)
1569

    
1570
                currentPid = appDocData.activeDrawing.name
1571

    
1572
                drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1573
                drawingCount = drawingTop.childCount()
1574
                
1575
                for drawing in range(drawingCount):
1576
                    drawingChild = drawingTop.child(drawing)
1577
                    if drawingChild.data(0, 0).find(currentPid) is 0:
1578
                        drawingChild.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1579
                self.changeViewCheckedState(True)
1580
                # up to here
1581
        except Exception as ex:
1582
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1583
            self.addMessage.emit(MessageType.Error, message)
1584

    
1585
    '''
1586
        @brief      remove item from tree widget and then remove from scene
1587
        @date       2018.05.25
1588
        @author     Jeongwoo
1589
    '''
1590
    def itemRemoved(self, item):
1591
        try:
1592
            self.itemTreeWidget.itemRemoved(item)
1593

    
1594
            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]]
1595
            for match in matches:
1596
                for connector in match.connectors:
1597
                    if connector.connectedItem is item: connector.connectedItem = None
1598

    
1599
            #matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'remove_assoc_item')]
1600
            #for _item in matches:
1601
            #    _item.remove_assoc_item(item)
1602

    
1603
            matches = [_item for _item in self.graphicsView.scene.items() if type(_item) is QEngineeringLineNoTextItem]
1604
            for match in matches:
1605
                if item is match.prop('From'):
1606
                    match.set_property('From', None)
1607
                elif item is match.prop('To'):
1608
                    match.set_property('To', None)
1609

    
1610
                for run in match.runs:
1611
                    if item in run.items:
1612
                        index = run.items.index(item)
1613
                        run.items.pop(index)
1614

    
1615
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'owner')]
1616
            for match in matches:
1617
                if match.owner is item:
1618
                    match.owner = None
1619

    
1620
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'attrs')]
1621
            done = False
1622
            for match in matches:
1623
                for assoc in match.associations():
1624
                    if item is assoc:
1625
                        for attr in match.attrs.keys():
1626
                            if str(item.uid) == str(attr.AssocItem.uid):
1627
                                attr.AssocItem = None
1628
                                match.attrs[attr] = ''
1629
                                done = True
1630
                                break
1631
                        match.remove_assoc_item(item)
1632
                        break
1633
                if done: break
1634

    
1635
            #if type(item) is QEngineeringFlowMarkItem and item.parentItem():
1636
            #    if item in item.parentItem()._flowMark:
1637
            #        item.parentItem()._flowMark.pop(item.parentItem()._flowMark.index(item))
1638

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

    
1644
    '''
1645
        @brief      recognize line
1646
        @author     humkyung
1647
        @date       2018.04.19
1648
        @history    Jeongwoo 2018.04.26 Variable name changed (texts → lineNos)
1649
                                        TextItem type changed (QEngineeringTextItem → QEngineeringLineNoTextItem)
1650
                    humkyung 2018.04.26 remove small objects before recognizing line
1651
                    Jeongwoo 2018.05.02 Show MessageBox when imageviewer doesn't have image
1652
                    Jeongwoo 2018.05.25 Move codes about LineDetector
1653
                    humkyung 2018.06.17 show progress dialog
1654
    '''
1655
    def connect_attributes(self, MainWindow):
1656
        from LineNoTracer import LineNoTracer
1657
        from ConnectAttrDialog import QConnectAttrDialog
1658

    
1659
        if not self.graphicsView.hasImage():
1660
            self.showImageSelectionMessageBox()
1661
            return
1662

    
1663
        try:
1664
            self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView)
1665
            if QDialog.Accepted == self.dlgConnectAttr.exec_():
1666
                self.itemTreeWidget.InitLineNoItems()
1667

    
1668
                # construct line no item
1669
                line_nos = AppDocData.instance().tracerLineNos
1670
                for line_no in line_nos:
1671
                    item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
1672
                    connectedItems = line_no.getConnectedItems()
1673
                    for connectedItem in connectedItems:
1674
                        if issubclass(type(connectedItem), SymbolSvgItem): 
1675
                            self.itemTreeWidget.addTreeItem(item, connectedItem)
1676
                # up to here
1677

    
1678
                self.graphicsView.invalidateScene()
1679
        except Exception as ex:
1680
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1681
            self.addMessage.emit(MessageType.Error, message)
1682

    
1683
    '''
1684
        @history    2018.05.25  Jeongwoo    Moved from MainWindow
1685
                                            SvgItem and TextItem Connect with method in this class
1686
                                            Change method to add GraphicsItem
1687
                    2018.05.28  Jeongwoo    Make QGraphicsItem by symbol, text object. Not xml
1688
                    2018.05.29  Jeongwoo    Change method name and Moved from QRecognitionDialog
1689
                    2018.05.30  Jeongwoo    Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol)
1690
                                            Change Method name and seperate each item
1691
                    humkyung 2018.06.11     display difference between original and recognized image
1692
                    Jeongwoo 2018.06.18     Update Scene after all item added
1693
                    2018.11.05  euisung     add save note item because of dependency
1694
                    2018.11.05  euisung     add db delete process before save
1695
                    2018.11.12  euisung     add title block properties
1696
                    2018.11.12  euisung     db part move new method to dbUpdate
1697
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1698
                    2018.11.29  euisung     change name drawDetectedItems() -> createDetectedItems
1699
    '''
1700
    def createDetectedItems(self, symbolList, textInfoList, otherTextInfoList, titleBlockTextInfoList):
1701
        try:
1702
            appDocData = AppDocData.instance()
1703

    
1704
            QApplication.processEvents()
1705
            self.createDetectedSymbolItem(symbolList)
1706
            QApplication.processEvents()
1707
            self.createDetectedTextItem(textInfoList)
1708
            QApplication.processEvents()
1709
            self.createDetectedOtherTextItem(otherTextInfoList)
1710
            QApplication.processEvents()
1711
            self.createDetectedTitleBlockTextItem(titleBlockTextInfoList)
1712

    
1713
            self.dbUpdate()
1714

    
1715
            # update scene
1716
            #self.graphicsView.scene.update(self.graphicsView.sceneRect())
1717
        except Exception as ex:
1718
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1719
            self.addMessage.emit(MessageType.Error, message)
1720

    
1721
    def drawDetectedItemsToScene(self):
1722
        '''
1723
            @brief  add detected items to scene
1724
            @author euisung
1725
            @date   2018.11.26
1726
        '''
1727
        appDocData = AppDocData.instance()
1728

    
1729
        try:
1730
            for symbol in appDocData.symbols:
1731
                if issubclass(type(symbol), SymbolSvgItem):
1732
                    self.addSvgItemToScene(symbol)
1733
                else:
1734
                    self.graphicsView.scene.addItem(symbol)
1735

    
1736
            for text in appDocData.texts:
1737
                self.addTextItemToScene(text)
1738

    
1739
            for lineNo in appDocData.tracerLineNos:
1740
                self.addTextItemToScene(lineNo)
1741

    
1742
            for line in appDocData.lines:
1743
                self.graphicsView.scene.addItem(line)
1744
                line.transfer.onRemoved.connect(self.itemRemoved)
1745
                for conn in line.connectors:
1746
                    conn.transfer.onPosChanged.connect(line.onConnectorPosChaned)
1747

    
1748
            for unknown in appDocData.unknowns + appDocData.lineIndicators:
1749
                self.graphicsView.scene.addItem(unknown)
1750
        finally:
1751
            # update scene
1752
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1753

    
1754
    def postDetectLineProcess(self):
1755
        '''
1756
            @brief  check allowables among undetected items
1757
            @author euisung
1758
            @date   2018.11.15
1759
            @history    2018.11.15  euisung    no more used, moved to TextItemFactoy isLineNo()
1760
        '''
1761
        from AppDocData import AppDocData
1762
        from TextItemFactory import TextItemFactory
1763

    
1764
        appDocData = AppDocData.instance()
1765

    
1766
        tableNames = ["Fluid Code", "Insulation Purpose", "PnID Number", "Piping Materials Class", "Unit Number"]
1767
        tableDatas = []
1768
        for tableName in tableNames:
1769
            tableNameFormat = tableName.replace(' ','').replace('&&', 'n')
1770
            tableDatas.append(appDocData.getCodeTable(tableNameFormat))
1771

    
1772
        items = self.graphicsView.scene.items()
1773
        for item in items:
1774
            if type(item) is not QEngineeringTextItem:
1775
                continue
1776
            text = item.text()
1777
            for tableData in tableDatas:
1778
                for data in tableData:
1779
                    if data[3] == '':
1780
                        continue
1781
                    else:
1782
                        allows = data[3].split(',')
1783
                        for allow in allows:
1784
                            text = text.replace(allow, data[1])
1785

    
1786
            lineItem = TextItemFactory.instance().createTextItem(text)
1787
            if type(lineItem) is QEngineeringLineNoTextItem:
1788
                lineItem.loc = item.loc
1789
                lineItem.size = item.size
1790
                lineItem.angle = item.angle
1791
                lineItem.area = item.area
1792
                #lineItem.addTextItemToScene(self.graphicsView.scene)
1793
                lineItem.transfer.onRemoved.connect(self.itemRemoved)
1794
                item.transfer.onRemoved.emit(item)
1795
                appDocData.lineNos.append(lineItem)
1796
                
1797
    def createDetectedTitleBlockTextItem(self, textInfoList):
1798
        '''
1799
            @brief  draw title block
1800
            @author euisung
1801
            @date   2018.11.12
1802
            @history    2018.11.26  euisung     remove scene dependency
1803
                        2018.11.29  euisung     change name drawDetectedTitleBlockTextItem() -> createDetectedTitleBlockTextItem
1804
        '''
1805
        from TextItemFactory import TextItemFactory
1806
        import math
1807

    
1808
        try:
1809
            appDocData = AppDocData.instance()
1810

    
1811
            # parse texts
1812
            for textInfo in textInfoList:
1813
                if len(textInfo[1]) is 0:
1814
                    continue
1815
                x = textInfo[1][0].getX()
1816
                y = textInfo[1][0].getY()
1817
                width = textInfo[1][0].getW()
1818
                height = textInfo[1][0].getH()
1819
                angle = round(math.radians(textInfo[1][0].getAngle()), 2)
1820
                text = textInfo[1][0].getText()
1821
                item = TextItemFactory.instance().createTextItem(textInfo)
1822

    
1823
                if item is not None:
1824
                    item.loc = (x, y)
1825
                    item.size = (width, height)
1826
                    item.angle = angle
1827
                    item.area = textInfo[0]
1828
                    #self.addTextItemToScene(item)
1829
                    #appDocData.texts.append(item)
1830
                    appDocData.allItems.append(item)
1831
        except Exception as ex:
1832
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1833
            self.addMessage.emit(MessageType.Error, message)
1834

    
1835
    '''
1836
        @brief      
1837
        @author     humkyung
1838
        @date       2018.08.23
1839
        @history    2018.11.26  euisung     remove scene dependency
1840
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1841
                    2018.11.    euisung     no more used
1842
                    2018.11.29  euisung     change name drawDetectedLines() -> createDetectedLines
1843
    '''
1844
    def createDetectedLines(self, lineList, worker):
1845
        appDocData = AppDocData.instance()
1846
        area = appDocData.getArea('Drawing')
1847

    
1848
        for pts in lineList:
1849
            processLine = QEngineeringLineItem(vertices=[(area.x + param[0], area.y + param[1]) for param in pts])
1850
            processLine.area = 'Drawing'
1851
            #self.graphicsView.scene.addItem(processLine)
1852
            appDocData.lines.append(processLine)
1853
            appDocData.allItems.append(processLine)
1854

    
1855
            #if processLine.length() > 100: # TODO: check critical length
1856
            #    processLine.addFlowArrow()
1857
        
1858
        # re-order process line's start,end according to flow mark
1859
        #worker.arrangeLinePosition(lines, symbols, listWidget)
1860
        # up to here
1861

    
1862
    '''
1863
        history     2018.06.09  humkyung    check length of original and connection point is 2 while parsing
1864
                    2018.11.26  euisung     remove scene dependency
1865
                    2018.11.29  euisung     change name drawDetectedSymbolItem() -> createDetectedSymbolItem
1866
    '''
1867
    def createDetectedSymbolItem(self, symbolList):
1868
        from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
1869
        from SymbolSvgItem import SymbolSvgItem
1870
        import math
1871

    
1872
        try:
1873
            appDocData = AppDocData.instance()
1874
            project = appDocData.getCurrentProject()
1875

    
1876
            searchedMap = []
1877
            for symbol in symbolList:
1878
                pt = [float(x) for x in symbol.getSp()]
1879
                size = [symbol.getWidth(), symbol.getHeight()]
1880
                name = symbol.getName()
1881
                angle = round(math.radians(symbol.getRotatedAngle()), 2)
1882
                _type = symbol.getType()
1883
                flip = symbol.getDetectFlip()
1884
                origin = [0,0]
1885
                if 2 == len(symbol.getOriginalPoint().split(',')):
1886
                    tokens = symbol.getOriginalPoint().split(',')
1887
                    origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
1888
                connPts = []
1889
                if symbol.getConnectionPoint() is not None and symbol.getConnectionPoint() != '':
1890
                    for param in symbol.getConnectionPoint().split('/'):
1891
                        tokens = param.split(',')
1892
                        connPts.append(('AUTO', pt[0] + float(tokens[0]), pt[1] + float(tokens[1]), '0') if len(tokens) == 2 else \
1893
                                       (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), '0') if len(tokens) == 3 else \
1894
                                       (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), tokens[3]) if len(tokens) == 4 else None)
1895

    
1896
                parentSymbol = symbol.getBaseSymbol()
1897
                childSymbol = symbol.getAdditionalSymbol()
1898
                hasInstrumentLabel = symbol.getHasInstrumentLabel()
1899

    
1900
                svgFilePath = os.path.join(project.getSvgFilePath(), _type, name + '.svg')
1901
                if os.path.isfile(svgFilePath):
1902
                    svg = SymbolSvgItem.createItem(_type, svgFilePath, owner=None, flip=flip)
1903
                    #print(pt)
1904
                    #print(origin)
1905
                    svg.buildItem(name, _type, angle, pt, size, origin, connPts, parentSymbol, childSymbol, hasInstrumentLabel)
1906
                    svg.reCalculationRotatedItem()
1907
                    svg.area = 'Drawing'
1908

    
1909
                    # set owner - 2018.07.20 added by humkyung                   
1910
                    matches = [searched for searched in searchedMap if searched[0] == symbol.owner]
1911
                    if len(matches) == 1:
1912
                        svg.owner = matches[0][1]
1913
                    searchedMap.append((symbol, svg))
1914
                    # up to here
1915

    
1916
                    svg.transfer.onRemoved.connect(self.itemRemoved)
1917
                    #self.addSvgItemToScene(svg)
1918
                    appDocData.symbols.append(svg)
1919
                    appDocData.allItems.append(svg)
1920
                else:
1921
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
1922
                    item.isSymbol = True
1923
                    item.angle = angle
1924
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
1925
                    #self.graphicsView.scene.addItem(item)
1926
                    #appDocData.symbols.append(item)
1927
                    appDocData.allItems.append(item)
1928
            # up to here
1929
        except Exception as ex:
1930
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1931
            self.addMessage.emit(MessageType.Error, message)
1932

    
1933
    '''
1934
        @history    2018.06.08  Jeongwoo    Add parameter on round method
1935
        @history    2018.11.02  euisung     Add save note text item
1936
        @history    2018.11.05  euisung     delete save note text item and move to drawDetectedItems()
1937
                    2018.11.26  euisung     remove scene dependency
1938
                    2018.11.29  euisung     change name drawDetectedTextItem() -> createDetectedTextItem
1939
    '''
1940
    def createDetectedTextItem(self, textInfoList):
1941
        from TextItemFactory import TextItemFactory
1942
        import math
1943

    
1944
        try:
1945
            appDocData = AppDocData.instance()
1946

    
1947
            # parse texts
1948
            for textInfo in textInfoList:
1949
                x = textInfo.getX()
1950
                y = textInfo.getY()
1951
                width = textInfo.getW()
1952
                height = textInfo.getH()
1953
                angle = round(math.radians(textInfo.getAngle()), 2)
1954
                text = textInfo.getText()
1955
                if not text: continue
1956

    
1957
                item = TextItemFactory.instance().createTextItem(textInfo)
1958
                if item is not None:
1959
                    item.loc = (x, y)
1960
                    item.size = (width, height)
1961
                    item.angle = angle
1962
                    item.area = 'Drawing'
1963
                    item.transfer.onRemoved.connect(self.itemRemoved)
1964
                    #self.addTextItemToScene(item)
1965
                    #appDocData.texts.append(item)
1966
                    appDocData.allItems.append(item)
1967
        except Exception as ex:
1968
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1969
            self.addMessage.emit(MessageType.Error, message)
1970

    
1971
    '''
1972
        @brief      draw detected texts except which in drawing area
1973
        @history    2018.11.29  euisung     change name drawDetectedOtherTextItem() -> createDetectedOtherTextItem
1974
    '''
1975
    def createDetectedOtherTextItem(self, otherTextInfoList):
1976
        from TextItemFactory import TextItemFactory
1977
        import math
1978

    
1979
        try:
1980
            appDocData = AppDocData.instance()
1981

    
1982
            # parse notes
1983
            for textInfoMap in otherTextInfoList:
1984
                if textInfoMap[0]=='Note':
1985
                    pass
1986

    
1987
                for textInfo in textInfoMap[1]:
1988
                    x = textInfo.getX()
1989
                    y = textInfo.getY()
1990
                    width = textInfo.getW()
1991
                    height = textInfo.getH()
1992
                    angle = round(math.radians(textInfo.getAngle()))
1993
                    text = textInfo.getText()
1994

    
1995
                    item = TextItemFactory.instance().createTextItem(textInfo)
1996

    
1997
                    item.loc = (x, y)
1998
                    item.size = (width, height)
1999
                    item.angle = angle
2000
                    item.area = textInfoMap[0]
2001
                    item.transfer.onRemoved.connect(self.itemRemoved)
2002
                    #appDocData.texts.append(item)
2003
                    appDocData.allItems.append(item)
2004
        except Exception as ex:
2005
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2006
            self.addMessage.emit(MessageType.Error, message)
2007

    
2008
    '''
2009
        @brief  draw unknown items 
2010
        @author humkyung
2011
        @date   2018.06.12
2012
        @history    2018.06.14  Jeongwoo    Change method to add unknown item
2013
                    2018.06.18  Jeongwoo    Add connect on unknown item
2014
                                            Add [transfer] for using pyqtSignal
2015
                    2018.11.26  euisung     remove scene dependency
2016
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
2017
                    2018.11.27  euisung     add save to xml
2018
                    2018.11.29  euisung     change name drawUnknownItems() -> createUnknownItems
2019
    '''
2020
    def createUnknownItems(self, path):
2021
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem 
2022
        from EngineeringLineItem import QEngineeringLineItem
2023
        from EngineeringUnknownItem import QEngineeringUnknownItem
2024
        from SaveWorkCommand import SaveWorkCommand
2025

    
2026
        try:
2027
            docData = AppDocData.instance()
2028
            project = docData.getCurrentProject()
2029
            windowSize = docData.getSlidingWindowSize()
2030

    
2031
            thickness = int(windowSize[1])
2032

    
2033
            if docData.needReOpening is not None:
2034
                docData.needReOpening = True
2035

    
2036
            diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(path))
2037
            if os.path.isfile(diffFilePath):
2038
                imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1]
2039

    
2040
                ## remove line
2041
                lines = docData.lines
2042
                for line in lines:
2043
                    line.drawToImage(imgDiff, 255, thickness) if line.thickness is None else line.drawToImage(imgDiff, 255, line.thickness)
2044
                cv2.imwrite(diffFilePath, imgDiff)
2045
                ## up to here
2046

    
2047
                imgNot = np.ones(imgDiff.shape, np.uint8)
2048
                cv2.bitwise_not(imgDiff, imgNot)
2049
                imgNot = cv2.dilate(imgNot, np.ones((8,8), np.uint8))
2050

    
2051
                image, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
2052

    
2053
                ##
2054
                idx = 0
2055
                ##
2056
                smallContours = []
2057
                minimumSize = docData.getConfigs('Filter', 'MinimumSize')
2058
                for contour in contours:
2059
                    [x, y, w, h] = cv2.boundingRect(contour)
2060

    
2061
                    # remove too small one
2062
                    if len(minimumSize) is 1:
2063
                        if (w * h < int(minimumSize[0].value) * int(minimumSize[0].value)):
2064
                            smallContours.append(contour)
2065
                            idx += 1
2066
                            continue
2067

    
2068
                    '''
2069
                    rect = QRectF(x, y, w, h)
2070
                    items = [item for item in diffItems if item.boundingRect().contains(rect)]
2071
                    if len(items) > 0: continue
2072
                    
2073
                    items = [item for item in diffItems if rect.contains(item.boundingRect())]
2074
                    for item in items:
2075
                        diffItems.remove(item)
2076
                    '''
2077

    
2078
                    # create unknown item
2079
                    epsilon = cv2.arcLength(contour, True)*0.001
2080
                    approx = cv2.approxPolyDP(contour, epsilon, True)
2081
                    approx = [pt[0] for pt in approx]
2082
                    resultStr, resultList = self.determineRemainObject(idx, contours, imgNot)
2083
                    if resultStr == 'LineIndicator':
2084
                        item = QEngineeringUnknownItem(approx, 'True', resultList[0], resultList[1])
2085
                        docData.lineIndicators.append(item)
2086
                    elif resultStr == 'MissingLine':
2087
                        pass
2088
                    elif resultStr == 'Unknown':
2089
                        item = QEngineeringUnknownItem(approx, 'False')
2090
                        docData.unknowns.append(item)
2091
                    item.area = 'Drawing'
2092
                    docData.allItems.append(item)
2093
                    item.transfer.onRemoved.connect(self.itemRemoved)
2094
                    idx += 1
2095
                    # up to here                    
2096

    
2097
                imgNotRemoveSmall = cv2.drawContours(imgNot, smallContours, -1, 0, -1)
2098
                notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(path))
2099
                cv2.imwrite(notFilePath, imgNotRemoveSmall)
2100
            else:
2101
                message = 'can\'t found {}'.format(diffFilePath)
2102
                self.addMessage.emit(MessageType.Normal, message)
2103

    
2104
            SaveWorkCommand.save_to_xml()
2105
        except Exception as ex:
2106
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2107
            self.addMessage.emit(MessageType.Error, message)
2108

    
2109
    def determineRemainObject(self, idx, contours, imgNot):
2110
        '''
2111
            @brief      determine remain objects -> line no indicator or unknown
2112
            @author     euisung
2113
            @date       2018.12.26
2114
            @history    2019.03.25  euisung    Change name isLineNoIndicator -> determineRemainObject
2115
        '''
2116
        import math
2117
        [x, y, w, h] = cv2.boundingRect(contours[idx])
2118
        
2119
        if (w < 250 and h < 250):
2120
            return ('Unknown', [])
2121
        
2122
        fLines = []
2123
        maxDifAngle = 3
2124
        mask = np.zeros_like(imgNot)
2125
        cv2.drawContours(mask, contours, idx, 123, -1) # Draw filled contour in mask
2126
        out = np.zeros_like(imgNot) # Extract out the object and place into output image
2127
        out[mask == 123] = imgNot[mask == 123]
2128

    
2129
        # Now crop
2130
        ##print(out)
2131
        (x, y) = np.where(mask == 123)
2132
        (topx, topy) = (np.min(x), np.min(y))
2133
        (bottomx, bottomy) = (np.max(x), np.max(y))
2134
        out = out[topx:bottomx+1, topy:bottomy+1]
2135
        h, w = out.shape[0], out.shape[1]
2136
        maxDifH, maxDifW = math.ceil(math.tan(4 * math.pi / 180) / 2 * w), math.ceil(math.tan(4 * math.pi / 180) / 2 * h)
2137

    
2138
        # detection lines
2139
        edged2 = cv2.Canny(out, 100, 200)
2140
        lines = cv2.HoughLinesP(image=edged2, rho=1, theta=np.pi/180, threshold=25, minLineLength=30, maxLineGap=25)
2141
        #lines = cv2.HoughLines(edged2, 1, np.pi/180, 60)
2142
        if lines is None:
2143
            return ('Unknown', [])
2144
        for line in lines:
2145
            #r, theta = line[0]
2146
            #a, b = np.cos(theta), np.sin(theta)
2147
            #x0, y0 = a * r, b * r
2148
            #x1, y1 = int(x0 + 1000 * (-b)), int(y0 + 1000 * a)
2149
            #x2, y2 = int(x0 - 1000 * (-b)), int(y0 - 1000 * a)
2150
            #cv2.line(out, (x1, y1), (x2, y2), (0, 255, 0), 3)
2151
            x1, y1, x2, y2 = line[0]
2152
            degree = math.atan2(y2 - y1, x2 - x1) * 180 / math.pi
2153
            fLine = [x1, y1, x2, y2, degree]
2154
            #print(fLine)
2155
            fLines.append(fLine)
2156
        
2157
        horLines = []
2158
        verLines = []
2159
        otherLines = []
2160
        isVH = None
2161
        for fLine in fLines:
2162
            degree = math.fabs(fLine[4])
2163
            if degree >= 90 - maxDifAngle:
2164
                verLines.append(fLine)
2165
            elif degree <= maxDifAngle:
2166
                horLines.append(fLine)
2167
            else:
2168
                otherLines.append(fLine)
2169

    
2170
        baseLines = []
2171
        baseDifV = 0
2172
        if len(horLines):
2173
            x, y = w / 2, 0
2174
            baseDifV = maxDifH
2175
            for horLine in horLines:
2176
                x1, y1, x2, y2 = horLine[0], horLine[1], horLine[2], horLine[3]
2177
                y = ((y2-y1)/(x2-x1))*x + y1 - ((y2-y1)/(x2-x1))*x1
2178
                horLine.append(y)
2179
            baseLines = horLines
2180
            isVH = 'H'
2181
        if len(verLines):
2182
            x, y = 0, h / 2
2183
            baseDifV = maxDifW
2184
            for verLine in verLines:
2185
                x1, y1, x2, y2 = verLine[0], verLine[1], verLine[2], verLine[3]
2186
                x = ((x2-x1)/(y2-y1))*y + x1 - ((x2-x1)/(y2-y1))*y1
2187
                verLine.append(x)
2188
            baseLines = verLines
2189
            isVH = 'V'
2190

    
2191
        for otherLine in otherLines:
2192
            x, y = w / 2, 0
2193
            x1, y1, x2, y2 = otherLine[0], otherLine[1], otherLine[2], otherLine[3]
2194
            y = ((y2-y1)/(x2-x1))*x + y1 - ((y2-y1)/(x2-x1))*x1
2195
            otherLine.append(y)
2196

    
2197
        # determine line no indicator 
2198
        if not ((len(horLines) > 0 and len(verLines) > 0) or len(otherLines) is 0 or (len(horLines) == 0 and len(verLines) == 0)):    
2199
            result, mergedOtherLine = self.isLineNoIndicator(w, h, maxDifAngle, baseDifV, baseLines, otherLines)
2200
            if result:
2201
                #print(fLines)
2202
                return ('LineIndicator', [isVH, mergedOtherLine])
2203

    
2204
        return ('Unknown', [])
2205

    
2206
    def isLineNoIndicator(self, w, h, maxDifAngle, baseDifV, baseLines, otherLines):
2207
        '''
2208
            @brief      determine line no indicator
2209
            @author     euisung
2210
            @date       2019.03.25
2211
        '''
2212
        import math
2213

    
2214
        if (w < 250 and h < 250):
2215
            return (False, None)
2216

    
2217
        isSameLine = True
2218
        i = 0
2219
        for baseLine in baseLines:
2220
            if not isSameLine: break
2221
            j = 0
2222
            for baseLinee in baseLines:
2223
                if i == j:
2224
                    j += 1
2225
                    continue
2226
                difV = math.fabs(baseLine[5] - baseLinee[5])
2227
                if difV > baseDifV:
2228
                   isSameLine = False
2229
                   break
2230
                j += 1
2231
            i += 1
2232
        if not isSameLine:
2233
            return (False, None)
2234

    
2235
        isSameLine = True
2236
        i = 0
2237
        maxY = 0
2238
        for otherLine in otherLines:
2239
            y = otherLine[5]
2240
            if math.fabs(y) > maxY:
2241
                maxY = math.fabs(y)
2242
            if not isSameLine: break
2243
            j = 0
2244
            for otherLinee in otherLines:
2245
                if i == j:
2246
                    j += 1
2247
                    continue
2248
                difV = math.fabs(otherLine[4] - otherLinee[4])
2249
                if difV > maxDifAngle:
2250
                   isSameLine = False
2251
                   break
2252
                j += 1
2253
            i += 1
2254
        if not isSameLine:
2255
            return (False, None)
2256
                
2257
        isSameLine = True
2258
        mergedOtherLine = [0, 0, 0, 0]
2259
        i = 0
2260
        maxDif = math.ceil(math.tan(4 * math.pi / 180) * maxY)
2261
        for otherLine in otherLines:
2262
            if not isSameLine: break
2263
            j = 0
2264
            for otherLinee in otherLines:
2265
                if i == j:
2266
                    j += 1
2267
                    continue
2268
                angle = math.fabs(otherLine[4] + otherLinee[4]) / 2
2269
                difV = math.fabs(otherLine[5] - otherLinee[5])
2270
                dist = math.sin((90 - angle) * math.pi / 180) * difV 
2271
                if dist > maxDif:
2272
                   isSameLine = False
2273
                   break
2274
                j += 1
2275
            i += 1
2276
            mergedOtherLine[0] += otherLine[0]
2277
            mergedOtherLine[1] += otherLine[1]
2278
            mergedOtherLine[2] += otherLine[2]
2279
            mergedOtherLine[3] += otherLine[3]
2280
        if not isSameLine:
2281
            (False, None)
2282
                        
2283
        # Show the output image
2284
        #print('line no indicator')
2285
        mergedOtherLine[0] = round(mergedOtherLine[0] / len(otherLines))
2286
        mergedOtherLine[1] = round(mergedOtherLine[1] / len(otherLines))
2287
        mergedOtherLine[2] = round(mergedOtherLine[2] / len(otherLines))
2288
        mergedOtherLine[3] = round(mergedOtherLine[3] / len(otherLines))
2289
        #cv2.line(out, (mergedOtherLine[0], mergedOtherLine[1]), (mergedOtherLine[2], mergedOtherLine[3]), (255, 255, 255), 3)
2290
        #cv2.imshow('Output', out)
2291
        #cv2.waitKey(0)
2292
        #cv2.destroyAllWindows()
2293
        return (True, mergedOtherLine)
2294

    
2295
    '''
2296
        @brief      load recognition result
2297
        @author     humkyung
2298
        @date       2018.04.??
2299
        @history    humkyung 2018.01.12 parse originalpoint and connectionpoint
2300
                    Jeongwoo 2018.04.17 add QGraphicItem with Rotated text
2301
                    Jeongwoo 2018.04.23 Change to Draw texts on QEngineeringTextItem
2302
                    humkyung 2018.04.23 connect item remove slot to result tree
2303
                    Jeongwoo 2018.04.25 Add if state with QEngineeringNoteItem
2304
                    Jeongwoo 2018.04.26 Change method to create TextItem object with TextItemFactory
2305
                    Jeongwoo 2018.05.03 Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
2306
                    Jeongwoo 2018.05.29 Change method name / Change method to add item / Add Line item
2307
                    Jeongwoo 2018.05.30 Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol) / Change method name / Change XML NODE NAMES
2308
                    Jeongwoo 2018.06.12 Add LineNoTextItem from LINE_NO
2309
                    Jeongwoo 2018.06.14 Add UnknownItem from UNKNOWN
2310
                    Jeongwoo 2018.06.18 Update Scene after all item added
2311
                                        Add connect on unknown item
2312
                                        Add [transfer] for using pyqtSignal
2313
                    kyouho  2018.07.12  Add line property logic
2314
                    humkyung 2018.08.22 show progress while loading xml file
2315
                    2018.11.22      euisung     fix note road
2316
    '''
2317
    def loadRecognitionResultFromXml(self, xmlPath):
2318
        docData = AppDocData.instance()
2319
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
2320
        from EngineeringRunItem import QEngineeringRunItem
2321
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2322

    
2323
        try:
2324
            #self.graphicsView.scene.blockSignals(True)
2325

    
2326
            symbols = []
2327
            lines = []
2328

    
2329
            xml = parse(xmlPath)
2330
            root = xml.getroot()
2331
            
2332
            maxValue = 0
2333
            maxValue = maxValue + len(list(root.iter('SYMBOL')))
2334
            maxValue = maxValue + len(list(root.iter('ATTRIBUTE')))
2335
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
2336
            maxValue = maxValue + len(list(root.iter('LINE')))
2337
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
2338
            maxValue = maxValue + len(list(root.iter('SIZETEXT')))
2339
            maxValue = maxValue + len(list(root.iter('TRIM_LINE_NO')))
2340
            self.progress.setMaximum(maxValue)
2341

    
2342
            """ parsing all symbols """
2343
            for symbol in root.find('SYMBOLS').iter('SYMBOL'):
2344
                item = SymbolSvgItem.fromXml(symbol)
2345
                if item is not None:
2346
                    item.transfer.onRemoved.connect(self.itemRemoved)
2347
                    symbols.append(item)
2348
                    docData.symbols.append(item)
2349
                    self.addSvgItemToScene(item)
2350
                else:
2351
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2352
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2353
                    angle = float(symbol.find('ANGLE').text)
2354
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2355
                    item.isSymbol = True
2356
                    item.angle = angle
2357
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2358
                    self.graphicsView.scene.addItem(item)
2359

    
2360
                self.progress.setValue(self.progress.value() + 1)
2361
                
2362
            QApplication.processEvents()
2363

    
2364
            # parse texts
2365
            for text in root.find('TEXTINFOS').iter('ATTRIBUTE'):
2366
                item = QEngineeringTextItem.fromXml(text)
2367
                if item is not None:
2368
                    uid = text.find('UID')
2369
                    attributeValue = text.find('ATTRIBUTEVALUE')
2370
                    name = text.find('NAME').text
2371
                    item.transfer.onRemoved.connect(self.itemRemoved)
2372
                    self.addTextItemToScene(item)
2373
                    #docData.texts.append(item)
2374

    
2375
                    if name == 'TEXT':
2376
                        if uid is not None and attributeValue is not None:
2377
                            item.uid = uid.text
2378
                            item.attribute = attributeValue.text
2379

    
2380
                self.progress.setValue(self.progress.value() + 1)
2381
                
2382
            QApplication.processEvents()
2383

    
2384
            # note
2385
            for text in root.find('NOTES').iter('ATTRIBUTE'):
2386
                item = QEngineeringTextItem.fromXml(text)
2387
                if item is not None:
2388
                    uid = text.find('UID')
2389
                    attributeValue = text.find('ATTRIBUTEVALUE')
2390
                    name = text.find('NAME').text
2391
                    item.transfer.onRemoved.connect(self.itemRemoved)
2392
                    self.addTextItemToScene(item)
2393

    
2394
                    if name == 'NOTE':
2395
                        if uid is not None:
2396
                            item.uid = uid.text
2397

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

    
2402
            for line in root.find('LINEINFOS').iter('LINE'):
2403
                item = QEngineeringLineItem.fromXml(line)
2404
                if item:
2405
                    item.transfer.onRemoved.connect(self.itemRemoved)
2406
                    self.graphicsView.scene.addItem(item)
2407
                    lines.append(item)
2408

    
2409
                self.progress.setValue(self.progress.value() + 1)
2410
                
2411
            QApplication.processEvents()
2412

    
2413
            for unknown in root.iter('UNKNOWN'):
2414
                item = QEngineeringUnknownItem.fromXml(unknown)
2415
                item.transfer.onRemoved.connect(self.itemRemoved)
2416
                if item is not None:
2417
                    item.transfer.onRemoved.connect(self.itemRemoved)
2418
                    self.graphicsView.scene.addItem(item)
2419

    
2420
                self.progress.setValue(self.progress.value() + 1)
2421
                
2422
            QApplication.processEvents()
2423

    
2424
            #""" add tree widget """
2425
            #for item in symbols:
2426
            #    docData.symbols.append(item)
2427
            #    self.addSvgItemToScene(item)
2428
            #    self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2429

    
2430
            for line_no_node in root.find('LINENOS').iter('LINE_NO'):
2431
                line_no = QEngineeringLineNoTextItem.fromXml(line_no_node)
2432
                if line_no is None: continue
2433

    
2434
                line_no.transfer.onRemoved.connect(self.itemRemoved)
2435
                self.addTextItemToScene(line_no)
2436
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2437

    
2438
                runs_node = line_no_node.findall('RUN')
2439
                if runs_node is None: continue
2440

    
2441
                for run_node in runs_node:
2442
                    line_run = QEngineeringRunItem()
2443
                    for child_node in run_node:
2444
                        uidElement = child_node.find('UID')
2445
                        if uidElement is not None:
2446
                            uid = uidElement.text
2447
                            run_item = self.graphicsView.findItemByUid(uid)
2448
                            if run_item is not None:
2449
                                run_item._owner = line_no
2450
                                line_run.items.append(run_item)
2451
                    line_run.owner = line_no
2452
                    line_no.runs.append(line_run)
2453

    
2454
                    for run_item in line_run.items:
2455
                        if issubclass(type(run_item), SymbolSvgItem): self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2456

    
2457
                #docData.tracerLineNos.append(line_no)
2458

    
2459
                self.progress.setValue(self.progress.value() + 1)
2460
            QApplication.processEvents()
2461

    
2462
            for trimLineNo in root.iter('TRIM_LINE_NO'):
2463
                line_no = QEngineeringTrimLineNoTextItem()
2464
                line_no.uid = uuid.UUID(trimLineNo.find('UID').text, version=4)
2465

    
2466
                run = trimLineNo.find('RUN')
2467
                if run is not None:
2468
                    line_run = QEngineeringRunItem()
2469
                    for child in run:
2470
                        uidElement = child.find('UID')
2471
                        if uidElement is not None:
2472
                            uid = uidElement.text
2473
                            run_item = self.graphicsView.findItemByUid(uid)
2474
                            if run_item is not None:
2475
                                run_item.owner = line_no
2476
                                line_run.items.append(run_item)
2477
                    line_no.runs.append(line_run)
2478
                    line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2479
                    
2480
                    for run_item in line_run.items:
2481
                        if issubclass(type(run_item), SymbolSvgItem): self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2482

    
2483
                    docData.tracerLineNos.append(line_no)
2484

    
2485
                self.progress.setValue(self.progress.value() + 1)
2486

    
2487
            if root.find('VENDORS') is not None:
2488
                for vendor in root.find('VENDORS').iter('VENDOR'):
2489
                    item = QEngineeringVendorItem.fromXml(vendor)
2490
                    item.transfer.onRemoved.connect(self.itemRemoved)
2491
                    self.graphicsView.scene.addItem(item)
2492

    
2493
            # connect flow item to line
2494
            for line in lines:
2495
                line.update_arrow()
2496
            #for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
2497
            #    for line in lines:
2498
            #        if flowMark.owner is line:
2499
            #            line._flowMark.append(flowMark)
2500
            #            flowMark.setParentItem(line)
2501
            # up to here
2502

    
2503
            """ update scene """
2504
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2505
            for item in self.graphicsView.scene.items():
2506
                item.setVisible(True)
2507
                
2508
                # binding items
2509
                if hasattr(item, 'owner'):
2510
                    item.owner
2511
                if hasattr(item, 'connectors'):
2512
                    for connector in item.connectors:
2513
                        connector.connectedItem
2514

    
2515
        except Exception as ex:
2516
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2517
            self.addMessage.emit(MessageType.Error, message)
2518
        finally:
2519
            pass
2520
            #self.graphicsView.scene.blockSignals(False)
2521

    
2522
    '''
2523
        @brief      Remove added item on same place and Add GraphicsItem
2524
        @author     Jeongwoo
2525
        @date       2018.05.25
2526
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2527
                    2018.06.18  Jeongwoo    Set Z-index
2528
    '''
2529
    def addSvgItemToScene(self, svgItem):
2530
        svgItem.addSvgItemToScene(self.graphicsView.scene)
2531
        
2532
    '''
2533
        @brief      Remove added item on same place and Add GraphicsItem
2534
        @author     Jeongwoo
2535
        @date       2018.05.25
2536
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2537
                    2018.06.05  Jeongwoo    Remove Size condition
2538
                    2018.06.18  Jeongwoo    Set Z-index
2539
    '''
2540
    def addTextItemToScene(self, textItem):
2541
        textItem.addTextItemToScene(self.graphicsView.scene)
2542
        
2543
    '''
2544
        @brief      Remove added item on same place and Add GraphicsItem
2545
        @author     Jeongwoo
2546
        @date       2018.05.29
2547
        @history    2018.06.18  Jeongwoo    Set Z-index
2548
    '''
2549
    def addLineItemToScene(self, lineItem):
2550
        self.graphicsView.scene.addItem(lineItem)
2551

    
2552
    '''
2553
        @brief      generate output xml file
2554
        @author     humkyung
2555
        @date       2018.04.23
2556
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
2557
    '''
2558
    def generateOutput(self):
2559
        import XmlGenerator as xg
2560

    
2561
        if not self.graphicsView.hasImage():
2562
            self.showImageSelectionMessageBox()
2563
            return
2564

    
2565
        try:
2566
            appDocData = AppDocData.instance()
2567

    
2568
            ## collect items
2569
            appDocData.lines.clear()
2570
            appDocData.lines = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem and item.owner is None]
2571

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

    
2575
            appDocData.equipments.clear()
2576
            for item in self.graphicsView.scene.items():
2577
                if type(item) is QEngineeringEquipmentItem:
2578
                    appDocData.equipments.append(item)
2579

    
2580
            appDocData.texts.clear()
2581
            appDocData.texts = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem) and type(item) is not QEngineeringLineNoTextItem]
2582
            ## up to here
2583

    
2584
            appDocData.imgOutput = np.ones((appDocData.imgHeight, appDocData.imgWidth), np.uint8)*255
2585
            xg.writeOutputXml(appDocData.imgName, appDocData.imgWidth, appDocData.imgHeight) # TODO: check
2586
            project = appDocData.getCurrentProject()
2587
            cv2.imwrite(os.path.join(project.getTempPath() , 'OUTPUT.png') , appDocData.imgOutput)
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      resetting attribute at secne
2594
        @author     kyoyho
2595
        @date       2018.08.21
2596
    '''
2597
    """
2598
    def checkAttribute(self):
2599
        try:
2600

2601
            docData = AppDocData.instance()
2602
            if not self.graphicsView.hasImage():
2603
                return
2604

2605
            # symbol 경우
2606
            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]
2607
            for item in items:
2608
                attrs = item.attrs
2609
                
2610
                removeAttrList = []
2611
                for attr in attrs:
2612
                    if type(attr) is tuple:
2613
                        continue
2614

2615
                    if attr is None:
2616
                        removeAttrList.append(attr)
2617
                        continue
2618

2619
                    attrInfo = docData.getSymbolAttributeByUID(attr.UID)
2620
                    if attrInfo is None:
2621
                        removeAttrList.append(attr)
2622
                    # 해당 attribute가 맞는지 확인
2623
                    else:
2624
                        attrType = attrInfo.AttributeType
2625
                        _type = type(attr)
2626
                        if attrType == 'Symbol Item':
2627
                            if not issubclass(_type, SymbolSvgItem):
2628
                                removeAttrList.append(attr)
2629
                        elif attrType == 'Text Item':
2630
                            if _type is not QEngineeringTextItem:
2631
                                removeAttrList.append(attr)
2632
                        elif attrType == 'Int':
2633
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
2634
                                removeAttrList.append(attr)
2635
                        elif attrType == 'String':
2636
                            if _type is not UserInputAttribute:
2637
                                removeAttrList.append(attr)
2638

2639
                for attr in removeAttrList:
2640
                    del attrs[attr]
2641

2642
            # Line No Text Item의 경우
2643
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringLineNoTextItem)]
2644
            for item in items:
2645
                attrs = item.attrs
2646
                
2647
                removeAttrList = []
2648
                for attr in attrs:
2649
                    if type(attr) is UserInputAttribute:
2650
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
2651
                        if attrInfo is None:
2652
                            removeAttrList.append(attr)
2653

2654
                for attr in removeAttrList:
2655
                    del attrs[attr]
2656

2657
        except Exception as ex:
2658
                message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2659
                self.addMessage.emit(MessageType.Error, message)
2660
    """
2661
    '''
2662
        @brief      Check Number
2663
        @author     kyouho
2664
        @date       2018.08.20
2665
    '''
2666
    def isNumber(self, num):
2667
        p = re.compile('(^[0-9]+$)')
2668
        result = p.match(num)
2669

    
2670
        if result:
2671
            return True
2672
        else:
2673
            return False
2674

    
2675
    '''
2676
        @brief      find overlap Connector
2677
        @author     kyouho
2678
        @date       2018.08.28
2679
    '''
2680
    def findOverlapConnector(self, connectorItem):
2681
        from shapely.geometry import Point
2682
        from EngineeringConnectorItem import QEngineeringConnectorItem
2683
        itemList = []
2684
        
2685
        x = connectorItem.center()[0]
2686
        y = connectorItem.center()[1]
2687

    
2688
        connectors = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringConnectorItem and item != connectorItem]
2689
        for connector in connectors:
2690
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
2691
                itemList.append(connector.parent)
2692

    
2693
        return itemList
2694

    
2695
if __name__ == '__main__':
2696
    import locale
2697
    from PyQt5.QtCore import QTranslator
2698
    from License import QLicenseDialog
2699
    from ProjectDialog import Ui_Dialog
2700
    from App import App 
2701

    
2702
    app = App(sys.argv)
2703
    try:
2704
        if True == QLicenseDialog.check_license_key():
2705
            dlg = Ui_Dialog()
2706
            selectedProject = dlg.showDialog()
2707
            if selectedProject is not None:
2708
                AppDocData.instance().setCurrentProject(selectedProject)
2709
                app._mainWnd = MainWindow.instance()
2710
                app._mainWnd.show()
2711
                sys.exit(app.exec_())
2712
    except Exception as ex:
2713
        print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
2714
    finally:
2715
        pass
클립보드 이미지 추가 (최대 크기: 500 MB)