프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / MainWindow.py @ 0de8c1ca

이력 | 보기 | 이력해설 | 다운로드 (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.selectionChanged.connect(self.onSelectionChanged)
259
        self.actionInitialize.triggered.connect(self.onInitializeScene)
260
        self.actionSave.triggered.connect(self.actionSaveCliked)
261
        self.addMessage.connect(self.onAddMessage)
262
        self.actionFindReplaceText.triggered.connect(self.findReplaceTextClicked)
263
        self.pushButtonDetectSymbol.clicked.connect(self.onShowDetectSymbol)
264
        #self.graphicsView.scene.contents_changed.connect(self.scene_changed)
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
    def display_number_of_items(self):
587
        """display count of symbol, line, text"""
588

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

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

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

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

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

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

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

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

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

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

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

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

    
675
    def actionSaveCliked(self):
676
        from EngineeringAbstractItem import QEngineeringAbstractItem
677
        from SaveWorkCommand import SaveWorkCommand
678

    
679
        try:
680
            app_doc_data = AppDocData.instance()
681
            if app_doc_data.imgName is None:
682
                self.showImageSelectionMessageBox()
683
                return
684

    
685
            app_doc_data.clearItemList(False)
686

    
687
            items = self.graphicsView.scene.items()
688
            for item in items:
689
                if issubclass(type(item), QEngineeringAbstractItem):
690
                    app_doc_data.allItems.append(item)
691
                    if issubclass(type(item), QEngineeringTextItem):
692
                        app_doc_data.texts.append(item)
693

    
694
            itemTypes = []
695
            for item in items:
696
                typeExist = False
697
                for itemType in itemTypes:
698
                    if type(item) is itemType:
699
                        typeExist = True
700
                        break
701
                if not typeExist:
702
                    itemTypes.append(type(item))
703

    
704
            self._save_work_cmd = SaveWorkCommand()
705
            self._save_work_cmd.show_progress.connect(self.progress_bar.setValue)
706
            self._save_work_cmd.display_message.connect(self.onAddMessage)
707
            self._save_work_cmd.finished.connect(self.save_finished)
708

    
709
            self._save_work_cmd.start()
710
        except Exception as ex:
711
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
712
                                                          sys.exc_info()[-1].tb_lineno)
713
            self.addMessage.emit(MessageType.Error, message)
714

    
715
    def save_finished(self):
716
        """reload drawing list"""
717

    
718
        self._save_work_cmd.show_progress.emit(100)
719
        QMessageBox.about(self.graphicsView, self.tr('Information'), self._save_work_cmd.resultStr)
720
        self.load_drawing_list()
721

    
722
        app_doc_data = AppDocData.instance()
723
        app_doc_data.activeDrawing.modified = False
724
        title = self.windowTitle()
725
        self.setWindowTitle(title[:-1] if title[-1] == '*' else title)
726

    
727
    '''
728
        @brief      refresh resultPropertyTableWidget
729
        @author     kyouho
730
        @date       2018.07.19
731
    '''
732

    
733
    def refreshResultPropertyTableWidget(self):
734
        items = self.graphicsView.scene.selectedItems()
735
        if len(items) == 1:
736
            self.resultPropertyTableWidget.show_item_property(items[0])
737

    
738
    '''
739
        @brief  add message listwidget
740
        @author humkyung
741
        @date   2018.07.31
742
    '''
743

    
744
    def onAddMessage(self, messageType, message):
745
        from AppDocData import MessageType
746

    
747
        try:
748
            current = QDateTime.currentDateTime()
749

    
750
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
751
            item.setFlags(item.flags() | Qt.ItemIsEditable)
752
            if messageType == MessageType.Error:
753
                item.setBackground(Qt.red)
754

    
755
            self.listWidgetLog.insertItem(0, item)
756
        except Exception as ex:
757
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
758
                                                      sys.exc_info()[-1].tb_lineno))
759

    
760
    '''
761
        @brief      clear log
762
        @author     humkyung
763
        @date       2018.08.01
764
    '''
765

    
766
    def onClearLog(self):
767
        self.listWidgetLog.clear()
768

    
769
    '''
770
        @brief      rotate selected symbol
771
        @author     humkyung
772
        @date       2018.08.15
773
    '''
774

    
775
    def onRotate(self, action):
776
        selected = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem)]
777
        if len(selected) == 1:
778
            selected[0].rotateSymbol()
779

    
780
    '''
781
        @brief      Area Zoom
782
        @author     Jeongwoo
783
        @date       2018.06.27
784
        @history    connect command's rejected signal
785
    '''
786

    
787
    def onAreaZoom(self, action):
788
        if self.actionZoom.isChecked():
789
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
790
            cmd.onRejected.connect(self.onCommandRejected)
791
            self.graphicsView.command = cmd
792

    
793
    def onVendor(self, action):
794
        '''
795
            @brief      make vendor package area
796
            @author     euisung
797
            @date       2019.04.29
798
        '''
799
        if not self.graphicsView.hasImage():
800
            self.actionVendor.setChecked(False)
801
            self.showImageSelectionMessageBox()
802
            return
803

    
804
        self.actionVendor.setChecked(True)
805
        if not hasattr(self.actionVendor, 'tag'):
806
            self.actionVendor.tag = PlacePolygonCommand.PlacePolygonCommand(self.graphicsView)
807
            self.actionVendor.tag.onSuccess.connect(self.onVendorCreated)
808
            self.actionVendor.tag.onRejected.connect(self.onCommandRejected)
809

    
810
        self.graphicsView.command = self.actionVendor.tag
811

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

    
835
    '''
836
        @brief      Fit Window
837
        @author     Jeongwoo
838
        @date       2018.06.27
839
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
840
    '''
841

    
842
    def fitWindow(self, action):
843
        self.graphicsView.useDefaultCommand()
844
        self.graphicsView.zoomImageInit()
845

    
846
    def scene_changed(self):
847
        """update modified flag"""
848

    
849
        self.display_number_of_items()
850

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

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

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

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

    
894
    def on_help(self):
895
        """ open help file """
896
        import os
897

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

    
906
    '''
907
        @brief      selection changed
908
        @author     humkyung
909
        @date       2018.06.27
910
        @history    humkung 2018.07.08 call tree widget's findItem
911
    '''
912

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

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

    
936
    def onInitializeScene(self, action):
937
        if not self.graphicsView.hasImage():
938
            self.actionEquipment.setChecked(False)
939
            self.showImageSelectionMessageBox()
940

    
941
            return
942

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

    
951
                appDocData = AppDocData.instance()
952
                appDocData.clearItemList(True)
953

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

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

    
974
                if self.path is not None:
975
                    baseName = os.path.basename(self.path)
976
                    self.itemTreeWidget.setCurrentPID(baseName)
977

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

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

    
990
    def actionGroupTriggered(self, action):
991
        if hasattr(self.actionLine, 'tag'):
992
            self.actionLine.tag.onRejected.emit(None)
993

    
994
        if hasattr(self.actionVendor, 'tag'):
995
            self.actionVendor.tag.onRejected.emit(None)
996

    
997
        if self.graphicsView.command is not None:
998
            self.graphicsView.useDefaultCommand()
999

    
1000
        for _action in self.actionGroup.actions():
1001
            _action.setChecked(False)
1002

    
1003
        action.setChecked(True)
1004

    
1005
    '''
1006
        @brief      Create Equipment
1007
        @author     Jeongwoo
1008
        @date       18.05.03
1009
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
1010
    '''
1011

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

    
1023
    '''
1024
        @brief      Create Nozzle
1025
        @author     Jeongwoo
1026
        @date       2018.05.03
1027
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
1028
    '''
1029

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

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

    
1049
    def onAreaOcr(self):
1050
        if not self.graphicsView.hasImage():
1051
            self.actionOCR.setChecked(False)
1052
            self.showImageSelectionMessageBox()
1053
            return
1054

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

    
1063
    '''
1064
        @brief      show text recognition dialog
1065
        @author     humkyung
1066
        @date       2018.08.08
1067
    '''
1068

    
1069
    def onRecognizeText(self, x, y, width, height):
1070
        from OcrResultDialog import QOcrResultDialog
1071

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

    
1105
    '''
1106
        @brief  area configuration
1107
    '''
1108

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

    
1119
    '''
1120
        @brief  configuration
1121
    '''
1122

    
1123
    def configuration(self):
1124
        from ConfigurationDialog import QConfigurationDialog
1125

    
1126
        self.dlgConfiguration = QConfigurationDialog(self)
1127
        # self.dlgConfiguration.show()
1128
        if QDialog.Accepted == self.dlgConfiguration.exec_():
1129
            QEngineeringLineItem.LINE_TYPE_COLORS.clear()
1130
            QEngineeringInstrumentItem.INST_COLOR = None
