프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / MainWindow.py @ 6a87bac1

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

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

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

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

    
21
import cv2
22
import numpy as np
23

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

    
29
from PIL import Image
30

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
262
        errors = []
263

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
366
            appDocData.saveDrawings(drawings)
367
        except Exception as ex:
368
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
369
            self.addMessage.emit(MessageType.Error, message)
370

    
371
    def open_selected_drawing(self, item, column):
372
        """
373
        @brief      open selected p&id drawing
374
        @author     humkyung
375
        @date       18.11.02
376
        """
377
        appDocData = AppDocData.instance()
378
        drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), item.text(column))
379
        self.onOpenImageDrawing(drawing)
380

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

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

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

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

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

    
430
        from TextItemEditDialog import QTextItemEditDialog
431

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

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

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

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

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

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

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

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

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

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

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

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

    
510
        appDocData.clearItemList(False)
511

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

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

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

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

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

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

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

    
572

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

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

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

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

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

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

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

    
626

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

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

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

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

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

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

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

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

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

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

    
726
            return
727

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

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

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

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

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

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

    
769
        action.setChecked(True)
770

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

    
787

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1009
        return self.path
1010

    
1011
    def changeViewCheckedState(self, checked):
1012
        '''
1013
            @brief      change view checked state
1014
            @author     euisung
1015
            @date       2019.03.06
1016
        '''
1017
        self.actionImage_Drawing.setChecked(checked)
1018
        self.actionViewText.setChecked(checked)
1019
        self.actionViewSymbol.setChecked(checked)
1020
        self.actionViewLine.setChecked(checked)
1021
        self.actionViewUnknown.setChecked(checked)
1022
        self.actionViewInconsistency.setChecked(checked)
1023
        self.tableWidgetInconsistency.clearContents()
1024
        self.tableWidgetInconsistency.setRowCount(0)
1025

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

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

    
1047
    '''
1048
        @brief  visible/invisible Symbol 
1049
        @author humkyung
1050
        @date   2018.06.28
1051
    '''
1052
    def onViewSymbol(self, isChecked):
1053
        selected = [item for item in self.graphicsView.scene.items() if (issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringErrorItem)]
1054
        for item in selected:
1055
            item.setVisible(isChecked)
1056

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

    
1067
    def onViewInconsistency(self, isChecked):
1068
        '''
1069
        @brief  visible/invisible Inconsistency
1070
        @author euisung
1071
        @date   2019.04.03
1072
        '''
1073
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringErrorItem]
1074
        for item in selected:
1075
            item.setVisible(isChecked)
1076

    
1077
    '''
1078
        @brief  visible/invisible Unknown 
1079
        @author humkyung
1080
        @date   2018.06.28
1081
    '''
1082
    def onViewUnknown(self, isChecked):
1083
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
1084
        for item in selected:
1085
            item.setVisible(isChecked)
1086

    
1087
    '''
1088
        @brief  create a symbol
1089
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
1090
                                            Add SymbolSvgItem
1091
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1092
                                            Change method to make svg and image path
1093
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
1094
    '''
1095
    def onCreateSymbolClicked(self):
1096
        cmd = FenceCommand.FenceCommand(self.graphicsView)
1097
        cmd.onSuccess.connect(self.onAreaSelected)
1098
        self.graphicsView.command = cmd
1099
        QApplication.setOverrideCursor(Qt.CrossCursor)
1100

    
1101
    '''
1102
        @brief      show SymbolEditorDialog with image selected by user
1103
        @author     humkyung
1104
        @date       2018.07.20
1105
    '''
1106
    def onAreaSelected(self, x, y, width, height):
1107
        try:
1108
            image = self.graphicsView.image()
1109
            if image is not None:
1110
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height), AppDocData.instance().getCurrentProject())
1111
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
1112
                self.dirTreeWidget.initDirTreeWidget()
1113
                if isAccepted:
1114
                    if isImmediateInsert:
1115
                        svgPath = newSym.getSvgFileFullPath()
1116
                        img = cv2.imread(newSym.getImageFileFullPath(), 1)
1117
                        w, h = (0, 0)
1118
                        if len(img.shape[::-1]) == 2:
1119
                            w, h = img.shape[::-1]
1120
                        else:
1121
                            _chan, w, h = img.shape[::-1]
1122
                        svg = SymbolSvgItem(svgPath)
1123
                        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)
1124

    
1125
                        svg.transfer.onRemoved.connect(self.itemTreeWidget.itemRemoved)
1126
                        svg.addSvgItemToScene(self.graphicsView.scene)
1127
                        for connector in svg.connectors:
1128
                            self.graphicsView.scene.addItem(connector)
1129
        finally:
1130
            self.graphicsView.useDefaultCommand()
1131
            QApplication.restoreOverrideCursor()
1132
    
1133
    '''
1134
        @brief      create a line
1135
        @author     humkyung
1136
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
1137
    '''
1138
    def onPlaceLine(self):        
1139
        if not self.graphicsView.hasImage():
1140
            self.actionLine.setChecked(False)
1141
            self.showImageSelectionMessageBox()
1142
            return
1143

    
1144
        self.actionLine.setChecked(True)
1145
        if not hasattr(self.actionLine, 'tag'):
1146
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
1147
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
1148
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
1149

    
1150
        self.graphicsView.command = self.actionLine.tag
1151

    
1152
    '''
1153
        @brief      add created lines to scene
1154
        @author     humkyung
1155
        @date       2018.07.23
1156
    '''
1157
    def onLineCreated(self):
1158
        from EngineeringConnectorItem import QEngineeringConnectorItem
1159

    
1160
        try:
1161
            count = len(self.actionLine.tag._polyline._vertices)
1162
            if count > 1:
1163
                items = []
1164

    
1165
                lineType = self.lineComboBox.currentText()
1166
                for index in range(count - 1):
1167
                    start = self.actionLine.tag._polyline._vertices[index]
1168
                    end  = self.actionLine.tag._polyline._vertices[index + 1]
1169
                    
1170
                    lineItem = QEngineeringLineItem(vertices=[start, end])
1171
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
1172
                    lineItem.lineType = lineType
1173
                    if items:
1174
                        lineItem.connectIfPossible(items[-1], 5)
1175
                    else:
1176
                        pt = lineItem.startPoint()
1177
                        selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
1178
                        if selected is not None and type(selected) is QEngineeringConnectorItem:
1179
                            lineItem.connectIfPossible(selected.parent, 5)
1180
                    
1181
                    items.append(lineItem)
1182
                    self.graphicsView.scene.addItem(lineItem)
1183

    
1184
                pt = items[-1].endPoint()
1185
                selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
1186
                if selected is not None and type(selected) is QEngineeringConnectorItem:
1187
                    items[-1].connectIfPossible(selected.parent, 5)
1188
        finally:
1189
            self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1190
            self.actionLine.tag.reset()
1191

    
1192
    '''
1193
        @brief      refresh scene
1194
        @author     humkyung
1195
        @date       2018.07.23
1196
    '''
1197
    def onCommandRejected(self, cmd):
1198
        try:
1199
            if type(cmd) is PlaceLineCommand.PlaceLineCommand:
1200
                self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1201
                self.graphicsView.scene.update()
1202
                self.actionLine.tag.reset()
