프로젝트

일반

사용자정보

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

hytos / DTI_PID / DTI_PID / MainWindow.py @ 6067f4b2

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

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

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

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

    
20
import cv2
21
import numpy as np
22

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

    
28
from PIL import Image
29

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

    
34
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Shapes')
35
from EngineeringAbstractItem import QEngineeringAbstractItem
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 EngineeringNoteItem import QEngineeringNoteItem
43
from QEngineeringSizeTextItem import QEngineeringSizeTextItem
44
from EngineeringUnknownItem import QEngineeringUnknownItem
45
from EngineeringEquipmentItem import QEngineeringEquipmentItem
46
from EngineeringInstrumentItem import QEngineeringInstrumentItem
47
from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
48
from EngineeringErrorItem import QEngineeringErrorItem
49
from EngineeringVendorItem import QEngineeringVendorItem
50
from EngineeringEndBreakItem import QEngineeringEndBreakItem
51
from EngineeringReducerItem import QEngineeringReducerItem
52
from EngineeringFlowMarkItem import QEngineeringFlowMarkItem
53
from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
54
from AppDocData import *
55
import SymbolTreeWidget, SymbolPropertyTableWidget
56
import SymbolEditorDialog
57
import ItemTreeWidget
58
import ItemPropertyTableWidget
59
from UserInputAttribute import UserInputAttribute
60
from TextItemFactory import TextItemFactory
61
from TrainingImageListDialog import QTrainingImageListDialog
62
from TrainingSymbolImageListDialog import QTrainingSymbolImageListDialog
63
from TextDataListDialog import QTextDataListDialog
64
from ImportTextFromCADDialog import QImportTextFromCADDialog
65
from SymbolThicknessDialog import QSymbolThicknessDialog
66
from DisplayColors import DisplayColors
67
from DisplayColors import DisplayOptions
68
import uuid
69

    
70

    
71
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane):
72
    """ This is MainWindow class """
73
    addMessage = pyqtSignal(Enum, str)
74

    
75
    '''
76
        @brief      initialize
77
        @author 
78
        @date   
79
        @history    humkyung 2018.04.12 add splitter widget
80
                    Jeongwoo 2018.04.27 Add Signal/Slot Connection 'noteNoSingleClicked'
81
                    Jeongwoo 2018.05.09 Initialize Action group
82
                    Jeongwoo 2018.05.10 Add Signal/Slot Connection 'lineNoSingleClicked'
83
                                        Add QActionGroup for managing checkable action
84
                    Jeongwoo 2018.06.27 Add Action [Zoom, Fit Window] and Add new actions into ActionGroup
85
                    humkyung 2018.08.23 add labelStatus to statusbar
86
                    Euisung 2018.09.27 add OCR Training , Signal/Slot Connection 'oCRTrainingClicked'
87
                    Euisung 2018.10.05 add OCR Editor , Signal/Slot Connection 'oCRTrainingEdidorClicked'
88
                    Euisung 2018.10.22 delete Signal/Slot Connection 'oCRTrainingEdidorClicked'
89
    '''
90

    
91
    def __init__(self):
92
        from App import App
93
        from LineTypeConditions import LineTypeConditions
94

    
95
        super(self.__class__, self).__init__()
96
        self.setupUi(self)
97
        self.progress_bar = QProgressBar()
98
        self._label_mouse = QLabel(self.statusbar)
99
        self._label_mouse.setText(self.tr('mouse pos : ({},{})'.format(0, 0)))
100
        self.labelStatus = QLabel(self.statusbar)
101
        self.labelStatus.setText(self.tr('Unrecognition : '))
102
        self.labelSymbolStatus = QLabel(self.statusbar)
103
        self.labelSymbolStatus.setText(self.tr('Symbol : '))
104
        self.labelLineStatus = QLabel(self.statusbar)
105
        self.labelLineStatus.setText(self.tr('Line : '))
106
        self.labelTextStatus = QLabel(self.statusbar)
107
        self.labelTextStatus.setText(self.tr('Text : '))
108

    
109
        self.statusbar.addWidget(self._label_mouse)
110
        self.statusbar.addPermanentWidget(self.progress_bar, 1)
111
        self.statusbar.addPermanentWidget(self.labelSymbolStatus)
112
        self.statusbar.addPermanentWidget(self.labelLineStatus)
113
        self.statusbar.addPermanentWidget(self.labelTextStatus)
114
        self.statusbar.addPermanentWidget(self.labelStatus)
115

    
116
        docData = AppDocData.instance()
117
        docData.clear()
118
        project = docData.getCurrentProject()
119
        _translate = QCoreApplication.translate
120
        version = QCoreApplication.applicationVersion()
121
        # set title
122
        self.setWindowTitle(_translate(f"{App.NAME}({version}) - {project.name}",
123
                                       f"{App.NAME}({version}) - {project.name}"))
124

    
125
        self.lineComboBox = QComboBox(self.toolBar)
126
        for condition in LineTypeConditions.items():
127
            self.lineComboBox.addItem(condition.name)
128

    
129
        configs = docData.getConfigs('Line', 'Default Type')
130
        value = configs[0].value if 1 == len(configs) else ''
131
        if value:
132
            at = self.lineComboBox.findText(value)
133
            self.lineComboBox.setCurrentIndex(at)
134
        else:
135
            at = self.lineComboBox.findText('Secondary')
136
            self.lineComboBox.setCurrentIndex(at)
137
        # self.lineComboBox.currentIndexChanged.connect(self.onLineTypeChanged)
138

    
139
        self.toolBar.insertWidget(self.actionOCR, self.lineComboBox)
140
        self.toolBar.insertSeparator(self.actionOCR)
141

    
142
        self.graphicsView = QtImageViewer.QtImageViewer(self)
143
        self.graphicsView.setParent(self.centralwidget)
144
        self.graphicsView.useDefaultCommand()  # USE DEFAULT COMMAND
145
        self.graphicsView.setMouseTracking(True)
146
        self.graphicsView.viewport().installEventFilter(self)
147

    
148
        self._display_widget = QWidget()
149
        layout = QVBoxLayout()
150
        self._by_line_no = QRadioButton()
151
        self._by_line_no.setChecked(True)
152
        self._by_line_no.setText('By Group')
153
        self._by_line_no.toggled.connect(self.display_colors)
154
        layout.addWidget(self._by_line_no)
155
        self._by_line_type = QRadioButton()
156
        self._by_line_type.setText('By Type')
157
        layout.addWidget(self._by_line_type)
158
        self._display_widget.setLayout(layout)
159
        self.EditToolbar.insertWidget(None, self._display_widget)
160
        self._by_line_no.setChecked(
161
            True) if DisplayColors.instance().option == DisplayOptions.DisplayByLineNo else \
162
            self._by_line_type.setChecked(True)
163

    
164
        self.verticalLayout.addWidget(self.graphicsView)
165

    
166
        # Add Custom TreeWidget
167
        self.dirTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
168
        self.dirTreeWidget.header().hide()
169
        self.symbolTabVerticalLayout.addWidget(self.dirTreeWidget)
170

    
171
        # Add Custom Property TableWidget
172
        self.propertyTableWidget = SymbolPropertyTableWidget.QSymbolPropertyTableWidget()
173
        self.symbolTabVerticalLayout.addWidget(self.propertyTableWidget)
174
        self.dirTreeWidget.singleClicked.connect(self.propertyTableWidget.getClickedSymbol)
175
        # add splitter widget
176
        splitter = QSplitter(Qt.Vertical)
177
        splitter.addWidget(self.dirTreeWidget)
178
        splitter.addWidget(self.propertyTableWidget)
179
        self.symbolTabVerticalLayout.addWidget(splitter)
180
        # up to here
181

    
182
        # Add Custom Result Tree Widget (Symbol Explorer)
183
        self.itemTreeWidget = ItemTreeWidget.QItemTreeWidget(self.graphicsView)
184
        self.itemTreeWidget.header().hide()
185
        self.symbolExplorerVerticalLayout.addWidget(self.itemTreeWidget)
186

    
187
        # Add Empty Widget
188
        self.resultPropertyTableWidget = ItemPropertyTableWidget.QItemPropertyTableWidget(self)
189
        self.symbolExplorerVerticalLayout.addWidget(self.resultPropertyTableWidget)
190
        self.itemTreeWidget.singleClicked.connect(self.resultPropertyTableWidget.onSymbolClicked)
191
        self.itemTreeWidget.noteNoSingleClicked.connect(self.resultPropertyTableWidget.onNoteClicked)
192
        self.itemTreeWidget.lineNoSingleClicked.connect(self.resultPropertyTableWidget.onLineNoClicked)
193
        self.itemTreeWidget.drawingClicked.connect(self.resultPropertyTableWidget.onDrawingClicked)
194
        # add splitter widget
195
        splitter = QSplitter(Qt.Vertical)
196
        splitter.addWidget(self.itemTreeWidget)
197
        splitter.addWidget(self.resultPropertyTableWidget)
198
        self.symbolExplorerVerticalLayout.addWidget(splitter)
199
        # up to here
200

    
201
        # Initialize Action group
202
        self.actionGroup = QActionGroup(self)
203
        self.actionGroup.addAction(self.actionRecognition)
204
        self.actionGroup.addAction(self.actionLineRecognition)
205
        self.actionGroup.addAction(self.actionLine)
206
        self.actionGroup.addAction(self.actionGenerateOutput)
207
        self.actionGroup.addAction(self.actionOCR)
208
        self.actionGroup.addAction(self.actionZoom)
209
        self.actionGroup.addAction(self.actionFitWindow)
210
        self.actionGroup.addAction(self.actionSave)
211
        self.actionGroup.addAction(self.actionValidate)
212
        self.actionGroup.addAction(self.actionVendor)
213
        self.actionGroup.triggered.connect(self.actionGroupTriggered)
214

    
215
        # connect signals and slots
216
        self.actionClose.triggered.connect(self.close)
217
        self.actionOpen.triggered.connect(self.open_image_drawing)
218
        self.actionLine.triggered.connect(self.onPlaceLine)
219
        self.actionRecognition.triggered.connect(self.recognize)
220
        self.pushButtonBatchRecognition.clicked.connect(self.recognizeBatch)
221
        self.pushButtonRefreshDrawings.clicked.connect(self.load_drawing_list)
222
        self.actionLineRecognition.triggered.connect(self.connect_attributes)
223
        self.actionArea.triggered.connect(self.areaConfiguration)
224
        self.actionConfiguration.triggered.connect(self.configuration)
225
        self.actionOCR.triggered.connect(self.onAreaOcr)
226
        self.actionGenerateOutput.triggered.connect(self.generateOutput)
227
        self.pushButtonCreateSymbol.clicked.connect(self.onCreateSymbolClicked)
228
        self.pushButtonClearLog.clicked.connect(self.onClearLog)
229
        self.actionHMB_DATA.triggered.connect(self.onHMBData)
230
        self.actionItem_Data_List.triggered.connect(self.showItemDataList)
231
        self.actionText_Data_List.triggered.connect(self.showTextDataList)
232
        self.actionSpecialItemTypes.triggered.connect(self.on_show_special_item_types)  # show special item types dialog
233
        self.actionDataTransfer.triggered.connect(self.on_show_data_transfer)  # show data transfer dialog
234
        self.actionDataExport.triggered.connect(self.on_show_data_export)
235
        self.actionExportEqpDatasheet.triggered.connect(
236
            self.on_show_eqp_datasheet_export)  # show eqp datasheet export dialog
237
        self.actionOPCRelation.triggered.connect(self.on_show_opc_relation)  # show OPC Relation dialog
238
        self.actionCodeTable.triggered.connect(self.onShowCodeTable)
239
        self.actionCustom_Code_Table.triggered.connect(self.onShowCustomCodeTable)
240
        self.actionImage_Drawing.triggered.connect(self.onViewImageDrawing)
241
        self.actionDrawing_Only.triggered.connect(self.onViewDrawingOnly)
242
        self.actionValidate.triggered.connect(self.onValidation)
243
        self.actionViewText.triggered.connect(self.onViewText)
244
        self.actionViewSymbol.triggered.connect(self.onViewSymbol)
245
        self.actionViewLine.triggered.connect(self.onViewLine)
246
        self.actionViewUnknown.triggered.connect(self.onViewUnknown)
247
        self.actionViewInconsistency.triggered.connect(self.onViewInconsistency)
248
        self.actionViewVendor_Area.triggered.connect(self.onViewVendorArea)
249
        self.actionRotate.triggered.connect(self.onRotate)
250
        self.actionZoom.triggered.connect(self.onAreaZoom)
251
        self.actionVendor.triggered.connect(self.onVendor)
252
        self.actionFitWindow.triggered.connect(self.fitWindow)
253
        self.actionpdf_to_image.triggered.connect(self.onConvertPDFToImage)
254
        self.actionImport_Text_From_CAD.triggered.connect(self.onImportTextFromCAD)
255
        self.actionSymbol_Thickness_Reinforcement.triggered.connect(self.onSymbolThickness)
256
        self.actionHelp.triggered.connect(self.on_help)
257
        self.graphicsView.scene.selectionChanged.connect(self.onSelectionChanged)
258
        self.actionInitialize.triggered.connect(self.onInitializeScene)
259
        self.actionSave.triggered.connect(self.actionSaveCliked)
260
        self.addMessage.connect(self.onAddMessage)
261
        self.actionFindReplaceText.triggered.connect(self.findReplaceTextClicked)
262
        self.pushButtonDetectSymbol.clicked.connect(self.show_detect_symbol_dialog)
263
        # self.graphicsView.scene.contents_changed.connect(self.scene_changed)
264

    
265
        configs = docData.getAppConfigs('app', 'mode')
266
        if configs and 1 == len(configs) and 'advanced' == configs[0].value:
267
            self.actionOCR_Training.triggered.connect(self.oCRTrainingClicked)
268
            self.actionSymbol_Training.triggered.connect(self.symbolTrainingClicked)
269
        else:
270
            self.actionOCR_Training.setVisible(False)
271
            self.actionSymbol_Training.setVisible(False)
272
            self.pushButtonBatchRecognition.setVisible(False)
273
            self.pushButtonCreateSymbol.setVisible(False)
274
            self.pushButtonDetectSymbol.setVisible(False)
275

    
276
        self.delimiter = '"'
277

    
278
        self.resizeDocks({self.dockWidget}, {self.dockWidgetObjectExplorer.sizeHint().width()}, Qt.Horizontal)
279

    
280
        self.treeWidgetDrawingList.setHeaderHidden(False)
281
        self.treeWidgetDrawingList.header().setStretchLastSection(False)
282
        self.treeWidgetDrawingList.setHeaderLabels([self.tr('Name'), self.tr('DateTime')])
283
        self.treeWidgetDrawingList.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
284
        self.treeWidgetDrawingList.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
285
        self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing)
286
        self.load_drawing_list()
287

    
288
        # load stylesheet file list
289
        stylesheet_name = QtWidgets.qApp.stylesheet_name
290
        files = [os.path.splitext(file)[0] for file in os.listdir(os.path.dirname(os.path.realpath(__file__))) if
291
                 os.path.splitext(file)[1] == '.qss']
292
        for file in files:
293
            action = self.menuTheme.addAction(file)
294
            action.setCheckable(True)
295
            action.setChecked(True) if stylesheet_name == file else action.setChecked(False)
296
            action.triggered.connect(partial(self.load_stylesheet, file))
297
        # up to here
298

    
299
        # load language files
300
        language_name = QtWidgets.qApp.language_name
301
        files = ['en_us']  # englisgh is default language
302
        files.extend([os.path.splitext(file)[0] for file in
303
                      os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate')) if
304
                      os.path.splitext(file)[1] == '.qm'])
305
        for file in files:
306
            action = self.menuLanguage.addAction(file)
307
            action.setCheckable(True)
308
            action.setChecked(True) if language_name.lower() == file.lower() else action.setChecked(False)
309
            action.triggered.connect(partial(self.load_language, file))
310
        # up to here
311

    
312
        # inconsistency table
313
        self.tableWidgetInconsistency.setColumnCount(3)
314
        self.tableWidgetInconsistency.setHorizontalHeaderLabels(['Owner', 'Type', 'Message'])
315
        self.tableWidgetInconsistency.setEditTriggers(QAbstractItemView.NoEditTriggers)
316
        self.tableWidgetInconsistency.itemClicked.connect(self.inconsistencyItemClickEvent)
317
        self.tableWidgetInconsistency.keyPressEvent = self.inconsistencyTableKeyPressEvent
318
        self.tableWidgetInconsistency.setSortingEnabled(True)
319

    
320
    def eventFilter(self, source, event):
321
        """display mouse position of graphics view"""
322
        if (event.type() == QEvent.MouseMove):
323
            pos = self.graphicsView.mapToScene(event.pos())
324
            self._label_mouse.setText('mouse pos : ({},{})'.format(round(pos.x()), round(pos.y())))
325

    
326
        return QWidget.eventFilter(self, source, event)
327

    
328
    def closeEvent(self, event):
329
        """ask user to save drawing which is modified"""
330

    
331
        self.save_drawing_if_necessary()