1131

    
1132
    '''
1133
        @brief  show special item types dialog 
1134
        @author humkyung
1135
        @date   2019.08.10
1136
    '''
1137

    
1138
    def on_show_special_item_types(self):
1139
        from SpecialItemTypesDialog import QSpecialItemTypesDialog
1140

    
1141
        dlg = QSpecialItemTypesDialog(self)
1142
        dlg.exec_()
1143

    
1144
    def on_show_data_transfer(self):
1145
        """ show data transfer dialog """
1146
        from DataTransferDialog import QDataTransferDialog
1147

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

    
1151
    def on_show_data_export(self):
1152
        """ show data export dialog """
1153
        from DataExportDialog import QDataExportDialog
1154

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

    
1158
    def on_show_eqp_datasheet_export(self):
1159
        """ show eqp datasheet export dialog """
1160
        from EqpDatasheetExportDialog import QEqpDatasheetExportDialog
1161

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

    
1165
    def on_show_opc_relation(self):
1166
        """ show opc relation dialog """
1167
        from OPCRelationDialog import QOPCRelationDialog
1168

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

    
1172
    '''
1173
        @brief  show nominal diameter dialog 
1174
        @author humkyung
1175
        @date   2018.06.28
1176
    '''
1177

    
1178
    def onShowCodeTable(self):
1179
        from CodeTableDialog import QCodeTableDialog
1180

    
1181
        dlg = QCodeTableDialog(self)
1182
        dlg.show()
1183
        dlg.exec_()
1184
        if dlg.code_area:
1185
            if dlg.code_area.scene():
1186
                self.graphicsView.scene.removeItem(dlg.code_area)
1187
        if dlg.desc_area:
1188
            if dlg.desc_area.scene():
1189
                self.graphicsView.scene.removeItem(dlg.desc_area)
1190
        self.graphicsView.useDefaultCommand()
1191

    
1192
    '''
1193
        @brief  show HMB data
1194
        @author humkyung
1195
        @date   2018.07.11
1196
    '''
1197

    
1198
    def onHMBData(self):
1199
        from HMBDialog import QHMBDialog
1200

    
1201
        dlg = QHMBDialog(self)
1202
        dlg.show()
1203
        dlg.exec_()
1204

    
1205
    '''
1206
        @brief  show line data list 
1207
        @author humkyung
1208
        @date   2018.05.03
1209
    '''
1210

    
1211
    def showItemDataList(self):
1212
        from ItemDataExportDialog import QItemDataExportDialog
1213

    
1214
        self.dlgLineDataList = QItemDataExportDialog(self)
1215
        self.dlgLineDataList.exec_()
1216

    
1217
    def showTextDataList(self):
1218
        '''
1219
            @brief      show all text item in scene
1220
            @author     euisung
1221
            @date       2019.04.18
1222
        '''
1223
        try:
1224
            if not self.graphicsView.hasImage():
1225
                self.showImageSelectionMessageBox()
1226
                return
1227

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

    
1237
    '''
1238
        @brief  Show Image Selection Guide MessageBox
1239
        @author Jeongwoo
1240
        @date   2018.05.02
1241
    '''
1242

    
1243
    def showImageSelectionMessageBox(self):
1244
        QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("First select image drawing"))
1245

    
1246
    '''
1247
        @brief  change selected lines' type by selected line type
1248
        @author humkyung
1249
        @date   2018.06.27
1250
    '''
1251

    
1252
    def onLineTypeChanged(self, param):
1253
        lineType = self.lineComboBox.itemText(param)
1254
        selected = [item for item in self.graphicsView.scene.selectedItems() if type(item) is QEngineeringLineItem]
1255
        if selected:
1256
            for item in selected:
1257
                item.lineType = lineType
1258

    
1259
    def display_colors(self, value):
1260
        """ display colors """
1261
        from DisplayColors import DisplayColors
1262
        from DisplayColors import DisplayOptions
1263

    
1264
        DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value == True else DisplayOptions.DisplayByLineType
1265
        if hasattr(self, 'graphicsView'):
1266
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1267
            DisplayColors.instance().save_data()
1268

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

    
1281
    def onOpenImageDrawing(self, path=None):
1282
        from Drawing import Drawing
1283

    
1284
        try:
1285
            self.save_drawing_if_necessary()
1286
            if hasattr(self, '_save_work_cmd'):
1287
                self._save_work_cmd.wait()
1288

    
1289
            app_doc_data = AppDocData.instance()
1290

    
1291
            project = app_doc_data.getCurrentProject()
1292

    
1293
            self.path = self.graphicsView.loadImageFromFile(project.getDrawingFilePath(),
1294
                                                            path if type(path) is str else '')
1295
            if os.path.isfile(self.path):
1296
                self.onCommandRejected()
1297
                app_doc_data.clear()
1298

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

    
1308
                drawingList = self.treeWidgetDrawingList.topLevelItem(0)
1309
                for childIdex in range(drawingList.childCount()):
1310
                    drawingList.child(childIdex).setCheckState(0, Qt.Unchecked)
1311
                for childIdex in range(drawingList.childCount()):
1312
                    child = drawingList.child(childIdex)
1313
                    if child.text(0).replace('.png', '') == app_doc_data.activeDrawing.name:
1314
                        child.setCheckState(0, Qt.Checked)
1315
                        break
1316

    
1317
                try:
1318
                    self.show_Progress_bar()
1319

    
1320
                    # disconnect scene changed if signal is connected
1321
                    if self.graphicsView.scene.receivers(self.graphicsView.scene.contents_changed) > 0:
1322
                        self.graphicsView.scene.contents_changed.disconnect()
1323

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

    
1332
                    self.display_number_of_items()
1333
                    # connect scene changed signal
1334
                    self.graphicsView.scene.contents_changed.connect(self.scene_changed)
1335
                finally:
1336
                    if hasattr(self, 'progress'):
1337
                        self.progress.setValue(self.progress.maximum())
1338
                        # self.progress.hide()
1339

    
1340
                self.changeViewCheckedState(True)
1341
        except Exception as ex:
1342
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1343
                                                           sys.exc_info()[-1].tb_lineno)
1344
            self.addMessage.emit(MessageType.Error, message)
1345

    
1346
        return self.path
1347

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

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

    
1379
    def onViewDrawingOnly(self, isChecked):
1380
        '''
1381
            @brief  visible/invisible except image drawing
1382
            @author euisung
1383
            @date   2019.04.22
1384
        '''
1385
        self.changeViewCheckedState(not isChecked, False)
1386
        for item in self.graphicsView.scene.items():
1387
            if type(item) is not QGraphicsPixmapItem:
1388
                item.setVisible(not isChecked)
1389

    
1390
    '''
1391
        @brief  visible/invisible image drawing
1392
        @author humkyung
1393
        @date   2018.06.25
1394
    '''
1395

    
1396
    def onViewImageDrawing(self, isChecked):
1397
        for item in self.graphicsView.scene.items():
1398
            if type(item) is QGraphicsPixmapItem:
1399
                item.setVisible(isChecked)
1400
                break
1401

    
1402
    '''
1403
        @brief  visible/invisible Text 
1404
        @author humkyung
1405
        @date   2018.06.28
1406
    '''
1407

    
1408
    def onViewText(self, isChecked):
1409
        selected = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)]
1410
        for item in selected:
1411
            item.setVisible(isChecked)
1412

    
1413
    '''
1414
        @brief  visible/invisible Symbol 
1415
        @author humkyung
1416
        @date   2018.06.28
1417
    '''
1418

    
1419
    def onViewSymbol(self, isChecked):
1420
        selected = [item for item in self.graphicsView.scene.items() if
1421
                    (issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringErrorItem)]
1422
        for item in selected:
1423
            item.setVisible(isChecked)
1424

    
1425
    '''
1426
        @brief  visible/invisible Line
1427
        @author humkyung
1428
        @date   2018.06.28
1429
    '''
1430

    
1431
    def onViewLine(self, isChecked):
1432
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineItem]
1433
        for item in selected:
1434
            item.setVisible(isChecked)
1435

    
1436
    def onViewInconsistency(self, isChecked):
1437
        '''
1438
            @brief  visible/invisible Inconsistency
1439
            @author euisung
1440
            @date   2019.04.03
1441
        '''
1442
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringErrorItem]
1443
        for item in selected:
1444
            item.setVisible(isChecked)
1445

    
1446
    '''
1447
        @brief  visible/invisible Unknown 
1448
        @author humkyung
1449
        @date   2018.06.28
1450
    '''
1451

    
1452
    def onViewUnknown(self, isChecked):
1453
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringUnknownItem]
1454
        for item in selected:
1455
            item.setVisible(isChecked)
1456

    
1457
    def onViewVendorArea(self, isChecked):