1203

    
1204
                self.actionLine.setChecked(False)
1205
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
1206
                self.actionZoom.setChecked(False)
1207
            elif type(cmd) is AreaOcrCommand.AreaOcrCommand:
1208
                self.actionOCR.setChecked(False)
1209
        finally:
1210
            self.graphicsView.useDefaultCommand()
1211
     
1212
    '''
1213
        @brief      restore to default command when user press Escape key
1214
        @author     humkyung 
1215
        @date       2018.08.09
1216
    '''
1217
    def keyPressEvent(self, event):
1218
        try:
1219
            if event.key() == Qt.Key_Escape:
1220
                checked = self.actionGroup.checkedAction()
1221
                if checked:
1222
                    checked.setChecked(False)
1223
                    self.graphicsView.useDefaultCommand()
1224

    
1225
            QMainWindow.keyPressEvent(self, event)
1226
        except Exception as ex:
1227
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1228
            self.addMessage.emit(MessageType.Error, message)
1229
    
1230
    def recognizeBatch(self, MainWindow):
1231
        '''
1232
            @brief      batch recognize symbol, text and line
1233
            @author     euisung
1234
            @date       2018.11.23
1235
        
1236
        '''
1237
        from datetime import datetime
1238
        from RecognitionDialog import QRecognitionDialog
1239

    
1240
        appDocData = AppDocData.instance()
1241
        project = appDocData.getCurrentProject()
1242
        appDocData.needReOpening = None
1243
        currentPid = None
1244
        
1245
        if self.graphicsView.hasImage():
1246
            currentPid = appDocData.activeDrawing.name
1247

    
1248
        drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1249
        drawingCount = drawingTop.childCount()
1250
        checkedTreeItems = []
1251
        checkedDrawingPath = []
1252
        for drawing in range(drawingCount):
1253
            drawingChild = drawingTop.child(drawing)
1254
            if drawingChild.checkState(0) == 2:
1255
                checkedTreeItems.append(drawingChild)
1256
                checkedDrawingPath.append(os.path.join(project.getDrawingFilePath(), drawingChild.data(0, 0)))
1257
                if currentPid is not None and drawingChild.data(0, 0).find(currentPid) is 0:
1258
                    appDocData.needReOpening = False # later check need reopening at drawUnknownItems()
1259
                    currentPid = drawingChild.data(0, 0)
1260

    
1261
        if len(checkedDrawingPath) == 0:
1262
            self.showImageSelectionMessageBox()
1263
            return
1264

    
1265
        try:
1266
            self.onClearLog()
1267
            self.dlg = QRecognitionDialog(self, checkedDrawingPath, True)
1268
            self.dlg.exec_()
1269
            if self.dlg.isAccepted == True:
1270
                pass
1271

    
1272
            if appDocData.needReOpening == True:
1273
                drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), currentPid)
1274
                self.onOpenImageDrawing(drawing)
1275

    
1276
            # save working date-time
1277
            drawings = appDocData.getDrawings()
1278
            checkedDrawings = []
1279
            for checkedTreeItem in checkedTreeItems:
1280
                for drawing in drawings:
1281
                    if checkedTreeItem.data(0, 0) == drawing[1]:
1282
                        if drawing[0]:
1283
                            drawing[2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1284
                            checkedDrawings.append(drawing)
1285
                            checkedTreeItem.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1286
            appDocData.saveDrawings(checkedDrawings)
1287
            self.changeViewCheckedState(True)
1288
            # up to here
1289
        except Exception as ex:
1290
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1291
            self.addMessage.emit(MessageType.Error, message)
1292

    
1293
    '''
1294
        @brief      recognize symbol and text
1295
        @author     humkyung
1296
        @date       2018.04.??
1297
        @history    2018.04.16  humkyung    execute line no tracing
1298
                    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
1299
                    2018.05.25  Jeongwoo    Add parameter on QRecognitionDialog.__init__() and Move thread to QRecognitionDialog
1300
                                            Remove codes below if self.dlg.isAccepted == True
1301
                    2018.05.29  Jeongwoo    Remove connects and comments
1302
                    humkyung 2018.11.05 save working date-time
1303
    '''
1304
    def recognize(self, MainWindow):
1305
        from datetime import datetime
1306
        from RecognitionDialog import QRecognitionDialog
1307

    
1308
        if not self.graphicsView.hasImage():
1309
            self.showImageSelectionMessageBox()
1310
            return
1311

    
1312
        try:
1313
            self.removedItems['LINE'] = []
1314
            self.removedItems['EQUIP'] = []
1315
            self.removedItems['INST'] = []
1316
            self.removedItems['NOTE'] = []
1317

    
1318
            appDocData = AppDocData.instance()
1319

    
1320
            self.onClearLog()
1321
            appDocData.needReOpening = False
1322
            drawingList = []
1323
            drawingList.append(self.path)
1324
            self.dlg = QRecognitionDialog(self, drawingList, False)
1325
            self.dlg.exec_()
1326

    
1327
            if appDocData.needReOpening == True:
1328
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
1329
                self.drawDetectedItemsToScene()
1330
                
1331
                # save working date-time
1332
                drawings = appDocData.getDrawings()
1333
                drawing = [drawing for drawing in drawings if appDocData.imgName == os.path.splitext(drawing[1])[0]]
1334
                if drawing[0]:
1335
                    drawing[0][2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1336
                    appDocData.saveDrawings(drawing)
1337

    
1338
                currentPid = appDocData.activeDrawing.name
1339

    
1340
                drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1341
                drawingCount = drawingTop.childCount()
1342
                
1343
                for drawing in range(drawingCount):
1344
                    drawingChild = drawingTop.child(drawing)
1345
                    if drawingChild.data(0, 0).find(currentPid) is 0:
1346
                        drawingChild.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1347
                self.changeViewCheckedState(True)
1348
                # up to here
1349
        except Exception as ex:
1350
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1351
            self.addMessage.emit(MessageType.Error, message)
1352

    
1353
    '''
1354
        @brief      remove item from tree widget and then remove from scene
1355
        @date       2018.05.25
1356
        @author     Jeongwoo
1357
    '''
1358
    def itemRemoved(self, item):
1359
        try:
1360
            self.itemTreeWidget.itemRemoved(item)
1361

    
1362
            if type(item) is QEngineeringLineNoTextItem:
1363
                self.removedItems['LINE'].append(str(item.uid))
1364
            elif type(item) is QEngineeringInstrumentItem:
1365
                self.removedItems['INST'].append(str(item.uid))
1366
            elif type(item) is QEngineeringEquipmentItem:
1367
                self.removedItems['EQUIP'].append(str(item.uid))
1368
            elif type(item) is QEngineeringNoteItem:
1369
                self.removedItems['NOTE'].append(str(item.uid))
1370

    
1371
            if hasattr(item, 'connectors'):
1372
                for sceneItem in self.graphicsView.scene.items():
1373
                    if hasattr(sceneItem, 'connectors'):
1374
                        for sceneConnector in sceneItem.connectors:
1375
                            if sceneConnector.connectedItem is not None and item.uid == sceneConnector.connectedItem.uid:
1376
                                sceneConnector.connectedItem = None
1377

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

    
1383
    '''
1384
        @brief      recognize line
1385
        @author     humkyung
1386
        @date       2018.04.19
1387
        @history    Jeongwoo 2018.04.26 Variable name changed (texts → lineNos)
1388
                                        TextItem type changed (QEngineeringTextItem → QEngineeringLineNoTextItem)
1389
                    humkyung 2018.04.26 remove small objects before recognizing line
1390
                    Jeongwoo 2018.05.02 Show MessageBox when imageviewer doesn't have image
1391
                    Jeongwoo 2018.05.25 Move codes about LineDetector
1392
                    humkyung 2018.06.17 show progress dialog
1393
    '''
1394
    def recognizeLine(self, MainWindow):
1395
        from LineNoTracer import LineNoTracer
1396
        from ConnectAttrDialog import QConnectAttrDialog
1397

    
1398
        if not self.graphicsView.hasImage():
1399
            self.showImageSelectionMessageBox()
1400
            return
1401

    
1402
        try:
1403
            self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView)
1404
            self.dlgConnectAttr.exec_()
1405

    
1406
            self.itemTreeWidget.InitLineNoItems()
1407

    
1408
            # construct line no item
1409
            docData = AppDocData.instance()
1410
            for lineno in docData.tracerLineNos:
1411
                item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, lineno)
