프로젝트

일반

사용자정보

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

hytos / DTI_PID / DTI_PID / MainWindow.py @ 54eedb38

이력 | 보기 | 이력해설 | 다운로드 (140 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
from openpyxl import *
70
from openpyxl.styles import *
71

    
72

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

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

    
93
    def __init__(self):
94
        from App import App
95
        from LineTypeConditions import LineTypeConditions
96

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

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

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

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

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

    
141
        self.toolBar.insertWidget(self.actionOCR, self.lineComboBox)
142
        self.toolBar.insertSeparator(self.actionOCR)
143

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

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

    
166
        self.verticalLayout.addWidget(self.graphicsView)
167

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

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

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

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

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

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

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

    
277
        self.delimiter = '"'
278

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
488
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root,
489
                                       [file, drawing[0].datetime if drawing else None])
490
                item.setIcon(0, QIcon(':newPrefix/image.png'))
491
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
492
                item.setCheckState(0, Qt.Unchecked)
493

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

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

    
506
    def open_selected_drawing(self, item, column):
507
        """
508
        @brief      open selected p&id drawing
509
        @author     humkyung
510
        @date       18.11.02
511
        """
512
        appDocData = AppDocData.instance()
513
        drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), item.text(0))
514
        self.onOpenImageDrawing(drawing)
515

    
516
    def onShowDetectSymbol(self):
517
        from DetectSymbolDialog import QDetectSymbolDialog
518

    
519
        dlgDetectSymbol = QDetectSymbolDialog(self)
520
        dlgDetectSymbol.show()
521
        dlgDetectSymbol.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

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

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

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

    
580
        from TextItemEditDialog import QTextItemEditDialog
581

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

    
586
    '''
587
        @brief      show unknownitem's count
588
        @author     humkyung
589
        @date       2018.08.23
590
        @history    humkyung 2018.08.30 display count of symbol, line, text
591
    '''
592

    
593
    def onSceneChanged(self):
594
        items = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
595
        if len(items) > 0:
596
            self.labelStatus.setText(
597
                "<font color='red'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
598
        else:
599
            self.labelStatus.setText(
600
                "<font color='black'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
601

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

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

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

    
612
        self.itemTreeWidget.sceneChanged(self.graphicsView.scene.items())
613

    
614
    def dbUpdate(self):
615
        '''
616
            @brief      db update when save or recognition
617
            @author     euisung
618
            @date       2018.11.12
619
            @history    2018.11.02      euisung     remove scene dependency
620
        '''
621
        try:
622
            appDocData = AppDocData.instance()
623

    
624
            titleBlockProps = appDocData.getTitleBlockProperties()
625
            # items = self.graphicsView.scene.items()
626
            items = appDocData.allItems
627
            titleBlockItems = []
628
            for item in items:
629
                # if type(item) is QEngineeringLineNoTextItem:
630
                #    item.saveLineData()
631
                if type(item) is QEngineeringTextItem:
632
                    for titleBlockProp in titleBlockProps:
633
                        if item.area == titleBlockProp[0]:
634
                            titleBlockItems.append(item)
635

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

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

    
659
    def save_drawing_if_necessary(self):
660
        """ask to user to save drawing or not when drawing is modified"""
661

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

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

    
680
    def actionSaveCliked(self):
681
        from EngineeringAbstractItem import QEngineeringAbstractItem
682
        from SaveWorkCommand import SaveWorkCommand
683

    
684
        try:
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
    '''
733
        @brief      refresh resultPropertyTableWidget
734
        @author     kyouho
735
        @date       2018.07.19
736
    '''
737

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

    
743
    '''
744
        @brief  add message listwidget
745
        @author humkyung
746
        @date   2018.07.31
747
    '''
748

    
749
    def onAddMessage(self, messageType, message):
750
        from AppDocData import MessageType
751

    
752
        try:
753
            current = QDateTime.currentDateTime()
754

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

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

    
765
    '''
766
        @brief      clear log
767
        @author     humkyung
768
        @date       2018.08.01
769
    '''
770

    
771
    def onClearLog(self):
772
        self.listWidgetLog.clear()
773

    
774
    '''
775
        @brief      rotate selected symbol
776
        @author     humkyung
777
        @date       2018.08.15
778
    '''
779

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

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

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

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

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

    
815
        self.graphicsView.command = self.actionVendor.tag
816

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

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

    
847
    def fitWindow(self, action):
848
        self.graphicsView.useDefaultCommand()
849
        self.graphicsView.zoomImageInit()
850

    
851
    def scene_changed(self):
852
        """update modified flag"""
853

    
854
        app_doc_data = AppDocData.instance()
855
        app_doc_data.activeDrawing.modified = True
856
        title = self.windowTitle()
857
        self.setWindowTitle(title if title[-1] == '*' else title + '*')
858

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

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

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

    
897
    def on_help(self):
898
        """ open help file """
899
        import os
900

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

    
909
    '''
910
        @brief      selection changed
911
        @author     humkyung
912
        @date       2018.06.27
913
        @history    humkung 2018.07.08 call tree widget's findItem
914
    '''
915

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

    
932
    '''
933
        @brief      Initialize scene and itemTreeWidget
934
        @author     Jeongwoo
935
        @date       2018.06.14
936
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
937
    '''
938

    
939
    def onInitializeScene(self, action):
940
        if not self.graphicsView.hasImage():
941
            self.actionEquipment.setChecked(False)
942
            self.showImageSelectionMessageBox()
943

    
944
            return
945

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

    
954
                appDocData = AppDocData.instance()
955
                appDocData.clearItemList(True)
956

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

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

    
977
                if self.path is not None:
978
                    baseName = os.path.basename(self.path)
979
                    self.itemTreeWidget.setCurrentPID(baseName)
980

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

    
986
    '''
987
        @brief      Manage Checkable Action statement
988
        @author     Jeongwoo
989
        @date       2018.05.10
990
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
991
    '''
992

    
993
    def actionGroupTriggered(self, action):
994
        if hasattr(self.actionLine, 'tag'):
995
            self.actionLine.tag.onRejected.emit(None)
996

    
997
        if hasattr(self.actionVendor, 'tag'):
998
            self.actionVendor.tag.onRejected.emit(None)
999

    
1000
        if self.graphicsView.command is not None:
1001
            self.graphicsView.useDefaultCommand()
1002

    
1003
        for _action in self.actionGroup.actions():
1004
            _action.setChecked(False)
1005

    
1006
        action.setChecked(True)
1007

    
1008
    '''
1009
        @brief      Create Equipment
1010
        @author     Jeongwoo
1011
        @date       18.05.03
1012
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
1013
    '''
1014

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

    
1026
    '''
1027
        @brief      Create Nozzle
1028
        @author     Jeongwoo
1029
        @date       2018.05.03
1030
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
1031
    '''
1032

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

    
1044
    '''
1045
        @brief      Area OCR
1046
        @author     Jeongwoo
1047
        @date       18.04.18
1048
        @history    2018.05.02  Jeongwoo    Change graphicsView.command by actionOCR checked state
1049
                                            Show MessageBox when imageviewer doesn't have image
1050
    '''
1051

    
1052
    def onAreaOcr(self):
1053
        if not self.graphicsView.hasImage():
1054
            self.actionOCR.setChecked(False)
1055
            self.showImageSelectionMessageBox()
1056
            return
1057

    
1058
        if self.actionOCR.isChecked():
1059
            cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView)
1060
            cmd.onSuccess.connect(self.onRecognizeText)
1061
            cmd.onRejected.connect(self.onCommandRejected)
1062
            self.graphicsView.command = cmd
1063
        else:
1064
            self.graphicsView.useDefaultCommand()
1065

    
1066
    '''
1067
        @brief      show text recognition dialog
1068
        @author     humkyung
1069
        @date       2018.08.08
1070
    '''
1071

    
1072
    def onRecognizeText(self, x, y, width, height):
1073
        from OcrResultDialog import QOcrResultDialog
1074

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

    
1108
    '''
1109
        @brief  area configuration
1110
    '''
1111

    
1112
    def areaConfiguration(self):
1113
        from ConfigurationAreaDialog import QConfigurationAreaDialog
1114
        if not self.graphicsView.hasImage():
1115
            self.showImageSelectionMessageBox()
1116
            return
1117
        self.onCommandRejected()
1118
        self.dlgConfigurationArea = QConfigurationAreaDialog(self)
1119
        self.dlgConfigurationArea.show()
1120
        self.dlgConfigurationArea.exec_()
1121

    
1122
    '''
1123
        @brief  configuration
1124
    '''
1125

    
1126
    def configuration(self):
1127
        from ConfigurationDialog import QConfigurationDialog
1128

    
1129
        self.dlgConfiguration = QConfigurationDialog(self)
1130
        # self.dlgConfiguration.show()
1131
        if QDialog.Accepted == self.dlgConfiguration.exec_():
1132
            QEngineeringLineItem.LINE_TYPE_COLORS.clear()
1133
            QEngineeringInstrumentItem.INST_COLOR = None
1134

    
1135
    '''
1136
        @brief  show special item types dialog 
1137
        @author humkyung
1138
        @date   2019.08.10
1139
    '''
1140

    
1141
    def on_show_special_item_types(self):
1142
        from SpecialItemTypesDialog import QSpecialItemTypesDialog
1143

    
1144
        dlg = QSpecialItemTypesDialog(self)
1145
        dlg.exec_()
1146

    
1147
    def on_show_data_transfer(self):
1148
        """ show data transfer dialog """
1149
        from DataTransferDialog import QDataTransferDialog
1150

    
1151
        dlg = QDataTransferDialog(self)
1152
        dlg.exec_()
1153

    
1154
    def on_show_data_export(self):
1155
        """ show data export dialog """
1156
        from DataExportDialog import QDataExportDialog
1157

    
1158
        dlg = QDataExportDialog(self)
1159
        dlg.exec_()
1160

    
1161
    def on_show_eqp_datasheet_export(self):
1162
        """ show eqp datasheet export dialog """
1163
        from EqpDatasheetExportDialog import QEqpDatasheetExportDialog
1164

    
1165
        dlg = QEqpDatasheetExportDialog(self)
1166
        dlg.exec_()
1167

    
1168
    def on_show_opc_relation(self):
1169
        """ show opc relation dialog """
1170
        from OPCRelationDialog import QOPCRelationDialog
1171

    
1172
        dlg = QOPCRelationDialog(self)
1173
        dlg.exec_()
1174

    
1175
    '''
1176
        @brief  show nominal diameter dialog 
1177
        @author humkyung
1178
        @date   2018.06.28
1179
    '''
1180

    
1181
    def onShowCodeTable(self):
1182
        from CodeTableDialog import QCodeTableDialog
1183

    
1184
        dlg = QCodeTableDialog(self)
1185
        dlg.exec_()
1186

    
1187
    '''
1188
        @brief  show HMB data
1189
        @author humkyung
1190
        @date   2018.07.11
1191
    '''
1192

    
1193
    def onHMBData(self):
1194
        from HMBDialog import QHMBDialog
1195

    
1196
        dlg = QHMBDialog(self)
1197
        dlg.show()
1198
        dlg.exec_()
1199

    
1200
    '''
1201
        @brief  show line data list 
1202
        @author humkyung
1203
        @date   2018.05.03
1204
    '''
1205

    
1206
    def showItemDataList(self):
1207
        from ItemDataExportDialog import QItemDataExportDialog
1208

    
1209
        self.dlgLineDataList = QItemDataExportDialog(self)
1210
        self.dlgLineDataList.exec_()
1211

    
1212
    def showTextDataList(self):
1213
        '''
1214
            @brief      show all text item in scene
1215
            @author     euisung
1216
            @date       2019.04.18
1217
        '''
1218
        try:
1219
            if not self.graphicsView.hasImage():
1220
                self.showImageSelectionMessageBox()
1221
                return
1222

    
1223
            self.onCommandRejected()
1224
            dialog = QTextDataListDialog(self)
1225
            dialog.show()
1226
            dialog.exec_()
1227
        except Exception as ex:
1228
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1229
                                                          sys.exc_info()[-1].tb_lineno)