1458
        '''
1459
            @brief  visible/invisible Vendor Area
1460
            @author euisung
1461
            @date   2019.04.29
1462
        '''
1463
        selected = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringVendorItem]
1464
        for item in selected:
1465
            item.setVisible(isChecked)
1466

    
1467
    '''
1468
        @brief  create a symbol
1469
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
1470
                                            Add SymbolSvgItem
1471
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1472
                                            Change method to make svg and image path
1473
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
1474
    '''
1475

    
1476
    def onCreateSymbolClicked(self):
1477
        cmd = FenceCommand.FenceCommand(self.graphicsView)
1478
        cmd.onSuccess.connect(self.onAreaSelected)
1479
        self.graphicsView.command = cmd
1480
        QApplication.setOverrideCursor(Qt.CrossCursor)
1481

    
1482
    '''
1483
        @brief      show SymbolEditorDialog with image selected by user
1484
        @author     humkyung
1485
        @date       2018.07.20
1486
    '''
1487

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

    
1512
                        svg.transfer.onRemoved.connect(self.itemTreeWidget.itemRemoved)
1513
                        svg.addSvgItemToScene(self.graphicsView.scene)
1514
                        for connector in svg.connectors:
1515
                            self.graphicsView.scene.addItem(connector)
1516
        finally:
1517
            self.onCommandRejected()
1518
            QApplication.restoreOverrideCursor()
1519

    
1520
    '''
1521
        @brief      create a line
1522
        @author     humkyung
1523
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
1524
    '''
1525

    
1526
    def onPlaceLine(self):
1527
        if not self.graphicsView.hasImage():
1528
            self.actionLine.setChecked(False)
1529
            self.showImageSelectionMessageBox()
1530
            return
1531

    
1532
        self.actionLine.setChecked(True)
1533
        if not hasattr(self.actionLine, 'tag'):
1534
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
1535
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
1536
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
1537

    
1538
        self.graphicsView.command = self.actionLine.tag
1539

    
1540
    '''
1541
        @brief      add created lines to scene
1542
        @author     humkyung
1543
        @date       2018.07.23
1544
    '''
1545

    
1546
    def onLineCreated(self):
1547
        from EngineeringConnectorItem import QEngineeringConnectorItem
1548

    
1549
        try:
1550
            count = len(self.actionLine.tag._polyline._vertices)
1551
            if count > 1:
1552
                items = []
1553

    
1554
                lineType = self.lineComboBox.currentText()
1555
                for index in range(count - 1):
1556
                    start = self.actionLine.tag._polyline._vertices[index]
1557
                    end = self.actionLine.tag._polyline._vertices[index + 1]
1558

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

    
1573
                    items.append(lineItem)
1574
                    self.graphicsView.scene.addItem(lineItem)
1575

    
1576
                pt = items[-1].endPoint()
1577
                selected = [item for item in self.graphicsView.scene.items(QPointF(pt[0], pt[1])) if
1578
                            type(item) is QEngineeringConnectorItem and item.parent is not items[-1]]
1579
                if selected:
1580
                    items[-1].connect_if_possible(selected[0].parent, 5)
1581

    
1582
        finally:
1583
            self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1584
            self.actionLine.tag.reset()
1585

    
1586
    '''
1587
        @brief      refresh scene
1588
        @author     humkyung
1589
        @date       2018.07.23
1590
    '''
1591

    
1592
    def onCommandRejected(self, cmd=None):
1593
        try:
1594
            if type(cmd) is PlaceLineCommand.PlaceLineCommand:
1595
                if self.actionLine.tag._polyline:
1596
                    self.graphicsView.scene.removeItem(self.actionLine.tag._polyline)
1597
                self.graphicsView.scene.update()
1598
                self.actionLine.tag.reset()
1599

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

    
1623
    '''
1624
        @brief      restore to default command when user press Escape key
1625
        @author     humkyung 
1626
        @date       2018.08.09
1627
        
1628
    '''
1629

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

    
1698
                textItems = [text for text in self.graphicsView.scene.selectedItems() if
1699
                             type(text) is QEngineeringTextItem]
1700
                if not textItems or len(textItems) is 1:
1701
                    return
1702
                
1703
                angle = None
1704
                for item in textItems:
1705
                    if angle is None:
1706
                        angle = item.angle
1707
                    else:
1708
                        if angle != item.angle:
1709
                            return
1710

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

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

    
1745
            QMainWindow.keyPressEvent(self, event)
1746
        except Exception as ex:
1747
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1748
                                                          sys.exc_info()[-1].tb_lineno)
1749
            self.addMessage.emit(MessageType.Error, message)
1750

    
1751
    def recognizeBatch(self, MainWindow):
1752
        '''
1753
            @brief      batch recognize symbol, text and line
1754
            @author     euisung
1755
            @date       2018.11.23
1756
        
1757
        '''
1758
        from datetime import datetime
1759
        from RecognitionDialog import QRecognitionDialog
1760

    
1761
        appDocData = AppDocData.instance()
1762
        project = appDocData.getCurrentProject()
1763
        appDocData.needReOpening = None
1764
        currentPid = None
1765

    
1766
        if self.graphicsView.hasImage():
1767
            currentPid = appDocData.activeDrawing.name
1768

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

    
1782
        if len(checkedDrawingPath) == 0:
1783
            self.showImageSelectionMessageBox()
1784
            return
1785

    
1786
        try:
1787
            self.onClearLog()
1788
            self.dlg = QRecognitionDialog(self, checkedDrawingPath, True)
1789
            self.dlg.exec_()
1790
            if self.dlg.isAccepted == True:
1791
                pass
1792

    
1793
            if appDocData.needReOpening == True:
1794
                drawing = os.path.join(appDocData.getCurrentProject().getDrawingFilePath(), currentPid)
1795
                self.onOpenImageDrawing(drawing)
1796

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

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

    
1827
    def recognize(self, MainWindow):
1828
        from datetime import datetime
1829
        from RecognitionDialog import QRecognitionDialog
1830

    
1831
        if not self.graphicsView.hasImage():
1832
            self.showImageSelectionMessageBox()
1833
            return
1834

    
1835
        try:
1836
            appDocData = AppDocData.instance()
1837

    
1838
            self.onClearLog()
1839
            appDocData.needReOpening = False
1840
            drawingList = []
1841
            drawingList.append(self.path)
1842
            self.dlg = QRecognitionDialog(self, drawingList, False)
1843
            self.dlg.exec_()
1844

    
1845
            if appDocData.needReOpening == True:
1846
                self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name)
1847
                self.drawDetectedItemsToScene()
1848

    
1849
                # save working date-time
1850
                drawings = appDocData.getDrawings()
1851
                drawing = [drawing for drawing in drawings if appDocData.imgName == os.path.splitext(drawing.name)[0]]
1852
                if drawing[0]:
1853
                    drawing[0].datetime = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
1854
                    appDocData.saveDrawings(drawing)
1855

    
1856
                currentPid = appDocData.activeDrawing.name
1857

    
1858
                drawingTop = self.treeWidgetDrawingList.topLevelItem(0)
1859
                drawingCount = drawingTop.childCount()
1860

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

    
1872
    '''
1873
        @brief      remove item from tree widget and then remove from scene
1874
        @date       2018.05.25
1875
        @author     Jeongwoo
1876
    '''
1877

    
1878
    def itemRemoved(self, item):
1879
        try:
1880
            self.itemTreeWidget.itemRemoved(item)
1881

    
1882
            matches = [_item for _item in self.graphicsView.scene.items() if
1883
                       hasattr(_item, 'connectors') and [connector for connector in _item.connectors if
1884
                                                         connector.connectedItem is item]]
1885
            for match in matches:
1886
                for connector in match.connectors:
1887
                    if connector.connectedItem is item:
1888
                        connector.connectedItem = None
1889
                        connector.highlight(False)
1890

    
1891
            # matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'remove_assoc_item')]
1892
            # for _item in matches:
1893
            #    _item.remove_assoc_item(item)
1894

    
1895
            matches = [_item for _item in self.graphicsView.scene.items() if type(_item) is QEngineeringLineNoTextItem]
1896
            matches.extend([lineNo for lineNo in AppDocData.instance().tracerLineNos if type(lineNo) is QEngineeringTrimLineNoTextItem])
1897
            for match in matches:
1898
                if item is match.prop('From'):
1899
                    match.set_property('From', None)
1900
                elif item is match.prop('To'):
1901
                    match.set_property('To', None)
1902

    
1903
                for run in match.runs:
1904
                    if item in run.items:
1905
                        index = run.items.index(item)
1906
                        run.items.pop(index)
1907
                        if not run.items:
1908
                            run.explode()
1909
                        break
1910

    
1911
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'owner')]
1912
            for match in matches:
1913
                if match.owner is item:
1914
                    match.owner = None
1915

    
1916
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'attrs')]
1917
            # done = False
1918
            for match in matches:
1919
                for assoc in match.associations():
1920
                    if item is assoc:
1921
                        for attr in match.attrs.keys():
1922
                            if attr.AssocItem and str(item.uid) == str(attr.AssocItem.uid):
1923
                                attr.AssocItem = None
1924
                                match.attrs[attr] = ''
1925
                                # done = True
1926
                        match.remove_assoc_item(item)
1927
                        break
1928
                # if done: break
1929

    
1930
            # remove error item from inconsistency list
1931
            if type(item) is QEngineeringErrorItem:
1932
                for row in range(self.tableWidgetInconsistency.rowCount()):
1933
                    if item is self.tableWidgetInconsistency.item(row, 0).tag:
1934
                        self.tableWidgetInconsistency.removeRow(row)
1935
                        break
1936

    
1937
            if item.scene() is not None: item.scene().removeItem(item)
1938
        except Exception as ex:
1939
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1940
                                                          sys.exc_info()[-1].tb_lineno)
1941
            self.addMessage.emit(MessageType.Error, message)
1942

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

    
1955
    def connect_attributes(self, MainWindow):
1956
        from LineNoTracer import LineNoTracer
1957
        from ConnectAttrDialog import QConnectAttrDialog
1958

    
1959
        if not self.graphicsView.hasImage():
1960
            self.showImageSelectionMessageBox()
1961
            return
1962

    
1963
        try:
1964
            self.dlgConnectAttr = QConnectAttrDialog(self, self.graphicsView)
1965
            self.dlgConnectAttr.exec_()
1966
            if self.dlgConnectAttr.isRunned:
1967
                self.itemTreeWidget.InitLineNoItems()
1968

    
1969
                # construct line no item
1970
                line_nos = AppDocData.instance().tracerLineNos
1971
                for line_no in line_nos:
1972
                    item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
1973
                    connectedItems = line_no.getConnectedItems()
1974
                    for connectedItem in connectedItems:
1975
                        if issubclass(type(connectedItem), SymbolSvgItem):
1976
                            self.itemTreeWidget.addTreeItem(item, connectedItem)
1977
                # up to here
1978

    
1979
                self.tableWidgetInconsistency.clearContents()
1980
                if self.dlgConnectAttr.ui.checkBoxValidation.isChecked():
1981
                    self.onValidation()
1982

    
1983
                self.graphicsView.invalidateScene()
1984
        except Exception as ex:
1985
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1986
                                                          sys.exc_info()[-1].tb_lineno)
1987
            self.addMessage.emit(MessageType.Error, message)
1988

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

    
2007
    def createDetectedItems(self, symbolList, textInfoList, otherTextInfoList, titleBlockTextInfoList):
2008
        try:
2009
            appDocData = AppDocData.instance()
2010

    
2011
            QApplication.processEvents()
2012
            self.createDetectedSymbolItem(symbolList)
2013
            QApplication.processEvents()
2014
            self.createDetectedTextItem(textInfoList)
2015
            QApplication.processEvents()
2016
            self.createDetectedOtherTextItem(otherTextInfoList)
2017
            QApplication.processEvents()
2018
            self.createDetectedTitleBlockTextItem(titleBlockTextInfoList)
2019

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

    
2027
    def drawDetectedItemsToScene(self):
2028
        '''
2029
            @brief  add detected items to scene
2030
            @author euisung
2031
            @date   2018.11.26
2032
        '''
2033
        appDocData = AppDocData.instance()
2034

    
2035
        try:
2036
            for symbol in appDocData.symbols:
2037
                if issubclass(type(symbol), SymbolSvgItem):
2038
                    self.addSvgItemToScene(symbol)
2039
                else:
2040
                    self.graphicsView.scene.addItem(symbol)
2041

    
2042
            for text in appDocData.texts:
2043
                self.addTextItemToScene(text)
2044

    
2045
            for lineNo in appDocData.tracerLineNos:
2046
                self.addTextItemToScene(lineNo)
2047

    
2048
            for line in appDocData.lines:
2049
                self.graphicsView.scene.addItem(line)
2050
                line.transfer.onRemoved.connect(self.itemRemoved)
2051
                for conn in line.connectors:
2052
                    conn.transfer.onPosChanged.connect(line.onConnectorPosChaned)
2053

    
2054
            for unknown in appDocData.unknowns + appDocData.lineIndicators:
2055
                self.graphicsView.scene.addItem(unknown)
2056
        finally:
2057
            # update scene
2058
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2059

    
2060
    def postDetectLineProcess(self):
2061
        '''
2062
            @brief  check allowables among undetected items
2063
            @author euisung
2064
            @date   2018.11.15
2065
            @history    2018.11.15  euisung    no more used, moved to TextItemFactoy isLineNo()
2066
        '''
2067
        from TextItemFactory import TextItemFactory
2068

    
2069
        appDocData = AppDocData.instance()
2070

    
2071
        tableNames = ["Fluid Code", "Insulation Purpose", "PnID Number", "Piping Materials Class", "Unit Number"]
2072
        tableDatas = []
2073
        for tableName in tableNames:
2074
            tableNameFormat = tableName.replace(' ', '').replace('&&', 'n')
2075
            tableDatas.append(appDocData.getCodeTable(tableNameFormat))
2076

    
2077
        items = self.graphicsView.scene.items()
2078
        for item in items:
2079
            if type(item) is not QEngineeringTextItem:
2080
                continue
2081
            text = item.text()
2082
            for tableData in tableDatas:
2083
                for data in tableData:
2084
                    if data[3] == '':
2085
                        continue
2086
                    else:
2087
                        allows = data[3].split(',')
2088
                        for allow in allows:
2089
                            text = text.replace(allow, data[1])
2090

    
2091
            lineItem = TextItemFactory.instance().createTextItem(text)
2092
            if type(lineItem) is QEngineeringLineNoTextItem:
2093
                lineItem.loc = item.loc
2094
                lineItem.size = item.size
2095
                lineItem.angle = item.angle
2096
                lineItem.area = item.area
2097
                # lineItem.addTextItemToScene(self.graphicsView.scene)
2098
                lineItem.transfer.onRemoved.connect(self.itemRemoved)
2099
                item.transfer.onRemoved.emit(item)
2100
                appDocData.lineNos.append(lineItem)
2101

    
2102
    def createDetectedTitleBlockTextItem(self, textInfoList):
2103
        '''
2104
            @brief  draw title block
2105
            @author euisung
2106
            @date   2018.11.12
2107
            @history    2018.11.26  euisung     remove scene dependency
2108
                        2018.11.29  euisung     change name drawDetectedTitleBlockTextItem() -> createDetectedTitleBlockTextItem
2109
        '''
2110
        from TextItemFactory import TextItemFactory
2111
        import math
2112

    
2113
        try:
2114
            appDocData = AppDocData.instance()
2115

    
2116
            # parse texts
2117
            for textInfo in textInfoList:
2118
                if len(textInfo[1]) is 0:
2119
                    continue
2120
                x = textInfo[1][0].getX()
2121
                y = textInfo[1][0].getY()
2122
                width = textInfo[1][0].getW()
2123
                height = textInfo[1][0].getH()
2124
                angle = round(math.radians(textInfo[1][0].getAngle()), 2)
2125
                text = textInfo[1][0].getText()
2126
                item = TextItemFactory.instance().createTextItem(textInfo)
2127

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

    
2141
    '''
2142
        @brief      
2143
        @author     humkyung
2144
        @date       2018.08.23
2145
        @history    2018.11.26  euisung     remove scene dependency
2146
                    2018.11.26  euisung     isolate scene adding part -> drawDetectedItemsToScene()
2147
                    2018.11.    euisung     no more used
2148
                    2018.11.29  euisung     change name drawDetectedLines() -> createDetectedLines
2149
    '''
2150

    
2151
    def createDetectedLines(self, lineList, worker):
2152
        appDocData = AppDocData.instance()
2153
        area = appDocData.getArea('Drawing')
2154

    
2155
        for pts in lineList:
2156
            processLine = QEngineeringLineItem(vertices=[(area.x + param[0], area.y + param[1]) for param in pts])
2157
            processLine.area = 'Drawing'
2158
            # self.graphicsView.scene.addItem(processLine)
2159
            appDocData.lines.append(processLine)
2160
            appDocData.allItems.append(processLine)
2161

    
2162
            # if processLine.length() > 100: # TODO: check critical length
2163
            #    processLine.addFlowArrow()
2164

    
2165
        # re-order process line's start,end according to flow mark
2166
        # worker.arrangeLinePosition(lines, symbols, listWidget)
2167
        # up to here
