프로젝트

일반

사용자정보

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

hytos / DTI_PID / DTI_PID / MainWindow.py @ 174022b7

이력 | 보기 | 이력해설 | 다운로드 (146 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
    '''
85
        @brief      initialize
86
        @author 
87
        @date   
88
        @history    humkyung 2018.04.12 add splitter widget
89
                    Jeongwoo 2018.04.27 Add Signal/Slot Connection 'noteNoSingleClicked'
90
                    Jeongwoo 2018.05.09 Initialize Action group
91
                    Jeongwoo 2018.05.10 Add Signal/Slot Connection 'lineNoSingleClicked'
92
                                        Add QActionGroup for managing checkable action
93
                    Jeongwoo 2018.06.27 Add Action [Zoom, Fit Window] and Add new actions into ActionGroup
94
                    humkyung 2018.08.23 add labelStatus to statusbar
95
                    Euisung 2018.09.27 add OCR Training , Signal/Slot Connection 'oCRTrainingClicked'
96
                    Euisung 2018.10.05 add OCR Editor , Signal/Slot Connection 'oCRTrainingEdidorClicked'
97
                    Euisung 2018.10.22 delete Signal/Slot Connection 'oCRTrainingEdidorClicked'
98
    '''
99

    
100
    def __init__(self):
101
        from App import App
102
        from LineTypeConditions import LineTypeConditions
103

    
104
        super(self.__class__, self).__init__()
105
        self.setupUi(self)
106
        self.progress_bar = QProgressBar()
107
        self._label_mouse = QLabel(self.statusbar)
108
        self._label_mouse.setText(self.tr('mouse pos : ({},{})'.format(0, 0)))
109
        self.labelStatus = QLabel(self.statusbar)
110
        self.labelStatus.setText(self.tr('Unrecognition : '))
111
        self.labelSymbolStatus = QLabel(self.statusbar)
112
        self.labelSymbolStatus.setText(self.tr('Symbol : '))
113
        self.labelLineStatus = QLabel(self.statusbar)
114
        self.labelLineStatus.setText(self.tr('Line : '))
115
        self.labelTextStatus = QLabel(self.statusbar)
116
        self.labelTextStatus.setText(self.tr('Text : '))
117

    
118
        self.statusbar.addWidget(self._label_mouse)
119
        self.statusbar.addPermanentWidget(self.progress_bar, 1)
120
        self.statusbar.addPermanentWidget(self.labelSymbolStatus)
121
        self.statusbar.addPermanentWidget(self.labelLineStatus)
122
        self.statusbar.addPermanentWidget(self.labelTextStatus)
123
        self.statusbar.addPermanentWidget(self.labelStatus)
124

    
125
        app_doc_data = AppDocData.instance()
126
        app_doc_data.clear()
127
        project = app_doc_data.getCurrentProject()
128
        _translate = QCoreApplication.translate
129
        version = QCoreApplication.applicationVersion()
130
        # set title
131
        self.setWindowTitle(self.title)
132

    
133
        # save timer
134
        self.save_timer = None
135

    
136
        self.lineComboBox = QComboBox(self.toolBar)
137
        for condition in LineTypeConditions.items():
138
            self.lineComboBox.addItem(condition.name)
139

    
140
        configs = app_doc_data.getConfigs('Line', 'Default Type')
141
        value = configs[0].value if 1 == len(configs) else ''
142
        if value:
143
            at = self.lineComboBox.findText(value)
144
            self.lineComboBox.setCurrentIndex(at)
145
        else:
146
            at = self.lineComboBox.findText('Secondary')
147
            self.lineComboBox.setCurrentIndex(at)
148

    
149
        self.toolBar.insertWidget(self.actionOCR, self.lineComboBox)
150
        self.toolBar.insertSeparator(self.actionOCR)
151

    
152
        self.packageComboBox = QComboBox(self.toolBar)
153
        self.packageComboBox.addItems(['Equipment Package', 'Vendor Package'])
154
        self.toolBar.insertWidget(self.actionValidate, self.packageComboBox)
155

    
156
        self._scene = QtImageViewerScene(self)
157

    
158
        self.graphicsView = QtImageViewer(self)
159
        self.graphicsView.setParent(self.centralwidget)
160
        self.graphicsView.useDefaultCommand()  # USE DEFAULT COMMAND
161
        self.graphicsView.setMouseTracking(True)
162
        self.graphicsView.viewport().installEventFilter(self)
163
        self.graphicsView.setScene(self._scene)
164

    
165
        self._display_widget = QDisplayWidget()
166
        self._display_widget.radioButtonByGroup.toggled.connect(self.display_colors)
167
        self._display_widget.radioButtonByGroup.toggled.connect(self.display_colors)
168
        self.EditToolbar.addWidget(self._display_widget)
169
        self._display_widget.radioButtonByGroup.setChecked(True) \
170
            if DisplayColors.instance().option == DisplayOptions.DisplayByLineNo else \
171
            self._display_widget.radioButtonByType.setChecked(True)
172

    
173
        self.verticalLayout.addWidget(self.graphicsView)
174

    
175
        # Add Custom TreeWidget
176
        self.symbolTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
177
        self.symbolTreeWidget.header().hide()
178
        self.verticalLayoutSymbolTree.addWidget(self.symbolTreeWidget)
179
        self.lineEditFilter.textChanged.connect(self.on_search_text_changed)
180

    
181
        from LibraryItem import LibraryItemWidget
182
        self.libraryWidget = LibraryItemWidget(symbol_tree_widget=self.symbolTreeWidget)
183
        self.verticalLayoutLibrary.addWidget(self.libraryWidget)
184
        # Add Custom Property TableWidget
185
        self.propertyTableWidget = SymbolPropertyTableWidget.QSymbolPropertyTableWidget()
186
        self.verticalLayoutSymbolProperty.addWidget(self.propertyTableWidget)
187
        self.symbolTreeWidget.singleClicked.connect(self.propertyTableWidget.getClickedSymbol)
188

    
189
        self.splitterSymbol.setSizes([500, 300])
190

    
191
        # Add Custom Result Tree Widget (Symbol Explorer)
192
        self.itemTreeWidget = ItemTreeWidget.QItemTreeWidget(self.graphicsView)
193
        self.itemTreeWidget.header().hide()
194
        self.symbolExplorerVerticalLayout.addWidget(self.itemTreeWidget)
195

    
196
        # Add Empty Widget
197
        self.resultPropertyTableWidget = ItemPropertyTableWidget.QItemPropertyTableWidget(self)
198
        self.symbolExplorerVerticalLayout.addWidget(self.resultPropertyTableWidget)
199
        #self.itemTreeWidget.singleClicked.connect(self.resultPropertyTableWidget.show_item_property)
200
        self.itemTreeWidget.noteNoSingleClicked.connect(self.resultPropertyTableWidget.onNoteClicked)
201
        #self.itemTreeWidget.lineNoSingleClicked.connect(self.resultPropertyTableWidget.onLineNoClicked)
202
        self.itemTreeWidget.drawingClicked.connect(self.resultPropertyTableWidget.onDrawingClicked)
203
        # add splitter widget
204
        splitter = QSplitter(Qt.Vertical)
205
        splitter.addWidget(self.itemTreeWidget)
206
        splitter.addWidget(self.resultPropertyTableWidget)
207
        self.symbolExplorerVerticalLayout.addWidget(splitter)
208
        # up to here
209

    
210
        # Initialize Action group
211
        self.actionGroup = QActionGroup(self)
212
        self.actionGroup.addAction(self.actionRecognition)
213
        self.actionGroup.addAction(self.actionLineRecognition)
214
        self.actionGroup.addAction(self.actionLine)
215
        self.actionGroup.addAction(self.actionGenerateOutput)
216
        self.actionGroup.addAction(self.actionOCR)
217
        self.actionGroup.addAction(self.actionZoom)
218
        self.actionGroup.addAction(self.actionFitWindow)
219
        self.actionGroup.addAction(self.actionSave)
220
        self.actionGroup.addAction(self.actionValidate)
221
        self.actionGroup.addAction(self.actionVendor)
222
        self.actionGroup.triggered.connect(self.actionGroupTriggered)
223

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

    
278
        configs = app_doc_data.getAppConfigs('app', 'mode')
279
        if configs and 1 == len(configs) and 'advanced' == configs[0].value:
280
            self.actionOCR_Training.triggered.connect(self.oCRTrainingClicked)
281
            self.actionSymbol_Training.triggered.connect(self.symbolTrainingClicked)
282
            self.actionMake_Label_Data.triggered.connect(self.make_label_data)
283
        else:
284
            # self.actionOCR_Training.setVisible(False)
285
            # self.actionSymbol_Training.setVisible(False)
286
            self.menu_2.setEnabled(False)  # Data
287
            self.menu_4.setEnabled(False)  # Tool
288
            self.actionConfiguration.setVisible(False)
289
            self.pushButtonCreateSymbol.setVisible(False)
290
            self.pushButtonDetectSymbol.setVisible(False)
291

    
292
        self.delimiter = '"'
293

    
294
        self.resizeDocks({self.dockWidget}, {self.dockWidgetObjectExplorer.sizeHint().width()}, Qt.Horizontal)
295

    
296
        self.treeWidgetDrawingList.setHeaderHidden(False)
297
        self.treeWidgetDrawingList.header().setStretchLastSection(False)
298
        self.treeWidgetDrawingList.setHeaderLabels([self.tr('Name'), self.tr('DateTime')])
299
        self.treeWidgetDrawingList.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
300
        self.treeWidgetDrawingList.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
301
        self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing)
302
        self.load_drawing_list()
303

    
304
        # load stylesheet file list
305
        stylesheet_name = QtWidgets.qApp.stylesheet_name
306
        files = [os.path.splitext(file)[0] for file in os.listdir(os.path.dirname(os.path.realpath(__file__))) if
307
                 os.path.splitext(file)[1] == '.qss']
308
        for file in files:
309
            action = self.menuTheme.addAction(file)
310
            action.setCheckable(True)
311
            action.setChecked(True) if stylesheet_name == file else action.setChecked(False)
312
            action.triggered.connect(partial(self.load_stylesheet, file))
313
        # up to here
314

    
315
        # load language files
316
        language_name = QtWidgets.qApp.language_name
317
        files = ['en_us']  # english is default language
318
        files.extend([os.path.splitext(file)[0] for file in
319
                      os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate')) if
320
                      os.path.splitext(file)[1] == '.qm'])
321
        for file in files:
322
            action = self.menuLanguage.addAction(file)
323
            action.setCheckable(True)
324
            action.setChecked(True) if language_name.lower() == file.lower() else action.setChecked(False)
325
            action.triggered.connect(partial(self.load_language, file))
326
        # up to here
327

    
328
        # inconsistency table
329
        self.tableWidgetInconsistency.setColumnCount(3)
330
        self.tableWidgetInconsistency.setHorizontalHeaderLabels(['Owner', 'Type', 'Message'])
331
        self.tableWidgetInconsistency.setEditTriggers(QAbstractItemView.NoEditTriggers)
332
        self.tableWidgetInconsistency.itemClicked.connect(self.inconsistencyItemClickEvent)
333
        self.tableWidgetInconsistency.keyPressEvent = self.inconsistencyTableKeyPressEvent
334
        self.tableWidgetInconsistency.setSortingEnabled(True)
335

    
336
        self.read_settings()
337

    
338
    @property
339
    def title(self) -> str:
340
        """return window title"""
341

    
342
        from App import App
343

    
344
        app_doc_data = AppDocData.instance()
345
        project = app_doc_data.getCurrentProject()
346
        version = QCoreApplication.applicationVersion()
347
        title = f"{App.NAME}({version}) - {project.name}:" \
348
                f"{app_doc_data.activeDrawing.name if app_doc_data.activeDrawing else ''}"
349
        #title = f"{App.NAME} : ID2 " \
350
        #        f"{app_doc_data.activeDrawing.name if app_doc_data.activeDrawing else ''}"
351

    
352
        return title
353

    
354
    @property
355
    def scene(self):
356
        """getter scene"""
357
        return self._scene
358

    
359
    def eventFilter(self, source, event):
360
        """display mouse position of graphics view"""
361
        try:
362
            if event.type() == QEvent.MouseMove:
363
                self.current_pos = self.graphicsView.mapToScene(event.pos())
364
                self._label_mouse.setText(
365
                    'mouse pos : ({},{})'.format(round(self.current_pos.x()), round(self.current_pos.y())))
366
        except Exception as ex:
367
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
368
                                                           sys.exc_info()[-1].tb_lineno)
369
            self.addMessage.emit(MessageType.Error, message)
370

    
371
        return QWidget.eventFilter(self, source, event)
372

    
373
    def closeEvent(self, event):
374
        """save geometry and state and ask user to save drawing which is modified"""
375

    
376
        self.settings.setValue('geometry', self.saveGeometry())
377
        self.settings.setValue('windowState', self.saveState())
378
        # TODO: need to modify
379
        # self.save_drawing_if_necessary()
380
        AppDocData.instance().clear()
381
        event.accept()
382

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
529
    def load_drawing_list(self):
530
        """load p&id drawing list"""
531
        from Drawing import Drawing
532

    
533
        try:
534
            app_doc_data = AppDocData.instance()
535
            drawings = app_doc_data.getDrawings()
536

    
537
            self.treeWidgetDrawingList.clear()
538
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList,
539
                                                              [self.tr('P&ID Drawings'), ''])
540
            self.treeWidgetDrawingList.root.setFlags(
541
                self.treeWidgetDrawingList.root.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
542
            self.treeWidgetDrawingList.root.setCheckState(0, Qt.Unchecked)
543
            files = app_doc_data.getDrawingFileList()
544

    
545
            # self.progress_bar.setMaximum(len(files))
546
            count = 0
547
            # self.progress_bar.setValue(count)
548
            for file in files:
549
                x = [drawing for drawing in drawings if drawing.name == file]
550
                if not x or not x[0].UID:
551
                    drawing = Drawing(None, file, None)
552
                    drawings.append(drawing)
553
                else:
554
                    drawing = x[0]
555

    
556
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [file, drawing.datetime])
557
                item.setIcon(0, QIcon(':newPrefix/image.png'))
558
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
559
                item.setCheckState(0, Qt.Unchecked)
560
                item.setData(Qt.UserRole, 0, drawing)
561

    
562
                count += 1
563
                # self.progress_bar.setValue(count)
564
                # QApplication.processEvents()
565

    
566
            self.treeWidgetDrawingList.root.setText(0, self.tr('P&ID Drawings') +
567
                                                    f"({self.treeWidgetDrawingList.root.childCount()})")
568
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
569
            self.treeWidgetDrawingList.root.sortChildren(0, Qt.AscendingOrder)
570
            self.treeWidgetDrawingList.resizeColumnToContents(0)
571

    
572
            app_doc_data.saveDrawings(drawings)
573
        except Exception as ex:
574
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
575
                                                           sys.exc_info()[-1].tb_lineno)
576
            self.addMessage.emit(MessageType.Error, message)
577
        finally:
578
            self.progress_bar.setValue(self.progress_bar.maximum())
579

    
580
    def open_selected_drawing(self, item, column):
581
        """open selected p&id drawing"""
582

    
583
        app_doc_data = AppDocData.instance()
584
        drawing = item.data(Qt.UserRole, 0)
585
        if drawing:
586
            # uncheck all drawing tree item
587
            drawing_top = self.treeWidgetDrawingList.topLevelItem(0)
588
            count = drawing_top.childCount()
589
            for idx in range(count):
590
                child = drawing_top.child(idx)
591
                child.setCheckState(column, Qt.Unchecked)
592
            # up to here
593

    
594
            drawing.image = None
595
            self.open_image_drawing(drawing)
596
            item.setCheckState(column, Qt.Checked)
597

    
598
    def show_detect_symbol_dialog(self):
599
        from DetectSymbolDialog import QDetectSymbolDialog
600

    
601
        dlg = QDetectSymbolDialog(self)
602
        dlg.exec_()
