프로젝트

일반

사용자정보

통계
| 개정판:

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

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

1
# coding: utf-8
2

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

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

    
18
import cv2
19
import numpy as np
20

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

    
26
from PIL import Image
27

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

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

    
53
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane):
54
    """
55
    This is MainWindow class
56
    """
57
    addMessage = pyqtSignal(Enum, str)
58

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

    
90
        docData = AppDocData.instance()
91
        project = docData.getCurrentProject()
92
        _translate = QCoreApplication.translate
93
        self.setWindowTitle(_translate("Digital P&ID - {}".format(project.name), "Digital P&ID - {}".format(project.name)))
94

    
95
        self.lineComboBox = QComboBox(self.toolBar)
96
        lineTypes = docData.getLineTypes()
97
        for lineType in lineTypes:
98
            self.lineComboBox.addItem(lineType)
99
        self.lineComboBox.currentIndexChanged.connect(self.onLineTypeChanged)
100

    
101
        self.toolBar.insertWidget(self.actionOCR, self.lineComboBox)
102
        self.toolBar.insertSeparator(self.actionOCR)
103
        self.graphicsView = QtImageViewer.QtImageViewer(self)
104
        self.graphicsView.setParent(self.centralwidget)
105
        self.graphicsView.useDefaultCommand() ##### USE DEFAULT COMMAND
106

    
107
        self.verticalLayout.addWidget(self.graphicsView)
108

    
109
        # Add Custom TreeWidget
110
        self.dirTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
111
        self.dirTreeWidget.header().hide()
112
        self.symbolTabVerticalLayout.addWidget(self.dirTreeWidget)
113

    
114
        # Add Custom Property TableWidget
115
        self.propertyTableWidget = SymbolPropertyTableWidget.QSymbolPropertyTableWidget()
116
        self.symbolTabVerticalLayout.addWidget(self.propertyTableWidget)
117
        self.dirTreeWidget.singleClicked.connect(self.propertyTableWidget.getClickedSymbol)
118
        # add splitter widget
119
        splitter = QSplitter(Qt.Vertical)
120
        splitter.addWidget(self.dirTreeWidget)
121
        splitter.addWidget(self.propertyTableWidget)
122
        self.symbolTabVerticalLayout.addWidget(splitter)
123
        # up to here
124

    
125
        # Add Custom Result Tree Widget (Symbol Explorer)
126
        self.resultTreeWidget = ItemTreeWidget.QItemTreeWidget(self.graphicsView)
127
        self.resultTreeWidget.header().hide()
128
        self.symbolExplorerVerticalLayout.addWidget(self.resultTreeWidget)
129

    
130
        # Add Empty Widget
131
        self.resultPropertyTableWidget = ItemPropertyTableWidget.QItemPropertyTableWidget(self)
132
        self.symbolExplorerVerticalLayout.addWidget(self.resultPropertyTableWidget)
133
        self.resultTreeWidget.singleClicked.connect(self.resultPropertyTableWidget.onSymbolClicked)
134
        self.resultTreeWidget.noteNoSingleClicked.connect(self.resultPropertyTableWidget.onNoteClicked)
135
        self.resultTreeWidget.lineNoSingleClicked.connect(self.resultPropertyTableWidget.onLineNoClicked)
136
        self.resultTreeWidget.drawingClicked.connect(self.resultPropertyTableWidget.onDrawingClicked)
137
        # add splitter widget
138
        splitter = QSplitter(Qt.Vertical)
139
        splitter.addWidget(self.resultTreeWidget)
140
        splitter.addWidget(self.resultPropertyTableWidget)
141
        self.symbolExplorerVerticalLayout.addWidget(splitter)
142
        # up to here
143

    
144
        # Initialize Action group
145
        self.actionGroup = QActionGroup(self)
146
        self.actionGroup.addAction(self.actionRecognition)
147
        self.actionGroup.addAction(self.actionLineRecognition)
148
        self.actionGroup.addAction(self.actionLine)
149
        self.actionGroup.addAction(self.actionGenerateOutput)
150
        self.actionGroup.addAction(self.actionOCR)
151
        self.actionGroup.addAction(self.actionZoom)
152
        self.actionGroup.addAction(self.actionFitWindow)
153
        self.actionGroup.addAction(self.actionSave)
154
        self.actionGroup.triggered.connect(self.actionGroupTriggered)
155

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

    
193
        # removedItems
194
        self.removedItems = {}
195
        self.removedItems['LINE'] = []
196
        self.removedItems['EQUIP'] = []
197
        self.removedItems['INST'] = []
198
        self.removedItems['NOTE'] = []
199

    
200
        self.delimiter = '"'
201
    
202
        self.resizeDocks({self.dockWidget}, {self.dockWidgetObjectExplorer.sizeHint().width()}, Qt.Horizontal)
203

    
204
        self.treeWidgetDrawingList.setHeaderHidden(False)
205
        self.treeWidgetDrawingList.header().setStretchLastSection(False)
206
        self.treeWidgetDrawingList.setHeaderLabels(['Name', 'DateTime'])
207
        self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing)
208
        self.load_drawing_list()
209

    
210
        # load stylesheet file list
211
        stylesheet_name = QtWidgets.qApp.stylesheet_name
212
        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']
213
        for file in files:
214
            action = self.menuTheme.addAction(file)
215
            action.setCheckable(True)
216
            action.setChecked(True) if stylesheet_name == file else action.setChecked(False)
217
            action.triggered.connect(partial(self.load_stylesheet, file))
218
        # up to here
219

    
220
    def load_stylesheet(self, file):
221
        """
222
        @brief  load stylesheets
223
        @author humkyung
224
        @date   2018.10.29
225
        """
226

    
227
        QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
228

    
229
        app_doc_data = AppDocData.instance()
230
        configs = [Config('app', 'stylesheet', file)]
231
        app_doc_data.saveAppConfigs(configs)
232
        
233
        for action in self.menuTheme.actions():
234
            if action.text() == file: continue
235
            action.setChecked(False)
236

    
237
    '''
238
        @brief      Clear TreeWidget and Set Current PID
239
        @author     Jeongwoo
240
        @date       18.04.11
241
        @history    2018.04.26  Jeongwoo    Add Child [SYMBOLS, NOTES] into root item
242
                    2018.05.09  Jeongwoo    Change method to add default tree items
243
                    humkyung 2018.06.10 add tree item for Line No and Unknown Item
244
    '''
245
    def load_drawing_list(self):
246
        """
247
        @brief      load p&id drawing list
248
        @author     humkyung
249
        @date       18.11.02
250
        """
251

    
252
        try:
253
            appDocData = AppDocData.instance()
254
            drawings = appDocData.getDrawings()
255

    
256
            self.treeWidgetDrawingList.clear()
257
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList, ['P&ID Drawings', ''])
258
            files = appDocData.getDrawingFileList()
259
            for file in files:
260
                drawing = [drawing for drawing in drawings if drawing[1] == file]
261
                if not drawing or not drawing[0]:
262
                    drawings.append([None, file, None])
263

    
264
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [file, drawing[0][2] if drawing and drawing[0] else ''])
265
                item.setIcon(0, QIcon(':newPrefix/image.png'))
266
            
267
            self.treeWidgetDrawingList.root.setText(0, 'P&ID Drawings({})'.format(self.treeWidgetDrawingList.root.childCount()))
268
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
269
            self.treeWidgetDrawingList.root.sortChildren(0, Qt.AscendingOrder)
270
            self.treeWidgetDrawingList.resizeColumnToContents(0)
271

    
272
            appDocData.saveDrawings(drawings)
273
        except Exception as ex:
274
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
275
            self.addMessage.emit(MessageType.Error, message)
276

    
277
    def open_selected_drawing(self, item, column):
278
        """
279
        @brief      open selected p&id drawing
280
        @author     humkyung
281
        @date       18.11.02
282
        """
283
        appDocData = AppDocData.instance()
284
        drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), item.text(column))
285
        self.onOpenImageDrawing(drawing)
286

    
287
    def onShowDetectSymbol(self):
288
        from DetectSymbolDialog import QDetectSymbolDialog
289

    
290
        dlgDetectSymbol = QDetectSymbolDialog(self)
291
        dlgDetectSymbol.show()
292
        dlgDetectSymbol.exec_()
293
        
294
    '''
295
        @brief      OCR Editor
296
        @author     euisung
297
        @date       2018.10.05
298
        @history    2018.10.16 euisung      no more used, Integrated with oCRTrainingClicked
299
    '''