2168

    
2169
    '''
2170
        history     2018.06.09  humkyung    check length of original and connection point is 2 while parsing
2171
                    2018.11.26  euisung     remove scene dependency
2172
                    2018.11.29  euisung     change name drawDetectedSymbolItem() -> createDetectedSymbolItem
2173
    '''
2174

    
2175
    def createDetectedSymbolItem(self, symbolList):
2176
        from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
2177
        from SymbolSvgItem import SymbolSvgItem
2178
        import math
2179

    
2180
        try:
2181
            appDocData = AppDocData.instance()
2182
            project = appDocData.getCurrentProject()
2183

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

    
2207
                parentSymbol = symbol.getBaseSymbol()
2208
                childSymbol = symbol.getAdditionalSymbol()
2209
                hasInstrumentLabel = symbol.getHasInstrumentLabel()
2210

    
2211
                svgFilePath = os.path.join(project.getSvgFilePath(), _type, name + '.svg')
2212
                if os.path.isfile(svgFilePath):
2213
                    svg = SymbolSvgItem.createItem(_type, svgFilePath, owner=None, flip=flip)
2214
                    # print(pt)
2215
                    # print(origin)
2216
                    svg.buildItem(name, _type, angle, pt, size, origin, connPts, parentSymbol, childSymbol,
2217
                                  hasInstrumentLabel)
2218
                    svg.reCalculationRotatedItem()
2219
                    svg.area = 'Drawing'
2220

    
2221
                    # set owner - 2018.07.20 added by humkyung                   
2222
                    matches = [searched for searched in searchedMap if searched[0] == symbol.owner]
2223
                    if len(matches) == 1:
2224
                        svg.owner = matches[0][1]
2225
                    searchedMap.append((symbol, svg))
2226
                    # up to here
2227

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

    
2246
    '''
2247
        @history    2018.06.08  Jeongwoo    Add parameter on round method
2248
        @history    2018.11.02  euisung     Add save note text item
2249
        @history    2018.11.05  euisung     delete save note text item and move to drawDetectedItems()
2250
                    2018.11.26  euisung     remove scene dependency
2251
                    2018.11.29  euisung     change name drawDetectedTextItem() -> createDetectedTextItem
2252
    '''
2253

    
2254
    def createDetectedTextItem(self, textInfoList):
2255
        from TextItemFactory import TextItemFactory
2256
        import math
2257

    
2258
        try:
2259
            appDocData = AppDocData.instance()
2260

    
2261
            # parse texts
2262
            for textInfo in textInfoList:
2263
                x = textInfo.getX()
2264
                y = textInfo.getY()
2265
                width = textInfo.getW()
2266
                height = textInfo.getH()
2267
                angle = round(math.radians(textInfo.getAngle()), 2)
2268
                text = textInfo.getText()
2269
                if not text: continue
2270

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

    
2286
    '''
2287
        @brief      draw detected texts except which in drawing area
2288
        @history    2018.11.29  euisung     change name drawDetectedOtherTextItem() -> createDetectedOtherTextItem
2289
    '''
2290

    
2291
    def createDetectedOtherTextItem(self, otherTextInfoList):
2292
        from TextItemFactory import TextItemFactory
2293
        import math
2294

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

    
2298
            # parse notes
2299
            for textInfoMap in otherTextInfoList:
2300
                if textInfoMap[0] == 'Note' or textInfoMap[1] is None:
2301
                    pass
2302

    
2303
                for textInfo in textInfoMap[1]:
2304
                    x = textInfo.getX()
2305
                    y = textInfo.getY()
2306
                    width = textInfo.getW()
2307
                    height = textInfo.getH()
2308
                    angle = round(math.radians(textInfo.getAngle()))
2309
                    text = textInfo.getText()
2310

    
2311
                    item = TextItemFactory.instance().createTextItem(textInfo)
2312

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

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

    
2338
    def createUnknownItems(self, path):
2339
        from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem
2340
        from EngineeringLineItem import QEngineeringLineItem
2341
        from EngineeringUnknownItem import QEngineeringUnknownItem
2342
        from SaveWorkCommand import SaveWorkCommand
2343

    
2344
        try:
2345
            docData = AppDocData.instance()
2346
            project = docData.getCurrentProject()
2347
            windowSize = docData.getSlidingWindowSize()
2348

    
2349
            thickness = int(windowSize[1])
2350

    
2351
            if docData.needReOpening is not None:
2352
                docData.needReOpening = True
2353

    
2354
            diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(path))
2355
            if os.path.isfile(diffFilePath):
2356
                imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255,
2357
                                        cv2.THRESH_BINARY)[1]
2358

    
2359
                ## remove line
2360
                lines = docData.lines
2361
                for line in lines:
2362
                    line.drawToImage(imgDiff, 255, thickness) if line.thickness is None else line.drawToImage(imgDiff,
2363
                                                                                                              255,
2364
                                                                                                              line.thickness)
2365
                cv2.imwrite(diffFilePath, imgDiff)
2366
                ## up to here
2367

    
2368
                imgNot = np.ones(imgDiff.shape, np.uint8)
2369
                cv2.bitwise_not(imgDiff, imgNot)
2370
                configs = docData.getConfigs('Filter', 'ErodeSize')
2371
                kernel = int(configs[0].value) if 1 == len(configs) else 3
2372
                imgNot = cv2.erode(imgNot, np.ones((kernel, kernel), np.uint8))
2373
                imgNot = cv2.dilate(imgNot, np.ones((8 + kernel, 8 + kernel), np.uint8))
2374

    
2375
                contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
2376

    
2377
                ##
2378
                idx = 0
2379
                ##
2380
                smallContours = []
2381
                minimumSize = docData.getConfigs('Filter', 'MinimumSize')
2382
                for contour in contours:
2383
                    [x, y, w, h] = cv2.boundingRect(contour)
2384

    
2385
                    # remove too small one
2386
                    if len(minimumSize) is 1:
2387
                        if (w * h < int(minimumSize[0].value) * int(minimumSize[0].value)):
2388
                            smallContours.append(contour)
2389
                            idx += 1
2390
                            continue
2391

    
2392
                    '''
2393
                    rect = QRectF(x, y, w, h)
2394
                    items = [item for item in diffItems if item.boundingRect().contains(rect)]
2395
                    if len(items) > 0: continue
2396
                    
2397
                    items = [item for item in diffItems if rect.contains(item.boundingRect())]
2398
                    for item in items:
2399
                        diffItems.remove(item)
2400
                    '''
2401

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

    
2421
                imgNotRemoveSmall = cv2.drawContours(imgNot, smallContours, -1, 0, -1)
2422
                notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(path))
2423
                cv2.imwrite(notFilePath, imgNotRemoveSmall)
2424
            else:
2425
                message = 'can\'t found {}'.format(diffFilePath)
2426
                self.addMessage.emit(MessageType.Normal, message)
2427

    
2428
            self.dbUpdate()
2429
            SaveWorkCommand.save_to_xml()
2430
        except Exception as ex:
2431
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2432
                                                          sys.exc_info()[-1].tb_lineno)
2433
            self.addMessage.emit(MessageType.Error, message)
2434

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

    
2445
        if (w < 250 and h < 250):
2446
            return ('Unknown', [])
2447

    
2448
        fLines = []
2449
        maxDifAngle = 3
2450
        mask = np.zeros_like(imgNot)
2451
        cv2.drawContours(mask, contours, idx, 123, -1)  # Draw filled contour in mask
2452
        out = np.zeros_like(imgNot)  # Extract out the object and place into output image
2453
        out[mask == 123] = imgNot[mask == 123]
2454

    
2455
        # Now crop
2456
        ##print(out)
2457
        (x, y) = np.where(mask == 123)
2458
        (topx, topy) = (np.min(x), np.min(y))
2459
        (bottomx, bottomy) = (np.max(x), np.max(y))
2460
        out = out[topx:bottomx + 1, topy:bottomy + 1]
2461
        h, w = out.shape[0], out.shape[1]
2462
        maxDifH, maxDifW = math.ceil(math.tan(4 * math.pi / 180) / 2 * w), math.ceil(
2463
            math.tan(4 * math.pi / 180) / 2 * h)
2464

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

    
2484
        horLines = []
2485
        verLines = []
2486
        otherLines = []
2487
        isVH = None
2488
        for fLine in fLines:
2489
            degree = math.fabs(fLine[4])
2490
            if degree >= 90 - maxDifAngle:
2491
                verLines.append(fLine)
2492
            elif degree <= maxDifAngle:
2493
                horLines.append(fLine)
2494
            else:
2495
                otherLines.append(fLine)
2496

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

    
2518
        for otherLine in otherLines:
2519
            x, y = w / 2, 0
2520
            x1, y1, x2, y2 = otherLine[0], otherLine[1], otherLine[2], otherLine[3]