332
        AppDocData.instance().clear()
333
        event.accept()
334

    
335
    def inconsistencyTableKeyPressEvent(self, event):
336
        try:
337
            row = self.tableWidgetInconsistency.selectedIndexes()[0].row()
338
            col = self.tableWidgetInconsistency.selectedIndexes()[0].column()
339
            from HighlightCommand import HighlightCommand
340
            if event.key() == Qt.Key_Up:
341
                if row is not 0:
342
                    errorItem = self.tableWidgetInconsistency.item(row - 1, 1).tag
343
                    HighlightCommand(self.graphicsView).execute(errorItem)
344
            elif event.key() == Qt.Key_Down:
345
                if row is not self.tableWidgetInconsistency.rowCount() - 1:
346
                    errorItem = self.tableWidgetInconsistency.item(row + 1, 1).tag
347
                    HighlightCommand(self.graphicsView).execute(errorItem)
348
            elif event.key() == Qt.Key_Delete:
349
                item = self.tableWidgetInconsistency.item(row, 0).tag
350
                if item and item.scene(): item.scene().removeItem(item)
351
                self.tableWidgetInconsistency.removeRow(row)
352
        except Exception as ex:
353
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
354
                                                           sys.exc_info()[-1].tb_lineno)
355
            self.addMessage.emit(MessageType.Error, message)
356
        # finally:
357
        #    return QTableView.keyPressEvent(self.tableWidgetInconsistency, event)
358

    
359
    def onValidation(self):
360
        """
361
        @brief  validation check
362
        @author euisung
363
        @date   2019.04.01
364
        """
365
        from ValidateCommand import ValidateCommand
366

    
367
        if not self.graphicsView.hasImage():
368
            self.showImageSelectionMessageBox()
369
            return
370

    
371
        try:
372
            # remove error items
373
            for item in self.graphicsView.scene.items():
374
                if type(item) is QEngineeringErrorItem:
375
                    item.transfer.onRemoved.emit(item)
376
            # up to here
377

    
378
            cmd = ValidateCommand(self.graphicsView)
379
            errors = cmd.execute(self.graphicsView.scene.items())
380
            for error in errors:
381
                error.transfer.onRemoved.connect(self.itemRemoved)
382
                self.graphicsView.scene.addItem(error)
383

    
384
            self.tableWidgetInconsistency.clearContents()
385
            self.tableWidgetInconsistency.setRowCount(len(errors))
386
            for index in range(len(errors)):
387
                self.makeInconsistencyTableRow(index, errors[index])
388
        except Exception as ex:
389
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
390
                                                           sys.exc_info()[-1].tb_lineno)
391
            self.addMessage.emit(MessageType.Error, message)
392

    
393
    def makeInconsistencyTableRow(self, row, errorItem):
394
        '''
395
            @brief  make row data for inconsistency widget
396
            @author euisung
397
            @date   2019.04.16
398
        '''
399

    
400
        item = QTableWidgetItem(str(errorItem.parent))
401
        item.tag = errorItem
402
        self.tableWidgetInconsistency.setItem(row, 0, item)
403

    
404
        item = QTableWidgetItem(str(type(errorItem.parent)))
405
        item.tag = errorItem
406
        self.tableWidgetInconsistency.setItem(row, 1, item)
407

    
408
        item = QTableWidgetItem(errorItem.msg)
409
        item.tag = errorItem
410
        self.tableWidgetInconsistency.setItem(row, 2, item)
411

    
412
    def inconsistencyItemClickEvent(self, item):
413
        """
414
        @brief  inconsistency table item clicked
415
        @author euisung
416
        @date   2019.04.02
417
        """
418
        from HighlightCommand import HighlightCommand
419

    
420
        HighlightCommand(self.graphicsView).execute(item.tag)
421

    
422
    def load_stylesheet(self, file):
423
        """
424
        @brief  load stylesheets
425
        @author humkyung
426
        @date   2018.10.29
427
        """
428

    
429
        QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
430

    
431
        app_doc_data = AppDocData.instance()
432
        configs = [Config('app', 'stylesheet', file)]
433
        app_doc_data.saveAppConfigs(configs)
434

    
435
        for action in self.menuTheme.actions():
436
            if action.text() == file: continue
437
            action.setChecked(False)
438

    
439
    def load_language(self, file):
440
        """
441
        load language file and then apply selected language 
442
        """
443
        try:
444
            qm_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate', '{0}.qm'.format(file))
445
            QtWidgets.qApp.load_language(qm_file)
446

    
447
            app_doc_data = AppDocData.instance()
448
            configs = [Config('app', 'language', file)]
449
            app_doc_data.saveAppConfigs(configs)
450

    
451
            for action in self.menuLanguage.actions():
452
                if action.text().lower() == file.lower(): continue
453
                action.setChecked(False)
454
        finally:
455
            self.retranslateUi(self)
456
            self.propertyTableWidget.retranslateUi()
457

    
458
    '''
459
        @brief      Clear TreeWidget and Set Current PID
460
        @author     Jeongwoo
461
        @date       18.04.11
462
        @history    2018.04.26  Jeongwoo    Add Child [SYMBOLS, NOTES] into root item
463
                    2018.05.09  Jeongwoo    Change method to add default tree items
464
                    humkyung 2018.06.10 add tree item for Line No and Unknown Item
465
    '''
466

    
467
    def load_drawing_list(self):
468
        """load p&id drawing list"""
469
        from Drawing import Drawing
470

    
471
        try:
472
            app_doc_data = AppDocData.instance()
473
            drawings = app_doc_data.getDrawings()
474

    
475
            self.treeWidgetDrawingList.clear()
476
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList,
477
                                                              [self.tr('P&ID Drawings'), ''])
478
            self.treeWidgetDrawingList.root.setFlags(
479
                self.treeWidgetDrawingList.root.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
480
            self.treeWidgetDrawingList.root.setCheckState(0, Qt.Unchecked)
481
            files = app_doc_data.getDrawingFileList()
482
            for file in files:
483
                x = [drawing for drawing in drawings if drawing.name == file]
484
                if not x or not x[0].UID:
485
                    drawing = Drawing(None, file, None)
486
                    drawings.append(drawing)
487
                else:
488
                    drawing = x[0]
489

    
490
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [file, drawing.datetime])
491
                item.setIcon(0, QIcon(':newPrefix/image.png'))
492
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
493
                item.setCheckState(0, Qt.Unchecked)
494
                item.setData(Qt.UserRole, 0, drawing)
495

    
496
            self.treeWidgetDrawingList.root.setText(0, self.tr('P&ID Drawings') + '({})'.format(
497
                self.treeWidgetDrawingList.root.childCount()))
498
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
499
            self.treeWidgetDrawingList.root.sortChildren(0, Qt.AscendingOrder)
500
            self.treeWidgetDrawingList.resizeColumnToContents(0)
501

    
502
            app_doc_data.saveDrawings(drawings)
503
        except Exception as ex:
504
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
505
                                                           sys.exc_info()[-1].tb_lineno)
506
            self.addMessage.emit(MessageType.Error, message)
507

    
508
    def open_selected_drawing(self, item, column):
509
        """open selected p&id drawing"""
510

    
511
        app_doc_data = AppDocData.instance()
512
        drawing = item.data(Qt.UserRole, 0)
513
        if drawing:
514
            drawing.image = None
515
            self.open_image_drawing(drawing)
516

    
517
    def show_detect_symbol_dialog(self):
518
        from DetectSymbolDialog import QDetectSymbolDialog
519

    
520
        dlg = QDetectSymbolDialog(self)
521
        dlg.exec_()
522

    
523
    '''
524
        @brief      OCR Editor
525
        @author     euisung
526
        @date       2018.10.05
527
        @history    2018.10.16 euisung      no more used, Integrated with oCRTrainingClicked
528
    '''
529

    
530
    def oCRTrainingEdidorClicked(self):
531
        from TrainingEditorDialog import QTrainingEditorDialog
532

    
533
        try:
534
            dialog = QTrainingEditorDialog(self)
535
            dialog.exec_()
536
        except Exception as ex:
537
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
538
                                                           sys.exc_info()[-1].tb_lineno)
539
            self.addMessage.emit(MessageType.Error, message)
540

    
541
        return
542

    
543
    '''
544
        @brief      OCR Training
545
        @author     euisung
546
        @date       2018.09.27
547
        @history    euisung 2018.10.16 TrainingListDialog -> TrainingImageListDialog
548
    '''
549

    
550
    def oCRTrainingClicked(self):
551
        try:
552
            dialog = QTrainingImageListDialog(self)
553
            dialog.exec_()
554
        except Exception as ex:
555
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
556
                                                           sys.exc_info()[-1].tb_lineno)
557
            self.addMessage.emit(MessageType.Error, message)
558

    
559
    def symbolTrainingClicked(self):
560
        try:
561
            dialog = QTrainingSymbolImageListDialog(self)
562
            dialog.exec_()
563
        except Exception as ex:
564
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
565
                                                           sys.exc_info()[-1].tb_lineno)
566
            self.addMessage.emit(MessageType.Error, message)
567

    
568
    '''
569
        @brief      show unknownitem's count
570
        @author     kyouho
571
        @date       2018.08.27
572
    '''
573

    
574
    def findReplaceTextClicked(self):
575
        if not self.graphicsView.hasImage():
576
            self.showImageSelectionMessageBox()
577
            return
578

    
579
        from TextItemEditDialog import QTextItemEditDialog
580

    
581
        self.dlgTextItemEdit = QTextItemEditDialog(self)
582
        self.dlgTextItemEdit.show()
583
        self.dlgTextItemEdit.exec_()
584

    
585
    def display_number_of_items(self):
586
        """display count of symbol, line, text"""
587

    
588
        items = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
589
        if len(items) > 0:
590
            self.labelStatus.setText(
591
                "<font color='red'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
592
        else:
593
            self.labelStatus.setText(
594
                "<font color='black'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
595

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

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

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

    
606
        self.itemTreeWidget.sceneChanged(self.graphicsView.scene.items())
607

    
608
    def dbUpdate(self):
609
        '''
610
            @brief      db update when save or recognition
611
            @author     euisung
612
            @date       2018.11.12
613
            @history    2018.11.02      euisung     remove scene dependency
614
        '''
615
        try:
616
            appDocData = AppDocData.instance()
617
            items = appDocData.allItems
618

    
619
            '''
620
            titleBlockProps = appDocData.getTitleBlockProperties()
621
            titleBlockItems = []
622
            for item in items:
623
                # if type(item) is QEngineeringLineNoTextItem:
624
                #    item.saveLineData()
625
                if type(item) is QEngineeringTextItem:
626
                    for titleBlockProp in titleBlockProps:
627
                        if item.area == titleBlockProp[0]:
628
                            titleBlockItems.append(item)
629
            '''
630

    
631
            # unknown item is not saved now for performance
632
            db_items = [item for item in items if issubclass(type(item), QEngineeringAbstractItem) and type(
633
                item) is not QGraphicsBoundingBoxItem and type(item) is not QEngineeringErrorItem and type(
634
                item) is not QEngineeringLineNoTextItem and type(item) is not QEngineeringUnknownItem]
635
            db_items.extend([item for item in items if type(item) is QEngineeringLineNoTextItem])
636
            db_items.extend([line for line in appDocData.tracerLineNos if type(line) is QEngineeringTrimLineNoTextItem])
637
            #db_items.extend(titleBlockItems)
638
            configs = appDocData.getConfigs('Data Load', 'Xml First')
639
            if configs and int(configs[0].value) is 1:
640
                db_items.extend([item for item in items if type(item) is QEngineeringUnknownItem])
641

    
642
            '''
643
            dbItems = [item for item in items if
644
                       type(item) is QEngineeringInstrumentItem or type(item) is QEngineeringEquipmentItem or type(
645
                           item) is QEngineeringReducerItem or \
646
                       type(item) is QEngineeringNoteItem or type(item) is SymbolSvgItem or type(
647
                           item) is QEngineeringLineNoTextItem or type(
648
                           item) is QEngineeringVendorItem] + titleBlockItems
649
            '''
650
            appDocData.saveToDatabase(db_items)
651
        except Exception as ex:
652
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
653
                                                           sys.exc_info()[-1].tb_lineno)
654
            self.addMessage.emit(MessageType.Error, message)
655

    
656
    def save_drawing_if_necessary(self):
657
        """ask to user to save drawing or not when drawing is modified"""
658

    
659
        app_doc_data = AppDocData.instance()
660
        if app_doc_data.activeDrawing and app_doc_data.activeDrawing.modified:
661
            if QMessageBox.Yes == QMessageBox.question(self, self.tr("Question"),
662
                                                       self.tr("Do you want to save drawing?"),
663
                                                       QMessageBox.Yes | QMessageBox.No):
664
                self.actionSaveCliked()
665

    
666
    '''
667
        @brief      action save click event
668
        @author     kyouho
669
        @date       2018.08.09
670
        @history    2018.11.02      euisung     add line data list db update
671
                    humkyung save saved time to database
672
                    2018.11.05      euisung     add note data list db update
673
                    2018.11.05      euisung     add db delete process before save
674
                    2018.11.12      euisung     db part move new method to dbUpdate
675
    '''
676

    
677
    def actionSaveCliked(self):
678
        from EngineeringAbstractItem import QEngineeringAbstractItem
679
        from SaveWorkCommand import SaveWorkCommand
680

    
681
        try:
682
            if not self.actionSave.isEnabled():
683
                return
684
            self.actionSave.setEnabled(False)
685
            app_doc_data = AppDocData.instance()
686
            if app_doc_data.imgName is None:
687
                self.showImageSelectionMessageBox()
688
                return
689

    
690
            app_doc_data.clearItemList(False)
691

    
692
            items = self.graphicsView.scene.items()
693
            for item in items:
694
                if issubclass(type(item), QEngineeringAbstractItem):
695
                    app_doc_data.allItems.append(item)
696
                    if issubclass(type(item), QEngineeringTextItem):
697
                        app_doc_data.texts.append(item)
698

    
699
            itemTypes = []
700
            for item in items:
701
                typeExist = False
702
                for itemType in itemTypes:
703
                    if type(item) is itemType:
704
                        typeExist = True
705
                        break
706
                if not typeExist:
707
                    itemTypes.append(type(item))
708

    
709
            self._save_work_cmd = SaveWorkCommand()
710
            self._save_work_cmd.show_progress.connect(self.progress_bar.setValue)
711
            self._save_work_cmd.display_message.connect(self.onAddMessage)
712
            self._save_work_cmd.finished.connect(self.save_finished)
713

    
714
            self._save_work_cmd.start()
715
        except Exception as ex:
716
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
717
                                                           sys.exc_info()[-1].tb_lineno)
718
            self.addMessage.emit(MessageType.Error, message)
719

    
720
    def save_finished(self):
721
        """reload drawing list"""
722

    
723
        self._save_work_cmd.show_progress.emit(100)
724
        QMessageBox.about(self.graphicsView, self.tr('Information'), self._save_work_cmd.resultStr)
725
        self.load_drawing_list()
726

    
727
        app_doc_data = AppDocData.instance()
728
        app_doc_data.activeDrawing.modified = False
729
        title = self.windowTitle()
730
        self.setWindowTitle(title[:-1] if title[-1] == '*' else title)
731

    
732
        self.actionSave.setEnabled(True)
733

    
734
    '''
735
        @brief      refresh resultPropertyTableWidget
736
        @author     kyouho
737
        @date       2018.07.19
738
    '''
739

    
740
    def refreshResultPropertyTableWidget(self):
741
        items = self.graphicsView.scene.selectedItems()
742
        if len(items) == 1:
743
            self.resultPropertyTableWidget.show_item_property(items[0])
744

    
745
    '''
746
        @brief  add message listwidget
747
        @author humkyung
748
        @date   2018.07.31
749
    '''
750

    
751
    def onAddMessage(self, messageType, message):
752
        from AppDocData import MessageType
753

    
754
        try:
755
            current = QDateTime.currentDateTime()
756

    
757
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
758
            item.setFlags(item.flags() | Qt.ItemIsEditable)
759
            if messageType == MessageType.Error:
760
                item.setBackground(Qt.red)
761

    
762
            self.listWidgetLog.insertItem(0, item)
763
        except Exception as ex:
764
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
765
                                                       sys.exc_info()[-1].tb_lineno))
766

    
767
    '''
768
        @brief      clear log
769
        @author     humkyung
770
        @date       2018.08.01
771
    '''
772

    
773
    def onClearLog(self):
774
        self.listWidgetLog.clear()
775

    
776
    '''
777
        @brief      rotate selected symbol
778
        @author     humkyung
779
        @date       2018.08.15
780
    '''
781

    
782
    def onRotate(self, action):
783
        selected = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem)]
784
        if len(selected) == 1:
785
            selected[0].rotateSymbol()
786

    
787
    '''
788
        @brief      Area Zoom
789
        @author     Jeongwoo
790
        @date       2018.06.27
791
        @history    connect command's rejected signal
792
    '''
793

    
794
    def onAreaZoom(self, action):
795
        if self.actionZoom.isChecked():