300
    def oCRTrainingEdidorClicked(self):
301
        from TrainingEditorDialog import QTrainingEditorDialog
302

    
303
        try:
304
            dialog = QTrainingEditorDialog(self)
305
            dialog.exec_()
306
        except Exception as ex:
307
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
308
            self.addMessage.emit(MessageType.Error, message)
309
            
310
        return
311

    
312
    '''
313
        @brief      OCR Training
314
        @author     euisung
315
        @date       2018.09.27
316
        @history    euisung 2018.10.16 TrainingListDialog -> TrainingImageListDialog
317
    '''
318
    def oCRTrainingClicked(self):
319
        from TrainingImageListDialog import QTrainingImageListDialog
320
        #import ctypes
321
        #if not ctypes.windll.shell32.IsUserAnAdmin():
322
        #    reply = QMessageBox.information(self, 'Error', '관리자 권한으로 실행해 주세요.')
323
        #    #return
324
        try:
325
            dialog = QTrainingImageListDialog(self)
326
            dialog.exec_()
327
        except Exception as ex:
328
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
329
            self.addMessage.emit(MessageType.Error, message)
330
            
331
        return
332

    
333
    '''
334
        @brief      show unknownitem's count
335
        @author     kyouho
336
        @date       2018.08.27
337
    '''
338
    def findReplaceTextClicked(self):
339
        if not self.graphicsView.hasImage():
340
            self.showImageSelectionMessageBox()
341
            return
342

    
343
        from TextItemEditDialog import QTextItemEditDialog
344

    
345
        self.dlgTextItemEdit = QTextItemEditDialog(self)
346
        self.dlgTextItemEdit.show()
347
        self.dlgTextItemEdit.exec_()
348

    
349
    '''
350
        @brief      show unknownitem's count
351
        @author     humkyung
352
        @date       2018.08.23
353
        @history    humkyung 2018.08.30 display count of symbol, line, text
354
    '''
355
    def onSceneChanged(self):
356
        items = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
357
        if len(items) > 0:
358
            self.labelStatus.setText("<font color='red'>미인식 : {}</font>".format(len(items)))
359
        else:
360
            self.labelStatus.setText("<font color='black'>미인식 : {}</font>".format(len(items)))
361

    
362
        items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem)]
363
        self.labelSymbolStatus.setText("<font color='blue'>심볼 : {}</font>".format(len(items)))
364

    
365
        items = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem]
366
        self.labelLineStatus.setText("<font color='blue'>라인 : {}</font>".format(len(items)))
367

    
368
        items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
369
        self.labelTextStatus.setText("<font color='blue'>텍스트 : {}</font>".format(len(items)))
370

    
371
    '''
372
        @brief      action save click event
373
        @author     kyouho
374
        @date       2018.08.09
375
        @history    euisung     2018.11.02       add line data list db update
376
                    humkyung save saved time to database
377
    '''
378
    def actionSaveCliked(self):
379
        from datetime import datetime
380
        from AppDocData import AppDocData
381

    
382
        appDocData = AppDocData.instance()
383
        if appDocData.imgName is None:
384
            self.showImageSelectionMessageBox()
385
            return
386

    
387
        items = self.graphicsView.scene.items()
388
        for item in items:
389
            if type(item) is QEngineeringLineNoTextItem:
390
                item.saveLineData()
391
            if type(item) is QEngineeringEquipmentItem:
392
                item.saveEquipData()
393
            if type(item) is QEngineeringInstrumentItem:
394
                item.saveInstData()
395
        self.saveToXml(True)
396

    
397
        drawings = appDocData.getDrawings()
398
        drawing = [drawing for drawing in drawings if appDocData.imgName == os.path.splitext(drawing[1])[0]]
399
        if drawing[0]:
400
            drawing[0][2] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
401
            appDocData.saveDrawings(drawing)
402

    
403
    '''
404
        @brief      save items to xml
405
        @author     kyouho
406
        @date       2018.07.31
407
    '''
408
    def saveToXml(self, alert = True):
409
        import XmlGenerator as xg
410
        from AppDocData import AppDocData
411
        docData = AppDocData.instance()
412
        if docData.imgName is None:
413
            self.showImageSelectionMessageBox()
414
            return
415
        result = xg.writeXmlOnScene(docData.imgName, docData.imgWidth, docData.imgHeight, self.graphicsView.scene)
416
        
417
        if len(self.removedItems['LINE']):
418
            docData.deleteLineDataList_LineNo(self.removedItems['LINE'])
419
            self.removedItems['LINE'] = []
420

    
421
        if len(self.removedItems['EQUIP']):
422
            docData.deleteEquipDataList(self.removedItems['EQUIP'])
423
            self.removedItems['EQUIP'] = []
424

    
425
        if len(self.removedItems['INST']):
426
            docData.deleteInstDataList(self.removedItems['INST'])
427
            self.removedItems['INST'] = []
428

    
429
        if len(self.removedItems['NOTE']):
430
            docData.deleteNoteDataList(self.removedItems['NOTE'])
431
            self.removedItems['NOTE'] = []
432

    
433

    
434
        if alert:
435
            resultStr = '[저장 결과]'
436

    
437
            for item in result.items():
438
                itemName = str(item[0])
439
                itemSuccessCount = str(item[1][0])
440
                itemFailUidList = item[1][1]
441
                resultStr += "\r\n" + itemName + " Save Count : " + itemSuccessCount
442
                if len(itemFailUidList) > 0:
443
                    resultStr += "\r\n" + itemName + " Error List(UID)"
444
                    for uid in itemFailUidList:
445
                        resultStr += "\r\n" + uid
446

    
447
            QMessageBox.about(self.graphicsView, "알림", resultStr)
448

    
449
    '''
450
        @brief      refresh resultPropertyTableWidget
451
        @author     kyouho
452
        @date       2018.07.19
453
    '''
454
    def refreshResultPropertyTableWidget(self):
455
        items = self.graphicsView.scene.selectedItems()
456
        if len(items) == 1:
457
            self.resultPropertyTableWidget.onSymbolClicked(items[0])
458
    
459
    '''
460
        @brief      resultPropertyTableWidget Cell Click Event
461
        @author     kyouho
462
        @date       2018.08.23
463
    '''
464
    def cellClickedEvent(self, row, column):
465
        item = self.graphicsView.scene.selectedItems()
466
        if len(item) != 1:
467
            return
468
        item = item[0]
469

    
470
        cell = self.resultPropertyTableWidget.item(row, column)
471
        for valueCell, uid in self.resultPropertyTableWidget.attrValueList:
472
            if valueCell == cell and issubclass(type(item), SymbolSvgItem):
473
                for attr in item.attrs:
474
                    if attr.attribute == uid and (issubclass(type(attr), SymbolSvgItem) or type(attr) is QEngineeringTextItem):
475
                        prevItem = item
476
                        currentItem = attr
477

    
478
                        rect = currentItem.sceneBoundingRect()
479
                        self.graphicsView.centerOn(rect.center())
480
                        self.graphicsView.zoomImage(True, QMouseEvent(QEvent.MouseButtonPress, self.graphicsView.mapFromScene(QPointF(rect.left(), rect.top())), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier), 3)
481
                        prevItem.setSelected(True)
482

    
483
                        currentItem.setHightlight()
484
                    elif (issubclass(type(attr), SymbolSvgItem) or type(attr) is QEngineeringTextItem):
485
                        attr.unsetHightlight()
486

    
487

    
488
    '''
489
        @brief  add message listwidget
490
        @author humkyung
491
        @date   2018.07.31
492
    '''
493
    def onAddMessage(self, messageType, message):
494
        from AppDocData import MessageType
495

    
496
        try:
497
            current = QDateTime.currentDateTime()
498

    
499
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
500
            if messageType == MessageType.Error:
501
                item.setBackground(Qt.red)
502

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

    
507
    '''
508
        @brief      clear log
509
        @author     humkyung
510
        @date       2018.08.01
511
    '''
512
    def onClearLog(self):
513
        self.listWidgetLog.clear()
514

    
515
    '''
516
        @brief      rotate selected symbol
517
        @author     humkyung
518
        @date       2018.08.15
519
    '''
520
    def onRotate(self, action):
521
        selected = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem)]
522
        if len(selected) == 1:
523
            selected[0].rotateSymbol()
524

    
525
    '''
526
        @brief      Area Zoom
527
        @author     Jeongwoo
528
        @date       2018.06.27
529
        @history    connect command's rejected signal
530
    '''
531
    def onAreaZoom(self, action):