603

    
604
    '''
605
        @brief      OCR Editor
606
        @author     euisung
607
        @date       2018.10.05
608
        @history    2018.10.16 euisung      no more used, Integrated with oCRTrainingClicked
609
    '''
610

    
611
    def oCRTrainingEdidorClicked(self):
612
        from TrainingEditorDialog import QTrainingEditorDialog
613

    
614
        try:
615
            dialog = QTrainingEditorDialog(self)
616
            dialog.exec_()
617
        except Exception as ex:
618
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
619
                                                           sys.exc_info()[-1].tb_lineno)
620
            self.addMessage.emit(MessageType.Error, message)
621

    
622
        return
623

    
624
    '''
625
        @brief      OCR Training
626
        @author     euisung
627
        @date       2018.09.27
628
        @history    euisung 2018.10.16 TrainingListDialog -> TrainingImageListDialog
629
    '''
630

    
631
    def oCRTrainingClicked(self):
632
        try:
633
            dialog = QTrainingImageListDialog(self)
634
            dialog.exec_()
635
        except Exception as ex:
636
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
637
                                                           sys.exc_info()[-1].tb_lineno)
638
            self.addMessage.emit(MessageType.Error, message)
639

    
640
    def symbolTrainingClicked(self):
641
        try:
642
            dialog = QTrainingSymbolImageListDialog(self)
643
            dialog.show()
644
            dialog.exec_()
645
        except Exception as ex:
646
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
647
                                                           sys.exc_info()[-1].tb_lineno)
648
            self.addMessage.emit(MessageType.Error, message)
649

    
650
    def findReplaceTextClicked(self):
651
        """pop up find and replace dialog"""
652
        if not self.graphicsView.hasImage():
653
            self.showImageSelectionMessageBox()
654
            return
655

    
656
        from TextItemEditDialog import QTextItemEditDialog
657

    
658
        self.dlgTextItemEdit = QTextItemEditDialog(self)
659
        self.dlgTextItemEdit.show()
660
        self.dlgTextItemEdit.exec_()
661

    
662
    def ReplaceInsertSymbolClicked(self):
663
        """pop up replace and insert dialog"""
664
        if not self.graphicsView.hasImage():
665
            self.showImageSelectionMessageBox()
666
            return
667

    
668
        from ReplaceSymbolDialog import QReplaceSymbolDialog
669

    
670
        self.dlgReplace = QReplaceSymbolDialog(self)
671
        self.dlgReplace.show()
672
        self.dlgReplace.exec_()
673

    
674
    def on_recognize_line(self):
675
        """recognize lines in selected area"""
676
        from RecognizeLineCommand import RecognizeLineCommand
677

    
678
        if not self.graphicsView.hasImage():
679
            self.actionOCR.setChecked(False)
680
            self.showImageSelectionMessageBox()
681
            return
682

    
683
        cmd = RecognizeLineCommand(self.graphicsView)
684
        cmd.onSuccess.connect(self.on_success_to_recognize_line)
685
        cmd.onRejected.connect(self.onCommandRejected)
686
        self.graphicsView.command = cmd
687

    
688
    '''
689
            @brief      show text recognition dialog
690
            @author     humkyung
691
            @date       2018.08.08
692
        '''
693

    
694
    def on_success_to_recognize_line(self, x, y, width, height):
695
        import io
696
        from LineDetector import LineDetector
697
        from EngineeringGraphicsLineItem import QEngineeringGraphicsLineItem
698

    
699
        try:
700
            image = self.graphicsView.image().copy(x, y, width, height)
701
            buffer = QBuffer()
702
            buffer.open(QBuffer.ReadWrite)
703
            image.save(buffer, "PNG")
704
            pyImage = Image.open(io.BytesIO(buffer.data()))
705
            img = np.array(pyImage)
706
            img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
707

    
708
            detector = LineDetector(img)
709
            lines = detector.detect_line_without_symbol()
710
            for line in lines:
711
                vertices = [[line[0][0] + x, line[0][1] + y], [line[1][0] + x, line[1][1] + y]]
712
                line_item = QEngineeringGraphicsLineItem(vertices)
713
                self.graphicsView.scene().addItem(line_item)
714

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

    
720
    def display_number_of_items(self):
721
        """display count of symbol, line, text"""
722

    
723
        items = [item for item in self.graphicsView.scene().items() if type(item) is QEngineeringUnknownItem]
724
        if len(items) > 0:
725
            self.labelStatus.setText(
726
                "<font color='red'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
727
        else:
728
            self.labelStatus.setText(
729
                "<font color='black'>" + self.tr('Unrecognition') + " : {}</font>".format(len(items)))
730

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

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

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

    
741
        self.itemTreeWidget.sceneChanged(self.graphicsView.scene().items())
742

    
743
    def dbUpdate(self):
744
        """ no more used """
745
        """db update when save or recognition"""
746

    
747
        try:
748
            appDocData = AppDocData.instance()
749
            items = appDocData.allItems
750

    
751
            '''
752
            titleBlockProps = appDocData.getTitleBlockProperties()
753
            titleBlockItems = []
754
            for item in items:
755
                # if type(item) is QEngineeringLineNoTextItem:
756
                #    item.saveLineData()
757
                if type(item) is QEngineeringTextItem:
758
                    for titleBlockProp in titleBlockProps:
759
                        if item.area == titleBlockProp[0]:
760
                            titleBlockItems.append(item)
761
            '''
762

    
763
            # unknown item is not saved now for performance
764
            db_items = [item for item in items if issubclass(type(item), QEngineeringAbstractItem) and
765
                        type(item) is not QGraphicsBoundingBoxItem and
766
                        type(item) is not QEngineeringErrorItem and
767
                        type(item) is not QEngineeringLineNoTextItem and
768
                        type(item) is not QEngineeringUnknownItem]
769
            db_items.extend([item for item in items if type(item) is QEngineeringLineNoTextItem])
770
            db_items.extend([line for line in appDocData.tracerLineNos if type(line) is QEngineeringTrimLineNoTextItem])
771
            # db_items.extend(titleBlockItems)
772
            configs = appDocData.getConfigs('Data Save', 'Unknown Xml Only')
773
            if configs and int(configs[0].value) is -1:
774
                db_items.extend([item for item in items if type(item) is QEngineeringUnknownItem])
775

    
776
            '''
777
            dbItems = [item for item in items if
778
                       type(item) is QEngineeringInstrumentItem or type(item) is QEngineeringEquipmentItem or type(
779
                           item) is QEngineeringReducerItem or \
780
                       type(item) is QEngineeringNoteItem or type(item) is SymbolSvgItem or type(
781
                           item) is QEngineeringLineNoTextItem or type(
782
                           item) is QEngineeringVendorItem] + titleBlockItems
783
            '''
784
            appDocData.saveToDatabase(db_items)
785
        except Exception as ex:
786
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
787
                                                           sys.exc_info()[-1].tb_lineno)
788
            self.addMessage.emit(MessageType.Error, message)
789

    
790
    def save_drawing_if_necessary(self):
791
        """ask to user to save drawing or not when drawing is modified"""
792

    
793
        app_doc_data = AppDocData.instance()
794
        if app_doc_data.activeDrawing and app_doc_data.activeDrawing.modified:
795
            #if QMessageBox.Yes == QMessageBox.question(self, self.tr("Question"),
796
            #                                           self.tr("Do you want to save drawing?"),
797
            #                                           QMessageBox.Yes | QMessageBox.No):
798
            #    self.actionSaveCliked()
799
            #    return True
800
            if QMessageBox.Ignore == QMessageBox.question(self, self.tr('Continue?'),
801
                                                       self.tr('Changes may not have been saved.'),
802
                                                       QMessageBox.Ignore | QMessageBox.Cancel):
803
                return False
804
            return True
805

    
806
    '''
807
        @brief      action save click event
808
        @author     kyouho
809
        @date       2018.08.09
810
        @history    2018.11.02      euisung     add line data list db update
811
                    humkyung save saved time to database
812
                    2018.11.05      euisung     add note data list db update
813
                    2018.11.05      euisung     add db delete process before save
814
                    2018.11.12      euisung     db part move new method to dbUpdate
815
    '''
816

    
817
    def actionSaveCliked(self):
818
        from EngineeringAbstractItem import QEngineeringAbstractItem
819
        from SaveWorkCommand import SaveWorkCommand
820

    
821
        try:
822
            if not self.actionSave.isEnabled():
823
                return
824
            self.actionSave.setEnabled(False)
825

    
826
            # save alarm
827
            self.save_alarm_enable(False)
828

    
829
            app_doc_data = AppDocData.instance()
830
            if app_doc_data.imgName is None:
831
                self.showImageSelectionMessageBox()
832
                return
833

    
834
            app_doc_data.clearItemList(False)
835

    
836
            items = self.graphicsView.scene().items()
837

    
838
            '''
839
            # for check line disappear bug
840
            disappear_lines = [line for line in app_doc_data.lines if line not in items]
841
            '''
842

    
843
            '''
844
            for item in items:
845
                if issubclass(type(item), QEngineeringAbstractItem):
846
                    app_doc_data.allItems.append(item)
847
                    if issubclass(type(item), QEngineeringTextItem):
848
                        app_doc_data.texts.append(item)
849
            '''
850

    
851
            '''
852
            # for check line disappear bug
853
            if disappear_lines:
854
                app_doc_data.allItems.extend(disappear_lines)
855
                for dis_line in disappear_lines:
856
                    self.addMessage.emit(MessageType.Check, f"disapper line from scene : {str(dis_line)}")
857
            '''
858

    
859
            '''
860
            itemTypes = []
861
            for item in items:
862
                typeExist = False
863
                for itemType in itemTypes:
864
                    if type(item) is itemType:
865
                        typeExist = True
866
                        break
867
                if not typeExist:
868
                    itemTypes.append(type(item))
869
            '''
870

    
871
            self._save_work_cmd = SaveWorkCommand(self.graphicsView.scene())
872
            self._save_work_cmd.show_progress.connect(self.progress_bar.setValue)
873
            self._save_work_cmd.display_message.connect(self.onAddMessage)
874
            self._save_work_cmd.finished.connect(self.save_finished)
875

    
876
            self._save_work_cmd.start()
877
        except Exception as ex:
878
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
879
                                                           sys.exc_info()[-1].tb_lineno)
880
            self.addMessage.emit(MessageType.Error, message)
881

    
882
    def save_finished(self):
883
        """reload drawing list"""
884

    
885
        self._save_work_cmd.show_progress.emit(100)
886
        QMessageBox.about(self.graphicsView, self.tr('Information'), self._save_work_cmd.resultStr)
887
        self.load_drawing_list()
888

    
889
        app_doc_data = AppDocData.instance()
890
        app_doc_data.activeDrawing.modified = False
891
        title = self.windowTitle()
892
        self.setWindowTitle(title[:-1] if title[-1] == '*' else title)
893

    
894
        self.actionSave.setEnabled(True)
895
        
896
        # save alarm
897
        self.save_alarm_enable(True)
898

    
899
    '''
900
        @brief      refresh resultPropertyTableWidget
901
        @author     kyouho
902
        @date       2018.07.19
903
    '''
904

    
905
    def refreshResultPropertyTableWidget(self):
906
        items = self.graphicsView.scene().selectedItems()
907
        if len(items) == 1:
908
            self.resultPropertyTableWidget.show_item_property(items[0])
909

    
910
    '''
911
        @brief  add message listwidget
912
        @author humkyung
913
        @date   2018.07.31
914
    '''
915

    
916
    def onAddMessage(self, messageType, message):
917
        from AppDocData import MessageType
918

    
919
        try:
920
            current = QDateTime.currentDateTime()
921

    
922
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
923
            item.setFlags(item.flags() | Qt.ItemIsEditable)
924
            if messageType == MessageType.Error:
925
                item.setBackground(Qt.red)
926
            elif messageType == 'check':
927
                item.setBackground(Qt.yellow)
928

    
929
            self.listWidgetLog.insertItem(0, item)
930
        except Exception as ex:
931
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
932
                                                       sys.exc_info()[-1].tb_lineno))
933

    
934
    '''
935
        @brief      clear log
936
        @author     humkyung
937
        @date       2018.08.01
938
    '''
939

    
940
    def onClearLog(self):
941
        self.listWidgetLog.clear()
942

    
943
    '''
944
        @brief      rotate selected symbol
945
        @author     humkyung
946
        @date       2018.08.15
947
    '''
948

    
949
    def onRotate(self, action):
950
        selected = [item for item in self.graphicsView.scene().selectedItems() if issubclass(type(item), SymbolSvgItem)]
951
        if len(selected) == 1:
952
            from RotateCommand import RotateCommand
953
            self.graphicsView.scene()._undo_stack.push(RotateCommand(self.graphicsView.scene(), selected))
954

    
955
    '''
956
        @brief      Area Zoom
957
        @author     Jeongwoo
958
        @date       2018.06.27
959
        @history    connect command's rejected signal
960
    '''
961

    
962
    def onAreaZoom(self, action):
963
        if self.actionZoom.isChecked():
964
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
965
            cmd.onRejected.connect(self.onCommandRejected)
966
            self.graphicsView.command = cmd
967

    
968
    def onVendor(self, action):
969
        """make vendor package area"""
970

    
971
        if not self.graphicsView.hasImage():
972
            self.actionVendor.setChecked(False)
973
            self.showImageSelectionMessageBox()
974
            return
975

    
976
        self.actionVendor.setChecked(True)
977
        if not hasattr(self.actionVendor, 'tag'):
978
            self.actionVendor.tag = PlacePolygonCommand.PlacePolygonCommand(self.graphicsView)
979
            self.actionVendor.tag.onSuccess.connect(self.onVendorCreated)
980
            self.actionVendor.tag.onRejected.connect(self.onCommandRejected)
981

    
982
        self.graphicsView.command = self.actionVendor.tag
983

    
984
    def onVendorCreated(self):
985
        """add created vendor polygon area to scene"""
986

    
987
        try:
988
            count = len(self.actionVendor.tag._polyline._vertices)
989
            if count > 2:
990
                points = []
991
                for point in self.actionVendor.tag._polyline._vertices:
992
                    points.append(QPoint(round(point[0]), round(point[1])))
993
                polygon = QPolygonF(points)
994
                item = QEngineeringVendorItem(polygon, pack_type=self.packageComboBox.currentText())
995
                item.area = 'Drawing'
996
                item.transfer.onRemoved.connect(self.itemRemoved)
997
                self.graphicsView.scene().addItem(item)
998
        finally:
999
            self.graphicsView.scene().removeItem(self.actionVendor.tag._polyline)
1000
            self.actionVendor.tag.reset()
1001

    
1002
    '''
1003
        @brief      Fit Window
1004
        @author     Jeongwoo
1005
        @date       2018.06.27
1006
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
1007
    '''
1008

    
1009
    def fitWindow(self, action):
1010
        self.graphicsView.useDefaultCommand()
1011
        self.graphicsView.zoomImageInit()
1012

    
1013
    def scene_changed(self):
1014
        """update modified flag"""
1015

    
1016
        self.display_number_of_items()
1017

    
1018
        app_doc_data = AppDocData.instance()
1019
        app_doc_data.activeDrawing.modified = True
1020
        title = self.windowTitle()
1021
        self.setWindowTitle(title if title[-1] == '*' else title + '*')
1022

    
1023
    def onConvertPDFToImage(self):
1024
        """convert to selected pdf to image"""
1025
        import os
1026

    
1027
        try:
1028
            file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'bin64', 'PDF_TO_IMAGE.exe')
1029
            os.startfile(file_path)
1030
        except Exception as ex:
1031
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1032
                                                           sys.exc_info()[-1].tb_lineno)
1033
            self.addMessage.emit(MessageType.Error, message)
1034

    
1035
    def onImportTextFromCAD(self):
1036
        """ import text from cad """
1037
        try:
1038
            self.onCommandRejected()
1039
            dialog = QImportTextFromCADDialog(self)
1040
            dialog.show()
1041
            dialog.exec_()
1042
        except Exception as ex:
1043
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1044
                                                           sys.exc_info()[-1].tb_lineno)
1045
            self.addMessage.emit(MessageType.Error, message)
1046

    
1047
    def onSymbolThickness(self):
1048
        """ symbol thickness reinforcement by using configuration filter drawing dilate size """
1049
        try:
1050
            self.onCommandRejected()
1051
            dialog = QSymbolThicknessDialog(self)
1052
            dialog.exec_()
1053
        except Exception as ex:
1054
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1055
                                                           sys.exc_info()[-1].tb_lineno)
1056
            self.addMessage.emit(MessageType.Error, message)
1057

    
1058
    def on_help(self):
1059
        """ open help file """
1060
        import os
1061

    
1062
        try:
1063
            help_file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ID2 User Manual.pdf')
1064
            os.system('"{}"'.format(help_file_path))
1065
        except Exception as ex:
1066
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1067
                                                           sys.exc_info()[-1].tb_lineno)
1068
            self.addMessage.emit(MessageType.Error, message)
1069

    
1070
    def onSelectionChanged(self):
1071
        """selection changed"""
1072
        items = [item for item in self.graphicsView.scene().selectedItems() if issubclass(type(item), SymbolSvgItem) or
1073
                 type(item) is QEngineeringLineItem or issubclass(type(item), QEngineeringTextItem) or
1074
                 type(item) is QEngineeringUnknownItem or type(item) is QEngineeringVendorItem]
1075
        if items:
1076
            lineNos = [item for item in items if type(item) is QEngineeringLineNoTextItem]
1077
            item = items[-1] if not lineNos else lineNos[0]
1078
            self.itemTreeWidget.findItem(item)
1079
            self.resultPropertyTableWidget.show_item_property(item)
1080
            if type(item) is QEngineeringErrorItem:
1081
                for index in range(self.tableWidgetInconsistency.rowCount()):
1082
                    if self.tableWidgetInconsistency.item(index, 1).tag is item:
1083
                        self.tableWidgetInconsistency.selectRow(index)
1084
                        break
1085
            if issubclass(type(item), SymbolSvgItem):
1086
                pass
1087
                #self.symbolTreeWidget.select_symbol(item)
1088
        else:
1089
            self.resultPropertyTableWidget.show_item_property(None)
1090

    
1091
    '''
1092
        @brief      Initialize scene and itemTreeWidget
1093
        @author     Jeongwoo
1094
        @date       2018.06.14
1095
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
1096
    '''
1097

    
1098
    def on_initialize_scene(self, action):
1099
        if not self.graphicsView.hasImage():
1100
            self.showImageSelectionMessageBox()
1101

    
1102
            return
1103

    
1104
        try:
1105
            msg = QMessageBox()
1106
            msg.setIcon(QMessageBox.Critical)
1107
            msg.setText(self.tr('Do you want to remove all items?\nThis work cannot be recovered.'))
1108
            msg.setWindowTitle(self.tr("Initialize"))
1109
            msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
1110
            if QMessageBox.Ok == msg.exec_():
1111
                app_doc_data = AppDocData.instance()
1112
                app_doc_data.clearItemList(True)
1113

    
1114
                scene = self.graphicsView.scene()
1115
                pixmap = self.graphicsView.getPixmapHandle()
1116
                scene.removeItem(pixmap)    # disconnect pixmap from scene
1117
                scene.clear()               # remove all items from scene and then delete them
1118
                scene.addItem(pixmap)       # add pixmap
1119

    
1120
                if self.path is not None:
1121
                    baseName = os.path.basename(self.path)
1122
                    self.itemTreeWidget.setCurrentPID(baseName)
1123

    
1124
        except Exception as ex:
1125
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1126
                                                           sys.exc_info()[-1].tb_lineno)
1127
            self.addMessage.emit(MessageType.Error, message)
1128

    
1129
    '''
1130
        @brief      Manage Checkable Action statement
1131
        @author     Jeongwoo
1132
        @date       2018.05.10
1133
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
1134
    '''
1135

    
1136
    def actionGroupTriggered(self, action):
1137
        if hasattr(self.actionLine, 'tag'):
1138
            self.actionLine.tag.onRejected.emit(None)
1139

    
1140
        if hasattr(self.actionVendor, 'tag'):
1141
            self.actionVendor.tag.onRejected.emit(None)
1142

    
1143
        if self.graphicsView.command is not None:
1144
            self.graphicsView.useDefaultCommand()
1145

    
1146
        for _action in self.actionGroup.actions():
1147
            _action.setChecked(False)
1148

    
1149
        action.setChecked(True)
1150

    
1151
    '''
1152
        @brief      Create Equipment
1153
        @author     Jeongwoo
1154
        @date       18.05.03
1155
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
1156
    '''
1157

    
1158
    def createEquipment(self):
1159
        if not self.graphicsView.hasImage():
1160
            self.actionEquipment.setChecked(False)
1161
            self.showImageSelectionMessageBox()
1162
            return
1163
        if self.actionEquipment.isChecked():
1164
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget,
1165
                                                                                self.symbolTreeWidget)
1166
        else:
1167
            self.graphicsView.useDefaultCommand()
1168

    
1169
    '''
1170
        @brief      Create Nozzle
1171
        @author     Jeongwoo
1172
        @date       2018.05.03
1173
        @history    2018.05.04  Jeongwoo    Add Parameter on CreateSymbolCommand
1174
    '''
1175

    
1176
    def createNozzle(self):
1177
        if not self.graphicsView.hasImage():
1178
            self.actionNozzle.setChecked(False)
1179
            self.showImageSelectionMessageBox()
1180
            return
1181
        if self.actionNozzle.isChecked():
1182
            self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget,
1183
                                                                                self.symbolTreeWidget)
1184
        else:
1185
            self.graphicsView.useDefaultCommand()
1186

    
1187
    '''
1188
        @brief      Area OCR
1189
        @author     Jeongwoo
1190
        @date       18.04.18
1191
        @history    2018.05.02  Jeongwoo    Change graphicsView.command by actionOCR checked state
1192
                                            Show MessageBox when imageviewer doesn't have image
1193
    '''
1194

    
1195
    def onAreaOcr(self):
1196
        if not self.graphicsView.hasImage():
1197
            self.actionOCR.setChecked(False)
1198
            self.showImageSelectionMessageBox()
1199
            return
1200

    
1201
        if self.actionOCR.isChecked():
1202
            cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView)
1203
            cmd.onSuccess.connect(self.onRecognizeText)
1204
            cmd.onRejected.connect(self.onCommandRejected)
1205
            self.graphicsView.command = cmd
1206
        else:
1207
            self.graphicsView.useDefaultCommand()
1208

    
1209
    '''
1210
        @brief      show text recognition dialog
1211
        @author     humkyung
1212
        @date       2018.08.08
1213
    '''
1214

    
1215
    def onRecognizeText(self, x, y, width, height):
1216
        from OcrResultDialog import QOcrResultDialog
1217
        from Area import Area
1218

    
1219
        try:
1220
            app_doc_data = AppDocData.instance()
1221

    
1222
            modifiers = QApplication.keyboardModifiers()
1223
            image = self.graphicsView.image().copy(x, y, width, height)
1224
            dialog = QOcrResultDialog(self, image, QRectF(x, y, width, height),
1225
                                      format=QOcrResultDialog.Format.Table if modifiers == Qt.AltModifier else QOcrResultDialog.Format.Normal)
1226
            if modifiers == Qt.ControlModifier:
1227
                return
1228
            (res, textInfoList) = dialog.showDialog()
1229
            if QDialog.Accepted == res and textInfoList:
1230
                for textInfo in textInfoList:
1231
                    item = QEngineeringTextItem.create_text_with(self.graphicsView.scene(), textInfo)
1232
                    if item:
1233
                        item.setDefaultTextColor(Qt.blue)
1234
                        item.transfer.onRemoved.connect(self.itemRemoved)
1235

    
1236
                        area_list = app_doc_data.getAreaList()
1237
                        title_area_list = app_doc_data.getTitleBlockProperties()
1238
                        title_list = []
1239
                        if title_area_list:
1240
                            for title_area in title_area_list:
1241
                                area = Area(title_area[0])
1242
                                area.parse(title_area[2])
1243
                                title_list.append(area)
1244
                        for area in area_list + title_list:
1245
                            pt = [item.sceneBoundingRect().center().x(), item.sceneBoundingRect().center().y()]
1246
                            if area.contains(pt):
1247
                                item.area = area.name
1248
                                break
1249
                    else:
1250
                        self.addMessage.emit(MessageType.Normal, self.tr('Fail to create text.'))
1251
            elif QDialog.Accepted == res and not textInfoList:
1252
                QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("Fail to recognize text"))
1253
        except Exception as ex:
1254
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1255
                                                           sys.exc_info()[-1].tb_lineno)
1256
            self.addMessage.emit(MessageType.Error, message)
1257

    
1258
    '''
1259
        @brief  area configuration
1260
    '''
1261

    
1262
    def areaConfiguration(self):
1263
        from ConfigurationAreaDialog import QConfigurationAreaDialog
1264
        if not self.graphicsView.hasImage():
1265
            self.showImageSelectionMessageBox()
1266
            return
1267
        self.onCommandRejected()
1268
        self.dlgConfigurationArea = QConfigurationAreaDialog(self)
1269
        self.dlgConfigurationArea.show()
1270
        self.dlgConfigurationArea.exec_()
1271

    
1272
    '''
1273
        @brief  configuration
1274
    '''
1275

    
1276
    def configuration(self):
1277
        from ConfigurationDialog import QConfigurationDialog
1278

    
1279
        self.dlgConfiguration = QConfigurationDialog(self)
1280
        # self.dlgConfiguration.show()
1281
        if QDialog.Accepted == self.dlgConfiguration.exec_():
1282
            QEngineeringLineItem.LINE_TYPE_COLORS.clear()
1283
            QEngineeringInstrumentItem.INST_COLOR = None
1284

    
1285
    '''
1286
        @brief  show special item types dialog 
1287
        @author humkyung
1288
        @date   2019.08.10
1289
    '''
1290

    
1291
    def on_show_special_item_types(self):
1292
        from SpecialItemTypesDialog import QSpecialItemTypesDialog
1293

    
1294
        dlg = QSpecialItemTypesDialog(self)
1295
        dlg.exec_()
1296

    
1297
    def on_show_data_transfer(self):
1298
        """ show data transfer dialog """
1299
        from DataTransferDialog import QDataTransferDialog
1300

    
1301
        dlg = QDataTransferDialog(self)
1302
        dlg.exec_()
1303

    
1304
    def on_show_data_export(self):
1305
        """ show data export dialog """
1306
        from DataExportDialog import QDataExportDialog
1307

    
1308
        dlg = QDataExportDialog(self)
1309
        dlg.exec_()
1310

    
1311
    def on_show_eqp_datasheet_export(self):
1312
        """ show eqp datasheet export dialog """
1313
        from EqpDatasheetExportDialog import QEqpDatasheetExportDialog
1314

    
1315
        dlg = QEqpDatasheetExportDialog(self)
1316
        dlg.exec_()
1317

    
1318
    def on_show_opc_relation(self):
1319
        """ show opc relation dialog """
1320
        from OPCRelationDialog import QOPCRelationDialog
1321

    
1322
        dlg = QOPCRelationDialog(self)
1323
        dlg.exec_()
1324

    
1325
    '''
1326
        @brief  show nominal diameter dialog 
1327
        @author humkyung
1328
        @date   2018.06.28
1329
    '''
1330

    
1331
    def onShowCodeTable(self):
1332
        from CodeTableDialog import QCodeTableDialog
1333

    
1334
        dlg = QCodeTableDialog(self)
1335
        dlg.show()
1336
        dlg.exec_()
1337
        if dlg.code_area:
1338
            if dlg.code_area.scene():
1339
                self.graphicsView.scene().removeItem(dlg.code_area)
1340
        if dlg.desc_area:
1341
            if dlg.desc_area.scene():
1342
                self.graphicsView.scene().removeItem(dlg.desc_area)
1343
        self.graphicsView.useDefaultCommand()
1344

    
1345
    def onShowCustomCodeTable(self):
1346
        from CustomCodeTablesDialog import CustomCodeTablesDialog
1347

    
1348
        dlg = CustomCodeTablesDialog(self)
1349
        dlg.show()
1350
        dlg.exec_()
1351
        self.graphicsView.useDefaultCommand()
1352

    
1353
    '''
1354
        @brief  show HMB data
1355
        @author humkyung
1356
        @date   2018.07.11
1357
    '''
1358

    
1359
    def onHMBData(self):
1360
        from HMBDialog import QHMBDialog
1361

    
1362
        dlg = QHMBDialog(self)
1363
        dlg.show()
1364
        dlg.exec_()
1365

    
1366
    '''
1367
        @brief  show line data list 
1368
        @author humkyung
1369
        @date   2018.05.03
1370
    '''
1371

    
1372
    def showItemDataList(self):
1373
        from ItemDataExportDialog import QItemDataExportDialog
1374

    
1375
        dlg = QItemDataExportDialog(self)
1376
        dlg.exec_()
1377

    
1378
    def showTextDataList(self):
1379
        '''
1380
            @brief      show all text item in scene
1381
            @author     euisung
1382
            @date       2019.04.18
1383
        '''
1384
        try:
1385
            if not self.graphicsView.hasImage():
1386
                self.showImageSelectionMessageBox()
1387
                return
1388

    
1389
            self.onCommandRejected()
1390
            dialog = QTextDataListDialog(self)
1391
            dialog.show()
1392
        except Exception as ex:
1393
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1394
                                                           sys.exc_info()[-1].tb_lineno)
1395
            self.addMessage.emit(MessageType.Error, message)
1396

    
1397
    '''
1398
        @brief  Show Image Selection Guide MessageBox
1399
        @author Jeongwoo
1400
        @date   2018.05.02
1401
    '''
1402

    
1403
    def showImageSelectionMessageBox(self):
1404
        QMessageBox.about(self.graphicsView, self.tr("Notice"), self.tr("First select image drawing"))
1405

    
1406
    def on_search_text_changed(self):
1407
        """filter symbol tree view"""
1408
        regexp = QRegExp(self.lineEditFilter.text(), Qt.CaseInsensitive, QRegExp.FixedString)
1409

    
1410
        proxy_model = self.symbolTreeWidget.model()
1411
        proxy_model.text = self.lineEditFilter.text().lower()
1412
        proxy_model.setFilterRegExp(regexp)
1413

    
1414
        self.symbolTreeWidget.expandAll()
1415

    
1416
    '''
1417
        @brief  change selected lines' type by selected line type
1418
        @author humkyung
1419
        @date   2018.06.27
1420
    '''
1421

    
1422
    def onLineTypeChanged(self, param):
1423
        lineType = self.lineComboBox.itemText(param)
1424
        selected = [item for item in self.graphicsView.scene().selectedItems() if type(item) is QEngineeringLineItem]
1425
        if selected:
1426
            for item in selected:
1427
                item.lineType = lineType
1428

    
1429
    def display_colors(self, value):
1430
        """ display colors """
1431
        from DisplayColors import DisplayColors
1432
        from DisplayColors import DisplayOptions
1433

    
1434
        DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value is True else DisplayOptions.DisplayByLineType
1435
        if hasattr(self, 'graphicsView'):
1436
            self.graphicsView.scene().update(self.graphicsView.sceneRect())
1437
            DisplayColors.instance().save_data()
1438

    
1439
    def open_image_drawing(self, drawing, force=False):
1440
        """open and display image drawing file"""
1441
        from Drawing import Drawing
1442
        from App import App
1443
        from LoadCommand import LoadCommand
1444
        import concurrent.futures as futures
1445

    
1446
        # Yield successive n-sized
1447
        # chunks from l.
1448
        def divide_chunks(l, n):
1449
            # looping till length l
1450
            for i in range(0, len(l), n):
1451
                yield l[i:i + n]
1452

    
1453
        def update_items(items):
1454
            for item in items:
1455
                # binding items
1456
                item.owner
1457
                for connector in item.connectors:
1458
                    connector.connectedItem
1459

    
1460
            return items
1461

    
1462
        try:
1463
            app_doc_data = AppDocData.instance()
1464

    
1465
            if not self.actionSave.isEnabled():
1466
                return
1467

    
1468
            if not force and self.save_drawing_if_necessary():
1469
                return
1470

    
1471
            occupied = app_doc_data.set_occupying_drawing(drawing.UID)
1472
            if occupied:
1473
                QMessageBox.about(self.graphicsView, self.tr("Notice"),
1474
                                  self.tr(f"The drawing is locked for editing by another user({occupied})"))
1475
                return
1476

    
1477
            # save alarm
1478
            self.save_alarm_enable(False)
1479

    
1480
            if hasattr(self, '_save_work_cmd'):
1481
                self._save_work_cmd.wait()
1482

    
1483
            project = app_doc_data.getCurrentProject()
1484

    
1485
            self.path = self.graphicsView.loadImageFromFile(drawing)
1486
            if os.path.isfile(self.path):
1487
                self.onCommandRejected()
1488
                app_doc_data.clear()
1489

    
1490
                app_doc_data.setImgFilePath(self.path)
1491
                app_doc_data.activeDrawing = drawing
1492
                
1493
                #app_doc_data.activeDrawing.set_pid_source(Image.open(self.path))
1494
                self.itemTreeWidget.setCurrentPID(app_doc_data.activeDrawing.name)
1495

    
1496
                drawingList = self.treeWidgetDrawingList.topLevelItem(0)
1497
                for idx in range(drawingList.childCount()):
1498
                    child = drawingList.child(idx)
1499
                    if child.data(Qt.UserRole, 0) is drawing:
1500
                        child.setCheckState(0, Qt.Checked)
1501
                    else:
1502
                        child.setCheckState(0, Qt.Unchecked)
1503

    
1504
                try:
1505
                    self.show_Progress_bar()
1506

    
1507
                    # disconnect scene changed if signal is connected
1508
                    if self.graphicsView.scene().receivers(self.graphicsView.scene().contents_changed) > 0:
1509
                        self.graphicsView.scene().contents_changed.disconnect()
1510

    
1511
                    SymbolSvgItem.DOCUMENTS.clear()
1512

    
1513
                    # load data
1514
                    cmd = LoadCommand()
1515
                    cmd.display_message.connect(self.onAddMessage)
1516
                    cmd.set_maximum.connect(self.progress.setMaximum)
1517
                    cmd.show_progress.connect(self.progress.setValue)
1518
                    cmd.execute((drawing, self.graphicsView.scene()),
1519
                                symbol=True, text=True, line=True, unknown=True, package=True, update=True)
1520
                    # up to here
1521

    
1522
                    """"update item tree widget"""
1523
                    line_no_items = [item for item in self.graphicsView.scene().items()
1524
                                     if type(item) is QEngineeringLineNoTextItem]
1525
                    for line_no in line_no_items:
1526
                        line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
1527
                        for run in line_no.runs:
1528
                            for run_item in run.items:
1529
                                if issubclass(type(run_item), SymbolSvgItem):
1530
                                    self.init_add_tree_item(line_no_tree_item, run_item)
1531

    
1532
                    line_no_items = [item for item in self.graphicsView.scene().items()
1533
                                     if type(item) is QEngineeringTrimLineNoTextItem]
1534
                    for line_no in line_no_items:
1535
                        line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
1536
                        for run in line_no.runs:
1537
                            for run_item in run.items:
1538
                                if issubclass(type(run_item), SymbolSvgItem):
1539
                                    self.init_add_tree_item(line_no_tree_item, run_item)
1540

    
1541
                    for trim_line_no in app_doc_data.tracerLineNos:
1542
                        line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, trim_line_no)
1543
                        for run in trim_line_no.runs:
1544
                            for run_item in run.items:
1545
                                if issubclass(type(run_item), SymbolSvgItem):
1546
                                    self.init_add_tree_item(line_no_tree_item, run_item)
1547

    
1548
                    self.itemTreeWidget.update_item_count()
1549
                    self.itemTreeWidget.expandAll()
1550
                    """up to here"""
1551

    
1552
                    """update scene"""
1553
                    for item in self._scene.items():
1554
                        item.setVisible(True)
1555

    
1556
                    self._scene.update(self._scene.sceneRect())
1557

    
1558
                    """
1559
                    # old open drawing
1560
                    path = os.path.join(app_doc_data.getCurrentProject().getTempPath(), app_doc_data.imgName + '.xml')
1561
                    configs = app_doc_data.getConfigs('Data Load', 'Xml First')
1562
                    if configs and int(configs[0].value) >= 1 and os.path.isfile(path):
1563
                        self.load_recognition_result_from_xml(drawing)
1564
                    elif configs and int(configs[0].value) <= 1:
1565
                        self.load_drawing(app_doc_data.activeDrawing)
1566
                    """
1567

    
1568
                    self.display_number_of_items()
1569
                    # connect scene changed signal
1570
                    self.graphicsView.scene().contents_changed.connect(self.scene_changed)
1571
                finally:
1572
                    if hasattr(self, 'progress'):
1573
                        self.progress.setValue(self.progress.maximum())
1574

    
1575
                self.changeViewCheckedState(True)
1576
                self.setWindowTitle(self.title)
1577

    
1578
                # save alarm
1579
                self.save_alarm_enable(True, True)
1580
        except Exception as ex:
1581
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1582
                                                           sys.exc_info()[-1].tb_lineno)
1583
            self.addMessage.emit(MessageType.Error, message)
1584

    
1585
        return self.path
1586

    
1587
    def save_alarm_enable(self, enable, init=False):
1588
        from datetime import datetime
1589

    
1590
        app_doc_data = AppDocData.instance()
1591
        configs = app_doc_data.getConfigs('Data Save', 'Time')
1592
        time_min = int(configs[0].value) if 1 == len(configs) else 0
1593

    
1594
        if enable and time_min > 0:
1595
            if not self.save_timer:
1596
                self.save_timer = QTimer()
1597
                self.save_timer.timeout.connect(self.save_alarm)
1598
                self.save_timer.setInterval(60000)
1599

    
1600
            if init:
1601
                self.save_timer._init_time = datetime.now()
1602
                self.save_timer._stop_time = None
1603
                self.save_timer._interval_time = datetime.now() - datetime.now()
1604

    
1605
            if self.save_timer._stop_time:
1606
                self.save_timer._interval_time = datetime.now() - self.save_timer._stop_time
1607
            
1608
            #if 60000 * time_min != self.save_timer.interval():
1609
            #    self.save_timer.setInterval(60000)
1610

    
1611
            self.save_timer.start()
1612
        else:
1613
            if self.save_timer:
1614
                self.save_timer.stop()
1615
                self.save_timer._stop_time = datetime.now()
1616

    
1617
    def save_alarm(self):
1618
        from datetime import datetime
1619

    
1620
        app_doc_data = AppDocData.instance()
1621
        configs = app_doc_data.getConfigs('Data Save', 'Time')
1622
        time_min = int(configs[0].value) if 1 == len(configs) else 0
1623

    
1624
        self.save_timer.stop()
1625
        if self.graphicsView.hasFocus() and (datetime.now() - self.save_timer._init_time - self.save_timer._interval_time).seconds > time_min * 60:
1626
            QMessageBox.information(self, self.tr('Information'), self.tr('Please save Drawing'))
1627
            self.save_timer._init_time = datetime.now()
1628
            self.save_timer._interval_time = datetime.now() - datetime.now()
1629
        self.save_timer.start()
1630

    
1631
    def export_as_svg(self):
1632
        """export scene to svg file"""
1633
        from ExportCommand import ExportCommand
1634

    
1635
        options = QFileDialog.Options()
1636
        options |= QFileDialog.DontUseNativeDialog
1637
        file_path, _ = QFileDialog.getSaveFileName(self, "Export as svg", os.getcwd(), "svg file(*.svg)",
1638
                                                   options=options)
1639
        if file_path:
1640
            cmd = ExportCommand(self.graphicsView.scene(), 'svg')
1641
            cmd.display_message.connect(self.onAddMessage)
1642
            if cmd.execute(file_path):
1643
                QMessageBox.information(self, self.tr('Information'), self.tr('Successfully export to svg file'))
1644
            else:
1645
                QMessageBox.information(self, self.tr('Error'), self.tr('Fail to export to svg file'))
1646

    
1647
    def export_as_xml(self):
1648
        pass
1649

    
1650
    def export_as_image(self):
1651
        """export scene to image file"""
1652
        from ExportCommand import ExportCommand
1653

    
1654
        options = QFileDialog.Options()
1655
        options |= QFileDialog.DontUseNativeDialog
1656
        file_path, _ = QFileDialog.getSaveFileName(self, "Export as png", os.getcwd(), "png file(*.png)",
1657
                                                   options=options)
1658
        if file_path:
1659
            try:
1660
                # hide image drawing
1661
                self.onViewImageDrawing(False)
1662

    
1663
                cmd = ExportCommand(self.graphicsView.scene(), 'image')
1664
                cmd.display_message.connect(self.onAddMessage)
1665

    
1666
                if cmd.execute(file_path):
1667
                    QMessageBox.information(self, self.tr('Information'), self.tr('Successfully export to image file'))
1668
                else:
1669
                    QMessageBox.information(self, self.tr('Error'), self.tr('Fail to export to image file'))
1670
            finally:
1671
                if self.actionImage_Drawing.isChecked():
1672
                    self.onViewImageDrawing(True)
1673
                    self.actionImage_Drawing.setChecked(True)
1674

    
1675
    def show_Progress_bar(self):
1676
        """ show progress bar """
1677
        self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
1678
                                        self) if not hasattr(self, 'progress') else self.progress
1679
        self.progress.setWindowModality(Qt.WindowModal)
1680
        self.progress.setAutoReset(True)
1681
        self.progress.setAutoClose(True)
1682
        self.progress.setMinimum(0)
1683
        self.progress.setMaximum(100)
1684
        self.progress.resize(600, 100)
1685
        self.progress.setWindowTitle(self.tr("Reading file..."))
1686
        self.progress.show()
1687

    
1688
    def changeViewCheckedState(self, checked, clear=True):
1689
        '''
1690
            @brief      change view checked state
1691
            @author     euisung
1692
            @date       2019.03.06
1693
        '''
1694
        # self.actionImage_Drawing.setChecked(checked)
1695
        self.actionViewText.setChecked(checked)
1696
        self.actionViewSymbol.setChecked(checked)
1697
        self.actionViewLine.setChecked(checked)
1698
        self.actionViewUnknown.setChecked(checked)
1699
        self.actionViewInconsistency.setChecked(checked)
1700
        self.actionViewVendor_Area.setChecked(not checked)
1701
        self.actionDrawing_Only.setChecked(not checked)
1702
        if clear:
1703
            self.tableWidgetInconsistency.clearContents()
1704
            self.tableWidgetInconsistency.setRowCount(0)
1705

    
1706
    def onViewDrawingOnly(self, isChecked):
1707
        '''
1708
            @brief  visible/invisible except image drawing
1709
            @author euisung
1710
            @date   2019.04.22
1711
        '''
1712
        self.changeViewCheckedState(not isChecked, False)
1713
        for item in self.graphicsView.scene().items():
1714
            if type(item) is not QGraphicsPixmapItem:
1715
                item.setVisible(not isChecked)
1716

    
1717
    '''
1718
        @brief  visible/invisible image drawing
1719
        @author humkyung
1720
        @date   2018.06.25
1721
    '''
1722

    
1723
    def onViewImageDrawing(self, isChecked):
1724
        for item in self.graphicsView.scene().items():
1725
            if type(item) is QGraphicsPixmapItem:
1726
                item.setVisible(isChecked)
1727
                break
1728

    
1729
    def onViewText(self, checked):
1730
        """visible/invisible text"""
1731
        selected = [item for item in self.graphicsView.scene().items() if issubclass(type(item), QEngineeringTextItem)
1732
                    and type(item) is not QEngineeringLineNoTextItem]
1733
        for item in selected:
1734
            item.setVisible(checked)
1735

    
1736
    def onViewSymbol(self, checked):
1737
        """visible/invisible symbol"""
1738
        selected = [item for item in self.graphicsView.scene().items() if
1739
                    (issubclass(type(item), SymbolSvgItem) and type(item) is not QEngineeringErrorItem)]
1740
        for item in selected:
1741
            item.setVisible(checked)
1742

    
1743
    def onViewLine(self, checked):
1744
        """visible/invisible line"""
1745
        selected = [item for item in self.graphicsView.scene().items() if type(item) is QEngineeringLineItem]
1746
        for item in selected:
1747
            item.setVisible(checked)
1748

    
1749
    def onViewInconsistency(self, isChecked):
1750
        '''
1751
            @brief  visible/invisible Inconsistency
1752
            @author euisung
1753
            @date   2019.04.03
1754
        '''
1755
        selected = [item for item in self.graphicsView.scene().items() if type(item) is QEngineeringErrorItem]
1756
        for item in selected:
1757
            item.setVisible(isChecked)
1758

    
1759
    '''
1760
        @brief  visible/invisible Unknown 
1761
        @author humkyung
1762
        @date   2018.06.28
1763
    '''
1764

    
1765
    def onViewUnknown(self, isChecked):
1766
        selected = [item for item in self.graphicsView.scene().items() if type(item) is QEngineeringUnknownItem]
1767
        for item in selected:
1768
            item.setVisible(isChecked)
1769

    
1770
    def onViewVendorArea(self, isChecked):
1771
        '''
1772
            @brief  visible/invisible Vendor Area
1773
            @author euisung
1774
            @date   2019.04.29
1775
        '''
1776
        selected = [item for item in self.graphicsView.scene().items() if issubclass(type(item), QEngineeringVendorItem)]
1777
        for item in selected:
1778
            item.setVisible(isChecked)
1779

    
1780
    '''
1781
        @brief  create a symbol
1782
        @history    2018.05.02  Jeongwoo    Change return value of QSymbolEditorDialog (Single variable → Tuple)
1783
                                            Add SymbolSvgItem
1784
                    2018.05.03  Jeongwoo    Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
1785
                                            Change method to make svg and image path
1786
                    2018.06.08  Jeongwoo    Add Paramter on SymbolSvgItem.buildItem()
1787
    '''
1788
    def onCreateSymbolClicked(self):
1789
        selected = [item for item in self.graphicsView.scene().selectedItems() if issubclass(type(item), QEngineeringVendorItem)]
1790
        if len(selected) == 1:
1791
            symbol_image = AppDocData.instance().activeDrawing.image_origin
1792
            rect = selected[0].sceneBoundingRect()
1793

    
1794
            points = []
1795
            for conn in selected[0].connectors:
1796
                points.append([round(conn.center()[0] - rect.x()), round(conn.center()[1] - rect.y())])
1797
            poly = np.array(points, np.int32)
1798

    
1799
            #mask = np.zeros((int(rect.height()), int(rect.width())))
1800
            #cv2.fillPoly(mask, [poly], (255))
1801
            #poly_copied = np.multiply(mask, symbol_image[round(rect.y()):round(rect.y() + rect.height()),
1802
            #                   round(rect.x()):round(rect.x() + rect.width())])
1803
            #cv2.fillPoly(mask,[poly],0)
1804
            #src2 = np.multiply(mask,src2)
1805

    
1806
            mask = np.ones((int(rect.height()), int(rect.width())), dtype=np.uint8) * 255
1807
            cv2.fillPoly(mask, [poly], (0))
1808
            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())])
1809
            sym_img = cv2.merge((sym_img, sym_img, sym_img))
1810

    
1811
            h, w, c = sym_img.shape
1812
            qImg = QImage(sym_img.data, w, h, w * c, QImage.Format_RGB888)
1813
            #pixmap = QPixmap.fromImage(qImg)
1814

    
1815
            self.onAreaSelected(None, None, None, None, package=qImg, position=rect.topLeft(), package_item=selected[0])
1816
        else:
1817
            cmd = FenceCommand.FenceCommand(self.graphicsView)