1230
            self.addMessage.emit(MessageType.Error, message)
1231

    
1232
    '''
1233
        @brief  Show Image Selection Guide MessageBox
1234
        @author Jeongwoo
1235
        @date   2018.05.02
1236
    '''
1237

    
1238
    def showImageSelectionMessageBox(self):
1239
        QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("First select image drawing"))
1240

    
1241
    '''
1242
        @brief  change selected lines' type by selected line type
1243
        @author humkyung
1244
        @date   2018.06.27
1245
    '''
1246

    
1247
    def onLineTypeChanged(self, param):
1248
        lineType = self.lineComboBox.itemText(param)
1249
        selected = [item for item in self.graphicsView.scene.selectedItems() if type(item) is QEngineeringLineItem]
1250
        if selected:
1251
            for item in selected:
1252
                item.lineType = lineType
1253

    
1254
    def display_colors(self, value):
1255
        """ display colors """
1256
        from DisplayColors import DisplayColors
1257
        from DisplayColors import DisplayOptions
1258

    
1259
        DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value == True else DisplayOptions.DisplayByLineType
1260
        if hasattr(self, 'graphicsView'):
1261
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1262
            DisplayColors.instance().save_data()
1263

    
1264
    '''
1265
        @brief      Open image drawing file and then display it
1266
        @author     humkyung
1267
        @date       2018.??.??
1268
        @history    18.04.23 Jeongwoo    Add AppDocData.instance().setCurrentPidSource
1269
                    18.04.23 Jeongwoo    Add Store Set Current Pid Image on AppDocData
1270
                    18.05.02 Jeongwoo    Add useDefaultCommand()
1271
                    humkyung 2018.05.24 load recognition result file if exists
1272
                    Jeongwoo 2018.05.29 load data on xml if xml file exist
1273
                    humkyung 2018.08.22 clear scene before loading xml file
1274
    '''
1275

    
1276
    def onOpenImageDrawing(self, path=None):
1277
        from Drawing import Drawing
1278

    
1279
        try:
1280
            self.save_drawing_if_necessary()
1281
            if hasattr(self, '_save_work_cmd'):
1282
                self._save_work_cmd.wait()
1283

    
1284
            app_doc_data = AppDocData.instance()
1285

    
1286
            project = app_doc_data.getCurrentProject()
1287

    
1288
            self.path = self.graphicsView.loadImageFromFile(project.getDrawingFilePath(),
1289
                                                            path if type(path) is str else '')
1290
            if os.path.isfile(self.path):
1291
                self.onCommandRejected()
1292
                app_doc_data.clear()
1293

    
1294
                app_doc_data.setImgFilePath(self.path)
1295
                app_doc_data.activeDrawing = Drawing(None, app_doc_data.imgName, None)
1296
                if not app_doc_data.set_occupying_drawing(app_doc_data.activeDrawing.UID):
1297
                    QMessageBox.about(self.graphicsView, self.tr("Notice"),
1298
                                      self.tr("The drawing is locked for editing by another user"))
1299
                    return
1300
                app_doc_data.activeDrawing.set_pid_source(Image.open(self.path))
1301
                self.itemTreeWidget.setCurrentPID(app_doc_data.activeDrawing.name)
1302

    
1303
                drawingList = self.treeWidgetDrawingList.topLevelItem(0)
1304
                for childIdex in range(drawingList.childCount()):
1305
                    drawingList.child(childIdex).setCheckState(0, Qt.Unchecked)
1306
                for childIdex in range(drawingList.childCount()):
1307
                    child = drawingList.child(childIdex)
1308
                    if child.text(0).replace('.png', '') == app_doc_data.activeDrawing.name:
1309
                        child.setCheckState(0, Qt.Checked)
1310
                        break
1311

    
1312
                try:
1313
                    self.show_Progress_bar()
1314

    
1315
                    # disconnect scene changed if signal is connected
1316
                    if self.graphicsView.scene.receivers(self.graphicsView.scene.contents_changed) > 0:
1317
                        self.graphicsView.scene.contents_changed.disconnect()
1318

    
1319
                    # Load data
1320
                    path = os.path.join(app_doc_data.getCurrentProject().getTempPath(), app_doc_data.imgName + '.xml')
1321
                    configs = app_doc_data.getConfigs('Data Load', 'Xml First')
1322
                    if configs and int(configs[0].value) is 1 and os.path.isfile(path):
1323
                        self.loadRecognitionResultFromXml(path)
1324
                    else:
1325
                        self.load_drawing(app_doc_data.activeDrawing)
1326

    
1327
                    # connect scene changed signal
1328
                    self.graphicsView.scene.contents_changed.connect(self.scene_changed)
1329
                finally:
1330
                    if hasattr(self, 'progress'):
1331
                        self.progress.setValue(self.progress.maximum())
1332
                        # self.progress.hide()
1333

    
1334
                self.changeViewCheckedState(True)
1335
        except Exception as ex:
1336
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1337
                                                           sys.exc_info()[-1].tb_lineno)
1338
            self.addMessage.emit(MessageType.Error, message)
1339

    
1340
        return self.path
1341

    
1342
    def show_Progress_bar(self):
1343
        """ show progress bar """
1344
        self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
1345
                                        self) if not hasattr(self, 'progress') else self.progress
1346
        self.progress.setWindowModality(Qt.WindowModal)
1347
        self.progress.setAutoReset(True)
1348
        self.progress.setAutoClose(True)
1349
        self.progress.setMinimum(0)
1350
        self.progress.setMaximum(100)
1351
        self.progress.resize(600, 100)
1352
        self.progress.setWindowTitle(self.tr("Reading file..."))
1353
        self.progress.show()
1354

    
1355
    def changeViewCheckedState(self, checked, clear=True):
1356
        '''
1357
            @brief      change view checked state
1358
            @author     euisung
1359
            @date       2019.03.06
1360
        '''
1361
        # self.actionImage_Drawing.setChecked(checked)
1362
        self.actionViewText.setChecked(checked)
1363
        self.actionViewSymbol.setChecked(checked)
1364
        self.actionViewLine.setChecked(checked)
1365
        self.actionViewUnknown.setChecked(checked)
1366
        self.actionViewInconsistency.setChecked(checked)
1367
        self.actionViewVendor_Area.setChecked(not checked)
1368
        self.actionDrawing_Only.setChecked(not checked)
1369
        if clear:
1370
            self.tableWidgetInconsistency.clearContents()
1371
            self.tableWidgetInconsistency.setRowCount(0)
1372

    
1373
    def onViewDrawingOnly(self, isChecked):
1374
        '''
1375
            @brief  visible/invisible except image drawing
1376
            @author euisung
1377
            @date   2019.04.22
1378
        '''
1379
        self.changeViewCheckedState(not isChecked, False)
1380
        for item in self.graphicsView.scene.items():
1381
            if type(item) is not QGraphicsPixmapItem:
1382
                item.setVisible(not isChecked)
1383

    
1384
    '''
1385
        @brief  visible/invisible image drawing
1386
        @author humkyung
1387
        @date   2018.06.25
1388
    '''
1389

    
1390
    def onViewImageDrawing(self, isChecked):
1391
        for item in self.graphicsView.scene.items():
1392
            if type(item) is QGraphicsPixmapItem:
1393
                item.setVisible(isChecked)
1394
                break
1395

    
1396
    '''
1397
        @brief  visible/invisible Text 
1398
        @author humkyung
1399
        @date   2018.06.28
1400
    '''
1401

    
1402
    def onViewText(self, isChecked):
1403
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
1404
        for item in selected:
1405
            item.setVisible(isChecked)
1406

    
1407
    '''
1408
        @brief  visible/invisible Symbol 
1409
        @author humkyung
1410
        @date   2018.06.28
1411
    '''
1412

    
1413
    def onViewSymbol(self, isChecked):
1414
        selected = [item for item in self.graphicsView.scene.items() if
1415
                    (issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringErrorItem)]
1416
        for item in selected:
1417
            item.setVisible(isChecked)
1418

    
1419
    '''
1420
        @brief  visible/invisible Line
1421
        @author humkyung
1422
        @date   2018.06.28
1423
    '''
1424

    
1425
    def onViewLine(self, isChecked):
1426
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem]
1427
        for item in selected:
1428
            item.setVisible(isChecked)
1429

    
1430
    def onViewInconsistency(self, isChecked):
1431
        '''
1432
            @brief  visible/invisible Inconsistency
1433
            @author euisung
1434
            @date   2019.04.03
1435
        '''
1436
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringErrorItem]
1437
        for item in selected:
1438
            item.setVisible(isChecked)
1439

    
1440
    '''
1441
        @brief  visible/invisible Unknown 
1442
        @author humkyung
1443
        @date   2018.06.28
1444
    '''
1445

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

    
1451
    def onViewVendorArea(self, isChecked):
1452
        '''
1453
            @brief  visible/invisible Vendor Area
1454
            @author euisung
1455
            @date   2019.04.29
1456
        '''
1457
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringVendorItem]
1458
        for item in selected:
1459
            item.setVisible(isChecked)
1460

    
1461
    '''
1462
        @brief  create a symbol
1463
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
1464
                                            Add SymbolSvgItem
1465
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1466
                                            Change method to make svg and image path
1467
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
1468
    '''
1469

    
1470
    def onCreateSymbolClicked(self):
1471
        cmd = FenceCommand.FenceCommand(self.graphicsView)
1472
        cmd.onSuccess.connect(self.onAreaSelected)
1473
        self.graphicsView.command = cmd
1474
        QApplication.setOverrideCursor(Qt.CrossCursor)
1475

    
1476
    '''
1477
        @brief      show SymbolEditorDialog with image selected by user
1478
        @author     humkyung
1479
        @date       2018.07.20
1480
    '''
1481

    
1482
    def onAreaSelected(self, x, y, width, height):
1483
        try:
1484
            image = self.graphicsView.image()
1485
            if image is not None:
1486
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height),
1487
                                                                            AppDocData.instance().getCurrentProject())
1488
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
1489
                self.dirTreeWidget.initDirTreeWidget()
1490
                if isAccepted:
1491
                    if isImmediateInsert:
1492
                        svgPath = newSym.getSvgFileFullPath()
1493
                        img = cv2.imread(newSym.getImageFileFullPath(), 1)
1494
                        w, h = (0, 0)
1495
                        if len(img.shape[::-1]) == 2:
1496
                            w, h = img.shape[::-1]
1497
                        else:
1498
                            _chan, w, h = img.shape[::-1]
1499
                        svg = SymbolSvgItem(svgPath)
1500
                        svg.buildItem(newSym.getName(), newSym.getType(), 0, [offsetX, offsetY], [w, h],
1501
                                      [float(x) for x in newSym.getOriginalPoint().split(',')],
1502
                                      [(float(x.split(',')[0]), float(x.split(',')[1])) for x in
1503
                                       newSym.getConnectionPoint().split('/')], newSym.getBaseSymbol(),
1504
                                      newSym.getAdditionalSymbol(), newSym.getHasInstrumentLabel)
1505

    
1506
                        svg.transfer.onRemoved.connect(self.itemTreeWidget.itemRemoved)
1507
                        svg.addSvgItemToScene(self.graphicsView.scene)
1508
                        for connector in svg.connectors:
1509
                            self.graphicsView.scene.addItem(connector)
1510
        finally:
1511
            self.onCommandRejected()
1512
            QApplication.restoreOverrideCursor()
1513

    
1514
    '''
1515
        @brief      create a line
1516
        @author     humkyung
1517
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
1518
    '''
1519

    
1520
    def onPlaceLine(self):
1521
        if not self.graphicsView.hasImage():
1522
            self.actionLine.setChecked(False)
1523
            self.showImageSelectionMessageBox()
1524
            return
1525

    
1526
        self.actionLine.setChecked(True)
1527
        if not hasattr(self.actionLine, 'tag'):
1528
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
1529
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
1530
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
1531

    
1532
        self.graphicsView.command = self.actionLine.tag
1533

    
1534
    '''
1535
        @brief      add created lines to scene
1536
        @author     humkyung
1537
        @date       2018.07.23
1538
    '''