532
        if self.actionZoom.isChecked():
533
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
534
            cmd.onRejected.connect(self.onCommandRejected)
535
            self.graphicsView.command = cmd
536

    
537
    '''
538
        @brief      Fit Window
539
        @author     Jeongwoo
540
        @date       2018.06.27
541
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
542
    '''
543
    def fitWindow(self, action):
544
        self.graphicsView.useDefaultCommand()
545
        self.graphicsView.zoomImageInit()
546

    
547
    def onConvertPDFToImage(self):
548
        """
549
        @brief      convert to selected pdf to image
550
        @author     humkyung 
551
        @date       2018.07.09
552
        @history    Euisung 2018.10.11 hide shell
553
        """
554
        try: 
555
            filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)) , 'bin64', 'PDF_TO_IMAGE.exe')
556
            subprocess.call(filePath, shell = False)
557
        except Exception as ex:
558
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
559

    
560
    '''
561
        @brief      selection changed
562
        @author     humkyung
563
        @date       2018.06.27
564
        @history    humkung 2018.07.08 call tree widget's findItem
565
    '''
566
    def onSelectionChanged(self):
567
        items = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem) or \
568
            type(item) is QEngineeringLineItem or type(item) is QEngineeringLineNoTextItem or type(item) is QEngineeringNoteItem]
569
        if items:
570
            item = items[-1]
571
            self.resultTreeWidget.findItem(item)
572
            self.resultPropertyTableWidget.showItemProperty(item)
573
        else:
574
            self.resultPropertyTableWidget.showItemProperty(None)
575
        
576
    '''
577
        @brief      Initialize scene and ResultTreeWidget
578
        @author     Jeongwoo
579
        @date       2018.06.14
580
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
581
    '''
582
    def onInitializeScene(self, action):
583
        if not self.graphicsView.hasImage():
584
            self.actionEquipment.setChecked(False)
585
            self.showImageSelectionMessageBox()
586

    
587
            return
588

    
589
        msg = QMessageBox()
590
        msg.setIcon(QMessageBox.Critical)
591
        msg.setText("선택한 인식한 항목들을 삭제하시겠습니까?\n삭제된 항목들은 복구할 수 없습니다.")
592
        msg.setWindowTitle("항목 삭제")
593
        msg.setStandardButtons(QMessageBox.Ok|QMessageBox.Cancel)
594
        if QMessageBox.Ok == msg.exec_():
595
            items = self.graphicsView.scene.items()
596
            for item in items:
597
                if type(item) is not QGraphicsPixmapItem:
598
                    self.graphicsView.scene.removeItem(item)
599

    
600
                    if type(item) is QEngineeringLineNoTextItem:
601
                        self.removedItems['LINE'].append(str(item.uid))
602
                    elif type(item) is QEngineeringInstrumentItem:
603
                        self.removedItems['INST'].append(str(item.uid))
604
                    elif type(item) is QEngineeringEquipmentItem:
605
                        self.removedItems['EQUIP'].append(str(item.uid))
606
                    elif type(item) is QEngineeringNoteItem:
607
                        self.removedItems['NOTE'].append(str(item.uid))
608
                    
609
            if self.path is not None:
610
                baseName = os.path.basename(self.path)
611
                self.resultTreeWidget.setCurrentPID(baseName)
612

    
613
    '''
614
        @brief      Manage Checkable Action statement
615
        @author     Jeongwoo
616
        @date       2018.05.10
617
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
618
    '''
619
    def actionGroupTriggered(self, action):
620
        if self.graphicsView.command is not None:
621
            self.graphicsView.useDefaultCommand()
622

    
623
        for _action in self.actionGroup.actions():
624
            _action.setChecked(False)
625

    
626
        action.setChecked(True)
627

    
628
    '''
629
        @brief      Create Equipment
630
        @author     Jeongwoo
631
        @date       18.05.03
632
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
633
    '''
634
    def createEquipment(self):
635
        if not self.graphicsView.hasImage():
636
            self.actionEquipment.setChecked(False)
637
            self.showImageSelectionMessageBox()
638
            return
639
        if self.actionEquipment.isChecked():
640
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.resultTreeWidget, self.dirTreeWidget)
641
        else:
642
            self.graphicsView.useDefaultCommand()
643

    
644

    
645
    '''
646
        @brief      Create Nozzle
647
        @author     Jeongwoo
648
        @date       2018.05.03
649
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
650
    '''
651
    def createNozzle(self):
652
        if not self.graphicsView.hasImage():
653
            self.actionNozzle.setChecked(False)
654
            self.showImageSelectionMessageBox()
655
            return
656
        if self.actionNozzle.isChecked():
657
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.resultTreeWidget, self.dirTreeWidget)
658
        else:
659
            self.graphicsView.useDefaultCommand()
660

    
661
    '''
662
        @brief      Area OCR
663
        @author     Jeongwoo
664
        @date       18.04.18
665
        @history    2018.05.02  Jeongwoo    Change graphicsView.command by actionOCR checked state
666
                                            Show MessageBox when imageviewer doesn't have image
667
    '''
668
    def onAreaOcr(self):
669
        if not self.graphicsView.hasImage():
670
            self.actionOCR.setChecked(False)
671
            self.showImageSelectionMessageBox()
672
            return
673

    
674
        if self.actionOCR.isChecked():
675
            cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView)
676
            cmd.onSuccess.connect(self.onRecognizeText)
677
            cmd.onRejected.connect(self.onCommandRejected)
678
            self.graphicsView.command = cmd
679
        else:
680
            self.graphicsView.useDefaultCommand()
681
    
682
    '''
683
        @brief      show text recognition dialog
684
        @author     humkyung
685
        @date       2018.08.08
686
    '''
687
    def onRecognizeText(self, x, y, width, height):
688
        from OcrResultDialog import QOcrResultDialog
689

    
690
        try:
691
            image = self.graphicsView.image().copy(x, y, width, height)
692
            dialog = QOcrResultDialog(self.graphicsView, image, QRectF(x, y, width, height))
693
            (isAccept, textInfoList) = dialog.showDialog()
694
            if isAccept:
695
                if textInfoList is not None and len(textInfoList) > 0:
696
                    docData = AppDocData.instance()
697
                    configs = docData.getConfigs('Line No', 'Delimiter')
698
                    delimiter = configs[0].value if 1 == len(configs) else '-'
699
                    lineNoconfigs = docData.getConfigs('Line No', 'Configuration')
700
                    for textInfo in textInfoList:
701
                        x = textInfo.getX()
702
                        y = textInfo.getY()
703
                        angle = textInfo.getAngle()
704
                        text = textInfo.getText()
705
                        width = textInfo.getW()
706
                        height = textInfo.getH()
707
                        item = TextItemFactory.instance().createTextItem(text)
708
                        if item is not None:
709
                            item.loc = (x, y)
710
                            item.size = (width, height)
711
                            item.angle = angle
712
                            item.setPlainText(text)
713
                            item.setDefaultTextColor(Qt.blue)
714
                            item.addTextItemToScene(self.graphicsView.scene)
715
                            item.transfer.onRemoved.connect(self.itemRemoved)
716
                        else:
717
                            message = 'error occured({}) in {}:{}'.format('텍스트 생성에 실패했습니다.', sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
718
                            self.addMessage.emit(MessageType.Normal, message)
719
                else:
720
                    QMessageBox.about(self.graphicsView, "알림", "텍스트 검출 실패")
721
        except Exception as ex:
722
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
723
            self.addMessage.emit(MessageType.Error, message)
724

    
725
    '''
726
        @brief  area configuration
727
    '''
728
    def areaConfiguration(self):
729
        from ConfigurationAreaDialog import QConfigurationAreaDialog
730

    
731
        self.dlgConfigurationArea = QConfigurationAreaDialog(self)
732
        self.dlgConfigurationArea.show()
733
        self.dlgConfigurationArea.exec_()
734

    
735
    '''
736
        @brief  configuration
737
    '''
738
    def configuration(self):
739
        from ConfigurationDialog import QConfigurationDialog
740

    
741
        self.dlgConfiguration = QConfigurationDialog(self)
742
        self.dlgConfiguration.show()
743
        self.dlgConfiguration.exec_()
744

    
745
    '''
746
        @brief  show nominal diameter dialog 
747
        @author humkyung
748
        @date   2018.06.28
749
    '''
750
    def onShowCodeTable(self):
751
        from CodeTableDialog import QCodeTableDialog
752

    
753
        dlg = QCodeTableDialog(self)
754
        dlg.exec_()
755

    
756
    '''
757
        @brief  show HMB data
758
        @author humkyung
759
        @date   2018.07.11
760
    '''
761
    def onHMBData(self):
762
        from HMBDialog import QHMBDialog
763

    
764
        dlg = QHMBDialog(self)
765
        dlg.show()
766
        dlg.exec_()
767

    
768
    '''
769
        @brief  show line data list 
770
        @author humkyung
771
        @date   2018.05.03
772
    '''
773
    def showItemDataList(self):
774
        from ItemDataExportDialog import QItemDataExportDialog
775

    
776
        self.dlgLineDataList = QItemDataExportDialog(self)
777
        self.dlgLineDataList.exec_()
778

    
779
    '''
780
        @brief  Show Image Selection Guide MessageBox
781
        @author Jeongwoo
782
        @date   2018.05.02
783
    '''
784
    def showImageSelectionMessageBox(self):
785
        QMessageBox.about(self.graphicsView, "알림", "이미지를 선택하신 후 시도해주세요.")
786
        
787
    '''
788
        @brief  change selected lines' type by selected line type
789
        @author humkyung
790
        @date   2018.06.27
791
    '''
792
    def onLineTypeChanged(self, param):
793
        lineType = self.lineComboBox.itemText(param)
794
        selected = [item for item in self.graphicsView.scene.selectedItems() if type(item) is QEngineeringLineItem]
795
        if selected:
796
            for item in selected:
797
                item.lineType = lineType
798

    
799
    '''
800
        @brief      Open image drawing file and then display it
801
        @author     humkyung
802
        @date       2018.??.??
803
        @history    18.04.23 Jeongwoo    Add AppDocData.instance().setCurrentPidSource
804
                    18.04.23 Jeongwoo    Add Store Set Current Pid Image on AppDocData
805
                    18.05.02 Jeongwoo    Add useDefaultCommand()
806
                    humkyung 2018.05.24 load recognition result file if exists
807
                    Jeongwoo 2018.05.29 load data on xml if xml file exist
808
                    humkyung 2018.08.22 clear scene before loading xml file
809
    '''
810
    def onOpenImageDrawing(self, path=None):
811
        from Drawing import Drawing
812

    
813
        try:
814
            appDocData = AppDocData.instance()
815
            project = appDocData.getCurrentProject()
816
            
817
            for item in self.graphicsView.scene.items():
818
                self.graphicsView.scene.removeItem(item)
819

    
820
            self.path = self.graphicsView.loadImageFromFile(project.getDrawingFilePath(), path if type(path) is str else '')
821
            if os.path.isfile(self.path):
822
                appDocData.clear()
823
                self.graphicsView.useDefaultCommand()
824

    
825
                appDocData.setImgFilePath(self.path)
826
                appDocData.activeDrawing = Drawing(appDocData.imgName)
827
                appDocData.setCurrentPidSource(Image.open(self.path))
828
                self.resultTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
829

    
830
                ## Load data on xml
831
                path = os.path.join(appDocData.getCurrentProject().getTempPath(), appDocData.imgName + '.xml')
832
                if os.path.isfile(path):
833
                    try:
834
                        self.progress = QProgressDialog("잠시만 기다려주세요", "Cancel", 0, 100, self) if not hasattr(self, 'progress') else self.progress
835
                        self.progress.setWindowModality(Qt.WindowModal)
836
                        self.progress.setAutoReset(True)
837
                        self.progress.setAutoClose(True)
838
                        self.progress.setMinimum(0)
839
                        self.progress.resize(600,100)
840
                        self.progress.setWindowTitle("파일 읽는 중...")
841
                        self.progress.show()
842

    
843
                        self.loadRecognitionResultFromXml(path)
844
                        self.checkAttribute()
845
                    finally:
846
                        self.progress.setValue(self.progress.maximum())
847
                        self.progress.hide()
848
        except Exception as ex:
849
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
850
            self.addMessage.emit(MessageType.Error, message)
851

    
852
        return self.path
853

    
854
    '''
855
        @brief  visible/invisible image drawing
856
        @author humkyung
857
        @date   2018.06.25
858
    '''
859
    def onViewImageDrawing(self, isChecked):
860
        for item in self.graphicsView.scene.items():
861
            if type(item) is QGraphicsPixmapItem:
862
                item.setVisible(isChecked)
863
                break
864

    
865
    '''
866
        @brief  visible/invisible Text 
867
        @author humkyung
868
        @date   2018.06.28
869
    '''
870
    def onViewText(self, isChecked):
871
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
872
        for item in selected:
873
            item.setVisible(isChecked)
874

    
875
    '''
876
        @brief  visible/invisible Symbol 
877
        @author humkyung
878
        @date   2018.06.28
879
    '''
880
    def onViewSymbol(self, isChecked):
881
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem)]
882
        for item in selected:
883
            item.setVisible(isChecked)
884

    
885
    '''
886
        @brief  visible/invisible Line
887
        @author humkyung
888
        @date   2018.06.28
889
    '''
890
    def onViewLine(self, isChecked):
891
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem]
892
        for item in selected:
893
            item.setVisible(isChecked)
894

    
895
    '''
896
        @brief  visible/invisible Unknown 
897
        @author humkyung
898
        @date   2018.06.28
899
    '''
900
    def onViewUnknown(self, isChecked):
901
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
902
        for item in selected:
903
            item.setVisible(isChecked)
904

    
905
    '''
906
        @brief  create a symbol
907
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
908
                                            Add SymbolSvgItem
909
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
910
                                            Change method to make svg and image path
911
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
912
    '''
913
    def onCreateSymbolClicked(self):
914
        cmd = FenceCommand.FenceCommand(self.graphicsView)
915
        cmd.onSuccess.connect(self.onAreaSelected)
916
        self.graphicsView.command = cmd
917
        QApplication.setOverrideCursor(Qt.CrossCursor)
918

    
919
    '''
920
        @brief      show SymbolEditorDialog with image selected by user
921
        @author     humkyung
922
        @date       2018.07.20
923
    '''
924
    def onAreaSelected(self, x, y, width, height):
925
        try:
926
            image = self.graphicsView.image()
927
            if image is not None:
928
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height), AppDocData.instance().getCurrentProject())
929
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
930
                self.dirTreeWidget.initDirTreeWidget()
931
                if isAccepted:
932
                    if isImmediateInsert:
933
                        svgPath = newSym.getSvgFileFullPath()
934
                        img = cv2.imread(newSym.getImageFileFullPath(), 1)
935
                        w, h = (0, 0)
936
                        if len(img.shape[::-1]) == 2:
937
                            w, h = img.shape[::-1]
938
                        else:
939
                            _chan, w, h = img.shape[::-1]
940
                        svg = SymbolSvgItem(svgPath)
941
                        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)
942

    
943
                        svg.transfer.onRemoved.connect(self.resultTreeWidget.itemRemoved)
944
                        svg.addSvgItemToScene(self.graphicsView.scene)
945
                        for connector in svg.connectors:
946
                            self.graphicsView.scene.addItem(connector)
947
        finally:
948
            self.graphicsView.useDefaultCommand()
949
            QApplication.restoreOverrideCursor()
950
    
951
    '''
952
        @brief      create a line
953
        @author     humkyung
954
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
955
    '''
956
    def onPlaceLine(self):        
957
        if not self.graphicsView.hasImage():
958
            self.actionLine.setChecked(False)
959
            self.showImageSelectionMessageBox()
960
            return
961

    
962
        self.actionLine.setChecked(True)
963
        if not hasattr(self.actionLine, 'tag'):
964
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
965
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
966
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
967

    
968
        self.graphicsView.command = self.actionLine.tag
969

    
970
    '''
971
        @brief      add created lines to scene
972
        @author     humkyung
973
        @date       2018.07.23
974
    '''
975
    def onLineCreated(self):
976
        from EngineeringConnectorItem import QEngineeringConnectorItem
977

    
978
        try:
979
            count = len(self.actionLine.tag._polyline._vertices)
980
            if count > 1:
981
                items = []
982

    
983
                lineType = self.lineComboBox.currentText()
984
                for index in range(count - 1):
985
                    start = self.actionLine.tag._polyline._vertices[index]
986
                    end  = self.actionLine.tag._polyline._vertices[index + 1]
987
                    
988
                    lineItem = QEngineeringLineItem(vertices=[start, end])
989
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
990
                    lineItem.lineType = lineType
991
                    if items:
992
                        lineItem.connectIfPossible(items[-1], 5)
993
                    else:
994
                        pt = lineItem.startPoint()
995
                        selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
996
                        if selected is not None and type(selected) is QEngineeringConnectorItem:
997
                            lineItem.connectIfPossible(selected.parent, 5)
998
                    
999
                    items.append(lineItem)
1000
                    self.graphicsView.scene.addItem(lineItem)
1001

    
1002
                pt = items[-1].endPoint()
1003
                selected = self.graphicsView.scene.itemAt(QPointF(pt[0], pt[1]), QTransform())
1004
                if selected is not None and type(selected) is QEngineeringConnectorItem:
1005
                    items[-1].connectIfPossible(selected.parent, 5)
1006
        finally:
1007
            self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1008
            self.actionLine.tag.reset()
1009

    
1010
    '''
1011
        @brief      refresh scene
1012
        @author     humkyung
1013
        @date       2018.07.23
1014
    '''
1015
    def onCommandRejected(self, cmd):
1016
        try:
1017
            if type(cmd) is PlaceLineCommand.PlaceLineCommand:
1018
                self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1019
                self.graphicsView.scene.update()
1020
                self.actionLine.tag.reset()
1021

    
1022
                self.actionLine.setChecked(False)
1023
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
1024
                self.actionZoom.setChecked(False)
1025
            elif type(cmd) is AreaOcrCommand.AreaOcrCommand:
1026
                self.actionOCR.setChecked(False)
1027
        finally:
1028
            self.graphicsView.useDefaultCommand()
1029
     
1030
    '''
1031
        @brief      restore to default command when user press Escape key
1032
        @author     humkyung 
1033
        @date       2018.08.09
1034
    '''
1035
    def keyPressEvent(self, event):
1036
        try:
1037
            if event.key() == Qt.Key_Escape:
1038
                checked = self.actionGroup.checkedAction()
1039
                if checked:
1040
                    checked.setChecked(False)
1041
                    self.graphicsView.useDefaultCommand()
1042

    
1043
            QMainWindow.keyPressEvent(self, event)
1044
        except Exception as ex:
1045
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1046
            self.addMessage.emit(MessageType.Error, message)
1047
       
1048
    '''
1049
        @brief      recognize symbol and text
1050
        @author     humkyung
1051
        @date       2018.04.??
1052
        @history    2018.04.16  humkyung    execute line no tracing
1053
                    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
1054
                    2018.05.25  Jeongwoo    Add parameter on QRecognitionDialog.__init__() and Move thread to QRecognitionDialog
1055
                                            Remove codes below if self.dlg.isAccepted == True
1056
                    2018.05.29  Jeongwoo    Remove connects and comments
1057
    '''
1058
    def recognize(self, MainWindow):
1059
        from RecognitionDialog import QRecognitionDialog
1060

    
1061
        if not self.graphicsView.hasImage():
1062
            self.showImageSelectionMessageBox()
1063
            return
1064

    
1065
        try:
1066
            self.removedItems['LINE'] = []
1067
            self.removedItems['EQUIP'] = []
1068
            self.removedItems['INST'] = []
1069
            self.removedItems['NOTE'] = []
1070

    
1071
            appDocData = AppDocData.instance()
1072
            self.resultTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
1073
            ## up to here
1074

    
1075
            self.onClearLog()
1076
            self.dlg = QRecognitionDialog(self, self.path)
1077
            self.dlg.exec_()
1078
            if self.dlg.isAccepted == True:
1079
                '''DO NOTHING'''
1080
        except Exception as ex:
1081
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1082
            self.addMessage.emit(MessageType.Error, message)
1083

    
1084
    '''
1085
        @brief      remove item from tree widget and then remove from scene
1086
        @date       2018.05.25
1087
        @author     Jeongwoo
1088
    '''
1089
    def itemRemoved(self, item):
1090
        try:
1091
            self.resultTreeWidget.itemRemoved(item)
1092

    
1093
            if type(item) is QEngineeringLineNoTextItem:
1094
                self.removedItems['LINE'].append(str(item.uid))
1095
            elif type(item) is QEngineeringInstrumentItem:
1096
                self.removedItems['INST'].append(str(item.uid))
1097
            elif type(item) is QEngineeringEquipmentItem:
1098
                self.removedItems['EQUIP'].append(str(item.uid))
1099
            elif type(item) is QEngineeringNoteItem:
1100
                self.removedItems['NOTE'].append(str(item.uid))
1101

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

    
1107
    '''
1108
        @brief      recognize line
1109
        @author     humkyung
1110
        @date       2018.04.19
1111
        @history    Jeongwoo 2018.04.26 Variable name changed (texts → lineNos)
1112
                                        TextItem type changed (QEngineeringTextItem → QEngineeringLineNoTextItem)
1113
                    humkyung 2018.04.26 remove small objects before recognizing line
1114
                    Jeongwoo 2018.05.02 Show MessageBox when imageviewer doesn't have image
1115
                    Jeongwoo 2018.05.25 Move codes about LineDetector
1116
                    humkyung 2018.06.17 show progress dialog
1117
    '''
1118
    def recognizeLine(self, MainWindow):
1119
        from LineNoTracer import LineNoTracer
1120
        from ConnectAttrDialog import QConnectAttrDialog
1121

    
1122
        if not self.graphicsView.hasImage():
1123
            self.showImageSelectionMessageBox()
1124
            return
1125

    
1126
        try:
1127
            self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView)
1128
            self.dlgConnectAttr.exec_()
1129

    
1130
            self.resultTreeWidget.InitLineNoItems()
1131

    
1132
            # construct line no item
1133
            docData = AppDocData.instance()
1134
            for lineno in docData.lineNos:
1135
                item = self.resultTreeWidget.addTreeItem(self.resultTreeWidget.root, lineno)
1136
                connectedItems = lineno.getConnectedItems()
1137
                for connectedItem in connectedItems:
1138
                    if issubclass(type(connectedItem), SymbolSvgItem): 
1139
                        self.resultTreeWidget.addTreeItem(item, connectedItem)
1140
            # up to here
1141
        except Exception as ex:
1142
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1143
            self.addMessage.emit(MessageType.Error, message)
1144

    
1145
    '''
1146
        @history    2018.05.25  Jeongwoo    Moved from MainWindow
1147
                                            SvgItem and TextItem Connect with method in this class
1148
                                            Change method to add GraphicsItem
1149
                    2018.05.28  Jeongwoo    Make QGraphicsItem by symbol, text object. Not xml
1150
                    2018.05.29  Jeongwoo    Change method name and Moved from QRecognitionDialog
1151
                    2018.05.30  Jeongwoo    Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol)
1152
                                            Change Method name and seperate each item
1153
                    humkyung 2018.06.11     display difference between original and recognized image
1154
                    Jeongwoo 2018.06.18     Update Scene after all item added
1155
    '''
1156
    def drawDetectedItems(self, symbolList, textInfoList, otherTextInfoList):
1157
        QApplication.processEvents()
1158
        self.drawDetectedSymbolItem(symbolList)
1159
        QApplication.processEvents()
1160
        self.drawDetectedTextItem(textInfoList)
1161
        QApplication.processEvents()
1162
        self.drawDetectedOtherTextItem(otherTextInfoList)
1163

    
1164
        # Update Scene
1165
        self.graphicsView.scene.update(self.graphicsView.sceneRect())
1166

    
1167
    '''
1168
        @brief      
1169
        @author     humkyung
1170
        @date       2018.08.23
1171
    '''
1172
    def drawDetectedLines(self, lineList, worker):
1173
        area = AppDocData.instance().getArea('Drawing')
1174

    
1175
        lines = []
1176
        for pts in lineList:
1177
            processLine = QEngineeringLineItem(vertices=[(area.x + param[0], area.y + param[1]) for param in pts])
1178
            processLine.area = 'Drawing'
1179
            self.graphicsView.scene.addItem(processLine)
1180
            lines.append(processLine)
1181

    
1182
            if processLine.length() > 100: # TODO: check critical length
1183
                processLine.addFlowArrow()
1184
        
1185
        # re-order process line's start,end according to flow mark
1186
        #worker.arrangeLinePosition(lines, symbols, listWidget)
1187
        # up to here
1188

    
1189
    '''
1190
        history    humkyung 2018.06.09 check length of original and connection point is 2 while parsing
1191
    '''
1192
    def drawDetectedSymbolItem(self, symbolList):
1193
        from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
1194
        from SymbolSvgItem import SymbolSvgItem
1195
        import math
1196

    
1197
        try:
1198
            project = AppDocData.instance().getCurrentProject()