1412
                connectedItems = lineno.getConnectedItems()
1413
                for connectedItem in connectedItems:
1414
                    if issubclass(type(connectedItem), SymbolSvgItem): 
1415
                        self.itemTreeWidget.addTreeItem(item, connectedItem)
1416
            # up to here
1417
        except Exception as ex:
1418
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1419
            self.addMessage.emit(MessageType.Error, message)
1420

    
1421
    '''
1422
        @history    2018.05.25  Jeongwoo    Moved from MainWindow
1423
                                            SvgItem and TextItem Connect with method in this class
1424
                                            Change method to add GraphicsItem
1425
                    2018.05.28  Jeongwoo    Make QGraphicsItem by symbol, text object. Not xml
1426
                    2018.05.29  Jeongwoo    Change method name and Moved from QRecognitionDialog
1427
                    2018.05.30  Jeongwoo    Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol)
1428
                                            Change Method name and seperate each item
1429
                    humkyung 2018.06.11     display difference between original and recognized image
1430
                    Jeongwoo 2018.06.18     Update Scene after all item added
1431
                    2018.11.05  euisung     add save note item because of dependency
1432
                    2018.11.05  euisung     add db delete process before save
1433
                    2018.11.12  euisung     add title block properties
1434
                    2018.11.12  euisung     db part move new method to dbUpdate
1435
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1436
                    2018.11.29  euisung     change name drawDetectedItems() -> createDetectedItems
1437
    '''
1438
    def createDetectedItems(self, symbolList, textInfoList, otherTextInfoList, titleBlockTextInfoList):
1439
        try:
1440
            appDocData = AppDocData.instance()
1441

    
1442
            QApplication.processEvents()
1443
            self.createDetectedSymbolItem(symbolList)
1444
            QApplication.processEvents()
1445
            self.createDetectedTextItem(textInfoList)
1446
            QApplication.processEvents()
1447
            self.createDetectedOtherTextItem(otherTextInfoList)
1448
            QApplication.processEvents()
1449
            self.createDetectedTitleBlockTextItem(titleBlockTextInfoList)
1450

    
1451
            self.dbUpdate()
1452
            #self.saveToXml(False)
1453

    
1454
            # update scene
1455
            #self.graphicsView.scene.update(self.graphicsView.sceneRect())
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 drawDetectedItemsToScene(self):
1461
        '''
1462
            @brief  add detected items to scene
1463
            @author euisung
1464
            @date   2018.11.26
1465
        '''
1466
        appDocData = AppDocData.instance()
1467

    
1468
        try:
1469
            for symbol in appDocData.symbols:
1470
                if issubclass(type(symbol), SymbolSvgItem):
1471
                    self.addSvgItemToScene(symbol)
1472
                else:
1473
                    self.graphicsView.scene.addItem(symbol)
1474

    
1475
            for text in appDocData.texts:
1476
                self.addTextItemToScene(text)
1477

    
1478
            for line in appDocData.lines:
1479
                self.graphicsView.scene.addItem(line)
1480
                line.transfer.onRemoved.connect(self.itemRemoved)
1481
                for conn in line.connectors:
1482
                    conn.transfer.onPosChanged.connect(line.onConnectorPosChaned)
1483

    
1484
            for unknown in appDocData.unknowns + appDocData.lineIndicators:
1485
                self.addUnknownItemToScene(unknown)
1486
        finally:
1487
            # update scene
1488
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1489

    
1490
    def postDetectLineProcess(self):
1491
        '''
1492
            @brief  check allowables among undetected items
1493
            @author euisung
1494
            @date   2018.11.15
1495
            @history    2018.11.15  euisung    no more used, moved to TextItemFactoy isLineNo()
1496
        '''
1497
        from AppDocData import AppDocData
1498
        from TextItemFactory import TextItemFactory
1499

    
1500
        appDocData = AppDocData.instance()
1501

    
1502
        tableNames = ["Fluid Code", "Insulation Purpose", "PnID Number", "Piping Materials Class", "Unit Number"]
1503
        tableDatas = []
1504
        for tableName in tableNames:
1505
            tableNameFormat = tableName.replace(' ','').replace('&&', 'n')
1506
            tableDatas.append(appDocData.getCodeTable(tableNameFormat))
1507

    
1508
        items = self.graphicsView.scene.items()
1509
        for item in items:
1510
            if type(item) is not QEngineeringTextItem:
1511
                continue
1512
            text = item.text()
1513
            for tableData in tableDatas:
1514
                for data in tableData:
1515
                    if data[3] == '':
1516
                        continue
1517
                    else:
1518
                        allows = data[3].split(',')
1519
                        for allow in allows:
1520
                            text = text.replace(allow, data[1])
1521

    
1522
            lineItem = TextItemFactory.instance().createTextItem(text)
1523
            if type(lineItem) is QEngineeringLineNoTextItem:
1524
                lineItem.loc = item.loc
1525
                lineItem.size = item.size
1526
                lineItem.angle = item.angle
1527
                lineItem.area = item.area
1528
                #lineItem.addTextItemToScene(self.graphicsView.scene)
1529
                lineItem.transfer.onRemoved.connect(self.itemRemoved)
1530
                item.transfer.onRemoved.emit(item)
1531
                appDocData.lineNos.append(lineItem)
1532
                
1533
    def createDetectedTitleBlockTextItem(self, textInfoList):
1534
        '''
1535
            @brief  draw title block
1536
            @author euisung
1537
            @date   2018.11.12
1538
            @history    2018.11.26  euisung     remove scene dependency
1539
                        2018.11.29  euisung     change name drawDetectedTitleBlockTextItem() -> createDetectedTitleBlockTextItem
1540
        '''
1541
        from TextItemFactory import TextItemFactory
1542
        import math
1543

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

    
1547
            # parse texts
1548
            for textInfo in textInfoList:
1549
                if len(textInfo[1]) is 0:
1550
                    continue
1551
                x = textInfo[1][0].getX()
1552
                y = textInfo[1][0].getY()
1553
                width = textInfo[1][0].getW()
1554
                height = textInfo[1][0].getH()