1539

    
1540
    def onLineCreated(self):
1541
        from EngineeringConnectorItem import QEngineeringConnectorItem
1542

    
1543
        try:
1544
            count = len(self.actionLine.tag._polyline._vertices)
1545
            if count > 1:
1546
                items = []
1547

    
1548
                lineType = self.lineComboBox.currentText()
1549
                for index in range(count - 1):
1550
                    start = self.actionLine.tag._polyline._vertices[index]
1551
                    end = self.actionLine.tag._polyline._vertices[index + 1]
1552

    
1553
                    lineItem = QEngineeringLineItem(vertices=[start, end])
1554
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
1555
                    lineItem.lineType = lineType
1556
                    if items:
1557
                        lineItem.connect_if_possible(items[-1], 5)
1558
                    else:
1559
                        pt = lineItem.startPoint()
1560
                        selected = [item for item in self.graphicsView.scene.items(QPointF(pt[0], pt[1])) if
1561
                                    type(item) is QEngineeringConnectorItem or type(item) is QEngineeringLineItem]
1562
                        if selected:
1563
                            lineItem.connect_if_possible(
1564
                                selected[0].parent if type(selected[0]) is QEngineeringConnectorItem else selected[0],
1565
                                5)
1566

    
1567
                    items.append(lineItem)
1568
                    self.graphicsView.scene.addItem(lineItem)
1569

    
1570
                pt = items[-1].endPoint()
1571
                selected = [item for item in self.graphicsView.scene.items(QPointF(pt[0], pt[1])) if
1572
                            type(item) is QEngineeringConnectorItem and item.parent is not items[-1]]
1573
                if selected:
1574
                    items[-1].connect_if_possible(selected[0].parent, 5)
1575

    
1576
        finally:
1577
            self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1578
            self.actionLine.tag.reset()
1579

    
1580
    '''
1581
        @brief      refresh scene
1582
        @author     humkyung
1583
        @date       2018.07.23
1584
    '''
1585

    
1586
    def onCommandRejected(self, cmd=None):
1587
        try:
1588
            if type(cmd) is PlaceLineCommand.PlaceLineCommand:
1589
                if self.actionLine.tag._polyline:
1590
                    self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1591
                self.graphicsView.scene.update()
1592
                self.actionLine.tag.reset()
1593

    
1594
                self.actionLine.setChecked(False)
1595
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
1596
                self.actionZoom.setChecked(False)
1597
            elif type(cmd) is AreaOcrCommand.AreaOcrCommand:
1598
                self.actionOCR.setChecked(False)
1599
            elif type(cmd) is PlacePolygonCommand.PlacePolygonCommand:
1600
                self.actionVendor.setChecked(False)
1601
            else:
1602
                if hasattr(self.actionLine, 'tag') and self.actionLine.tag._polyline:
1603
                    self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1604
                    self.graphicsView.scene.update()
1605
                    self.actionLine.tag.reset()
1606
                if hasattr(self.actionVendor, 'tag') and self.actionVendor.tag._polyline:
1607
                    self.graphicsView.scene.removeItem(self.actionVendor.tag._polyline)
1608
                    self.graphicsView.scene.update()
1609
                    self.actionVendor.tag.reset()
1610
                self.actionLine.setChecked(False)
1611
                self.actionZoom.setChecked(False)
1612
                self.actionOCR.setChecked(False)
1613
                self.actionVendor.setChecked(False)
1614
        finally:
1615
            self.graphicsView.useDefaultCommand()
1616

    
1617
    '''
1618
        @brief      restore to default command when user press Escape key
1619
        @author     humkyung 
1620
        @date       2018.08.09
1621
        
1622
    '''
1623

    
1624
    def keyPressEvent(self, event):
1625
        try:
1626
            if event.key() == Qt.Key_Escape:
1627
                # already catched in command
1628
                pass
1629
                # checked = self.actionGroup.checkedAction()
1630
                # if checked:
1631
                #    checked.setChecked(False)
1632
                #    self.graphicsView.useDefaultCommand()
1633
            elif event.key() == Qt.Key_1:
1634
                if self.actionImage_Drawing.isChecked():
1635
                    self.onViewImageDrawing(False)
1636
                    self.actionImage_Drawing.setChecked(False)
1637
                else:
1638
                    self.onViewImageDrawing(True)
1639
                    self.actionImage_Drawing.setChecked(True)
1640
            elif event.key() == Qt.Key_2:
1641
                if self.actionViewText.isChecked():
1642
                    self.onViewText(False)
1643
                    self.actionViewText.setChecked(False)
1644
                else:
1645
                    self.onViewText(True)
1646
                    self.actionViewText.setChecked(True)
1647
            elif event.key() == Qt.Key_3:
1648
                if self.actionViewSymbol.isChecked():
1649
                    self.onViewSymbol(False)
1650
                    self.actionViewSymbol.setChecked(False)
1651
                else:
1652
                    self.onViewSymbol(True)
1653
                    self.actionViewSymbol.setChecked(True)
1654
            elif event.key() == Qt.Key_4:
1655
                if self.actionViewLine.isChecked():
1656
                    self.onViewLine(False)
1657
                    self.actionViewLine.setChecked(False)
1658
                else:
1659
                    self.onViewLine(True)
1660
                    self.actionViewLine.setChecked(True)
1661
            elif event.key() == Qt.Key_5:
1662
                if self.actionViewUnknown.isChecked():
1663
                    self.onViewUnknown(False)
1664
                    self.actionViewUnknown.setChecked(False)
1665
                else:
1666
                    self.onViewUnknown(True)
1667
                    self.actionViewUnknown.setChecked(True)
1668
            elif event.key() == Qt.Key_6:
1669
                if self.actionViewInconsistency.isChecked():
1670
                    self.onViewInconsistency(False)
1671
                    self.actionViewInconsistency.setChecked(False)
1672
                else:
1673
                    self.onViewInconsistency(True)
1674
                    self.actionViewInconsistency.setChecked(True)
1675
            elif event.key() == Qt.Key_7:
1676
                if self.actionViewVendor_Area.isChecked():
1677
                    self.onViewVendorArea(False)
1678
                    self.actionViewVendor_Area.setChecked(False)
1679
                else:
1680
                    self.onViewVendorArea(True)
1681
                    self.actionViewVendor_Area.setChecked(True)
1682
            elif event.key() == 96:  # '`' key
1683
                if self.actionDrawing_Only.isChecked():
1684
                    self.onViewDrawingOnly(False)
1685
                    self.actionDrawing_Only.setChecked(False)
1686
                else:
1687
                    self.onViewDrawingOnly(True)
1688
                    self.actionDrawing_Only.setChecked(True)
1689
            elif event.key() == Qt.Key_M:  # merge text as vertical
1690
                from TextInfo import TextInfo
1691

    
1692
                textItems = [text for text in self.graphicsView.scene.selectedItems() if
1693
                             type(text) is QEngineeringTextItem]
1694
                if not textItems or len(textItems) is 1:
1695
                    return
1696
                
1697
                angle = None
1698
                for item in textItems:
1699
                    if angle is None:
1700
                        angle = item.angle
1701
                    else:
1702
                        if angle != item.angle:
1703
                            return
1704

    
1705
                textItems = sorted(textItems, key=lambda text: text.loc[1]) if textItems[0].angle == 0 else ( \
1706
                                sorted(textItems, key=lambda text: text.loc[0]) if textItems[0].angle == 1.57 else ( \
1707
                                    sorted(textItems, key=lambda text: text.loc[1], reverse=True) if textItems[0].angle == 4.71 else \
1708
                                        sorted(textItems, key=lambda text: text.loc[0], reverse=True)))
1709
                minX = sys.maxsize
1710
                minY = sys.maxsize
1711
                maxX = 0
1712
                maxY = 0
1713
                newText = ''
1714
                for text in textItems:
1715
                    if text.loc[0] < minX: minX = text.loc[0]
1716
                    if text.loc[1] < minY: minY = text.loc[1]
1717
                    if text.loc[0] + text.size[0] > maxX: maxX = text.loc[0] + text.size[0]
1718
                    if text.loc[1] + text.size[1] > maxY: maxY = text.loc[1] + text.size[1]
1719
                    newText = newText + text.text() + "\n"
1720
                    text.transfer.onRemoved.emit(text)
1721
                newText = newText[:-1]
1722

    
1723
                textInfo = TextInfo(newText, minX, minY, maxX - minX, maxY - minY, textItems[0].angle)
1724
                x = textInfo.getX()
1725
                y = textInfo.getY()
1726
                angle = textInfo.getAngle()
1727
                text = textInfo.getText()
1728
                width = textInfo.getW()
1729
                height = textInfo.getH()
1730
                item = TextItemFactory.instance().createTextItem(textInfo)
1731
                if item is not None:
1732
                    item.loc = [x, y]
1733
                    item.size = (width, height)
1734
                    item.angle = angle
1735
                    item.setDefaultTextColor(Qt.blue)
1736
                    item.addTextItemToScene(self.graphicsView.scene)
1737
                    item.transfer.onRemoved.connect(self.itemRemoved)
1738

    
1739
            QMainWindow.keyPressEvent(self, event)
1740
        except Exception as ex:
1741
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1742
                                                          sys.exc_info()[-1].tb_lineno)
1743
            self.addMessage.emit(MessageType.Error, message)
1744

    
1745
    def recognizeBatch(self, MainWindow):
1746
        '''
1747
            @brief      batch recognize symbol, text and line
1748
            @author     euisung
1749
            @date       2018.11.23
1750
        
1751
        '''
1752
        from datetime import datetime
1753
        from RecognitionDialog import QRecognitionDialog
1754

    
1755
        appDocData = AppDocData.instance()
1756
        project = appDocData.getCurrentProject()
1757
        appDocData.needReOpening = None
1758
        currentPid = None
1759

    
1760
        if self.graphicsView.hasImage():
1761
            currentPid = appDocData.activeDrawing.name
1762

    
1763
        drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1764
        drawingCount = drawingTop.childCount()
1765
        checkedTreeItems = []
1766
        checkedDrawingPath = []
1767
        for drawing in range(drawingCount):
1768
            drawingChild = drawingTop.child(drawing)
1769
            if drawingChild.checkState(0) == 2:
1770
                checkedTreeItems.append(drawingChild)
1771
                checkedDrawingPath.append(os.path.join(project.getDrawingFilePath(), drawingChild.data(0, 0)))
1772
                if currentPid is not None and drawingChild.data(0, 0).find(currentPid) is 0:
1773
                    appDocData.needReOpening = False  # later check need reopening at drawUnknownItems()
1774
                    currentPid = drawingChild.data(0, 0)
1775

    
1776
        if len(checkedDrawingPath) == 0:
1777
            self.showImageSelectionMessageBox()
1778
            return
1779

    
1780
        try:
1781
            self.onClearLog()
1782
            self.dlg = QRecognitionDialog(self, checkedDrawingPath, True)
1783
            self.dlg.exec_()
1784
            if self.dlg.isAccepted == True:
1785
                pass
1786

    
1787
            if appDocData.needReOpening == True:
1788
                drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), currentPid)
1789
                self.onOpenImageDrawing(drawing)
1790

    
1791
            # save working date-time
1792
            drawings = appDocData.getDrawings()
1793
            checkedDrawings = []
1794
            for checkedTreeItem in checkedTreeItems:
1795
                for drawing in drawings:
1796
                    if checkedTreeItem.data(0, 0) == drawing.name:
1797
                        if drawing:
1798
                            drawing.datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1799
                            checkedDrawings.append(drawing)
1800
                            checkedTreeItem.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1801
            appDocData.saveDrawings(checkedDrawings)
1802
            self.changeViewCheckedState(True)
1803
            # up to here
1804
        except Exception as ex:
1805
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1806
                                                          sys.exc_info()[-1].tb_lineno)
1807
            self.addMessage.emit(MessageType.Error, message)