796
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
797
            cmd.onRejected.connect(self.onCommandRejected)
798
            self.graphicsView.command = cmd
799

    
800
    def onVendor(self, action):
801
        '''
802
            @brief      make vendor package area
803
            @author     euisung
804
            @date       2019.04.29
805
        '''
806
        if not self.graphicsView.hasImage():
807
            self.actionVendor.setChecked(False)
808
            self.showImageSelectionMessageBox()
809
            return
810

    
811
        self.actionVendor.setChecked(True)
812
        if not hasattr(self.actionVendor, 'tag'):
813
            self.actionVendor.tag = PlacePolygonCommand.PlacePolygonCommand(self.graphicsView)
814
            self.actionVendor.tag.onSuccess.connect(self.onVendorCreated)
815
            self.actionVendor.tag.onRejected.connect(self.onCommandRejected)
816

    
817
        self.graphicsView.command = self.actionVendor.tag
818

    
819
    def onVendorCreated(self):
820
        '''
821
            @brief      add created vendor polygon area to scene
822
            @author     euisung
823
            @date       2019.04.29
824
        '''
825
        try:
826
            count = len(self.actionVendor.tag._polyline._vertices)
827
            if count > 2:
828
                qPoints = []
829
                points = []
830
                for point in self.actionVendor.tag._polyline._vertices:
831
                    points.append([round(point[0]), round(point[1])])
832
                    qPoints.append(QPoint(round(point[0]), round(point[1])))
833
                vendorArea = QPolygonF(qPoints)
834
                vendorItem = QEngineeringVendorItem(vendorArea, points)
835
                vendorItem.area = 'Drawing'
836
                vendorItem.transfer.onRemoved.connect(self.itemRemoved)
837
                self.graphicsView.scene.addItem(vendorItem)
838
        finally:
839
            self.graphicsView.scene.removeItem(self.actionVendor.tag._polyline)
840
            self.actionVendor.tag.reset()
841

    
842
    '''
843
        @brief      Fit Window
844
        @author     Jeongwoo
845
        @date       2018.06.27
846
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
847
    '''
848

    
849
    def fitWindow(self, action):
850
        self.graphicsView.useDefaultCommand()
851
        self.graphicsView.zoomImageInit()
852

    
853
    def scene_changed(self):
854
        """update modified flag"""
855

    
856
        self.display_number_of_items()
857

    
858
        app_doc_data = AppDocData.instance()
859
        app_doc_data.activeDrawing.modified = True
860
        title = self.windowTitle()
861
        self.setWindowTitle(title if title[-1] == '*' else title + '*')
862

    
863
    def onConvertPDFToImage(self):
864
        """
865
        @brief      convert to selected pdf to image
866
        @author     humkyung 
867
        @date       2018.07.09
868
        @history    Euisung 2018.10.11 hide shell
869
        """
870
        try:
871
            filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'bin64', 'PDF_TO_IMAGE.exe')
872
            subprocess.call(filePath, shell=False)
873
        except Exception as ex:
874
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
875
                                                           sys.exc_info()[-1].tb_lineno)
876
            self.addMessage.emit(MessageType.Error, message)
877

    
878
    def onImportTextFromCAD(self):
879
        """ import text from cad """
880
        try:
881
            self.onCommandRejected()
882
            dialog = QImportTextFromCADDialog(self)
883
            dialog.show()
884
            dialog.exec_()
885
        except Exception as ex:
886
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
887
                                                           sys.exc_info()[-1].tb_lineno)
888
            self.addMessage.emit(MessageType.Error, message)
889

    
890
    def onSymbolThickness(self):
891
        """ symbol thickness reinforcement by using configuration filter drawing dilate size """
892
        try:
893
            self.onCommandRejected()
894
            dialog = QSymbolThicknessDialog(self)
895
            dialog.exec_()
896
        except Exception as ex:
897
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
898
                                                           sys.exc_info()[-1].tb_lineno)
899
            self.addMessage.emit(MessageType.Error, message)
900

    
901
    def on_help(self):
902
        """ open help file """
903
        import os
904

    
905
        try:
906
            help_file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ID2 User Manual.pdf')
907
            os.system('"{}"'.format(help_file_path))
908
        except Exception as ex:
909
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
910
                                                           sys.exc_info()[-1].tb_lineno)
911
            self.addMessage.emit(MessageType.Error, message)
912

    
913
    '''
914
        @brief      selection changed
915
        @author     humkyung
916
        @date       2018.06.27
917
        @history    humkung 2018.07.08 call tree widget's findItem
918
    '''
919

    
920
    def onSelectionChanged(self):
921
        items = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem) or \
922
                 type(item) is QEngineeringLineItem or issubclass(type(item), QEngineeringTextItem) or type(
923
            item) is QEngineeringUnknownItem or type(item) is QEngineeringVendorItem]
924
        if items:
925
            item = items[-1]
926
            self.itemTreeWidget.findItem(item)
927
            self.resultPropertyTableWidget.show_item_property(item)
928
            if type(item) is QEngineeringErrorItem:
929
                for index in range(self.tableWidgetInconsistency.rowCount()):
930
                    if self.tableWidgetInconsistency.item(index, 1).tag is item:
931
                        self.tableWidgetInconsistency.selectRow(index)
932
                        break
933
        else:
934
            self.resultPropertyTableWidget.show_item_property(None)
935

    
936
    '''
937
        @brief      Initialize scene and itemTreeWidget
938
        @author     Jeongwoo
939
        @date       2018.06.14
940
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
941
    '''
942

    
943
    def onInitializeScene(self, action):
944
        if not self.graphicsView.hasImage():
945
            #self.actionEquipment.setChecked(False)
946
            self.showImageSelectionMessageBox()
947

    
948
            return
949

    
950
        try:
951
            msg = QMessageBox()
952
            msg.setIcon(QMessageBox.Critical)
953
            msg.setText(self.tr('Do you want to remove all items?\nThis work cannot be recovered.'))
954
            msg.setWindowTitle(self.tr("Initialize"))
955
            msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
956
            if QMessageBox.Ok == msg.exec_():
957

    
958
                appDocData = AppDocData.instance()
959
                appDocData.clearItemList(True)
960

    
961
                items = self.graphicsView.scene.items()
962
                for item in items:
963
                    if type(item) is not QGraphicsPixmapItem and item.scene() is not None:
964
                        # if hasattr(item, 'tranfer'):
965
                        #    item.tranfer.onRemoved.emit(item)
966
                        # else:
967
                        #    self.graphicsView.scene.removeItem(item)
968
                        self.graphicsView.scene.removeItem(item)
969

    
970
                        '''
971
                        if type(item) is QEngineeringLineNoTextItem:
972
                            self.removedItems['LINE'].append(str(item.uid))
973
                        elif type(item) is QEngineeringInstrumentItem:
974
                            self.removedItems['INST'].append(str(item.uid))
975
                        elif type(item) is QEngineeringEquipmentItem:
976
                            self.removedItems['EQUIP'].append(str(item.uid))
977
                        elif type(item) is QEngineeringNoteItem:
978
                            self.removedItems['NOTE'].append(str(item.uid))
979
                        '''
980

    
981
                if self.path is not None:
982
                    baseName = os.path.basename(self.path)
983
                    self.itemTreeWidget.setCurrentPID(baseName)
984

    
985
        except Exception as ex:
986
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
987
                                                           sys.exc_info()[-1].tb_lineno)
988
            self.addMessage.emit(MessageType.Error, message)
989

    
990
    '''
991
        @brief      Manage Checkable Action statement
992
        @author     Jeongwoo
993
        @date       2018.05.10
994
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
995
    '''
996

    
997
    def actionGroupTriggered(self, action):
998
        if hasattr(self.actionLine, 'tag'):
999
            self.actionLine.tag.onRejected.emit(None)
1000

    
1001
        if hasattr(self.actionVendor, 'tag'):
1002
            self.actionVendor.tag.onRejected.emit(None)
1003

    
1004
        if self.graphicsView.command is not None:
1005
            self.graphicsView.useDefaultCommand()
1006

    
1007
        for _action in self.actionGroup.actions():
1008
            _action.setChecked(False)
1009

    
1010
        action.setChecked(True)
1011

    
1012
    '''
1013
        @brief      Create Equipment
1014
        @author     Jeongwoo
1015
        @date       18.05.03
1016
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
1017
    '''
1018

    
1019
    def createEquipment(self):
1020
        if not self.graphicsView.hasImage():
1021
            self.actionEquipment.setChecked(False)
1022
            self.showImageSelectionMessageBox()
1023
            return
1024
        if self.actionEquipment.isChecked():
1025
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget,
1026
                                                                                self.dirTreeWidget)
1027
        else:
1028
            self.graphicsView.useDefaultCommand()
1029

    
1030
    '''
1031
        @brief      Create Nozzle
1032
        @author     Jeongwoo
1033
        @date       2018.05.03
1034
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
1035
    '''
1036

    
1037
    def createNozzle(self):
1038
        if not self.graphicsView.hasImage():
1039
            self.actionNozzle.setChecked(False)
1040
            self.showImageSelectionMessageBox()
1041
            return
1042
        if self.actionNozzle.isChecked():
1043
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget,
1044
                                                                                self.dirTreeWidget)
1045
        else:
1046
            self.graphicsView.useDefaultCommand()
1047

    
1048
    '''
1049
        @brief      Area OCR
1050
        @author     Jeongwoo
1051
        @date       18.04.18
1052
        @history    2018.05.02  Jeongwoo    Change graphicsView.command by actionOCR checked state
1053
                                            Show MessageBox when imageviewer doesn't have image
1054
    '''
1055

    
1056
    def onAreaOcr(self):
1057
        if not self.graphicsView.hasImage():
1058
            self.actionOCR.setChecked(False)
1059
            self.showImageSelectionMessageBox()
1060
            return
1061

    
1062
        if self.actionOCR.isChecked():
1063
            cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView)
1064
            cmd.onSuccess.connect(self.onRecognizeText)
1065
            cmd.onRejected.connect(self.onCommandRejected)
1066
            self.graphicsView.command = cmd
1067
        else:
1068
            self.graphicsView.useDefaultCommand()
1069

    
1070
    '''
1071
        @brief      show text recognition dialog
1072
        @author     humkyung
1073
        @date       2018.08.08
1074
    '''
1075

    
1076
    def onRecognizeText(self, x, y, width, height):
1077
        from OcrResultDialog import QOcrResultDialog
1078

    
1079
        try:
1080
            image = self.graphicsView.image().copy(x, y, width, height)
1081
            dialog = QOcrResultDialog(self.graphicsView, image, QRectF(x, y, width, height))
1082
            (isAccept, textInfoList) = dialog.showDialog()
1083
            if isAccept:
1084
                if textInfoList is not None and len(textInfoList) > 0:
1085
                    docData = AppDocData.instance()
1086
                    for textInfo in textInfoList:
1087
                        x = textInfo.getX()
1088
                        y = textInfo.getY()
1089
                        angle = textInfo.getAngle()
1090
                        text = textInfo.getText()
1091
                        width = textInfo.getW()
1092
                        height = textInfo.getH()
1093
                        item = TextItemFactory.instance().createTextItem(textInfo)
1094
                        if item is not None:
1095
                            item.loc = [x, y]
1096
                            item.size = (width, height)
1097
                            item.angle = angle
1098
                            item.setDefaultTextColor(Qt.blue)
1099
                            item.addTextItemToScene(self.graphicsView.scene)
1100
                            item.transfer.onRemoved.connect(self.itemRemoved)
1101
                        else:
1102
                            message = 'error occurred({}) in {}:{}'.format('텍스트 생성에 실패했습니다.', sys.exc_info()[
1103
                                -1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
1104
                            self.addMessage.emit(MessageType.Normal, message)
1105
                else:
1106
                    QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("Fail to recognize text"))
1107
        except Exception as ex:
1108
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1109
                                                           sys.exc_info()[-1].tb_lineno)
1110
            self.addMessage.emit(MessageType.Error, message)
1111

    
1112
    '''
1113
        @brief  area configuration
1114
    '''
1115

    
1116
    def areaConfiguration(self):
1117
        from ConfigurationAreaDialog import QConfigurationAreaDialog
1118
        if not self.graphicsView.hasImage():
1119
            self.showImageSelectionMessageBox()
1120
            return
1121
        self.onCommandRejected()
1122
        self.dlgConfigurationArea = QConfigurationAreaDialog(self)
1123
        self.dlgConfigurationArea.show()
1124
        self.dlgConfigurationArea.exec_()
1125

    
1126
    '''
1127
        @brief  configuration
1128
    '''
1129

    
1130
    def configuration(self):
1131
        from ConfigurationDialog import QConfigurationDialog
1132

    
1133
        self.dlgConfiguration = QConfigurationDialog(self)
1134
        # self.dlgConfiguration.show()
1135
        if QDialog.Accepted == self.dlgConfiguration.exec_():
1136
            QEngineeringLineItem.LINE_TYPE_COLORS.clear()
1137
            QEngineeringInstrumentItem.INST_COLOR = None
1138

    
1139
    '''
1140
        @brief  show special item types dialog 
1141
        @author humkyung
1142
        @date   2019.08.10
1143
    '''
1144

    
1145
    def on_show_special_item_types(self):
1146
        from SpecialItemTypesDialog import QSpecialItemTypesDialog
1147

    
1148
        dlg = QSpecialItemTypesDialog(self)
1149
        dlg.exec_()
1150

    
1151
    def on_show_data_transfer(self):
1152
        """ show data transfer dialog """
1153
        from DataTransferDialog import QDataTransferDialog
1154

    
1155
        dlg = QDataTransferDialog(self)
1156
        dlg.exec_()
1157

    
1158
    def on_show_data_export(self):
1159
        """ show data export dialog """
1160
        from DataExportDialog import QDataExportDialog
1161

    
1162
        dlg = QDataExportDialog(self)
1163
        dlg.exec_()
1164

    
1165
    def on_show_eqp_datasheet_export(self):
1166
        """ show eqp datasheet export dialog """
1167
        from EqpDatasheetExportDialog import QEqpDatasheetExportDialog
1168

    
1169
        dlg = QEqpDatasheetExportDialog(self)
1170
        dlg.exec_()
1171

    
1172
    def on_show_opc_relation(self):
1173
        """ show opc relation dialog """
1174
        from OPCRelationDialog import QOPCRelationDialog
1175

    
1176
        dlg = QOPCRelationDialog(self)
1177
        dlg.exec_()
1178

    
1179
    '''
1180
        @brief  show nominal diameter dialog 
1181
        @author humkyung
1182
        @date   2018.06.28
1183
    '''
1184

    
1185
    def onShowCodeTable(self):
1186
        from CodeTableDialog import QCodeTableDialog
1187

    
1188
        dlg = QCodeTableDialog(self)
1189
        dlg.show()
1190
        dlg.exec_()
1191
        if dlg.code_area:
1192
            if dlg.code_area.scene():
1193
                self.graphicsView.scene.removeItem(dlg.code_area)
1194
        if dlg.desc_area:
1195
            if dlg.desc_area.scene():
1196
                self.graphicsView.scene.removeItem(dlg.desc_area)
1197
        self.graphicsView.useDefaultCommand()
1198

    
1199
    def onShowCustomCodeTable(self):
1200
        from CustomCodeTablesDialog import CustomCodeTablesDialog
1201

    
1202
        dlg = CustomCodeTablesDialog(self)
1203
        dlg.show()
1204
        dlg.exec_()
1205
        self.graphicsView.useDefaultCommand()
1206

    
1207
    '''
1208
        @brief  show HMB data
1209
        @author humkyung
1210
        @date   2018.07.11
1211
    '''
1212

    
1213
    def onHMBData(self):
1214
        from HMBDialog import QHMBDialog
1215

    
1216
        dlg = QHMBDialog(self)
1217
        dlg.show()
1218
        dlg.exec_()
1219

    
1220
    '''
1221
        @brief  show line data list 
1222
        @author humkyung
1223
        @date   2018.05.03
1224
    '''
1225

    
1226
    def showItemDataList(self):
1227
        from ItemDataExportDialog import QItemDataExportDialog
1228

    
1229
        self.dlgLineDataList = QItemDataExportDialog(self)
1230
        self.dlgLineDataList.exec_()
1231

    
1232
    def showTextDataList(self):
1233
        '''
1234
            @brief      show all text item in scene
1235
            @author     euisung
1236
            @date       2019.04.18
1237
        '''
1238
        try:
1239
            if not self.graphicsView.hasImage():
1240
                self.showImageSelectionMessageBox()
1241
                return
1242

    
1243
            self.onCommandRejected()
1244
            dialog = QTextDataListDialog(self)
1245
            dialog.show()
1246
            dialog.exec_()
1247
        except Exception as ex:
1248
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1249
                                                           sys.exc_info()[-1].tb_lineno)
1250
            self.addMessage.emit(MessageType.Error, message)
1251

    
1252
    '''
1253
        @brief  Show Image Selection Guide MessageBox
1254
        @author Jeongwoo
1255
        @date   2018.05.02
1256
    '''
1257

    
1258
    def showImageSelectionMessageBox(self):
