프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / MainWindow.py @ 3b8a801a

이력 | 보기 | 이력해설 | 다운로드 (148 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
import asyncio
9

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

    
21
import cv2
22
import numpy as np
23

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

    
29
from PIL import Image
30

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

    
35
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Shapes')
36
from EngineeringAbstractItem import QEngineeringAbstractItem
37
from EngineeringPolylineItem import QEngineeringPolylineItem
38
from EngineeringLineItem import QEngineeringLineItem
39
from SymbolSvgItem import SymbolSvgItem
40
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
41
from EngineeringTextItem import QEngineeringTextItem
42
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
43
from EngineeringNoteItem import QEngineeringNoteItem
44
from QEngineeringSizeTextItem import QEngineeringSizeTextItem
45
from EngineeringUnknownItem import QEngineeringUnknownItem
46
from EngineeringEquipmentItem import QEngineeringEquipmentItem
47
from EngineeringInstrumentItem import QEngineeringInstrumentItem
48
from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
49
from EngineeringErrorItem import QEngineeringErrorItem
50
from EngineeringVendorItem import QEngineeringVendorItem
51
from EngineeringEndBreakItem import QEngineeringEndBreakItem
52
from EngineeringReducerItem import QEngineeringReducerItem
53
from EngineeringFlowMarkItem import QEngineeringFlowMarkItem
54
from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
55
from AppDocData import *
56
import SymbolTreeWidget, SymbolPropertyTableWidget
57
import SymbolEditorDialog
58
import ItemTreeWidget
59
import ItemPropertyTableWidget
60
from UserInputAttribute import UserInputAttribute
61
from TextItemFactory import TextItemFactory
62
from TrainingImageListDialog import QTrainingImageListDialog
63
from TrainingSymbolImageListDialog import QTrainingSymbolImageListDialog
64
from TextDataListDialog import QTextDataListDialog
65
from ImportTextFromCADDialog import QImportTextFromCADDialog
66
from SymbolThicknessDialog import QSymbolThicknessDialog
67
from DisplayColors import DisplayColors
68
from DisplayColors import DisplayOptions
69
import uuid
70

    
71

    
72
class QDisplayWidget(QWidget):
73
    def __init__(self):
74
        from PyQt5 import QtWidgets, uic
75

    
76
        QWidget.__init__(self)
77
        uic.loadUi(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'UI', 'DisplayWidget.ui'), self)
78

    
79

    
80
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstance):
81
    """ This is MainWindow class """
82
    addMessage = pyqtSignal(Enum, str)
83

    
84
    def __init__(self):
85
        """initialize"""
86
        from App import App
87
        from LineTypeConditions import LineTypeConditions
88

    
89
        super(self.__class__, self).__init__()
90
        self.setupUi(self)
91
        self.progress_bar = QProgressBar()
92
        self._label_mouse = QLabel(self.statusbar)
93
        self._label_mouse.setText(self.tr('mouse pos : ({},{})'.format(0, 0)))
94
        self.labelStatus = QLabel(self.statusbar)
95
        self.labelStatus.setText(self.tr('Unrecognition : '))
96
        self.labelSymbolStatus = QLabel(self.statusbar)
97
        self.labelSymbolStatus.setText(self.tr('Symbol : '))
98
        self.labelLineStatus = QLabel(self.statusbar)
99
        self.labelLineStatus.setText(self.tr('Line : '))
100
        self.labelTextStatus = QLabel(self.statusbar)
101
        self.labelTextStatus.setText(self.tr('Text : '))
102

    
103
        self.statusbar.addWidget(self._label_mouse)
104
        self.statusbar.addPermanentWidget(self.progress_bar, 1)
105
        self.statusbar.addPermanentWidget(self.labelSymbolStatus)
106
        self.statusbar.addPermanentWidget(self.labelLineStatus)
107
        self.statusbar.addPermanentWidget(self.labelTextStatus)
108
        self.statusbar.addPermanentWidget(self.labelStatus)
109

    
110
        #self.refresh_rate = 0
111

    
112
        app_doc_data = AppDocData.instance()
113
        app_doc_data.clear()
114
        project = app_doc_data.getCurrentProject()
115
        _translate = QCoreApplication.translate
116
        version = QCoreApplication.applicationVersion()
117
        # set title
118
        self.setWindowTitle(self.title)
119

    
120
        # save timer
121
        self.save_timer = None
122

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

    
127
        configs = app_doc_data.getConfigs('Line', 'Default Type')
128
        value = configs[0].value if 1 == len(configs) else ''
129
        if value:
130
            at = self.lineComboBox.findText(value)
131
            self.lineComboBox.setCurrentIndex(at)
132
        else:
133
            at = self.lineComboBox.findText('Secondary')
134
            self.lineComboBox.setCurrentIndex(at)
135

    
136
        self.toolBar.insertWidget(self.actionOCR, self.lineComboBox)
137
        self.toolBar.insertSeparator(self.actionOCR)
138

    
139
        self.packageComboBox = QComboBox(self.toolBar)
140
        self.packageComboBox.addItems(['Equipment Package', 'Vendor Package'])
141
        self.toolBar.insertWidget(self.actionValidate, self.packageComboBox)
142

    
143
        self._scene = QtImageViewerScene(self)
144

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

    
152
        self._display_widget = QDisplayWidget()
153
        self._display_widget.radioButtonByGroup.toggled.connect(self.display_colors)
154
        self._display_widget.radioButtonByGroup.toggled.connect(self.display_colors)
155
        self.EditToolbar.addWidget(self._display_widget)
156
        self._display_widget.radioButtonByGroup.setChecked(True) \
157
            if DisplayColors.instance().option == DisplayOptions.DisplayByLineNo else \
158
            self._display_widget.radioButtonByType.setChecked(True)
159

    
160
        self.verticalLayout.addWidget(self.graphicsView)
161

    
162
        # Add Custom TreeWidget
163
        self.symbolTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
164
        self.symbolTreeWidget.header().hide()
165
        self.verticalLayoutSymbolTree.addWidget(self.symbolTreeWidget)
166
        self.lineEditFilter.textChanged.connect(self.on_search_text_changed)
167

    
168
        from LibraryItem import LibraryItemWidget
169
        self.libraryWidget = LibraryItemWidget(symbol_tree_widget=self.symbolTreeWidget)
170
        self.verticalLayoutLibrary.addWidget(self.libraryWidget)
171
        # Add Custom Property TableWidget
172
        self.propertyTableWidget = SymbolPropertyTableWidget.QSymbolPropertyTableWidget()
173
        self.verticalLayoutSymbolProperty.addWidget(self.propertyTableWidget)
174
        self.symbolTreeWidget.singleClicked.connect(self.propertyTableWidget.getClickedSymbol)
175

    
176
        self.splitterSymbol.setSizes([500, 300])
177

    
178
        # Add Custom Result Tree Widget (Symbol Explorer)
179
        self.itemTreeWidget = ItemTreeWidget.QItemTreeWidget(self.graphicsView)
180
        self.itemTreeWidget.header().hide()
181
        self.symbolExplorerVerticalLayout.addWidget(self.itemTreeWidget)
182

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

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

    
211
        # connect signals and slots
212
        self.actionClose.triggered.connect(self.close)
213
        self.actionOpen.triggered.connect(self.open_image_drawing)
214
        self.actionExportAsSVG.triggered.connect(self.export_as_svg)
215
        self.actionExportAsXML.triggered.connect(self.export_as_xml)
216
        self.actionExportAsImage.triggered.connect(self.export_as_image)
217
        self.actionLine.triggered.connect(self.onPlaceLine)
218
        self.actionRecognition.triggered.connect(self.recognize)
219
        self.pushButtonRefreshDrawings.clicked.connect(self.load_drawing_list)
220
        self.pushButtonRefreshTree.clicked.connect(self.refresh_item_list)
221
        self.actionLineRecognition.triggered.connect(self.connect_attributes)
222
        self.actionArea.triggered.connect(self.areaConfiguration)
223
        self.actionConfiguration.triggered.connect(self.configuration)
224
        self.actionOCR.triggered.connect(self.onAreaOcr)
225
        self.actionGenerateOutput.triggered.connect(self.generateOutput)
226
        self.pushButtonCreateSymbol.clicked.connect(self.onCreateSymbolClicked)
227
        self.toolButtonClearLog.clicked.connect(self.on_clear_log)
228
        self.actionHMB_DATA.triggered.connect(self.onHMBData)
229
        self.actionItem_Data_List.triggered.connect(self.showItemDataList)
230
        self.actionText_Data_List.triggered.connect(self.showTextDataList)
231
        self.actionSpecialItemTypes.triggered.connect(self.on_show_special_item_types)  # show special item types dialog
232
        self.actionDataTransfer.triggered.connect(self.on_show_data_transfer)  # show data transfer dialog
233
        self.actionDataExport.triggered.connect(self.on_show_data_export)
234
        self.actionExportEqpDatasheet.triggered.connect(self.on_show_eqp_datasheet_export)  # show eqp datasheet export dialog
235
        self.actionOPCRelation.triggered.connect(self.on_show_opc_relation)  # show OPC Relation dialog
236
        self.actionCodeTable.triggered.connect(self.onShowCodeTable)
237
        self.actionCustom_Code_Table.triggered.connect(self.onShowCustomCodeTable)
238
        self.actionReplace_Code_Table.triggered.connect(self.onShowReplaceCodeTable)
239
        self.actionImage_Drawing.triggered.connect(self.onViewImageDrawing)
240
        self.actionDrawing_Only.triggered.connect(self.onViewDrawingOnly)
241
        self.actionValidate.triggered.connect(self.onValidation)
242
        self.actionViewText.triggered.connect(self.onViewText)
243
        self.actionViewSymbol.triggered.connect(self.onViewSymbol)
244
        self.actionViewLine.triggered.connect(self.onViewLine)
245
        self.actionViewUnknown.triggered.connect(self.onViewUnknown)
246
        self.actionViewInconsistency.triggered.connect(self.onViewInconsistency)
247
        self.actionViewVendor_Area.triggered.connect(self.onViewVendorArea)
248
        self.actionRotate.triggered.connect(self.onRotate)
249
        self.actionZoom.triggered.connect(self.onAreaZoom)
250
        self.actionVendor.triggered.connect(self.onVendor)
251
        self.actionFitWindow.triggered.connect(self.fitWindow)
252
        self.actionpdf_to_image.triggered.connect(self.onConvertPDFToImage)
253
        self.actionImport_Text_From_CAD.triggered.connect(self.on_import_text_from_cad)
254
        self.actionSymbol_Thickness_Reinforcement.triggered.connect(self.onSymbolThickness)
255
        self.actionHelp.triggered.connect(self.on_help)
256
        self.actionReadme.triggered.connect(self.on_readme)
257
        self.graphicsView.scene().selectionChanged.connect(self.onSelectionChanged)
258
        self.actionInitialize.triggered.connect(self.on_initialize_scene)
259
        self.actionSave.triggered.connect(self.actionSaveCliked)
260
        self.addMessage.connect(self.onAddMessage)
261
        self.actionFindReplaceText.triggered.connect(self.findReplaceTextClicked)
262
        self.actionSymbol_Replace_Insert.triggered.connect(self.replaceInsertSymbolClicked)
263
        self.actionConnectLineToSymbol.triggered.connect(self.on_connect_line_to_symbol)
264
        self.actionGlobal_Validation.triggered.connect(self.on_validation_global_clicked)
265
        self.actionEditRecognizeLine.triggered.connect(self.on_recognize_line)
266
        self.pushButtonDetectSymbol.clicked.connect(self.show_detect_symbol_dialog)
267
        self.actionUndo.triggered.connect(self._scene.undo_stack.undo)
268
        self.actionRedo.triggered.connect(self._scene.undo_stack.redo)
269

    
270
        configs = app_doc_data.getAppConfigs('app', 'mode')
271
        if configs and 1 == len(configs) and 'advanced' == configs[0].value:
272
            self.actionOCR_Training.triggered.connect(self.oCRTrainingClicked)
273
            self.actionSymbol_Training.triggered.connect(self.symbolTrainingClicked)
274
            self.actionMake_Label_Data.triggered.connect(self.on_make_label_data)
275
        else:
276
            # self.actionOCR_Training.setVisible(False)
277
            # self.actionSymbol_Training.setVisible(False)
278
            self.menu_2.setEnabled(False)  # Data
279
            self.menu_4.setEnabled(False)  # Tool
280
            self.actionConfiguration.setVisible(False)
281
            self.pushButtonCreateSymbol.setVisible(False)
282
            self.pushButtonDetectSymbol.setVisible(False)
283

    
284
        self.delimiter = '"'
285

    
286
        self.resizeDocks({self.dockWidget}, {self.dockWidgetObjectExplorer.sizeHint().width()}, Qt.Horizontal)
287

    
288
        self.treeWidgetDrawingList.setHeaderHidden(False)
289
        self.treeWidgetDrawingList.header().setStretchLastSection(False)
290
        self.treeWidgetDrawingList.setHeaderLabels([self.tr('Name'), self.tr('DateTime')])
291
        self.treeWidgetDrawingList.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
292
        self.treeWidgetDrawingList.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
293
        self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing)
294
        self.load_drawing_list()
295

    
296
        # load stylesheet file list
297
        stylesheet_name = QtWidgets.qApp.stylesheet_name
298
        files = [os.path.splitext(file)[0] for file in os.listdir(os.path.dirname(os.path.realpath(__file__))) if
299
                 os.path.splitext(file)[1] == '.qss']
300
        for file in files:
301
            action = self.menuTheme.addAction(file)
302
            action.setCheckable(True)
303
            action.setChecked(True) if stylesheet_name == file else action.setChecked(False)
304
            action.triggered.connect(partial(self.load_stylesheet, file))
305
        # up to here
306

    
307
        # load language files
308
        language_name = QtWidgets.qApp.language_name
309
        files = ['en_us']  # english is default language
310
        files.extend([os.path.splitext(file)[0] for file in
311
                      os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate')) if
312
                      os.path.splitext(file)[1] == '.qm'])
313
        for file in files:
314
            action = self.menuLanguage.addAction(file)
315
            action.setCheckable(True)
316
            action.setChecked(True) if language_name.lower() == file.lower() else action.setChecked(False)
317
            action.triggered.connect(partial(self.load_language, file))
318
        # up to here
319

    
320
        # inconsistency table
321
        self.tableWidgetInconsistency.setColumnCount(3)
322
        self.tableWidgetInconsistency.setHorizontalHeaderLabels(['Owner', 'Type', 'Message'])
323
        self.tableWidgetInconsistency.setEditTriggers(QAbstractItemView.NoEditTriggers)
324
        self.tableWidgetInconsistency.itemClicked.connect(self.inconsistencyItemClickEvent)
325
        self.tableWidgetInconsistency.keyPressEvent = self.inconsistencyTableKeyPressEvent
326
        self.tableWidgetInconsistency.setSortingEnabled(True)
327

    
328
        self.read_settings()
329

    
330
    @property
331
    def title(self) -> str:
332
        """return window title"""
333

    
334
        from App import App
335

    
336
        app_doc_data = AppDocData.instance()
337
        project = app_doc_data.getCurrentProject()
338
        version = QCoreApplication.applicationVersion()
339
        title = f"{App.NAME}({version}) - {project.name}:" \
340
                f"{app_doc_data.activeDrawing.name if app_doc_data.activeDrawing else ''}"
341
        #title = f"{App.NAME} : ID2 " \
342
        #        f"{app_doc_data.activeDrawing.name if app_doc_data.activeDrawing else ''}"
343

    
344
        return title
345

    
346
    @property
347
    def scene(self):
348
        """getter scene"""
349
        return self._scene
350

    
351
    def eventFilter(self, source, event):
352
        """display mouse position of graphics view"""
353
        try:
354
            if event.type() == QEvent.MouseMove:
355
                self.current_pos = self.graphicsView.mapToScene(event.pos())
356
                self._label_mouse.setText(
357
                    'mouse pos : ({},{})'.format(round(self.current_pos.x()), round(self.current_pos.y())))
358
        except Exception as ex:
359
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
360
                                                           sys.exc_info()[-1].tb_lineno)
361
            self.addMessage.emit(MessageType.Error, message)
362

    
363
        return QWidget.eventFilter(self, source, event)
364

    
365
    def closeEvent(self, event):
366
        """save geometry and state and ask user to save drawing which is modified"""
367

    
368
        self.settings.setValue('geometry', self.saveGeometry())
369
        self.settings.setValue('windowState', self.saveState())
370
        # TODO: need to modify
371

    
372
        """save current view region"""
373
        app_doc_data = AppDocData.instance()
374
        if app_doc_data.activeDrawing:
375
            rect = self.graphicsView.viewport().rect()
376
            app_doc_data.activeDrawing.view_rect = self.graphicsView.mapToScene(rect).boundingRect()
377
            app_doc_data.update_view_region(app_doc_data.activeDrawing)