1808

    
1809
    '''
1810
        @brief      recognize symbol and text
1811
        @author     humkyung
1812
        @date       2018.04.??
1813
        @history    2018.04.16  humkyung    execute line no tracing
1814
                    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
1815
                    2018.05.25  Jeongwoo    Add parameter on QRecognitionDialog.__init__() and Move thread to QRecognitionDialog
1816
                                            Remove codes below if self.dlg.isAccepted == True
1817
                    2018.05.29  Jeongwoo    Remove connects and comments
1818
                    humkyung 2018.11.05 save working date-time
1819
    '''
1820

    
1821
    def recognize(self, MainWindow):
1822
        from datetime import datetime
1823
        from RecognitionDialog import QRecognitionDialog
1824

    
1825
        if not self.graphicsView.hasImage():
1826
            self.showImageSelectionMessageBox()
1827
            return
1828

    
1829
        try:
1830
            appDocData = AppDocData.instance()
1831

    
1832
            self.onClearLog()
1833
            appDocData.needReOpening = False
1834
            drawingList = []
1835
            drawingList.append(self.path)
1836
            self.dlg = QRecognitionDialog(self, drawingList, False)
1837
            self.dlg.exec_()
1838

    
1839
            if appDocData.needReOpening == True:
1840
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
1841
                self.drawDetectedItemsToScene()
1842

    
1843
                # save working date-time
1844
                drawings = appDocData.getDrawings()
1845
                drawing = [drawing for drawing in drawings if appDocData.imgName == os.path.splitext(drawing.name)[0]]
1846
                if drawing[0]:
1847
                    drawing[0].datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1848
                    appDocData.saveDrawings(drawing)
1849

    
1850
                currentPid = appDocData.activeDrawing.name
1851

    
1852
                drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1853
                drawingCount = drawingTop.childCount()
1854

    
1855
                for drawing in range(drawingCount):
1856
                    drawingChild = drawingTop.child(drawing)
1857
                    if drawingChild.data(0, 0).find(currentPid) is 0:
1858
                        drawingChild.setText(1, datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1859
                self.changeViewCheckedState(True)
1860
                # up to here
1861
        except Exception as ex:
1862
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1863
                                                          sys.exc_info()[-1].tb_lineno)
1864
            self.addMessage.emit(MessageType.Error, message)
1865

    
1866
    '''
1867
        @brief      remove item from tree widget and then remove from scene
1868
        @date       2018.05.25
1869
        @author     Jeongwoo
1870
    '''
1871

    
1872
    def itemRemoved(self, item):
1873
        try:
1874
            self.itemTreeWidget.itemRemoved(item)
1875

    
1876
            matches = [_item for _item in self.graphicsView.scene.items() if
1877
                       hasattr(_item, 'connectors') and [connector for connector in _item.connectors if
1878
                                                         connector.connectedItem is item]]
1879
            for match in matches:
1880
                for connector in match.connectors:
1881
                    if connector.connectedItem is item:
1882
                        connector.connectedItem = None
1883
                        connector.highlight(False)
1884

    
1885
            # matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'remove_assoc_item')]
1886
            # for _item in matches:
1887
            #    _item.remove_assoc_item(item)
1888

    
1889
            matches = [_item for _item in self.graphicsView.scene.items() if type(_item) is QEngineeringLineNoTextItem]
1890
            matches.extend([lineNo for lineNo in AppDocData.instance().tracerLineNos if type(lineNo) is QEngineeringTrimLineNoTextItem])
1891
            for match in matches:
1892
                if item is match.prop('From'):
1893
                    match.set_property('From', None)
1894
                elif item is match.prop('To'):
1895
                    match.set_property('To', None)
1896

    
1897
                for run in match.runs:
1898
                    if item in run.items:
1899
                        index = run.items.index(item)
1900
                        run.items.pop(index)
1901
                        if not run.items:
1902
                            run.explode()
1903
                        break
1904

    
1905
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'owner')]
1906
            for match in matches:
1907
                if match.owner is item:
1908
                    match.owner = None
1909

    
1910
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'attrs')]
1911
            # done = False
1912
            for match in matches:
1913
                for assoc in match.associations():
1914
                    if item is assoc:
1915
                        for attr in match.attrs.keys():
1916
                            if attr.AssocItem and str(item.uid) == str(attr.AssocItem.uid):
1917
                                attr.AssocItem = None
1918
                                match.attrs[attr] = ''
1919
                                # done = True
1920
                        match.remove_assoc_item(item)
1921
                        break
1922
                # if done: break
1923

    
1924
            # remove error item from inconsistency list
1925
            if type(item) is QEngineeringErrorItem:
1926
                for row in range(self.tableWidgetInconsistency.rowCount()):
1927
                    if item is self.tableWidgetInconsistency.item(row, 0).tag:
1928
                        self.tableWidgetInconsistency.removeRow(row)
1929
                        break
1930

    
1931
            if item.scene() is not None: item.scene().removeItem(item)
1932
        except Exception as ex:
1933
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1934
                                                          sys.exc_info()[-1].tb_lineno)
1935
            self.addMessage.emit(MessageType.Error, message)
1936

    
1937
    '''
1938
        @brief      recognize line
1939
        @author     humkyung
1940
        @date       2018.04.19
1941
        @history    Jeongwoo 2018.04.26 Variable name changed (texts → lineNos)
1942
                                        TextItem type changed (QEngineeringTextItem → QEngineeringLineNoTextItem)
1943
                    humkyung 2018.04.26 remove small objects before recognizing line
1944
                    Jeongwoo 2018.05.02 Show MessageBox when imageviewer doesn't have image
1945
                    Jeongwoo 2018.05.25 Move codes about LineDetector
1946
                    humkyung 2018.06.17 show progress dialog
1947
    '''
1948

    
1949
    def connect_attributes(self, MainWindow):
1950
        from LineNoTracer import LineNoTracer
1951
        from ConnectAttrDialog import QConnectAttrDialog
1952

    
1953
        if not self.graphicsView.hasImage():
1954
            self.showImageSelectionMessageBox()
1955
            return
1956

    
1957
        try:
1958
            self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView)
1959
            self.dlgConnectAttr.exec_()
1960
            if self.dlgConnectAttr.isRunned:
1961
                self.itemTreeWidget.InitLineNoItems()
1962

    
1963
                # construct line no item
1964
                line_nos = AppDocData.instance().tracerLineNos
1965
                for line_no in line_nos:
1966
                    item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
1967
                    connectedItems = line_no.getConnectedItems()
1968
                    for connectedItem in connectedItems:
1969
                        if issubclass(type(connectedItem), SymbolSvgItem):
1970
                            self.itemTreeWidget.addTreeItem(item, connectedItem)
1971
                # up to here
1972

    
1973
                self.tableWidgetInconsistency.clearContents()
1974
                if self.dlgConnectAttr.ui.checkBoxValidation.isChecked():
1975
                    self.onValidation()
1976

    
1977
                self.graphicsView.invalidateScene()
1978
        except Exception as ex:
1979
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1980
                                                          sys.exc_info()[-1].tb_lineno)
1981
            self.addMessage.emit(MessageType.Error, message)
1982

    
1983
    '''
1984
        @history    2018.05.25  Jeongwoo    Moved from MainWindow
1985
                                            SvgItem and TextItem Connect with method in this class
1986
                                            Change method to add GraphicsItem
1987
                    2018.05.28  Jeongwoo    Make QGraphicsItem by symbol, text object. Not xml
1988
                    2018.05.29  Jeongwoo    Change method name and Moved from QRecognitionDialog
1989
                    2018.05.30  Jeongwoo    Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol)
1990
                                            Change Method name and seperate each item
1991
                    humkyung 2018.06.11     display difference between original and recognized image
1992
                    Jeongwoo 2018.06.18     Update Scene after all item added
1993
                    2018.11.05  euisung     add save note item because of dependency
1994
                    2018.11.05  euisung     add db delete process before save
1995
                    2018.11.12  euisung     add title block properties
1996
                    2018.11.12  euisung     db part move new method to dbUpdate
1997
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
1998
                    2018.11.29  euisung     change name drawDetectedItems() -> createDetectedItems
1999
    '''
2000

    
2001
    def createDetectedItems(self, symbolList, textInfoList, otherTextInfoList, titleBlockTextInfoList):
2002
        try:
2003
            appDocData = AppDocData.instance()
2004

    
2005
            QApplication.processEvents()
2006
            self.createDetectedSymbolItem(symbolList)
2007
            QApplication.processEvents()
2008
            self.createDetectedTextItem(textInfoList)
2009
            QApplication.processEvents()
2010
            self.createDetectedOtherTextItem(otherTextInfoList)
2011
            QApplication.processEvents()
2012
            self.createDetectedTitleBlockTextItem(titleBlockTextInfoList)
2013

    
2014
            # update scene
2015
            # self.graphicsView.scene.update(self.graphicsView.sceneRect())
2016
        except Exception as ex:
2017
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2018
                                                          sys.exc_info()[-1].tb_lineno)
2019
            self.addMessage.emit(MessageType.Error, message)
2020

    
2021
    def drawDetectedItemsToScene(self):
2022
        '''
2023
            @brief  add detected items to scene
2024
            @author euisung
2025
            @date   2018.11.26
2026
        '''
2027
        appDocData = AppDocData.instance()
2028

    
2029
        try:
2030
            for symbol in appDocData.symbols:
2031
                if issubclass(type(symbol), SymbolSvgItem):
2032
                    self.addSvgItemToScene(symbol)
2033
                else:
2034
                    self.graphicsView.scene.addItem(symbol)
2035

    
2036
            for text in appDocData.texts:
2037
                self.addTextItemToScene(text)
2038

    
2039
            for lineNo in appDocData.tracerLineNos:
2040
                self.addTextItemToScene(lineNo)
2041

    
2042
            for line in appDocData.lines:
2043
                self.graphicsView.scene.addItem(line)
2044
                line.transfer.onRemoved.connect(self.itemRemoved)
2045
                for conn in line.connectors:
2046
                    conn.transfer.onPosChanged.connect(line.onConnectorPosChaned)
2047

    
2048
            for unknown in appDocData.unknowns + appDocData.lineIndicators:
2049
                self.graphicsView.scene.addItem(unknown)
2050
        finally:
2051
            # update scene
2052
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2053

    
2054
    def postDetectLineProcess(self):
2055
        '''
2056
            @brief  check allowables among undetected items
2057
            @author euisung
2058
            @date   2018.11.15
2059
            @history    2018.11.15  euisung    no more used, moved to TextItemFactoy isLineNo()
2060
        '''
2061
        from TextItemFactory import TextItemFactory
2062

    
2063
        appDocData = AppDocData.instance()
2064

    
2065
        tableNames = ["Fluid Code", "Insulation Purpose", "PnID Number", "Piping Materials Class", "Unit Number"]
2066
        tableDatas = []
2067
        for tableName in tableNames:
2068
            tableNameFormat = tableName.replace(' ', '').replace('&&', 'n')
2069
            tableDatas.append(appDocData.getCodeTable(tableNameFormat))
2070

    
2071
        items = self.graphicsView.scene.items()
2072
        for item in items:
2073
            if type(item) is not QEngineeringTextItem:
2074
                continue
2075
            text = item.text()
2076
            for tableData in tableDatas:
2077
                for data in tableData:
2078
                    if data[3] == '':
2079
                        continue
2080
                    else:
2081
                        allows = data[3].split(',')
2082
                        for allow in allows:
2083
                            text = text.replace(allow, data[1])
2084

    
2085
            lineItem = TextItemFactory.instance().createTextItem(text)
2086
            if type(lineItem) is QEngineeringLineNoTextItem:
2087
                lineItem.loc = item.loc
2088
                lineItem.size = item.size
2089
                lineItem.angle = item.angle
2090
                lineItem.area = item.area
2091
                # lineItem.addTextItemToScene(self.graphicsView.scene)
2092
                lineItem.transfer.onRemoved.connect(self.itemRemoved)
2093
                item.transfer.onRemoved.emit(item)
2094
                appDocData.lineNos.append(lineItem)
2095

    
2096
    def createDetectedTitleBlockTextItem(self, textInfoList):