1259
        QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("First select image drawing"))
1260

    
1261
    '''
1262
        @brief  change selected lines' type by selected line type
1263
        @author humkyung
1264
        @date   2018.06.27
1265
    '''
1266

    
1267
    def onLineTypeChanged(self, param):
1268
        lineType = self.lineComboBox.itemText(param)
1269
        selected = [item for item in self.graphicsView.scene.selectedItems() if type(item) is QEngineeringLineItem]
1270
        if selected:
1271
            for item in selected:
1272
                item.lineType = lineType
1273

    
1274
    def display_colors(self, value):
1275
        """ display colors """
1276
        from DisplayColors import DisplayColors
1277
        from DisplayColors import DisplayOptions
1278

    
1279
        DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value == True else DisplayOptions.DisplayByLineType
1280
        if hasattr(self, 'graphicsView'):
1281
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1282
            DisplayColors.instance().save_data()
1283

    
1284
    '''
1285
        @brief      Open image drawing file and then display it
1286
        @author     humkyung
1287
        @date       2018.??.??
1288
        @history    18.04.23 Jeongwoo    Add AppDocData.instance().setCurrentPidSource
1289
                    18.04.23 Jeongwoo    Add Store Set Current Pid Image on AppDocData
1290
                    18.05.02 Jeongwoo    Add useDefaultCommand()
1291
                    humkyung 2018.05.24 load recognition result file if exists
1292
                    Jeongwoo 2018.05.29 load data on xml if xml file exist
1293
                    humkyung 2018.08.22 clear scene before loading xml file
1294
    '''
1295

    
1296
    def open_image_drawing(self, drawing):
1297
        from Drawing import Drawing
1298

    
1299
        try:
1300
            if not self.actionSave.isEnabled():
1301
                return
1302
                
1303
            self.save_drawing_if_necessary()
1304
            if hasattr(self, '_save_work_cmd'):
1305
                self._save_work_cmd.wait()
1306

    
1307
            app_doc_data = AppDocData.instance()
1308
            project = app_doc_data.getCurrentProject()
1309

    
1310
            self.path = self.graphicsView.loadImageFromFile(drawing)
1311
            if os.path.isfile(self.path):
1312
                self.onCommandRejected()
1313
                app_doc_data.clear()
1314

    
1315
                app_doc_data.setImgFilePath(self.path)
1316
                app_doc_data.activeDrawing = drawing
1317
                if not app_doc_data.set_occupying_drawing(app_doc_data.activeDrawing.UID):
1318
                    QMessageBox.about(self.graphicsView, self.tr("Notice"),
1319
                                      self.tr("The drawing is locked for editing by another user"))
1320
                    return
1321
                app_doc_data.activeDrawing.set_pid_source(Image.open(self.path))
1322
                self.itemTreeWidget.setCurrentPID(app_doc_data.activeDrawing.name)
1323

    
1324
                drawingList = self.treeWidgetDrawingList.topLevelItem(0)
1325
                for childIdex in range(drawingList.childCount()):
1326
                    drawingList.child(childIdex).setCheckState(0, Qt.Unchecked)
1327
                for childIdex in range(drawingList.childCount()):
1328
                    child = drawingList.child(childIdex)
1329
                    if child.text(0).replace('.png', '') == app_doc_data.activeDrawing.name:
1330
                        child.setCheckState(0, Qt.Checked)
1331
                        break
1332

    
1333
                try:
1334
                    self.show_Progress_bar()
1335

    
1336
                    # disconnect scene changed if signal is connected
1337
                    if self.graphicsView.scene.receivers(self.graphicsView.scene.contents_changed) > 0:
1338
                        self.graphicsView.scene.contents_changed.disconnect()
1339

    
1340
                    # Load data
1341
                    path = os.path.join(app_doc_data.getCurrentProject().getTempPath(), app_doc_data.imgName + '.xml')
1342
                    configs = app_doc_data.getConfigs('Data Load', 'Xml First')
1343
                    if configs and int(configs[0].value) is 1 and os.path.isfile(path):
1344
                        self.loadRecognitionResultFromXml(path)
1345
                    else:
1346
                        self.load_drawing(app_doc_data.activeDrawing)
1347

    
1348
                    self.display_number_of_items()
1349
                    # connect scene changed signal
1350
                    self.graphicsView.scene.contents_changed.connect(self.scene_changed)
1351
                finally:
1352
                    if hasattr(self, 'progress'):
1353
                        self.progress.setValue(self.progress.maximum())
1354
                        # self.progress.hide()
1355

    
1356
                self.changeViewCheckedState(True)
1357
        except Exception as ex:
1358
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1359
                                                           sys.exc_info()[-1].tb_lineno)
1360
            self.addMessage.emit(MessageType.Error, message)
1361

    
1362
        return self.path
1363

    
1364
    def show_Progress_bar(self):
1365
        """ show progress bar """
1366
        self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
1367
                                        self) if not hasattr(self, 'progress') else self.progress
1368
        self.progress.setWindowModality(Qt.WindowModal)
1369
        self.progress.setAutoReset(True)
1370
        self.progress.setAutoClose(True)
1371
        self.progress.setMinimum(0)
1372
        self.progress.setMaximum(100)
1373
        self.progress.resize(600, 100)
1374
        self.progress.setWindowTitle(self.tr("Reading file..."))
1375
        self.progress.show()
1376

    
1377
    def changeViewCheckedState(self, checked, clear=True):
1378
        '''
1379
            @brief      change view checked state
1380
            @author     euisung
1381
            @date       2019.03.06
1382
        '''
1383
        # self.actionImage_Drawing.setChecked(checked)
1384
        self.actionViewText.setChecked(checked)
1385
        self.actionViewSymbol.setChecked(checked)
1386
        self.actionViewLine.setChecked(checked)
1387
        self.actionViewUnknown.setChecked(checked)
1388
        self.actionViewInconsistency.setChecked(checked)
1389
        self.actionViewVendor_Area.setChecked(not checked)
1390
        self.actionDrawing_Only.setChecked(not checked)
1391
        if clear:
1392
            self.tableWidgetInconsistency.clearContents()
1393
            self.tableWidgetInconsistency.setRowCount(0)
1394

    
1395
    def onViewDrawingOnly(self, isChecked):
1396
        '''
1397
            @brief  visible/invisible except image drawing
1398
            @author euisung
1399
            @date   2019.04.22
1400
        '''
1401
        self.changeViewCheckedState(not isChecked, False)
1402
        for item in self.graphicsView.scene.items():
1403
            if type(item) is not QGraphicsPixmapItem:
1404
                item.setVisible(not isChecked)
1405

    
1406
    '''
1407
        @brief  visible/invisible image drawing
1408
        @author humkyung
1409
        @date   2018.06.25
1410
    '''
1411

    
1412
    def onViewImageDrawing(self, isChecked):
1413
        for item in self.graphicsView.scene.items():
1414
            if type(item) is QGraphicsPixmapItem:
1415
                item.setVisible(isChecked)
1416
                break
1417

    
1418
    '''
1419
        @brief  visible/invisible Text 
1420
        @author humkyung
1421
        @date   2018.06.28
1422
    '''
1423

    
1424
    def onViewText(self, isChecked):
1425
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
1426
        for item in selected:
1427
            item.setVisible(isChecked)
1428

    
1429
    '''
1430
        @brief  visible/invisible Symbol 
1431
        @author humkyung
1432
        @date   2018.06.28
1433
    '''
1434

    
1435
    def onViewSymbol(self, isChecked):
1436
        selected = [item for item in self.graphicsView.scene.items() if
1437
                    (issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringErrorItem)]
1438
        for item in selected:
1439
            item.setVisible(isChecked)
1440

    
1441
    '''
1442
        @brief  visible/invisible Line
1443
        @author humkyung
1444
        @date   2018.06.28
1445
    '''
1446

    
1447
    def onViewLine(self, isChecked):
1448
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem]
1449
        for item in selected:
1450
            item.setVisible(isChecked)
1451

    
1452
    def onViewInconsistency(self, isChecked):
1453
        '''
1454
            @brief  visible/invisible Inconsistency
1455
            @author euisung
1456
            @date   2019.04.03
1457
        '''
1458
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringErrorItem]
1459
        for item in selected:
1460
            item.setVisible(isChecked)
1461

    
1462
    '''
1463
        @brief  visible/invisible Unknown 
1464
        @author humkyung
1465
        @date   2018.06.28
1466
    '''
1467

    
1468
    def onViewUnknown(self, isChecked):
1469
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
1470
        for item in selected:
1471
            item.setVisible(isChecked)
1472

    
1473
    def onViewVendorArea(self, isChecked):
1474
        '''
1475
            @brief  visible/invisible Vendor Area
1476
            @author euisung
1477
            @date   2019.04.29
1478
        '''
1479
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringVendorItem]
1480
        for item in selected:
1481
            item.setVisible(isChecked)
1482

    
1483
    '''
1484
        @brief  create a symbol
1485
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
1486
                                            Add SymbolSvgItem
1487
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1488
                                            Change method to make svg and image path
1489
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
1490
    '''
1491

    
1492
    def onCreateSymbolClicked(self):
1493
        cmd = FenceCommand.FenceCommand(self.graphicsView)
1494
        cmd.onSuccess.connect(self.onAreaSelected)
1495
        self.graphicsView.command = cmd
1496
        QApplication.setOverrideCursor(Qt.CrossCursor)
1497

    
1498
    '''
1499
        @brief      show SymbolEditorDialog with image selected by user
1500
        @author     humkyung
1501
        @date       2018.07.20
1502
    '''
1503

    
1504
    def onAreaSelected(self, x, y, width, height):
1505
        try:
1506
            image = self.graphicsView.image()
1507
            if image is not None:
1508
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height),
1509
                                                                            AppDocData.instance().getCurrentProject())
1510
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
1511
                self.dirTreeWidget.initDirTreeWidget()
1512
                if isAccepted:
1513
                    if isImmediateInsert:
1514
                        svgPath = newSym.getSvgFileFullPath()
1515
                        img = cv2.imread(newSym.getImageFileFullPath(), 1)
1516
                        w, h = (0, 0)
1517
                        if len(img.shape[::-1]) == 2:
1518
                            w, h = img.shape[::-1]
1519
                        else:
1520
                            _chan, w, h = img.shape[::-1]
1521
                        svg = SymbolSvgItem(svgPath)
1522
                        svg.buildItem(newSym.getName(), newSym.getType(), 0, [offsetX, offsetY], [w, h],
1523
                                      [float(x) for x in newSym.getOriginalPoint().split(',')],
1524
                                      [(float(x.split(',')[0]), float(x.split(',')[1])) for x in
1525
                                       newSym.getConnectionPoint().split('/')], newSym.getBaseSymbol(),
1526
                                      newSym.getAdditionalSymbol(), newSym.getHasInstrumentLabel)
1527

    
1528
                        svg.transfer.onRemoved.connect(self.itemTreeWidget.itemRemoved)
1529
                        svg.addSvgItemToScene(self.graphicsView.scene)
1530
                        for connector in svg.connectors:
1531
                            self.graphicsView.scene.addItem(connector)
1532
        finally:
1533
            self.onCommandRejected()
1534
            QApplication.restoreOverrideCursor()
1535

    
1536
    '''
1537
        @brief      create a line
1538
        @author     humkyung
1539
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
1540
    '''
1541

    
1542
    def onPlaceLine(self):
1543
        if not self.graphicsView.hasImage():
1544
            self.actionLine.setChecked(False)
1545
            self.showImageSelectionMessageBox()
1546
            return
1547

    
1548
        self.actionLine.setChecked(True)
1549
        if not hasattr(self.actionLine, 'tag'):
1550
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
1551
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
1552
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
1553

    
1554
        self.graphicsView.command = self.actionLine.tag
1555

    
1556
    '''
1557
        @brief      add created lines to scene
1558
        @author     humkyung
1559
        @date       2018.07.23
1560
    '''
1561

    
1562
    def onLineCreated(self):
1563
        from EngineeringConnectorItem import QEngineeringConnectorItem
1564
        from LineDetector import LineDetector
1565

    
1566
        try:
1567
            count = len(self.actionLine.tag._polyline._vertices)
1568
            if count > 1:
1569
                items = []
1570

    
1571
                detector = LineDetector(None)
1572

    
1573
                lineType = self.lineComboBox.currentText()
1574
                for index in range(count - 1):
1575
                    start = self.actionLine.tag._polyline._vertices[index]
1576
                    end = self.actionLine.tag._polyline._vertices[index + 1]
1577

    
1578
                    lineItem = QEngineeringLineItem(vertices=[start, end])
1579
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
1580
                    lineItem.lineType = lineType
1581
                    if items:
1582
                        lineItem.connect_if_possible(items[-1], 5)
1583
                    else:
1584
                        pt = lineItem.startPoint()
1585
                        selected = [item for item in self.graphicsView.scene.items(QPointF(pt[0], pt[1])) if
1586
                                    type(item) is QEngineeringConnectorItem or type(item) is QEngineeringLineItem]
1587
                        if selected and selected[0] is not lineItem:
1588
                            if type(selected[0]) is QEngineeringConnectorItem:
1589
                                lineItem.connect_if_possible(selected[0].parent, 5)
1590
                            else:
1591
                                detector.connectLineToLine(selected[0], lineItem, 5)
1592

    
1593
                    items.append(lineItem)
1594
                    self.graphicsView.scene.addItem(lineItem)
1595

    
1596
                pt = items[-1].endPoint()
1597
                selected = [item for item in self.graphicsView.scene.items(QPointF(pt[0], pt[1])) if
1598
                            (type(item) is QEngineeringConnectorItem and item.parent is not items[-1]) or type(item) is QEngineeringLineItem]
1599
                if selected and selected[0] is not items[-1]:
1600
                    if type(selected[0]) is QEngineeringConnectorItem:
1601
                        items[-1].connect_if_possible(selected[0].parent, 5)
1602
                    else:
1603
                        detector.connectLineToLine(selected[0], items[-1], 5)
1604

    
1605
        finally:
1606
            self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1607
            self.actionLine.tag.reset()
1608

    
1609
    '''
1610
        @brief      refresh scene
1611
        @author     humkyung
1612
        @date       2018.07.23
1613
    '''
1614

    
1615
    def onCommandRejected(self, cmd=None):
1616
        try:
1617
            if type(cmd) is PlaceLineCommand.PlaceLineCommand:
1618
                if self.actionLine.tag._polyline:
1619
                    self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1620
                self.graphicsView.scene.update()
1621
                self.actionLine.tag.reset()
1622

    
1623
                self.actionLine.setChecked(False)
1624
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
1625
                self.actionZoom.setChecked(False)
1626
            elif type(cmd) is AreaOcrCommand.AreaOcrCommand:
1627
                self.actionOCR.setChecked(False)
1628
            elif type(cmd) is PlacePolygonCommand.PlacePolygonCommand:
1629
                self.actionVendor.setChecked(False)
1630
            else:
1631
                if hasattr(self.actionLine, 'tag') and self.actionLine.tag._polyline:
1632
                    self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1633
                    self.graphicsView.scene.update()
1634
                    self.actionLine.tag.reset()
1635
                if hasattr(self.actionVendor, 'tag') and self.actionVendor.tag._polyline:
1636
                    self.graphicsView.scene.removeItem(self.actionVendor.tag._polyline)
1637
                    self.graphicsView.scene.update()
1638
                    self.actionVendor.tag.reset()
1639
                self.actionLine.setChecked(False)
1640
                self.actionZoom.setChecked(False)
1641
                self.actionOCR.setChecked(False)
1642
                self.actionVendor.setChecked(False)
1643
        finally:
1644
            self.graphicsView.useDefaultCommand()
1645

    
1646
    '''
1647
        @brief      restore to default command when user press Escape key
1648
        @author     humkyung 
1649
        @date       2018.08.09
1650
        
1651
    '''
1652

    
1653
    def keyPressEvent(self, event):
1654
        try:
1655
            if event.key() == Qt.Key_Escape:
1656
                # already catched in command
1657
                pass
1658
                # checked = self.actionGroup.checkedAction()
1659
                # if checked:
1660
                #    checked.setChecked(False)
1661
                #    self.graphicsView.useDefaultCommand()
1662
            elif event.key() == Qt.Key_1:
1663
                if self.actionImage_Drawing.isChecked():
1664
                    self.onViewImageDrawing(False)
1665
                    self.actionImage_Drawing.setChecked(False)
1666
                else:
1667
                    self.onViewImageDrawing(True)
1668
                    self.actionImage_Drawing.setChecked(True)
1669
            elif event.key() == Qt.Key_2:
1670
                if self.actionViewText.isChecked():
1671
                    self.onViewText(False)
1672
                    self.actionViewText.setChecked(False)
1673
                else:
1674
                    self.onViewText(True)
1675
                    self.actionViewText.setChecked(True)
1676
            elif event.key() == Qt.Key_3:
1677
                if self.actionViewSymbol.isChecked():
1678
                    self.onViewSymbol(False)
1679
                    self.actionViewSymbol.setChecked(False)
1680
                else:
1681
                    self.onViewSymbol(True)
1682
                    self.actionViewSymbol.setChecked(True)
1683
            elif event.key() == Qt.Key_4:
1684
                if self.actionViewLine.isChecked():
1685
                    self.onViewLine(False)
1686
                    self.actionViewLine.setChecked(False)
1687
                else:
1688
                    self.onViewLine(True)
1689
                    self.actionViewLine.setChecked(True)
1690
            elif event.key() == Qt.Key_5:
1691
                if self.actionViewUnknown.isChecked():
1692
                    self.onViewUnknown(False)
1693
                    self.actionViewUnknown.setChecked(False)
1694
                else:
1695
                    self.onViewUnknown(True)
1696
                    self.actionViewUnknown.setChecked(True)
1697
            elif event.key() == Qt.Key_6:
1698
                if self.actionViewInconsistency.isChecked():
1699
                    self.onViewInconsistency(False)
1700
                    self.actionViewInconsistency.setChecked(False)
1701
                else:
1702
                    self.onViewInconsistency(True)
1703
                    self.actionViewInconsistency.setChecked(True)
1704
            elif event.key() == Qt.Key_7:
1705
                if self.actionViewVendor_Area.isChecked():
1706
                    self.onViewVendorArea(False)
1707
                    self.actionViewVendor_Area.setChecked(False)
1708
                else:
1709
                    self.onViewVendorArea(True)
1710
                    self.actionViewVendor_Area.setChecked(True)
1711
            elif event.key() == 96:  # '`' key
1712
                if self.actionDrawing_Only.isChecked():
1713
                    self.onViewDrawingOnly(False)
1714
                    self.actionDrawing_Only.setChecked(False)
1715
                else:
1716
                    self.onViewDrawingOnly(True)
1717
                    self.actionDrawing_Only.setChecked(True)
1718
            elif event.key() == Qt.Key_M:  # merge text as vertical
1719
                from TextInfo import TextInfo
1720

    
1721
                textItems = [text for text in self.graphicsView.scene.selectedItems() if
1722
                             type(text) is QEngineeringTextItem]
1723
                if not textItems or len(textItems) is 1:
1724
                    return
1725

    
1726
                angle = None
1727
                for item in textItems:
1728
                    if angle is None:
1729
                        angle = item.angle
1730
                    else:
1731
                        if angle != item.angle:
1732
                            return
1733

    
1734
                textItems = sorted(textItems, key=lambda text: text.loc[1]) if textItems[0].angle == 0 else ( \
1735
                    sorted(textItems, key=lambda text: text.loc[0]) if textItems[0].angle == 1.57 else ( \
1736
                        sorted(textItems, key=lambda text: text.loc[1], reverse=True) if textItems[0].angle == 4.71 else \
1737
                            sorted(textItems, key=lambda text: text.loc[0], reverse=True)))
1738
                minX = sys.maxsize
1739
                minY = sys.maxsize
1740
                maxX = 0
1741
                maxY = 0
1742
                newText = ''
1743
                for text in textItems:
1744
                    if text.loc[0] < minX: minX = text.loc[0]
1745
                    if text.loc[1] < minY: minY = text.loc[1]
1746
                    if text.loc[0] + text.size[0] > maxX: maxX = text.loc[0] + text.size[0]
1747
                    if text.loc[1] + text.size[1] > maxY: maxY = text.loc[1] + text.size[1]
1748
                    newText = newText + text.text() + "\n"
1749
                    text.transfer.onRemoved.emit(text)
1750
                newText = newText[:-1]
1751

    
1752
                textInfo = TextInfo(newText, minX, minY, maxX - minX, maxY - minY, textItems[0].angle)
1753
                x = textInfo.getX()
1754
                y = textInfo.getY()
1755
                angle = textInfo.getAngle()
1756
                text = textInfo.getText()
1757
                width = textInfo.getW()
1758
                height = textInfo.getH()
1759
                item = TextItemFactory.instance().createTextItem(textInfo)
1760
                if item is not None:
1761
                    item.loc = [x, y]
1762
                    item.size = (width, height)
1763
                    item.angle = angle
1764
                    item.setDefaultTextColor(Qt.blue)
1765
                    item.addTextItemToScene(self.graphicsView.scene)
1766
                    item.transfer.onRemoved.connect(self.itemRemoved)
1767

    
1768
            QMainWindow.keyPressEvent(self, event)
1769
        except Exception as ex:
1770
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1771
                                                           sys.exc_info()[-1].tb_lineno)
1772
            self.addMessage.emit(MessageType.Error, message)
1773

    
1774
    def recognizeBatch(self, MainWindow):
1775
        '''
1776
            @brief      batch recognize symbol, text and line
1777
            @author     euisung
1778
            @date       2018.11.23
1779
        
1780
        '''
1781
        from datetime import datetime
1782
        from RecognitionDialog import QRecognitionDialog
1783

    
1784
        app_doc_data = AppDocData.instance()
1785
        project = app_doc_data.getCurrentProject()
1786
        app_doc_data.needReOpening = None
1787
        current_drawing, currentPid = None, None
1788

    
1789
        if self.graphicsView.hasImage():
1790
            current_drawing = app_doc_data.activeDrawing
1791
            currentPid = app_doc_data.activeDrawing.name
1792

    
1793
        # TODO: 무슨 의미인지 주석 필요
1794
        drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1795
        drawingCount = drawingTop.childCount()
1796
        checkedTreeItems = []
1797
        checkedDrawingPath = []
1798
        for drawing in range(drawingCount):
1799
            drawingChild = drawingTop.child(drawing)
1800
            if drawingChild.checkState(0) == 2:
1801
                checkedTreeItems.append(drawingChild)
1802
                checkedDrawingPath.append(os.path.join(project.getDrawingFilePath(), drawingChild.data(0, 0)))
1803
                if currentPid is not None and drawingChild.data(0, 0).find(currentPid) is 0:
1804
                    app_doc_data.needReOpening = False  # later check need reopening at drawUnknownItems()
1805
                    currentPid = drawingChild.data(0, 0)
1806
        # up to here
1807

    
1808
        if len(checkedDrawingPath) == 0:
1809
            self.showImageSelectionMessageBox()
1810
            return
1811

    
1812
        try:
1813
            self.onClearLog()
1814
            self.dlg = QRecognitionDialog(self, checkedDrawingPath, True)
1815
            self.dlg.exec_()
1816
            if self.dlg.isAccepted == True:
1817
                pass
1818

    
1819
            if app_doc_data.needReOpening == True:
1820
                self.open_image_drawing(current_drawing)
1821

    
1822
            # save working date-time
1823
            drawings = app_doc_data.getDrawings()
1824
            checkedDrawings = []
1825
            for checkedTreeItem in checkedTreeItems:
1826
                for drawing in drawings:
1827
                    if checkedTreeItem.data(0, 0) == drawing.name:
1828
                        if drawing:
1829
                            drawing.datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1830
                            checkedDrawings.append(drawing)
1831
                            checkedTreeItem.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1832
            app_doc_data.saveDrawings(checkedDrawings)
1833
            self.changeViewCheckedState(True)
1834
            # up to here
1835
        except Exception as ex:
1836
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1837
                                                           sys.exc_info()[-1].tb_lineno)
1838
            self.addMessage.emit(MessageType.Error, message)
1839

    
1840
    '''
1841
        @brief      recognize symbol and text
1842
        @author     humkyung
1843
        @date       2018.04.??
1844
        @history    2018.04.16  humkyung    execute line no tracing
1845
                    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
1846
                    2018.05.25  Jeongwoo    Add parameter on QRecognitionDialog.__init__() and Move thread to QRecognitionDialog
1847
                                            Remove codes below if self.dlg.isAccepted == True
1848
                    2018.05.29  Jeongwoo    Remove connects and comments
1849
                    humkyung 2018.11.05 save working date-time
1850
    '''
1851

    
1852
    def recognize(self, MainWindow):
1853
        from datetime import datetime
1854
        from RecognitionDialog import QRecognitionDialog
1855

    
1856
        if not self.graphicsView.hasImage():
1857
            self.showImageSelectionMessageBox()
1858
            return
1859

    
1860
        try:
1861
            appDocData = AppDocData.instance()
1862

    
1863
            self.onClearLog()
1864
            appDocData.needReOpening = False
1865
            drawingList = []
1866
            drawingList.append(self.path)
1867
            self.dlg = QRecognitionDialog(self, drawingList, False)
1868
            self.dlg.exec_()
1869

    
1870
            if appDocData.needReOpening == True:
1871
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
1872
                self.drawDetectedItemsToScene()
1873

    
1874
                # save working date-time
1875
                drawings = appDocData.getDrawings()
1876
                drawing = [drawing for drawing in drawings if appDocData.imgName == os.path.splitext(drawing.name)[0]]
1877
                if drawing[0]:
1878
                    drawing[0].datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1879
                    appDocData.saveDrawings(drawing)
1880

    
1881
                currentPid = appDocData.activeDrawing.name
1882

    
1883
                drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1884
                drawingCount = drawingTop.childCount()
1885

    
1886
                for drawing in range(drawingCount):
1887
                    drawingChild = drawingTop.child(drawing)
1888
                    if drawingChild.data(0, 0).find(currentPid) is 0:
1889
                        drawingChild.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1890
                self.changeViewCheckedState(True)
1891
                # up to here
1892
        except Exception as ex:
1893
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1894
                                                           sys.exc_info()[-1].tb_lineno)
1895
            self.addMessage.emit(MessageType.Error, message)
1896

    
1897
    '''
1898
        @brief      remove item from tree widget and then remove from scene
1899
        @date       2018.05.25
1900
        @author     Jeongwoo
1901
    '''
1902

    
1903
    def itemRemoved(self, item):
1904
        try:
1905
            self.itemTreeWidget.itemRemoved(item)
1906

    
1907
            matches = [_item for _item in self.graphicsView.scene.items() if
1908
                       hasattr(_item, 'connectors') and [connector for connector in _item.connectors if
1909
                                                         connector.connectedItem is item]]
1910
            for match in matches:
1911
                for connector in match.connectors:
1912
                    if connector.connectedItem is item:
1913
                        connector.connectedItem = None
1914
                        connector.highlight(False)
1915

    
1916
            # matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'remove_assoc_item')]
1917
            # for _item in matches:
1918
            #    _item.remove_assoc_item(item)
1919

    
1920
            app_doc_data = AppDocData.instance()
1921
            if type(item) is QEngineeringLineNoTextItem and item in app_doc_data.tracerLineNos:
1922
                app_doc_data.tracerLineNos.pop(app_doc_data.tracerLineNos.index(item))
1923

    
1924
            matches = [_item for _item in self.graphicsView.scene.items() if type(_item) is QEngineeringLineNoTextItem]
1925
            matches.extend([lineNo for lineNo in app_doc_data.tracerLineNos if
1926
                            type(lineNo) is QEngineeringTrimLineNoTextItem])
1927
            for match in matches:
1928
                if item is match.prop('From'):
1929
                    match.set_property('From', None)
1930
                if item is match.prop('To'):
1931
                    match.set_property('To', None)
1932

    
1933
                for run in match.runs:
1934
                    if item in run.items:
1935
                        index = run.items.index(item)
1936
                        run.items.pop(index)
1937
                        if not run.items:
1938
                            run.explode()
1939
                            if type(match) is QEngineeringTrimLineNoTextItem and not match.runs:
1940
                                app_doc_data.tracerLineNos.pop(app_doc_data.tracerLineNos.index(match))
1941
                        break
1942

    
1943
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'owner')]
1944
            for match in matches:
1945
                if match.owner is item:
1946
                    match.owner = None
1947

    
1948
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'attrs')]
1949
            # done = False
1950
            for match in matches:
1951
                for assoc in match.associations():
1952
                    if item is assoc:
1953
                        for attr in match.attrs.keys():
1954
                            if attr.AssocItem and str(item.uid) == str(attr.AssocItem.uid):
1955
                                attr.AssocItem = None
1956
                                match.attrs[attr] = ''
1957
                                # done = True
1958
                        match.remove_assoc_item(item)
1959
                        break
1960
                # if done: break
1961

    
1962
            # remove error item from inconsistency list
1963
            if type(item) is QEngineeringErrorItem:
1964
                for row in range(self.tableWidgetInconsistency.rowCount()):
1965
                    if item is self.tableWidgetInconsistency.item(row, 0).tag:
1966
                        self.tableWidgetInconsistency.removeRow(row)
1967
                        break
1968

    
1969
            if item.scene() is not None: item.scene().removeItem(item)
1970
        except Exception as ex:
1971
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1972
                                                           sys.exc_info()[-1].tb_lineno)
1973
            self.addMessage.emit(MessageType.Error, message)
1974

    
1975
    '''
1976
        @brief      recognize line
1977
        @author     humkyung
1978
        @date       2018.04.19
1979
        @history    Jeongwoo 2018.04.26 Variable name changed (texts → lineNos)
1980
                                        TextItem type changed (QEngineeringTextItem → QEngineeringLineNoTextItem)
1981
                    humkyung 2018.04.26 remove small objects before recognizing line
1982
                    Jeongwoo 2018.05.02 Show MessageBox when imageviewer doesn't have image
1983
                    Jeongwoo 2018.05.25 Move codes about LineDetector
1984
                    humkyung 2018.06.17 show progress dialog
1985
    '''
1986

    
1987
    def connect_attributes(self, MainWindow):
1988
        from LineNoTracer import LineNoTracer
1989
        from ConnectAttrDialog import QConnectAttrDialog
1990

    
1991
        if not self.graphicsView.hasImage():
1992
            self.showImageSelectionMessageBox()
1993
            return
1994

    
1995
        try:
1996
            self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView)
1997
            self.dlgConnectAttr.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint)
1998
            self.dlgConnectAttr.exec_()
1999
            if self.dlgConnectAttr.isRunned:
2000
                self.itemTreeWidget.InitLineNoItems()
2001

    
2002
                # construct line no item
2003
                line_nos = AppDocData.instance().tracerLineNos
2004
                for line_no in line_nos:
2005
                    item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2006
                    connectedItems = line_no.getConnectedItems()
2007
                    for connectedItem in connectedItems:
2008
                        if issubclass(type(connectedItem), SymbolSvgItem):
2009
                            self.itemTreeWidget.addTreeItem(item, connectedItem)
2010
                # up to here
2011

    
2012
                if self.dlgConnectAttr.obj.need_update_texts:
2013
                    for text, _text in self.dlgConnectAttr.obj.need_update_texts:
2014
                        text.setPlainText(_text)
2015

    
2016
                self.tableWidgetInconsistency.clearContents()
2017
                if self.dlgConnectAttr.ui.checkBoxValidation.isChecked():
2018
                    self.onValidation()
2019

    
2020
                self.graphicsView.invalidateScene()
2021
        except Exception as ex:
2022
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2023
                                                           sys.exc_info()[-1].tb_lineno)
2024
            self.addMessage.emit(MessageType.Error, message)
2025

    
2026
    '''
2027
        @history    2018.05.25  Jeongwoo    Moved from MainWindow
2028
                                            SvgItem and TextItem Connect with method in this class
2029
                                            Change method to add GraphicsItem
2030
                    2018.05.28  Jeongwoo    Make QGraphicsItem by symbol, text object. Not xml
2031
                    2018.05.29  Jeongwoo    Change method name and Moved from QRecognitionDialog
2032
                    2018.05.30  Jeongwoo    Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol)
2033
                                            Change Method name and seperate each item
2034
                    humkyung 2018.06.11     display difference between original and recognized image
2035
                    Jeongwoo 2018.06.18     Update Scene after all item added
2036
                    2018.11.05  euisung     add save note item because of dependency
2037
                    2018.11.05  euisung     add db delete process before save
2038
                    2018.11.12  euisung     add title block properties
2039
                    2018.11.12  euisung     db part move new method to dbUpdate
2040
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
2041
                    2018.11.29  euisung     change name drawDetectedItems() -> createDetectedItems
2042
    '''
2043

    
2044
    def createDetectedItems(self, symbolList, textInfoList, otherTextInfoList, titleBlockTextInfoList):
2045
        try:
2046
            appDocData = AppDocData.instance()
2047

    
2048
            QApplication.processEvents()
2049
            self.createDetectedSymbolItem(symbolList)
2050
            QApplication.processEvents()
2051
            self.createDetectedTextItem(textInfoList)
2052
            QApplication.processEvents()
2053
            self.createDetectedOtherTextItem(otherTextInfoList)
2054
            QApplication.processEvents()
2055
            self.createDetectedTitleBlockTextItem(titleBlockTextInfoList)
2056

    
2057
            # update scene
2058
            # self.graphicsView.scene.update(self.graphicsView.sceneRect())
2059
        except Exception as ex:
2060
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2061
                                                           sys.exc_info()[-1].tb_lineno)
2062
            self.addMessage.emit(MessageType.Error, message)
2063

    
2064
    def drawDetectedItemsToScene(self):
2065
        '''
2066
            @brief  add detected items to scene
2067
            @author euisung
2068
            @date   2018.11.26
2069
        '''