378
        """up to here"""
379

    
380
        # self.save_drawing_if_necessary()
381
        AppDocData.instance().clear()
382
        event.accept()
383

    
384
    def inconsistencyTableKeyPressEvent(self, event):
385
        try:
386
            row = self.tableWidgetInconsistency.selectedIndexes()[0].row()
387
            col = self.tableWidgetInconsistency.selectedIndexes()[0].column()
388
            from HighlightCommand import HighlightCommand
389
            if event.key() == Qt.Key_Up:
390
                if row is not 0:
391
                    errorItem = self.tableWidgetInconsistency.item(row - 1, 1).tag
392
                    HighlightCommand(self.graphicsView).execute(errorItem)
393
            elif event.key() == Qt.Key_Down:
394
                if row is not self.tableWidgetInconsistency.rowCount() - 1:
395
                    errorItem = self.tableWidgetInconsistency.item(row + 1, 1).tag
396
                    HighlightCommand(self.graphicsView).execute(errorItem)
397
            elif event.key() == Qt.Key_Delete:
398
                item = self.tableWidgetInconsistency.item(row, 0).tag
399
                if item and item.scene(): item.scene().removeItem(item)
400
                self.tableWidgetInconsistency.removeRow(row)
401

    
402
                self.tabWidget_2.setTabText(self.tabWidget_2.indexOf(self.tabInconsistency),
403
                                            self.tr('Inconsistency') + f"({self.tableWidgetInconsistency.rowCount()})")
404
        except Exception as ex:
405
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
406
                                                           sys.exc_info()[-1].tb_lineno)
407
            self.addMessage.emit(MessageType.Error, message)
408
        # finally:
409
        #    return QTableView.keyPressEvent(self.tableWidgetInconsistency, event)
410

    
411
    def onValidation(self):
412
        """validation check"""
413
        from ValidationDialog import QValidationDialog
414
        from ValidateCommand import ValidateCommand
415

    
416
        if not self.graphicsView.hasImage():
417
            self.showImageSelectionMessageBox()
418
            return
419

    
420
        try:
421
            dlg = QValidationDialog(self)
422
            if QDialog.Accepted == dlg.exec_():
423
                # remove error items
424
                for item in self.graphicsView.scene().items():
425
                    if type(item) is QEngineeringErrorItem:
426
                        item.transfer.onRemoved.emit(item)
427
                # up to here
428

    
429
                self.progress_bar.setMaximum(len(self.graphicsView.scene().items()))
430
                self.progress_bar.setValue(0)
431

    
432
                cmd = ValidateCommand(self.graphicsView)
433
                cmd.show_progress.connect(self.progress_bar.setValue)
434
                errors = cmd.execute(self.graphicsView.scene().items())
435
                for error in errors:
436
                    error.transfer.onRemoved.connect(self.itemRemoved)
437
                    #self.graphicsView.scene().addItem(error)
438
                    error.addSvgItemToScene(self.graphicsView.scene())
439

    
440
                self.tableWidgetInconsistency.clearContents()
441
                self.tableWidgetInconsistency.setRowCount(len(errors))
442
                for index, error in enumerate(errors):
443
                    self.makeInconsistencyTableRow(index, error)
444

    
445
                self.tabWidget_2.setTabText(self.tabWidget_2.indexOf(self.tabInconsistency),
446
                                            self.tr('Inconsistency') + f"({len(errors)})")
447
                if errors:
448
                    self.tabWidget_2.tabBar().setTabTextColor(self.tabWidget_2.indexOf(self.tabInconsistency), Qt.red)
449
                else:
450
                    self.tabWidget_2.tabBar().setTabTextColor(self.tabWidget_2.indexOf(self.tabInconsistency), Qt.black)
451
        except Exception as ex:
452
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
453
                                                           sys.exc_info()[-1].tb_lineno)
454
            self.addMessage.emit(MessageType.Error, message)
455
        finally:
456
            self.progress_bar.setValue(self.progress_bar.maximum())
457

    
458
    def makeInconsistencyTableRow(self, row, errorItem):
459
        '''
460
            @brief  make row data for inconsistency widget
461
            @author euisung
462
            @date   2019.04.16
463
        '''
464

    
465
        item = QTableWidgetItem(str(errorItem.parent))
466
        item.tag = errorItem
467
        self.tableWidgetInconsistency.setItem(row, 0, item)
468

    
469
        item = QTableWidgetItem(str(type(errorItem.parent)))
470
        item.tag = errorItem
471
        self.tableWidgetInconsistency.setItem(row, 1, item)
472

    
473
        item = QTableWidgetItem(errorItem.msg)
474
        item.tag = errorItem
475
        self.tableWidgetInconsistency.setItem(row, 2, item)
476

    
477
    def inconsistencyItemClickEvent(self, item):
478
        """
479
        @brief  inconsistency table item clicked
480
        @author euisung
481
        @date   2019.04.02
482
        """
483
        from HighlightCommand import HighlightCommand
484

    
485
        HighlightCommand(self.graphicsView).execute(item.tag)
486

    
487
    def read_settings(self):
488
        """read geometry and state"""
489
        from App import App
490

    
491
        try:
492
            self.settings = QSettings(App.COMPANY, App.NAME)
493
            self.restoreGeometry(self.settings.value("geometry", ""))
494
            self.restoreState(self.settings.value("windowState", ""))
495
        except Exception as ex:
496
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
497
                                                           sys.exc_info()[-1].tb_lineno)
498
            print(message)
499

    
500
    def load_stylesheet(self, file):
501
        """load stylesheets"""
502

    
503
        QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
504

    
505
        app_doc_data = AppDocData.instance()
506
        configs = [Config('app', 'stylesheet', file)]
507
        app_doc_data.saveAppConfigs(configs)
508

    
509
        for action in self.menuTheme.actions():
510
            if action.text() == file: continue
511
            action.setChecked(False)
512

    
513
    def load_language(self, file):
514
        """load language file and then apply selected language"""
515
        try:
516
            qm_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate', '{0}.qm'.format(file))
517
            QtWidgets.qApp.load_language(qm_file)
518

    
519
            app_doc_data = AppDocData.instance()
520
            configs = [Config('app', 'language', file)]
521
            app_doc_data.saveAppConfigs(configs)
522

    
523
            for action in self.menuLanguage.actions():
524
                if action.text().lower() == file.lower(): continue
525
                action.setChecked(False)
526
        finally:
527
            self.retranslateUi(self)
528
            self.propertyTableWidget.retranslateUi()
529

    
530
    def refresh_item_list(self):
531
        """refresh item tree"""
532
        self.itemTreeWidget.InitLineNoItems()
533

    
534
        line_nos = AppDocData.instance().tracerLineNos
535
        for line_no in line_nos:
536
            item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
537
            connectedItems = line_no.getConnectedItems()
538
            for connectedItem in connectedItems:
539
                if issubclass(type(connectedItem), SymbolSvgItem):
540
                    self.itemTreeWidget.addTreeItem(item, connectedItem)
541

    
542
    def load_drawing_list(self):
543
        """load p&id drawing list"""
544
        from Drawing import Drawing
545

    
546
        try:
547
            app_doc_data = AppDocData.instance()
548
            drawings = app_doc_data.getDrawings()
549

    
550
            self.treeWidgetDrawingList.clear()
551
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList,
552
                                                              [self.tr('P&ID Drawings'), ''])
553
            self.treeWidgetDrawingList.root.setFlags(
554
                self.treeWidgetDrawingList.root.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
555
            self.treeWidgetDrawingList.root.setCheckState(0, Qt.Unchecked)
556
            files = app_doc_data.getDrawingFileList()
557

    
558
            # self.progress_bar.setMaximum(len(files))
559
            count = 0
560
            # self.progress_bar.setValue(count)
561
            for file in files:
562
                x = [drawing for drawing in drawings if drawing.name == file]
563
                if not x or not x[0].UID:
564
                    drawing = Drawing(None, file, None)
565
                    drawings.append(drawing)
566
                else:
567
                    drawing = x[0]
568

    
569
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [file, drawing.datetime])
570
                item.setIcon(0, QIcon(':newPrefix/image.png'))
571
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
572
                item.setCheckState(0, Qt.Unchecked)
573
                item.setData(Qt.UserRole, 0, drawing)
574

    
575
                count += 1
576
                # self.progress_bar.setValue(count)
577
                # QApplication.processEvents()
578

    
579
            self.treeWidgetDrawingList.root.setText(0, self.tr('P&ID Drawings') +
580
                                                    f"({self.treeWidgetDrawingList.root.childCount()})")
581
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
582
            self.treeWidgetDrawingList.root.sortChildren(0, Qt.AscendingOrder)
583
            self.treeWidgetDrawingList.resizeColumnToContents(0)
584

    
585
            app_doc_data.saveDrawings(drawings)
586
        except Exception as ex:
587
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
588
                                                           sys.exc_info()[-1].tb_lineno)
589
            self.addMessage.emit(MessageType.Error, message)
590
        finally:
591
            self.progress_bar.setValue(self.progress_bar.maximum())
592

    
593
    def open_selected_drawing(self, item, column):
594
        """open selected p&id drawing"""
595

    
596
        app_doc_data = AppDocData.instance()
597
        drawing = item.data(Qt.UserRole, 0)
598
        if drawing:
599
            # uncheck all drawing tree item
600
            drawing_top = self.treeWidgetDrawingList.topLevelItem(0)
601
            count = drawing_top.childCount()
602
            for idx in range(count):
603
                child = drawing_top.child(idx)
604
                child.setCheckState(column, Qt.Unchecked)
605
            # up to here
606

    
607
            drawing.image = None
608
            self.open_image_drawing(drawing)
609
            item.setCheckState(column, Qt.Checked)
610

    
611
    def show_detect_symbol_dialog(self):
612
        from DetectSymbolDialog import QDetectSymbolDialog
613

    
614
        dlg = QDetectSymbolDialog(self)
615
        dlg.exec_()
616

    
617
    '''
618
        @brief      OCR Editor
619
        @author     euisung
620
        @date       2018.10.05
621
        @history    2018.10.16 euisung      no more used, Integrated with oCRTrainingClicked
622
    '''
623

    
624
    def oCRTrainingEdidorClicked(self):
625
        from TrainingEditorDialog import QTrainingEditorDialog
626

    
627
        try:
628
            dialog = QTrainingEditorDialog(self)
629
            dialog.exec_()
630
        except Exception as ex:
631
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
632
                                                           sys.exc_info()[-1].tb_lineno)
633
            self.addMessage.emit(MessageType.Error, message)
634

    
635
        return
636

    
637
    '''
638
        @brief      OCR Training
639
        @author     euisung
640
        @date       2018.09.27
641
        @history    euisung 2018.10.16 TrainingListDialog -> TrainingImageListDialog
642
    '''
643

    
644
    def oCRTrainingClicked(self):
645
        try:
646
            dialog = QTrainingImageListDialog(self)
647
            dialog.exec_()
648
        except Exception as ex:
649
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
650
                                                           sys.exc_info()[-1].tb_lineno)
651
            self.addMessage.emit(MessageType.Error, message)
652

    
653
    def symbolTrainingClicked(self):
654
        try:
655
            dialog = QTrainingSymbolImageListDialog(self)
656
            dialog.show()
657
            dialog.exec_()
658
        except Exception as ex:
659
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
660
                                                           sys.exc_info()[-1].tb_lineno)
661
            self.addMessage.emit(MessageType.Error, message)
662

    
663
    def findReplaceTextClicked(self):
664
        """pop up find and replace dialog"""
665
        if not self.graphicsView.hasImage():
666
            self.showImageSelectionMessageBox()
667
            return
668

    
669
        from TextItemEditDialog import QTextItemEditDialog
670

    
671
        dlgTextItemEdit = QTextItemEditDialog(self)
672
        dlgTextItemEdit.show()
673
        dlgTextItemEdit.exec_()
674

    
675
    def on_validation_global_clicked(self):
676
        """ global validation dialog """
677
        from ValidationGlobalDialog import QValidationGlobalDialog
678

    
679
        dlg = QValidationGlobalDialog(self)
680
        dlg.show()
681
        dlg.exec_()
682

    
683
    def replaceInsertSymbolClicked(self):
684
        """pop up replace and insert dialog"""
685
        if not self.graphicsView.hasImage():
686
            self.showImageSelectionMessageBox()
687
            return
688

    
689
        from ReplaceSymbolDialog import QReplaceSymbolDialog
690

    
691
        dlg = QReplaceSymbolDialog(self)
692
        dlg.show()
693
        dlg.exec_()
694

    
695
    def on_connect_line_to_symbol(self):
696
        """connect line to symbol"""
697
        from LineDetector import LineDetector
698

    
699
        if not self.graphicsView.hasImage():
700
            self.showImageSelectionMessageBox()
701
            return
702

    
703
        app_doc_data = AppDocData.instance()
704
        configs = app_doc_data.getConfigs('Project', 'Operation')
705
        configs = app_doc_data.getConfigs('Line Detector', 'Length to connect line')
706
        toler = int(configs[0].value) if configs else 20
707
        detector = LineDetector(app_doc_data.imgSrc)
708

    
709
        lines = [item for item in self.graphicsView.scene().items() if type(item) is QEngineeringLineItem]
710
        symbols = [item for item in self.graphicsView.scene().items() if issubclass(type(item), SymbolSvgItem)]
711
        if lines:
712
            # connect line to symbol
713
            try:
714
                for line in lines:
715
                    matches = [_symbol for _symbol in symbols if _symbol.is_connectable(line, toler=toler)]
716
                    for _symbol in matches:
717
                        detector.connectLineToSymbol(line, _symbol, toler=toler)
718
            except Exception as ex:
719
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
720
                          f"{sys.exc_info()[-1].tb_lineno}"
721
                self.addMessage.emit(MessageType.Error, message)
722
            # up to here
723

    
724
            # connect line to line
725
            try:
726
                for line in lines:
727
                    matches = [it for it in lines if (it is not line) and (not line.isParallel(it))]
728

    
729
                    for match in matches:
730
                        detector.connectLineToLine(match, line, toler)
731
            except Exception as ex:
732
                message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
733
                          f"{sys.exc_info()[-1].tb_lineno}"
734
                self.addMessage.emit(MessageType.Error, message)
735
            # up to here
736

    
737
        QMessageBox.information(self, self.tr('Information'), self.tr('Connecting between symbols and lines is complete'))
738

    
739
    def on_recognize_line(self):
740
        """recognize lines in selected area"""
741
        from RecognizeLineCommand import RecognizeLineCommand
742

    
743
        if not self.graphicsView.hasImage():
744
            self.actionOCR.setChecked(False)
745
            self.showImageSelectionMessageBox()
746
            return
747

    
748
        cmd = RecognizeLineCommand(self.graphicsView)
749
        cmd.onSuccess.connect(self.on_success_to_recognize_line)
750
        cmd.onRejected.connect(self.onCommandRejected)
751
        self.graphicsView.command = cmd
752

    
753
    '''
754
            @brief      show text recognition dialog
755
            @author     humkyung
756
            @date       2018.08.08
757
        '''
758

    
759
    def on_success_to_recognize_line(self, x, y, width, height):
760
        import io
761
        from LineDetector import LineDetector
762
        from EngineeringGraphicsLineItem import QEngineeringGraphicsLineItem
763

    
764
        try:
765
            image = self.graphicsView.image().copy(x, y, width, height)
766
            buffer = QBuffer()
767
            buffer.open(QBuffer.ReadWrite)
768
            image.save(buffer, "PNG")
769
            pyImage = Image.open(io.BytesIO(buffer.data()))
770
            img = np.array(pyImage)
771
            img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
772

    
773
            detector = LineDetector(img)
774
            lines = detector.detect_line_without_symbol()
775
            for line in lines:
776
                vertices = [[line[0][0] + x, line[0][1] + y], [line[1][0] + x, line[1][1] + y]]
777
                line_item = QEngineeringGraphicsLineItem(vertices)
778
                self.graphicsView.scene().addItem(line_item)
779

    
780
        except Exception as ex:
781
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
782
                                                           sys.exc_info()[-1].tb_lineno)
783
            self.addMessage.emit(MessageType.Error, message)
784

    
785
    def display_number_of_items(self):
786
        """display count of symbol, line, text"""
787

    
788
        items = [item for item in self.graphicsView.scene().items() if type(item) is QEngineeringUnknownItem]
789
        if len(items) > 0:
790
            self.labelStatus.setText(
791
                "<font color='red'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
792
        else:
793
            self.labelStatus.setText(
794
                "<font color='black'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
795

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

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

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

    
806
        self.itemTreeWidget.sceneChanged(self.graphicsView.scene().items())
807

    
808
    def dbUpdate(self):
809
        """ no more used """
810
        """db update when save or recognition"""
811

    
812
        try:
813
            appDocData = AppDocData.instance()
814
            items = appDocData.allItems
815

    
816
            '''
817
            titleBlockProps = appDocData.getTitleBlockProperties()
818
            titleBlockItems = []
819
            for item in items:
820
                # if type(item) is QEngineeringLineNoTextItem:
821
                #    item.saveLineData()
822
                if type(item) is QEngineeringTextItem:
823
                    for titleBlockProp in titleBlockProps:
824
                        if item.area == titleBlockProp[0]:
825
                            titleBlockItems.append(item)
826
            '''
827

    
828
            # unknown item is not saved now for performance
829
            db_items = [item for item in items if issubclass(type(item), QEngineeringAbstractItem) and
830
                        type(item) is not QGraphicsBoundingBoxItem and
831
                        type(item) is not QEngineeringErrorItem and
832
                        type(item) is not QEngineeringLineNoTextItem and
833
                        type(item) is not QEngineeringUnknownItem]
834
            db_items.extend([item for item in items if type(item) is QEngineeringLineNoTextItem])
835
            db_items.extend([line for line in appDocData.tracerLineNos if type(line) is QEngineeringTrimLineNoTextItem])
836
            # db_items.extend(titleBlockItems)
837
            configs = appDocData.getConfigs('Data Save', 'Unknown Xml Only')
838
            if configs and int(configs[0].value) is -1:
839
                db_items.extend([item for item in items if type(item) is QEngineeringUnknownItem])
840

    
841
            '''
842
            dbItems = [item for item in items if
843
                       type(item) is QEngineeringInstrumentItem or type(item) is QEngineeringEquipmentItem or type(
844
                           item) is QEngineeringReducerItem or \
845
                       type(item) is QEngineeringNoteItem or type(item) is SymbolSvgItem or type(
846
                           item) is QEngineeringLineNoTextItem or type(
847
                           item) is QEngineeringVendorItem] + titleBlockItems
848
            '''
849
            appDocData.saveToDatabase(db_items)
850
        except Exception as ex:
851
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
852
                                                           sys.exc_info()[-1].tb_lineno)
853
            self.addMessage.emit(MessageType.Error, message)
854

    
855
    def save_drawing_if_necessary(self):
856
        """ask to user to save drawing or not when drawing is modified"""
857

    
858
        app_doc_data = AppDocData.instance()
859
        if app_doc_data.activeDrawing and app_doc_data.activeDrawing.modified:
860
            #if QMessageBox.Yes == QMessageBox.question(self, self.tr("Question"),
861
            #                                           self.tr("Do you want to save drawing?"),
862
            #                                           QMessageBox.Yes | QMessageBox.No):
863
            #    self.actionSaveCliked()
864
            #    return True
865
            if QMessageBox.Ignore == QMessageBox.question(self, self.tr('Continue?'),
866
                                                       self.tr('Changes may not have been saved.'),
867
                                                       QMessageBox.Ignore | QMessageBox.Cancel):
868
                return False
869
            return True
870

    
871
    def actionSaveCliked(self):
872
        """save current drawing"""
873
        from EngineeringAbstractItem import QEngineeringAbstractItem
874
        from SaveWorkCommand import SaveWorkCommand
875

    
876
        try:
877
            if not self.actionSave.isEnabled():
878
                return
879
            self.actionSave.setEnabled(False)
880

    
881
            # save alarm
882
            self.save_alarm_enable(False)
883

    
884
            app_doc_data = AppDocData.instance()
885
            if app_doc_data.imgName is None:
886
                self.showImageSelectionMessageBox()
887
                return
888

    
889
            app_doc_data.clearItemList(False)
890

    
891
            items = self.graphicsView.scene().items()
892

    
893
            self._save_work_cmd = SaveWorkCommand(self.graphicsView.scene())
894
            self._save_work_cmd.show_progress.connect(self.progress_bar.setValue)
895
            self._save_work_cmd.display_message.connect(self.onAddMessage)
896
            self._save_work_cmd.finished.connect(self.save_finished)
897

    
898
            self._save_work_cmd.start()
899
        except Exception as ex:
900
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
901
                      f"{sys.exc_info()[-1].tb_lineno}"
902
            self.addMessage.emit(MessageType.Error, message)
903

    
904
    def save_finished(self):
905
        """reload drawing list"""
906

    
907
        self._save_work_cmd.show_progress.emit(100)
908
        QMessageBox.about(self.graphicsView, self.tr('Information'), self._save_work_cmd.resultStr)
909
        self.load_drawing_list()
910

    
911
        app_doc_data = AppDocData.instance()
912
        app_doc_data.activeDrawing.modified = False
913
        title = self.windowTitle()
914
        self.setWindowTitle(title[:-1] if title[-1] == '*' else title)
915

    
916
        self.actionSave.setEnabled(True)
917
        
918
        # save alarm
919
        self.save_alarm_enable(True)
920

    
921
    '''
922
        @brief      refresh resultPropertyTableWidget
923
        @author     kyouho
924
        @date       2018.07.19
925
    '''
926

    
927
    def refreshResultPropertyTableWidget(self):
928
        items = self.graphicsView.scene().selectedItems()
929
        if len(items) == 1:
930
            self.resultPropertyTableWidget.show_item_property(items[0])
931

    
932
    '''
933
        @brief  add message listwidget
934
        @author humkyung
935
        @date   2018.07.31
936
    '''
937

    
938
    def onAddMessage(self, messageType, message):
939
        from AppDocData import MessageType
940

    
941
        try:
942
            current = QDateTime.currentDateTime()
943

    
944
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
945
            item.setFlags(item.flags() | Qt.ItemIsEditable)
946
            if messageType == MessageType.Error:
947
                item.setBackground(Qt.red)
948
            elif messageType == 'check':
949
                item.setBackground(Qt.yellow)
950

    
951
            self.listWidgetLog.insertItem(0, item)
952
        except Exception as ex:
953
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
954
                                                       sys.exc_info()[-1].tb_lineno))
955

    
956
    def on_clear_log(self):
957
        """clear log"""
958
        self.listWidgetLog.clear()
959

    
960
    '''
961
        @brief      rotate selected symbol
962
        @author     humkyung
963
        @date       2018.08.15
964
    '''
965

    
966
    def onRotate(self, action):
967
        selected = [item for item in self.graphicsView.scene().selectedItems() if issubclass(type(item), SymbolSvgItem)]
968
        if len(selected) == 1:
969
            from RotateCommand import RotateCommand
970
            self.graphicsView.scene()._undo_stack.push(RotateCommand(self.graphicsView.scene(), selected))
971

    
972
    '''
973
        @brief      Area Zoom
974
        @author     Jeongwoo
975
        @date       2018.06.27
976
        @history    connect command's rejected signal
977
    '''
978

    
979
    def onAreaZoom(self, action):
980
        if self.actionZoom.isChecked():
981
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
982
            cmd.onRejected.connect(self.onCommandRejected)
983
            self.graphicsView.command = cmd
984

    
985
    def onVendor(self, action):
986
        """make vendor package area"""
987

    
988
        if not self.graphicsView.hasImage():
989
            self.actionVendor.setChecked(False)
990
            self.showImageSelectionMessageBox()
991
            return
992

    
993
        self.actionVendor.setChecked(True)
994
        if not hasattr(self.actionVendor, 'tag'):
995
            self.actionVendor.tag = PlacePolygonCommand.PlacePolygonCommand(self.graphicsView)
996
            self.actionVendor.tag.onSuccess.connect(self.onVendorCreated)
997
            self.actionVendor.tag.onRejected.connect(self.onCommandRejected)
998

    
999
        self.graphicsView.command = self.actionVendor.tag
1000

    
1001
    def onVendorCreated(self):
1002
        """add created vendor polygon area to scene"""
1003

    
1004
        try:
1005
            count = len(self.actionVendor.tag._polyline._vertices)
1006
            if count > 2:
1007
                points = []
1008
                for point in self.actionVendor.tag._polyline._vertices:
1009
                    points.append(QPoint(round(point[0]), round(point[1])))
1010
                polygon = QPolygonF(points)
1011
                item = QEngineeringVendorItem(polygon, pack_type=self.packageComboBox.currentText())
1012
                item.area = 'Drawing'
1013
                item.transfer.onRemoved.connect(self.itemRemoved)
1014
                self.graphicsView.scene().addItem(item)
1015
        finally:
1016
            self.graphicsView.scene().removeItem(self.actionVendor.tag._polyline)
1017
            self.actionVendor.tag.reset()
1018

    
1019
    def fitWindow(self, view_rect: QRectF = QRectF()):
1020
        """Fit Window"""
1021
        self.graphicsView.useDefaultCommand()
1022
        self.graphicsView.zoomImageInit()
1023

    
1024
        if view_rect:
1025
            self.graphicsView.zoom_rect(view_rect)
1026

    
1027
    def scene_changed(self):
1028
        """update modified flag"""
1029

    
1030
        self.display_number_of_items()
1031

    
1032
        app_doc_data = AppDocData.instance()
1033
        app_doc_data.activeDrawing.modified = True
1034
        title = self.windowTitle()
1035
        self.setWindowTitle(title if title[-1] == '*' else title + '*')
1036

    
1037
    def onConvertPDFToImage(self):
1038
        """convert to selected pdf to image"""
1039
        import os
1040

    
1041
        try:
1042
            file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'bin64', 'PDF_TO_IMAGE.exe')
1043
            os.startfile(file_path)
1044
        except Exception as ex:
1045
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1046
                                                           sys.exc_info()[-1].tb_lineno)
1047
            self.addMessage.emit(MessageType.Error, message)
1048

    
1049
    def on_import_text_from_cad(self):
1050
        """ import text from cad """
1051
        try:
1052
            self.onCommandRejected()
1053
            dialog = QImportTextFromCADDialog(self)
1054
            dialog.show()
1055
            dialog.exec_()
1056
        except Exception as ex:
1057
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
1058
                      f"{sys.exc_info()[-1].tb_lineno}"
1059
            self.addMessage.emit(MessageType.Error, message)
1060

    
1061
    def onSymbolThickness(self):
1062
        """ symbol thickness reinforcement by using configuration filter drawing dilate size """
1063
        try:
1064
            self.onCommandRejected()
1065
            dialog = QSymbolThicknessDialog(self)
1066
            dialog.exec_()
1067
        except Exception as ex:
1068
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1069
                                                           sys.exc_info()[-1].tb_lineno)
1070
            self.addMessage.emit(MessageType.Error, message)
1071

    
1072
    def on_help(self):
1073
        """ open help file """
1074
        import os
1075

    
1076
        try:
1077
            help_file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ID2 User Manual.pdf')
1078
            if os.path.exists(help_file_path):
1079
                os.startfile(f"\"{help_file_path}\"")
1080
            else:
1081
                QMessageBox.warning(self, self.tr('Warning'), self.tr('There is no help file'))
1082
        except Exception as ex:
1083
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
1084
                      f"{sys.exc_info()[-1].tb_lineno}"
1085
            self.addMessage.emit(MessageType.Error, message)
1086

    
1087
    def on_readme(self):
1088
        """open readme.html"""
1089

    
1090
        file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'readme.html')
1091
        if os.path.exists(file_path):
1092
            os.startfile(f"\"{file_path}\"")
1093
        else:
1094
            QMessageBox.warning(self, self.tr('Warning'), self.tr('There is no readme file'))
1095

    
1096
    def onSelectionChanged(self):
1097
        """selection changed"""
1098
        items = [item for item in self.graphicsView.scene().selectedItems() if issubclass(type(item), SymbolSvgItem) or
1099
                 type(item) is QEngineeringLineItem or issubclass(type(item), QEngineeringTextItem) or
1100
                 type(item) is QEngineeringUnknownItem or type(item) is QEngineeringVendorItem]
1101
        if items:
1102
            lineNos = [item for item in items if type(item) is QEngineeringLineNoTextItem]
1103
            item = items[-1] if not lineNos else lineNos[0]
1104
            self.itemTreeWidget.findItem(item)
1105
            self.resultPropertyTableWidget.show_item_property(item)
1106
            if type(item) is QEngineeringErrorItem:
1107
                for index in range(self.tableWidgetInconsistency.rowCount()):
1108
                    if self.tableWidgetInconsistency.item(index, 1).tag is item:
1109
                        self.tableWidgetInconsistency.selectRow(index)
1110
                        break
1111
            if issubclass(type(item), SymbolSvgItem):
1112
                pass
1113
                #self.symbolTreeWidget.select_symbol(item)
1114
        else:
1115
            self.resultPropertyTableWidget.show_item_property(None)
1116

    
1117
    '''
1118
        @brief      Initialize scene and itemTreeWidget
1119
        @author     Jeongwoo
1120
        @date       2018.06.14
1121
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
1122
    '''
1123

    
1124
    def on_initialize_scene(self, action):
1125
        if not self.graphicsView.hasImage():
1126
            self.showImageSelectionMessageBox()
1127

    
1128
            return
1129

    
1130
        try:
1131
            msg = QMessageBox()
1132
            msg.setIcon(QMessageBox.Critical)
1133
            msg.setText(self.tr('Do you want to remove all items?\nThis work cannot be recovered.'))
1134
            msg.setWindowTitle(self.tr("Initialize"))
1135
            msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
1136
            if QMessageBox.Ok == msg.exec_():
1137
                app_doc_data = AppDocData.instance()
1138
                app_doc_data.clearItemList(True)
1139

    
1140
                scene = self.graphicsView.scene()
1141
                pixmap = self.graphicsView.getPixmapHandle()
1142
                scene.removeItem(pixmap)    # disconnect pixmap from scene
1143
                scene.clear()               # remove all items from scene and then delete them
1144
                scene.addItem(pixmap)       # add pixmap
1145

    
1146
                if self.path is not None:
1147
                    baseName = os.path.basename(self.path)
1148
                    self.itemTreeWidget.setCurrentPID(baseName)
1149

    
1150
        except Exception as ex:
1151
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1152
                                                           sys.exc_info()[-1].tb_lineno)
1153
            self.addMessage.emit(MessageType.Error, message)
1154

    
1155
    '''
1156
        @brief      Manage Checkable Action statement
1157
        @author     Jeongwoo
1158
        @date       2018.05.10
1159
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
1160
    '''
1161

    
1162
    def actionGroupTriggered(self, action):
1163
        if hasattr(self.actionLine, 'tag'):
1164
            self.actionLine.tag.onRejected.emit(None)
1165

    
1166
        if hasattr(self.actionVendor, 'tag'):
1167
            self.actionVendor.tag.onRejected.emit(None)
1168

    
1169
        if self.graphicsView.command is not None:
1170
            self.graphicsView.useDefaultCommand()
1171

    
1172
        for _action in self.actionGroup.actions():
1173
            _action.setChecked(False)
1174

    
1175
        action.setChecked(True)
1176

    
1177
    '''
1178
        @brief      Create Equipment
1179
        @author     Jeongwoo
1180
        @date       18.05.03
1181
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
1182
    '''
1183

    
1184
    def createEquipment(self):
1185
        if not self.graphicsView.hasImage():
1186
            self.actionEquipment.setChecked(False)
1187
            self.showImageSelectionMessageBox()
1188
            return
1189
        if self.actionEquipment.isChecked():
1190
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget,
1191
                                                                                self.symbolTreeWidget)
1192
        else:
1193
            self.graphicsView.useDefaultCommand()
1194

    
1195
    '''
1196
        @brief      Create Nozzle
1197
        @author     Jeongwoo
1198
        @date       2018.05.03
1199
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
1200
    '''
1201

    
1202
    def createNozzle(self):
1203
        if not self.graphicsView.hasImage():
1204
            self.actionNozzle.setChecked(False)
1205
            self.showImageSelectionMessageBox()
1206
            return
1207
        if self.actionNozzle.isChecked():
1208
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget,
1209
                                                                                self.symbolTreeWidget)
1210
        else:
1211
            self.graphicsView.useDefaultCommand()
1212

    
1213
    '''
1214
        @brief      Area OCR
1215
        @author     Jeongwoo
1216
        @date       18.04.18
1217
        @history    2018.05.02  Jeongwoo    Change graphicsView.command by actionOCR checked state
1218
                                            Show MessageBox when imageviewer doesn't have image
1219
    '''
1220

    
1221
    def onAreaOcr(self):
1222
        if not self.graphicsView.hasImage():
1223
            self.actionOCR.setChecked(False)
1224
            self.showImageSelectionMessageBox()
1225
            return
1226

    
1227
        if self.actionOCR.isChecked():
1228
            cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView)
1229
            cmd.onSuccess.connect(self.onRecognizeText)
1230
            cmd.onRejected.connect(self.onCommandRejected)
1231
            self.graphicsView.command = cmd
1232
        else:
1233
            self.graphicsView.useDefaultCommand()
1234

    
1235
    '''
1236
        @brief      show text recognition dialog
1237
        @author     humkyung
1238
        @date       2018.08.08
1239
    '''
1240

    
1241
    def onRecognizeText(self, x, y, width, height):
1242
        from OcrResultDialog import QOcrResultDialog
1243
        from Area import Area
1244

    
1245
        try:
1246
            app_doc_data = AppDocData.instance()
1247

    
1248
            modifiers = QApplication.keyboardModifiers()
1249
            image = self.graphicsView.image().copy(x, y, width, height)
1250
            dialog = QOcrResultDialog(self, image, QRectF(x, y, width, height),
1251
                                      format=QOcrResultDialog.Format.Table if modifiers == Qt.AltModifier else QOcrResultDialog.Format.Normal)
1252
            if modifiers == Qt.ControlModifier:
1253
                return
1254
            (res, textInfoList) = dialog.showDialog()
1255
            if QDialog.Accepted == res and textInfoList:
1256
                for textInfo in textInfoList:
1257
                    item = QEngineeringTextItem.create_text_with(self.graphicsView.scene(), textInfo)
1258
                    if item:
1259
                        item.setDefaultTextColor(Qt.blue)
1260
                        item.transfer.onRemoved.connect(self.itemRemoved)
1261

    
1262
                        area_list = app_doc_data.getAreaList()
1263
                        title_area_list = app_doc_data.getTitleBlockProperties()
1264
                        title_list = []
1265
                        if title_area_list:
1266
                            for title_area in title_area_list:
1267
                                area = Area(title_area[0])
1268
                                area.parse(title_area[2])
1269
                                title_list.append(area)
1270
                        for area in area_list + title_list:
1271
                            pt = [item.sceneBoundingRect().center().x(), item.sceneBoundingRect().center().y()]
1272
                            if area.contains(pt):
1273
                                item.area = area.name
1274
                                break
1275
                    else:
1276
                        self.addMessage.emit(MessageType.Normal, self.tr('Fail to create text.'))
1277
            elif QDialog.Accepted == res and not textInfoList:
1278
                QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("Fail to recognize text"))
1279
        except Exception as ex:
1280
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1281
                                                           sys.exc_info()[-1].tb_lineno)
1282
            self.addMessage.emit(MessageType.Error, message)
1283

    
1284
    '''
1285
        @brief  area configuration
1286
    '''
1287

    
1288
    def areaConfiguration(self):
1289
        from ConfigurationAreaDialog import QConfigurationAreaDialog
1290
        if not self.graphicsView.hasImage():
1291
            self.showImageSelectionMessageBox()
1292
            return
1293
        self.onCommandRejected()
1294
        dlgConfigurationArea = QConfigurationAreaDialog(self)
1295
        dlgConfigurationArea.show()
1296
        dlgConfigurationArea.exec_()
1297

    
1298
    '''
1299
        @brief  configuration
1300
    '''
1301

    
1302
    def configuration(self):
1303
        from ConfigurationDialog import QConfigurationDialog
1304

    
1305
        dlgConfiguration = QConfigurationDialog(self)
1306
        if QDialog.Accepted == dlgConfiguration.exec_():
1307
            QEngineeringLineItem.LINE_TYPE_COLORS.clear()
1308
            QEngineeringInstrumentItem.INST_COLOR = None
1309

    
1310
    '''
1311
        @brief  show special item types dialog 
1312
        @author humkyung
1313
        @date   2019.08.10
1314
    '''
1315

    
1316
    def on_show_special_item_types(self):
1317
        from SpecialItemTypesDialog import QSpecialItemTypesDialog
1318

    
1319
        dlg = QSpecialItemTypesDialog(self)
1320
        dlg.exec_()
1321

    
1322
    def on_show_data_transfer(self):
1323
        """ show data transfer dialog """
1324
        from DataTransferDialog import QDataTransferDialog
1325

    
1326
        dlg = QDataTransferDialog(self)
1327
        dlg.exec_()
1328

    
1329
    def on_show_data_export(self):
1330
        """ show data export dialog """
1331
        from DataExportDialog import QDataExportDialog
1332

    
1333
        dlg = QDataExportDialog(self)
1334
        dlg.exec_()
1335

    
1336
    def on_show_eqp_datasheet_export(self):
1337
        """ show eqp datasheet export dialog """
1338
        from EqpDatasheetExportDialog import QEqpDatasheetExportDialog
1339

    
1340
        dlg = QEqpDatasheetExportDialog(self)
1341
        dlg.exec_()
1342

    
1343
    def on_show_opc_relation(self):
1344
        """ show opc relation dialog """
1345
        from OPCRelationDialog import QOPCRelationDialog
1346

    
1347
        dlg = QOPCRelationDialog(self)
1348
        dlg.exec_()
1349

    
1350
    '''
1351
        @brief  show nominal diameter dialog 
1352
        @author humkyung
1353
        @date   2018.06.28
1354
    '''
1355

    
1356
    def onShowCodeTable(self):
1357
        from CodeTableDialog import QCodeTableDialog
1358

    
1359
        dlg = QCodeTableDialog(self)
1360
        dlg.show()
1361
        dlg.exec_()
1362
        if dlg.code_area:
1363
            if dlg.code_area.scene():
1364
                self.graphicsView.scene().removeItem(dlg.code_area)
1365
        if dlg.desc_area:
1366
            if dlg.desc_area.scene():
1367
                self.graphicsView.scene().removeItem(dlg.desc_area)
1368
        self.graphicsView.useDefaultCommand()
1369

    
1370
    def onShowCustomCodeTable(self):
1371
        from CustomCodeTablesDialog import CustomCodeTablesDialog
1372

    
1373
        dlg = CustomCodeTablesDialog(self)
1374
        dlg.show()
1375
        dlg.exec_()
1376
        self.graphicsView.useDefaultCommand()
1377

    
1378
    def onShowReplaceCodeTable(self):
1379
        from CustomCodeTablesDialog import CustomCodeTablesDialog
1380

    
1381
        dlg = CustomCodeTablesDialog(self, replace=True)
1382
        dlg.show()
1383
        dlg.exec_()
1384
        self.graphicsView.useDefaultCommand()
1385

    
1386
    '''
1387
        @brief  show HMB data
1388
        @author humkyung
1389
        @date   2018.07.11
1390
    '''
1391

    
1392
    def onHMBData(self):
1393
        from HMBDialog import QHMBDialog
1394

    
1395
        dlg = QHMBDialog(self)
1396
        dlg.show()
1397
        dlg.exec_()
1398

    
1399
    '''
1400
        @brief  show line data list 
1401
        @author humkyung
1402
        @date   2018.05.03
1403
    '''
1404

    
1405
    def showItemDataList(self):
1406
        from ItemDataExportDialog import QItemDataExportDialog
1407

    
1408
        dlg = QItemDataExportDialog(self)
1409
        dlg.exec_()
1410

    
1411
    def showTextDataList(self):
1412
        '''
1413
            @brief      show all text item in scene
1414
            @author     euisung
1415
            @date       2019.04.18
1416
        '''
1417
        try:
1418
            if not self.graphicsView.hasImage():
1419
                self.showImageSelectionMessageBox()
1420
                return
1421

    
1422
            self.onCommandRejected()
1423
            dialog = QTextDataListDialog(self)
1424
            dialog.show()
1425
        except Exception as ex:
1426
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1427
                                                           sys.exc_info()[-1].tb_lineno)
1428
            self.addMessage.emit(MessageType.Error, message)
1429

    
1430
    '''
1431
        @brief  Show Image Selection Guide MessageBox
1432
        @author Jeongwoo
1433
        @date   2018.05.02
1434
    '''
1435

    
1436
    def showImageSelectionMessageBox(self):
1437
        QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("First select image drawing"))
1438

    
1439
    def on_search_text_changed(self):
1440
        """filter symbol tree view"""
1441
        regexp = QRegExp(self.lineEditFilter.text(), Qt.CaseInsensitive, QRegExp.FixedString)
1442

    
1443
        proxy_model = self.symbolTreeWidget.model()
1444
        proxy_model.text = self.lineEditFilter.text().lower()
1445
        proxy_model.setFilterRegExp(regexp)
1446

    
1447
        self.symbolTreeWidget.expandAll()
1448

    
1449
    '''
1450
        @brief  change selected lines' type by selected line type
1451
        @author humkyung
1452
        @date   2018.06.27
1453
    '''
1454

    
1455
    def onLineTypeChanged(self, param):
1456
        lineType = self.lineComboBox.itemText(param)
1457
        selected = [item for item in self.graphicsView.scene().selectedItems() if type(item) is QEngineeringLineItem]
1458
        if selected:
1459
            for item in selected:
1460
                item.lineType = lineType
1461

    
1462
    def display_colors(self, value):
1463
        """ display colors """
1464
        from DisplayColors import DisplayColors
1465
        from DisplayColors import DisplayOptions
1466

    
1467
        DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value is True else DisplayOptions.DisplayByLineType
1468
        if hasattr(self, 'graphicsView'):
1469
            self.graphicsView.scene().update(self.graphicsView.sceneRect())
1470
            DisplayColors.instance().save_data()
1471

    
1472
    def open_image_drawing(self, drawing, force=False):
1473
        """open and display image drawing file"""
1474
        from Drawing import Drawing
1475
        from App import App
1476
        from LoadCommand import LoadCommand
1477
        import concurrent.futures as futures
1478

    
1479
        # Yield successive n-sized
1480
        # chunks from l.
1481
        def divide_chunks(l, n):
1482
            # looping till length l
1483
            for i in range(0, len(l), n):
1484
                yield l[i:i + n]
1485

    
1486
        def update_items(items):
1487
            for item in items:
1488
                # binding items
1489
                item.owner
1490
                for connector in item.connectors:
1491
                    connector.connectedItem
1492

    
1493
            return items
1494

    
1495
        try:
1496
            app_doc_data = AppDocData.instance()
1497

    
1498
            if not self.actionSave.isEnabled():
1499
                return
1500

    
1501
            if not force and self.save_drawing_if_necessary():
1502
                return
1503

    
1504
            occupied = app_doc_data.set_occupying_drawing(drawing.UID)
1505
            if occupied:
1506
                QMessageBox.about(self.graphicsView, self.tr("Notice"),
1507
                                  self.tr(f"The drawing is locked for editing by another user({occupied})"))
1508
                return
1509

    
1510
            # save alarm
1511
            self.save_alarm_enable(False)
1512

    
1513
            if hasattr(self, '_save_work_cmd'):
1514
                self._save_work_cmd.wait()
1515

    
1516
            project = app_doc_data.getCurrentProject()
1517

    
1518
            self.path = self.graphicsView.loadImageFromFile(drawing)
1519
            if os.path.isfile(self.path):
1520
                self.onCommandRejected()
1521
                app_doc_data.clear(past=drawing.UID)
1522

    
1523
                app_doc_data.setImgFilePath(self.path)
1524
                app_doc_data.activeDrawing = drawing
1525
                
1526
                #app_doc_data.activeDrawing.set_pid_source(Image.open(self.path))
1527
                self.itemTreeWidget.setCurrentPID(app_doc_data.activeDrawing.name)
1528

    
1529
                drawingList = self.treeWidgetDrawingList.topLevelItem(0)
1530
                for idx in range(drawingList.childCount()):
1531
                    child = drawingList.child(idx)
1532
                    if child.data(Qt.UserRole, 0) is drawing:
1533
                        child.setCheckState(0, Qt.Checked)
1534
                    else:
1535
                        child.setCheckState(0, Qt.Unchecked)
1536

    
1537
                try:
1538
                    self.show_Progress_bar()
1539

    
1540
                    # disconnect scene changed if signal is connected
1541
                    if self.graphicsView.scene().receivers(self.graphicsView.scene().contents_changed) > 0:
1542
                        self.graphicsView.scene().contents_changed.disconnect()
1543

    
1544
                    SymbolSvgItem.DOCUMENTS.clear()
1545

    
1546
                    # load data
1547
                    cmd = LoadCommand()
1548
                    cmd.display_message.connect(self.onAddMessage)
1549
                    cmd.set_maximum.connect(self.progress.setMaximum)
1550
                    cmd.show_progress.connect(self.progress.setValue)
1551
                    cmd.execute((drawing, self.graphicsView.scene()),
1552
                                symbol=True, text=True, line=True, unknown=True, package=True, update=True)
1553
                    # up to here
1554

    
1555
                    """"update item tree widget"""
1556
                    line_no_items = [item for item in self.graphicsView.scene().items()
1557
                                     if type(item) is QEngineeringLineNoTextItem]
1558
                    for line_no in line_no_items:
1559
                        line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
1560
                        for run in line_no.runs:
1561
                            for run_item in run.items:
1562
                                if issubclass(type(run_item), SymbolSvgItem):
1563
                                    self.init_add_tree_item(line_no_tree_item, run_item)
1564

    
1565
                    line_no_items = [item for item in self.graphicsView.scene().items()
1566
                                     if type(item) is QEngineeringTrimLineNoTextItem]
1567
                    for line_no in line_no_items:
1568
                        line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
1569
                        for run in line_no.runs:
1570
                            for run_item in run.items:
1571
                                if issubclass(type(run_item), SymbolSvgItem):
1572
                                    self.init_add_tree_item(line_no_tree_item, run_item)
1573

    
1574
                    for trim_line_no in app_doc_data.tracerLineNos:
1575
                        line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, trim_line_no)
1576
                        for run in trim_line_no.runs:
1577
                            for run_item in run.items:
1578
                                if issubclass(type(run_item), SymbolSvgItem):
1579
                                    self.init_add_tree_item(line_no_tree_item, run_item)
1580

    
1581
                    self.itemTreeWidget.update_item_count()
1582
                    self.itemTreeWidget.expandAll()
1583
                    """up to here"""
1584

    
1585
                    """update scene"""
1586
                    for item in self._scene.items():
1587
                        item.setVisible(True)
1588

    
1589
                    self._scene.update(self._scene.sceneRect())
1590

    
1591
                    """
1592
                    # old open drawing
1593
                    path = os.path.join(app_doc_data.getCurrentProject().getTempPath(), app_doc_data.imgName + '.xml')
1594
                    configs = app_doc_data.getConfigs('Data Load', 'Xml First')
1595
                    if configs and int(configs[0].value) >= 1 and os.path.isfile(path):
1596
                        self.load_recognition_result_from_xml(drawing)
1597
                    elif configs and int(configs[0].value) <= 1:
1598
                        self.load_drawing(app_doc_data.activeDrawing)
1599
                    """
1600

    
1601
                    self.display_number_of_items()
1602
                    # connect scene changed signal
1603
                    self.graphicsView.scene().contents_changed.connect(self.scene_changed)
1604
                finally:
1605
                    if hasattr(self, 'progress'):
1606
                        self.progress.setValue(self.progress.maximum())
1607

    
1608
                self.changeViewCheckedState(True)
1609
                self.setWindowTitle(self.title)
1610
                self.fitWindow(drawing.view_rect)
1611

    
1612
                # save alarm
1613
                self.save_alarm_enable(True, True)
1614
        except Exception as ex:
1615
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
1616
                      f"{sys.exc_info()[-1].tb_lineno}"
1617
            self.addMessage.emit(MessageType.Error, message)
1618

    
1619
        return self.path
1620

    
1621
    def save_alarm_enable(self, enable, init=False):
1622
        from datetime import datetime
1623

    
1624
        try:
1625
            app_doc_data = AppDocData.instance()
1626
            configs = app_doc_data.getConfigs('Data Save', 'Time')
1627
            time_min = int(configs[0].value) if 1 == len(configs) else 0
1628

    
1629
            if enable and time_min > 0:
1630
                if not self.save_timer:
1631
                    self.save_timer = QTimer()
1632
                    self.save_timer.timeout.connect(self.save_alarm)
1633
                    self.save_timer.setInterval(60000)
1634

    
1635
                if init:
1636
                    self.save_timer._init_time = datetime.now()
1637
                    self.save_timer._stop_time = None
1638
                    self.save_timer._interval_time = datetime.now() - datetime.now()
1639

    
1640
                if self.save_timer._stop_time:
1641
                    self.save_timer._interval_time = datetime.now() - self.save_timer._stop_time
1642
                
1643
                #if 60000 * time_min != self.save_timer.interval():
1644
                #    self.save_timer.setInterval(60000)
1645

    
1646
                self.save_timer.start()
1647
            else:
1648
                if self.save_timer:
1649
                    self.save_timer.stop()
1650
                    self.save_timer._stop_time = datetime.now()
1651
        
1652
        except Exception as ex:
1653
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
1654
                      f"{sys.exc_info()[-1].tb_lineno}"
1655
            self.addMessage.emit(MessageType.Error, message)
1656

    
1657
    def save_alarm(self):
1658
        from datetime import datetime
1659

    
1660
        app_doc_data = AppDocData.instance()
1661
        configs = app_doc_data.getConfigs('Data Save', 'Time')
1662
        time_min = int(configs[0].value) if 1 == len(configs) else 0
1663

    
1664
        self.save_timer.stop()
1665
        if self.graphicsView.hasFocus() and (datetime.now() - self.save_timer._init_time - self.save_timer._interval_time).seconds > time_min * 60:
1666
            QMessageBox.information(self, self.tr('Information'), self.tr('Please save Drawing'))
1667
            self.save_timer._init_time = datetime.now()
1668
            self.save_timer._interval_time = datetime.now() - datetime.now()
1669
        self.save_timer.start()
1670

    
1671
    def export_as_svg(self):
1672
        """export scene to svg file"""
1673
        from ExportCommand import ExportCommand
1674

    
1675
        options = QFileDialog.Options()
1676
        options |= QFileDialog.DontUseNativeDialog
1677
        file_path, _ = QFileDialog.getSaveFileName(self, "Export as svg", os.getcwd(), "svg file(*.svg)",
1678
                                                   options=options)
1679
        if file_path:
1680
            cmd = ExportCommand(self.graphicsView.scene(), 'svg')
1681
            cmd.display_message.connect(self.onAddMessage)
1682
            if cmd.execute(file_path):
1683
                QMessageBox.information(self, self.tr('Information'), self.tr('Successfully export to svg file'))
1684
            else:
1685
                QMessageBox.information(self, self.tr('Error'), self.tr('Fail to export to svg file'))
1686

    
1687
    def export_as_xml(self):
1688
        pass
1689

    
1690
    def export_as_image(self):
1691
        """export scene to image file"""
1692
        from ExportCommand import ExportCommand
1693

    
1694
        options = QFileDialog.Options()
1695
        options |= QFileDialog.DontUseNativeDialog
1696
        file_path, _ = QFileDialog.getSaveFileName(self, "Export as png", os.getcwd(), "png file(*.png)",
1697
                                                   options=options)
1698
        if file_path:
1699
            try:
1700
                # hide image drawing
1701
                self.onViewImageDrawing(False)
1702

    
1703
                cmd = ExportCommand(self.graphicsView.scene(), 'image')
1704
                cmd.display_message.connect(self.onAddMessage)
1705

    
1706
                if cmd.execute(file_path):
1707
                    QMessageBox.information(self, self.tr('Information'), self.tr('Successfully export to image file'))
1708
                else:
1709
                    QMessageBox.information(self, self.tr('Error'), self.tr('Fail to export to image file'))
1710
            finally:
1711
                if self.actionImage_Drawing.isChecked():
1712
                    self.onViewImageDrawing(True)
1713
                    self.actionImage_Drawing.setChecked(True)
1714

    
1715
    def show_Progress_bar(self):
1716
        """ show progress bar """
1717
        self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
1718
                                        self) if not hasattr(self, 'progress') else self.progress
1719
        self.progress.setWindowModality(Qt.WindowModal)
1720
        self.progress.setAutoReset(True)
1721
        self.progress.setAutoClose(True)
1722
        self.progress.setMinimum(0)
1723
        self.progress.setMaximum(100)
1724
        self.progress.resize(600, 100)
1725
        self.progress.setWindowTitle(self.tr("Reading file..."))
1726
        self.progress.show()
1727

    
1728
    def changeViewCheckedState(self, checked, clear=True):
1729
        '''
1730
            @brief      change view checked state
1731
            @author     euisung
1732
            @date       2019.03.06
1733
        '''
1734
        # self.actionImage_Drawing.setChecked(checked)
1735
        self.actionViewText.setChecked(checked)
1736
        self.actionViewSymbol.setChecked(checked)
1737
        self.actionViewLine.setChecked(checked)
1738
        self.actionViewUnknown.setChecked(checked)
1739
        self.actionViewInconsistency.setChecked(checked)
1740
        self.actionViewVendor_Area.setChecked(not checked)
1741
        self.actionDrawing_Only.setChecked(not checked)
1742
        if clear:
1743
            self.tableWidgetInconsistency.clearContents()
1744
            self.tableWidgetInconsistency.setRowCount(0)
1745

    
1746
    def onViewDrawingOnly(self, isChecked):
1747
        '''
1748
            @brief  visible/invisible except image drawing
1749
            @author euisung
1750
            @date   2019.04.22
1751
        '''
1752
        self.changeViewCheckedState(not isChecked, False)
1753
        for item in self.graphicsView.scene().items():
1754
            if type(item) is not QGraphicsPixmapItem:
1755
                item.setVisible(not isChecked)
1756

    
1757
    '''
1758
        @brief  visible/invisible image drawing
1759
        @author humkyung
1760
        @date   2018.06.25
1761
    '''
1762

    
1763
    def onViewImageDrawing(self, isChecked):
1764
        for item in self.graphicsView.scene().items():
1765
            if type(item) is QGraphicsPixmapItem:
1766
                item.setVisible(isChecked)
1767
                break
1768

    
1769
    def onViewText(self, checked):
1770
        """visible/invisible text"""
1771
        selected = [item for item in self.graphicsView.scene().items() if issubclass(type(item), QEngineeringTextItem)
1772
                    and type(item) is not QEngineeringLineNoTextItem]
1773
        for item in selected:
1774
            item.setVisible(checked)
1775

    
1776
    def onViewSymbol(self, checked):
1777
        """visible/invisible symbol"""
1778
        selected = [item for item in self.graphicsView.scene().items() if
1779
                    (issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringErrorItem)]
1780
        for item in selected:
1781
            item.setVisible(checked)
1782

    
1783
    def onViewLine(self, checked):
1784
        """visible/invisible line"""
1785
        selected = [item for item in self.graphicsView.scene().items() if type(item) is QEngineeringLineItem]
1786
        for item in selected:
1787
            item.setVisible(checked)
1788

    
1789
    def onViewInconsistency(self, isChecked):
1790
        '''
1791
            @brief  visible/invisible Inconsistency
1792
            @author euisung
1793
            @date   2019.04.03
1794
        '''
1795
        selected = [item for item in self.graphicsView.scene().items() if type(item) is QEngineeringErrorItem]
1796
        for item in selected:
1797
            item.setVisible(isChecked)
1798

    
1799
    '''
1800
        @brief  visible/invisible Unknown 
1801
        @author humkyung
1802
        @date   2018.06.28
1803
    '''
1804

    
1805
    def onViewUnknown(self, isChecked):
1806
        selected = [item for item in self.graphicsView.scene().items() if type(item) is QEngineeringUnknownItem]
1807
        for item in selected:
1808
            item.setVisible(isChecked)
1809

    
1810
    def onViewVendorArea(self, isChecked):
1811
        '''
1812
            @brief  visible/invisible Vendor Area
1813
            @author euisung
1814
            @date   2019.04.29
1815
        '''
1816
        selected = [item for item in self.graphicsView.scene().items() if issubclass(type(item), QEngineeringVendorItem)]
1817
        for item in selected:
1818
            item.setVisible(isChecked)
1819

    
1820
    '''
1821
        @brief  create a symbol
1822
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
1823
                                            Add SymbolSvgItem
1824
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1825
                                            Change method to make svg and image path
1826
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
1827
    '''
1828
    def onCreateSymbolClicked(self):
1829
        selected = [item for item in self.graphicsView.scene().selectedItems() if issubclass(type(item), QEngineeringVendorItem)]
1830
        if len(selected) == 1:
1831
            symbol_image = AppDocData.instance().activeDrawing.image_origin
1832
            rect = selected[0].sceneBoundingRect()
1833

    
1834
            points = []
1835
            for conn in selected[0].connectors:
1836
                points.append([round(conn.center()[0] - rect.x()), round(conn.center()[1] - rect.y())])
1837
            poly = np.array(points, np.int32)
1838

    
1839
            #mask = np.zeros((int(rect.height()), int(rect.width())))
1840
            #cv2.fillPoly(mask, [poly], (255))
1841
            #poly_copied = np.multiply(mask, symbol_image[round(rect.y()):round(rect.y() + rect.height()),
1842
            #                   round(rect.x()):round(rect.x() + rect.width())])
1843
            #cv2.fillPoly(mask,[poly],0)
1844
            #src2 = np.multiply(mask,src2)
1845

    
1846
            mask = np.ones((int(rect.height()), int(rect.width())), dtype=np.uint8) * 255
1847
            cv2.fillPoly(mask, [poly], (0))
1848
            sym_img = cv2.bitwise_or(mask, symbol_image[int(rect.y()):int(rect.y()) + int(rect.height()), int(rect.x()):int(rect.x()) + int(rect.width())])
1849
            sym_img = cv2.merge((sym_img, sym_img, sym_img))
1850

    
1851
            h, w, c = sym_img.shape
1852
            qImg = QImage(sym_img.data, w, h, w * c, QImage.Format_RGB888)
1853
            #pixmap = QPixmap.fromImage(qImg)
1854

    
1855
            self.onAreaSelected(None, None, None, None, package=qImg, position=rect.topLeft(), package_item=selected[0])
1856
        else:
1857
            cmd = FenceCommand.FenceCommand(self.graphicsView)
1858
            cmd.onSuccess.connect(self.onAreaSelected)
1859
            self.graphicsView.command = cmd
1860
            QApplication.setOverrideCursor(Qt.CrossCursor)
1861

    
1862
    '''
1863
        @brief      show SymbolEditorDialog with image selected by user
1864
        @author     humkyung
1865
        @date       2018.07.20
1866
    '''
1867

    
1868
    def onAreaSelected(self, x, y, width, height, package=False, position=None, package_item=None):
1869
        try:
1870
            image = self.graphicsView.image()
1871
            if image is not None:
1872
                if not package:
1873
                    symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height),
1874
                                                                                AppDocData.instance().getCurrentProject())
1875
                else:
1876
                    symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, package,
1877
                                                                                AppDocData.instance().getCurrentProject(), package=True)
1878
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
1879
                # TODO: not initialize symbol tree view when user reject to create a new symbol
1880
                self.symbolTreeWidget.initSymbolTreeView()
1881
                if isAccepted:
1882
                    if isImmediateInsert:
1883
                        svg = QtImageViewer.createSymbolObject(newSym.getName())
1884
                        offsetX, offsetY = [int(point) for point in newSym.getOriginalPoint().split(',')]
1885
                        QtImageViewer.matchSymbolToLine(self.graphicsView.scene(), svg, QPoint(position.x() + offsetX, position.y() + offsetY))
1886

    
1887
                        package_item.transfer.onRemoved.emit(package_item)
1888
        finally:
1889
            self.onCommandRejected()
1890
            QApplication.restoreOverrideCursor()
1891

    
1892
    def on_make_label_data(self):
1893
        """ make label data from symbol info """
1894
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
1895

    
1896
        if not self.graphicsView.hasImage():
1897
            self.showImageSelectionMessageBox()
1898
            return
1899

    
1900
        app_doc_data = AppDocData.instance()
1901
        project = app_doc_data.getCurrentProject()
1902

    
1903
        smalls = []
1904
        bigs = []
1905

    
1906
        symbol_list = app_doc_data.getTargetSymbolList(all=True)
1907
        for symbol in symbol_list:
1908
            if symbol.width and symbol.height:
1909
                if symbol.width > 300 or symbol.height > 300:
1910
                    bigs.append(symbol.getName())
1911
                else:
1912
                    smalls.append(symbol.getName())
1913

    
1914
        symbols = [item for item in self.graphicsView.scene().items() if issubclass(type(item), SymbolSvgItem)]
1915
        names = [smalls, bigs]
1916

    
1917
        img = app_doc_data.activeDrawing.image_origin
1918

    
1919
        small_size = 500
1920
        big_size = 850
1921

    
1922
        save_path = project.getTrainingSymbolFilePath()
1923

    
1924
        index = 0
1925
        for size in [small_size, big_size]:
1926
            offsets = [0, int(size / 2)]
1927

    
1928
            width, height = img.shape[1], img.shape[0]
1929
            width_count, height_count = width // size + 2, height // size + 2
1930
            b_width, b_height = width_count * size, height_count * size
1931
            b_img = np.zeros((b_height, b_width), np.uint8) + 255
1932
            b_img[:height, :width] = img[:, :]
1933

    
1934
            for offset in offsets:
1935
                for row in range(height_count):
1936
                    for col in range(width_count):
1937
                        x, y = col * size + offset, row * size + offset
1938
                        tile_rect = QRectF(x, y, size, size)
1939
                        tile_symbols = []
1940
                        for symbol in [symbol for symbol in symbols if symbol.name in names[index]]:
1941
                            if tile_rect.contains(symbol.sceneBoundingRect()):
1942
                                tile_symbols.append(symbol)
1943
                                symbols.remove(symbol)
1944

    
1945
                        if tile_symbols:
1946
                            training_uid = str(uuid.uuid4())
1947
                            training_image_path = os.path.join(save_path, training_uid + '.png')
1948
                            training_xml_path = os.path.join(save_path, training_uid + '.xml')
1949

    
1950
                            # save image
1951
                            #_img = b_img[round(tile_rect.top()):round(tile_rect.bottom()),
1952
                            #       round(tile_rect.left()):round(tile_rect.right())]
1953
                            #cv2.imwrite(training_image_path, _img)
1954
                            _img = self.graphicsView.image().copy(round(tile_rect.left()), round(tile_rect.top()), round(tile_rect.width()), round(tile_rect.height()))
1955
                            _img.save(training_image_path)
1956

    
1957
                            # save label
1958
                            xml = Element('annotation')
1959
                            SubElement(xml, 'folder').text = 'None'
1960
                            SubElement(xml, 'filename').text = os.path.basename(save_path)
1961

    
1962
                            pathNode = Element('path')
1963
                            pathNode.text = save_path.replace('/', '\\')
1964
                            xml.append(pathNode)
1965

    
1966
                            sourceNode = Element('source')
1967
                            databaseNode = Element('database')
1968
                            databaseNode.text = 'Unknown'
1969
                            sourceNode.append(databaseNode)
1970
                            xml.append(sourceNode)
1971

    
1972
                            sizeNode = Element('size')
1973
                            widthNode = Element('width')
1974
                            widthNode.text = str(int(tile_rect.width()))
1975
                            sizeNode.append(widthNode)
1976
                            heightNode = Element('height')
1977
                            heightNode.text = str(int(tile_rect.height()))
1978
                            sizeNode.append(heightNode)
1979
                            depthNode = Element('depth')
1980
                            depthNode.text = '3'
1981
                            sizeNode.append(depthNode)
1982
                            xml.append(sizeNode)
1983

    
1984
                            segmentedNode = Element('segmented')
1985
                            segmentedNode.text = '0'
1986
                            xml.append(segmentedNode)
1987

    
1988
                            labelContent = []
1989
                            counts = {}
1990
                            for item in tile_symbols:
1991
                                rect = item.sceneBoundingRect()
1992
                                label, xMin, yMin, xMax, yMax = item.name, int(rect.x() - 5 - x), int(rect.y() - 5 - y), int(rect.x() + rect.width() + 5 - x), int(rect.y() + rect.height() + 5 - y)
1993
                                xMin = xMin if xMin > 0 else 0
1994
                                yMin = yMin if yMin > 0 else 0
1995
                                xMax = xMax if xMax < size else size
1996
                                yMax = yMax if yMax < size else size
1997

    
1998
                                if label == 'None' or label == '':
1999
                                    continue
2000
                                if label not in labelContent:
2001
                                    labelContent.append(label)
2002
                                    counts[label] = 1
2003
                                else:
2004
                                    counts[label] = counts[label] + 1
2005

    
2006
                                objectNode = Element('object')
2007
                                nameNode = Element('name')
2008
                                nameNode.text = label
2009
                                objectNode.append(nameNode)
2010
                                poseNode = Element('pose')
2011
                                poseNode.text = 'Unspecified'
2012
                                objectNode.append(poseNode)
2013
                                truncatedNode = Element('truncated')
2014
                                truncatedNode.text = '0'
2015
                                objectNode.append(truncatedNode)
2016
                                difficultNode = Element('difficult')
2017
                                difficultNode.text = '0'
2018
                                objectNode.append(difficultNode)
2019

    
2020
                                bndboxNode = Element('bndbox')
2021
                                xminNode = Element('xmin')
2022
                                xminNode.text = str(xMin)
2023
                                bndboxNode.append(xminNode)
2024
                                yminNode = Element('ymin')
2025
                                yminNode.text = str(yMin)
2026
                                bndboxNode.append(yminNode)
2027
                                xmaxNode = Element('xmax')
2028
                                xmaxNode.text = str(xMax)
2029
                                bndboxNode.append(xmaxNode)
2030
                                ymaxNode = Element('ymax')
2031
                                ymaxNode.text = str(yMax)
2032
                                bndboxNode.append(ymaxNode)
2033
                                objectNode.append(bndboxNode)
2034

    
2035
                                xml.append(objectNode)
2036

    
2037
                            ElementTree(xml).write(training_xml_path)
2038

    
2039
            index += 1
2040

    
2041
        QMessageBox.about(self, self.tr("Notice"), self.tr('Successfully applied. '))
2042

    
2043
    '''
2044
        @brief      create a line
2045
        @author     humkyung
2046
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
2047
    '''
2048
    def onPlaceLine(self):
2049
        if not self.graphicsView.hasImage():