1555
                angle = round(math.radians(textInfo[1][0].getAngle()), 2)
1556
                text = textInfo[1][0].getText()
1557
                item = TextItemFactory.instance().createTextItem(textInfo)
1558

    
1559
                if item is not None:
1560
                    item.loc = (x, y)
1561
                    item.size = (width, height)
1562
                    item.angle = angle
1563
                    item.area = textInfo[0]
1564
                    #self.addTextItemToScene(item)
1565
                    appDocData.texts.append(item)
1566
                    appDocData.allItems.append(item)
1567
        except Exception as ex:
1568
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1569
            self.addMessage.emit(MessageType.Error, message)
1570

    
1571
    '''
1572
        @brief      
1573
        @author     humkyung
1574
        @date       2018.08.23
1575
        @history    2018.11.26  euisung     remove scene dependency
1576
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1577
                    2018.11.    euisung     no more used
1578
                    2018.11.29  euisung     change name drawDetectedLines() -> createDetectedLines
1579
    '''
1580
    def createDetectedLines(self, lineList, worker):
1581
        appDocData = AppDocData.instance()
1582
        area = appDocData.getArea('Drawing')
1583

    
1584
        for pts in lineList:
1585
            processLine = QEngineeringLineItem(vertices=[(area.x + param[0], area.y + param[1]) for param in pts])
1586
            processLine.area = 'Drawing'
1587
            #self.graphicsView.scene.addItem(processLine)
1588
            appDocData.lines.append(processLine)
1589
            appDocData.allItems.append(processLine)
1590

    
1591
            if processLine.length() > 100: # TODO: check critical length
1592
                processLine.addFlowArrow()
1593
        
1594
        # re-order process line's start,end according to flow mark
1595
        #worker.arrangeLinePosition(lines, symbols, listWidget)
1596
        # up to here
1597

    
1598
    '''
1599
        history     2018.06.09  humkyung    check length of original and connection point is 2 while parsing
1600
                    2018.11.26  euisung     remove scene dependency
1601
                    2018.11.29  euisung     change name drawDetectedSymbolItem() -> createDetectedSymbolItem
1602
    '''
1603
    def createDetectedSymbolItem(self, symbolList):
1604
        from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
1605
        from SymbolSvgItem import SymbolSvgItem
1606
        import math
1607

    
1608
        try:
1609
            appDocData = AppDocData.instance()
1610
            project = appDocData.getCurrentProject()
1611

    
1612
            searchedMap = []
1613
            for symbol in symbolList:
1614
                pt = [float(x) for x in symbol.getSp()]
1615
                size = [symbol.getWidth(), symbol.getHeight()]
1616
                name = symbol.getName()
1617
                angle = round(math.radians(symbol.getRotatedAngle()), 2)
1618
                _type = symbol.getType()
1619
                origin = [0,0]
1620
                if 2 == len(symbol.getOriginalPoint().split(',')):
1621
                    tokens = symbol.getOriginalPoint().split(',')
1622
                    origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
1623
                connPts = []
1624
                if symbol.getConnectionPoint() is not None and symbol.getConnectionPoint() != '':
1625
                    for param in symbol.getConnectionPoint().split('/'):
1626
                        tokens = param.split(',')
1627
                        connPts.append(('AUTO', pt[0] + float(tokens[0]), pt[1] + float(tokens[1]), '0') if len(tokens) == 2 else \
1628
                                       (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), '0') if len(tokens) == 3 else \
1629
                                       (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), tokens[3]) if len(tokens) == 4 else None)
1630

    
1631
                parentSymbol = symbol.getBaseSymbol()
1632
                childSymbol = symbol.getAdditionalSymbol()
1633
                hasInstrumentLabel = symbol.getHasInstrumentLabel()
1634

    
1635
                svgFilePath = os.path.join(project.getSvgFilePath(), _type, name + '.svg')
1636
                if os.path.isfile(svgFilePath):
1637
                    svg = SymbolSvgItem.createItem(_type, svgFilePath)
1638
                    svg.buildItem(name, _type, angle, pt, size, origin, connPts, parentSymbol, childSymbol, hasInstrumentLabel)
1639
                    svg.reCalculationRotatedItem()
1640
                    svg.area = 'Drawing'
1641

    
1642
                    # set owner - 2018.07.20 added by humkyung                   
1643
                    matches = [searched for searched in searchedMap if searched[0] == symbol.owner]
1644
                    if len(matches) == 1:
1645
                        svg.owner = matches[0][1]
1646
                    searchedMap.append((symbol, svg))
1647
                    # up to here
1648

    
1649
                    svg.transfer.onRemoved.connect(self.itemRemoved)
1650
                    #self.addSvgItemToScene(svg)
1651
                    appDocData.symbols.append(svg)
1652
                    appDocData.allItems.append(svg)
1653
                else:
1654
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
1655
                    item.isSymbol = True
1656
                    item.angle = angle
1657
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
1658
                    #self.graphicsView.scene.addItem(item)
1659
                    appDocData.symbols.append(item)
1660
                    appDocData.allItems.append(item)
1661
            # up to here
1662
        except Exception as ex:
1663
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1664
            self.addMessage.emit(MessageType.Error, message)
1665

    
1666
    '''
1667
        @history    2018.06.08  Jeongwoo    Add parameter on round method
1668
        @history    2018.11.02  euisung     Add save note text item
1669
        @history    2018.11.05  euisung     delete save note text item and move to drawDetectedItems()
1670
                    2018.11.26  euisung     remove scene dependency
1671
                    2018.11.29  euisung     change name drawDetectedTextItem() -> createDetectedTextItem
1672
    '''
1673
    def createDetectedTextItem(self, textInfoList):
1674
        from TextItemFactory import TextItemFactory
1675
        import math
1676

    
1677
        try:
1678
            appDocData = AppDocData.instance()
1679

    
1680
            # parse texts
1681
            for textInfo in textInfoList:
1682
                x = textInfo.getX()
1683
                y = textInfo.getY()
1684
                width = textInfo.getW()
1685
                height = textInfo.getH()
1686
                angle = round(math.radians(textInfo.getAngle()), 2)
1687
                text = textInfo.getText()
1688
                if not text: continue
1689

    
1690
                item = TextItemFactory.instance().createTextItem(textInfo)
1691
                if item is not None:
1692
                    item.loc = (x, y)
1693
                    item.size = (width, height)
1694
                    item.angle = angle
1695
                    item.area = 'Drawing'
1696
                    item.transfer.onRemoved.connect(self.itemRemoved)
1697
                    #self.addTextItemToScene(item)
1698
                    appDocData.texts.append(item)
1699
                    appDocData.allItems.append(item)
1700
        except Exception as ex:
1701
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1702
            self.addMessage.emit(MessageType.Error, message)
1703

    
1704
    '''
1705
        @brief      draw detected texts except which in drawing area
1706
        @history    2018.11.29  euisung     change name drawDetectedOtherTextItem() -> createDetectedOtherTextItem
1707
    '''
1708
    def createDetectedOtherTextItem(self, otherTextInfoList):
1709
        from TextItemFactory import TextItemFactory
1710
        import math
1711

    
1712
        try:
1713
            appDocData = AppDocData.instance()
1714

    
1715
            # parse notes
1716
            for textInfoMap in otherTextInfoList:
1717
                if textInfoMap[0]=='Note':
1718
                    pass
1719

    
1720
                for textInfo in textInfoMap[1]:
1721
                    x = textInfo.getX()
1722
                    y = textInfo.getY()
1723
                    width = textInfo.getW()
1724
                    height = textInfo.getH()
1725
                    angle = round(math.radians(textInfo.getAngle()))
1726
                    text = textInfo.getText()
1727

    
1728
                    item = TextItemFactory.instance().createTextItem(textInfo)
1729

    
1730
                    item.loc = (x, y)
1731
                    item.size = (width, height)
1732
                    item.angle = angle
1733
                    item.area = textInfoMap[0]
1734
                    item.transfer.onRemoved.connect(self.itemRemoved)
1735
                    appDocData.texts.append(item)
1736
                    appDocData.allItems.append(item)
1737
        except Exception as ex:
1738
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1739
            self.addMessage.emit(MessageType.Error, message)
1740

    
1741
    '''
1742
        @brief  draw unknown items 
1743
        @author humkyung
1744
        @date   2018.06.12
1745
        @history    2018.06.14  Jeongwoo    Change method to add unknown item
1746
                    2018.06.18  Jeongwoo    Add connect on unknown item
1747
                                            Add [transfer] for using pyqtSignal
1748
                    2018.11.26  euisung     remove scene dependency
1749
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1750
                    2018.11.27  euisung     add save to xml
1751
                    2018.11.29  euisung     change name drawUnknownItems() -> createUnknownItems
1752
    '''
1753
    def createUnknownItems(self, path):
1754
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem 
1755
        from EngineeringLineItem import QEngineeringLineItem
1756
        from EngineeringUnknownItem import QEngineeringUnknownItem
1757

    
1758
        try:
1759
            docData = AppDocData.instance()
1760
            project = docData.getCurrentProject()
1761
            windowSize = docData.getSlidingWindowSize()
1762
            thickness = int(windowSize[1])
1763

    
1764
            if docData.needReOpening is not None:
1765
                docData.needReOpening = True
1766

    
1767
            diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(path))
1768
            if os.path.isfile(diffFilePath):
1769
                imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1]
1770

    
1771
                ## remove line
1772
                lines = docData.lines
1773
                for line in lines:
1774
                    line.drawToImage(imgDiff, 255, thickness) if line.thickness is None else line.drawToImage(imgDiff, 255, line.thickness)
1775
                cv2.imwrite(diffFilePath, imgDiff)
1776
                ## up to here
1777

    
1778
                imgNot = np.ones(imgDiff.shape, np.uint8)
1779
                cv2.bitwise_not(imgDiff, imgNot)
1780
                imgNot = cv2.dilate(imgNot, np.ones((8,8), np.uint8))
1781

    
1782
                image, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
1783

    
1784
                ##
1785
                idx = 0
1786
                ##
1787
                smallContours = []
1788
                minimumSize = docData.getConfigs('Filter', 'MinimumSize')
1789
                for contour in contours:
1790
                    [x, y, w, h] = cv2.boundingRect(contour)
1791

    
1792
                    # remove too small one
1793
                    if len(minimumSize) is 1:
1794
                        if (w * h < int(minimumSize[0].value) * int(minimumSize[0].value)):
1795
                            smallContours.append(contour)
1796
                            idx += 1
1797
                            continue
1798

    
1799
                    '''
1800
                    rect = QRectF(x, y, w, h)
1801
                    items = [item for item in diffItems if item.boundingRect().contains(rect)]
1802
                    if len(items) > 0: continue
1803
                    
1804
                    items = [item for item in diffItems if rect.contains(item.boundingRect())]
1805
                    for item in items:
1806
                        diffItems.remove(item)
1807
                    '''
1808

    
1809
                    # create unknown item
1810
                    epsilon = cv2.arcLength(contour, True)*0.001
1811
                    approx = cv2.approxPolyDP(contour, epsilon, True)
1812
                    approx = [pt[0] for pt in approx]
1813
                    resultStr, resultList = self.determineRemainObject(idx, contours, imgNot)
1814
                    if resultStr == 'LineIndicator':
1815
                        item = QEngineeringUnknownItem(approx, 'True', resultList[0], resultList[1])
1816
                        docData.lineIndicators.append(item)
1817
                    elif resultStr == 'MissingLine':
1818
                        pass
1819
                    elif resultStr == 'Unknown':
1820
                        item = QEngineeringUnknownItem(approx, 'False')
1821
                        docData.unknowns.append(item)
1822
                    item.area = 'Drawing'
1823
                    docData.allItems.append(item)
1824
                    item.transfer.onRemoved.connect(self.itemRemoved)
1825
                    idx += 1
1826
                    # up to here                    
1827

    
1828
                imgNotRemoveSmall = cv2.drawContours(imgNot, smallContours, -1, 0, -1)
1829
                notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(path))
1830
                cv2.imwrite(notFilePath, imgNotRemoveSmall)
1831
            else:
1832
                message = 'can\'t found {}'.format(diffFilePath)
1833
                self.addMessage.emit(MessageType.Normal, message)
1834

    
1835
            self.saveToXml(False)
1836
        except Exception as ex:
1837
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1838
            self.addMessage.emit(MessageType.Error, message)
1839

    
1840
    def determineRemainObject(self, idx, contours, imgNot):
1841
        '''
1842
            @brief      determine remain objects -> line no indicator or unknown
1843
            @author     euisung
1844
            @date       2018.12.26
1845
            @history    2019.03.25  euisung    Change name isLineNoIndicator -> determineRemainObject
1846
        '''
1847
        import math
1848
        [x, y, w, h] = cv2.boundingRect(contours[idx])
1849
        
1850
        if (w < 250 and h < 250):
1851
            return ('Unknown', [])
1852
        
1853
        fLines = []
1854
        maxDifAngle = 3
1855
        mask = np.zeros_like(imgNot)
1856
        cv2.drawContours(mask, contours, idx, 123, -1) # Draw filled contour in mask
1857
        out = np.zeros_like(imgNot) # Extract out the object and place into output image
1858
        out[mask == 123] = imgNot[mask == 123]
1859

    
1860
        # Now crop
1861
        ##print(out)
1862
        (x, y) = np.where(mask == 123)
1863
        (topx, topy) = (np.min(x), np.min(y))
1864
        (bottomx, bottomy) = (np.max(x), np.max(y))
1865
        out = out[topx:bottomx+1, topy:bottomy+1]
1866
        h, w = out.shape[0], out.shape[1]
1867
        maxDifH, maxDifW = math.ceil(math.tan(4 * math.pi / 180) / 2 * w), math.ceil(math.tan(4 * math.pi / 180) / 2 * h)
1868

    
1869
        # detection lines
1870
        edged2 = cv2.Canny(out, 100, 200)
1871
        lines = cv2.HoughLinesP(image=edged2, rho=1, theta=np.pi/180, threshold=25, minLineLength=30, maxLineGap=25)
1872
        #lines = cv2.HoughLines(edged2, 1, np.pi/180, 60)
1873
        if lines is None:
1874
            return ('Unknown', [])
1875
        for line in lines:
1876
            #r, theta = line[0]
1877
            #a, b = np.cos(theta), np.sin(theta)