2070
        appDocData = AppDocData.instance()
2071

    
2072
        try:
2073
            for symbol in appDocData.symbols:
2074
                if issubclass(type(symbol), SymbolSvgItem):
2075
                    self.addSvgItemToScene(symbol)
2076
                else:
2077
                    self.graphicsView.scene.addItem(symbol)
2078

    
2079
            for text in appDocData.texts:
2080
                self.addTextItemToScene(text)
2081

    
2082
            for lineNo in appDocData.tracerLineNos:
2083
                self.addTextItemToScene(lineNo)
2084

    
2085
            for line in appDocData.lines:
2086
                self.graphicsView.scene.addItem(line)
2087
                line.transfer.onRemoved.connect(self.itemRemoved)
2088
                for conn in line.connectors:
2089
                    conn.transfer.onPosChanged.connect(line.onConnectorPosChaned)
2090

    
2091
            for unknown in appDocData.unknowns + appDocData.lineIndicators:
2092
                self.graphicsView.scene.addItem(unknown)
2093
        finally:
2094
            # update scene
2095
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2096

    
2097
    def postDetectLineProcess(self):
2098
        '''
2099
            @brief  check allowables among undetected items
2100
            @author euisung
2101
            @date   2018.11.15
2102
            @history    2018.11.15  euisung    no more used, moved to TextItemFactoy isLineNo()
2103
        '''
2104
        from TextItemFactory import TextItemFactory
2105

    
2106
        appDocData = AppDocData.instance()
2107

    
2108
        tableNames = ["Fluid Code", "Insulation Purpose", "PnID Number", "Piping Materials Class", "Unit Number"]
2109
        tableDatas = []
2110
        for tableName in tableNames:
2111
            tableNameFormat = tableName.replace(' ', '').replace('&&', 'n')
2112
            tableDatas.append(appDocData.getCodeTable(tableNameFormat))
2113

    
2114
        items = self.graphicsView.scene.items()
2115
        for item in items:
2116
            if type(item) is not QEngineeringTextItem:
2117
                continue
2118
            text = item.text()
2119
            for tableData in tableDatas:
2120
                for data in tableData:
2121
                    if data[3] == '':
2122
                        continue
2123
                    else:
2124
                        allows = data[3].split(',')
2125
                        for allow in allows:
2126
                            text = text.replace(allow, data[1])
2127

    
2128
            lineItem = TextItemFactory.instance().createTextItem(text)
2129
            if type(lineItem) is QEngineeringLineNoTextItem:
2130
                lineItem.loc = item.loc
2131
                lineItem.size = item.size
2132
                lineItem.angle = item.angle
2133
                lineItem.area = item.area
2134
                # lineItem.addTextItemToScene(self.graphicsView.scene)
2135
                lineItem.transfer.onRemoved.connect(self.itemRemoved)
2136
                item.transfer.onRemoved.emit(item)
2137
                appDocData.lineNos.append(lineItem)
2138

    
2139
    def createDetectedTitleBlockTextItem(self, textInfoList):
2140
        '''
2141
            @brief  draw title block
2142
            @author euisung
2143
            @date   2018.11.12
2144
            @history    2018.11.26  euisung     remove scene dependency
2145
                        2018.11.29  euisung     change name drawDetectedTitleBlockTextItem() -> createDetectedTitleBlockTextItem
2146
        '''
2147
        from TextItemFactory import TextItemFactory
2148
        import math
2149

    
2150
        try:
2151
            appDocData = AppDocData.instance()
2152

    
2153
            # parse texts
2154
            for textInfos in textInfoList:
2155
                if len(textInfos[1]) is 0:
2156
                    continue
2157

    
2158
                for textInfo in textInfos[1]:
2159
                    x = textInfo.getX()
2160
                    y = textInfo.getY()
2161
                    width = textInfo.getW()
2162
                    height = textInfo.getH()
2163
                    angle = round(math.radians(textInfo.getAngle()), 2)
2164
                    text = textInfo.getText()
2165
                    if not text: continue
2166
                    item = TextItemFactory.instance().createTextItem(textInfo)
2167

    
2168
                    if item is not None:
2169
                        item.loc = [x, y]
2170
                        item.size = (width, height)
2171
                        item.angle = angle
2172
                        item.area = textInfos[0]
2173
                        # self.addTextItemToScene(item)
2174
                        # appDocData.texts.append(item)
2175
                        appDocData.allItems.append(item)
2176
        except Exception as ex:
2177
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2178
                                                           sys.exc_info()[-1].tb_lineno)
2179
            self.addMessage.emit(MessageType.Error, message)
2180

    
2181
    '''
2182
        @brief      
2183
        @author     humkyung
2184
        @date       2018.08.23
2185
        @history    2018.11.26  euisung     remove scene dependency
2186
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
2187
                    2018.11.    euisung     no more used
2188
                    2018.11.29  euisung     change name drawDetectedLines() -> createDetectedLines
2189
    '''
2190

    
2191
    def createDetectedLines(self, lineList, worker):
2192
        appDocData = AppDocData.instance()
2193
        area = appDocData.getArea('Drawing')
2194

    
2195
        for pts in lineList:
2196
            processLine = QEngineeringLineItem(vertices=[(area.x + param[0], area.y + param[1]) for param in pts])
2197
            processLine.area = 'Drawing'
2198
            # self.graphicsView.scene.addItem(processLine)
2199
            appDocData.lines.append(processLine)
2200
            appDocData.allItems.append(processLine)
2201

    
2202
            # if processLine.length() > 100: # TODO: check critical length
2203
            #    processLine.addFlowArrow()
2204

    
2205
        # re-order process line's start,end according to flow mark
2206
        # worker.arrangeLinePosition(lines, symbols, listWidget)
2207
        # up to here
2208

    
2209
    '''
2210
        history     2018.06.09  humkyung    check length of original and connection point is 2 while parsing
2211
                    2018.11.26  euisung     remove scene dependency
2212
                    2018.11.29  euisung     change name drawDetectedSymbolItem() -> createDetectedSymbolItem
2213
    '''
2214

    
2215
    def createDetectedSymbolItem(self, symbolList):
2216
        from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
2217
        from SymbolSvgItem import SymbolSvgItem
2218
        import math
2219

    
2220
        try:
2221
            appDocData = AppDocData.instance()
2222
            project = appDocData.getCurrentProject()
2223

    
2224
            searchedMap = []
2225
            for symbol in symbolList:
2226
                pt = [float(x) for x in symbol.getSp()]
2227
                size = [symbol.getWidth(), symbol.getHeight()]
2228
                name = symbol.getName()
2229
                angle = round(math.radians(symbol.getRotatedAngle()), 2)
2230
                _type = symbol.getType()
2231
                flip = symbol.getDetectFlip()
2232
                origin = [0, 0]
2233
                if 2 == len(symbol.getOriginalPoint().split(',')):
2234
                    tokens = symbol.getOriginalPoint().split(',')
2235
                    origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
2236
                connPts = []
2237
                if symbol.getConnectionPoint() is not None and symbol.getConnectionPoint() != '':
2238
                    for param in symbol.getConnectionPoint().split('/'):
2239
                        tokens = param.split(',')
2240
                        connPts.append(
2241
                            ('AUTO', pt[0] + float(tokens[0]), pt[1] + float(tokens[1]), '0') if len(tokens) == 2 else \
2242
                                (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), '0') if len(
2243
                                    tokens) == 3 else \
2244
                                    (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), tokens[3]) if len(
2245
                                        tokens) == 4 else None)
2246

    
2247
                parentSymbol = symbol.getBaseSymbol()
2248
                childSymbol = symbol.getAdditionalSymbol()
2249
                hasInstrumentLabel = symbol.getHasInstrumentLabel()
2250

    
2251
                svgFilePath = os.path.join(project.getSvgFilePath(), _type, name + '.svg')
2252
                if os.path.isfile(svgFilePath):
2253
                    svg = SymbolSvgItem.createItem(_type, None, svgFilePath, owner=None, flip=flip)
2254
                    svg.buildItem(name, _type, angle, pt, size, origin, connPts, parentSymbol, childSymbol,
2255
                                  hasInstrumentLabel)
2256
                    svg.reCalculationRotatedItem()
2257
                    svg.area = 'Drawing'
2258

    
2259
                    # set owner - 2018.07.20 added by humkyung                   
2260
                    matches = [searched for searched in searchedMap if searched[0] == symbol.owner]
2261
                    if len(matches) == 1:
2262
                        svg.owner = matches[0][1]
2263
                    searchedMap.append((symbol, svg))
2264
                    # up to here
2265

    
2266
                    svg.transfer.onRemoved.connect(self.itemRemoved)
2267
                    # self.addSvgItemToScene(svg)
2268
                    appDocData.symbols.append(svg)
2269
                    appDocData.allItems.append(svg)
2270
                else:
2271
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2272
                    item.isSymbol = True
2273
                    item.angle = angle
2274
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2275
                    # self.graphicsView.scene.addItem(item)
2276
                    # appDocData.symbols.append(item)
2277
                    appDocData.allItems.append(item)
2278
            # up to here
2279
        except Exception as ex:
2280
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2281
                                                           sys.exc_info()[-1].tb_lineno)
2282
            self.addMessage.emit(MessageType.Error, message)
2283

    
2284
    '''
2285
        @history    2018.06.08  Jeongwoo    Add parameter on round method
2286
        @history    2018.11.02  euisung     Add save note text item
2287
        @history    2018.11.05  euisung     delete save note text item and move to drawDetectedItems()
2288
                    2018.11.26  euisung     remove scene dependency
2289
                    2018.11.29  euisung     change name drawDetectedTextItem() -> createDetectedTextItem
2290
    '''
2291

    
2292
    def createDetectedTextItem(self, textInfoList):
2293
        from TextItemFactory import TextItemFactory
2294
        import math
2295

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

    
2299
            # parse texts
2300
            for textInfo in textInfoList:
2301
                x = textInfo.getX()
2302
                y = textInfo.getY()
2303
                width = textInfo.getW()
2304
                height = textInfo.getH()
2305
                angle = round(math.radians(textInfo.getAngle()), 2)
2306
                text = textInfo.getText()
2307
                if not text: continue
2308

    
2309
                item = TextItemFactory.instance().createTextItem(textInfo)
2310
                if item is not None:
2311
                    item.loc = [x, y]
2312
                    item.size = (width, height)
2313
                    item.angle = angle
2314
                    item.area = 'Drawing'
2315
                    item.transfer.onRemoved.connect(self.itemRemoved)
2316
                    # self.addTextItemToScene(item)
2317
                    # appDocData.texts.append(item)
2318
                    appDocData.allItems.append(item)
2319
        except Exception as ex:
2320
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2321
                                                           sys.exc_info()[-1].tb_lineno)
2322
            self.addMessage.emit(MessageType.Error, message)
2323

    
2324
    '''
2325
        @brief      draw detected texts except which in drawing area
2326
        @history    2018.11.29  euisung     change name drawDetectedOtherTextItem() -> createDetectedOtherTextItem
2327
    '''
2328

    
2329
    def createDetectedOtherTextItem(self, otherTextInfoList):
2330
        from TextItemFactory import TextItemFactory
2331
        import math
2332

    
2333
        try:
2334
            appDocData = AppDocData.instance()
2335

    
2336
            # parse notes
2337
            for textInfoMap in otherTextInfoList:
2338
                if textInfoMap[0] == 'Note' or textInfoMap[1] is None:
2339
                    pass
2340

    
2341
                for textInfo in textInfoMap[1]:
2342
                    x = textInfo.getX()
2343
                    y = textInfo.getY()
2344
                    width = textInfo.getW()
2345
                    height = textInfo.getH()
2346
                    angle = round(math.radians(textInfo.getAngle()))
2347
                    text = textInfo.getText()
2348

    
2349
                    item = TextItemFactory.instance().createTextItem(textInfo)
2350

    
2351
                    item.loc = [x, y]
2352
                    item.size = (width, height)
2353
                    item.angle = angle
2354
                    item.area = textInfoMap[0]
2355
                    item.transfer.onRemoved.connect(self.itemRemoved)
2356
                    # appDocData.texts.append(item)
2357
                    appDocData.allItems.append(item)
2358
        except Exception as ex:
2359
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2360
                                                           sys.exc_info()[-1].tb_lineno)
2361
            self.addMessage.emit(MessageType.Error, message)
2362

    
2363
    '''
2364
        @brief  draw unknown items 
2365
        @author humkyung
2366
        @date   2018.06.12
2367
        @history    2018.06.14  Jeongwoo    Change method to add unknown item
2368
                    2018.06.18  Jeongwoo    Add connect on unknown item
2369
                                            Add [transfer] for using pyqtSignal
2370
                    2018.11.26  euisung     remove scene dependency
2371
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
2372
                    2018.11.27  euisung     add save to xml
2373
                    2018.11.29  euisung     change name drawUnknownItems() -> createUnknownItems
2374
    '''
2375

    
2376
    def createUnknownItems(self, path):
2377
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem
2378
        from EngineeringLineItem import QEngineeringLineItem
2379
        from EngineeringUnknownItem import QEngineeringUnknownItem
2380
        from SaveWorkCommand import SaveWorkCommand
2381

    
2382
        try:
2383
            docData = AppDocData.instance()
2384
            project = docData.getCurrentProject()
2385
            windowSize = docData.getSlidingWindowSize()
2386

    
2387
            thickness = int(windowSize[1])
2388

    
2389
            if docData.needReOpening is not None:
2390
                docData.needReOpening = True
2391

    
2392
            diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(path))
2393
            if os.path.isfile(diffFilePath):
2394
                imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255,
2395
                                        cv2.THRESH_BINARY)[1]
2396

    
2397
                ## remove line
2398
                lines = docData.lines
2399
                for line in lines:
2400
                    line.drawToImage(imgDiff, 255, thickness) if line.thickness is None else line.drawToImage(imgDiff,
2401
                                                                                                              255,
2402
                                                                                                              line.thickness)
2403
                cv2.imwrite(diffFilePath, imgDiff)
2404
                ## up to here
2405

    
2406
                imgNot = np.ones(imgDiff.shape, np.uint8)
2407
                cv2.bitwise_not(imgDiff, imgNot)
2408
                configs = docData.getConfigs('Filter', 'ErodeSize')
2409
                kernel = int(configs[0].value) if 1 == len(configs) else 3
2410
                imgNot = cv2.erode(imgNot, np.ones((kernel, kernel), np.uint8))
2411
                imgNot = cv2.dilate(imgNot, np.ones((8 + kernel, 8 + kernel), np.uint8))
2412

    
2413
                contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
2414

    
2415
                ##
2416
                idx = 0
2417
                ##
2418
                smallContours = []
2419
                minimumSize = docData.getConfigs('Filter', 'MinimumSize')
2420
                for contour in contours:
2421
                    [x, y, w, h] = cv2.boundingRect(contour)
2422

    
2423
                    # remove too small one
2424
                    if len(minimumSize) is 1:
2425
                        if (w * h < int(minimumSize[0].value) * int(minimumSize[0].value)):
2426
                            smallContours.append(contour)
2427
                            idx += 1
2428
                            continue
2429

    
2430
                    '''
2431
                    rect = QRectF(x, y, w, h)
2432
                    items = [item for item in diffItems if item.boundingRect().contains(rect)]
2433
                    if len(items) > 0: continue
2434
                    
2435
                    items = [item for item in diffItems if rect.contains(item.boundingRect())]
2436
                    for item in items:
2437
                        diffItems.remove(item)
2438
                    '''
2439

    
2440
                    # create unknown item
2441
                    epsilon = cv2.arcLength(contour, True) * 0.001
2442
                    approx = cv2.approxPolyDP(contour, epsilon, True)
2443
                    approx = [pt[0] for pt in approx]
2444
                    resultStr, resultList = self.determineRemainObject(idx, contours, imgNot)
2445
                    if resultStr == 'LineIndicator':
2446
                        item = QEngineeringUnknownItem(approx, 'True', resultList[0], resultList[1])
2447
                        docData.lineIndicators.append(item)
2448
                    elif resultStr == 'MissingLine':
2449
                        pass
2450
                    elif resultStr == 'Unknown':
2451
                        item = QEngineeringUnknownItem(approx, 'False')
2452
                        docData.unknowns.append(item)
2453
                    item.area = 'Drawing'
2454
                    docData.allItems.append(item)
2455
                    item.transfer.onRemoved.connect(self.itemRemoved)
2456
                    idx += 1
2457
                    # up to here                    
2458

    
2459
                imgNotRemoveSmall = cv2.drawContours(imgNot, smallContours, -1, 0, -1)
2460
                notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(path))
2461
                cv2.imwrite(notFilePath, imgNotRemoveSmall)
2462
            else:
2463
                message = 'can\'t found {}'.format(diffFilePath)
2464
                self.addMessage.emit(MessageType.Normal, message)
2465

    
2466
            self.dbUpdate()
2467
            SaveWorkCommand.save_to_xml()
2468
        except Exception as ex:
2469
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2470
                                                           sys.exc_info()[-1].tb_lineno)
2471
            self.addMessage.emit(MessageType.Error, message)