2050
            self.actionLine.setChecked(False)
2051
            self.showImageSelectionMessageBox()
2052
            return
2053

    
2054
        self.actionLine.setChecked(True)
2055
        if not hasattr(self.actionLine, 'tag'):
2056
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
2057
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
2058
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
2059

    
2060
        self.graphicsView.command = self.actionLine.tag
2061

    
2062
    '''
2063
        @brief      add created lines to scene
2064
        @author     humkyung
2065
        @date       2018.07.23
2066
    '''
2067

    
2068
    def onLineCreated(self):
2069
        from EngineeringConnectorItem import QEngineeringConnectorItem
2070
        from LineDetector import LineDetector
2071

    
2072
        try:
2073
            app_doc_data = AppDocData.instance()
2074

    
2075
            count = len(self.actionLine.tag._polyline._vertices)
2076
            if count > 1:
2077
                items = []
2078

    
2079
                detector = LineDetector(None)
2080

    
2081
                if not self.actionLine.tag.line_type:
2082
                    line_type = self.lineComboBox.currentText()
2083
                else:
2084
                    if not (QEngineeringLineItem.check_piping(self.actionLine.tag.line_type) ^ QEngineeringLineItem.check_piping(self.lineComboBox.currentText())):
2085
                        line_type = self.lineComboBox.currentText()
2086
                    else:
2087
                        line_type = self.actionLine.tag.line_type
2088
                for index in range(count - 1):
2089
                    start = self.actionLine.tag._polyline._vertices[index]
2090
                    end = self.actionLine.tag._polyline._vertices[index + 1]
2091

    
2092
                    lineItem = QEngineeringLineItem(vertices=[start, end])
2093
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
2094
                    lineItem.lineType = line_type
2095
                    if items:
2096
                        lineItem.connect_if_possible(items[-1], 5)
2097
                    else:
2098
                        pt = lineItem.start_point()
2099
                        selected = [item for item in self.graphicsView.scene().items(QPointF(pt[0], pt[1])) if
2100
                                    type(item) is QEngineeringConnectorItem or type(item) is QEngineeringLineItem]
2101
                        if selected and selected[0] is not lineItem:
2102
                            if type(selected[0]) is QEngineeringConnectorItem:
2103
                                lineItem.connect_if_possible(selected[0].parent, 5)
2104
                            else:
2105
                                detector.connectLineToLine(selected[0], lineItem, 5)
2106

    
2107
                    items.append(lineItem)
2108
                    self.graphicsView.scene().addItem(lineItem)
2109
                    #app_doc_data.lines.append(lineItem)
2110

    
2111
                pt = items[-1].end_point()
2112
                selected = [item for item in self.graphicsView.scene().items(QPointF(pt[0], pt[1])) if
2113
                            (type(item) is QEngineeringConnectorItem and item.parentItem() is not items[-1]) or
2114
                            (type(item) is QEngineeringLineItem and item is not items[-1])]
2115
                if selected and selected[0] is not items[-1]:
2116
                    if type(selected[0]) is QEngineeringConnectorItem:
2117
                        items[-1].connect_if_possible(selected[0].parent, 5)
2118
                    else:
2119
                        detector.connectLineToLine(selected[0], items[-1], 5)
2120

    
2121
                self._scene.undo_stack.push(CreateCommand(self._scene, items))
2122
        finally:
2123
            self.graphicsView.scene().removeItem(self.actionLine.tag._polyline)
2124
            self.actionLine.tag.reset()
2125

    
2126
    '''
2127
        @brief      refresh scene
2128
        @author     humkyung
2129
        @date       2018.07.23
2130
    '''
2131

    
2132
    def onCommandRejected(self, cmd=None):
2133
        try:
2134
            if type(cmd) is PlaceLineCommand.PlaceLineCommand:
2135
                if self.actionLine.tag._polyline:
2136
                    self.graphicsView.scene().removeItem(self.actionLine.tag._polyline)
2137
                self.graphicsView.scene().update()
2138
                self.actionLine.tag.reset()
2139

    
2140
                self.actionLine.setChecked(False)
2141
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
2142
                self.actionZoom.setChecked(False)
2143
            elif type(cmd) is AreaOcrCommand.AreaOcrCommand:
2144
                self.actionOCR.setChecked(False)
2145
            elif type(cmd) is PlacePolygonCommand.PlacePolygonCommand:
2146
                self.actionVendor.setChecked(False)
2147
            else:
2148
                if hasattr(self.actionLine, 'tag') and self.actionLine.tag._polyline:
2149
                    self.graphicsView.scene().removeItem(self.actionLine.tag._polyline)
2150
                    self.graphicsView.scene().update()
2151
                    self.actionLine.tag.reset()
2152
                if hasattr(self.actionVendor, 'tag') and self.actionVendor.tag._polyline:
2153
                    self.graphicsView.scene().removeItem(self.actionVendor.tag._polyline)
2154
                    self.graphicsView.scene().update()
2155
                    self.actionVendor.tag.reset()
2156
                self.actionLine.setChecked(False)
2157
                self.actionZoom.setChecked(False)
2158
                self.actionOCR.setChecked(False)
2159
                self.actionVendor.setChecked(False)
2160
        finally:
2161
            self.graphicsView.useDefaultCommand()
2162

    
2163
    '''
2164
        @brief      restore to default command when user press Escape key
2165
        @author     humkyung 
2166
        @date       2018.08.09
2167
        
2168
    '''
2169

    
2170
    def keyPressEvent(self, event):
2171
        try:
2172
            if event.key() == Qt.Key_Escape:
2173
                checked = self.actionGroup.checkedAction()
2174
                if checked:
2175
                    checked.setChecked(False)
2176
                    self.graphicsView.useDefaultCommand()
2177
            elif event.key() == Qt.Key_1:
2178
                if self.actionImage_Drawing.isChecked():
2179
                    self.onViewImageDrawing(False)
2180
                    self.actionImage_Drawing.setChecked(False)
2181
                else:
2182
                    self.onViewImageDrawing(True)
2183
                    self.actionImage_Drawing.setChecked(True)
2184
            elif event.key() == Qt.Key_2:
2185
                if self.actionViewText.isChecked():
2186
                    self.onViewText(False)
2187
                    self.actionViewText.setChecked(False)
2188
                else:
2189
                    self.onViewText(True)
2190
                    self.actionViewText.setChecked(True)
2191
            elif event.key() == Qt.Key_3:
2192
                if self.actionViewSymbol.isChecked():
2193
                    self.onViewSymbol(False)
2194
                    self.actionViewSymbol.setChecked(False)
2195
                else:
2196
                    self.onViewSymbol(True)
2197
                    self.actionViewSymbol.setChecked(True)
2198
            elif event.key() == Qt.Key_4:
2199
                if self.actionViewLine.isChecked():
2200
                    self.onViewLine(False)
2201
                    self.actionViewLine.setChecked(False)
2202
                else:
2203
                    self.onViewLine(True)
2204
                    self.actionViewLine.setChecked(True)
2205
            elif event.key() == Qt.Key_5:
2206
                if self.actionViewUnknown.isChecked():
2207
                    self.onViewUnknown(False)
2208
                    self.actionViewUnknown.setChecked(False)
2209
                else:
2210
                    self.onViewUnknown(True)
2211
                    self.actionViewUnknown.setChecked(True)
2212
            elif event.key() == Qt.Key_6:
2213
                if self.actionViewInconsistency.isChecked():
2214
                    self.onViewInconsistency(False)
2215
                    self.actionViewInconsistency.setChecked(False)
2216
                else:
2217
                    self.onViewInconsistency(True)
2218
                    self.actionViewInconsistency.setChecked(True)
2219
            elif event.key() == Qt.Key_7:
2220
                if self.actionViewVendor_Area.isChecked():
2221
                    self.onViewVendorArea(False)
2222
                    self.actionViewVendor_Area.setChecked(False)
2223
                else:
2224
                    self.onViewVendorArea(True)
2225
                    self.actionViewVendor_Area.setChecked(True)
2226
            elif event.key() == 96:  # '`' key
2227
                if self.actionDrawing_Only.isChecked():
2228
                    self.onViewDrawingOnly(False)
2229
                    self.actionDrawing_Only.setChecked(False)
2230
                else:
2231
                    self.onViewDrawingOnly(True)
2232
                    self.actionDrawing_Only.setChecked(True)
2233
            elif event.key() == Qt.Key_M:  # merge text as vertical
2234
                from TextInfo import TextInfo
2235

    
2236
                textItems = [text for text in self.graphicsView.scene().selectedItems() if
2237
                             issubclass(type(text), QEngineeringTextItem)]
2238
                if not textItems or len(textItems) is 1:
2239
                    return
2240

    
2241
                angle = None
2242
                for item in textItems:
2243
                    if angle is None:
2244
                        angle = item.angle
2245
                    else:
2246
                        if angle != item.angle:
2247
                            return
2248

    
2249
                modifiers = QApplication.keyboardModifiers()
2250
                enter_or_space = ' ' if modifiers == Qt.ControlModifier else '\n'
2251
                x_or_y = 0 if modifiers == Qt.ControlModifier else 1
2252

    
2253
                textItems = sorted(textItems, key=lambda text: text.loc[x_or_y]) if textItems[0].angle == 0 else ( \
2254
                    sorted(textItems, key=lambda text: text.loc[x_or_y]) if textItems[0].angle == 1.57 else ( \
2255
                        sorted(textItems, key=lambda text: text.loc[x_or_y], reverse=True) if textItems[0].angle == 4.71 else \
2256
                            sorted(textItems, key=lambda text: text.loc[x_or_y], reverse=True)))
2257

    
2258
                if textItems[0].angle == 1.57 and modifiers == Qt.ControlModifier:
2259
                    textItems.reverse()
2260

    
2261
                minX = sys.maxsize
2262
                minY = sys.maxsize
2263
                maxX = 0
2264
                maxY = 0
2265
                newText = ''
2266

    
2267
                for text in textItems:
2268
                    if text.loc[0] < minX: minX = text.loc[0]
2269
                    if text.loc[1] < minY: minY = text.loc[1]
2270
                    if text.loc[0] + text.size[0] > maxX: maxX = text.loc[0] + text.size[0]
2271
                    if text.loc[1] + text.size[1] > maxY: maxY = text.loc[1] + text.size[1]
2272
                    newText = newText + text.text() + enter_or_space
2273
                    text.transfer.onRemoved.emit(text)
2274
                newText = newText[:-1]
2275

    
2276
                textInfo = TextInfo(newText, minX, minY, maxX - minX, maxY - minY, textItems[0].angle)
2277
                x = textInfo.getX()
2278
                y = textInfo.getY()
2279
                angle = textInfo.getAngle()
2280
                text = textInfo.getText()
2281
                width = textInfo.getW()
2282
                height = textInfo.getH()
2283
                item = TextItemFactory.instance().createTextItem(textInfo)
2284
                if item is not None:
2285
                    item.loc = [x, y]
2286
                    item.size = (width, height)
2287
                    item.angle = angle
2288
                    item.setDefaultTextColor(Qt.blue)
2289
                    item.addTextItemToScene(self.graphicsView.scene())
2290
                    item.transfer.onRemoved.connect(self.itemRemoved)
2291
            elif event.key() == Qt.Key_D:
2292
                # pop up development toolkit dialog
2293
                from DevelopmentToolkitDialog import QDevelopmentToolkitDialog
2294

    
2295
                modifiers = QApplication.keyboardModifiers()
2296
                if modifiers == Qt.ControlModifier:
2297
                    dlg = QDevelopmentToolkitDialog(self, self.graphicsView)
2298
                    dlg.show()
2299
            elif event.key() == Qt.Key_I:
2300
                # insert symbol item that is selected symbol in tree to main window if symbol already selected on main window, replace
2301
                index = self.symbolTreeWidget.currentIndex()
2302
                proxy_model = self.symbolTreeWidget.model()
2303
                items = [proxy_model.sourceModel().itemFromIndex(proxy_model.mapToSource(index))]
2304
                if items and hasattr(items[0], 'svgFilePath'):
2305
                    symData = items[0].data(self.symbolTreeWidget.TREE_DATA_ROLE)
2306
                    symName = symData.getName()
2307
                else:
2308
                    return
2309

    
2310
                symbolItems = [symbol for symbol in self.graphicsView.scene().selectedItems() if
2311
                               issubclass(type(symbol), SymbolSvgItem)]
2312
                old_symbol = None
2313
                if symbolItems and len(symbolItems) is 1:
2314
                    old_symbol = symbolItems[0]
2315
                    #scenePos = QPoint(old_symbol.origin[0], old_symbol.origin[1])
2316
                    scenePos = old_symbol.mapToScene(old_symbol.transformOriginPoint())
2317
                    old_symbol.transfer.onRemoved.emit(old_symbol)
2318
                else:
2319
                    scenePos = self.current_pos
2320

    
2321
                svg = QtImageViewer.createSymbolObject(symName)
2322
                QtImageViewer.matchSymbolToLine(self.graphicsView.scene(), svg, scenePos)
2323

    
2324
                if old_symbol and svg:
2325
                    from ReplaceCommand import ReplaceCommand
2326

    
2327
                    cmd = ReplaceCommand(self.graphicsView.scene(), old_symbol, svg)
2328
                    self._scene.undo_stack.push(cmd)
2329
                    return
2330
            elif event.key() == Qt.Key_J:
2331
                # insert and connect symbol item that is selected symbol in tree to selected symbol
2332
                index = self.symbolTreeWidget.currentIndex()
2333
                proxy_model = self.symbolTreeWidget.model()
2334
                items = [proxy_model.sourceModel().itemFromIndex(proxy_model.mapToSource(index))]
2335
                if items and hasattr(items[0], 'svgFilePath'):
2336
                    symData = items[0].data(self.symbolTreeWidget.TREE_DATA_ROLE)
2337
                    symName = symData.getName()
2338
                else:
2339
                    return
2340

    
2341
                symbolItems = [symbol for symbol in self.graphicsView.scene().selectedItems() if
2342
                               issubclass(type(symbol), SymbolSvgItem)]
2343
                if symbolItems and len(symbolItems) is not 1:
2344
                    return
2345
                    
2346
                target_symbol = symbolItems[0]
2347
                index =  [index for index in range(len(target_symbol.conn_type)) \
2348
                            if target_symbol.conn_type[index] == 'Primary' or target_symbol.conn_type[index] == 'Secondary']
2349
                for connector in target_symbol.connectors:
2350
                    svg = QtImageViewer.createSymbolObject(symName)
2351
                    if len(svg.connectors) > 1: 
2352
                        if ((target_symbol.conn_type and target_symbol.connectors.index(connector) in index) or not target_symbol.conn_type) and \
2353
                                    (not connector.connectedItem or (connector.connectedItem and type(connector.connectedItem) is QEngineeringLineItem)):
2354
                            QtImageViewer.matchSymbolToLine(self.graphicsView.scene(), svg, connector.sceneBoundingRect().center())
2355
                    elif len(svg.connectors) == 1:
2356
                        if ((target_symbol.conn_type and target_symbol.connectors.index(connector) in index) or not target_symbol.conn_type) and \
2357
                                    not connector.connectedItem:
2358
                            QtImageViewer.matchSymbolToLine(self.graphicsView.scene(), svg, connector.sceneBoundingRect().center())
2359

    
2360
                if target_symbol:
2361
                    return
2362
            elif event.key() == Qt.Key_X:
2363
                app_doc_data = AppDocData.instance()
2364
                configs = app_doc_data.getAppConfigs('app', 'mode')
2365
                if configs and 1 == len(configs) and 'advanced' == configs[0].value:
2366
                    advanced = True
2367
                    items = self.graphicsView.scene().selectedItems()
2368
                    if items:
2369
                        item = self.symbolTreeWidget.currentItem()
2370
                        if item:
2371
                            self.symbolTreeWidget.showSymbolEditorDialog(item, 0)
2372
            elif event.key() == Qt.Key_F6:
2373
                from DEXPI import scene_to_dexpi
2374

    
2375
                app_doc_data = AppDocData.instance()
2376
                scene_to_dexpi('D:\\Temp\\DEXPI.xml', app_doc_data.activeDrawing.name, self.graphicsView.scene())
2377

    
2378
            QMainWindow.keyPressEvent(self, event)
2379
        except Exception as ex:
2380
            message = f"error occurred({repr(ex)}) in {sys.exc_info()[-1].tb_frame.f_code.co_filename}:" \
2381
                      f"{sys.exc_info()[-1].tb_lineno}"
2382
            self.addMessage.emit(MessageType.Error, message)
2383

    
2384
    def recognize(self):
2385
        """recognize symbol, text and line for selected drawings"""
2386
        from datetime import datetime
2387
        from RecognitionDialog import QRecognitionDialog
2388

    
2389
        # save alarm
2390
        self.save_alarm_enable(False)
2391

    
2392
        app_doc_data = AppDocData.instance()
2393
        current_drawing, currentPid = None, None