2521
            y = ((y2 - y1) / (x2 - x1)) * x + y1 - ((y2 - y1) / (x2 - x1)) * x1
2522
            otherLine.append(y)
2523

    
2524
        # determine line no indicator 
2525
        if not ((len(horLines) > 0 and len(verLines) > 0) or len(otherLines) is 0 or (
2526
                len(horLines) == 0 and len(verLines) == 0)):
2527
            result, mergedOtherLine = self.isLineNoIndicator(w, h, maxDifAngle, baseDifV, baseLines, otherLines)
2528
            if result:
2529
                # print(fLines)
2530
                return ('LineIndicator', [isVH, mergedOtherLine])
2531

    
2532
        return ('Unknown', [])
2533

    
2534
    def isLineNoIndicator(self, w, h, maxDifAngle, baseDifV, baseLines, otherLines):
2535
        '''
2536
            @brief      determine line no indicator
2537
            @author     euisung
2538
            @date       2019.03.25
2539
        '''
2540
        import math
2541

    
2542
        if (w < 250 and h < 250):
2543
            return (False, None)
2544

    
2545
        isSameLine = True
2546
        i = 0
2547
        for baseLine in baseLines:
2548
            if not isSameLine: break
2549
            j = 0
2550
            for baseLinee in baseLines:
2551
                if i == j:
2552
                    j += 1
2553
                    continue
2554
                difV = math.fabs(baseLine[5] - baseLinee[5])
2555
                if difV > baseDifV:
2556
                    isSameLine = False
2557
                    break
2558
                j += 1
2559
            i += 1
2560
        if not isSameLine:
2561
            return (False, None)
2562

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

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

    
2611
        # Show the output image
2612
        # print('line no indicator')
2613
        mergedOtherLine[0] = round(mergedOtherLine[0] / len(otherLines))
2614
        mergedOtherLine[1] = round(mergedOtherLine[1] / len(otherLines))
2615
        mergedOtherLine[2] = round(mergedOtherLine[2] / len(otherLines))
2616
        mergedOtherLine[3] = round(mergedOtherLine[3] / len(otherLines))
2617
        # cv2.line(out, (mergedOtherLine[0], mergedOtherLine[1]), (mergedOtherLine[2], mergedOtherLine[3]), (255, 255, 255), 3)
2618
        # cv2.imshow('Output', out)
2619
        # cv2.waitKey(0)
2620
        # cv2.destroyAllWindows()
2621
        return (True, mergedOtherLine)
2622

    
2623
    def init_add_tree_item(self, line_no_tree_item, run_item):
2624
        """ insert symbol item and find line no as owner """
2625
        # insert
2626
        self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2627
        # find
2628
        self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2629

    
2630
    def load_drawing(self, drawing):
2631
        """ load drawing """
2632
        from EngineeringRunItem import QEngineeringRunItem
2633
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2634

    
2635
        app_doc_data = AppDocData.instance()
2636
        try:
2637
            symbols = []
2638
            lines = []
2639

    
2640
            components = app_doc_data.get_components(drawing.UID)
2641
            maxValue = len(components)
2642
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2643

    
2644
            """ parsing all symbols """
2645
            for symbol in [component for component in components if int(component['SymbolType_UID']) != -1]:
2646
                item = SymbolSvgItem.from_database(symbol)
2647
                if item is not None:
2648
                    item.transfer.onRemoved.connect(self.itemRemoved)
2649
                    symbols.append(item)
2650
                    app_doc_data.symbols.append(item)
2651
                    self.addSvgItemToScene(item)
2652
                else:
2653
                    pt = [float(symbol['X']), float(symbol['Y'])]
2654
                    size = [float(symbol['Width']), float(symbol['Height'])]
2655
                    angle = float(symbol['Rotation'])
2656
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2657
                    item.isSymbol = True
2658
                    item.angle = angle
2659
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2660
                    self.graphicsView.scene.addItem(item)
2661
                    item.transfer.onRemoved.connect(self.itemRemoved)
2662

    
2663
                self.progress.setValue(self.progress.value() + 1)
2664

    
2665
            QApplication.processEvents()
2666

    
2667
            # parse texts
2668
            for text in [component for component in components if
2669
                         component['Name'] == 'Text' and component['SymbolType_UID'] == -1]:
2670
                item = QEngineeringTextItem.from_database(text)
2671
                if item is not None:
2672
                    item.uid = text['UID']
2673
                    item.attribute = text['Value']
2674
                    name = text['Name']
2675
                    item.transfer.onRemoved.connect(self.itemRemoved)
2676
                    self.addTextItemToScene(item)
2677

    
2678
                self.progress.setValue(self.progress.value() + 1)
2679

    
2680
            QApplication.processEvents()
2681

    
2682
            # note
2683
            for note in [component for component in components if
2684
                         component['Name'] == 'Note' and component['SymbolType_UID'] == -1]:
2685
                item = QEngineeringTextItem.from_database(note)
2686
                if item is not None:
2687
                    item.uid = note['UID']
2688
                    attributeValue = note['Value']
2689
                    name = note['Name']
2690
                    item.transfer.onRemoved.connect(self.itemRemoved)
2691
                    self.addTextItemToScene(item)
2692

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

    
2695
            QApplication.processEvents()
2696

    
2697
            for line in [component for component in components if
2698
                         component['Name'] == 'Line' and component['SymbolType_UID'] == -1]:
2699
                item = QEngineeringLineItem.from_database(line)
2700
                if item:
2701
                    item.transfer.onRemoved.connect(self.itemRemoved)
2702
                    self.graphicsView.scene.addItem(item)
2703
                    lines.append(item)
2704

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

    
2707
            QApplication.processEvents()
2708

    
2709
            for unknown in [component for component in components if
2710
                            component['Name'] == 'Unknown' and component['SymbolType_UID'] == -1]:
2711
                item = QEngineeringUnknownItem.from_database(unknown)
2712
                item.transfer.onRemoved.connect(self.itemRemoved)
2713
                if item is not None:
2714
                    item.transfer.onRemoved.connect(self.itemRemoved)
2715
                    self.graphicsView.scene.addItem(item)
2716

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

    
2719
            QApplication.processEvents()
2720

    
2721
            for component in [component for component in components if
2722
                              component['Name'] == 'Line NO' and component['SymbolType_UID'] == -1]:
2723
                line_no = QEngineeringLineNoTextItem.from_database(component)
2724
                if type(line_no) is QEngineeringLineNoTextItem:
2725
                    line_no.transfer.onRemoved.connect(self.itemRemoved)
2726
                    self.addTextItemToScene(line_no)
2727
                    line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2728

    
2729
                    runs = app_doc_data.get_pipe_runs(str(line_no.uid))
2730
                    if not runs: continue
2731
                    for run in runs:
2732
                        line_run = QEngineeringRunItem()
2733
                        run_items = app_doc_data.get_pipe_run_items(run['UID'])
2734
                        for record in run_items:
2735
                            uid = record['Components_UID']
2736
                            run_item = self.graphicsView.findItemByUid(uid)
2737
                            if run_item is not None:
2738
                                run_item._owner = line_no
2739
                                line_run.items.append(run_item)
2740
                        line_run.owner = line_no
2741
                        line_no.runs.append(line_run)
2742

    
2743
                        for run_item in line_run.items:
2744
                            if issubclass(type(run_item), SymbolSvgItem):
2745
                                self.init_add_tree_item(line_no_tree_item, run_item)
2746

    
2747
                self.progress.setValue(self.progress.value() + 1)
2748
            QApplication.processEvents()
2749

    
2750
            for component in [component for component in components if
2751
                              component['Name'] == 'Trim Line NO' and component['SymbolType_UID'] == -1]:
2752
                line_no = QEngineeringTrimLineNoTextItem()
2753
                line_no.uid = uuid.UUID(component['UID'])
2754

    
2755
                runs = app_doc_data.get_pipe_runs(str(line_no.uid))
2756
                if not runs: continue
2757
                for run in runs:
2758
                    line_run = QEngineeringRunItem()
2759
                    run_items = app_doc_data.get_pipe_run_items(run['UID'])
2760
                    for record in run_items:
2761
                        uid = record['Components_UID']
2762
                        run_item = self.graphicsView.findItemByUid(uid)
2763
                        if run_item is not None:
2764
                            run_item.owner = line_no
2765
                            line_run.items.append(run_item)
2766
                line_no.runs.append(line_run)
2767
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2768

    
2769
                for run_item in line_run.items:
2770
                    if issubclass(type(run_item), SymbolSvgItem):
2771
                        self.init_add_tree_item(line_no_tree_item, run_item)
2772

    
2773
                app_doc_data.tracerLineNos.append(line_no)
2774

    
2775
                self.progress.setValue(self.progress.value() + 1)