1818
            cmd.onSuccess.connect(self.onAreaSelected)
1819
            self.graphicsView.command = cmd
1820
            QApplication.setOverrideCursor(Qt.CrossCursor)
1821

    
1822
    '''
1823
        @brief      show SymbolEditorDialog with image selected by user
1824
        @author     humkyung
1825
        @date       2018.07.20
1826
    '''
1827

    
1828
    def onAreaSelected(self, x, y, width, height, package=False, position=None, package_item=None):
1829
        try:
1830
            image = self.graphicsView.image()
1831
            if image is not None:
1832
                if not package:
1833
                    symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height),
1834
                                                                                AppDocData.instance().getCurrentProject())
1835
                else:
1836
                    symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, package,
1837
                                                                                AppDocData.instance().getCurrentProject(), package=True)
1838
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
1839
                # TODO: not initialize symbol tree view when user reject to create a new symbol
1840
                self.symbolTreeWidget.initSymbolTreeView()
1841
                if isAccepted:
1842
                    if isImmediateInsert:
1843
                        svg = QtImageViewer.createSymbolObject(newSym.getName())
1844
                        offsetX, offsetY = [int(point) for point in newSym.getOriginalPoint().split(',')]
1845
                        QtImageViewer.matchSymbolToLine(self.graphicsView.scene(), svg, QPoint(position.x() + offsetX, position.y() + offsetY))
1846

    
1847
                        package_item.transfer.onRemoved.emit(selected[0])
1848
        finally:
1849
            self.onCommandRejected()
1850
            QApplication.restoreOverrideCursor()
1851

    
1852
    def make_label_data(self):
1853
        """ make label data from symbol info """
1854
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
1855

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

    
1860
        app_doc_data = AppDocData.instance()
1861
        project = app_doc_data.getCurrentProject()
1862

    
1863
        smalls = []
1864
        bigs = []
1865

    
1866
        symbol_list = app_doc_data.getTargetSymbolList(all=True)
1867
        for symbol in symbol_list:
1868
            if symbol.width and symbol.height:
1869
                if symbol.width > 300 or symbol.height > 300:
1870
                    bigs.append(symbol.getName())
1871
                else:
1872
                    smalls.append(symbol.getName())
1873

    
1874
        symbols = [item for item in self.graphicsView.scene().items() if issubclass(type(item), SymbolSvgItem)]
1875
        names = [smalls, bigs]
1876

    
1877
        img = app_doc_data.activeDrawing.image_origin
1878

    
1879
        small_size = 500
1880
        big_size = 850
1881

    
1882
        save_path = project.getTrainingSymbolFilePath()
1883

    
1884
        index = 0
1885
        for size in [small_size, big_size]:
1886
            offsets = [0, int(size / 2)]
1887

    
1888
            width, height = img.shape[1], img.shape[0]
1889
            width_count, height_count = width // size + 2, height // size + 2
1890
            b_width, b_height = width_count * size, height_count * size
1891
            b_img = np.zeros((b_height, b_width), np.uint8) + 255
1892
            b_img[:height, :width] = img[:, :]
1893

    
1894
            for offset in offsets:
1895
                for row in range(height_count):
1896
                    for col in range(width_count):
1897
                        x, y = col * size + offset, row * size + offset
1898
                        tile_rect = QRectF(x, y, size, size)
1899
                        tile_symbols = []
1900
                        for symbol in [symbol for symbol in symbols if symbol.name in names[index]]:
1901
                            if tile_rect.contains(symbol.sceneBoundingRect()):
1902
                                tile_symbols.append(symbol)
1903
                                symbols.remove(symbol)
1904

    
1905
                        if tile_symbols:
1906
                            training_uid = str(uuid.uuid4())
1907
                            training_image_path = os.path.join(save_path, training_uid + '.png')
1908
                            training_xml_path = os.path.join(save_path, training_uid + '.xml')
1909

    
1910
                            # save image
1911
                            #_img = b_img[round(tile_rect.top()):round(tile_rect.bottom()),
1912
                            #       round(tile_rect.left()):round(tile_rect.right())]
1913
                            #cv2.imwrite(training_image_path, _img)
1914
                            _img = self.graphicsView.image().copy(round(tile_rect.left()), round(tile_rect.top()), round(tile_rect.width()), round(tile_rect.height()))
1915
                            _img.save(training_image_path)
1916

    
1917
                            # save label
1918
                            xml = Element('annotation')
1919
                            SubElement(xml, 'folder').text = 'None'
1920
                            SubElement(xml, 'filename').text = os.path.basename(save_path)
1921

    
1922
                            pathNode = Element('path')
1923
                            pathNode.text = save_path.replace('/', '\\')
1924
                            xml.append(pathNode)
1925

    
1926
                            sourceNode = Element('source')
1927
                            databaseNode = Element('database')
1928
                            databaseNode.text = 'Unknown'
1929
                            sourceNode.append(databaseNode)
1930
                            xml.append(sourceNode)
1931

    
1932
                            sizeNode = Element('size')
1933
                            widthNode = Element('width')
1934
                            widthNode.text = str(int(tile_rect.width()))
1935
                            sizeNode.append(widthNode)
1936
                            heightNode = Element('height')
1937
                            heightNode.text = str(int(tile_rect.height()))
1938
                            sizeNode.append(heightNode)
1939
                            depthNode = Element('depth')
1940
                            depthNode.text = '3'
1941
                            sizeNode.append(depthNode)
1942
                            xml.append(sizeNode)
1943

    
1944
                            segmentedNode = Element('segmented')
1945
                            segmentedNode.text = '0'
1946
                            xml.append(segmentedNode)
1947

    
1948
                            labelContent = []
1949
                            counts = {}
1950
                            for item in tile_symbols:
1951
                                rect = item.sceneBoundingRect()
1952
                                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)
1953
                                xMin = xMin if xMin > 0 else 0
1954
                                yMin = yMin if yMin > 0 else 0
1955
                                xMax = xMax if xMax < size else size
1956
                                yMax = yMax if yMax < size else size
1957

    
1958
                                if label == 'None' or label == '':
1959
                                    continue
1960
                                if label not in labelContent:
1961
                                    labelContent.append(label)
1962
                                    counts[label] = 1
1963
                                else:
1964
                                    counts[label] = counts[label] + 1
1965

    
1966
                                objectNode = Element('object')
1967
                                nameNode = Element('name')
1968
                                nameNode.text = label
1969
                                objectNode.append(nameNode)
1970
                                poseNode = Element('pose')
1971
                                poseNode.text = 'Unspecified'
1972
                                objectNode.append(poseNode)
1973
                                truncatedNode = Element('truncated')
1974
                                truncatedNode.text = '0'
1975
                                objectNode.append(truncatedNode)
1976
                                difficultNode = Element('difficult')
1977
                                difficultNode.text = '0'
1978
                                objectNode.append(difficultNode)
1979

    
1980
                                bndboxNode = Element('bndbox')
1981
                                xminNode = Element('xmin')
1982
                                xminNode.text = str(xMin)
1983
                                bndboxNode.append(xminNode)
1984
                                yminNode = Element('ymin')
1985
                                yminNode.text = str(yMin)
1986
                                bndboxNode.append(yminNode)
1987
                                xmaxNode = Element('xmax')
1988
                                xmaxNode.text = str(xMax)
1989
                                bndboxNode.append(xmaxNode)
1990
                                ymaxNode = Element('ymax')
1991
                                ymaxNode.text = str(yMax)
1992
                                bndboxNode.append(ymaxNode)
1993
                                objectNode.append(bndboxNode)
1994

    
1995
                                xml.append(objectNode)
1996

    
1997
                            ElementTree(xml).write(training_xml_path)
1998

    
1999
            index += 1
2000

    
2001
        QMessageBox.about(self, self.tr("Notice"), self.tr('Successfully applied. '))
2002

    
2003
    '''
2004
        @brief      create a line
2005
        @author     humkyung
2006
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
2007
    '''
2008
    def onPlaceLine(self):
2009
        if not self.graphicsView.hasImage():
2010
            self.actionLine.setChecked(False)
2011
            self.showImageSelectionMessageBox()
2012
            return
2013

    
2014
        self.actionLine.setChecked(True)
2015
        if not hasattr(self.actionLine, 'tag'):
2016
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
2017
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
2018
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
2019

    
2020
        self.graphicsView.command = self.actionLine.tag
2021

    
2022
    '''
2023
        @brief      add created lines to scene
2024
        @author     humkyung
2025
        @date       2018.07.23
2026
    '''
2027

    
2028
    def onLineCreated(self):
2029
        from EngineeringConnectorItem import QEngineeringConnectorItem
2030
        from LineDetector import LineDetector
2031

    
2032
        try:
2033
            app_doc_data = AppDocData.instance()
2034

    
2035
            count = len(self.actionLine.tag._polyline._vertices)
2036
            if count > 1:
2037
                items = []
2038

    
2039
                detector = LineDetector(None)
2040

    
2041
                if not self.actionLine.tag.line_type:
2042
                    line_type = self.lineComboBox.currentText()
2043
                else:
2044
                    if not (QEngineeringLineItem.check_piping(self.actionLine.tag.line_type) ^ QEngineeringLineItem.check_piping(self.lineComboBox.currentText())):
2045
                        line_type = self.lineComboBox.currentText()
2046
                    else:
2047
                        line_type = self.actionLine.tag.line_type
2048
                for index in range(count - 1):
2049
                    start = self.actionLine.tag._polyline._vertices[index]
2050
                    end = self.actionLine.tag._polyline._vertices[index + 1]
2051

    
2052
                    lineItem = QEngineeringLineItem(vertices=[start, end])
2053
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
2054
                    lineItem.lineType = line_type
2055
                    if items:
2056
                        lineItem.connect_if_possible(items[-1], 5)
2057
                    else:
2058
                        pt = lineItem.start_point()
2059
                        selected = [item for item in self.graphicsView.scene().items(QPointF(pt[0], pt[1])) if
2060
                                    type(item) is QEngineeringConnectorItem or type(item) is QEngineeringLineItem]
2061
                        if selected and selected[0] is not lineItem:
2062
                            if type(selected[0]) is QEngineeringConnectorItem:
2063
                                lineItem.connect_if_possible(selected[0].parent, 5)
2064
                            else:
2065
                                detector.connectLineToLine(selected[0], lineItem, 5)
2066

    
2067
                    items.append(lineItem)
2068
                    self.graphicsView.scene().addItem(lineItem)
2069
                    #app_doc_data.lines.append(lineItem)
2070

    
2071
                pt = items[-1].end_point()
2072
                selected = [item for item in self.graphicsView.scene().items(QPointF(pt[0], pt[1])) if
2073
                            (type(item) is QEngineeringConnectorItem and item.parentItem() is not items[-1]) or
2074
                            (type(item) is QEngineeringLineItem and item is not items[-1])]
2075
                if selected and selected[0] is not items[-1]:
2076
                    if type(selected[0]) is QEngineeringConnectorItem:
2077
                        items[-1].connect_if_possible(selected[0].parent, 5)
2078
                    else:
2079
                        detector.connectLineToLine(selected[0], items[-1], 5)
2080

    
2081
                self._scene.undo_stack.push(CreateCommand(self._scene, items))
2082
        finally:
2083
            self.graphicsView.scene().removeItem(self.actionLine.tag._polyline)
2084
            self.actionLine.tag.reset()
2085

    
2086
    '''
2087
        @brief      refresh scene
2088
        @author     humkyung
2089
        @date       2018.07.23
2090
    '''
2091

    
2092
    def onCommandRejected(self, cmd=None):
2093
        try:
2094
            if type(cmd) is PlaceLineCommand.PlaceLineCommand:
2095
                if self.actionLine.tag._polyline:
2096
                    self.graphicsView.scene().removeItem(self.actionLine.tag._polyline)
2097
                self.graphicsView.scene().update()
2098
                self.actionLine.tag.reset()
2099

    
2100
                self.actionLine.setChecked(False)
2101
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
2102
                self.actionZoom.setChecked(False)
2103
            elif type(cmd) is AreaOcrCommand.AreaOcrCommand:
2104
                self.actionOCR.setChecked(False)
2105
            elif type(cmd) is PlacePolygonCommand.PlacePolygonCommand:
2106
                self.actionVendor.setChecked(False)
2107
            else:
2108
                if hasattr(self.actionLine, 'tag') and self.actionLine.tag._polyline:
2109
                    self.graphicsView.scene().removeItem(self.actionLine.tag._polyline)
2110
                    self.graphicsView.scene().update()
2111
                    self.actionLine.tag.reset()
2112
                if hasattr(self.actionVendor, 'tag') and self.actionVendor.tag._polyline:
2113
                    self.graphicsView.scene().removeItem(self.actionVendor.tag._polyline)
2114
                    self.graphicsView.scene().update()
2115
                    self.actionVendor.tag.reset()
2116
                self.actionLine.setChecked(False)
2117
                self.actionZoom.setChecked(False)
2118
                self.actionOCR.setChecked(False)
2119
                self.actionVendor.setChecked(False)
2120
        finally:
2121
            self.graphicsView.useDefaultCommand()
2122

    
2123
    '''
2124
        @brief      restore to default command when user press Escape key
2125
        @author     humkyung 
2126
        @date       2018.08.09
2127
        
2128
    '''
2129

    
2130
    def keyPressEvent(self, event):
2131
        try:
2132
            if event.key() == Qt.Key_Escape:
2133
                checked = self.actionGroup.checkedAction()
2134
                if checked:
2135
                    checked.setChecked(False)
2136
                    self.graphicsView.useDefaultCommand()
2137
            elif event.key() == Qt.Key_1:
2138
                if self.actionImage_Drawing.isChecked():
2139
                    self.onViewImageDrawing(False)
2140
                    self.actionImage_Drawing.setChecked(False)
2141
                else:
2142
                    self.onViewImageDrawing(True)
2143
                    self.actionImage_Drawing.setChecked(True)
2144
            elif event.key() == Qt.Key_2:
2145
                if self.actionViewText.isChecked():
2146
                    self.onViewText(False)
2147
                    self.actionViewText.setChecked(False)
2148
                else:
2149
                    self.onViewText(True)
2150
                    self.actionViewText.setChecked(True)
2151
            elif event.key() == Qt.Key_3:
2152
                if self.actionViewSymbol.isChecked():
2153
                    self.onViewSymbol(False)
2154
                    self.actionViewSymbol.setChecked(False)
2155
                else:
2156
                    self.onViewSymbol(True)
2157
                    self.actionViewSymbol.setChecked(True)
2158
            elif event.key() == Qt.Key_4:
2159
                if self.actionViewLine.isChecked():
2160
                    self.onViewLine(False)
2161
                    self.actionViewLine.setChecked(False)
2162
                else:
2163
                    self.onViewLine(True)
2164
                    self.actionViewLine.setChecked(True)
2165
            elif event.key() == Qt.Key_5:
2166
                if self.actionViewUnknown.isChecked():
2167
                    self.onViewUnknown(False)
2168
                    self.actionViewUnknown.setChecked(False)
2169
                else:
2170
                    self.onViewUnknown(True)
2171
                    self.actionViewUnknown.setChecked(True)
2172
            elif event.key() == Qt.Key_6:
2173
                if self.actionViewInconsistency.isChecked():
2174
                    self.onViewInconsistency(False)
2175
                    self.actionViewInconsistency.setChecked(False)
2176
                else:
2177
                    self.onViewInconsistency(True)
2178
                    self.actionViewInconsistency.setChecked(True)
2179
            elif event.key() == Qt.Key_7:
2180
                if self.actionViewVendor_Area.isChecked():
2181
                    self.onViewVendorArea(False)
2182
                    self.actionViewVendor_Area.setChecked(False)
2183
                else:
2184
                    self.onViewVendorArea(True)
2185
                    self.actionViewVendor_Area.setChecked(True)
2186
            elif event.key() == 96:  # '`' key
2187
                if self.actionDrawing_Only.isChecked():
2188
                    self.onViewDrawingOnly(False)