1878
            #x0, y0 = a * r, b * r
1879
            #x1, y1 = int(x0 + 1000 * (-b)), int(y0 + 1000 * a)
1880
            #x2, y2 = int(x0 - 1000 * (-b)), int(y0 - 1000 * a)
1881
            #cv2.line(out, (x1, y1), (x2, y2), (0, 255, 0), 3)
1882
            x1, y1, x2, y2 = line[0]
1883
            degree = math.atan2(y2 - y1, x2 - x1) * 180 / math.pi
1884
            fLine = [x1, y1, x2, y2, degree]
1885
            #print(fLine)
1886
            fLines.append(fLine)
1887
        
1888
        horLines = []
1889
        verLines = []
1890
        otherLines = []
1891
        isVH = None
1892
        for fLine in fLines:
1893
            degree = math.fabs(fLine[4])
1894
            if degree >= 90 - maxDifAngle:
1895
                verLines.append(fLine)
1896
            elif degree <= maxDifAngle:
1897
                horLines.append(fLine)
1898
            else:
1899
                otherLines.append(fLine)
1900

    
1901
        baseLines = []
1902
        baseDifV = 0
1903
        if len(horLines):
1904
            x, y = w / 2, 0
1905
            baseDifV = maxDifH
1906
            for horLine in horLines:
1907
                x1, y1, x2, y2 = horLine[0], horLine[1], horLine[2], horLine[3]
1908
                y = ((y2-y1)/(x2-x1))*x + y1 - ((y2-y1)/(x2-x1))*x1
1909
                horLine.append(y)
1910
            baseLines = horLines
1911
            isVH = 'H'
1912
        if len(verLines):
1913
            x, y = 0, h / 2
1914
            baseDifV = maxDifW
1915
            for verLine in verLines:
1916
                x1, y1, x2, y2 = verLine[0], verLine[1], verLine[2], verLine[3]
1917
                x = ((x2-x1)/(y2-y1))*y + x1 - ((x2-x1)/(y2-y1))*y1
1918
                verLine.append(x)
1919
            baseLines = verLines
1920
            isVH = 'V'
1921

    
1922
        for otherLine in otherLines:
1923
            x, y = w / 2, 0
1924
            x1, y1, x2, y2 = otherLine[0], otherLine[1], otherLine[2], otherLine[3]
1925
            y = ((y2-y1)/(x2-x1))*x + y1 - ((y2-y1)/(x2-x1))*x1
1926
            otherLine.append(y)
1927

    
1928
        # determine line no indicator 
1929
        if not ((len(horLines) > 0 and len(verLines) > 0) or len(otherLines) is 0 or (len(horLines) == 0 and len(verLines) == 0)):    
1930
            result, mergedOtherLine = self.isLineNoIndicator(w, h, maxDifAngle, baseDifV, baseLines, otherLines)
1931
            if result:
1932
                #print(fLines)
1933
                return ('LineIndicator', [isVH, mergedOtherLine])
1934

    
1935
        return ('Unknown', [])
1936

    
1937
    def isLineNoIndicator(self, w, h, maxDifAngle, baseDifV, baseLines, otherLines):
1938
        '''
1939
            @brief      determine line no indicator
1940
            @author     euisung
1941
            @date       2019.03.25
1942
        '''
1943
        import math
1944

    
1945
        if (w < 250 and h < 250):
1946
            return (False, None)
1947

    
1948
        isSameLine = True
1949
        i = 0
1950
        for baseLine in baseLines:
1951
            if not isSameLine: break
1952
            j = 0
1953
            for baseLinee in baseLines:
1954
                if i == j:
1955
                    j += 1
1956
                    continue
1957
                difV = math.fabs(baseLine[5] - baseLinee[5])
1958
                if difV > baseDifV:
1959
                   isSameLine = False
1960
                   break
1961
                j += 1
1962
            i += 1
1963
        if not isSameLine:
1964
            return (False, None)
1965

    
1966
        isSameLine = True
1967
        i = 0
1968
        maxY = 0
1969
        for otherLine in otherLines:
1970
            y = otherLine[5]
1971
            if math.fabs(y) > maxY:
1972
                maxY = math.fabs(y)
1973
            if not isSameLine: break
1974
            j = 0
1975
            for otherLinee in otherLines:
1976
                if i == j:
1977
                    j += 1
1978
                    continue
1979
                difV = math.fabs(otherLine[4] - otherLinee[4])
1980
                if difV > maxDifAngle:
1981
                   isSameLine = False
1982
                   break
1983
                j += 1
1984
            i += 1
1985
        if not isSameLine:
1986
            return (False, None)
1987
                
1988
        isSameLine = True
1989
        mergedOtherLine = [0, 0, 0, 0]
1990
        i = 0
1991
        maxDif = math.ceil(math.tan(4 * math.pi / 180) * maxY)
1992
        for otherLine in otherLines:
1993
            if not isSameLine: break
1994
            j = 0
1995
            for otherLinee in otherLines:
1996
                if i == j:
1997
                    j += 1
1998
                    continue
1999
                angle = math.fabs(otherLine[4] + otherLinee[4]) / 2
2000
                difV = math.fabs(otherLine[5] - otherLinee[5])
2001
                dist = math.sin((90 - angle) * math.pi / 180) * difV 
2002
                if dist > maxDif:
2003
                   isSameLine = False
2004
                   break
2005
                j += 1
2006
            i += 1
2007
            mergedOtherLine[0] += otherLine[0]
2008
            mergedOtherLine[1] += otherLine[1]
2009
            mergedOtherLine[2] += otherLine[2]
2010
            mergedOtherLine[3] += otherLine[3]
2011
        if not isSameLine:
2012
            (False, None)
2013
                        
2014
        # Show the output image
2015
        #print('line no indicator')
2016
        mergedOtherLine[0] = round(mergedOtherLine[0] / len(otherLines))
2017
        mergedOtherLine[1] = round(mergedOtherLine[1] / len(otherLines))
2018
        mergedOtherLine[2] = round(mergedOtherLine[2] / len(otherLines))
2019
        mergedOtherLine[3] = round(mergedOtherLine[3] / len(otherLines))
2020
        #cv2.line(out, (mergedOtherLine[0], mergedOtherLine[1]), (mergedOtherLine[2], mergedOtherLine[3]), (255, 255, 255), 3)
2021
        #cv2.imshow('Output', out)
2022
        #cv2.waitKey(0)
2023
        #cv2.destroyAllWindows()
2024
        return (True, mergedOtherLine)
2025

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

    
2054
        try:
2055
            symbols = []
2056

    
2057
            xml = parse(xmlPath)
2058
            root = xml.getroot()
2059
            
2060
            maxValue = 0
2061
            maxValue = maxValue + len(list(root.iter('SYMBOL')))
2062
            maxValue = maxValue + len(list(root.iter('ATTRIBUTE')))
2063
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
2064
            maxValue = maxValue + len(list(root.iter('LINE')))
2065
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
2066
            maxValue = maxValue + len(list(root.iter('SIZETEXT')))
2067
            self.progress.setMaximum(maxValue)
2068

    
2069
            for symbol in root.find('SYMBOLS').iter('SYMBOL'):
2070
                item = SymbolSvgItem.fromXml(symbol)
2071
                if item[0] is not None:
2072
                    item[0].transfer.onRemoved.connect(self.itemRemoved)
2073
                    symbols.append(item)                    
2074
                else:
2075
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2076
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2077
                    angle = float(symbol.find('ANGLE').text)
2078
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2079
                    item.isSymbol = True
2080
                    item.angle = angle
2081
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2082
                    self.graphicsView.scene.addItem(item)
2083

    
2084
                self.progress.setValue(self.progress.value() + 1)
2085
                
2086
            QApplication.processEvents()
2087

    
2088
            # set symbol's owner
2089
            childItems = [item for item in symbols if item[1] is not None]
2090
            for item in childItems:
2091
                matches = [param for param in symbols if str(param[0].uid) == item[1]]
2092
                if len(matches) == 1:
2093
                    item[0].owner = matches[0][0]
2094
            # up to here
2095
           
2096
            for item in symbols:
2097
                self.addSvgItemToScene(item[0])
2098
                docData.symbols.append(item[0])
2099

    
2100
            # parse texts
2101
            for text in root.find('TEXTINFOS').iter('ATTRIBUTE'):
2102
                item = QEngineeringTextItem.fromXml(text)
2103
                if item is not None:
2104
                    uid = text.find('UID')
2105
                    attributeValue = text.find('ATTRIBUTEVALUE')
2106
                    name = text.find('NAME').text
2107
                    item.transfer.onRemoved.connect(self.itemRemoved)
2108
                    self.addTextItemToScene(item)
2109
                    docData.texts.append(item)
2110

    
2111
                    if name == 'TEXT':
2112
                        if uid is not None and attributeValue is not None:
2113
                            item.uid = uid.text
2114
                            item.attribute = attributeValue.text
2115

    
2116
                self.progress.setValue(self.progress.value() + 1)
2117
                
2118
            QApplication.processEvents()
2119

    
2120
            # note
2121
            for text in root.find('NOTES').iter('ATTRIBUTE'):
2122
                item = QEngineeringTextItem.fromXml(text)
2123
                if item is not None:
2124
                    uid = text.find('UID')
2125
                    attributeValue = text.find('ATTRIBUTEVALUE')
2126
                    name = text.find('NAME').text
2127
                    item.transfer.onRemoved.connect(self.itemRemoved)
2128
                    self.addTextItemToScene(item)
2129

    
2130
                    if name == 'NOTE':
2131
                        if uid is not None:
2132
                            item.uid = uid.text
2133

    
2134
                self.progress.setValue(self.progress.value() + 1)
2135
                
2136
            QApplication.processEvents()
2137

    
2138
            for line in root.find('LINEINFOS').iter('LINE'):
2139
                item = QEngineeringLineItem.fromXml(line)
2140
                item.transfer.onRemoved.connect(self.itemRemoved)
2141
                if item: self.addLineItemToScene(item)
2142

    
2143
                #errors = item.validate()
2144
                #for error in errors: self.graphicsView.scene.addItem(error)
2145

    
2146
                self.progress.setValue(self.progress.value() + 1)
2147
                
2148
            QApplication.processEvents()
2149

    
2150
            for unknown in root.iter('UNKNOWN'):
2151
                item = QEngineeringUnknownItem.fromXml(unknown)
2152
                item.transfer.onRemoved.connect(self.itemRemoved)
2153
                if item is not None:
2154
                    item.transfer.onRemoved.connect(self.itemRemoved)
2155
                    self.addUnknownItemToScene(item)
2156

    
2157
                self.progress.setValue(self.progress.value() + 1)
2158
                
2159
            QApplication.processEvents()
2160

    
2161
            for line_no in root.find('LINENOS').iter('LINE_NO'):
2162
                item = QEngineeringLineNoTextItem.fromXml(line_no)
2163
                if item is not None:
2164
                    item.transfer.onRemoved.connect(self.itemRemoved)
2165
                    self.addTextItemToScene(item)
2166

    
2167
                connLine = line_no.find('CONNLINE')
2168
                if connLine is not None:
2169
                    lineUID = connLine.text
2170
                    connLine = self.graphicsView.findItemByUid(lineUID)
2171
                    if connLine is not None:
2172
                        item.conns.append(connLine)
2173

    
2174
                run = line_no.find('RUN')
2175
                if run is not None:
2176
                    lineRunItem = QEngineeringRunItem()
2177
                    for child in run:
2178
                        uidElement = child.find('UID')
2179
                        if uidElement is not None:
2180
                            uid = uidElement.text
2181
                            runItem = self.graphicsView.findItemByUid(uid)
2182
                            if runItem is not None:
2183
                                lineRunItem.items.append(runItem)
2184

    
2185
                    item.runs.append(lineRunItem)
2186
                    treeItem = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2187
                    for connectedItem in lineRunItem.items:
2188
                        if issubclass(type(connectedItem), SymbolSvgItem): self.itemTreeWidget.addTreeItem(treeItem, connectedItem)
2189
                    docData.tracerLineNos.append(item)
2190

    
2191
                self.progress.setValue(self.progress.value() + 1)
2192
            QApplication.processEvents()
2193

    
2194
            for trimLineNo in root.iter('TRIM_LINE_NO'):
2195
                item = QEngineeringTrimLineNoTextItem()
2196
                item.uid = trimLineNo.find('UID')
2197

    
2198
                run = trimLineNo.find('RUN')
2199
                if run is not None:
2200
                    lineRunItem = QEngineeringRunItem()
2201
                    for child in run:
2202
                        uidElement = child.find('UID')
2203
                        if uidElement is not None:
2204
                            uid = uidElement.text
2205
                            runItem = self.graphicsView.findItemByUid(uid)
2206
                            if runItem is not None:
2207
                                lineRunItem.items.append(runItem)
2208

    
2209
                    item.runs.append(lineRunItem)
2210
                    treeItem = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2211
                    for connectedItem in lineRunItem.items:
2212
                        if issubclass(type(connectedItem), SymbolSvgItem): self.itemTreeWidget.addTreeItem(treeItem, connectedItem)
2213
                    docData.tracerLineNos.append(item)
2214
            # up to here
2215

    
2216
            # set symbol's connectItem
2217
            from EngineeringConnectorItem import QEngineeringConnectorItem
2218
            connectors = [item for item in self.graphicsView.scene.items() if type(item) == QEngineeringConnectorItem and item.connectedItem is not None]
2219
            for connector in connectors:
2220
                # 처음에는 UID가 connectedItem에 String으로 들어가있기 때문에
2221
                connector.connectedItem = self.graphicsView.findItemByUid(connector.connectedItem)
2222

    
2223
            symbols = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and len(item.attrs) > 0 and type(item) is not QEngineeringSpecBreakItem]
2224
            for symbol in symbols:
2225
                # 처음에는 attrs의 uid가 connectedItem에 String으로 들어가있기 때문에
2226
                for key in symbol.attrs.keys():
2227
                    if type(symbol.attrs[key]) is not UserInputAttribute and type(symbol.attrs[key]) is not tuple:
2228
                        symbol.attrs[key] = self.graphicsView.findItemByUid(symbol.attrs[key])
2229
                        
2230
            # Update Scene
2231
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2232
            for item in self.graphicsView.scene.items():
2233
                item.setVisible(True)