1199

    
1200
            searchedMap = []
1201
            for symbol in symbolList:
1202
                pt = [float(x) for x in symbol.getSp()]
1203
                size = [symbol.getWidth(), symbol.getHeight()]
1204
                name = symbol.getName()
1205
                angle = round(math.radians(symbol.getRotatedAngle()), 2)
1206
                _type = symbol.getType()
1207
                origin = [0,0]
1208
                if 2 == len(symbol.getOriginalPoint().split(',')):
1209
                    tokens = symbol.getOriginalPoint().split(',')
1210
                    origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
1211
                connPts = []
1212
                if symbol.getConnectionPoint() is not None:
1213
                    connPts = [(param.split(',')[0], pt[0] + float(param.split(',')[1]), pt[1] + float(param.split(',')[2])) for param in symbol.getConnectionPoint().split('/') if 3 == len(param.split(','))]
1214
                parentSymbol = symbol.getBaseSymbol()
1215
                childSymbol = symbol.getAdditionalSymbol()
1216
                hasInstrumentLabel = symbol.getHasInstrumentLabel()
1217

    
1218
                svgFilePath = os.path.join(project.getSvgFilePath(), _type, name + '.svg')
1219
                if os.path.isfile(svgFilePath):
1220
                    svg = SymbolSvgItem.createItem(_type, svgFilePath)
1221
                    svg.buildItem(name, _type, angle, pt, size, origin, connPts, parentSymbol, childSymbol, hasInstrumentLabel)
1222
                    svg.reCalculationRotatedItem()
1223
                    svg.area = 'Drawing'
1224

    
1225
                    # set owner - 2018.07.20 added by humkyung                   
1226
                    matches = [searched for searched in searchedMap if searched[0] == symbol.owner]
1227
                    if len(matches) == 1:
1228
                        svg.owner = matches[0][1]
1229
                    searchedMap.append((symbol, svg))
1230
                    # up to here
1231

    
1232
                    svg.transfer.onRemoved.connect(self.itemRemoved)
1233
                    self.addSvgItemToScene(svg)
1234
                    
1235
                    # Equipment Item 경우 저장
1236
                    if type(svg) is QEngineeringEquipmentItem:
1237
                        svg.saveEquipData()
1238

    
1239
                    # Instrument Item 경우 저장
1240
                    if type(svg) is QEngineeringInstrumentItem:
1241
                        svg.saveInstData()
1242
                else:
1243
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
1244
                    item.isSymbol = True
1245
                    item.angle = angle
1246
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
1247
                    self.graphicsView.scene.addItem(item)
1248
            # up to here
1249
        except Exception as ex:
1250
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1251
            self.addMessage.emit(MessageType.Error, message)
1252

    
1253
    '''
1254
        @history    2018.06.08  Jeongwoo    Add parameter on round method
1255
    '''
1256
    def drawDetectedTextItem(self, textInfoList):
1257
        from TextItemFactory import TextItemFactory
1258
        import math
1259

    
1260
        try:
1261
            appDocData = AppDocData.instance()
1262

    
1263
            # parse texts
1264
            for textInfo in textInfoList:
1265
                x = textInfo.getX()
1266
                y = textInfo.getY()
1267
                width = textInfo.getW()
1268
                height = textInfo.getH()
1269
                angle = round(math.radians(textInfo.getAngle()), 2)
1270
                text = textInfo.getText()
1271
                item = TextItemFactory.instance().createTextItem(text)
1272

    
1273
                if item is not None:
1274
                    item.loc = (x, y)
1275
                    item.size = (width, height)
1276
                    item.angle = angle
1277
                    item.setPlainText(text)
1278
                    item.area = 'Drawing'
1279
                    item.transfer.onRemoved.connect(self.itemRemoved)
1280
                    self.addTextItemToScene(item)
1281
                    appDocData.texts.append(item)
1282

    
1283
                    # Line No Text Item 경우 저장
1284
                    if type(item) is QEngineeringLineNoTextItem:
1285
                        item.saveLineData()
1286
                    #sung
1287
                    #if type(item) is QEngineeringNoteItem:
1288
                    #    item.saveNoteData()
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      draw detected texts except which in drawing area
1295
    '''
1296
    def drawDetectedOtherTextItem(self, otherTextInfoList):
1297
        from TextItemFactory import TextItemFactory
1298
        import math
1299

    
1300
        try:
1301
            appDocData = AppDocData.instance()
1302

    
1303
            # parse notes
1304
            for textInfoMap in otherTextInfoList:
1305
                if textInfoMap[0]=='Note':
1306
                    pass
1307

    
1308
                for textInfo in textInfoMap[1]:
1309
                    x = textInfo.getX()
1310
                    y = textInfo.getY()
1311
                    width = textInfo.getW()
1312
                    height = textInfo.getH()
1313
                    angle = round(math.radians(textInfo.getAngle()))
1314
                    text = textInfo.getText()
1315

    
1316
                    item = TextItemFactory.instance().createTextItem(text)
1317

    
1318
                    item.loc = (x, y)
1319
                    item.size = (width, height)
1320
                    item.angle = angle
1321
                    item.setPlainText(text)
1322
                    item.area = textInfoMap[0]
1323
                    self.addTextItemToScene(item)
1324
                    appDocData.texts.append(item)
1325

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

    
1330

    
1331
    '''
1332
        @brief  draw unknown items 
1333
        @author humkyung
1334
        @date   2018.06.12
1335
        @history    2018.06.14  Jeongwoo    Change method to add unknown item
1336
                    2018.06.18  Jeongwoo    Add connect on unknown item
1337
                                            Add [transfer] for using pyqtSignal
1338
    '''
1339
    def drawUnknownItems(self):
1340
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem 
1341
        from EngineeringLineItem import QEngineeringLineItem
1342
        from EngineeringUnknownItem import QEngineeringUnknownItem
1343

    
1344
        try:
1345
            docData = AppDocData.instance()
1346
            project = docData.getCurrentProject()
1347
            windowSize = docData.getSlidingWindowSize()
1348
            thickness = int(windowSize[1])
1349

    
1350
            diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(self.path))
1351
            if os.path.isfile(diffFilePath):
1352
                imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1]
1353

    
1354
                ## remove line
1355
                lines = [item for item in self.graphicsView.scene.items() if (type(item) is QEngineeringLineItem)]
1356
                for line in lines:
1357
                    line.drawToImage(imgDiff, 255, thickness)
1358
                cv2.imwrite(diffFilePath, imgDiff)
1359
                ## up to here
1360

    
1361
                imgNot = np.ones(imgDiff.shape, np.uint8)
1362
                cv2.bitwise_not(imgDiff, imgNot)
1363
                imgNot = cv2.dilate(imgNot, np.ones((8,8), np.uint8))
1364

    
1365
                diffItems = []
1366

    
1367
                image, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
1368
                for contour in contours:
1369
                    [x, y, w, h] = cv2.boundingRect(contour)
1370

    
1371
                    # remove too small one
1372
                    if (w < 10 or h < 10): continue
1373

    
1374
                    '''
1375
                    rect = QRectF(x, y, w, h)
1376
                    items = [item for item in diffItems if item.boundingRect().contains(rect)]
1377
                    if len(items) > 0: continue
1378
                    
1379
                    items = [item for item in diffItems if rect.contains(item.boundingRect())]
1380
                    for item in items:
1381
                        diffItems.remove(item)
1382
                    '''
1383

    
1384
                    # create unknown item
1385
                    epsilon = cv2.arcLength(contour, True)*0.001
1386
                    approx = cv2.approxPolyDP(contour, epsilon, True)
1387
                    approx = [pt[0] for pt in approx]
1388
                    item = QEngineeringUnknownItem(approx)
1389
                    item.ara = 'Drawing'
1390
                    diffItems.append(item)
1391
                    # up to here
1392

    
1393
                for item in diffItems:
1394
                    item.transfer.onRemoved.connect(self.itemRemoved)
1395
                    self.addUnknownItemToScene(item)
1396

    
1397
                notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(self.path))
1398
                cv2.imwrite(notFilePath, imgNot)
1399
            else:
1400
                message = 'can\'t found {}'.format(diffFilePath)
1401
                self.addMessage.emit(MessageType.Normal, message)
1402
        except Exception as ex:
1403
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1404
            self.addMessage.emit(MessageType.Error, message)
1405

    
1406
    '''
1407
        @brief      load recognition result
1408
        @author     humkyung
1409
        @date       2018.04.??