2189
                    self.actionDrawing_Only.setChecked(False)
2190
                else:
2191
                    self.onViewDrawingOnly(True)
2192
                    self.actionDrawing_Only.setChecked(True)
2193
            elif event.key() == Qt.Key_M:  # merge text as vertical
2194
                from TextInfo import TextInfo
2195

    
2196
                textItems = [text for text in self.graphicsView.scene().selectedItems() if
2197
                             issubclass(type(text), QEngineeringTextItem)]
2198
                if not textItems or len(textItems) is 1:
2199
                    return
2200

    
2201
                angle = None
2202
                for item in textItems:
2203
                    if angle is None:
2204
                        angle = item.angle
2205
                    else:
2206
                        if angle != item.angle:
2207
                            return
2208

    
2209
                modifiers = QApplication.keyboardModifiers()
2210
                enter_or_space = ' ' if modifiers == Qt.ControlModifier else '\n'
2211
                x_or_y = 0 if modifiers == Qt.ControlModifier else 1
2212

    
2213
                textItems = sorted(textItems, key=lambda text: text.loc[x_or_y]) if textItems[0].angle == 0 else ( \
2214
                    sorted(textItems, key=lambda text: text.loc[x_or_y]) if textItems[0].angle == 1.57 else ( \
2215
                        sorted(textItems, key=lambda text: text.loc[x_or_y], reverse=True) if textItems[0].angle == 4.71 else \
2216
                            sorted(textItems, key=lambda text: text.loc[x_or_y], reverse=True)))
2217

    
2218
                if textItems[0].angle == 1.57 and modifiers == Qt.ControlModifier:
2219
                    textItems.reverse()
2220

    
2221
                minX = sys.maxsize
2222
                minY = sys.maxsize
2223
                maxX = 0
2224
                maxY = 0
2225
                newText = ''
2226

    
2227
                for text in textItems:
2228
                    if text.loc[0] < minX: minX = text.loc[0]
2229
                    if text.loc[1] < minY: minY = text.loc[1]
2230
                    if text.loc[0] + text.size[0] > maxX: maxX = text.loc[0] + text.size[0]
2231
                    if text.loc[1] + text.size[1] > maxY: maxY = text.loc[1] + text.size[1]
2232
                    newText = newText + text.text() + enter_or_space
2233
                    text.transfer.onRemoved.emit(text)
2234
                newText = newText[:-1]
2235

    
2236
                textInfo = TextInfo(newText, minX, minY, maxX - minX, maxY - minY, textItems[0].angle)
2237
                x = textInfo.getX()
2238
                y = textInfo.getY()
2239
                angle = textInfo.getAngle()
2240
                text = textInfo.getText()
2241
                width = textInfo.getW()
2242
                height = textInfo.getH()
2243
                item = TextItemFactory.instance().createTextItem(textInfo)
2244
                if item is not None:
2245
                    item.loc = [x, y]
2246
                    item.size = (width, height)
2247
                    item.angle = angle
2248
                    item.setDefaultTextColor(Qt.blue)
2249
                    item.addTextItemToScene(self.graphicsView.scene())
2250
                    item.transfer.onRemoved.connect(self.itemRemoved)
2251
            elif event.key() == Qt.Key_D:
2252
                # pop up development toolkit dialog
2253
                from DevelopmentToolkitDialog import QDevelopmentToolkitDialog
2254

    
2255
                modifiers = QApplication.keyboardModifiers()
2256
                if modifiers == Qt.ControlModifier:
2257
                    dlg = QDevelopmentToolkitDialog(self, self.graphicsView)
2258
                    dlg.show()
2259
            elif event.key() == Qt.Key_I:
2260
                # insert symbol item that is selected symbol in tree to main window if symbol already selected on main window, replace
2261
                index = self.symbolTreeWidget.currentIndex()
2262
                proxy_model = self.symbolTreeWidget.model()
2263
                items = [proxy_model.sourceModel().itemFromIndex(proxy_model.mapToSource(index))]
2264
                if items and hasattr(items[0], 'svgFilePath'):
2265
                    symData = items[0].data(self.symbolTreeWidget.TREE_DATA_ROLE)
2266
                    symName = symData.getName()
2267
                else:
2268
                    return
2269

    
2270
                symbolItems = [symbol for symbol in self.graphicsView.scene().selectedItems() if
2271
                               issubclass(type(symbol), SymbolSvgItem)]
2272
                old_symbol = None
2273
                if symbolItems and len(symbolItems) is 1:
2274
                    old_symbol = symbolItems[0]
2275
                    #scenePos = QPoint(old_symbol.origin[0], old_symbol.origin[1])
2276
                    scenePos = old_symbol.mapToScene(old_symbol.transformOriginPoint())
2277
                    old_symbol.transfer.onRemoved.emit(old_symbol)
2278
                else:
2279
                    scenePos = self.current_pos
2280

    
2281
                svg = QtImageViewer.createSymbolObject(symName)
2282
                QtImageViewer.matchSymbolToLine(self.graphicsView.scene(), svg, scenePos)
2283

    
2284
                if old_symbol and svg:
2285
                    from ReplaceCommand import ReplaceCommand
2286

    
2287
                    cmd = ReplaceCommand(self.graphicsView.scene(), old_symbol, svg)
2288
                    self._scene.undo_stack.push(cmd)
2289
                    return
2290
            elif event.key() == Qt.Key_J:
2291
                # insert and connect symbol item that is selected symbol in tree to selected symbol
2292
                index = self.symbolTreeWidget.currentIndex()
2293
                proxy_model = self.symbolTreeWidget.model()
2294
                items = [proxy_model.sourceModel().itemFromIndex(proxy_model.mapToSource(index))]
2295
                if items and hasattr(items[0], 'svgFilePath'):
2296
                    symData = items[0].data(self.symbolTreeWidget.TREE_DATA_ROLE)
2297
                    symName = symData.getName()
2298
                else:
2299
                    return
2300

    
2301
                symbolItems = [symbol for symbol in self.graphicsView.scene().selectedItems() if
2302
                               issubclass(type(symbol), SymbolSvgItem)]
2303
                if symbolItems and len(symbolItems) is not 1:
2304
                    return
2305
                    
2306
                target_symbol = symbolItems[0]
2307
                index =  [index for index in range(len(target_symbol.conn_type)) \
2308
                            if target_symbol.conn_type[index] == 'Primary' or target_symbol.conn_type[index] == 'Secondary']
2309
                for connector in target_symbol.connectors:
2310
                    svg = QtImageViewer.createSymbolObject(symName)
2311
                    if len(svg.connectors) > 1: 
2312
                        if ((target_symbol.conn_type and target_symbol.connectors.index(connector) in index) or not target_symbol.conn_type) and \
2313
                                    (not connector.connectedItem or (connector.connectedItem and type(connector.connectedItem) is QEngineeringLineItem)):
2314
                            QtImageViewer.matchSymbolToLine(self.graphicsView.scene(), svg, connector.sceneBoundingRect().center())
2315
                    elif len(svg.connectors) == 1:
2316
                        if ((target_symbol.conn_type and target_symbol.connectors.index(connector) in index) or not target_symbol.conn_type) and \
2317
                                    not connector.connectedItem:
2318
                            QtImageViewer.matchSymbolToLine(self.graphicsView.scene(), svg, connector.sceneBoundingRect().center())
2319

    
2320
                if target_symbol:
2321
                    return
2322
            elif event.key() == Qt.Key_X:
2323
                app_doc_data = AppDocData.instance()
2324
                configs = app_doc_data.getAppConfigs('app', 'mode')
2325
                if configs and 1 == len(configs) and 'advanced' == configs[0].value:
2326
                    advanced = True
2327
                    items = self.graphicsView.scene().selectedItems()
2328
                    if items:
2329
                        item = self.symbolTreeWidget.currentItem()
2330
                        if item:
2331
                            self.symbolTreeWidget.showSymbolEditorDialog(item, 0)
2332

    
2333
            QMainWindow.keyPressEvent(self, event)
2334
        except Exception as ex:
2335
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2336
                                                           sys.exc_info()[-1].tb_lineno)
2337
            self.addMessage.emit(MessageType.Error, message)
2338

    
2339
    def recognize(self):
2340
        """recognize symbol, text and line for selected drawings"""
2341
        from datetime import datetime
2342
        from RecognitionDialog import QRecognitionDialog
2343

    
2344
        # save alarm
2345
        self.save_alarm_enable(False)
2346

    
2347
        app_doc_data = AppDocData.instance()
2348
        current_drawing, currentPid = None, None
2349

    
2350
        if self.graphicsView.hasImage():
2351
            current_drawing = app_doc_data.activeDrawing
2352
            currentPid = app_doc_data.activeDrawing.name
2353

    
2354
        # get checked drawings
2355
        drawing_top = self.treeWidgetDrawingList.topLevelItem(0)
2356
        count = drawing_top.childCount()
2357
        checked_drawings = {}
2358
        for idx in range(count):
2359
            child = drawing_top.child(idx)
2360
            if child.checkState(0) == Qt.Checked and child.data(Qt.UserRole, 0):
2361
                checked_drawings[child.data(Qt.UserRole, 0)] = child
2362
        # up to here
2363

    
2364
        # if there is no checked drawing
2365
        if current_drawing and currentPid and not checked_drawings:
2366
            for idx in range(count):
2367
                child = drawing_top.child(idx)
2368
                if child.data(Qt.UserRole, 0) is current_drawing:
2369
                    checked_drawings[child.data(Qt.UserRole, 0)] = child
2370

    
2371
        if not checked_drawings:
2372
            self.showImageSelectionMessageBox()
2373
            return
2374

    
2375
        try:
2376
            self.onClearLog()
2377
            dlg = QRecognitionDialog(self, [drawing for drawing in checked_drawings.keys()])
2378
            dlg.exec_()
2379

    
2380
            if current_drawing and current_drawing in checked_drawings.keys() and dlg.isTreated:
2381
                self.open_image_drawing(current_drawing, force=True)
2382

    
2383
            # save working date-time
2384
            _now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
2385
            for drawing, tree_item in checked_drawings.items():
2386
                drawing.datetime = _now
2387
                tree_item.setText(1, _now)
2388
            #app_doc_data.saveDrawings(checked_drawings.keys())
2389
            self.changeViewCheckedState(True)
2390
            # up to here
2391
        except Exception as ex:
2392
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
2393
                                                           sys.exc_info()[-1].tb_lineno)
2394
            self.addMessage.emit(MessageType.Error, message)
2395

    
2396
        # save alarm
2397
            self.save_alarm_enable(True)
2398

    
2399
    '''
2400
        @brief      remove item from tree widget and then remove from scene
2401
        @date       2018.05.25
2402
        @author     Jeongwoo
2403
    '''
2404

    
2405
    def itemRemoved(self, item):
2406
        try:
2407
            if type(item) is QEngineeringErrorItem:
2408
                # remove error item from inconsistency list
2409
                for row in range(self.tableWidgetInconsistency.rowCount()):
2410
                    if item is self.tableWidgetInconsistency.item(row, 0).tag:
2411
                        self.tableWidgetInconsistency.removeRow(row)
2412
                        break
2413

    
2414
                if item.scene() is not None: item.scene().removeItem(item)
2415
                del item
2416
            else:
2417
                self.itemTreeWidget.itemRemoved(item)
2418

    
2419
                matches = [_item for _item in self.graphicsView.scene().items() if
2420
                           hasattr(_item, 'connectors') and [connector for connector in _item.connectors if
2421
                                                             connector.connectedItem is item]]
2422
                for match in matches:
2423
                    for connector in match.connectors:
2424
                        if connector.connectedItem is item:
2425
                            connector.connectedItem = None
2426
                            connector.highlight(False)
2427

    
2428
                # matches = [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'remove_assoc_item')]
2429
                # for _item in matches:
2430
                #    _item.remove_assoc_item(item)
2431

    
2432
                app_doc_data = AppDocData.instance()
2433
                if type(item) is QEngineeringLineNoTextItem and item in app_doc_data.tracerLineNos:
2434
                    app_doc_data.tracerLineNos.pop(app_doc_data.tracerLineNos.index(item))
2435

    
2436
                if type(item) is QEngineeringLineItem and item in app_doc_data.lines:
2437
                    app_doc_data.lines.remove(item)
2438

    
2439
                matches = [_item for _item in self.graphicsView.scene().items() if
2440
                           type(_item) is QEngineeringLineNoTextItem]
2441
                matches.extend([lineNo for lineNo in app_doc_data.tracerLineNos if
2442
                                type(lineNo) is QEngineeringTrimLineNoTextItem])
2443
                for match in matches:
2444
                    if item is match.prop('From'):
2445
                        match.set_property('From', None)
2446
                    if item is match.prop('To'):
2447
                        match.set_property('To', None)
2448

    
2449
                    for run_index in reversed(range(len(match.runs))):
2450
                        run = match.runs[run_index]
2451
                        if item in run.items:
2452
                            index = run.items.index(item)
2453
                            run.items.pop(index)
2454
                            if not run.items:
2455
                                run.explode()
2456
                                if type(match) is QEngineeringTrimLineNoTextItem and not match.runs:
2457
                                    app_doc_data.tracerLineNos.pop(app_doc_data.tracerLineNos.index(match))
2458
                            # break
2459

    
2460
                matches = [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'owner')]
2461
                for match in matches:
2462
                    if match.owner is item:
2463
                        match.owner = None
2464

    
2465
                matches = [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'attrs')]
2466
                # done = False
2467
                for match in matches:
2468
                    assocs = match.associations()
2469
                    for assoc in assocs:
2470
                        if item is assoc:
2471
                            for attr in match.attrs.keys():
2472
                                if attr.AssocItem and str(item.uid) == str(attr.AssocItem.uid):
2473
                                    attr.AssocItem = None
2474
                                    match.attrs[attr] = ''
2475
                                    # done = True
2476
                            match.remove_assoc_item(item)
2477
                            break
2478
                    # if done: break
2479

    
2480
                if item.scene() is not None: item.scene().removeItem(item)
2481
        except Exception as ex:
2482
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2483
                                                           sys.exc_info()[-1].tb_lineno)
2484
            self.addMessage.emit(MessageType.Error, message)
2485

    
2486
    def connect_attributes(self, MainWindow):
2487
        """connect attributes to symbol"""
2488
        from LineNoTracer import LineNoTracer
2489
        from ConnectAttrDialog import QConnectAttrDialog
2490

    
2491
        if not self.graphicsView.hasImage():
2492
            self.showImageSelectionMessageBox()
2493
            return
2494

    
2495
        # save alarm
2496
        self.save_alarm_enable(False)
2497

    
2498
        try:
2499
            dlg = QConnectAttrDialog(self, self.graphicsView.scene())
2500
            dlg.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint)
2501
            dlg.exec_()
2502
            if dlg.isRunned:
2503
                self.itemTreeWidget.InitLineNoItems()
2504

    
2505
                # construct line no item
2506
                line_nos = AppDocData.instance().tracerLineNos
2507
                for line_no in line_nos:
2508
                    item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2509
                    connectedItems = line_no.getConnectedItems()
2510
                    for connectedItem in connectedItems:
2511
                        if issubclass(type(connectedItem), SymbolSvgItem):
2512
                            self.itemTreeWidget.addTreeItem(item, connectedItem)
2513
                # up to here
2514

    
2515
                if dlg.validation_checked:
2516
                    self.onValidation()
2517

    
2518
                self.graphicsView.invalidateScene()
2519
        except Exception as ex:
2520
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2521
                                                           sys.exc_info()[-1].tb_lineno)
2522
            self.addMessage.emit(MessageType.Error, message)
2523
        finally:
2524
            # save alarm
2525
            self.save_alarm_enable(True)
2526

    
2527
    def postDetectLineProcess(self):
2528
        '''
2529
            @brief  check allowables among undetected items
2530
            @author euisung
2531
            @date   2018.11.15
2532
            @history    2018.11.15  euisung    no more used, moved to TextItemFactoy isLineNo()
2533
        '''