2234

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

    
2239
    '''
2240
        @brief      Remove added item on same place and Add GraphicsItem
2241
        @author     Jeongwoo
2242
        @date       2018.05.25
2243
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2244
                    2018.06.18  Jeongwoo    Set Z-index
2245
    '''
2246
    def addSvgItemToScene(self, svgItem):
2247
        svgItem.addSvgItemToScene(self.graphicsView.scene)
2248
        
2249
    '''
2250
        @brief      Remove added item on same place and Add GraphicsItem
2251
        @author     Jeongwoo
2252
        @date       2018.05.25
2253
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2254
                    2018.06.05  Jeongwoo    Remove Size condition
2255
                    2018.06.18  Jeongwoo    Set Z-index
2256
    '''
2257
    def addTextItemToScene(self, textItem):
2258
        textItem.addTextItemToScene(self.graphicsView.scene)
2259
        
2260
    '''
2261
        @brief      Remove added item on same place and Add GraphicsItem
2262
        @author     Jeongwoo
2263
        @date       2018.05.29
2264
        @history    2018.06.18  Jeongwoo    Set Z-index
2265
    '''
2266
    def addLineItemToScene(self, lineItem):
2267
        self.graphicsView.scene.addItem(lineItem)
2268

    
2269
    '''
2270
        @brief      Remove added item on same place and Add Unknown Item
2271
        @author     Jeongwoo
2272
        @date       2018.06.14
2273
        @history    2018.06.18  Jeongwoo    Set Z-index
2274
    '''
2275
    def addUnknownItemToScene(self, unknownItem):
2276
        try:
2277
            unknownItem.addUnknownItemToScene(self.graphicsView.scene)
2278
        except Exception as ex:
2279
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2280
            self.addMessage.emit(MessageType.Error, message)
2281

    
2282
    '''
2283
        @brief      generate output xml file
2284
        @author     humkyung
2285
        @date       2018.04.23
2286
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
2287
    '''
2288
    def generateOutput(self):
2289
        import XmlGenerator as xg
2290

    
2291
        if not self.graphicsView.hasImage():
2292
            self.showImageSelectionMessageBox()
2293
            return
2294

    
2295
        try:
2296
            appDocData = AppDocData.instance()
2297

    
2298
            ## collect items
2299
            appDocData.lines.clear()
2300
            appDocData.lines = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem and item.owner is None]
2301

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

    
2305
            appDocData.equipments.clear()
2306
            for item in self.graphicsView.scene.items():
2307
                if type(item) is QEngineeringEquipmentItem:
2308
                    appDocData.equipments.append(item)
2309

    
2310
            appDocData.texts.clear()
2311
            appDocData.texts = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem) and type(item) is not QEngineeringLineNoTextItem]
2312
            ## up to here
2313

    
2314
            appDocData.imgOutput = np.ones((appDocData.imgHeight, appDocData.imgWidth), np.uint8)*255
2315
            xg.writeOutputXml(appDocData.imgName, appDocData.imgWidth, appDocData.imgHeight) # TODO: check
2316
            project = appDocData.getCurrentProject()
2317
            cv2.imwrite(os.path.join(project.getTempPath() , 'OUTPUT.png') , appDocData.imgOutput)
2318
        except Exception as ex:
2319
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2320
            self.addMessage.emit(MessageType.Error, message)
2321

    
2322
    '''
2323
        @brief      resetting attribute at secne
2324
        @author     kyoyho
2325
        @date       2018.08.21
2326
    '''
2327
    def checkAttribute(self):
2328
        try:
2329

    
2330
            docData = AppDocData.instance()
2331
            if not self.graphicsView.hasImage():
2332
                return
2333

    
2334
            # symbol 경우
2335
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringSpecBreakItem]
2336
            for item in items:
2337
                attrs = item.attrs
2338
                
2339
                removeAttrList = []
2340
                for attr in attrs:
2341
                    if type(attr) is tuple:
2342
                        continue
2343

    
2344
                    if attr is None:
2345
                        removeAttrList.append(attr)
2346
                        continue
2347

    
2348
                    attrInfo = docData.getSymbolAttributeByUID(attr.UID)
2349
                    if attrInfo is None:
2350
                        removeAttrList.append(attr)
2351
                    # 해당 attribute가 맞는지 확인
2352
                    else:
2353
                        attrType = attrInfo.AttributeType
2354
                        _type = type(attr)
2355
                        if attrType == 'Symbol Item':
2356
                            if not issubclass(_type, SymbolSvgItem):
2357
                                removeAttrList.append(attr)
2358
                        elif attrType == 'Text Item':
2359
                            if _type is not QEngineeringTextItem:
2360
                                removeAttrList.append(attr)
2361
                        elif attrType == 'Int':
2362
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
2363
                                removeAttrList.append(attr)
2364
                        elif attrType == 'String':
2365
                            if _type is not UserInputAttribute:
2366
                                removeAttrList.append(attr)
2367

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

    
2371
            # Line No Text Item의 경우
2372
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringLineNoTextItem)]
2373
            for item in items:
2374
                attrs = item.attrs
2375
                
2376
                removeAttrList = []
2377
                for attr in attrs:
2378
                    if type(attr) is UserInputAttribute:
2379
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
2380
                        if attrInfo is None:
2381
                            removeAttrList.append(attr)
2382

    
2383
                for attr in removeAttrList:
2384
                    del attrs[attr]
2385

    
2386
        except Exception as ex:
2387
                message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
2388
                self.addMessage.emit(MessageType.Error, message)
2389
    '''
2390
        @brief      Check Number
2391
        @author     kyouho
2392
        @date       2018.08.20
2393
    '''
2394
    def isNumber(self, num):
2395
        p = re.compile('(^[0-9]+$)')
2396
        result = p.match(num)
2397

    
2398
        if result:
2399
            return True
2400
        else:
2401
            return False
2402

    
2403
    '''
2404
        @brief      find overlap Connector
2405
        @author     kyouho
2406
        @date       2018.08.28
2407
    '''
2408
    def findOverlapConnector(self, connectorItem):
2409
        from shapely.geometry import Point
2410
        from EngineeringConnectorItem import QEngineeringConnectorItem
2411
        itemList = []
2412
        
2413
        x = connectorItem.center()[0]
2414
        y = connectorItem.center()[1]
2415

    
2416
        connectors = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringConnectorItem and item != connectorItem]
2417
        for connector in connectors:
2418
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
2419
                itemList.append(connector.parent)
2420

    
2421
        return itemList
2422

    
2423
if __name__ == '__main__':
2424
    import locale
2425
    from PyQt5.QtCore import QTranslator
2426
    from License import QLicenseDialog
2427
    from ProjectDialog import Ui_Dialog
2428
    from App import App 
2429

    
2430
    app = App(sys.argv)
2431
    try:
2432
        if True == QLicenseDialog.check_license_key():
2433
            dlg = Ui_Dialog()
2434
            selectedProject = dlg.showDialog()
2435
            if selectedProject is not None:
2436
                AppDocData.instance().setCurrentProject(selectedProject)
2437
                app._mainWnd = MainWindow.instance()
2438
                app._mainWnd.show()
2439
                sys.exit(app.exec_())
2440
    except Exception as ex:
2441
        print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
2442
    finally:
2443
        pass
2444