2097
        '''
2098
            @brief  draw title block
2099
            @author euisung
2100
            @date   2018.11.12
2101
            @history    2018.11.26  euisung     remove scene dependency
2102
                        2018.11.29  euisung     change name drawDetectedTitleBlockTextItem() -> createDetectedTitleBlockTextItem
2103
        '''
2104
        from TextItemFactory import TextItemFactory
2105
        import math
2106

    
2107
        try:
2108
            appDocData = AppDocData.instance()
2109

    
2110
            # parse texts
2111
            for textInfo in textInfoList:
2112
                if len(textInfo[1]) is 0:
2113
                    continue
2114
                x = textInfo[1][0].getX()
2115
                y = textInfo[1][0].getY()
2116
                width = textInfo[1][0].getW()
2117
                height = textInfo[1][0].getH()
2118
                angle = round(math.radians(textInfo[1][0].getAngle()), 2)
2119
                text = textInfo[1][0].getText()
2120
                item = TextItemFactory.instance().createTextItem(textInfo)
2121

    
2122
                if item is not None:
2123
                    item.loc = [x, y]
2124
                    item.size = (width, height)
2125
                    item.angle = angle
2126
                    item.area = textInfo[0]
2127
                    # self.addTextItemToScene(item)
2128
                    # appDocData.texts.append(item)
2129
                    appDocData.allItems.append(item)
2130
        except Exception as ex:
2131
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2132
                                                          sys.exc_info()[-1].tb_lineno)
2133
            self.addMessage.emit(MessageType.Error, message)
2134

    
2135
    '''
2136
        @brief      
2137
        @author     humkyung
2138
        @date       2018.08.23
2139
        @history    2018.11.26  euisung     remove scene dependency
2140
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
2141
                    2018.11.    euisung     no more used
2142
                    2018.11.29  euisung     change name drawDetectedLines() -> createDetectedLines
2143
    '''
2144

    
2145
    def createDetectedLines(self, lineList, worker):
2146
        appDocData = AppDocData.instance()
2147
        area = appDocData.getArea('Drawing')
2148

    
2149
        for pts in lineList:
2150
            processLine = QEngineeringLineItem(vertices=[(area.x + param[0], area.y + param[1]) for param in pts])
2151
            processLine.area = 'Drawing'
2152
            # self.graphicsView.scene.addItem(processLine)
2153
            appDocData.lines.append(processLine)
2154
            appDocData.allItems.append(processLine)
2155

    
2156
            # if processLine.length() > 100: # TODO: check critical length
2157
            #    processLine.addFlowArrow()
2158

    
2159
        # re-order process line's start,end according to flow mark
2160
        # worker.arrangeLinePosition(lines, symbols, listWidget)
2161
        # up to here
2162

    
2163
    '''
2164
        history     2018.06.09  humkyung    check length of original and connection point is 2 while parsing
2165
                    2018.11.26  euisung     remove scene dependency
2166
                    2018.11.29  euisung     change name drawDetectedSymbolItem() -> createDetectedSymbolItem
2167
    '''
2168

    
2169
    def createDetectedSymbolItem(self, symbolList):
2170
        from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
2171
        from SymbolSvgItem import SymbolSvgItem
2172
        import math
2173

    
2174
        try:
2175
            appDocData = AppDocData.instance()
2176
            project = appDocData.getCurrentProject()
2177

    
2178
            searchedMap = []
2179
            for symbol in symbolList:
2180
                pt = [float(x) for x in symbol.getSp()]
2181
                size = [symbol.getWidth(), symbol.getHeight()]
2182
                name = symbol.getName()
2183
                angle = round(math.radians(symbol.getRotatedAngle()), 2)
2184
                _type = symbol.getType()
2185
                flip = symbol.getDetectFlip()
2186
                origin = [0, 0]
2187
                if 2 == len(symbol.getOriginalPoint().split(',')):
2188
                    tokens = symbol.getOriginalPoint().split(',')
2189
                    origin = [pt[0] + float(tokens[0]), pt[1] + float(tokens[1])]
2190
                connPts = []
2191
                if symbol.getConnectionPoint() is not None and symbol.getConnectionPoint() != '':
2192
                    for param in symbol.getConnectionPoint().split('/'):
2193
                        tokens = param.split(',')
2194
                        connPts.append(
2195
                            ('AUTO', pt[0] + float(tokens[0]), pt[1] + float(tokens[1]), '0') if len(tokens) == 2 else \
2196
                                (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), '0') if len(
2197
                                    tokens) == 3 else \
2198
                                    (tokens[0], pt[0] + float(tokens[1]), pt[1] + float(tokens[2]), tokens[3]) if len(
2199
                                        tokens) == 4 else None)
2200

    
2201
                parentSymbol = symbol.getBaseSymbol()
2202
                childSymbol = symbol.getAdditionalSymbol()
2203
                hasInstrumentLabel = symbol.getHasInstrumentLabel()
2204

    
2205
                svgFilePath = os.path.join(project.getSvgFilePath(), _type, name + '.svg')
2206
                if os.path.isfile(svgFilePath):
2207
                    svg = SymbolSvgItem.createItem(_type, svgFilePath, owner=None, flip=flip)
2208
                    # print(pt)
2209
                    # print(origin)
2210
                    svg.buildItem(name, _type, angle, pt, size, origin, connPts, parentSymbol, childSymbol,
2211
                                  hasInstrumentLabel)
2212
                    svg.reCalculationRotatedItem()
2213
                    svg.area = 'Drawing'
2214

    
2215
                    # set owner - 2018.07.20 added by humkyung                   
2216
                    matches = [searched for searched in searchedMap if searched[0] == symbol.owner]
2217
                    if len(matches) == 1:
2218
                        svg.owner = matches[0][1]
2219
                    searchedMap.append((symbol, svg))
2220
                    # up to here
2221

    
2222
                    svg.transfer.onRemoved.connect(self.itemRemoved)
2223
                    # self.addSvgItemToScene(svg)
2224
                    appDocData.symbols.append(svg)
2225
                    appDocData.allItems.append(svg)
2226
                else:
2227
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2228
                    item.isSymbol = True
2229
                    item.angle = angle
2230
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2231
                    # self.graphicsView.scene.addItem(item)
2232
                    # appDocData.symbols.append(item)
2233
                    appDocData.allItems.append(item)
2234
            # up to here
2235
        except Exception as ex:
2236
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2237
                                                          sys.exc_info()[-1].tb_lineno)
2238
            self.addMessage.emit(MessageType.Error, message)
2239

    
2240
    '''
2241
        @history    2018.06.08  Jeongwoo    Add parameter on round method
2242
        @history    2018.11.02  euisung     Add save note text item
2243
        @history    2018.11.05  euisung     delete save note text item and move to drawDetectedItems()
2244
                    2018.11.26  euisung     remove scene dependency
2245
                    2018.11.29  euisung     change name drawDetectedTextItem() -> createDetectedTextItem
2246
    '''
2247

    
2248
    def createDetectedTextItem(self, textInfoList):
2249
        from TextItemFactory import TextItemFactory
2250
        import math
2251

    
2252
        try:
2253
            appDocData = AppDocData.instance()
2254

    
2255
            # parse texts
2256
            for textInfo in textInfoList:
2257
                x = textInfo.getX()
2258
                y = textInfo.getY()
2259
                width = textInfo.getW()
2260
                height = textInfo.getH()
2261
                angle = round(math.radians(textInfo.getAngle()), 2)
2262
                text = textInfo.getText()
2263
                if not text: continue
2264

    
2265
                item = TextItemFactory.instance().createTextItem(textInfo)
2266
                if item is not None:
2267
                    item.loc = [x, y]
2268
                    item.size = (width, height)
2269
                    item.angle = angle
2270
                    item.area = 'Drawing'
2271
                    item.transfer.onRemoved.connect(self.itemRemoved)
2272
                    # self.addTextItemToScene(item)
2273
                    # appDocData.texts.append(item)
2274
                    appDocData.allItems.append(item)
2275
        except Exception as ex:
2276
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2277
                                                          sys.exc_info()[-1].tb_lineno)
2278
            self.addMessage.emit(MessageType.Error, message)
2279

    
2280
    '''
2281
        @brief      draw detected texts except which in drawing area
2282
        @history    2018.11.29  euisung     change name drawDetectedOtherTextItem() -> createDetectedOtherTextItem
2283
    '''
2284

    
2285
    def createDetectedOtherTextItem(self, otherTextInfoList):
2286
        from TextItemFactory import TextItemFactory
2287
        import math
2288

    
2289
        try:
2290
            appDocData = AppDocData.instance()
2291

    
2292
            # parse notes
2293
            for textInfoMap in otherTextInfoList:
2294
                if textInfoMap[0] == 'Note' or textInfoMap[1] is None:
2295
                    pass
2296

    
2297
                for textInfo in textInfoMap[1]:
2298
                    x = textInfo.getX()
2299
                    y = textInfo.getY()
2300
                    width = textInfo.getW()
2301
                    height = textInfo.getH()
2302
                    angle = round(math.radians(textInfo.getAngle()))
2303
                    text = textInfo.getText()
2304

    
2305
                    item = TextItemFactory.instance().createTextItem(textInfo)
2306

    
2307
                    item.loc = [x, y]
2308
                    item.size = (width, height)
2309
                    item.angle = angle
2310
                    item.area = textInfoMap[0]
2311
                    item.transfer.onRemoved.connect(self.itemRemoved)
2312
                    # appDocData.texts.append(item)
2313
                    appDocData.allItems.append(item)
2314
        except Exception as ex:
2315
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2316
                                                          sys.exc_info()[-1].tb_lineno)
2317
            self.addMessage.emit(MessageType.Error, message)
2318

    
2319
    '''
2320
        @brief  draw unknown items 
2321
        @author humkyung
2322
        @date   2018.06.12
2323
        @history    2018.06.14  Jeongwoo    Change method to add unknown item
2324
                    2018.06.18  Jeongwoo    Add connect on unknown item
2325
                                            Add [transfer] for using pyqtSignal
2326
                    2018.11.26  euisung     remove scene dependency
2327
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
2328
                    2018.11.27  euisung     add save to xml
2329
                    2018.11.29  euisung     change name drawUnknownItems() -> createUnknownItems
2330
    '''
2331

    
2332
    def createUnknownItems(self, path):
2333
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem
2334
        from EngineeringLineItem import QEngineeringLineItem
2335
        from EngineeringUnknownItem import QEngineeringUnknownItem
2336
        from SaveWorkCommand import SaveWorkCommand
2337

    
2338
        try:
2339
            docData = AppDocData.instance()
2340
            project = docData.getCurrentProject()
2341
            windowSize = docData.getSlidingWindowSize()
2342

    
2343
            thickness = int(windowSize[1])
2344

    
2345
            if docData.needReOpening is not None:
2346
                docData.needReOpening = True
2347

    
2348
            diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(path))
2349
            if os.path.isfile(diffFilePath):
2350
                imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255,
2351
                                        cv2.THRESH_BINARY)[1]
2352

    
2353
                ## remove line
2354
                lines = docData.lines
2355
                for line in lines:
2356
                    line.drawToImage(imgDiff, 255, thickness) if line.thickness is None else line.drawToImage(imgDiff,
2357
                                                                                                              255,
2358
                                                                                                              line.thickness)
2359
                cv2.imwrite(diffFilePath, imgDiff)
2360
                ## up to here
2361

    
2362
                imgNot = np.ones(imgDiff.shape, np.uint8)
2363
                cv2.bitwise_not(imgDiff, imgNot)
2364
                configs = docData.getConfigs('Filter', 'ErodeSize')
2365
                kernel = int(configs[0].value) if 1 == len(configs) else 3
2366
                imgNot = cv2.erode(imgNot, np.ones((kernel, kernel), np.uint8))
2367
                imgNot = cv2.dilate(imgNot, np.ones((8 + kernel, 8 + kernel), np.uint8))
2368

    
2369
                contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
2370

    
2371
                ##
2372
                idx = 0
2373
                ##
2374
                smallContours = []
2375
                minimumSize = docData.getConfigs('Filter', 'MinimumSize')
2376
                for contour in contours:
2377
                    [x, y, w, h] = cv2.boundingRect(contour)