2534
        from TextItemFactory import TextItemFactory
2535

    
2536
        appDocData = AppDocData.instance()
2537

    
2538
        tableNames = ["Fluid Code", "Insulation Purpose", "PnID Number", "Piping Materials Class", "Unit Number"]
2539
        tableDatas = []
2540
        for tableName in tableNames:
2541
            tableNameFormat = tableName.replace(' ', '').replace('&&', 'n')
2542
            tableDatas.append(appDocData.getCodeTable(tableNameFormat))
2543

    
2544
        items = self.graphicsView.scene().items()
2545
        for item in items:
2546
            if type(item) is not QEngineeringTextItem:
2547
                continue
2548
            text = item.text()
2549
            for tableData in tableDatas:
2550
                for data in tableData:
2551
                    if data[3] == '':
2552
                        continue
2553
                    else:
2554
                        allows = data[3].split(',')
2555
                        for allow in allows:
2556
                            text = text.replace(allow, data[1])
2557

    
2558
            lineItem = TextItemFactory.instance().createTextItem(text)
2559
            if type(lineItem) is QEngineeringLineNoTextItem:
2560
                lineItem.loc = item.loc
2561
                lineItem.size = item.size
2562
                lineItem.angle = item.angle
2563
                lineItem.area = item.area
2564
                # lineItem.addTextItemToScene(self.graphicsView.scene())
2565
                lineItem.transfer.onRemoved.connect(self.itemRemoved)
2566
                item.transfer.onRemoved.emit(item)
2567
                appDocData.lineNos.append(lineItem)
2568

    
2569
    def init_add_tree_item(self, line_no_tree_item, run_item):
2570
        """ insert symbol item and find line no as owner """
2571
        # insert
2572
        self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2573
        # find
2574
        self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2575

    
2576
    def load_drawing(self, drawing):
2577
        """ load drawing """
2578
        from EngineeringRunItem import QEngineeringRunItem
2579
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2580

    
2581
        app_doc_data = AppDocData.instance()
2582
        try:
2583
            symbols = []
2584
            lines = []
2585

    
2586
            components = app_doc_data.get_components(drawing.UID)
2587
            maxValue = len(components) * 2
2588
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2589

    
2590
            """ parsing all symbols """
2591
            for symbol in [component for component in components if int(component['SymbolType_UID']) != -1]:
2592
                item = SymbolSvgItem.from_database(symbol)
2593
                if item is not None:
2594
                    item.transfer.onRemoved.connect(self.itemRemoved)
2595
                    symbols.append(item)
2596
                    app_doc_data.symbols.append(item)
2597
                    item.addSvgItemToScene(self.graphicsView.scene())
2598
                else:
2599
                    pt = [float(symbol['X']), float(symbol['Y'])]
2600
                    size = [float(symbol['Width']), float(symbol['Height'])]
2601
                    angle = float(symbol['Rotation'])
2602
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2603
                    item.isSymbol = True
2604
                    item.angle = angle
2605
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2606
                    self.graphicsView.scene().addItem(item)
2607
                    item.transfer.onRemoved.connect(self.itemRemoved)
2608

    
2609
                self.progress.setValue(self.progress.value() + 1)
2610

    
2611
            QApplication.processEvents()
2612

    
2613
            # parse texts
2614
            for text in [component for component in components if
2615
                         component['Name'] == 'Text' and component['SymbolType_UID'] == -1]:
2616
                item = QEngineeringTextItem.from_database(text)
2617
                if item is not None:
2618
                    item.uid = text['UID']
2619
                    item.attribute = text['Value']
2620
                    name = text['Name']
2621
                    item.transfer.onRemoved.connect(self.itemRemoved)
2622
                    item.addTextItemToScene(self.graphicsView.scene())
2623

    
2624
                self.progress.setValue(self.progress.value() + 1)
2625

    
2626
            QApplication.processEvents()
2627

    
2628
            # note
2629
            for note in [component for component in components if
2630
                         component['Name'] == 'Note' and component['SymbolType_UID'] == -1]:
2631
                item = QEngineeringTextItem.from_database(note)
2632
                if item is not None:
2633
                    item.uid = note['UID']
2634
                    attributeValue = note['Value']
2635
                    name = note['Name']
2636
                    item.transfer.onRemoved.connect(self.itemRemoved)
2637
                    item.addTextItemToScene(self.graphicsView.scene())
2638

    
2639
                self.progress.setValue(self.progress.value() + 1)
2640

    
2641
            QApplication.processEvents()
2642

    
2643
            for line in [component for component in components if
2644
                         component['Name'] == 'Line' and component['SymbolType_UID'] == -1]:
2645
                item = QEngineeringLineItem.from_database(line)
2646
                if item:
2647
                    item.transfer.onRemoved.connect(self.itemRemoved)
2648
                    self.graphicsView.scene().addItem(item)
2649
                    lines.append(item)
2650

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

    
2653
            QApplication.processEvents()
2654

    
2655
            for unknown in [component for component in components if
2656
                            component['Name'] == 'Unknown' and component['SymbolType_UID'] == -1]:
2657
                item = QEngineeringUnknownItem.from_database(unknown)
2658
                item.transfer.onRemoved.connect(self.itemRemoved)
2659
                if item is not None:
2660
                    item.transfer.onRemoved.connect(self.itemRemoved)
2661
                    self.graphicsView.scene().addItem(item)
2662

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

    
2665
            QApplication.processEvents()
2666

    
2667
            for component in [component for component in components if
2668
                              component['Name'] == 'Line NO' and component['SymbolType_UID'] == -1]:
2669
                line_no = QEngineeringLineNoTextItem.from_database(component)
2670
                if type(line_no) is QEngineeringLineNoTextItem:
2671
                    line_no.transfer.onRemoved.connect(self.itemRemoved)
2672
                    self.addTextItemToScene(line_no)
2673
                    line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2674

    
2675
                    runs = app_doc_data.get_pipe_runs(str(line_no.uid))
2676
                    if not runs: continue
2677
                    for run in runs:
2678
                        line_run = QEngineeringRunItem()
2679
                        run_items = app_doc_data.get_pipe_run_items(run['UID'])
2680
                        for record in run_items:
2681
                            uid = record['Components_UID']
2682
                            run_item = self.graphicsView.findItemByUid(uid)
2683
                            if run_item is not None:
2684
                                run_item._owner = line_no
2685
                                line_run.items.append(run_item)
2686
                        line_run.owner = line_no
2687
                        line_no.runs.append(line_run)
2688

    
2689
                        for run_item in line_run.items:
2690
                            if issubclass(type(run_item), SymbolSvgItem):
2691
                                self.init_add_tree_item(line_no_tree_item, run_item)
2692

    
2693
                self.progress.setValue(self.progress.value() + 1)
2694
            QApplication.processEvents()
2695

    
2696
            for component in [component for component in components if
2697
                              component['Name'] == 'Trim Line NO' and component['SymbolType_UID'] == -1]:
2698
                line_no = QEngineeringTrimLineNoTextItem()
2699
                line_no.uid = uuid.UUID(component['UID'])
2700

    
2701
                runs = app_doc_data.get_pipe_runs(str(line_no.uid))
2702
                if not runs: continue
2703

    
2704
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2705

    
2706
                for run in runs:
2707
                    line_run = QEngineeringRunItem()
2708
                    run_items = app_doc_data.get_pipe_run_items(run['UID'])
2709
                    for record in run_items:
2710
                        uid = record['Components_UID']
2711
                        run_item = self.graphicsView.findItemByUid(uid)
2712
                        if run_item is not None:
2713
                            run_item.owner = line_no
2714
                            line_run.items.append(run_item)
2715
                    line_run.owner = line_no
2716
                    line_no.runs.append(line_run)
2717

    
2718
                    for run_item in line_run.items:
2719
                        if issubclass(type(run_item), SymbolSvgItem):
2720
                            self.init_add_tree_item(line_no_tree_item, run_item)
2721

    
2722
                app_doc_data.tracerLineNos.append(line_no)
2723

    
2724
                self.progress.setValue(self.progress.value() + 1)
2725

    
2726
            for component in [component for component in components if
2727
                              component['Name'] == 'VendorPackage' and component['SymbolType_UID'] == -1]:
2728
                item = QEngineeringVendorItem.from_database(component)
2729
                if item is not None:
2730
                    item.transfer.onRemoved.connect(self.itemRemoved)
2731
                    self.graphicsView.scene().addItem(item)
2732

    
2733
            # connect flow item to line
2734
            for line in lines:
2735
                line.update_arrow()
2736
                app_doc_data.lines.append(line)
2737
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
2738
            #    for line in lines:
2739
            #        if flowMark.owner is line:
2740
            #            line._flowMark.append(flowMark)
2741
            #            flowMark.setParentItem(line)
2742
            # up to here
2743

    
2744
            """ update scene """
2745
            self.graphicsView.scene().update(self.graphicsView.sceneRect())
2746
            for item in self.graphicsView.scene().items():
2747
                up_progress = False
2748
                # binding items
2749
                if hasattr(item, 'owner'):
2750
                    item.owner
2751
                    up_progress = True
2752
                if hasattr(item, 'connectors'):
2753
                    for connector in item.connectors:
2754
                        connector.connectedItem
2755
                    up_progress = True
2756

    
2757
                if up_progress:
2758
                    self.progress.setValue(self.progress.value() + 1)
2759
            
2760
            for item in self.graphicsView.scene().items():
2761
                item.setVisible(True)
2762

    
2763
        except Exception as ex:
2764
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2765
                                                           sys.exc_info()[-1].tb_lineno)
2766
            self.addMessage.emit(MessageType.Error, message)
2767
        finally:
2768
            app_doc_data.clearTempDBData()
2769
            self.itemTreeWidget.update_item_count()
2770
            self.itemTreeWidget.expandAll()
2771
            # self.graphicsView.scene().blockSignals(False)
2772

    
2773
    '''
2774
        @brief      load recognition result
2775
        @author     humkyung
2776
        @date       2018.04.??
2777
        @history    humkyung 2018.01.12 parse originalpoint and connectionpoint
2778
                    Jeongwoo 2018.04.17 add QGraphicItem with Rotated text
2779
                    Jeongwoo 2018.04.23 Change to Draw texts on QEngineeringTextItem
2780
                    humkyung 2018.04.23 connect item remove slot to result tree
2781
                    Jeongwoo 2018.04.25 Add if state with QEngineeringNoteItem
2782
                    Jeongwoo 2018.04.26 Change method to create TextItem object with TextItemFactory
2783
                    Jeongwoo 2018.05.03 Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
2784
                    Jeongwoo 2018.05.29 Change method name / Change method to add item / Add Line item
2785
                    Jeongwoo 2018.05.30 Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol) / Change method name / Change XML NODE NAMES
2786
                    Jeongwoo 2018.06.12 Add LineNoTextItem from LINE_NO
2787
                    Jeongwoo 2018.06.14 Add UnknownItem from UNKNOWN
2788
                    Jeongwoo 2018.06.18 Update Scene after all item added
2789
                                        Add connect on unknown item
2790
                                        Add [transfer] for using pyqtSignal
2791
                    kyouho  2018.07.12  Add line property logic
2792
                    humkyung 2018.08.22 show progress while loading xml file
2793
                    2018.11.22      euisung     fix note road
2794
    '''
2795

    
2796
    def load_recognition_result_from_xml(self, drawing):
2797
        # Yield successive n-sized
2798
        # chunks from l.
2799
        def divide_chunks(l, n):
2800
            # looping till length l
2801
            for i in range(0, len(l), n):
2802
                yield l[i:i + n]
2803

    
2804
        def update_items(items):
2805
            for item in items:
2806
                # binding items
2807
                item.owner
2808
                for connector in item.connectors:
2809
                    connector.connectedItem
2810

    
2811
            return items
2812

    
2813
        import concurrent.futures as futures
2814
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
2815
        from App import App
2816
        from EngineeringRunItem import QEngineeringRunItem
2817
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2818
        from EngineeringGraphicsLineItem import QEngineeringGraphicsLineItem
2819

    
2820
        app_doc_data = AppDocData.instance()
2821

    
2822
        try:
2823
            file_name = os.path.splitext(os.path.basename(drawing.file_path))[0]
2824
            path = os.path.join(app_doc_data.getCurrentProject().getTempPath(), file_name + '.xml')
2825
            self.graphicsView.scene().blockSignals(True)
2826

    
2827
            symbols = []
2828
            lines = []
2829

    
2830
            xml = parse(path)
2831
            root = xml.getroot()
2832

    
2833
            maxValue = 0
2834
            maxValue = maxValue + len(list(root.iter('SYMBOL'))) - \
2835
                       len(list(root.iterfind('LINENOS/LINE_NO/RUN/SYMBOL'))) - \