2776

    
2777
            for component in [component for component in components if
2778
                              component['Name'] == 'VendorPackage' and component['SymbolType_UID'] == -1]:
2779
                item = QEngineeringVendorItem.from_database(component)
2780
                if item is not None:
2781
                    item.transfer.onRemoved.connect(self.itemRemoved)
2782
                    self.graphicsView.scene.addItem(item)
2783

    
2784
            # connect flow item to line
2785
            for line in lines:
2786
                line.update_arrow()
2787
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
2788
            #    for line in lines:
2789
            #        if flowMark.owner is line:
2790
            #            line._flowMark.append(flowMark)
2791
            #            flowMark.setParentItem(line)
2792
            # up to here
2793

    
2794
            """ update scene """
2795
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2796
            for item in self.graphicsView.scene.items():
2797
                item.setVisible(True)
2798

    
2799
                # binding items
2800
                if hasattr(item, 'owner'):
2801
                    item.owner
2802
                if hasattr(item, 'connectors'):
2803
                    for connector in item.connectors:
2804
                        connector.connectedItem
2805

    
2806
        except Exception as ex:
2807
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2808
                                                          sys.exc_info()[-1].tb_lineno)
2809
            self.addMessage.emit(MessageType.Error, message)
2810
        finally:
2811
            app_doc_data.clearTempDBData
2812
            # self.graphicsView.scene.blockSignals(False)
2813

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

    
2837
    def loadRecognitionResultFromXml(self, xmlPath):
2838
        docData = AppDocData.instance()
2839
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
2840
        from EngineeringRunItem import QEngineeringRunItem
2841
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2842

    
2843
        try:
2844
            # self.graphicsView.scene.blockSignals(True)
2845

    
2846
            symbols = []
2847
            lines = []
2848

    
2849
            xml = parse(xmlPath)
2850
            root = xml.getroot()
2851

    
2852
            maxValue = 0
2853
            maxValue = maxValue + len(list(root.iter('SYMBOL'))) - len(
2854
                list(root.iterfind('LINENOS/LINE_NO/RUN/SYMBOL'))) - len(
2855
                list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/SYMBOL')))
2856
            maxValue = maxValue + len(list(root.iterfind('TEXTINFOS/ATTRIBUTE')))
2857
            maxValue = maxValue + len(list(root.iterfind('NOTES/ATTRIBUTE')))
2858
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
2859
            maxValue = maxValue + len(list(root.iter('LINE'))) - len(
2860
                list(root.iterfind('LINENOS/LINE_NO/RUN/LINE'))) - len(
2861
                list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/LINE')))
2862
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
2863
            # maxValue = maxValue + len(list(root.iter('SIZETEXT')))
2864
            maxValue = maxValue + len(list(root.iter('TRIM_LINE_NO')))
2865
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2866

    
2867
            """ parsing all symbols """
2868
            for symbol in root.find('SYMBOLS').iter('SYMBOL'):
2869
                item = SymbolSvgItem.fromXml(symbol)
2870
                if item is not None:
2871
                    item.transfer.onRemoved.connect(self.itemRemoved)
2872
                    symbols.append(item)
2873
                    docData.symbols.append(item)
2874
                    self.addSvgItemToScene(item)
2875
                else:
2876
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2877
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2878
                    angle = float(symbol.find('ANGLE').text)
2879
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2880
                    item.isSymbol = True
2881
                    item.angle = angle
2882
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2883
                    self.graphicsView.scene.addItem(item)
2884
                    item.transfer.onRemoved.connect(self.itemRemoved)
2885

    
2886
                self.progress.setValue(self.progress.value() + 1)
2887

    
2888
            QApplication.processEvents()
2889

    
2890
            # parse texts
2891
            for text in root.find('TEXTINFOS').iter('ATTRIBUTE'):
2892
                item = QEngineeringTextItem.fromXml(text)
2893
                if item is not None:
2894
                    uid = text.find('UID')
2895
                    attributeValue = text.find('ATTRIBUTEVALUE')
2896
                    name = text.find('NAME').text
2897
                    item.transfer.onRemoved.connect(self.itemRemoved)
2898
                    self.addTextItemToScene(item)
2899
                    # docData.texts.append(item)
2900

    
2901
                    if name == 'TEXT':
2902
                        if uid is not None and attributeValue is not None:
2903
                            item.uid = uid.text
2904
                            item.attribute = attributeValue.text
2905

    
2906
                self.progress.setValue(self.progress.value() + 1)
2907

    
2908
            QApplication.processEvents()
2909

    
2910
            # note
2911
            for text in root.find('NOTES').iter('ATTRIBUTE'):
2912
                item = QEngineeringTextItem.fromXml(text)
2913
                if item is not None:
2914
                    uid = text.find('UID')
2915
                    attributeValue = text.find('ATTRIBUTEVALUE')
2916
                    name = text.find('NAME').text
2917
                    item.transfer.onRemoved.connect(self.itemRemoved)
2918
                    self.addTextItemToScene(item)
2919

    
2920
                    if name == 'NOTE':
2921
                        if uid is not None:
2922
                            item.uid = uid.text
2923

    
2924
                self.progress.setValue(self.progress.value() + 1)
2925

    
2926
            QApplication.processEvents()
2927

    
2928
            for line in root.find('LINEINFOS').iter('LINE'):
2929
                item = QEngineeringLineItem.fromXml(line)
2930
                if item:
2931
                    item.transfer.onRemoved.connect(self.itemRemoved)
2932
                    self.graphicsView.scene.addItem(item)
2933
                    lines.append(item)
2934

    
2935
                self.progress.setValue(self.progress.value() + 1)
2936

    
2937
            QApplication.processEvents()
2938

    
2939
            for unknown in root.iter('UNKNOWN'):
2940
                item = QEngineeringUnknownItem.fromXml(unknown)
2941
                if item is not None:
2942
                    item.transfer.onRemoved.connect(self.itemRemoved)
2943
                    self.graphicsView.scene.addItem(item)
2944

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

    
2947
            QApplication.processEvents()
2948

    
2949
            # """ add tree widget """
2950
            # for item in symbols:
2951
            #    docData.symbols.append(item)
2952
            #    self.addSvgItemToScene(item)
2953
            #    self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2954

    
2955
            for line_no_node in root.find('LINENOS').iter('LINE_NO'):
2956
                line_no = QEngineeringLineNoTextItem.fromXml(line_no_node)
2957
                if line_no is None: continue
2958
                line_no.transfer.onRemoved.connect(self.itemRemoved)
2959
                self.addTextItemToScene(line_no)
2960
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2961
                if type(line_no) is not QEngineeringLineNoTextItem: continue
2962

    
2963
                runs_node = line_no_node.findall('RUN')
2964
                if runs_node is None: continue
2965

    
2966
                for run_node in runs_node:
2967
                    line_run = QEngineeringRunItem()
2968
                    for child_node in run_node:
2969
                        uidElement = child_node.find('UID')
2970
                        if uidElement is not None:
2971
                            uid = uidElement.text
2972
                            run_item = self.graphicsView.findItemByUid(uid)
2973
                            if run_item is not None:
2974
                                run_item._owner = line_no
2975
                                line_run.items.append(run_item)
2976
                    line_run.owner = line_no
2977
                    line_no.runs.append(line_run)
2978

    
2979
                    for run_item in line_run.items:
2980
                        if issubclass(type(run_item), SymbolSvgItem):
2981
                            self.init_add_tree_item(line_no_tree_item, run_item)
2982

    
2983
                # docData.tracerLineNos.append(line_no)
2984

    
2985
                self.progress.setValue(self.progress.value() + 1)
2986
            QApplication.processEvents()
2987

    
2988
            for trimLineNo in root.iter('TRIM_LINE_NO'):
2989
                line_no = QEngineeringTrimLineNoTextItem()
2990
                line_no.uid = uuid.UUID(trimLineNo.find('UID').text)
2991

    
2992
                run = trimLineNo.find('RUN')
2993
                if run is not None:
2994
                    line_run = QEngineeringRunItem()
2995
                    for child in run:
2996
                        uidElement = child.find('UID')
2997
                        if uidElement is not None:
2998
                            uid = uidElement.text
2999
                            run_item = self.graphicsView.findItemByUid(uid)
3000
                            if run_item is not None:
3001
                                run_item.owner = line_no
3002
                                line_run.items.append(run_item)
3003
                    line_no.runs.append(line_run)
3004
                    line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
3005

    
3006
                    for run_item in line_run.items:
3007
                        if issubclass(type(run_item), SymbolSvgItem):
3008
                            self.init_add_tree_item(line_no_tree_item, run_item)
3009

    
3010
                    docData.tracerLineNos.append(line_no)
3011

    
3012
                self.progress.setValue(self.progress.value() + 1)
3013
            QApplication.processEvents()
3014

    
3015
            if root.find('VENDORS') is not None:
3016
                for vendor in root.find('VENDORS').iter('VENDOR'):
3017
                    item = QEngineeringVendorItem.fromXml(vendor)
3018
                    item.transfer.onRemoved.connect(self.itemRemoved)
3019
                    self.graphicsView.scene.addItem(item)
3020

    
3021
            # connect flow item to line
3022
            for line in lines:
3023
                line.update_arrow()
3024
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
3025
            #    for line in lines:
3026
            #        if flowMark.owner is line:
3027
            #            line._flowMark.append(flowMark)
3028
            #            flowMark.setParentItem(line)
3029
            # up to here
3030

    
3031
            """ update scene """
3032
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
3033
            for item in self.graphicsView.scene.items():
3034
                item.setVisible(True)
3035

    
3036
                # binding items
3037
                if hasattr(item, 'owner'):
3038
                    item.owner
3039
                if hasattr(item, 'connectors'):
3040
                    for connector in item.connectors:
3041
                        connector.connectedItem
3042

    
3043
        except Exception as ex:
3044
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3045
                                                          sys.exc_info()[-1].tb_lineno)
3046
            self.addMessage.emit(MessageType.Error, message)
3047
        finally:
3048
            pass
3049
            # self.graphicsView.scene.blockSignals(False)
3050

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

    
3059
    def addSvgItemToScene(self, svgItem):
3060
        svgItem.addSvgItemToScene(self.graphicsView.scene)
3061

    
3062
    '''
3063
        @brief      Remove added item on same place and Add GraphicsItem
3064
        @author     Jeongwoo
3065
        @date       2018.05.25
3066
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
3067
                    2018.06.05  Jeongwoo    Remove Size condition
3068
                    2018.06.18  Jeongwoo    Set Z-index
3069
    '''
3070

    
3071
    def addTextItemToScene(self, textItem):
3072
        textItem.addTextItemToScene(self.graphicsView.scene)
3073

    
3074
    '''
3075
        @brief      Remove added item on same place and Add GraphicsItem
3076
        @author     Jeongwoo
3077
        @date       2018.05.29
3078
        @history    2018.06.18  Jeongwoo    Set Z-index
3079
    '''
3080

    
3081
    def addLineItemToScene(self, lineItem):
3082
        self.graphicsView.scene.addItem(lineItem)
3083

    
3084
    '''
3085
        @brief      generate output xml file
3086
        @author     humkyung
3087
        @date       2018.04.23
3088
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
3089
    '''
3090

    
3091
    def generateOutput(self):
3092
        import XmlGenerator as xg
3093

    
3094
        if not self.graphicsView.hasImage():
3095
            self.showImageSelectionMessageBox()
3096
            return
3097

    
3098
        try:
3099
            appDocData = AppDocData.instance()
3100

    
3101
            ## collect items
3102
            appDocData.lines.clear()
3103
            appDocData.lines = [item for item in self.graphicsView.scene.items() if
3104
                                type(item) is QEngineeringLineItem and item.owner is None]
3105

    
3106
            appDocData.symbols.clear()
3107
            appDocData.symbols = [item for item in self.graphicsView.scene.items() if
3108
                                  issubclass(type(item), SymbolSvgItem) and item.owner is None]
3109

    
3110
            appDocData.equipments.clear()
3111
            for item in self.graphicsView.scene.items():
3112
                if type(item) is QEngineeringEquipmentItem:
3113
                    appDocData.equipments.append(item)
3114

    
3115
            appDocData.texts.clear()
3116
            appDocData.texts = [item for item in self.graphicsView.scene.items() if
3117
                                issubclass(type(item), QEngineeringTextItem) and type(
3118
                                    item) is not QEngineeringLineNoTextItem]
3119
            ## up to here
3120

    
3121
            appDocData.imgOutput = np.ones((appDocData.activeDrawing.height, appDocData.activeDrawing.width),
3122
                                           np.uint8) * 255
3123
            xg.writeOutputXml(appDocData.imgName, appDocData.activeDrawing.width,
3124
                              appDocData.activeDrawing.height)  # TODO: check
3125
            project = appDocData.getCurrentProject()
3126
            cv2.imwrite(os.path.join(project.getTempPath(), 'OUTPUT.png'), appDocData.imgOutput)
3127
        except Exception as ex:
3128
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3129
                                                          sys.exc_info()[-1].tb_lineno)