2378

    
2379
                    # remove too small one
2380
                    if len(minimumSize) is 1:
2381
                        if (w * h < int(minimumSize[0].value) * int(minimumSize[0].value)):
2382
                            smallContours.append(contour)
2383
                            idx += 1
2384
                            continue
2385

    
2386
                    '''
2387
                    rect = QRectF(x, y, w, h)
2388
                    items = [item for item in diffItems if item.boundingRect().contains(rect)]
2389
                    if len(items) > 0: continue
2390
                    
2391
                    items = [item for item in diffItems if rect.contains(item.boundingRect())]
2392
                    for item in items:
2393
                        diffItems.remove(item)
2394
                    '''
2395

    
2396
                    # create unknown item
2397
                    epsilon = cv2.arcLength(contour, True) * 0.001
2398
                    approx = cv2.approxPolyDP(contour, epsilon, True)
2399
                    approx = [pt[0] for pt in approx]
2400
                    resultStr, resultList = self.determineRemainObject(idx, contours, imgNot)
2401
                    if resultStr == 'LineIndicator':
2402
                        item = QEngineeringUnknownItem(approx, 'True', resultList[0], resultList[1])
2403
                        docData.lineIndicators.append(item)
2404
                    elif resultStr == 'MissingLine':
2405
                        pass
2406
                    elif resultStr == 'Unknown':
2407
                        item = QEngineeringUnknownItem(approx, 'False')
2408
                        docData.unknowns.append(item)
2409
                    item.area = 'Drawing'
2410
                    docData.allItems.append(item)
2411
                    item.transfer.onRemoved.connect(self.itemRemoved)
2412
                    idx += 1
2413
                    # up to here                    
2414

    
2415
                imgNotRemoveSmall = cv2.drawContours(imgNot, smallContours, -1, 0, -1)
2416
                notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(path))
2417
                cv2.imwrite(notFilePath, imgNotRemoveSmall)
2418
            else:
2419
                message = 'can\'t found {}'.format(diffFilePath)
2420
                self.addMessage.emit(MessageType.Normal, message)
2421

    
2422
            self.dbUpdate()
2423
            SaveWorkCommand.save_to_xml()
2424
        except Exception as ex:
2425
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2426
                                                          sys.exc_info()[-1].tb_lineno)
2427
            self.addMessage.emit(MessageType.Error, message)
2428

    
2429
    def determineRemainObject(self, idx, contours, imgNot):
2430
        '''
2431
            @brief      determine remain objects -> line no indicator or unknown
2432
            @author     euisung
2433
            @date       2018.12.26
2434
            @history    2019.03.25  euisung    Change name isLineNoIndicator -> determineRemainObject
2435
        '''
2436
        import math
2437
        [x, y, w, h] = cv2.boundingRect(contours[idx])
2438

    
2439
        if (w < 250 and h < 250):
2440
            return ('Unknown', [])
2441

    
2442
        fLines = []
2443
        maxDifAngle = 3
2444
        mask = np.zeros_like(imgNot)
2445
        cv2.drawContours(mask, contours, idx, 123, -1)  # Draw filled contour in mask
2446
        out = np.zeros_like(imgNot)  # Extract out the object and place into output image
2447
        out[mask == 123] = imgNot[mask == 123]
2448

    
2449
        # Now crop
2450
        ##print(out)
2451
        (x, y) = np.where(mask == 123)
2452
        (topx, topy) = (np.min(x), np.min(y))
2453
        (bottomx, bottomy) = (np.max(x), np.max(y))
2454
        out = out[topx:bottomx + 1, topy:bottomy + 1]
2455
        h, w = out.shape[0], out.shape[1]
2456
        maxDifH, maxDifW = math.ceil(math.tan(4 * math.pi / 180) / 2 * w), math.ceil(
2457
            math.tan(4 * math.pi / 180) / 2 * h)
2458

    
2459
        # detection lines
2460
        edged2 = cv2.Canny(out, 100, 200)
2461
        lines = cv2.HoughLinesP(image=edged2, rho=1, theta=np.pi / 180, threshold=25, minLineLength=30, maxLineGap=25)
2462
        # lines = cv2.HoughLines(edged2, 1, np.pi/180, 60)
2463
        if lines is None:
2464
            return ('Unknown', [])
2465
        for line in lines:
2466
            # r, theta = line[0]
2467
            # a, b = np.cos(theta), np.sin(theta)
2468
            # x0, y0 = a * r, b * r
2469
            # x1, y1 = int(x0 + 1000 * (-b)), int(y0 + 1000 * a)
2470
            # x2, y2 = int(x0 - 1000 * (-b)), int(y0 - 1000 * a)
2471
            # cv2.line(out, (x1, y1), (x2, y2), (0, 255, 0), 3)
2472
            x1, y1, x2, y2 = line[0]
2473
            degree = math.atan2(y2 - y1, x2 - x1) * 180 / math.pi
2474
            fLine = [x1, y1, x2, y2, degree]
2475
            # print(fLine)
2476
            fLines.append(fLine)
2477

    
2478
        horLines = []
2479
        verLines = []
2480
        otherLines = []
2481
        isVH = None
2482
        for fLine in fLines:
2483
            degree = math.fabs(fLine[4])
2484
            if degree >= 90 - maxDifAngle:
2485
                verLines.append(fLine)
2486
            elif degree <= maxDifAngle:
2487
                horLines.append(fLine)
2488
            else:
2489
                otherLines.append(fLine)
2490

    
2491
        baseLines = []
2492
        baseDifV = 0
2493
        if len(horLines):
2494
            x, y = w / 2, 0
2495
            baseDifV = maxDifH
2496
            for horLine in horLines:
2497
                x1, y1, x2, y2 = horLine[0], horLine[1], horLine[2], horLine[3]
2498
                y = ((y2 - y1) / (x2 - x1)) * x + y1 - ((y2 - y1) / (x2 - x1)) * x1
2499
                horLine.append(y)
2500
            baseLines = horLines
2501
            isVH = 'H'
2502
        if len(verLines):
2503
            x, y = 0, h / 2
2504
            baseDifV = maxDifW
2505
            for verLine in verLines:
2506
                x1, y1, x2, y2 = verLine[0], verLine[1], verLine[2], verLine[3]
2507
                x = ((x2 - x1) / (y2 - y1)) * y + x1 - ((x2 - x1) / (y2 - y1)) * y1
2508
                verLine.append(x)
2509
            baseLines = verLines
2510
            isVH = 'V'
2511

    
2512
        for otherLine in otherLines:
2513
            x, y = w / 2, 0
2514
            x1, y1, x2, y2 = otherLine[0], otherLine[1], otherLine[2], otherLine[3]
2515
            y = ((y2 - y1) / (x2 - x1)) * x + y1 - ((y2 - y1) / (x2 - x1)) * x1
2516
            otherLine.append(y)
2517

    
2518
        # determine line no indicator 
2519
        if not ((len(horLines) > 0 and len(verLines) > 0) or len(otherLines) is 0 or (
2520
                len(horLines) == 0 and len(verLines) == 0)):
2521
            result, mergedOtherLine = self.isLineNoIndicator(w, h, maxDifAngle, baseDifV, baseLines, otherLines)
2522
            if result:
2523
                # print(fLines)
2524
                return ('LineIndicator', [isVH, mergedOtherLine])
2525

    
2526
        return ('Unknown', [])
2527

    
2528
    def isLineNoIndicator(self, w, h, maxDifAngle, baseDifV, baseLines, otherLines):
2529
        '''
2530
            @brief      determine line no indicator
2531
            @author     euisung
2532
            @date       2019.03.25
2533
        '''
2534
        import math
2535

    
2536
        if (w < 250 and h < 250):
2537
            return (False, None)
2538

    
2539
        isSameLine = True
2540
        i = 0
2541
        for baseLine in baseLines:
2542
            if not isSameLine: break
2543
            j = 0
2544
            for baseLinee in baseLines:
2545
                if i == j:
2546
                    j += 1
2547
                    continue
2548
                difV = math.fabs(baseLine[5] - baseLinee[5])
2549
                if difV > baseDifV:
2550
                    isSameLine = False
2551
                    break
2552
                j += 1
2553
            i += 1
2554
        if not isSameLine:
2555
            return (False, None)
2556

    
2557
        isSameLine = True
2558
        i = 0
2559
        maxY = 0
2560
        for otherLine in otherLines:
2561
            y = otherLine[5]
2562
            if math.fabs(y) > maxY:
2563
                maxY = math.fabs(y)
2564
            if not isSameLine: break
2565
            j = 0
2566
            for otherLinee in otherLines:
2567
                if i == j:
2568
                    j += 1
2569
                    continue
2570
                difV = math.fabs(otherLine[4] - otherLinee[4])
2571
                if difV > maxDifAngle:
2572
                    isSameLine = False
2573
                    break
2574
                j += 1
2575
            i += 1
2576
        if not isSameLine:
2577
            return (False, None)
2578

    
2579
        isSameLine = True
2580
        mergedOtherLine = [0, 0, 0, 0]
2581
        i = 0
2582
        maxDif = math.ceil(math.tan(4 * math.pi / 180) * maxY)
2583
        for otherLine in otherLines:
2584
            if not isSameLine: break
2585
            j = 0
2586
            for otherLinee in otherLines:
2587
                if i == j:
2588
                    j += 1
2589
                    continue
2590
                angle = math.fabs(otherLine[4] + otherLinee[4]) / 2
2591
                difV = math.fabs(otherLine[5] - otherLinee[5])
2592
                dist = math.sin((90 - angle) * math.pi / 180) * difV
2593
                if dist > maxDif:
2594
                    isSameLine = False
2595
                    break
2596
                j += 1
2597
            i += 1
2598
            mergedOtherLine[0] += otherLine[0]
2599
            mergedOtherLine[1] += otherLine[1]
2600
            mergedOtherLine[2] += otherLine[2]
2601
            mergedOtherLine[3] += otherLine[3]
2602
        if not isSameLine:
2603
            (False, None)
2604

    
2605
        # Show the output image
2606
        # print('line no indicator')
2607
        mergedOtherLine[0] = round(mergedOtherLine[0] / len(otherLines))
2608
        mergedOtherLine[1] = round(mergedOtherLine[1] / len(otherLines))
2609
        mergedOtherLine[2] = round(mergedOtherLine[2] / len(otherLines))
2610
        mergedOtherLine[3] = round(mergedOtherLine[3] / len(otherLines))
2611
        # cv2.line(out, (mergedOtherLine[0], mergedOtherLine[1]), (mergedOtherLine[2], mergedOtherLine[3]), (255, 255, 255), 3)
2612
        # cv2.imshow('Output', out)
2613
        # cv2.waitKey(0)
2614
        # cv2.destroyAllWindows()
2615
        return (True, mergedOtherLine)
2616

    
2617
    def load_drawing(self, drawing):
2618
        """ load drawing """
2619
        from EngineeringRunItem import QEngineeringRunItem
2620
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2621

    
2622
        app_doc_data = AppDocData.instance()
2623
        try:
2624
            symbols = []
2625
            lines = []
2626

    
2627
            components = app_doc_data.get_components(drawing.UID)
2628
            maxValue = len(components)
2629
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2630

    
2631
            """ parsing all symbols """
2632
            for symbol in [component for component in components if int(component['SymbolType_UID']) != -1]:
2633
                item = SymbolSvgItem.from_database(symbol)
2634
                if item is not None:
2635
                    item.transfer.onRemoved.connect(self.itemRemoved)
2636
                    symbols.append(item)
2637
                    app_doc_data.symbols.append(item)
2638
                    self.addSvgItemToScene(item)
2639
                else:
2640
                    pt = [float(symbol['X']), float(symbol['Y'])]
2641
                    size = [float(symbol['Width']), float(symbol['Height'])]
2642
                    angle = float(symbol['Rotation'])
2643
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2644
                    item.isSymbol = True
2645
                    item.angle = angle
2646
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2647
                    self.graphicsView.scene.addItem(item)
2648
                    item.transfer.onRemoved.connect(self.itemRemoved)
2649

    
2650
                self.progress.setValue(self.progress.value() + 1)