1410
        @history    humkyung 2018.01.12 parse originalpoint and connectionpoint
1411
                    Jeongwoo 2018.04.17 add QGraphicItem with Rotated text
1412
                    Jeongwoo 2018.04.23 Change to Draw texts on QEngineeringTextItem
1413
                    humkyung 2018.04.23 connect item remove slot to result tree
1414
                    Jeongwoo 2018.04.25 Add if state with QEngineeringNoteItem
1415
                    Jeongwoo 2018.04.26 Change method to create TextItem object with TextItemFactory
1416
                    Jeongwoo 2018.05.03 Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1417
                    Jeongwoo 2018.05.29 Change method name / Change method to add item / Add Line item
1418
                    Jeongwoo 2018.05.30 Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol) / Change method name / Change XML NODE NAMES
1419
                    Jeongwoo 2018.06.12 Add LineNoTextItem from LINE_NO
1420
                    Jeongwoo 2018.06.14 Add UnknownItem from UNKNOWN
1421
                    Jeongwoo 2018.06.18 Update Scene after all item added
1422
                                        Add connect on unknown item
1423
                                        Add [transfer] for using pyqtSignal
1424
                    kyouho  2018.07.12  Add line property logic
1425
                    humkyung 2018.08.22 show progress while loading xml file
1426
    '''
1427
    def loadRecognitionResultFromXml(self, xmlPath):
1428
        docData = AppDocData.instance()
1429
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
1430
        from EngineeringRunItem import QEngineeringRunItem
1431
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
1432

    
1433
        try:
1434
            symbols = []
1435

    
1436
            xml = parse(xmlPath)
1437
            root = xml.getroot()
1438
            
1439
            maxValue = 0
1440
            maxValue = maxValue + len(list(root.iter('SYMBOL')))
1441
            maxValue = maxValue + len(list(root.iter('ATTRIBUTE')))
1442
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
1443
            maxValue = maxValue + len(list(root.iter('LINE')))
1444
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
1445
            self.progress.setMaximum(maxValue)
1446

    
1447
            for symbol in root.find('SYMBOLS').iter('SYMBOL'):
1448
                item = SymbolSvgItem.fromXml(symbol)
1449
                if item[0] is not None:
1450
                    item[0].transfer.onRemoved.connect(self.itemRemoved)
1451
                    symbols.append(item)
1452
                else:
1453
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
1454
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
1455
                    angle = float(symbol.find('ANGLE').text)
1456
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
1457
                    item.isSymbol = True
1458
                    item.angle = angle
1459
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
1460
                    self.graphicsView.scene.addItem(item)
1461

    
1462
                self.progress.setValue(self.progress.value() + 1)
1463
                
1464
            QApplication.processEvents()
1465

    
1466
            # set symbol's owner
1467
            childItems = [item for item in symbols if item[1] is not None]
1468
            for item in childItems:
1469
                matches = [param for param in symbols if str(param[0].uid) == item[1]]
1470
                if len(matches) == 1:
1471
                    item[0].owner = matches[0][0]
1472
            # up to here
1473
           
1474
            for item in symbols:
1475
                self.addSvgItemToScene(item[0])
1476

    
1477
            # parse texts
1478
            for text in root.iter('ATTRIBUTE'):
1479
                item = QEngineeringTextItem.fromXml(text)
1480
                if item is not None:
1481
                    uid = text.find('UID')
1482
                    attributeValue = text.find('ATTRIBUTEVALUE')
1483
                    name = text.find('NAME').text
1484
                    item.transfer.onRemoved.connect(self.itemRemoved)
1485
                    self.addTextItemToScene(item)
1486

    
1487
                    if name == 'TEXT':
1488
                        if uid is not None and attributeValue is not None:
1489
                            item.uid = uid.text
1490
                            item.attribute = attributeValue.text
1491
                    elif name == 'NOTE':
1492
                        if uid is not None:
1493
                            item.uid = uid.text
1494

    
1495
                self.progress.setValue(self.progress.value() + 1)
1496
                
1497
            QApplication.processEvents()
1498

    
1499
            for line in root.find('LINEINFOS').iter('LINE'):
1500
                item = QEngineeringLineItem.fromXml(line)
1501
                item.transfer.onRemoved.connect(self.itemRemoved)
1502
                if item: self.addLineItemToScene(item)
1503

    
1504
                self.progress.setValue(self.progress.value() + 1)
1505
                
1506
            QApplication.processEvents()
1507

    
1508
            for unknown in root.iter('UNKNOWN'):
1509
                item = QEngineeringUnknownItem.fromXml(unknown)
1510
                item.transfer.onRemoved.connect(self.itemRemoved)
1511
                if item is not None:
1512
                    item.transfer.onRemoved.connect(self.itemRemoved)
1513
                    self.addUnknownItemToScene(item)
1514

    
1515
                self.progress.setValue(self.progress.value() + 1)
1516
                
1517
            QApplication.processEvents()
1518

    
1519
            for lineNo in root.iter('LINE_NO'):
1520
                location = lineNo.find('LOCATION').text if lineNo.find('LOCATION') is not None else '0,0'
1521
                x = float(location.split(',')[0])
1522
                y = float(location.split(',')[1])
1523
                width = float(lineNo.find('WIDTH').text) if lineNo.find('WIDTH') is not None else 0
1524
                height = float(lineNo.find('HEIGHT').text) if lineNo.find('HEIGHT') is not None else 0
1525
                angle = float(lineNo.find('ANGLE').text) if lineNo.find('ANGLE') is not None else 0
1526
                text = lineNo.find('TEXT').text
1527

    
1528
                item = TextItemFactory.instance().createTextItem(text)
1529
                if item is not None:
1530
                    item.loc = (x, y)
1531
                    item.size = (width, height)
1532
                    item.angle = angle
1533
                    item.setPlainText(text)
1534
                    item.transfer.onRemoved.connect(self.itemRemoved)
1535
                    self.addTextItemToScene(item)
1536

    
1537
                    # attr
1538
                    for userInputAttr in lineNo.iter('USERINPUTATTRIBUTE'):
1539
                        newAttr = UserInputAttribute(userInputAttr.find('TYPEUID').text, userInputAttr.find('TYPEVALUE').text)
1540
                        item.attrs.append(newAttr)
1541
                    for attr in lineNo.iter('ATTRIBUTE'):
1542
                        item.attrs[docData.getLinePropertiesByUID(attr.find('UID').text)[0]] = attr.find('VALUE').text
1543

    
1544
                connLine = lineNo.find('CONNLINE')
1545
                if connLine is not None:
1546
                    lineUID = connLine.text
1547
                    connLine = self.graphicsView.findItemByUid(lineUID)
1548
                    if connLine is not None:
1549
                        item.conns.append(connLine)
1550

    
1551
                run = lineNo.find('RUN')
1552
                if run is not None:
1553
                    lineRunItem = QEngineeringRunItem()
1554
                    for child in run:
1555
                        uidElement = child.find('UID')
1556
                        if uidElement is not None:
1557
                            uid = uidElement.text
1558
                            runItem = self.graphicsView.findItemByUid(uid)
1559
                            if runItem is not None:
1560
                                lineRunItem.items.append(runItem)
1561

    
1562
                    item.runs.append(lineRunItem)
1563
                    treeItem = self.resultTreeWidget.addTreeItem(self.resultTreeWidget.root, item)
1564
                    for connectedItem in lineRunItem.items:
1565
                        if issubclass(type(connectedItem), SymbolSvgItem): self.resultTreeWidget.addTreeItem(treeItem, connectedItem)
1566
                    docData.lineNos.append(item)
1567

    
1568
                self.progress.setValue(self.progress.value() + 1)
1569
            QApplication.processEvents()
1570

    
1571
            for trimLineNo in root.iter('TRIM_LINE_NO'):
1572
                item = QEngineeringTrimLineNoTextItem()
1573
                item.uid = trimLineNo.find('UID')
1574

    
1575
                run = trimLineNo.find('RUN')
1576
                if run is not None:
1577
                    lineRunItem = QEngineeringRunItem()
1578
                    for child in run:
1579
                        uidElement = child.find('UID')
1580
                        if uidElement is not None:
1581
                            uid = uidElement.text
1582
                            runItem = self.graphicsView.findItemByUid(uid)
1583
                            if runItem is not None:
1584
                                lineRunItem.items.append(runItem)
1585

    
1586
                    item.runs.append(lineRunItem)
1587
                    treeItem = self.resultTreeWidget.addTreeItem(self.resultTreeWidget.root, item)
1588
                    for connectedItem in lineRunItem.items:
1589
                        if issubclass(type(connectedItem), SymbolSvgItem): self.resultTreeWidget.addTreeItem(treeItem, connectedItem)
1590
                    docData.lineNos.append(item)
1591
            # up to here
1592

    
1593
            # set symbol's connectItem
1594
            from EngineeringConnectorItem import QEngineeringConnectorItem
1595
            connectors = [item for item in self.graphicsView.scene.items() if type(item) == QEngineeringConnectorItem and item.connectedItem is not None]
1596
            for connector in connectors:
1597
                # 처음에는 UID가 connectedItem에 String으로 들어가있기 때문에
1598
                connector.connectedItem = self.graphicsView.findItemByUid(connector.connectedItem)
1599

    
1600
            symbols = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and len(item.attrs) > 0]
1601
            for symbol in symbols:
1602
                # 처음에는 attrs의 uid가 connectedItem에 String으로 들어가있기 때문에
1603
                for index in range(len(symbol.attrs)):
1604
                    if type(symbol.attrs[index]) is not UserInputAttribute and type(symbol.attrs[index]) is not tuple:
1605
                        symbol.attrs[index] = self.graphicsView.findItemByUid(symbol.attrs[index])
1606
                        
1607
            # Update Scene
1608
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1609

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

    
1614
    '''