2472

    
2473
    def determineRemainObject(self, idx, contours, imgNot):
2474
        '''
2475
            @brief      determine remain objects -> line no indicator or unknown
2476
            @author     euisung
2477
            @date       2018.12.26
2478
            @history    2019.03.25  euisung    Change name isLineNoIndicator -> determineRemainObject
2479
        '''
2480
        import math
2481
        [x, y, w, h] = cv2.boundingRect(contours[idx])
2482

    
2483
        if (w < 250 and h < 250):
2484
            return ('Unknown', [])
2485

    
2486
        fLines = []
2487
        maxDifAngle = 3
2488
        mask = np.zeros_like(imgNot)
2489
        cv2.drawContours(mask, contours, idx, 123, -1)  # Draw filled contour in mask
2490
        out = np.zeros_like(imgNot)  # Extract out the object and place into output image
2491
        out[mask == 123] = imgNot[mask == 123]
2492

    
2493
        # Now crop
2494
        ##print(out)
2495
        (x, y) = np.where(mask == 123)
2496
        (topx, topy) = (np.min(x), np.min(y))
2497
        (bottomx, bottomy) = (np.max(x), np.max(y))
2498
        out = out[topx:bottomx + 1, topy:bottomy + 1]
2499
        h, w = out.shape[0], out.shape[1]
2500
        maxDifH, maxDifW = math.ceil(math.tan(4 * math.pi / 180) / 2 * w), math.ceil(
2501
            math.tan(4 * math.pi / 180) / 2 * h)
2502

    
2503
        # detection lines
2504
        edged2 = cv2.Canny(out, 100, 200)
2505
        lines = cv2.HoughLinesP(image=edged2, rho=1, theta=np.pi / 180, threshold=25, minLineLength=30, maxLineGap=25)
2506
        # lines = cv2.HoughLines(edged2, 1, np.pi/180, 60)
2507
        if lines is None:
2508
            return ('Unknown', [])
2509
        for line in lines:
2510
            # r, theta = line[0]
2511
            # a, b = np.cos(theta), np.sin(theta)
2512
            # x0, y0 = a * r, b * r
2513
            # x1, y1 = int(x0 + 1000 * (-b)), int(y0 + 1000 * a)
2514
            # x2, y2 = int(x0 - 1000 * (-b)), int(y0 - 1000 * a)
2515
            # cv2.line(out, (x1, y1), (x2, y2), (0, 255, 0), 3)
2516
            x1, y1, x2, y2 = line[0]
2517
            degree = math.atan2(y2 - y1, x2 - x1) * 180 / math.pi
2518
            fLine = [x1, y1, x2, y2, degree]
2519
            # print(fLine)
2520
            fLines.append(fLine)
2521

    
2522
        horLines = []
2523
        verLines = []
2524
        otherLines = []
2525
        isVH = None
2526
        for fLine in fLines:
2527
            degree = math.fabs(fLine[4])
2528
            if degree >= 90 - maxDifAngle:
2529
                verLines.append(fLine)
2530
            elif degree <= maxDifAngle:
2531
                horLines.append(fLine)
2532
            else:
2533
                otherLines.append(fLine)
2534

    
2535
        baseLines = []
2536
        baseDifV = 0
2537
        if len(horLines):
2538
            x, y = w / 2, 0
2539
            baseDifV = maxDifH
2540
            for horLine in horLines:
2541
                x1, y1, x2, y2 = horLine[0], horLine[1], horLine[2], horLine[3]
2542
                y = ((y2 - y1) / (x2 - x1)) * x + y1 - ((y2 - y1) / (x2 - x1)) * x1
2543
                horLine.append(y)
2544
            baseLines = horLines
2545
            isVH = 'H'
2546
        if len(verLines):
2547
            x, y = 0, h / 2
2548
            baseDifV = maxDifW
2549
            for verLine in verLines:
2550
                x1, y1, x2, y2 = verLine[0], verLine[1], verLine[2], verLine[3]
2551
                x = ((x2 - x1) / (y2 - y1)) * y + x1 - ((x2 - x1) / (y2 - y1)) * y1
2552
                verLine.append(x)
2553
            baseLines = verLines
2554
            isVH = 'V'
2555

    
2556
        for otherLine in otherLines:
2557
            x, y = w / 2, 0
2558
            x1, y1, x2, y2 = otherLine[0], otherLine[1], otherLine[2], otherLine[3]
2559
            y = ((y2 - y1) / (x2 - x1)) * x + y1 - ((y2 - y1) / (x2 - x1)) * x1
2560
            otherLine.append(y)
2561

    
2562
        # determine line no indicator 
2563
        if not ((len(horLines) > 0 and len(verLines) > 0) or len(otherLines) is 0 or (
2564
                len(horLines) == 0 and len(verLines) == 0)):
2565
            result, mergedOtherLine = self.isLineNoIndicator(w, h, maxDifAngle, baseDifV, baseLines, otherLines)
2566
            if result:
2567
                # print(fLines)
2568
                return ('LineIndicator', [isVH, mergedOtherLine])
2569

    
2570
        return ('Unknown', [])
2571

    
2572
    def isLineNoIndicator(self, w, h, maxDifAngle, baseDifV, baseLines, otherLines):
2573
        '''
2574
            @brief      determine line no indicator
2575
            @author     euisung
2576
            @date       2019.03.25
2577
        '''
2578
        import math
2579

    
2580
        if (w < 250 and h < 250):
2581
            return (False, None)
2582

    
2583
        isSameLine = True
2584
        i = 0
2585
        for baseLine in baseLines:
2586
            if not isSameLine: break
2587
            j = 0
2588
            for baseLinee in baseLines:
2589
                if i == j:
2590
                    j += 1
2591
                    continue
2592
                difV = math.fabs(baseLine[5] - baseLinee[5])
2593
                if difV > baseDifV:
2594
                    isSameLine = False
2595
                    break
2596
                j += 1
2597
            i += 1
2598
        if not isSameLine:
2599
            return (False, None)
2600

    
2601
        isSameLine = True
2602
        i = 0
2603
        maxY = 0
2604
        for otherLine in otherLines:
2605
            y = otherLine[5]
2606
            if math.fabs(y) > maxY:
2607
                maxY = math.fabs(y)
2608
            if not isSameLine: break
2609
            j = 0
2610
            for otherLinee in otherLines:
2611
                if i == j:
2612
                    j += 1
2613
                    continue
2614
                difV = math.fabs(otherLine[4] - otherLinee[4])
2615
                if difV > maxDifAngle:
2616
                    isSameLine = False
2617
                    break
2618
                j += 1
2619
            i += 1
2620
        if not isSameLine:
2621
            return (False, None)
2622

    
2623
        isSameLine = True
2624
        mergedOtherLine = [0, 0, 0, 0]
2625
        i = 0
2626
        maxDif = math.ceil(math.tan(4 * math.pi / 180) * maxY)
2627
        for otherLine in otherLines:
2628
            if not isSameLine: break
2629
            j = 0
2630
            for otherLinee in otherLines:
2631
                if i == j:
2632
                    j += 1
2633
                    continue
2634
                angle = math.fabs(otherLine[4] + otherLinee[4]) / 2
2635
                difV = math.fabs(otherLine[5] - otherLinee[5])
2636
                dist = math.sin((90 - angle) * math.pi / 180) * difV
2637
                if dist > maxDif:
2638
                    isSameLine = False
2639
                    break
2640
                j += 1
2641
            i += 1
2642
            mergedOtherLine[0] += otherLine[0]
2643
            mergedOtherLine[1] += otherLine[1]
2644
            mergedOtherLine[2] += otherLine[2]
2645
            mergedOtherLine[3] += otherLine[3]
2646
        if not isSameLine:
2647
            (False, None)
2648

    
2649
        # Show the output image
2650
        # print('line no indicator')
2651
        mergedOtherLine[0] = round(mergedOtherLine[0] / len(otherLines))
2652
        mergedOtherLine[1] = round(mergedOtherLine[1] / len(otherLines))
2653
        mergedOtherLine[2] = round(mergedOtherLine[2] / len(otherLines))
2654
        mergedOtherLine[3] = round(mergedOtherLine[3] / len(otherLines))
2655
        # cv2.line(out, (mergedOtherLine[0], mergedOtherLine[1]), (mergedOtherLine[2], mergedOtherLine[3]), (255, 255, 255), 3)
2656
        # cv2.imshow('Output', out)
2657
        # cv2.waitKey(0)
2658
        # cv2.destroyAllWindows()
2659
        return (True, mergedOtherLine)
2660

    
2661
    def init_add_tree_item(self, line_no_tree_item, run_item):
2662
        """ insert symbol item and find line no as owner """
2663
        # insert
2664
        self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2665
        # find
2666
        self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2667

    
2668
    def load_drawing(self, drawing):
2669
        """ load drawing """
2670
        from EngineeringRunItem import QEngineeringRunItem
2671
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2672

    
2673
        app_doc_data = AppDocData.instance()
2674
        try:
2675
            symbols = []
2676
            lines = []
2677

    
2678
            components = app_doc_data.get_components(drawing.UID)
2679
            maxValue = len(components)
2680
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2681

    
2682
            """ parsing all symbols """
2683
            for symbol in [component for component in components if int(component['SymbolType_UID']) != -1]:
2684
                item = SymbolSvgItem.from_database(symbol)
2685
                if item is not None:
2686
                    item.transfer.onRemoved.connect(self.itemRemoved)
2687
                    symbols.append(item)
2688
                    app_doc_data.symbols.append(item)
2689
                    self.addSvgItemToScene(item)
2690
                else:
2691
                    pt = [float(symbol['X']), float(symbol['Y'])]
2692
                    size = [float(symbol['Width']), float(symbol['Height'])]
2693
                    angle = float(symbol['Rotation'])
2694
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2695
                    item.isSymbol = True
2696
                    item.angle = angle
2697
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2698
                    self.graphicsView.scene.addItem(item)
2699
                    item.transfer.onRemoved.connect(self.itemRemoved)
2700

    
2701
                self.progress.setValue(self.progress.value() + 1)
2702

    
2703
            QApplication.processEvents()
2704

    
2705
            # parse texts
2706
            for text in [component for component in components if
2707
                         component['Name'] == 'Text' and component['SymbolType_UID'] == -1]:
2708
                item = QEngineeringTextItem.from_database(text)
2709
                if item is not None:
2710
                    item.uid = text['UID']
2711
                    item.attribute = text['Value']
2712
                    name = text['Name']
2713
                    item.transfer.onRemoved.connect(self.itemRemoved)
2714
                    self.addTextItemToScene(item)
2715

    
2716
                self.progress.setValue(self.progress.value() + 1)
2717

    
2718
            QApplication.processEvents()
2719

    
2720
            # note
2721
            for note in [component for component in components if
2722
                         component['Name'] == 'Note' and component['SymbolType_UID'] == -1]:
2723
                item = QEngineeringTextItem.from_database(note)
2724
                if item is not None:
2725
                    item.uid = note['UID']
2726
                    attributeValue = note['Value']
2727
                    name = note['Name']
2728
                    item.transfer.onRemoved.connect(self.itemRemoved)
2729
                    self.addTextItemToScene(item)
2730

    
2731
                self.progress.setValue(self.progress.value() + 1)
2732

    
2733
            QApplication.processEvents()
2734

    
2735
            for line in [component for component in components if
2736
                         component['Name'] == 'Line' and component['SymbolType_UID'] == -1]:
2737
                item = QEngineeringLineItem.from_database(line)
2738
                if item:
2739
                    item.transfer.onRemoved.connect(self.itemRemoved)
2740
                    self.graphicsView.scene.addItem(item)
2741
                    lines.append(item)
2742

    
2743
                self.progress.setValue(self.progress.value() + 1)
2744

    
2745
            QApplication.processEvents()
2746

    
2747
            for unknown in [component for component in components if
2748
                            component['Name'] == 'Unknown' and component['SymbolType_UID'] == -1]:
2749
                item = QEngineeringUnknownItem.from_database(unknown)
2750
                item.transfer.onRemoved.connect(self.itemRemoved)
2751
                if item is not None:
2752
                    item.transfer.onRemoved.connect(self.itemRemoved)
2753
                    self.graphicsView.scene.addItem(item)
2754

    
2755
                self.progress.setValue(self.progress.value() + 1)
2756

    
2757
            QApplication.processEvents()
2758

    
2759
            for component in [component for component in components if
2760
                              component['Name'] == 'Line NO' and component['SymbolType_UID'] == -1]:
2761
                line_no = QEngineeringLineNoTextItem.from_database(component)
2762
                if type(line_no) is QEngineeringLineNoTextItem:
2763
                    line_no.transfer.onRemoved.connect(self.itemRemoved)
2764
                    self.addTextItemToScene(line_no)
2765
                    line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2766

    
2767
                    runs = app_doc_data.get_pipe_runs(str(line_no.uid))
2768
                    if not runs: continue
2769
                    for run in runs:
2770
                        line_run = QEngineeringRunItem()
2771
                        run_items = app_doc_data.get_pipe_run_items(run['UID'])
2772
                        for record in run_items:
2773
                            uid = record['Components_UID']
2774
                            run_item = self.graphicsView.findItemByUid(uid)
2775
                            if run_item is not None:
2776
                                run_item._owner = line_no
2777
                                line_run.items.append(run_item)
2778
                        line_run.owner = line_no
2779
                        line_no.runs.append(line_run)
2780

    
2781
                        for run_item in line_run.items:
2782
                            if issubclass(type(run_item), SymbolSvgItem):
2783
                                self.init_add_tree_item(line_no_tree_item, run_item)
2784

    
2785
                self.progress.setValue(self.progress.value() + 1)
2786
            QApplication.processEvents()
2787

    
2788
            for component in [component for component in components if
2789
                              component['Name'] == 'Trim Line NO' and component['SymbolType_UID'] == -1]:
2790
                line_no = QEngineeringTrimLineNoTextItem()
2791
                line_no.uid = uuid.UUID(component['UID'])
2792

    
2793
                runs = app_doc_data.get_pipe_runs(str(line_no.uid))
2794
                if not runs: continue
2795
                for run in runs:
2796
                    line_run = QEngineeringRunItem()
2797
                    run_items = app_doc_data.get_pipe_run_items(run['UID'])
2798
                    for record in run_items:
2799
                        uid = record['Components_UID']
2800
                        run_item = self.graphicsView.findItemByUid(uid)
2801
                        if run_item is not None:
2802
                            run_item.owner = line_no
2803
                            line_run.items.append(run_item)
2804
                line_no.runs.append(line_run)
2805
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2806

    
2807
                for run_item in line_run.items:
2808
                    if issubclass(type(run_item), SymbolSvgItem):
2809
                        self.init_add_tree_item(line_no_tree_item, run_item)
2810

    
2811
                app_doc_data.tracerLineNos.append(line_no)
2812

    
2813
                self.progress.setValue(self.progress.value() + 1)
2814

    
2815
            for component in [component for component in components if
2816
                              component['Name'] == 'VendorPackage' and component['SymbolType_UID'] == -1]:
2817
                item = QEngineeringVendorItem.from_database(component)
2818
                if item is not None:
2819
                    item.transfer.onRemoved.connect(self.itemRemoved)
2820
                    self.graphicsView.scene.addItem(item)
2821

    
2822
            # connect flow item to line
2823
            for line in lines:
2824
                line.update_arrow()
2825
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
2826
            #    for line in lines:
2827
            #        if flowMark.owner is line:
2828
            #            line._flowMark.append(flowMark)
2829
            #            flowMark.setParentItem(line)
2830
            # up to here
2831

    
2832
            """ update scene """
2833
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2834
            for item in self.graphicsView.scene.items():
2835
                item.setVisible(True)
2836

    
2837
                # binding items
2838
                if hasattr(item, 'owner'):
2839
                    item.owner
2840
                if hasattr(item, 'connectors'):
2841
                    for connector in item.connectors:
2842
                        connector.connectedItem
2843

    
2844
        except Exception as ex:
2845
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2846
                                                           sys.exc_info()[-1].tb_lineno)
2847
            self.addMessage.emit(MessageType.Error, message)
2848
        finally:
2849
            app_doc_data.clearTempDBData()
2850
            self.itemTreeWidget.update_item_count()
2851
            self.itemTreeWidget.expandAll()
2852
            # self.graphicsView.scene.blockSignals(False)
2853

    
2854
    '''
2855
        @brief      load recognition result
2856
        @author     humkyung
2857
        @date       2018.04.??
2858
        @history    humkyung 2018.01.12 parse originalpoint and connectionpoint
2859
                    Jeongwoo 2018.04.17 add QGraphicItem with Rotated text
2860
                    Jeongwoo 2018.04.23 Change to Draw texts on QEngineeringTextItem
2861
                    humkyung 2018.04.23 connect item remove slot to result tree
2862
                    Jeongwoo 2018.04.25 Add if state with QEngineeringNoteItem
2863
                    Jeongwoo 2018.04.26 Change method to create TextItem object with TextItemFactory
2864
                    Jeongwoo 2018.05.03 Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
2865
                    Jeongwoo 2018.05.29 Change method name / Change method to add item / Add Line item
2866
                    Jeongwoo 2018.05.30 Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol) / Change method name / Change XML NODE NAMES
2867
                    Jeongwoo 2018.06.12 Add LineNoTextItem from LINE_NO
2868
                    Jeongwoo 2018.06.14 Add UnknownItem from UNKNOWN
2869
                    Jeongwoo 2018.06.18 Update Scene after all item added
2870
                                        Add connect on unknown item
2871
                                        Add [transfer] for using pyqtSignal
2872
                    kyouho  2018.07.12  Add line property logic
2873
                    humkyung 2018.08.22 show progress while loading xml file
2874
                    2018.11.22      euisung     fix note road
2875
    '''