2394

    
2395
        if self.graphicsView.hasImage():
2396
            current_drawing = app_doc_data.activeDrawing
2397
            currentPid = app_doc_data.activeDrawing.name
2398

    
2399
        # get checked drawings
2400
        drawing_top = self.treeWidgetDrawingList.topLevelItem(0)
2401
        count = drawing_top.childCount()
2402
        checked_drawings = {}
2403
        for idx in range(count):
2404
            child = drawing_top.child(idx)
2405
            if child.checkState(0) == Qt.Checked and child.data(Qt.UserRole, 0):
2406
                checked_drawings[child.data(Qt.UserRole, 0)] = child
2407
        # up to here
2408

    
2409
        # if there is no checked drawing
2410
        if current_drawing and currentPid and not checked_drawings:
2411
            for idx in range(count):
2412
                child = drawing_top.child(idx)
2413
                if child.data(Qt.UserRole, 0) is current_drawing:
2414
                    checked_drawings[child.data(Qt.UserRole, 0)] = child
2415

    
2416
        if not checked_drawings:
2417
            self.showImageSelectionMessageBox()
2418
            return
2419

    
2420
        try:
2421
            self.on_clear_log()
2422
            dlg = QRecognitionDialog(self, [drawing for drawing in checked_drawings.keys()])
2423
            dlg.exec_()
2424

    
2425
            if current_drawing and current_drawing in checked_drawings.keys() and dlg.isTreated:
2426
                self.open_image_drawing(current_drawing, force=True)
2427

    
2428
            # save working date-time
2429
            _now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
2430
            for drawing, tree_item in checked_drawings.items():
2431
                drawing.datetime = _now
2432
                tree_item.setText(1, _now)
2433
            #app_doc_data.saveDrawings(checked_drawings.keys())
2434
            self.changeViewCheckedState(True)
2435
            # up to here
2436
        except Exception as ex:
2437
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
2438
                                                           sys.exc_info()[-1].tb_lineno)
2439
            self.addMessage.emit(MessageType.Error, message)
2440

    
2441
        # save alarm
2442
            self.save_alarm_enable(True)
2443

    
2444
    '''
2445
        @brief      remove item from tree widget and then remove from scene
2446
        @date       2018.05.25
2447
        @author     Jeongwoo
2448
    '''
2449

    
2450
    def itemRemoved(self, item):
2451
        try:
2452
            if type(item) is QEngineeringErrorItem:
2453
                # remove error item from inconsistency list
2454
                for row in range(self.tableWidgetInconsistency.rowCount()):
2455
                    if item is self.tableWidgetInconsistency.item(row, 0).tag:
2456
                        self.tableWidgetInconsistency.removeRow(row)
2457
                        break
2458

    
2459
                if item.scene() is not None:
2460
                    item.scene().removeItem(item)
2461
                del item
2462
            else:
2463
                remove_scene = item.scene()
2464
                self.itemTreeWidget.itemRemoved(item)
2465

    
2466
                matches = [_item for _item in remove_scene.items() if
2467
                           hasattr(_item, 'connectors') and [connector for connector in _item.connectors if
2468
                                                             connector.connectedItem is item]]
2469
                for match in matches:
2470
                    for connector in match.connectors:
2471
                        if connector.connectedItem is item:
2472
                            connector.connectedItem = None
2473
                            connector.highlight(False)
2474

    
2475
                # matches = [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'remove_assoc_item')]
2476
                # for _item in matches:
2477
                #    _item.remove_assoc_item(item)
2478

    
2479
                app_doc_data = AppDocData.instance()
2480
                if type(item) is QEngineeringLineNoTextItem and item in app_doc_data.tracerLineNos:
2481
                    app_doc_data.tracerLineNos.pop(app_doc_data.tracerLineNos.index(item))
2482

    
2483
                if type(item) is QEngineeringLineItem and item in app_doc_data.lines:
2484
                    app_doc_data.lines.remove(item)
2485

    
2486
                matches = [_item for _item in remove_scene.items() if
2487
                           type(_item) is QEngineeringLineNoTextItem]
2488
                matches.extend([lineNo for lineNo in app_doc_data.tracerLineNos if
2489
                                type(lineNo) is QEngineeringTrimLineNoTextItem])
2490
                for match in matches:
2491
                    if item is match.prop('From'):
2492
                        match.set_property('From', None)
2493
                    if item is match.prop('To'):
2494
                        match.set_property('To', None)
2495

    
2496
                    for run_index in reversed(range(len(match.runs))):
2497
                        run = match.runs[run_index]
2498
                        if item in run.items:
2499
                            index = run.items.index(item)
2500
                            run.items.pop(index)
2501
                            if not run.items:
2502
                                run.explode()
2503
                                if type(match) is QEngineeringTrimLineNoTextItem and not match.runs:
2504
                                    app_doc_data.tracerLineNos.pop(app_doc_data.tracerLineNos.index(match))
2505
                            # break
2506

    
2507
                matches = [_item for _item in remove_scene.items() if hasattr(_item, 'owner')]
2508
                for match in matches:
2509
                    if match.owner is item:
2510
                        match.owner = None
2511

    
2512
                matches = [_item for _item in remove_scene.items() if hasattr(_item, 'attrs')]
2513
                # done = False
2514
                for match in matches:
2515
                    assocs = match.associations()
2516
                    for assoc in assocs:
2517
                        if item is assoc:
2518
                            for attr in match.attrs.keys():
2519
                                if attr.AssocItem and str(item.uid) == str(attr.AssocItem.uid):
2520
                                    attr.AssocItem = None
2521
                                    match.attrs[attr] = ''
2522
                                    # done = True
2523
                            match.remove_assoc_item(item)
2524
                            break
2525
                    # if done: break
2526

    
2527
                if item.scene() is not None: item.scene().removeItem(item)
2528
        except Exception as ex:
2529
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2530
                                                           sys.exc_info()[-1].tb_lineno)
2531
            self.addMessage.emit(MessageType.Error, message)
2532
        '''
2533
        finally:
2534
            if hasattr(item, '_cond'):
2535
                item._cond.wakeAll()
2536
        '''
2537

    
2538

    
2539
    def connect_attributes(self, MainWindow):
2540
        """connect attributes to symbol"""
2541
        from LineNoTracer import LineNoTracer
2542
        from ConnectAttrDialog import QConnectAttrDialog
2543

    
2544
        if not self.graphicsView.hasImage():
2545
            self.showImageSelectionMessageBox()
2546
            return
2547

    
2548
        # save alarm
2549
        self.save_alarm_enable(False)
2550

    
2551
        try:
2552
            dlg = QConnectAttrDialog(self, self.graphicsView.scene())
2553
            dlg.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint)
2554
            dlg.exec_()
2555
            if dlg.isRunned:
2556
                self.refresh_item_list()
2557

    
2558
                if dlg.validation_checked:
2559
                    self.onValidation()
2560

    
2561
                self.graphicsView.invalidateScene()
2562
        except Exception as ex:
2563
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2564
                                                           sys.exc_info()[-1].tb_lineno)
2565
            self.addMessage.emit(MessageType.Error, message)
2566
        finally:
2567
            # save alarm
2568
            self.save_alarm_enable(True)
2569

    
2570
    def postDetectLineProcess(self):
2571
        '''
2572
            @brief  check allowables among undetected items
2573
            @author euisung
2574
            @date   2018.11.15
2575
            @history    2018.11.15  euisung    no more used, moved to TextItemFactoy isLineNo()
2576
        '''
2577
        from TextItemFactory import TextItemFactory
2578

    
2579
        appDocData = AppDocData.instance()
2580

    
2581
        tableNames = ["Fluid Code", "Insulation Purpose", "PnID Number", "Piping Materials Class", "Unit Number"]
2582
        tableDatas = []
2583
        for tableName in tableNames:
2584
            tableNameFormat = tableName.replace(' ', '').replace('&&', 'n')
2585
            tableDatas.append(appDocData.getCodeTable(tableNameFormat))
2586

    
2587
        items = self.graphicsView.scene().items()
2588
        for item in items:
2589
            if type(item) is not QEngineeringTextItem:
2590
                continue
2591
            text = item.text()
2592
            for tableData in tableDatas:
2593
                for data in tableData:
2594
                    if data[3] == '':
2595
                        continue
2596
                    else:
2597
                        allows = data[3].split(',')
2598
                        for allow in allows:
2599
                            text = text.replace(allow, data[1])
2600

    
2601
            lineItem = TextItemFactory.instance().createTextItem(text)
2602
            if type(lineItem) is QEngineeringLineNoTextItem:
2603
                lineItem.loc = item.loc
2604
                lineItem.size = item.size
2605
                lineItem.angle = item.angle
2606
                lineItem.area = item.area
2607
                # lineItem.addTextItemToScene(self.graphicsView.scene())
2608
                lineItem.transfer.onRemoved.connect(self.itemRemoved)
2609
                item.transfer.onRemoved.emit(item)
2610
                appDocData.lineNos.append(lineItem)
2611

    
2612
    def init_add_tree_item(self, line_no_tree_item, run_item):
2613
        """ insert symbol item and find line no as owner """
2614
        # insert
2615
        self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2616
        # find
2617
        self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2618

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

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

    
2629
            components = app_doc_data.get_components(drawing.UID)
2630
            maxValue = len(components) * 2
2631
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2632

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

    
2652
                self.progress.setValue(self.progress.value() + 1)
2653

    
2654
            QApplication.processEvents()
2655

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

    
2667
                self.progress.setValue(self.progress.value() + 1)
2668

    
2669
            QApplication.processEvents()
2670

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

    
2682
                self.progress.setValue(self.progress.value() + 1)
2683

    
2684
            QApplication.processEvents()
2685

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

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

    
2696
            QApplication.processEvents()
2697

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

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

    
2708
            QApplication.processEvents()
2709

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

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

    
2732
                        for run_item in line_run.items:
2733
                            if issubclass(type(run_item), SymbolSvgItem):
2734
                                self.init_add_tree_item(line_no_tree_item, run_item)
2735

    
2736
                self.progress.setValue(self.progress.value() + 1)
2737
            QApplication.processEvents()
2738

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

    
2744
                runs = app_doc_data.get_pipe_runs(str(line_no.uid))
2745
                if not runs: continue
2746

    
2747
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2748

    
2749
                for run in runs:
2750
                    line_run = QEngineeringRunItem()
2751
                    run_items = app_doc_data.get_pipe_run_items(run['UID'])
2752
                    for record in run_items:
2753
                        uid = record['Components_UID']
2754
                        run_item = self.graphicsView.findItemByUid(uid)
2755
                        if run_item is not None:
2756
                            run_item.owner = line_no
2757
                            line_run.items.append(run_item)
2758
                    line_run.owner = line_no
2759
                    line_no.runs.append(line_run)
2760

    
2761
                    for run_item in line_run.items:
2762
                        if issubclass(type(run_item), SymbolSvgItem):
2763
                            self.init_add_tree_item(line_no_tree_item, run_item)
2764

    
2765
                app_doc_data.tracerLineNos.append(line_no)
2766

    
2767
                self.progress.setValue(self.progress.value() + 1)
2768

    
2769
            for component in [component for component in components if
2770
                              component['Name'] == 'VendorPackage' and component['SymbolType_UID'] == -1]:
2771
                item = QEngineeringVendorItem.from_database(component)
2772
                if item is not None:
2773
                    item.transfer.onRemoved.connect(self.itemRemoved)
2774
                    self.graphicsView.scene().addItem(item)
2775

    
2776
            # connect flow item to line
2777
            for line in lines:
2778
                line.update_arrow()
2779
                app_doc_data.lines.append(line)
2780
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
2781
            #    for line in lines:
2782
            #        if flowMark.owner is line:
2783
            #            line._flowMark.append(flowMark)
2784
            #            flowMark.setParentItem(line)
2785
            # up to here
2786

    
2787
            """ update scene """
2788
            self.graphicsView.scene().update(self.graphicsView.sceneRect())
2789
            for item in self.graphicsView.scene().items():
2790
                up_progress = False
2791
                # binding items
2792
                if hasattr(item, 'owner'):
2793
                    item.owner
2794
                    up_progress = True
2795
                if hasattr(item, 'connectors'):
2796
                    for connector in item.connectors:
2797
                        connector.connectedItem
2798
                    up_progress = True
2799

    
2800
                if up_progress:
2801
                    self.progress.setValue(self.progress.value() + 1)
2802
            
2803
            for item in self.graphicsView.scene().items():
2804
                item.setVisible(True)
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.itemTreeWidget.update_item_count()
2813
            self.itemTreeWidget.expandAll()
2814
            # self.graphicsView.scene().blockSignals(False)
2815

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

    
2839
    def load_recognition_result_from_xml(self, drawing):
2840
        # Yield successive n-sized
2841
        # chunks from l.
2842
        def divide_chunks(l, n):
2843
            # looping till length l
2844
            for i in range(0, len(l), n):
2845
                yield l[i:i + n]
2846

    
2847
        def update_items(items):
2848
            for item in items:
2849
                # binding items
2850
                item.owner
2851
                for connector in item.connectors:
2852
                    connector.connectedItem
2853

    
2854
            return items
2855

    
2856
        import concurrent.futures as futures
2857
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
2858
        from App import App
2859
        from EngineeringRunItem import QEngineeringRunItem
2860
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2861
        from EngineeringGraphicsLineItem import QEngineeringGraphicsLineItem
2862

    
2863
        app_doc_data = AppDocData.instance()
2864

    
2865
        try:
2866
            file_name = os.path.splitext(os.path.basename(drawing.file_path))[0]
2867
            path = os.path.join(app_doc_data.getCurrentProject().getTempPath(), file_name + '.xml')
2868
            self.graphicsView.scene().blockSignals(True)
2869

    
2870
            symbols = []
2871
            lines = []
2872

    
2873
            xml = parse(path)
2874
            root = xml.getroot()
2875

    
2876
            maxValue = 0
2877
            maxValue = maxValue + len(list(root.iter('SYMBOL'))) - \
2878
                       len(list(root.iterfind('LINENOS/LINE_NO/RUN/SYMBOL'))) - \