2651

    
2652
            QApplication.processEvents()
2653

    
2654
            # parse texts
2655
            for text in [component for component in components if
2656
                         component['Name'] == 'Text' and component['SymbolType_UID'] == -1]:
2657
                item = QEngineeringTextItem.from_database(text)
2658
                if item is not None:
2659
                    item.uid = text['UID']
2660
                    item.attribute = text['Value']
2661
                    name = text['Name']
2662
                    item.transfer.onRemoved.connect(self.itemRemoved)
2663
                    self.addTextItemToScene(item)
2664

    
2665
                self.progress.setValue(self.progress.value() + 1)
2666

    
2667
            QApplication.processEvents()
2668

    
2669
            # note
2670
            for note in [component for component in components if
2671
                         component['Name'] == 'Note' and component['SymbolType_UID'] == -1]:
2672
                item = QEngineeringTextItem.from_database(note)
2673
                if item is not None:
2674
                    item.uid = note['UID']
2675
                    attributeValue = note['Value']
2676
                    name = note['Name']
2677
                    item.transfer.onRemoved.connect(self.itemRemoved)
2678
                    self.addTextItemToScene(item)
2679

    
2680
                self.progress.setValue(self.progress.value() + 1)
2681

    
2682
            QApplication.processEvents()
2683

    
2684
            for line in [component for component in components if
2685
                         component['Name'] == 'Line' and component['SymbolType_UID'] == -1]:
2686
                item = QEngineeringLineItem.from_database(line)
2687
                if item:
2688
                    item.transfer.onRemoved.connect(self.itemRemoved)
2689
                    self.graphicsView.scene.addItem(item)
2690
                    lines.append(item)
2691

    
2692
                self.progress.setValue(self.progress.value() + 1)
2693

    
2694
            QApplication.processEvents()
2695

    
2696
            for unknown in [component for component in components if
2697
                            component['Name'] == 'Unknown' and component['SymbolType_UID'] == -1]:
2698
                item = QEngineeringUnknownItem.from_database(unknown)
2699
                item.transfer.onRemoved.connect(self.itemRemoved)
2700
                if item is not None:
2701
                    item.transfer.onRemoved.connect(self.itemRemoved)
2702
                    self.graphicsView.scene.addItem(item)
2703

    
2704
                self.progress.setValue(self.progress.value() + 1)
2705

    
2706
            QApplication.processEvents()
2707

    
2708
            for component in [component for component in components if
2709
                              component['Name'] == 'Line NO' and component['SymbolType_UID'] == -1]:
2710
                line_no = QEngineeringLineNoTextItem.from_database(component)
2711
                if type(line_no) is QEngineeringLineNoTextItem:
2712
                    line_no.transfer.onRemoved.connect(self.itemRemoved)
2713
                    self.addTextItemToScene(line_no)
2714
                    line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2715

    
2716
                    runs = app_doc_data.get_pipe_runs(str(line_no.uid))
2717
                    if not runs: continue
2718
                    for run in runs:
2719
                        line_run = QEngineeringRunItem()
2720
                        run_items = app_doc_data.get_pipe_run_items(run['UID'])
2721
                        for record in run_items:
2722
                            uid = record['Components_UID']
2723
                            run_item = self.graphicsView.findItemByUid(uid)
2724
                            if run_item is not None:
2725
                                run_item._owner = line_no
2726
                                line_run.items.append(run_item)
2727
                        line_run.owner = line_no
2728
                        line_no.runs.append(line_run)
2729

    
2730
                        for run_item in line_run.items:
2731
                            if issubclass(type(run_item), SymbolSvgItem): self.itemTreeWidget.addTreeItem(
2732
                                line_no_tree_item, run_item)
2733

    
2734
                self.progress.setValue(self.progress.value() + 1)
2735
            QApplication.processEvents()
2736

    
2737
            for component in [component for component in components if
2738
                              component['Name'] == 'Trim Line NO' and component['SymbolType_UID'] == -1]:
2739
                line_no = QEngineeringTrimLineNoTextItem()
2740
                line_no.uid = uuid.UUID(component['UID'])
2741

    
2742
                runs = app_doc_data.get_pipe_runs(str(line_no.uid))
2743
                if not runs: continue
2744
                for run in runs:
2745
                    line_run = QEngineeringRunItem()
2746
                    run_items = app_doc_data.get_pipe_run_items(run['UID'])
2747
                    for record in run_items:
2748
                        uid = record['Components_UID']
2749
                        run_item = self.graphicsView.findItemByUid(uid)
2750
                        if run_item is not None:
2751
                            run_item.owner = line_no
2752
                            line_run.items.append(run_item)
2753
                line_no.runs.append(line_run)
2754
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2755

    
2756
                for run_item in line_run.items:
2757
                    if issubclass(type(run_item), SymbolSvgItem): self.itemTreeWidget.addTreeItem(line_no_tree_item,
2758
                                                                                                  run_item)
2759

    
2760
                app_doc_data.tracerLineNos.append(line_no)
2761

    
2762
                self.progress.setValue(self.progress.value() + 1)
2763

    
2764
            for component in [component for component in components if
2765
                              component['Name'] == 'VendorPackage' and component['SymbolType_UID'] == -1]:
2766
                item = QEngineeringVendorItem.from_database(component)
2767
                if item is not None:
2768
                    item.transfer.onRemoved.connect(self.itemRemoved)
2769
                    self.graphicsView.scene.addItem(item)
2770

    
2771
            # connect flow item to line
2772
            for line in lines:
2773
                line.update_arrow()
2774
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
2775
            #    for line in lines:
2776
            #        if flowMark.owner is line:
2777
            #            line._flowMark.append(flowMark)
2778
            #            flowMark.setParentItem(line)
2779
            # up to here
2780

    
2781
            """ update scene """
2782
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2783
            for item in self.graphicsView.scene.items():
2784
                item.setVisible(True)
2785

    
2786
                # binding items
2787
                if hasattr(item, 'owner'):
2788
                    item.owner
2789
                if hasattr(item, 'connectors'):
2790
                    for connector in item.connectors:
2791
                        connector.connectedItem
2792

    
2793
        except Exception as ex:
2794
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2795
                                                          sys.exc_info()[-1].tb_lineno)
2796
            self.addMessage.emit(MessageType.Error, message)
2797
        finally:
2798
            app_doc_data.clearTempDBData
2799
            # self.graphicsView.scene.blockSignals(False)
2800

    
2801
    '''
2802
        @brief      load recognition result
2803
        @author     humkyung
2804
        @date       2018.04.??
2805
        @history    humkyung 2018.01.12 parse originalpoint and connectionpoint
2806
                    Jeongwoo 2018.04.17 add QGraphicItem with Rotated text
2807
                    Jeongwoo 2018.04.23 Change to Draw texts on QEngineeringTextItem
2808
                    humkyung 2018.04.23 connect item remove slot to result tree
2809
                    Jeongwoo 2018.04.25 Add if state with QEngineeringNoteItem
2810
                    Jeongwoo 2018.04.26 Change method to create TextItem object with TextItemFactory
2811
                    Jeongwoo 2018.05.03 Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
2812
                    Jeongwoo 2018.05.29 Change method name / Change method to add item / Add Line item
2813
                    Jeongwoo 2018.05.30 Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol) / Change method name / Change XML NODE NAMES
2814
                    Jeongwoo 2018.06.12 Add LineNoTextItem from LINE_NO
2815
                    Jeongwoo 2018.06.14 Add UnknownItem from UNKNOWN
2816
                    Jeongwoo 2018.06.18 Update Scene after all item added
2817
                                        Add connect on unknown item
2818
                                        Add [transfer] for using pyqtSignal
2819
                    kyouho  2018.07.12  Add line property logic
2820
                    humkyung 2018.08.22 show progress while loading xml file
2821
                    2018.11.22      euisung     fix note road
2822
    '''
2823

    
2824
    def loadRecognitionResultFromXml(self, xmlPath):
2825
        docData = AppDocData.instance()
2826
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
2827
        from EngineeringRunItem import QEngineeringRunItem
2828
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2829

    
2830
        try:
2831
            # self.graphicsView.scene.blockSignals(True)
2832

    
2833
            symbols = []
2834
            lines = []
2835

    
2836
            xml = parse(xmlPath)
2837
            root = xml.getroot()
2838

    
2839
            maxValue = 0