2876

    
2877
    def loadRecognitionResultFromXml(self, xmlPath):
2878
        docData = AppDocData.instance()
2879
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
2880
        from EngineeringRunItem import QEngineeringRunItem
2881
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2882

    
2883
        try:
2884
            # self.graphicsView.scene.blockSignals(True)
2885

    
2886
            symbols = []
2887
            lines = []
2888

    
2889
            xml = parse(xmlPath)
2890
            root = xml.getroot()
2891

    
2892
            maxValue = 0
2893
            maxValue = maxValue + len(list(root.iter('SYMBOL'))) - len(
2894
                list(root.iterfind('LINENOS/LINE_NO/RUN/SYMBOL'))) - len(
2895
                list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/SYMBOL')))
2896
            maxValue = maxValue + len(list(root.iterfind('TEXTINFOS/ATTRIBUTE')))
2897
            maxValue = maxValue + len(list(root.iterfind('NOTES/ATTRIBUTE')))
2898
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
2899
            maxValue = maxValue + len(list(root.iter('LINE'))) - len(
2900
                list(root.iterfind('LINENOS/LINE_NO/RUN/LINE'))) - len(
2901
                list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/LINE')))
2902
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
2903
            # maxValue = maxValue + len(list(root.iter('SIZETEXT')))
2904
            maxValue = maxValue + len(list(root.iter('TRIM_LINE_NO')))
2905
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2906

    
2907
            """ parsing all symbols """
2908
            for symbol in root.find('SYMBOLS').iter('SYMBOL'):
2909
                item = SymbolSvgItem.fromXml(symbol)
2910
                if item is not None:
2911
                    item.transfer.onRemoved.connect(self.itemRemoved)
2912
                    symbols.append(item)
2913
                    docData.symbols.append(item)
2914
                    self.addSvgItemToScene(item)
2915
                else:
2916
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2917
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2918
                    angle = float(symbol.find('ANGLE').text)
2919
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2920
                    item.isSymbol = True
2921
                    item.angle = angle
2922
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2923
                    self.graphicsView.scene.addItem(item)
2924
                    item.transfer.onRemoved.connect(self.itemRemoved)
2925

    
2926
                self.progress.setValue(self.progress.value() + 1)
2927

    
2928
            QApplication.processEvents()
2929

    
2930
            # parse texts
2931
            for text in root.find('TEXTINFOS').iter('ATTRIBUTE'):
2932
                item = QEngineeringTextItem.fromXml(text)
2933
                if item is not None:
2934
                    uid = text.find('UID')
2935
                    attributeValue = text.find('ATTRIBUTEVALUE')
2936
                    name = text.find('NAME').text
2937
                    item.transfer.onRemoved.connect(self.itemRemoved)
2938
                    self.addTextItemToScene(item)
2939
                    # docData.texts.append(item)
2940

    
2941
                    if name == 'TEXT':
2942
                        if uid is not None and attributeValue is not None:
2943
                            item.uid = uid.text
2944
                            item.attribute = attributeValue.text
2945

    
2946
                self.progress.setValue(self.progress.value() + 1)
2947

    
2948
            QApplication.processEvents()
2949

    
2950
            # note
2951
            for text in root.find('NOTES').iter('ATTRIBUTE'):
2952
                item = QEngineeringTextItem.fromXml(text)
2953
                if item is not None:
2954
                    uid = text.find('UID')
2955
                    attributeValue = text.find('ATTRIBUTEVALUE')
2956
                    name = text.find('NAME').text
2957
                    item.transfer.onRemoved.connect(self.itemRemoved)
2958
                    self.addTextItemToScene(item)
2959

    
2960
                    if name == 'NOTE':
2961
                        if uid is not None:
2962
                            item.uid = uid.text
2963

    
2964
                self.progress.setValue(self.progress.value() + 1)
2965

    
2966
            QApplication.processEvents()
2967

    
2968
            for line in root.find('LINEINFOS').iter('LINE'):
2969
                item = QEngineeringLineItem.fromXml(line)
2970
                if item:
2971
                    item.transfer.onRemoved.connect(self.itemRemoved)
2972
                    self.graphicsView.scene.addItem(item)
2973
                    lines.append(item)
2974

    
2975
                self.progress.setValue(self.progress.value() + 1)
2976

    
2977
            QApplication.processEvents()
2978

    
2979
            for unknown in root.iter('UNKNOWN'):
2980
                item = QEngineeringUnknownItem.fromXml(unknown)
2981
                if item is not None:
2982
                    item.transfer.onRemoved.connect(self.itemRemoved)
2983
                    self.graphicsView.scene.addItem(item)
2984

    
2985
                self.progress.setValue(self.progress.value() + 1)
2986

    
2987
            QApplication.processEvents()
2988

    
2989
            # """ add tree widget """
2990
            # for item in symbols:
2991
            #    docData.symbols.append(item)
2992
            #    self.addSvgItemToScene(item)
2993
            #    self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2994

    
2995
            for line_no_node in root.find('LINENOS').iter('LINE_NO'):
2996
                line_no = QEngineeringLineNoTextItem.fromXml(line_no_node)
2997
                if line_no is None: continue
2998
                line_no.transfer.onRemoved.connect(self.itemRemoved)
2999
                self.addTextItemToScene(line_no)
3000
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
3001
                if type(line_no) is not QEngineeringLineNoTextItem: continue
3002

    
3003
                runs_node = line_no_node.findall('RUN')
3004
                if runs_node is None: continue
3005

    
3006
                for run_node in runs_node:
3007
                    line_run = QEngineeringRunItem()
3008
                    for child_node in run_node:
3009
                        uidElement = child_node.find('UID')
3010
                        if uidElement is not None:
3011
                            uid = uidElement.text
3012
                            run_item = self.graphicsView.findItemByUid(uid)
3013
                            if run_item is not None:
3014
                                run_item._owner = line_no
3015
                                line_run.items.append(run_item)
3016
                    line_run.owner = line_no
3017
                    line_no.runs.append(line_run)
3018

    
3019
                    for run_item in line_run.items:
3020
                        if issubclass(type(run_item), SymbolSvgItem):
3021
                            self.init_add_tree_item(line_no_tree_item, run_item)
3022

    
3023
                # docData.tracerLineNos.append(line_no)
3024

    
3025
                self.progress.setValue(self.progress.value() + 1)
3026
            QApplication.processEvents()
3027

    
3028
            for trimLineNo in root.iter('TRIM_LINE_NO'):
3029
                line_no = QEngineeringTrimLineNoTextItem()
3030
                line_no.uid = uuid.UUID(trimLineNo.find('UID').text)
3031

    
3032
                run = trimLineNo.find('RUN')
3033
                if run is not None:
3034
                    line_run = QEngineeringRunItem()
3035
                    for child in run:
3036
                        uidElement = child.find('UID')
3037
                        if uidElement is not None:
3038
                            uid = uidElement.text
3039
                            run_item = self.graphicsView.findItemByUid(uid)
3040
                            if run_item is not None:
3041
                                run_item.owner = line_no
3042
                                line_run.items.append(run_item)
3043
                    line_no.runs.append(line_run)
3044
                    line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
3045

    
3046
                    for run_item in line_run.items:
3047
                        if issubclass(type(run_item), SymbolSvgItem):
3048
                            self.init_add_tree_item(line_no_tree_item, run_item)
3049

    
3050
                    docData.tracerLineNos.append(line_no)
3051

    
3052
                self.progress.setValue(self.progress.value() + 1)
3053
            QApplication.processEvents()
3054

    
3055
            if root.find('VENDORS') is not None:
3056
                for vendor in root.find('VENDORS').iter('VENDOR'):
3057
                    item = QEngineeringVendorItem.fromXml(vendor)
3058
                    item.transfer.onRemoved.connect(self.itemRemoved)
3059
                    self.graphicsView.scene.addItem(item)
3060

    
3061
            # connect flow item to line
3062
            for line in lines:
3063
                line.update_arrow()
3064
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
3065
            #    for line in lines:
3066
            #        if flowMark.owner is line:
3067
            #            line._flowMark.append(flowMark)
3068
            #            flowMark.setParentItem(line)
3069
            # up to here
3070

    
3071
            """ update scene """
3072
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
3073
            for item in self.graphicsView.scene.items():
3074
                item.setVisible(True)
3075

    
3076
                # binding items
3077
                if hasattr(item, 'owner'):
3078
                    item.owner
3079
                if hasattr(item, 'connectors'):
3080
                    for connector in item.connectors:
3081
                        connector.connectedItem
3082

    
3083
        except Exception as ex:
3084
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3085
                                                           sys.exc_info()[-1].tb_lineno)
3086
            self.addMessage.emit(MessageType.Error, message)
3087
        finally:
3088
            self.itemTreeWidget.update_item_count()
3089
            self.itemTreeWidget.expandAll()
3090
            # self.graphicsView.scene.blockSignals(False)
3091

    
3092
    '''
3093
        @brief      Remove added item on same place and Add GraphicsItem
3094
        @author     Jeongwoo
3095
        @date       2018.05.25
3096
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
3097
                    2018.06.18  Jeongwoo    Set Z-index
3098
    '''
3099

    
3100
    def addSvgItemToScene(self, svgItem):
3101
        svgItem.addSvgItemToScene(self.graphicsView.scene)
3102

    
3103
    '''
3104
        @brief      Remove added item on same place and Add GraphicsItem
3105
        @author     Jeongwoo
3106
        @date       2018.05.25
3107
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
3108
                    2018.06.05  Jeongwoo    Remove Size condition
3109
                    2018.06.18  Jeongwoo    Set Z-index
3110
    '''
3111

    
3112
    def addTextItemToScene(self, textItem):
3113
        textItem.addTextItemToScene(self.graphicsView.scene)
3114

    
3115
    '''
3116
        @brief      Remove added item on same place and Add GraphicsItem
3117
        @author     Jeongwoo
3118
        @date       2018.05.29
3119
        @history    2018.06.18  Jeongwoo    Set Z-index
3120
    '''
3121

    
3122
    def addLineItemToScene(self, lineItem):
3123
        self.graphicsView.scene.addItem(lineItem)
3124

    
3125
    '''
3126
        @brief      generate output xml file
3127
        @author     humkyung
3128
        @date       2018.04.23
3129
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
3130
    '''
3131

    
3132
    def generateOutput(self):
3133
        import XmlGenerator as xg
3134

    
3135
        if not self.graphicsView.hasImage():
3136
            self.showImageSelectionMessageBox()
3137
            return
3138

    
3139
        try:
3140
            appDocData = AppDocData.instance()
3141

    
3142
            ## collect items
3143
            appDocData.lines.clear()
3144
            appDocData.lines = [item for item in self.graphicsView.scene.items() if
3145
                                type(item) is QEngineeringLineItem and item.owner is None]
3146

    
3147
            appDocData.symbols.clear()
3148
            appDocData.symbols = [item for item in self.graphicsView.scene.items() if
3149
                                  issubclass(type(item), SymbolSvgItem) and item.owner is None]
3150

    
3151
            appDocData.equipments.clear()
3152
            for item in self.graphicsView.scene.items():
3153
                if type(item) is QEngineeringEquipmentItem:
3154
                    appDocData.equipments.append(item)
3155

    
3156
            appDocData.texts.clear()
3157
            appDocData.texts = [item for item in self.graphicsView.scene.items() if
3158
                                issubclass(type(item), QEngineeringTextItem) and type(
3159
                                    item) is not QEngineeringLineNoTextItem]
3160
            ## up to here
3161

    
3162
            appDocData.imgOutput = np.ones((appDocData.activeDrawing.height, appDocData.activeDrawing.width),
3163
                                           np.uint8) * 255
3164
            xg.writeOutputXml(appDocData.imgName, appDocData.activeDrawing.width,
3165
                              appDocData.activeDrawing.height)  # TODO: check
3166
            project = appDocData.getCurrentProject()
3167
            cv2.imwrite(os.path.join(project.getTempPath(), 'OUTPUT.png'), appDocData.imgOutput)
3168
        except Exception as ex:
3169
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3170
                                                           sys.exc_info()[-1].tb_lineno)
3171
            self.addMessage.emit(MessageType.Error, message)
3172

    
3173
    '''
3174
        @brief      resetting attribute at secne
3175
        @author     kyoyho
3176
        @date       2018.08.21
3177
    '''
3178
    """
3179
    def checkAttribute(self):
3180
        try:
3181

3182
            docData = AppDocData.instance()
3183
            if not self.graphicsView.hasImage():
3184
                return
3185

3186
            # symbol 경우
3187
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringSpecBreakItem and type(item) is not QEngineeringEndBreakItem]
3188
            for item in items:
3189
                attrs = item.attrs
3190
                
3191
                removeAttrList = []
3192
                for attr in attrs:
3193
                    if type(attr) is tuple:
3194
                        continue
3195

3196
                    if attr is None:
3197
                        removeAttrList.append(attr)
3198
                        continue
3199

3200
                    attrInfo = docData.getSymbolAttributeByUID(attr.UID)
3201
                    if attrInfo is None:
3202
                        removeAttrList.append(attr)
3203
                    # 해당 attribute가 맞는지 확인
3204
                    else:
3205
                        attrType = attrInfo.AttributeType
3206
                        _type = type(attr)
3207
                        if attrType == 'Symbol Item':
3208
                            if not issubclass(_type, SymbolSvgItem):
3209
                                removeAttrList.append(attr)
3210
                        elif attrType == 'Text Item':
3211
                            if _type is not QEngineeringTextItem:
3212
                                removeAttrList.append(attr)
3213
                        elif attrType == 'Int':
3214
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
3215
                                removeAttrList.append(attr)
3216
                        elif attrType == 'String':
3217
                            if _type is not UserInputAttribute:
3218
                                removeAttrList.append(attr)
3219

3220
                for attr in removeAttrList:
3221
                    del attrs[attr]
3222

3223
            # Line No Text Item의 경우
3224
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringLineNoTextItem)]
3225
            for item in items:
3226
                attrs = item.attrs
3227
                
3228
                removeAttrList = []
3229
                for attr in attrs:
3230
                    if type(attr) is UserInputAttribute:
3231
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
3232
                        if attrInfo is None:
3233
                            removeAttrList.append(attr)
3234

3235
                for attr in removeAttrList:
3236
                    del attrs[attr]
3237

3238
        except Exception as ex:
3239
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
3240
                self.addMessage.emit(MessageType.Error, message)
3241
    """
3242
    '''
3243
        @brief      Check Number
3244
        @author     kyouho
3245
        @date       2018.08.20
3246
    '''
3247

    
3248
    def isNumber(self, num):
3249
        p = re.compile('(^[0-9]+$)')
3250
        result = p.match(num)
3251

    
3252
        if result:
3253
            return True
3254
        else:
3255
            return False
3256

    
3257
    '''
3258
        @brief      find overlap Connector
3259
        @author     kyouho
3260
        @date       2018.08.28
3261
    '''
3262

    
3263
    def findOverlapConnector(self, connectorItem):
3264
        from shapely.geometry import Point
3265
        from EngineeringConnectorItem import QEngineeringConnectorItem
3266
        itemList = []
3267

    
3268
        x = connectorItem.center()[0]
3269
        y = connectorItem.center()[1]
3270

    
3271
        connectors = [item for item in self.graphicsView.scene.items() if
3272
                      type(item) is QEngineeringConnectorItem and item != connectorItem]
3273
        for connector in connectors:
3274
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
3275
                itemList.append(connector.parent)
3276

    
3277
        return itemList
3278

    
3279

    
3280
if __name__ == '__main__':
3281
    import locale
3282
    from PyQt5.QtCore import QTranslator
3283
    from License import QLicenseDialog
3284
    from ProjectDialog import Ui_Dialog
3285
    from App import App
3286

    
3287
    app = App(sys.argv)
3288
    try:
3289
        if True == QLicenseDialog.check_license_key():
3290
            dlg = Ui_Dialog()
3291
            selectedProject = dlg.showDialog()
3292
            if selectedProject is not None:
3293
                AppDocData.instance().setCurrentProject(selectedProject)
3294
                app._mainWnd = MainWindow.instance()
3295
                app._mainWnd.show()
3296
                sys.exit(app.exec_())
3297
    except Exception as ex:
3298
        print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3299
                                                   sys.exc_info()[-1].tb_lineno))
3300
    finally:
3301
        pass
클립보드 이미지 추가 (최대 크기: 500 MB)