3130
            self.addMessage.emit(MessageType.Error, message)
3131

    
3132
    '''
3133
        @brief      resetting attribute at secne
3134
        @author     kyoyho
3135
        @date       2018.08.21
3136
    '''
3137
    """
3138
    def checkAttribute(self):
3139
        try:
3140

3141
            docData = AppDocData.instance()
3142
            if not self.graphicsView.hasImage():
3143
                return
3144

3145
            # symbol 경우
3146
            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]
3147
            for item in items:
3148
                attrs = item.attrs
3149
                
3150
                removeAttrList = []
3151
                for attr in attrs:
3152
                    if type(attr) is tuple:
3153
                        continue
3154

3155
                    if attr is None:
3156
                        removeAttrList.append(attr)
3157
                        continue
3158

3159
                    attrInfo = docData.getSymbolAttributeByUID(attr.UID)
3160
                    if attrInfo is None:
3161
                        removeAttrList.append(attr)
3162
                    # 해당 attribute가 맞는지 확인
3163
                    else:
3164
                        attrType = attrInfo.AttributeType
3165
                        _type = type(attr)
3166
                        if attrType == 'Symbol Item':
3167
                            if not issubclass(_type, SymbolSvgItem):
3168
                                removeAttrList.append(attr)
3169
                        elif attrType == 'Text Item':
3170
                            if _type is not QEngineeringTextItem:
3171
                                removeAttrList.append(attr)
3172
                        elif attrType == 'Int':
3173
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
3174
                                removeAttrList.append(attr)
3175
                        elif attrType == 'String':
3176
                            if _type is not UserInputAttribute:
3177
                                removeAttrList.append(attr)
3178

3179
                for attr in removeAttrList:
3180
                    del attrs[attr]
3181

3182
            # Line No Text Item의 경우
3183
            items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringLineNoTextItem)]
3184
            for item in items:
3185
                attrs = item.attrs
3186
                
3187
                removeAttrList = []
3188
                for attr in attrs:
3189
                    if type(attr) is UserInputAttribute:
3190
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
3191
                        if attrInfo is None:
3192
                            removeAttrList.append(attr)
3193

3194
                for attr in removeAttrList:
3195
                    del attrs[attr]
3196

3197
        except Exception as ex:
3198
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
3199
                self.addMessage.emit(MessageType.Error, message)
3200
    """
3201
    '''
3202
        @brief      Check Number
3203
        @author     kyouho
3204
        @date       2018.08.20
3205
    '''
3206

    
3207
    def isNumber(self, num):
3208
        p = re.compile('(^[0-9]+$)')
3209
        result = p.match(num)
3210

    
3211
        if result:
3212
            return True
3213
        else:
3214
            return False
3215

    
3216
    '''
3217
        @brief      find overlap Connector
3218
        @author     kyouho
3219
        @date       2018.08.28
3220
    '''
3221

    
3222
    def findOverlapConnector(self, connectorItem):
3223
        from shapely.geometry import Point
3224
        from EngineeringConnectorItem import QEngineeringConnectorItem
3225
        itemList = []
3226

    
3227
        x = connectorItem.center()[0]
3228
        y = connectorItem.center()[1]
3229

    
3230
        connectors = [item for item in self.graphicsView.scene.items() if
3231
                      type(item) is QEngineeringConnectorItem and item != connectorItem]
3232
        for connector in connectors:
3233
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
3234
                itemList.append(connector.parent)
3235

    
3236
        return itemList
3237

    
3238

    
3239
if __name__ == '__main__':
3240
    import locale
3241
    from PyQt5.QtCore import QTranslator
3242
    from License import QLicenseDialog
3243
    from ProjectDialog import Ui_Dialog
3244
    from App import App
3245

    
3246
    app = App(sys.argv)
3247
    try:
3248
        if True == QLicenseDialog.check_license_key():
3249
            dlg = Ui_Dialog()
3250
            selectedProject = dlg.showDialog()
3251
            if selectedProject is not None:
3252
                AppDocData.instance().setCurrentProject(selectedProject)
3253
                app._mainWnd = MainWindow.instance()
3254
                app._mainWnd.show()
3255
                sys.exit(app.exec_())
3256
    except Exception as ex:
3257
        print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3258
                                                  sys.exc_info()[-1].tb_lineno))
3259
    finally:
3260
        pass
클립보드 이미지 추가 (최대 크기: 500 MB)