2840
            maxValue = maxValue + len(list(root.iter('SYMBOL'))) - len(
2841
                list(root.iterfind('LINENOS/LINE_NO/RUN/SYMBOL'))) - len(
2842
                list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/SYMBOL')))
2843
            maxValue = maxValue + len(list(root.iterfind('TEXTINFOS/ATTRIBUTE')))
2844
            maxValue = maxValue + len(list(root.iterfind('NOTES/ATTRIBUTE')))
2845
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
2846
            maxValue = maxValue + len(list(root.iter('LINE'))) - len(
2847
                list(root.iterfind('LINENOS/LINE_NO/RUN/LINE'))) - len(
2848
                list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/LINE')))
2849
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
2850
            # maxValue = maxValue + len(list(root.iter('SIZETEXT')))
2851
            maxValue = maxValue + len(list(root.iter('TRIM_LINE_NO')))
2852
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2853

    
2854
            """ parsing all symbols """
2855
            for symbol in root.find('SYMBOLS').iter('SYMBOL'):
2856
                item = SymbolSvgItem.fromXml(symbol)
2857
                if item is not None:
2858
                    item.transfer.onRemoved.connect(self.itemRemoved)
2859
                    symbols.append(item)
2860
                    docData.symbols.append(item)
2861
                    self.addSvgItemToScene(item)
2862
                else:
2863
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2864
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2865
                    angle = float(symbol.find('ANGLE').text)
2866
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2867
                    item.isSymbol = True
2868
                    item.angle = angle
2869
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2870
                    self.graphicsView.scene.addItem(item)
2871
                    item.transfer.onRemoved.connect(self.itemRemoved)
2872

    
2873
                self.progress.setValue(self.progress.value() + 1)
2874

    
2875
            QApplication.processEvents()
2876

    
2877
            # parse texts
2878
            for text in root.find('TEXTINFOS').iter('ATTRIBUTE'):
2879
                item = QEngineeringTextItem.fromXml(text)
2880
                if item is not None:
2881
                    uid = text.find('UID')
2882
                    attributeValue = text.find('ATTRIBUTEVALUE')
2883
                    name = text.find('NAME').text
2884
                    item.transfer.onRemoved.connect(self.itemRemoved)
2885
                    self.addTextItemToScene(item)
2886
                    # docData.texts.append(item)
2887

    
2888
                    if name == 'TEXT':
2889
                        if uid is not None and attributeValue is not None:
2890
                            item.uid = uid.text
2891
                            item.attribute = attributeValue.text
2892

    
2893
                self.progress.setValue(self.progress.value() + 1)
2894

    
2895
            QApplication.processEvents()
2896

    
2897
            # note
2898
            for text in root.find('NOTES').iter('ATTRIBUTE'):
2899
                item = QEngineeringTextItem.fromXml(text)
2900
                if item is not None:
2901
                    uid = text.find('UID')
2902
                    attributeValue = text.find('ATTRIBUTEVALUE')
2903
                    name = text.find('NAME').text
2904
                    item.transfer.onRemoved.connect(self.itemRemoved)
2905
                    self.addTextItemToScene(item)
2906

    
2907
                    if name == 'NOTE':
2908
                        if uid is not None:
2909
                            item.uid = uid.text
2910

    
2911
                self.progress.setValue(self.progress.value() + 1)
2912

    
2913
            QApplication.processEvents()
2914

    
2915
            for line in root.find('LINEINFOS').iter('LINE'):
2916
                item = QEngineeringLineItem.fromXml(line)
2917
                if item:
2918
                    item.transfer.onRemoved.connect(self.itemRemoved)
2919
                    self.graphicsView.scene.addItem(item)
2920
                    lines.append(item)
2921

    
2922
                self.progress.setValue(self.progress.value() + 1)
2923

    
2924
            QApplication.processEvents()
2925

    
2926
            for unknown in root.iter('UNKNOWN'):
2927
                item = QEngineeringUnknownItem.fromXml(unknown)
2928
                if item is not None:
2929
                    item.transfer.onRemoved.connect(self.itemRemoved)
2930
                    self.graphicsView.scene.addItem(item)
2931

    
2932
                self.progress.setValue(self.progress.value() + 1)
2933

    
2934
            QApplication.processEvents()
2935

    
2936
            # """ add tree widget """
2937
            # for item in symbols:
2938
            #    docData.symbols.append(item)
2939
            #    self.addSvgItemToScene(item)
2940
            #    self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2941

    
2942
            for line_no_node in root.find('LINENOS').iter('LINE_NO'):
2943
                line_no = QEngineeringLineNoTextItem.fromXml(line_no_node)
2944
                if line_no is None: continue
2945
                line_no.transfer.onRemoved.connect(self.itemRemoved)
2946
                self.addTextItemToScene(line_no)
2947
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2948
                if type(line_no) is not QEngineeringLineNoTextItem: continue
2949

    
2950
                runs_node = line_no_node.findall('RUN')
2951
                if runs_node is None: continue
2952

    
2953
                for run_node in runs_node:
2954
                    line_run = QEngineeringRunItem()
2955
                    for child_node in run_node:
2956
                        uidElement = child_node.find('UID')
2957
                        if uidElement is not None:
2958
                            uid = uidElement.text
2959
                            run_item = self.graphicsView.findItemByUid(uid)
2960
                            if run_item is not None:
2961
                                run_item._owner = line_no
2962
                                line_run.items.append(run_item)
2963
                    line_run.owner = line_no
2964
                    line_no.runs.append(line_run)
2965

    
2966
                    for run_item in line_run.items:
2967
                        if issubclass(type(run_item), SymbolSvgItem): self.itemTreeWidget.addTreeItem(line_no_tree_item,
2968
                                                                                                      run_item)
2969

    
2970
                # docData.tracerLineNos.append(line_no)
2971

    
2972
                self.progress.setValue(self.progress.value() + 1)
2973
            QApplication.processEvents()
2974

    
2975
            for trimLineNo in root.iter('TRIM_LINE_NO'):
2976
                line_no = QEngineeringTrimLineNoTextItem()
2977
                line_no.uid = uuid.UUID(trimLineNo.find('UID').text)
2978

    
2979
                run = trimLineNo.find('RUN')
2980
                if run is not None:
2981
                    line_run = QEngineeringRunItem()
2982
                    for child in run:
2983
                        uidElement = child.find('UID')
2984
                        if uidElement is not None:
2985
                            uid = uidElement.text
2986
                            run_item = self.graphicsView.findItemByUid(uid)
2987
                            if run_item is not None:
2988
                                run_item.owner = line_no
2989
                                line_run.items.append(run_item)
2990
                    line_no.runs.append(line_run)
2991
                    line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2992

    
2993
                    for run_item in line_run.items:
2994
                        if issubclass(type(run_item), SymbolSvgItem): self.itemTreeWidget.addTreeItem(line_no_tree_item,
2995
                                                                                                      run_item)
2996

    
2997
                    docData.tracerLineNos.append(line_no)
2998

    
2999
                self.progress.setValue(self.progress.value() + 1)
3000
            QApplication.processEvents()
3001

    
3002
            if root.find('VENDORS') is not None:
3003
                for vendor in root.find('VENDORS').iter('VENDOR'):
3004
                    item = QEngineeringVendorItem.fromXml(vendor)
3005
                    item.transfer.onRemoved.connect(self.itemRemoved)
3006
                    self.graphicsView.scene.addItem(item)
3007

    
3008
            # connect flow item to line
3009
            for line in lines:
3010
                line.update_arrow()
3011
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
3012
            #    for line in lines:
3013
            #        if flowMark.owner is line:
3014
            #            line._flowMark.append(flowMark)
3015
            #            flowMark.setParentItem(line)
3016
            # up to here
3017

    
3018
            """ update scene """
3019
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
3020
            for item in self.graphicsView.scene.items():
3021
                item.setVisible(True)
3022

    
3023
                # binding items
3024
                if hasattr(item, 'owner'):
3025
                    item.owner
3026
                if hasattr(item, 'connectors'):
3027
                    for connector in item.connectors:
3028
                        connector.connectedItem
3029

    
3030
        except Exception as ex:
3031
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3032
                                                          sys.exc_info()[-1].tb_lineno)
3033
            self.addMessage.emit(MessageType.Error, message)
3034
        finally:
3035
            pass
3036
            # self.graphicsView.scene.blockSignals(False)
3037

    
3038
    '''
3039
        @brief      Remove added item on same place and Add GraphicsItem
3040
        @author     Jeongwoo
3041
        @date       2018.05.25
3042
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
3043
                    2018.06.18  Jeongwoo    Set Z-index
3044
    '''
3045

    
3046
    def addSvgItemToScene(self, svgItem):
3047
        svgItem.addSvgItemToScene(self.graphicsView.scene)
3048

    
3049
    '''
3050
        @brief      Remove added item on same place and Add GraphicsItem
3051
        @author     Jeongwoo
3052
        @date       2018.05.25
3053
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
3054
                    2018.06.05  Jeongwoo    Remove Size condition
3055
                    2018.06.18  Jeongwoo    Set Z-index
3056
    '''
3057

    
3058
    def addTextItemToScene(self, textItem):
3059
        textItem.addTextItemToScene(self.graphicsView.scene)
3060

    
3061
    '''
3062
        @brief      Remove added item on same place and Add GraphicsItem
3063
        @author     Jeongwoo
3064
        @date       2018.05.29
3065
        @history    2018.06.18  Jeongwoo    Set Z-index
3066
    '''
3067

    
3068
    def addLineItemToScene(self, lineItem):
3069
        self.graphicsView.scene.addItem(lineItem)
3070

    
3071
    '''
3072
        @brief      generate output xml file
3073
        @author     humkyung
3074
        @date       2018.04.23
3075
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
3076
    '''
3077

    
3078
    def generateOutput(self):
3079
        import XmlGenerator as xg
3080

    
3081
        if not self.graphicsView.hasImage():
3082
            self.showImageSelectionMessageBox()
3083
            return
3084

    
3085
        try:
3086
            appDocData = AppDocData.instance()
3087

    
3088
            ## collect items
3089
            appDocData.lines.clear()
3090
            appDocData.lines = [item for item in self.graphicsView.scene.items() if
3091
                                type(item) is QEngineeringLineItem and item.owner is None]
3092

    
3093
            appDocData.symbols.clear()
3094
            appDocData.symbols = [item for item in self.graphicsView.scene.items() if
3095
                                  issubclass(type(item), SymbolSvgItem) and item.owner is None]
3096

    
3097
            appDocData.equipments.clear()
3098
            for item in self.graphicsView.scene.items():
3099
                if type(item) is QEngineeringEquipmentItem:
3100
                    appDocData.equipments.append(item)
3101

    
3102
            appDocData.texts.clear()
3103
            appDocData.texts = [item for item in self.graphicsView.scene.items() if
3104
                                issubclass(type(item), QEngineeringTextItem) and type(
3105
                                    item) is not QEngineeringLineNoTextItem]
3106
            ## up to here
3107

    
3108
            appDocData.imgOutput = np.ones((appDocData.activeDrawing.height, appDocData.activeDrawing.width),
3109
                                           np.uint8) * 255
3110
            xg.writeOutputXml(appDocData.imgName, appDocData.activeDrawing.width,
3111
                              appDocData.activeDrawing.height)  # TODO: check
3112
            project = appDocData.getCurrentProject()
3113
            cv2.imwrite(os.path.join(project.getTempPath(), 'OUTPUT.png'), appDocData.imgOutput)
3114
        except Exception as ex:
3115
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3116
                                                          sys.exc_info()[-1].tb_lineno)
3117
            self.addMessage.emit(MessageType.Error, message)
3118

    
3119
    '''
3120
        @brief      resetting attribute at secne
3121
        @author     kyoyho
3122
        @date       2018.08.21
3123
    '''
3124
    """
3125
    def checkAttribute(self):
3126
        try:
3127

3128
            docData = AppDocData.instance()
3129
            if not self.graphicsView.hasImage():
3130
                return
3131

3132
            # symbol 경우
3133
            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]
3134
            for item in items:
3135
                attrs = item.attrs
3136
                
3137
                removeAttrList = []
3138
                for attr in attrs:
3139
                    if type(attr) is tuple:
3140
                        continue
3141

3142
                    if attr is None:
3143
                        removeAttrList.append(attr)
3144
                        continue
3145

3146
                    attrInfo = docData.getSymbolAttributeByUID(attr.UID)
3147
                    if attrInfo is None:
3148
                        removeAttrList.append(attr)
3149
                    # 해당 attribute가 맞는지 확인
3150
                    else:
3151
                        attrType = attrInfo.AttributeType
3152
                        _type = type(attr)
3153
                        if attrType == 'Symbol Item':
3154
                            if not issubclass(_type, SymbolSvgItem):
3155
                                removeAttrList.append(attr)
3156
                        elif attrType == 'Text Item':
3157
                            if _type is not QEngineeringTextItem:
3158
                                removeAttrList.append(attr)
3159
                        elif attrType == 'Int':
3160
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
3161
                                removeAttrList.append(attr)
3162
                        elif attrType == 'String':
3163
                            if _type is not UserInputAttribute:
3164
                                removeAttrList.append(attr)
3165

3166
                for attr in removeAttrList:
3167
                    del attrs[attr]
3168

3169
            # Line No Text Item의 경우
3170
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringLineNoTextItem)]
3171
            for item in items:
3172
                attrs = item.attrs
3173
                
3174
                removeAttrList = []
3175
                for attr in attrs:
3176
                    if type(attr) is UserInputAttribute:
3177
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
3178
                        if attrInfo is None:
3179
                            removeAttrList.append(attr)
3180

3181
                for attr in removeAttrList:
3182
                    del attrs[attr]
3183

3184
        except Exception as ex:
3185
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
3186
                self.addMessage.emit(MessageType.Error, message)
3187
    """
3188
    '''
3189
        @brief      Check Number
3190
        @author     kyouho
3191
        @date       2018.08.20
3192
    '''
3193

    
3194
    def isNumber(self, num):
3195
        p = re.compile('(^[0-9]+$)')
3196
        result = p.match(num)
3197

    
3198
        if result:
3199
            return True
3200
        else:
3201
            return False
3202

    
3203
    '''
3204
        @brief      find overlap Connector
3205
        @author     kyouho
3206
        @date       2018.08.28
3207
    '''
3208

    
3209
    def findOverlapConnector(self, connectorItem):
3210
        from shapely.geometry import Point
3211
        from EngineeringConnectorItem import QEngineeringConnectorItem
3212
        itemList = []
3213

    
3214
        x = connectorItem.center()[0]
3215
        y = connectorItem.center()[1]
3216

    
3217
        connectors = [item for item in self.graphicsView.scene.items() if
3218
                      type(item) is QEngineeringConnectorItem and item != connectorItem]
3219
        for connector in connectors:
3220
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
3221
                itemList.append(connector.parent)
3222

    
3223
        return itemList
3224

    
3225

    
3226
if __name__ == '__main__':
3227
    import locale
3228
    from PyQt5.QtCore import QTranslator
3229
    from License import QLicenseDialog
3230
    from ProjectDialog import Ui_Dialog
3231
    from App import App
3232

    
3233
    app = App(sys.argv)
3234
    try:
3235
        if True == QLicenseDialog.check_license_key():
3236
            dlg = Ui_Dialog()
3237
            selectedProject = dlg.showDialog()
3238
            if selectedProject is not None:
3239
                AppDocData.instance().setCurrentProject(selectedProject)
3240
                app._mainWnd = MainWindow.instance()
3241
                app._mainWnd.show()
3242
                sys.exit(app.exec_())
3243
    except Exception as ex:
3244
        print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3245
                                                  sys.exc_info()[-1].tb_lineno))
3246
    finally:
3247
        pass
클립보드 이미지 추가 (최대 크기: 500 MB)