2836
                       len(list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/SYMBOL')))
2837
            maxValue = maxValue + len(list(root.iterfind('TEXTINFOS/ATTRIBUTE')))
2838
            maxValue = maxValue + len(list(root.iterfind('NOTES/ATTRIBUTE')))
2839
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
2840
            maxValue = maxValue + len(list(root.iter('LINE'))) - \
2841
                       len(list(root.iterfind('LINENOS/LINE_NO/RUN/LINE'))) - \
2842
                       len(list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/LINE')))
2843
            maxValue = maxValue + len(list(root.iter('GRAPHICS_LINE')))
2844
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
2845
            # maxValue = maxValue + len(list(root.iter('SIZETEXT')))
2846
            maxValue = maxValue + len(list(root.iter('TRIM_LINE_NO')))
2847
            maxValue *= 2
2848
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2849

    
2850
            """ parsing all symbols """
2851
            """
2852
            with futures.ThreadPoolExecutor(max_workers=App.THREAD_MAX_WORKER) as pool:
2853
                future_symbol = {pool.submit(SymbolSvgItem.fromXml, symbol): symbol for symbol in root.find('SYMBOLS').iter('SYMBOL')}
2854

2855
                for future in futures.as_completed(future_symbol):
2856
                    try:
2857
                        item = future.result()
2858
                        if item:
2859
                            if item is not None:
2860
                                item.transfer.onRemoved.connect(self.itemRemoved)
2861
                                symbols.append(item)
2862
                                docData.symbols.append(item)
2863
                                self.addSvgItemToScene(item)
2864
                            else:
2865
                                pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2866
                                size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2867
                                angle = float(symbol.find('ANGLE').text)
2868
                                item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2869
                                item.isSymbol = True
2870
                                item.angle = angle
2871
                                item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2872
                                self.graphicsView.scene().addItem(item)
2873
                                item.transfer.onRemoved.connect(self.itemRemoved)
2874
                    except Exception as ex:
2875
                        message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
2876
                                                                       sys.exc_info()[-1].tb_lineno)
2877

2878
            """
2879
            for symbol in root.find('SYMBOLS').iter('SYMBOL'):
2880
                item = SymbolSvgItem.fromXml(symbol)
2881
                if item is not None:
2882
                    item.transfer.onRemoved.connect(self.itemRemoved)
2883
                    symbols.append(item)
2884
                    #app_doc_data.symbols.append(item)
2885
                    item.addSvgItemToScene(self.graphicsView.scene())
2886
                else:
2887
                    pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2888
                    size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2889
                    angle = float(symbol.find('ANGLE').text)
2890
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2891
                    item.isSymbol = True
2892
                    item.angle = angle
2893
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2894
                    self.graphicsView.scene().addItem(item)
2895
                    item.transfer.onRemoved.connect(self.itemRemoved)
2896

    
2897
                self.progress.setValue(self.progress.value() + 1)
2898

    
2899
            QApplication.processEvents()
2900

    
2901
            # parse texts
2902
            for text in root.find('TEXTINFOS').iter('ATTRIBUTE'):
2903
                item = QEngineeringTextItem.fromXml(text)
2904
                if item is not None:
2905
                    uid = text.find('UID')
2906
                    attributeValue = text.find('ATTRIBUTEVALUE')
2907
                    name = text.find('NAME').text
2908
                    item.transfer.onRemoved.connect(self.itemRemoved)
2909
                    item.addTextItemToScene(self.graphicsView.scene())
2910
                    # docData.texts.append(item)
2911

    
2912
                    if name == 'TEXT':
2913
                        if uid is not None and attributeValue is not None:
2914
                            item.uid = uid.text
2915
                            item.attribute = attributeValue.text
2916

    
2917
                self.progress.setValue(self.progress.value() + 1)
2918

    
2919
            QApplication.processEvents()
2920

    
2921
            # note
2922
            for text in root.find('NOTES').iter('ATTRIBUTE'):
2923
                item = QEngineeringTextItem.fromXml(text)
2924
                if item is not None:
2925
                    uid = text.find('UID')
2926
                    attributeValue = text.find('ATTRIBUTEVALUE')
2927
                    name = text.find('NAME').text
2928
                    item.transfer.onRemoved.connect(self.itemRemoved)
2929
                    item.addTextItemToScene(self.graphicsView.scene())
2930

    
2931
                    if name == 'NOTE':
2932
                        if uid is not None:
2933
                            item.uid = uid.text
2934

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

    
2937
            QApplication.processEvents()
2938

    
2939
            for line in root.find('LINEINFOS').iter('LINE'):
2940
                item = QEngineeringLineItem.fromXml(line)
2941
                if item:
2942
                    item.transfer.onRemoved.connect(self.itemRemoved)
2943
                    self.graphicsView.scene().addItem(item)
2944
                    lines.append(item)
2945

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

    
2948
            for line in root.find('LINEINFOS').iter('GRAPHICS_LINE'):
2949
                item = QEngineeringGraphicsLineItem.fromXml(line)
2950
                if item:
2951
                    item.transfer.onRemoved.connect(self.itemRemoved)
2952
                    self.graphicsView.scene().addItem(item)
2953

    
2954
                self.progress.setValue(self.progress.value() + 1)
2955

    
2956
            QApplication.processEvents()
2957

    
2958
            for unknown in root.iter('UNKNOWN'):
2959
                item = QEngineeringUnknownItem.fromXml(unknown)
2960
                if item is not None:
2961
                    item.transfer.onRemoved.connect(self.itemRemoved)
2962
                    self.graphicsView.scene().addItem(item)
2963

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

    
2966
            QApplication.processEvents()
2967

    
2968
            # """ add tree widget """
2969
            # for item in symbols:
2970
            #    docData.symbols.append(item)
2971
            #    self.addSvgItemToScene(item)
2972
            #    self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, item)
2973

    
2974
            for line_no_node in root.find('LINENOS').iter('LINE_NO'):
2975
                line_no = QEngineeringLineNoTextItem.fromXml(line_no_node)
2976
                if line_no is None: continue
2977
                line_no.transfer.onRemoved.connect(self.itemRemoved)
2978
                line_no.addTextItemToScene(self.graphicsView.scene())
2979
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2980
                if type(line_no) is not QEngineeringLineNoTextItem: continue
2981

    
2982
                runs_node = line_no_node.findall('RUN')
2983
                if runs_node is None: continue
2984

    
2985
                for run_node in runs_node:
2986
                    line_run = QEngineeringRunItem()
2987
                    for child_node in run_node:
2988
                        uidElement = child_node.find('UID')
2989
                        if uidElement is not None:
2990
                            uid = uidElement.text
2991
                            run_item = self.graphicsView.findItemByUid(uid)
2992
                            if run_item is not None:
2993
                                run_item._owner = line_no
2994
                                line_run.items.append(run_item)
2995
                    line_run.owner = line_no
2996
                    line_no.runs.append(line_run)
2997

    
2998
                    for run_item in line_run.items:
2999
                        if issubclass(type(run_item), SymbolSvgItem):
3000
                            self.init_add_tree_item(line_no_tree_item, run_item)
3001

    
3002
                # docData.tracerLineNos.append(line_no)
3003

    
3004
                self.progress.setValue(self.progress.value() + 1)
3005
            QApplication.processEvents()
3006

    
3007
            for trimLineNo in root.iter('TRIM_LINE_NO'):
3008
                line_no = QEngineeringTrimLineNoTextItem()
3009
                line_no.uid = uuid.UUID(trimLineNo.find('UID').text)
3010

    
3011
                runs_node = trimLineNo.findall('RUN')
3012
                if runs_node is None: continue
3013
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
3014

    
3015
                for run in runs_node:
3016
                    line_run = QEngineeringRunItem()
3017
                    for child in run:
3018
                        uidElement = child.find('UID')
3019
                        if uidElement is not None:
3020
                            uid = uidElement.text
3021
                            run_item = self.graphicsView.findItemByUid(uid)
3022
                            if run_item is not None:
3023
                                run_item.owner = line_no
3024
                                line_run.items.append(run_item)
3025
                    line_run.owner = line_no
3026
                    line_no.runs.append(line_run)
3027

    
3028
                    for run_item in line_run.items:
3029
                        if issubclass(type(run_item), SymbolSvgItem):
3030
                            self.init_add_tree_item(line_no_tree_item, run_item)
3031

    
3032
                app_doc_data.tracerLineNos.append(line_no)
3033

    
3034
                self.progress.setValue(self.progress.value() + 1)
3035
            QApplication.processEvents()
3036

    
3037
            if root.find('VENDORS') is not None:
3038
                for vendor in root.find('VENDORS').iter('VENDOR'):
3039
                    item = QEngineeringVendorItem.fromXml(vendor)
3040
                    item.transfer.onRemoved.connect(self.itemRemoved)
3041
                    self.graphicsView.scene().addItem(item)
3042

    
3043
            # connect flow item to line
3044
            for line in lines:
3045
                line.update_arrow()
3046
                app_doc_data.lines.append(line)
3047
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
3048
            #    for line in lines:
3049
            #        if flowMark.owner is line:
3050
            #            line._flowMark.append(flowMark)
3051
            #            flowMark.setParentItem(line)
3052
            # up to here
3053

    
3054
            """
3055
            group_box = QGroupBox("Contact Details")
3056
            number_label = QLabel("Telephone number");
3057
            number_edit = QTextEdit('hello\nthis is ....')
3058
            layout = QFormLayout()
3059
            layout.addRow(number_label, number_edit)
3060
            group_box.setLayout(layout)
3061

3062
            proxy =  ㅐ()
3063
            proxy.setWidget(group_box)
3064
            self.graphicsView.scene().addItem(proxy)  # (group_box, QGraphicsItem.ItemIgnoresTransformations)
3065
            """
3066

    
3067
            """ update scene """
3068
            _items = [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'owner') or hasattr(_item, 'connectors')]
3069
            if _items:
3070
                items = divide_chunks(_items, App.THREAD_MAX_WORKER if len(_items) > App.THREAD_MAX_WORKER else len(_items))
3071
                with futures.ThreadPoolExecutor(max_workers=App.THREAD_MAX_WORKER) as pool:
3072
                    future_items = {pool.submit(update_items, _items): _items for _items in items}
3073
                    for future in futures.as_completed(future_items):
3074
                        _items = future.result()
3075
                        self.progress.setValue(self.progress.value() + len(_items))
3076

    
3077
            """
3078
            for item in [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'owner') or hasattr(_item, 'connectors')]:
3079
                up_progress = False
3080
                # binding items
3081
                item.owner
3082
                for connector in item.connectors:
3083
                    connector.connectedItem
3084

3085
                self.progress.setValue(self.progress.value() + 1)
3086
            """
3087

    
3088
            for item in self.graphicsView.scene().items():
3089
                item.setVisible(True)
3090

    
3091
            self.graphicsView.scene().update(self.graphicsView.sceneRect())
3092
        except Exception as ex:
3093
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3094
                                                           sys.exc_info()[-1].tb_lineno)
3095
            self.addMessage.emit(MessageType.Error, message)
3096
        finally:
3097
            self.itemTreeWidget.update_item_count()
3098
            self.itemTreeWidget.expandAll()
3099
            self.graphicsView.scene().blockSignals(False)
3100

    
3101
    '''
3102
        @brief      Remove added item on same place and Add GraphicsItem
3103
        @author     Jeongwoo
3104
        @date       2018.05.29
3105
        @history    2018.06.18  Jeongwoo    Set Z-index
3106
    '''
3107

    
3108
    def addLineItemToScene(self, lineItem):
3109
        self.graphicsView.scene().addItem(lineItem)
3110

    
3111
    '''
3112
        @brief      generate output xml file
3113
        @author     humkyung
3114
        @date       2018.04.23
3115
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
3116
    '''
3117

    
3118
    def generateOutput(self):
3119
        import XmlGenerator as xg
3120

    
3121
        if not self.graphicsView.hasImage():
3122
            self.showImageSelectionMessageBox()
3123
            return
3124

    
3125
        try:
3126
            appDocData = AppDocData.instance()
3127

    
3128
            # collect items
3129
            appDocData.lines.clear()
3130
            appDocData.lines = [item for item in self.graphicsView.scene().items() if
3131
                                type(item) is QEngineeringLineItem and item.owner is None]
3132

    
3133
            appDocData.symbols.clear()
3134
            appDocData.symbols = [item for item in self.graphicsView.scene().items() if
3135
                                  issubclass(type(item), SymbolSvgItem) and item.owner is None]
3136

    
3137
            appDocData.equipments.clear()
3138
            for item in self.graphicsView.scene().items():
3139
                if type(item) is QEngineeringEquipmentItem:
3140
                    appDocData.equipments.append(item)
3141

    
3142
            appDocData.texts.clear()
3143
            appDocData.texts = [item for item in self.graphicsView.scene().items() if
3144
                                issubclass(type(item), QEngineeringTextItem) and type(
3145
                                    item) is not QEngineeringLineNoTextItem]
3146
            # up to here
3147

    
3148
            appDocData.imgOutput = np.ones((appDocData.activeDrawing.height, appDocData.activeDrawing.width),
3149
                                           np.uint8) * 255
3150
            xg.writeOutputXml(appDocData.imgName, appDocData.activeDrawing.width,
3151
                              appDocData.activeDrawing.height)  # TODO: check
3152
            project = appDocData.getCurrentProject()
3153
            cv2.imwrite(os.path.join(project.getTempPath(), 'OUTPUT.png'), appDocData.imgOutput)
3154
        except Exception as ex:
3155
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3156
                                                           sys.exc_info()[-1].tb_lineno)
3157
            self.addMessage.emit(MessageType.Error, message)
3158

    
3159
    '''
3160
        @brief      resetting attribute at secne
3161
        @author     kyoyho
3162
        @date       2018.08.21
3163
    '''
3164
    """
3165
    def checkAttribute(self):
3166
        try:
3167

3168
            docData = AppDocData.instance()
3169
            if not self.graphicsView.hasImage():
3170
                return
3171

3172
            # symbol 경우
3173
            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]
3174
            for item in items:
3175
                attrs = item.attrs
3176
                
3177
                removeAttrList = []
3178
                for attr in attrs:
3179
                    if type(attr) is tuple:
3180
                        continue
3181

3182
                    if attr is None:
3183
                        removeAttrList.append(attr)
3184
                        continue
3185

3186
                    attrInfo = docData.getSymbolAttributeByUID(attr.UID)
3187
                    if attrInfo is None:
3188
                        removeAttrList.append(attr)
3189
                    # 해당 attribute가 맞는지 확인
3190
                    else:
3191
                        attrType = attrInfo.AttributeType
3192
                        _type = type(attr)
3193
                        if attrType == 'Symbol Item':
3194
                            if not issubclass(_type, SymbolSvgItem):
3195
                                removeAttrList.append(attr)
3196
                        elif attrType == 'Text Item':
3197
                            if _type is not QEngineeringTextItem:
3198
                                removeAttrList.append(attr)
3199
                        elif attrType == 'Int':
3200
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
3201
                                removeAttrList.append(attr)
3202
                        elif attrType == 'String':
3203
                            if _type is not UserInputAttribute:
3204
                                removeAttrList.append(attr)
3205

3206
                for attr in removeAttrList:
3207
                    del attrs[attr]
3208

3209
            # Line No Text Item의 경우
3210
            items = [item for item in self.graphicsView.scene().items() if issubclass(type(item), QEngineeringLineNoTextItem)]
3211
            for item in items:
3212
                attrs = item.attrs
3213
                
3214
                removeAttrList = []
3215
                for attr in attrs:
3216
                    if type(attr) is UserInputAttribute:
3217
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
3218
                        if attrInfo is None:
3219
                            removeAttrList.append(attr)
3220

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

3224
        except Exception as ex:
3225
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
3226
                self.addMessage.emit(MessageType.Error, message)
3227
    """
3228
    '''
3229
        @brief      Check Number
3230
        @author     kyouho
3231
        @date       2018.08.20
3232
    '''
3233

    
3234
    def isNumber(self, num):
3235
        p = re.compile('(^[0-9]+$)')
3236
        result = p.match(num)
3237

    
3238
        if result:
3239
            return True
3240
        else:
3241
            return False
3242

    
3243
    '''
3244
        @brief      find overlap Connector
3245
        @author     kyouho
3246
        @date       2018.08.28
3247
    '''
3248

    
3249
    def findOverlapConnector(self, connectorItem):
3250
        from shapely.geometry import Point
3251
        from EngineeringConnectorItem import QEngineeringConnectorItem
3252
        itemList = []
3253

    
3254
        x = connectorItem.center()[0]
3255
        y = connectorItem.center()[1]
3256

    
3257
        connectors = [item for item in self.graphicsView.scene().items() if
3258
                      type(item) is QEngineeringConnectorItem and item != connectorItem]
3259
        for connector in connectors:
3260
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
3261
                itemList.append(connector.parent)
3262

    
3263
        return itemList
3264

    
3265
    def make_diff_image(self):
3266
        """ make diff image """
3267
        # test
3268

    
3269
        from RecognitionDialog import Worker
3270
        from symbol import Symbol
3271
        import math
3272
        from PIL import Image
3273

    
3274
        app_doc_data = AppDocData.instance()
3275
        img = app_doc_data.imgSrc.copy()
3276

    
3277
        # check break
3278
        symbols = [item for item in self.graphicsView.scene().items() if issubclass(type(item), SymbolSvgItem)]
3279

    
3280
        for symbol in symbols:
3281
            rect = symbol.sceneBoundingRect()
3282
            sName = symbol.name
3283
            sType = symbol.type
3284
            sp = (rect.x(), rect.y())
3285
            w, h = rect.width(), rect.height()
3286
            rotatedAngle = round(math.degrees(symbol.angle))
3287
            detectFlip = symbol.flip
3288

    
3289
            dummySym = Symbol(sName, sType, sp, w, h, 0, 0, 0, rotatedAngle,
3290
                                   1, 0, 1, 0,
3291
                                   ','.join(str(x) for x in [0, 0]),
3292
                                   '/'.join('{},{},{},{}'.format(param[0], param[1], param[2], param[3]) for param in
3293
                                            []),
3294
                                   'dummy', 'dummy', 0, detectFlip=detectFlip,
3295
                                   hasInstrumentLabel=0, text_area='')
3296

    
3297
            Worker.remove_detected_symbol_image(dummySym, img, lock=False)
3298

    
3299
        Image.fromarray(img).show()
3300

    
3301
if __name__ == '__main__':
3302
    import locale
3303
    from PyQt5.QtCore import QTranslator
3304
    from License import QLicenseDialog
3305
    from ProjectDialog import Ui_Dialog
3306
    from App import App
3307

    
3308
    app = App(sys.argv)
3309
    try:
3310
        if True == QLicenseDialog.check_license_key():
3311
            dlg = Ui_Dialog()
3312
            selectedProject = dlg.showDialog()
3313
            if selectedProject is not None:
3314
                AppDocData.instance().setCurrentProject(selectedProject)
3315
                app._mainWnd = MainWindow.instance()
3316
                app._mainWnd.show()
3317
                sys.exit(app.exec_())
3318
    except Exception as ex:
3319
        print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3320
                                                   sys.exc_info()[-1].tb_lineno))
3321
    finally:
3322
        pass
클립보드 이미지 추가 (최대 크기: 500 MB)