1615
        @brief      Remove added item on same place and Add GraphicsItem
1616
        @author     Jeongwoo
1617
        @date       2018.05.25
1618
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
1619
                    2018.06.18  Jeongwoo    Set Z-index
1620
    '''
1621
    def addSvgItemToScene(self, svgItem):
1622
        svgItem.addSvgItemToScene(self.graphicsView.scene)
1623
        
1624
    '''
1625
        @brief      Remove added item on same place and Add GraphicsItem
1626
        @author     Jeongwoo
1627
        @date       2018.05.25
1628
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
1629
                    2018.06.05  Jeongwoo    Remove Size condition
1630
                    2018.06.18  Jeongwoo    Set Z-index
1631
    '''
1632
    def addTextItemToScene(self, textItem):
1633
        textItem.addTextItemToScene(self.graphicsView.scene)
1634
        
1635
    '''
1636
        @brief      Remove added item on same place and Add GraphicsItem
1637
        @author     Jeongwoo
1638
        @date       2018.05.29
1639
        @history    2018.06.18  Jeongwoo    Set Z-index
1640
    '''
1641
    def addLineItemToScene(self, lineItem):
1642
        lineItem.addLineItemToScene(self.graphicsView.scene)
1643

    
1644
    '''
1645
        @brief      Remove added item on same place and Add Unknown Item
1646
        @author     Jeongwoo
1647
        @date       2018.06.14
1648
        @history    2018.06.18  Jeongwoo    Set Z-index
1649
    '''
1650
    def addUnknownItemToScene(self, unknownItem):
1651
        try:
1652
            unknownItem.addUnknownItemToScene(self.graphicsView.scene)
1653
        except Exception as ex:
1654
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1655
            self.addMessage.emit(MessageType.Error, message)
1656

    
1657
    '''
1658
        @brief      generate output xml file
1659
        @author     humkyung
1660
        @date       2018.04.23
1661
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
1662
    '''
1663
    def generateOutput(self):
1664
        import XmlGenerator as xg
1665

    
1666
        if not self.graphicsView.hasImage():
1667
            self.showImageSelectionMessageBox()
1668
            return
1669

    
1670
        try:
1671
            appDocData = AppDocData.instance()
1672

    
1673
            ## collect items
1674
            appDocData.lines.clear()
1675
            appDocData.lines = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem and item.owner is None]
1676

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

    
1680
            appDocData.equipments.clear()
1681
            for item in self.graphicsView.scene.items():
1682
                if type(item) is QEngineeringEquipmentItem:
1683
                    appDocData.equipments.append(item)
1684

    
1685
            appDocData.texts.clear()
1686
            appDocData.texts = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem) and type(item) is not QEngineeringLineNoTextItem]
1687
            ## up to here
1688

    
1689
            appDocData.imgOutput = np.ones((appDocData.imgHeight, appDocData.imgWidth), np.uint8)*255
1690
            xg.writeOutputXml(appDocData.imgName, appDocData.imgWidth, appDocData.imgHeight) # TODO: check
1691
            project = appDocData.getCurrentProject()
1692
            cv2.imwrite(os.path.join(project.getTempPath() , 'OUTPUT.png') , appDocData.imgOutput)
1693
        except Exception as ex:
1694
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1695
            self.addMessage.emit(MessageType.Error, message)
1696

    
1697
    '''
1698
        @brief      resetting attribute at secne
1699
        @author     kyoyho
1700
        @date       2018.08.21
1701
    '''
1702
    def checkAttribute(self):
1703
        try:
1704

    
1705
            docData = AppDocData.instance()
1706
            if not self.graphicsView.hasImage():
1707
                return
1708

    
1709
            # symbol 경우
1710
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem)]
1711
            for item in items:
1712
                attrs = item.attrs
1713
                
1714
                removeAttrList = []
1715
                for attr in attrs:
1716
                    if type(attr) is tuple:
1717
                        continue
1718

    
1719
                    if attr is None:
1720
                        removeAttrList.append(attr)
1721
                        continue
1722

    
1723
                    attrInfo = docData.getSymbolAttributeByUID(attr.attribute)
1724
                    if attrInfo is None:
1725
                        removeAttrList.append(attr)
1726
                    # 해당 attribute가 맞는지 확인
1727
                    else:
1728
                        attrType = attrInfo[2]
1729
                        _type = type(attr)
1730
                        if attrType == 'Symbol Item':
1731
                            if not issubclass(_type, SymbolSvgItem):
1732
                                removeAttrList.append(attr)
1733
                        elif attrType == 'Text Item':
1734
                            if _type is not QEngineeringTextItem:
1735
                                removeAttrList.append(attr)
1736
                        elif attrType == 'Int':
1737
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
1738
                                removeAttrList.append(attr)
1739
                        elif attrType == 'String':
1740
                            if _type is not UserInputAttribute:
1741
                                removeAttrList.append(attr)
1742

    
1743
                for attr in removeAttrList:
1744
                    attrs.remove(attr)
1745

    
1746
            # Line No Text Item의 경우
1747
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringLineNoTextItem)]
1748
            for item in items:
1749
                attrs = item.attrs
1750
                
1751
                removeAttrList = []
1752
                for attr in attrs:
1753
                    if type(attr) is UserInputAttribute:
1754
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
1755
                        if attrInfo is None:
1756
                            removeAttrList.append(attr)
1757

    
1758
                for attr in removeAttrList:
1759
                    attrs.remove(attr)
1760

    
1761
        except Exception as ex:
1762
                message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1763
                self.addMessage.emit(MessageType.Error, message)
1764
    '''
1765
        @brief      Check Number
1766
        @author     kyouho
1767
        @date       2018.08.20
1768
    '''
1769
    def isNumber(self, num):
1770
        p = re.compile('(^[0-9]+$)')
1771
        result = p.match(num)
1772

    
1773
        if result:
1774
            return True
1775
        else:
1776
            return False
1777

    
1778
    '''
1779
        @brief      find overlap Connector
1780
        @author     kyouho
1781
        @date       2018.08.28
1782
    '''
1783
    def findOverlapConnector(self, connectorItem):
1784
        from shapely.geometry import Point
1785
        from EngineeringConnectorItem import QEngineeringConnectorItem
1786
        itemList = []
1787
        
1788
        x = connectorItem.center()[0]
1789
        y = connectorItem.center()[1]
1790

    
1791
        connectors = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringConnectorItem and item != connectorItem]
1792
        for connector in connectors:
1793
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
1794
                itemList.append(connector.parent)
1795

    
1796
        return itemList
1797

    
1798
            
1799
if __name__ == '__main__':
1800
    from ProjectDialog import Ui_Dialog
1801
    from App import App 
1802

    
1803
    app = App(sys.argv)
1804
    try:
1805
        dlg = Ui_Dialog()
1806
        selectedProject = dlg.showDialog()
1807
        if selectedProject is not None:
1808
            AppDocData.instance().setCurrentProject(selectedProject)
1809
            app._mainWnd = MainWindow.instance()
1810
            app._mainWnd.show()
1811
            sys.exit(app.exec_())
1812
    except Exception as ex:
1813
        print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
1814
    finally:
1815
        pass
클립보드 이미지 추가 (최대 크기: 500 MB)