2879
                       len(list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/SYMBOL')))
2880
            maxValue = maxValue + len(list(root.iterfind('TEXTINFOS/ATTRIBUTE')))
2881
            maxValue = maxValue + len(list(root.iterfind('NOTES/ATTRIBUTE')))
2882
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
2883
            maxValue = maxValue + len(list(root.iter('LINE'))) - \
2884
                       len(list(root.iterfind('LINENOS/LINE_NO/RUN/LINE'))) - \
2885
                       len(list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/LINE')))
2886
            maxValue = maxValue + len(list(root.iter('GRAPHICS_LINE')))
2887
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
2888
            # maxValue = maxValue + len(list(root.iter('SIZETEXT')))
2889
            maxValue = maxValue + len(list(root.iter('TRIM_LINE_NO')))
2890
            maxValue *= 2
2891
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2892

    
2893
            """ parsing all symbols """
2894
            """
2895
            with futures.ThreadPoolExecutor(max_workers=App.THREAD_MAX_WORKER) as pool:
2896
                future_symbol = {pool.submit(SymbolSvgItem.fromXml, symbol): symbol for symbol in root.find('SYMBOLS').iter('SYMBOL')}
2897

2898
                for future in futures.as_completed(future_symbol):
2899
                    try:
2900
                        item = future.result()
2901
                        if item:
2902
                            if item is not None:
2903
                                item.transfer.onRemoved.connect(self.itemRemoved)
2904
                                symbols.append(item)
2905
                                docData.symbols.append(item)
2906
                                self.addSvgItemToScene(item)
2907
                            else:
2908
                                pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2909
                                size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2910
                                angle = float(symbol.find('ANGLE').text)
2911
                                item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2912
                                item.isSymbol = True
2913
                                item.angle = angle
2914
                                item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2915
                                self.graphicsView.scene().addItem(item)
2916
                                item.transfer.onRemoved.connect(self.itemRemoved)
2917
                    except Exception as ex:
2918
                        message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
2919
                                                                       sys.exc_info()[-1].tb_lineno)
2920

2921
            """
2922
            for symbol in root.find('SYMBOLS').iter('SYMBOL'):
2923
                item = SymbolSvgItem.fromXml(symbol)
2924
                if item is not None:
2925
                    item.transfer.onRemoved.connect(self.itemRemoved)
2926
                    symbols.append(item)
2927
                    #app_doc_data.symbols.append(item)
2928
                    item.addSvgItemToScene(self.graphicsView.scene())
2929
                else:
2930
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2931
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2932
                    angle = float(symbol.find('ANGLE').text)
2933
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2934
                    item.isSymbol = True
2935
                    item.angle = angle
2936
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2937
                    self.graphicsView.scene().addItem(item)
2938
                    item.transfer.onRemoved.connect(self.itemRemoved)
2939

    
2940
                self.progress.setValue(self.progress.value() + 1)
2941

    
2942
            QApplication.processEvents()
2943

    
2944
            # parse texts
2945
            for text in root.find('TEXTINFOS').iter('ATTRIBUTE'):
2946
                item = QEngineeringTextItem.fromXml(text)
2947
                if item is not None:
2948
                    uid = text.find('UID')
2949
                    attributeValue = text.find('ATTRIBUTEVALUE')
2950
                    name = text.find('NAME').text
2951
                    item.transfer.onRemoved.connect(self.itemRemoved)
2952
                    item.addTextItemToScene(self.graphicsView.scene())
2953
                    # docData.texts.append(item)
2954

    
2955
                    if name == 'TEXT':
2956
                        if uid is not None and attributeValue is not None:
2957
                            item.uid = uid.text
2958
                            item.attribute = attributeValue.text
2959

    
2960
                self.progress.setValue(self.progress.value() + 1)
2961

    
2962
            QApplication.processEvents()
2963

    
2964
            # note
2965
            for text in root.find('NOTES').iter('ATTRIBUTE'):
2966
                item = QEngineeringTextItem.fromXml(text)
2967
                if item is not None:
2968
                    uid = text.find('UID')
2969
                    attributeValue = text.find('ATTRIBUTEVALUE')
2970
                    name = text.find('NAME').text
2971
                    item.transfer.onRemoved.connect(self.itemRemoved)
2972
                    item.addTextItemToScene(self.graphicsView.scene())
2973

    
2974
                    if name == 'NOTE':
2975
                        if uid is not None:
2976
                            item.uid = uid.text
2977

    
2978
                self.progress.setValue(self.progress.value() + 1)
2979

    
2980
            QApplication.processEvents()
2981

    
2982
            for line in root.find('LINEINFOS').iter('LINE'):
2983
                item = QEngineeringLineItem.fromXml(line)
2984
                if item:
2985
                    item.transfer.onRemoved.connect(self.itemRemoved)
2986
                    self.graphicsView.scene().addItem(item)
2987
                    lines.append(item)
2988

    
2989
                self.progress.setValue(self.progress.value() + 1)
2990

    
2991
            for line in root.find('LINEINFOS').iter('GRAPHICS_LINE'):
2992
                item = QEngineeringGraphicsLineItem.fromXml(line)
2993
                if item:
2994
                    item.transfer.onRemoved.connect(self.itemRemoved)
2995
                    self.graphicsView.scene().addItem(item)
2996

    
2997
                self.progress.setValue(self.progress.value() + 1)
2998

    
2999
            QApplication.processEvents()
3000

    
3001
            for unknown in root.iter('UNKNOWN'):
3002
                item = QEngineeringUnknownItem.fromXml(unknown)
3003
                if item is not None:
3004
                    item.transfer.onRemoved.connect(self.itemRemoved)
3005
                    self.graphicsView.scene().addItem(item)
3006

    
3007
                self.progress.setValue(self.progress.value() + 1)
3008

    
3009
            QApplication.processEvents()
3010

    
3011
            # """ add tree widget """
3012
            # for item in symbols:
3013
            #    docData.symbols.append(item)
3014
            #    self.addSvgItemToScene(item)
3015
            #    self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
3016

    
3017
            for line_no_node in root.find('LINENOS').iter('LINE_NO'):
3018
                line_no = QEngineeringLineNoTextItem.fromXml(line_no_node)
3019
                if line_no is None: continue
3020
                line_no.transfer.onRemoved.connect(self.itemRemoved)
3021
                line_no.addTextItemToScene(self.graphicsView.scene())
3022
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
3023
                if type(line_no) is not QEngineeringLineNoTextItem: continue
3024

    
3025
                runs_node = line_no_node.findall('RUN')
3026
                if runs_node is None: continue
3027

    
3028
                for run_node in runs_node:
3029
                    line_run = QEngineeringRunItem()
3030
                    for child_node in run_node:
3031
                        uidElement = child_node.find('UID')
3032
                        if uidElement is not None:
3033
                            uid = uidElement.text
3034
                            run_item = self.graphicsView.findItemByUid(uid)
3035
                            if run_item is not None:
3036
                                run_item._owner = line_no
3037
                                line_run.items.append(run_item)
3038
                    line_run.owner = line_no
3039
                    line_no.runs.append(line_run)
3040

    
3041
                    for run_item in line_run.items:
3042
                        if issubclass(type(run_item), SymbolSvgItem):
3043
                            self.init_add_tree_item(line_no_tree_item, run_item)
3044

    
3045
                # docData.tracerLineNos.append(line_no)
3046

    
3047
                self.progress.setValue(self.progress.value() + 1)
3048
            QApplication.processEvents()
3049

    
3050
            for trimLineNo in root.iter('TRIM_LINE_NO'):
3051
                line_no = QEngineeringTrimLineNoTextItem()
3052
                line_no.uid = uuid.UUID(trimLineNo.find('UID').text)
3053

    
3054
                runs_node = trimLineNo.findall('RUN')
3055
                if runs_node is None: continue
3056
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
3057

    
3058
                for run in runs_node:
3059
                    line_run = QEngineeringRunItem()
3060
                    for child in run:
3061
                        uidElement = child.find('UID')
3062
                        if uidElement is not None:
3063
                            uid = uidElement.text
3064
                            run_item = self.graphicsView.findItemByUid(uid)
3065
                            if run_item is not None:
3066
                                run_item.owner = line_no
3067
                                line_run.items.append(run_item)
3068
                    line_run.owner = line_no
3069
                    line_no.runs.append(line_run)
3070

    
3071
                    for run_item in line_run.items:
3072
                        if issubclass(type(run_item), SymbolSvgItem):
3073
                            self.init_add_tree_item(line_no_tree_item, run_item)
3074

    
3075
                app_doc_data.tracerLineNos.append(line_no)
3076

    
3077
                self.progress.setValue(self.progress.value() + 1)
3078
            QApplication.processEvents()
3079

    
3080
            if root.find('VENDORS') is not None:
3081
                for vendor in root.find('VENDORS').iter('VENDOR'):
3082
                    item = QEngineeringVendorItem.fromXml(vendor)
3083
                    item.transfer.onRemoved.connect(self.itemRemoved)
3084
                    self.graphicsView.scene().addItem(item)
3085

    
3086
            # connect flow item to line
3087
            for line in lines:
3088
                line.update_arrow()
3089
                app_doc_data.lines.append(line)
3090
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
3091
            #    for line in lines:
3092
            #        if flowMark.owner is line:
3093
            #            line._flowMark.append(flowMark)
3094
            #            flowMark.setParentItem(line)
3095
            # up to here
3096

    
3097
            """
3098
            group_box = QGroupBox("Contact Details")
3099
            number_label = QLabel("Telephone number");
3100
            number_edit = QTextEdit('hello\nthis is ....')
3101
            layout = QFormLayout()
3102
            layout.addRow(number_label, number_edit)
3103
            group_box.setLayout(layout)
3104

3105
            proxy =  ㅐ()
3106
            proxy.setWidget(group_box)
3107
            self.graphicsView.scene().addItem(proxy)  # (group_box, QGraphicsItem.ItemIgnoresTransformations)
3108
            """
3109

    
3110
            """ update scene """
3111
            _items = [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'owner') or hasattr(_item, 'connectors')]
3112
            if _items:
3113
                items = divide_chunks(_items, App.THREAD_MAX_WORKER if len(_items) > App.THREAD_MAX_WORKER else len(_items))
3114
                with futures.ThreadPoolExecutor(max_workers=App.THREAD_MAX_WORKER) as pool:
3115
                    future_items = {pool.submit(update_items, _items): _items for _items in items}
3116
                    for future in futures.as_completed(future_items):
3117
                        _items = future.result()
3118
                        self.progress.setValue(self.progress.value() + len(_items))
3119

    
3120
            """
3121
            for item in [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'owner') or hasattr(_item, 'connectors')]:
3122
                up_progress = False
3123
                # binding items
3124
                item.owner
3125
                for connector in item.connectors:
3126
                    connector.connectedItem
3127

3128
                self.progress.setValue(self.progress.value() + 1)
3129
            """
3130

    
3131
            for item in self.graphicsView.scene().items():
3132
                item.setVisible(True)
3133

    
3134
            self.graphicsView.scene().update(self.graphicsView.sceneRect())
3135
        except Exception as ex:
3136
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3137
                                                           sys.exc_info()[-1].tb_lineno)
3138
            self.addMessage.emit(MessageType.Error, message)
3139
        finally:
3140
            self.itemTreeWidget.update_item_count()
3141
            self.itemTreeWidget.expandAll()
3142
            self.graphicsView.scene().blockSignals(False)
3143

    
3144
    '''
3145
        @brief      Remove added item on same place and Add GraphicsItem
3146
        @author     Jeongwoo
3147
        @date       2018.05.29
3148
        @history    2018.06.18  Jeongwoo    Set Z-index
3149
    '''
3150

    
3151
    def addLineItemToScene(self, lineItem):
3152
        self.graphicsView.scene().addItem(lineItem)
3153

    
3154
    '''
3155
        @brief      generate output xml file
3156
        @author     humkyung
3157
        @date       2018.04.23
3158
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
3159
    '''
3160

    
3161
    def generateOutput(self):
3162
        import XmlGenerator as xg
3163

    
3164
        if not self.graphicsView.hasImage():
3165
            self.showImageSelectionMessageBox()
3166
            return
3167

    
3168
        try:
3169
            appDocData = AppDocData.instance()
3170

    
3171
            # collect items
3172
            appDocData.lines.clear()
3173
            appDocData.lines = [item for item in self.graphicsView.scene().items() if
3174
                                type(item) is QEngineeringLineItem and item.owner is None]
3175

    
3176
            appDocData.symbols.clear()
3177
            appDocData.symbols = [item for item in self.graphicsView.scene().items() if
3178
                                  issubclass(type(item), SymbolSvgItem) and item.owner is None]
3179

    
3180
            appDocData.equipments.clear()
3181
            for item in self.graphicsView.scene().items():
3182
                if type(item) is QEngineeringEquipmentItem:
3183
                    appDocData.equipments.append(item)
3184

    
3185
            appDocData.texts.clear()
3186
            appDocData.texts = [item for item in self.graphicsView.scene().items() if
3187
                                issubclass(type(item), QEngineeringTextItem) and type(
3188
                                    item) is not QEngineeringLineNoTextItem]
3189
            # up to here
3190

    
3191
            appDocData.imgOutput = np.ones((appDocData.activeDrawing.height, appDocData.activeDrawing.width),
3192
                                           np.uint8) * 255
3193
            xg.writeOutputXml(appDocData.imgName, appDocData.activeDrawing.width,
3194
                              appDocData.activeDrawing.height)  # TODO: check
3195
            project = appDocData.getCurrentProject()
3196
            cv2.imwrite(os.path.join(project.getTempPath(), 'OUTPUT.png'), appDocData.imgOutput)
3197
        except Exception as ex:
3198
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3199
                                                           sys.exc_info()[-1].tb_lineno)
3200
            self.addMessage.emit(MessageType.Error, message)
3201

    
3202
    '''
3203
        @brief      resetting attribute at secne
3204
        @author     kyoyho
3205
        @date       2018.08.21
3206
    '''
3207
    """
3208
    def checkAttribute(self):
3209
        try:
3210

3211
            docData = AppDocData.instance()
3212
            if not self.graphicsView.hasImage():
3213
                return
3214

3215
            # symbol 경우
3216
            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]
3217
            for item in items:
3218
                attrs = item.attrs
3219
                
3220
                removeAttrList = []
3221
                for attr in attrs:
3222
                    if type(attr) is tuple:
3223
                        continue
3224

3225
                    if attr is None:
3226
                        removeAttrList.append(attr)
3227
                        continue
3228

3229
                    attrInfo = docData.getSymbolAttributeByUID(attr.UID)
3230
                    if attrInfo is None:
3231
                        removeAttrList.append(attr)
3232
                    # 해당 attribute가 맞는지 확인
3233
                    else:
3234
                        attrType = attrInfo.AttributeType
3235
                        _type = type(attr)
3236
                        if attrType == 'Symbol Item':
3237
                            if not issubclass(_type, SymbolSvgItem):
3238
                                removeAttrList.append(attr)
3239
                        elif attrType == 'Text Item':
3240
                            if _type is not QEngineeringTextItem:
3241
                                removeAttrList.append(attr)
3242
                        elif attrType == 'Int':
3243
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
3244
                                removeAttrList.append(attr)
3245
                        elif attrType == 'String':
3246
                            if _type is not UserInputAttribute:
3247
                                removeAttrList.append(attr)
3248

3249
                for attr in removeAttrList:
3250
                    del attrs[attr]
3251

3252
            # Line No Text Item의 경우
3253
            items = [item for item in self.graphicsView.scene().items() if issubclass(type(item), QEngineeringLineNoTextItem)]
3254
            for item in items:
3255
                attrs = item.attrs
3256
                
3257
                removeAttrList = []
3258
                for attr in attrs:
3259
                    if type(attr) is UserInputAttribute:
3260
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
3261
                        if attrInfo is None:
3262
                            removeAttrList.append(attr)
3263

3264
                for attr in removeAttrList:
3265
                    del attrs[attr]
3266

3267
        except Exception as ex:
3268
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
3269
                self.addMessage.emit(MessageType.Error, message)
3270
    """
3271
    '''
3272
        @brief      Check Number
3273
        @author     kyouho
3274
        @date       2018.08.20
3275
    '''
3276

    
3277
    def isNumber(self, num):
3278
        p = re.compile('(^[0-9]+$)')
3279
        result = p.match(num)
3280

    
3281
        if result:
3282
            return True
3283
        else:
3284
            return False
3285

    
3286
    '''
3287
        @brief      find overlap Connector
3288
        @author     kyouho
3289
        @date       2018.08.28
3290
    '''
3291

    
3292
    def findOverlapConnector(self, connectorItem):
3293
        from shapely.geometry import Point
3294
        from EngineeringConnectorItem import QEngineeringConnectorItem
3295
        itemList = []
3296

    
3297
        x = connectorItem.center()[0]
3298
        y = connectorItem.center()[1]
3299

    
3300
        connectors = [item for item in self.graphicsView.scene().items() if
3301
                      type(item) is QEngineeringConnectorItem and item != connectorItem]
3302
        for connector in connectors:
3303
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
3304
                itemList.append(connector.parent)
3305

    
3306
        return itemList
3307

    
3308
    def make_diff_image(self):
3309
        """ make diff image """
3310
        # test
3311

    
3312
        from RecognitionDialog import Worker
3313
        from symbol import Symbol
3314
        import math
3315
        from PIL import Image
3316

    
3317
        app_doc_data = AppDocData.instance()
3318
        img = app_doc_data.imgSrc.copy()
3319

    
3320
        # check break
3321
        symbols = [item for item in self.graphicsView.scene().items() if issubclass(type(item), SymbolSvgItem)]
3322

    
3323
        for symbol in symbols:
3324
            rect = symbol.sceneBoundingRect()
3325
            sName = symbol.name
3326
            sType = symbol.type
3327
            sp = (rect.x(), rect.y())
3328
            w, h = rect.width(), rect.height()
3329
            rotatedAngle = round(math.degrees(symbol.angle))
3330
            detectFlip = symbol.flip
3331

    
3332
            dummySym = Symbol(sName, sType, sp, w, h, 0, 0, 0, rotatedAngle,
3333
                                   1, 0, 1, 0,
3334
                                   ','.join(str(x) for x in [0, 0]),
3335
                                   '/'.join('{},{},{},{}'.format(param[0], param[1], param[2], param[3]) for param in
3336
                                            []),
3337
                                   'dummy', 'dummy', 0, detectFlip=detectFlip,
3338
                                   hasInstrumentLabel=0, text_area='')
3339

    
3340
            Worker.remove_detected_symbol_image(dummySym, img, lock=False)
3341

    
3342
        Image.fromarray(img).show()
3343

    
3344
    #def paintEvent(self, event):
3345
    #    self.refresh_rate += 1
3346
    #    if self.refresh_rate == 3:
3347
    #        super(self.__class__, self).paintEvent(event)
3348
    #        self.refresh_rate = 0
3349

    
3350
if __name__ == '__main__':
3351
    import locale
3352
    from PyQt5.QtCore import QTranslator
3353
    from License import QLicenseDialog
3354
    from ProjectDialog import Ui_Dialog
3355
    from App import App
3356

    
3357
    app = App(sys.argv)
3358
    try:
3359
        if True == QLicenseDialog.check_license_key():
3360
            dlg = Ui_Dialog()
3361
            selectedProject = dlg.showDialog()
3362
            if selectedProject is not None:
3363
                AppDocData.instance().setCurrentProject(selectedProject)
3364
                app._mainWnd = MainWindow.instance()
3365
                app._mainWnd.show()
3366
                sys.exit(app.exec_())
3367
    except Exception as ex:
3368
        print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3369
                                                   sys.exc_info()[-1].tb_lineno))
3370
    finally:
3371
        pass