프로젝트

일반

사용자정보

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

hytos / DTI_PID / DTI_PID / MainWindow.py @ 23a1a458

이력 | 보기 | 이력해설 | 다운로드 (145 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 type(item) is 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

    
1789
    def onCreateSymbolClicked(self):
1790
        cmd = FenceCommand.FenceCommand(self.graphicsView)
1791
        cmd.onSuccess.connect(self.onAreaSelected)
1792
        self.graphicsView.command = cmd
1793
        QApplication.setOverrideCursor(Qt.CrossCursor)
1794

    
1795
    '''
1796
        @brief      show SymbolEditorDialog with image selected by user
1797
        @author     humkyung
1798
        @date       2018.07.20
1799
    '''
1800

    
1801
    def onAreaSelected(self, x, y, width, height):
1802
        try:
1803
            image = self.graphicsView.image()
1804
            if image is not None:
1805
                symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height),
1806
                                                                            AppDocData.instance().getCurrentProject())
1807
                (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
1808
                # TODO: not initialize symbol tree view when user reject to create a new symbol
1809
                self.symbolTreeWidget.initSymbolTreeView()
1810
                if isAccepted:
1811
                    if isImmediateInsert:
1812
                        svgPath = newSym.getSvgFileFullPath()
1813
                        img = cv2.imread(newSym.getImageFileFullPath(), 1)
1814
                        w, h = (0, 0)
1815
                        if len(img.shape[::-1]) == 2:
1816
                            w, h = img.shape[::-1]
1817
                        else:
1818
                            _chan, w, h = img.shape[::-1]
1819
                        svg = SymbolSvgItem(svgPath)
1820
                        svg.buildItem(newSym.getName(), newSym.getType(), 0, [offsetX, offsetY], [w, h],
1821
                                      [float(x) for x in newSym.getOriginalPoint().split(',')],
1822
                                      [(float(x.split(',')[0]), float(x.split(',')[1])) for x in
1823
                                       newSym.getConnectionPoint().split('/')], newSym.getBaseSymbol(),
1824
                                      newSym.getAdditionalSymbol(), newSym.getHasInstrumentLabel)
1825

    
1826
                        svg.transfer.onRemoved.connect(self.itemTreeWidget.itemRemoved)
1827
                        svg.addSvgItemToScene(self.graphicsView.scene())
1828
                        for connector in svg.connectors:
1829
                            self.graphicsView.scene().addItem(connector)
1830
        finally:
1831
            self.onCommandRejected()
1832
            QApplication.restoreOverrideCursor()
1833

    
1834
    def make_label_data(self):
1835
        """ make label data from symbol info """
1836
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
1837

    
1838
        if not self.graphicsView.hasImage():
1839
            self.showImageSelectionMessageBox()
1840
            return
1841

    
1842
        app_doc_data = AppDocData.instance()
1843
        project = app_doc_data.getCurrentProject()
1844

    
1845
        smalls = []
1846
        bigs = []
1847

    
1848
        symbol_list = app_doc_data.getTargetSymbolList(all=True)
1849
        for symbol in symbol_list:
1850
            if symbol.width and symbol.height:
1851
                if symbol.width > 300 or symbol.height > 300:
1852
                    bigs.append(symbol.getName())
1853
                else:
1854
                    smalls.append(symbol.getName())
1855

    
1856
        symbols = [item for item in self.graphicsView.scene().items() if issubclass(type(item), SymbolSvgItem)]
1857
        names = [smalls, bigs]
1858

    
1859
        img = app_doc_data.activeDrawing.image_origin
1860

    
1861
        small_size = 500
1862
        big_size = 850
1863

    
1864
        save_path = project.getTrainingSymbolFilePath()
1865

    
1866
        index = 0
1867
        for size in [small_size, big_size]:
1868
            offsets = [0, int(size / 2)]
1869

    
1870
            width, height = img.shape[1], img.shape[0]
1871
            width_count, height_count = width // size + 2, height // size + 2
1872
            b_width, b_height = width_count * size, height_count * size
1873
            b_img = np.zeros((b_height, b_width), np.uint8) + 255
1874
            b_img[:height, :width] = img[:, :]
1875

    
1876
            for offset in offsets:
1877
                for row in range(height_count):
1878
                    for col in range(width_count):
1879
                        x, y = col * size + offset, row * size + offset
1880
                        tile_rect = QRectF(x, y, size, size)
1881
                        tile_symbols = []
1882
                        for symbol in [symbol for symbol in symbols if symbol.name in names[index]]:
1883
                            if tile_rect.contains(symbol.sceneBoundingRect()):
1884
                                tile_symbols.append(symbol)
1885
                                symbols.remove(symbol)
1886

    
1887
                        if tile_symbols:
1888
                            training_uid = str(uuid.uuid4())
1889
                            training_image_path = os.path.join(save_path, training_uid + '.png')
1890
                            training_xml_path = os.path.join(save_path, training_uid + '.xml')
1891

    
1892
                            # save image
1893
                            #_img = b_img[round(tile_rect.top()):round(tile_rect.bottom()),
1894
                            #       round(tile_rect.left()):round(tile_rect.right())]
1895
                            #cv2.imwrite(training_image_path, _img)
1896
                            _img = self.graphicsView.image().copy(round(tile_rect.left()), round(tile_rect.top()), round(tile_rect.width()), round(tile_rect.height()))
1897
                            _img.save(training_image_path)
1898

    
1899
                            # save label
1900
                            xml = Element('annotation')
1901
                            SubElement(xml, 'folder').text = 'None'
1902
                            SubElement(xml, 'filename').text = os.path.basename(save_path)
1903

    
1904
                            pathNode = Element('path')
1905
                            pathNode.text = save_path.replace('/', '\\')
1906
                            xml.append(pathNode)
1907

    
1908
                            sourceNode = Element('source')
1909
                            databaseNode = Element('database')
1910
                            databaseNode.text = 'Unknown'
1911
                            sourceNode.append(databaseNode)
1912
                            xml.append(sourceNode)
1913

    
1914
                            sizeNode = Element('size')
1915
                            widthNode = Element('width')
1916
                            widthNode.text = str(int(tile_rect.width()))
1917
                            sizeNode.append(widthNode)
1918
                            heightNode = Element('height')
1919
                            heightNode.text = str(int(tile_rect.height()))
1920
                            sizeNode.append(heightNode)
1921
                            depthNode = Element('depth')
1922
                            depthNode.text = '3'
1923
                            sizeNode.append(depthNode)
1924
                            xml.append(sizeNode)
1925

    
1926
                            segmentedNode = Element('segmented')
1927
                            segmentedNode.text = '0'
1928
                            xml.append(segmentedNode)
1929

    
1930
                            labelContent = []
1931
                            counts = {}
1932
                            for item in tile_symbols:
1933
                                rect = item.sceneBoundingRect()
1934
                                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)
1935
                                xMin = xMin if xMin > 0 else 0
1936
                                yMin = yMin if yMin > 0 else 0
1937
                                xMax = xMax if xMax < size else size
1938
                                yMax = yMax if yMax < size else size
1939

    
1940
                                if label == 'None' or label == '':
1941
                                    continue
1942
                                if label not in labelContent:
1943
                                    labelContent.append(label)
1944
                                    counts[label] = 1
1945
                                else:
1946
                                    counts[label] = counts[label] + 1
1947

    
1948
                                objectNode = Element('object')
1949
                                nameNode = Element('name')
1950
                                nameNode.text = label
1951
                                objectNode.append(nameNode)
1952
                                poseNode = Element('pose')
1953
                                poseNode.text = 'Unspecified'
1954
                                objectNode.append(poseNode)
1955
                                truncatedNode = Element('truncated')
1956
                                truncatedNode.text = '0'
1957
                                objectNode.append(truncatedNode)
1958
                                difficultNode = Element('difficult')
1959
                                difficultNode.text = '0'
1960
                                objectNode.append(difficultNode)
1961

    
1962
                                bndboxNode = Element('bndbox')
1963
                                xminNode = Element('xmin')
1964
                                xminNode.text = str(xMin)
1965
                                bndboxNode.append(xminNode)
1966
                                yminNode = Element('ymin')
1967
                                yminNode.text = str(yMin)
1968
                                bndboxNode.append(yminNode)
1969
                                xmaxNode = Element('xmax')
1970
                                xmaxNode.text = str(xMax)
1971
                                bndboxNode.append(xmaxNode)
1972
                                ymaxNode = Element('ymax')
1973
                                ymaxNode.text = str(yMax)
1974
                                bndboxNode.append(ymaxNode)
1975
                                objectNode.append(bndboxNode)
1976

    
1977
                                xml.append(objectNode)
1978

    
1979
                            ElementTree(xml).write(training_xml_path)
1980

    
1981
            index += 1
1982

    
1983
        QMessageBox.about(self, self.tr("Notice"), self.tr('Successfully applied. '))
1984

    
1985
    '''
1986
        @brief      create a line
1987
        @author     humkyung
1988
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
1989
    '''
1990
    def onPlaceLine(self):
1991
        if not self.graphicsView.hasImage():
1992
            self.actionLine.setChecked(False)
1993
            self.showImageSelectionMessageBox()
1994
            return
1995

    
1996
        self.actionLine.setChecked(True)
1997
        if not hasattr(self.actionLine, 'tag'):
1998
            self.actionLine.tag = PlaceLineCommand.PlaceLineCommand(self.graphicsView)
1999
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
2000
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
2001

    
2002
        self.graphicsView.command = self.actionLine.tag
2003

    
2004
    '''
2005
        @brief      add created lines to scene
2006
        @author     humkyung
2007
        @date       2018.07.23
2008
    '''
2009

    
2010
    def onLineCreated(self):
2011
        from EngineeringConnectorItem import QEngineeringConnectorItem
2012
        from LineDetector import LineDetector
2013

    
2014
        try:
2015
            app_doc_data = AppDocData.instance()
2016

    
2017
            count = len(self.actionLine.tag._polyline._vertices)
2018
            if count > 1:
2019
                items = []
2020

    
2021
                detector = LineDetector(None)
2022

    
2023
                if not self.actionLine.tag.line_type:
2024
                    line_type = self.lineComboBox.currentText()
2025
                else:
2026
                    if not (QEngineeringLineItem.check_piping(self.actionLine.tag.line_type) ^ QEngineeringLineItem.check_piping(self.lineComboBox.currentText())):
2027
                        line_type = self.lineComboBox.currentText()
2028
                    else:
2029
                        line_type = self.actionLine.tag.line_type
2030
                for index in range(count - 1):
2031
                    start = self.actionLine.tag._polyline._vertices[index]
2032
                    end = self.actionLine.tag._polyline._vertices[index + 1]
2033

    
2034
                    lineItem = QEngineeringLineItem(vertices=[start, end])
2035
                    lineItem.transfer.onRemoved.connect(self.itemRemoved)
2036
                    lineItem.lineType = line_type
2037
                    if items:
2038
                        lineItem.connect_if_possible(items[-1], 5)
2039
                    else:
2040
                        pt = lineItem.start_point()
2041
                        selected = [item for item in self.graphicsView.scene().items(QPointF(pt[0], pt[1])) if
2042
                                    type(item) is QEngineeringConnectorItem or type(item) is QEngineeringLineItem]
2043
                        if selected and selected[0] is not lineItem:
2044
                            if type(selected[0]) is QEngineeringConnectorItem:
2045
                                lineItem.connect_if_possible(selected[0].parent, 5)
2046
                            else:
2047
                                detector.connectLineToLine(selected[0], lineItem, 5)
2048

    
2049
                    items.append(lineItem)
2050
                    self.graphicsView.scene().addItem(lineItem)
2051
                    #app_doc_data.lines.append(lineItem)
2052

    
2053
                pt = items[-1].end_point()
2054
                selected = [item for item in self.graphicsView.scene().items(QPointF(pt[0], pt[1])) if
2055
                            (type(item) is QEngineeringConnectorItem and item.parentItem() is not items[-1]) or
2056
                            (type(item) is QEngineeringLineItem and item is not items[-1])]
2057
                if selected and selected[0] is not items[-1]:
2058
                    if type(selected[0]) is QEngineeringConnectorItem:
2059
                        items[-1].connect_if_possible(selected[0].parent, 5)
2060
                    else:
2061
                        detector.connectLineToLine(selected[0], items[-1], 5)
2062

    
2063
                self._scene.undo_stack.push(CreateCommand(self._scene, items))
2064
        finally:
2065
            self.graphicsView.scene().removeItem(self.actionLine.tag._polyline)
2066
            self.actionLine.tag.reset()
2067

    
2068
    '''
2069
        @brief      refresh scene
2070
        @author     humkyung
2071
        @date       2018.07.23
2072
    '''
2073

    
2074
    def onCommandRejected(self, cmd=None):
2075
        try:
2076
            if type(cmd) is PlaceLineCommand.PlaceLineCommand:
2077
                if self.actionLine.tag._polyline:
2078
                    self.graphicsView.scene().removeItem(self.actionLine.tag._polyline)
2079
                self.graphicsView.scene().update()
2080
                self.actionLine.tag.reset()
2081

    
2082
                self.actionLine.setChecked(False)
2083
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
2084
                self.actionZoom.setChecked(False)
2085
            elif type(cmd) is AreaOcrCommand.AreaOcrCommand:
2086
                self.actionOCR.setChecked(False)
2087
            elif type(cmd) is PlacePolygonCommand.PlacePolygonCommand:
2088
                self.actionVendor.setChecked(False)
2089
            else:
2090
                if hasattr(self.actionLine, 'tag') and self.actionLine.tag._polyline:
2091
                    self.graphicsView.scene().removeItem(self.actionLine.tag._polyline)
2092
                    self.graphicsView.scene().update()
2093
                    self.actionLine.tag.reset()
2094
                if hasattr(self.actionVendor, 'tag') and self.actionVendor.tag._polyline:
2095
                    self.graphicsView.scene().removeItem(self.actionVendor.tag._polyline)
2096
                    self.graphicsView.scene().update()
2097
                    self.actionVendor.tag.reset()
2098
                self.actionLine.setChecked(False)
2099
                self.actionZoom.setChecked(False)
2100
                self.actionOCR.setChecked(False)
2101
                self.actionVendor.setChecked(False)
2102
        finally:
2103
            self.graphicsView.useDefaultCommand()
2104

    
2105
    '''
2106
        @brief      restore to default command when user press Escape key
2107
        @author     humkyung 
2108
        @date       2018.08.09
2109
        
2110
    '''
2111

    
2112
    def keyPressEvent(self, event):
2113
        try:
2114
            if event.key() == Qt.Key_Escape:
2115
                checked = self.actionGroup.checkedAction()
2116
                if checked:
2117
                    checked.setChecked(False)
2118
                    self.graphicsView.useDefaultCommand()
2119
            elif event.key() == Qt.Key_1:
2120
                if self.actionImage_Drawing.isChecked():
2121
                    self.onViewImageDrawing(False)
2122
                    self.actionImage_Drawing.setChecked(False)
2123
                else:
2124
                    self.onViewImageDrawing(True)
2125
                    self.actionImage_Drawing.setChecked(True)
2126
            elif event.key() == Qt.Key_2:
2127
                if self.actionViewText.isChecked():
2128
                    self.onViewText(False)
2129
                    self.actionViewText.setChecked(False)
2130
                else:
2131
                    self.onViewText(True)
2132
                    self.actionViewText.setChecked(True)
2133
            elif event.key() == Qt.Key_3:
2134
                if self.actionViewSymbol.isChecked():
2135
                    self.onViewSymbol(False)
2136
                    self.actionViewSymbol.setChecked(False)
2137
                else:
2138
                    self.onViewSymbol(True)
2139
                    self.actionViewSymbol.setChecked(True)
2140
            elif event.key() == Qt.Key_4:
2141
                if self.actionViewLine.isChecked():
2142
                    self.onViewLine(False)
2143
                    self.actionViewLine.setChecked(False)
2144
                else:
2145
                    self.onViewLine(True)
2146
                    self.actionViewLine.setChecked(True)
2147
            elif event.key() == Qt.Key_5:
2148
                if self.actionViewUnknown.isChecked():
2149
                    self.onViewUnknown(False)
2150
                    self.actionViewUnknown.setChecked(False)
2151
                else:
2152
                    self.onViewUnknown(True)
2153
                    self.actionViewUnknown.setChecked(True)
2154
            elif event.key() == Qt.Key_6:
2155
                if self.actionViewInconsistency.isChecked():
2156
                    self.onViewInconsistency(False)
2157
                    self.actionViewInconsistency.setChecked(False)
2158
                else:
2159
                    self.onViewInconsistency(True)
2160
                    self.actionViewInconsistency.setChecked(True)
2161
            elif event.key() == Qt.Key_7:
2162
                if self.actionViewVendor_Area.isChecked():
2163
                    self.onViewVendorArea(False)
2164
                    self.actionViewVendor_Area.setChecked(False)
2165
                else:
2166
                    self.onViewVendorArea(True)
2167
                    self.actionViewVendor_Area.setChecked(True)
2168
            elif event.key() == 96:  # '`' key
2169
                if self.actionDrawing_Only.isChecked():
2170
                    self.onViewDrawingOnly(False)
2171
                    self.actionDrawing_Only.setChecked(False)
2172
                else:
2173
                    self.onViewDrawingOnly(True)
2174
                    self.actionDrawing_Only.setChecked(True)
2175
            elif event.key() == Qt.Key_M:  # merge text as vertical
2176
                from TextInfo import TextInfo
2177

    
2178
                textItems = [text for text in self.graphicsView.scene().selectedItems() if
2179
                             issubclass(type(text), QEngineeringTextItem)]
2180
                if not textItems or len(textItems) is 1:
2181
                    return
2182

    
2183
                angle = None
2184
                for item in textItems:
2185
                    if angle is None:
2186
                        angle = item.angle
2187
                    else:
2188
                        if angle != item.angle:
2189
                            return
2190

    
2191
                modifiers = QApplication.keyboardModifiers()
2192
                enter_or_space = ' ' if modifiers == Qt.ControlModifier else '\n'
2193
                x_or_y = 0 if modifiers == Qt.ControlModifier else 1
2194

    
2195
                textItems = sorted(textItems, key=lambda text: text.loc[x_or_y]) if textItems[0].angle == 0 else ( \
2196
                    sorted(textItems, key=lambda text: text.loc[x_or_y]) if textItems[0].angle == 1.57 else ( \
2197
                        sorted(textItems, key=lambda text: text.loc[x_or_y], reverse=True) if textItems[0].angle == 4.71 else \
2198
                            sorted(textItems, key=lambda text: text.loc[x_or_y], reverse=True)))
2199

    
2200
                if textItems[0].angle == 1.57 and modifiers == Qt.ControlModifier:
2201
                    textItems.reverse()
2202

    
2203
                minX = sys.maxsize
2204
                minY = sys.maxsize
2205
                maxX = 0
2206
                maxY = 0
2207
                newText = ''
2208

    
2209
                for text in textItems:
2210
                    if text.loc[0] < minX: minX = text.loc[0]
2211
                    if text.loc[1] < minY: minY = text.loc[1]
2212
                    if text.loc[0] + text.size[0] > maxX: maxX = text.loc[0] + text.size[0]
2213
                    if text.loc[1] + text.size[1] > maxY: maxY = text.loc[1] + text.size[1]
2214
                    newText = newText + text.text() + enter_or_space
2215
                    text.transfer.onRemoved.emit(text)
2216
                newText = newText[:-1]
2217

    
2218
                textInfo = TextInfo(newText, minX, minY, maxX - minX, maxY - minY, textItems[0].angle)
2219
                x = textInfo.getX()
2220
                y = textInfo.getY()
2221
                angle = textInfo.getAngle()
2222
                text = textInfo.getText()
2223
                width = textInfo.getW()
2224
                height = textInfo.getH()
2225
                item = TextItemFactory.instance().createTextItem(textInfo)
2226
                if item is not None:
2227
                    item.loc = [x, y]
2228
                    item.size = (width, height)
2229
                    item.angle = angle
2230
                    item.setDefaultTextColor(Qt.blue)
2231
                    item.addTextItemToScene(self.graphicsView.scene())
2232
                    item.transfer.onRemoved.connect(self.itemRemoved)
2233
            elif event.key() == Qt.Key_D:
2234
                # pop up development toolkit dialog
2235
                from DevelopmentToolkitDialog import QDevelopmentToolkitDialog
2236

    
2237
                modifiers = QApplication.keyboardModifiers()
2238
                if modifiers == Qt.ControlModifier:
2239
                    dlg = QDevelopmentToolkitDialog(self, self.graphicsView)
2240
                    dlg.show()
2241
            elif event.key() == Qt.Key_I:
2242
                # insert symbol item that is selected symbol in tree to main window if symbol already selected on main window, replace
2243
                index = self.symbolTreeWidget.currentIndex()
2244
                proxy_model = self.symbolTreeWidget.model()
2245
                items = [proxy_model.sourceModel().itemFromIndex(proxy_model.mapToSource(index))]
2246
                if items and hasattr(items[0], 'svgFilePath'):
2247
                    symData = items[0].data(self.symbolTreeWidget.TREE_DATA_ROLE)
2248
                    symName = symData.getName()
2249
                else:
2250
                    return
2251

    
2252
                symbolItems = [symbol for symbol in self.graphicsView.scene().selectedItems() if
2253
                               issubclass(type(symbol), SymbolSvgItem)]
2254
                old_symbol = None
2255
                if symbolItems and len(symbolItems) is 1:
2256
                    old_symbol = symbolItems[0]
2257
                    #scenePos = QPoint(old_symbol.origin[0], old_symbol.origin[1])
2258
                    scenePos = old_symbol.mapToScene(old_symbol.transformOriginPoint())
2259
                    old_symbol.transfer.onRemoved.emit(old_symbol)
2260
                else:
2261
                    scenePos = self.current_pos
2262

    
2263
                svg = QtImageViewer.createSymbolObject(symName)
2264
                QtImageViewer.matchSymbolToLine(self.graphicsView.scene(), svg, scenePos)
2265

    
2266
                if old_symbol and svg:
2267
                    from ReplaceCommand import ReplaceCommand
2268

    
2269
                    cmd = ReplaceCommand(self.graphicsView.scene(), old_symbol, svg)
2270
                    self._scene.undo_stack.push(cmd)
2271
                    return
2272
            elif event.key() == Qt.Key_J:
2273
                # insert and connect symbol item that is selected symbol in tree to selected symbol
2274
                index = self.symbolTreeWidget.currentIndex()
2275
                proxy_model = self.symbolTreeWidget.model()
2276
                items = [proxy_model.sourceModel().itemFromIndex(proxy_model.mapToSource(index))]
2277
                if items and hasattr(items[0], 'svgFilePath'):
2278
                    symData = items[0].data(self.symbolTreeWidget.TREE_DATA_ROLE)
2279
                    symName = symData.getName()
2280
                else:
2281
                    return
2282

    
2283
                symbolItems = [symbol for symbol in self.graphicsView.scene().selectedItems() if
2284
                               issubclass(type(symbol), SymbolSvgItem)]
2285
                if symbolItems and len(symbolItems) is not 1:
2286
                    return
2287
                    
2288
                target_symbol = symbolItems[0]
2289
                index =  [index for index in range(len(target_symbol.conn_type)) \
2290
                            if target_symbol.conn_type[index] == 'Primary' or target_symbol.conn_type[index] == 'Secondary']
2291
                for connector in target_symbol.connectors:
2292
                    svg = QtImageViewer.createSymbolObject(symName)
2293
                    if len(svg.connectors) > 1: 
2294
                        if ((target_symbol.conn_type and target_symbol.connectors.index(connector) in index) or not target_symbol.conn_type) and \
2295
                                    (not connector.connectedItem or (connector.connectedItem and type(connector.connectedItem) is QEngineeringLineItem)):
2296
                            QtImageViewer.matchSymbolToLine(self.graphicsView.scene(), svg, connector.sceneBoundingRect().center())
2297
                    elif len(svg.connectors) == 1:
2298
                        if ((target_symbol.conn_type and target_symbol.connectors.index(connector) in index) or not target_symbol.conn_type) and \
2299
                                    not connector.connectedItem:
2300
                            QtImageViewer.matchSymbolToLine(self.graphicsView.scene(), svg, connector.sceneBoundingRect().center())
2301

    
2302
                if target_symbol:
2303
                    return
2304
            elif event.key() == Qt.Key_X:
2305
                app_doc_data = AppDocData.instance()
2306
                configs = app_doc_data.getAppConfigs('app', 'mode')
2307
                if configs and 1 == len(configs) and 'advanced' == configs[0].value:
2308
                    advanced = True
2309
                    items = self.graphicsView.scene().selectedItems()
2310
                    if items:
2311
                        item = self.symbolTreeWidget.currentItem()
2312
                        if item:
2313
                            self.symbolTreeWidget.showSymbolEditorDialog(item, 0)
2314

    
2315
            QMainWindow.keyPressEvent(self, event)
2316
        except Exception as ex:
2317
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2318
                                                           sys.exc_info()[-1].tb_lineno)
2319
            self.addMessage.emit(MessageType.Error, message)
2320

    
2321
    def recognize(self):
2322
        """recognize symbol, text and line for selected drawings"""
2323
        from datetime import datetime
2324
        from RecognitionDialog import QRecognitionDialog
2325

    
2326
        # save alarm
2327
        self.save_alarm_enable(False)
2328

    
2329
        app_doc_data = AppDocData.instance()
2330
        current_drawing, currentPid = None, None
2331

    
2332
        if self.graphicsView.hasImage():
2333
            current_drawing = app_doc_data.activeDrawing
2334
            currentPid = app_doc_data.activeDrawing.name
2335

    
2336
        # get checked drawings
2337
        drawing_top = self.treeWidgetDrawingList.topLevelItem(0)
2338
        count = drawing_top.childCount()
2339
        checked_drawings = {}
2340
        for idx in range(count):
2341
            child = drawing_top.child(idx)
2342
            if child.checkState(0) == Qt.Checked and child.data(Qt.UserRole, 0):
2343
                checked_drawings[child.data(Qt.UserRole, 0)] = child
2344
        # up to here
2345

    
2346
        # if there is no checked drawing
2347
        if current_drawing and currentPid and not checked_drawings:
2348
            for idx in range(count):
2349
                child = drawing_top.child(idx)
2350
                if child.data(Qt.UserRole, 0) is current_drawing:
2351
                    checked_drawings[child.data(Qt.UserRole, 0)] = child
2352

    
2353
        if not checked_drawings:
2354
            self.showImageSelectionMessageBox()
2355
            return
2356

    
2357
        try:
2358
            self.onClearLog()
2359
            dlg = QRecognitionDialog(self, [drawing for drawing in checked_drawings.keys()])
2360
            dlg.exec_()
2361

    
2362
            if current_drawing and current_drawing in checked_drawings.keys() and dlg.isTreated:
2363
                self.open_image_drawing(current_drawing, force=True)
2364

    
2365
            # save working date-time
2366
            _now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
2367
            for drawing, tree_item in checked_drawings.items():
2368
                drawing.datetime = _now
2369
                tree_item.setText(1, _now)
2370
            #app_doc_data.saveDrawings(checked_drawings.keys())
2371
            self.changeViewCheckedState(True)
2372
            # up to here
2373
        except Exception as ex:
2374
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
2375
                                                           sys.exc_info()[-1].tb_lineno)
2376
            self.addMessage.emit(MessageType.Error, message)
2377

    
2378
        # save alarm
2379
            self.save_alarm_enable(True)
2380

    
2381
    '''
2382
        @brief      remove item from tree widget and then remove from scene
2383
        @date       2018.05.25
2384
        @author     Jeongwoo
2385
    '''
2386

    
2387
    def itemRemoved(self, item):
2388
        try:
2389
            if type(item) is QEngineeringErrorItem:
2390
                # remove error item from inconsistency list
2391
                for row in range(self.tableWidgetInconsistency.rowCount()):
2392
                    if item is self.tableWidgetInconsistency.item(row, 0).tag:
2393
                        self.tableWidgetInconsistency.removeRow(row)
2394
                        break
2395

    
2396
                if item.scene() is not None: item.scene().removeItem(item)
2397
                del item
2398
            else:
2399
                self.itemTreeWidget.itemRemoved(item)
2400

    
2401
                matches = [_item for _item in self.graphicsView.scene().items() if
2402
                           hasattr(_item, 'connectors') and [connector for connector in _item.connectors if
2403
                                                             connector.connectedItem is item]]
2404
                for match in matches:
2405
                    for connector in match.connectors:
2406
                        if connector.connectedItem is item:
2407
                            connector.connectedItem = None
2408
                            connector.highlight(False)
2409

    
2410
                # matches = [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'remove_assoc_item')]
2411
                # for _item in matches:
2412
                #    _item.remove_assoc_item(item)
2413

    
2414
                app_doc_data = AppDocData.instance()
2415
                if type(item) is QEngineeringLineNoTextItem and item in app_doc_data.tracerLineNos:
2416
                    app_doc_data.tracerLineNos.pop(app_doc_data.tracerLineNos.index(item))
2417

    
2418
                if type(item) is QEngineeringLineItem and item in app_doc_data.lines:
2419
                    app_doc_data.lines.remove(item)
2420

    
2421
                matches = [_item for _item in self.graphicsView.scene().items() if
2422
                           type(_item) is QEngineeringLineNoTextItem]
2423
                matches.extend([lineNo for lineNo in app_doc_data.tracerLineNos if
2424
                                type(lineNo) is QEngineeringTrimLineNoTextItem])
2425
                for match in matches:
2426
                    if item is match.prop('From'):
2427
                        match.set_property('From', None)
2428
                    if item is match.prop('To'):
2429
                        match.set_property('To', None)
2430

    
2431
                    for run_index in reversed(range(len(match.runs))):
2432
                        run = match.runs[run_index]
2433
                        if item in run.items:
2434
                            index = run.items.index(item)
2435
                            run.items.pop(index)
2436
                            if not run.items:
2437
                                run.explode()
2438
                                if type(match) is QEngineeringTrimLineNoTextItem and not match.runs:
2439
                                    app_doc_data.tracerLineNos.pop(app_doc_data.tracerLineNos.index(match))
2440
                            # break
2441

    
2442
                matches = [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'owner')]
2443
                for match in matches:
2444
                    if match.owner is item:
2445
                        match.owner = None
2446

    
2447
                matches = [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'attrs')]
2448
                # done = False
2449
                for match in matches:
2450
                    assocs = match.associations()
2451
                    for assoc in assocs:
2452
                        if item is assoc:
2453
                            for attr in match.attrs.keys():
2454
                                if attr.AssocItem and str(item.uid) == str(attr.AssocItem.uid):
2455
                                    attr.AssocItem = None
2456
                                    match.attrs[attr] = ''
2457
                                    # done = True
2458
                            match.remove_assoc_item(item)
2459
                            break
2460
                    # if done: break
2461

    
2462
                if item.scene() is not None: item.scene().removeItem(item)
2463
        except Exception as ex:
2464
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2465
                                                           sys.exc_info()[-1].tb_lineno)
2466
            self.addMessage.emit(MessageType.Error, message)
2467

    
2468
    def connect_attributes(self, MainWindow):
2469
        """connect attributes to symbol"""
2470
        from LineNoTracer import LineNoTracer
2471
        from ConnectAttrDialog import QConnectAttrDialog
2472

    
2473
        if not self.graphicsView.hasImage():
2474
            self.showImageSelectionMessageBox()
2475
            return
2476

    
2477
        # save alarm
2478
        self.save_alarm_enable(False)
2479

    
2480
        try:
2481
            dlg = QConnectAttrDialog(self, self.graphicsView.scene())
2482
            dlg.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint)
2483
            dlg.exec_()
2484
            if dlg.isRunned:
2485
                self.itemTreeWidget.InitLineNoItems()
2486

    
2487
                # construct line no item
2488
                line_nos = AppDocData.instance().tracerLineNos
2489
                for line_no in line_nos:
2490
                    item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2491
                    connectedItems = line_no.getConnectedItems()
2492
                    for connectedItem in connectedItems:
2493
                        if issubclass(type(connectedItem), SymbolSvgItem):
2494
                            self.itemTreeWidget.addTreeItem(item, connectedItem)
2495
                # up to here
2496

    
2497
                if dlg.validation_checked:
2498
                    self.onValidation()
2499

    
2500
                self.graphicsView.invalidateScene()
2501
        except Exception as ex:
2502
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2503
                                                           sys.exc_info()[-1].tb_lineno)
2504
            self.addMessage.emit(MessageType.Error, message)
2505
        finally:
2506
            # save alarm
2507
            self.save_alarm_enable(True)
2508

    
2509
    def postDetectLineProcess(self):
2510
        '''
2511
            @brief  check allowables among undetected items
2512
            @author euisung
2513
            @date   2018.11.15
2514
            @history    2018.11.15  euisung    no more used, moved to TextItemFactoy isLineNo()
2515
        '''
2516
        from TextItemFactory import TextItemFactory
2517

    
2518
        appDocData = AppDocData.instance()
2519

    
2520
        tableNames = ["Fluid Code", "Insulation Purpose", "PnID Number", "Piping Materials Class", "Unit Number"]
2521
        tableDatas = []
2522
        for tableName in tableNames:
2523
            tableNameFormat = tableName.replace(' ', '').replace('&&', 'n')
2524
            tableDatas.append(appDocData.getCodeTable(tableNameFormat))
2525

    
2526
        items = self.graphicsView.scene().items()
2527
        for item in items:
2528
            if type(item) is not QEngineeringTextItem:
2529
                continue
2530
            text = item.text()
2531
            for tableData in tableDatas:
2532
                for data in tableData:
2533
                    if data[3] == '':
2534
                        continue
2535
                    else:
2536
                        allows = data[3].split(',')
2537
                        for allow in allows:
2538
                            text = text.replace(allow, data[1])
2539

    
2540
            lineItem = TextItemFactory.instance().createTextItem(text)
2541
            if type(lineItem) is QEngineeringLineNoTextItem:
2542
                lineItem.loc = item.loc
2543
                lineItem.size = item.size
2544
                lineItem.angle = item.angle
2545
                lineItem.area = item.area
2546
                # lineItem.addTextItemToScene(self.graphicsView.scene())
2547
                lineItem.transfer.onRemoved.connect(self.itemRemoved)
2548
                item.transfer.onRemoved.emit(item)
2549
                appDocData.lineNos.append(lineItem)
2550

    
2551
    def init_add_tree_item(self, line_no_tree_item, run_item):
2552
        """ insert symbol item and find line no as owner """
2553
        # insert
2554
        self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2555
        # find
2556
        self.itemTreeWidget.addTreeItem(line_no_tree_item, run_item)
2557

    
2558
    def load_drawing(self, drawing):
2559
        """ load drawing """
2560
        from EngineeringRunItem import QEngineeringRunItem
2561
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2562

    
2563
        app_doc_data = AppDocData.instance()
2564
        try:
2565
            symbols = []
2566
            lines = []
2567

    
2568
            components = app_doc_data.get_components(drawing.UID)
2569
            maxValue = len(components) * 2
2570
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2571

    
2572
            """ parsing all symbols """
2573
            for symbol in [component for component in components if int(component['SymbolType_UID']) != -1]:
2574
                item = SymbolSvgItem.from_database(symbol)
2575
                if item is not None:
2576
                    item.transfer.onRemoved.connect(self.itemRemoved)
2577
                    symbols.append(item)
2578
                    app_doc_data.symbols.append(item)
2579
                    item.addSvgItemToScene(self.graphicsView.scene())
2580
                else:
2581
                    pt = [float(symbol['X']), float(symbol['Y'])]
2582
                    size = [float(symbol['Width']), float(symbol['Height'])]
2583
                    angle = float(symbol['Rotation'])
2584
                    item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2585
                    item.isSymbol = True
2586
                    item.angle = angle
2587
                    item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2588
                    self.graphicsView.scene().addItem(item)
2589
                    item.transfer.onRemoved.connect(self.itemRemoved)
2590

    
2591
                self.progress.setValue(self.progress.value() + 1)
2592

    
2593
            QApplication.processEvents()
2594

    
2595
            # parse texts
2596
            for text in [component for component in components if
2597
                         component['Name'] == 'Text' and component['SymbolType_UID'] == -1]:
2598
                item = QEngineeringTextItem.from_database(text)
2599
                if item is not None:
2600
                    item.uid = text['UID']
2601
                    item.attribute = text['Value']
2602
                    name = text['Name']
2603
                    item.transfer.onRemoved.connect(self.itemRemoved)
2604
                    item.addTextItemToScene(self.graphicsView.scene())
2605

    
2606
                self.progress.setValue(self.progress.value() + 1)
2607

    
2608
            QApplication.processEvents()
2609

    
2610
            # note
2611
            for note in [component for component in components if
2612
                         component['Name'] == 'Note' and component['SymbolType_UID'] == -1]:
2613
                item = QEngineeringTextItem.from_database(note)
2614
                if item is not None:
2615
                    item.uid = note['UID']
2616
                    attributeValue = note['Value']
2617
                    name = note['Name']
2618
                    item.transfer.onRemoved.connect(self.itemRemoved)
2619
                    item.addTextItemToScene(self.graphicsView.scene())
2620

    
2621
                self.progress.setValue(self.progress.value() + 1)
2622

    
2623
            QApplication.processEvents()
2624

    
2625
            for line in [component for component in components if
2626
                         component['Name'] == 'Line' and component['SymbolType_UID'] == -1]:
2627
                item = QEngineeringLineItem.from_database(line)
2628
                if item:
2629
                    item.transfer.onRemoved.connect(self.itemRemoved)
2630
                    self.graphicsView.scene().addItem(item)
2631
                    lines.append(item)
2632

    
2633
                self.progress.setValue(self.progress.value() + 1)
2634

    
2635
            QApplication.processEvents()
2636

    
2637
            for unknown in [component for component in components if
2638
                            component['Name'] == 'Unknown' and component['SymbolType_UID'] == -1]:
2639
                item = QEngineeringUnknownItem.from_database(unknown)
2640
                item.transfer.onRemoved.connect(self.itemRemoved)
2641
                if item is not None:
2642
                    item.transfer.onRemoved.connect(self.itemRemoved)
2643
                    self.graphicsView.scene().addItem(item)
2644

    
2645
                self.progress.setValue(self.progress.value() + 1)
2646

    
2647
            QApplication.processEvents()
2648

    
2649
            for component in [component for component in components if
2650
                              component['Name'] == 'Line NO' and component['SymbolType_UID'] == -1]:
2651
                line_no = QEngineeringLineNoTextItem.from_database(component)
2652
                if type(line_no) is QEngineeringLineNoTextItem:
2653
                    line_no.transfer.onRemoved.connect(self.itemRemoved)
2654
                    self.addTextItemToScene(line_no)
2655
                    line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2656

    
2657
                    runs = app_doc_data.get_pipe_runs(str(line_no.uid))
2658
                    if not runs: continue
2659
                    for run in runs:
2660
                        line_run = QEngineeringRunItem()
2661
                        run_items = app_doc_data.get_pipe_run_items(run['UID'])
2662
                        for record in run_items:
2663
                            uid = record['Components_UID']
2664
                            run_item = self.graphicsView.findItemByUid(uid)
2665
                            if run_item is not None:
2666
                                run_item._owner = line_no
2667
                                line_run.items.append(run_item)
2668
                        line_run.owner = line_no
2669
                        line_no.runs.append(line_run)
2670

    
2671
                        for run_item in line_run.items:
2672
                            if issubclass(type(run_item), SymbolSvgItem):
2673
                                self.init_add_tree_item(line_no_tree_item, run_item)
2674

    
2675
                self.progress.setValue(self.progress.value() + 1)
2676
            QApplication.processEvents()
2677

    
2678
            for component in [component for component in components if
2679
                              component['Name'] == 'Trim Line NO' and component['SymbolType_UID'] == -1]:
2680
                line_no = QEngineeringTrimLineNoTextItem()
2681
                line_no.uid = uuid.UUID(component['UID'])
2682

    
2683
                runs = app_doc_data.get_pipe_runs(str(line_no.uid))
2684
                if not runs: continue
2685

    
2686
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2687

    
2688
                for run in runs:
2689
                    line_run = QEngineeringRunItem()
2690
                    run_items = app_doc_data.get_pipe_run_items(run['UID'])
2691
                    for record in run_items:
2692
                        uid = record['Components_UID']
2693
                        run_item = self.graphicsView.findItemByUid(uid)
2694
                        if run_item is not None:
2695
                            run_item.owner = line_no
2696
                            line_run.items.append(run_item)
2697
                    line_run.owner = line_no
2698
                    line_no.runs.append(line_run)
2699

    
2700
                    for run_item in line_run.items:
2701
                        if issubclass(type(run_item), SymbolSvgItem):
2702
                            self.init_add_tree_item(line_no_tree_item, run_item)
2703

    
2704
                app_doc_data.tracerLineNos.append(line_no)
2705

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

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

    
2715
            # connect flow item to line
2716
            for line in lines:
2717
                line.update_arrow()
2718
                app_doc_data.lines.append(line)
2719
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
2720
            #    for line in lines:
2721
            #        if flowMark.owner is line:
2722
            #            line._flowMark.append(flowMark)
2723
            #            flowMark.setParentItem(line)
2724
            # up to here
2725

    
2726
            """ update scene """
2727
            self.graphicsView.scene().update(self.graphicsView.sceneRect())
2728
            for item in self.graphicsView.scene().items():
2729
                up_progress = False
2730
                # binding items
2731
                if hasattr(item, 'owner'):
2732
                    item.owner
2733
                    up_progress = True
2734
                if hasattr(item, 'connectors'):
2735
                    for connector in item.connectors:
2736
                        connector.connectedItem
2737
                    up_progress = True
2738

    
2739
                if up_progress:
2740
                    self.progress.setValue(self.progress.value() + 1)
2741
            
2742
            for item in self.graphicsView.scene().items():
2743
                item.setVisible(True)
2744

    
2745
        except Exception as ex:
2746
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2747
                                                           sys.exc_info()[-1].tb_lineno)
2748
            self.addMessage.emit(MessageType.Error, message)
2749
        finally:
2750
            app_doc_data.clearTempDBData()
2751
            self.itemTreeWidget.update_item_count()
2752
            self.itemTreeWidget.expandAll()
2753
            # self.graphicsView.scene().blockSignals(False)
2754

    
2755
    '''
2756
        @brief      load recognition result
2757
        @author     humkyung
2758
        @date       2018.04.??
2759
        @history    humkyung 2018.01.12 parse originalpoint and connectionpoint
2760
                    Jeongwoo 2018.04.17 add QGraphicItem with Rotated text
2761
                    Jeongwoo 2018.04.23 Change to Draw texts on QEngineeringTextItem
2762
                    humkyung 2018.04.23 connect item remove slot to result tree
2763
                    Jeongwoo 2018.04.25 Add if state with QEngineeringNoteItem
2764
                    Jeongwoo 2018.04.26 Change method to create TextItem object with TextItemFactory
2765
                    Jeongwoo 2018.05.03 Change method to draw Svg Item on Scene (svg.addSvgItemToScene)
2766
                    Jeongwoo 2018.05.29 Change method name / Change method to add item / Add Line item
2767
                    Jeongwoo 2018.05.30 Add parameters on SymbolSvgItem.__init__() (parentSymbol, childSymbol) / Change method name / Change XML NODE NAMES
2768
                    Jeongwoo 2018.06.12 Add LineNoTextItem from LINE_NO
2769
                    Jeongwoo 2018.06.14 Add UnknownItem from UNKNOWN
2770
                    Jeongwoo 2018.06.18 Update Scene after all item added
2771
                                        Add connect on unknown item
2772
                                        Add [transfer] for using pyqtSignal
2773
                    kyouho  2018.07.12  Add line property logic
2774
                    humkyung 2018.08.22 show progress while loading xml file
2775
                    2018.11.22      euisung     fix note road
2776
    '''
2777

    
2778
    def load_recognition_result_from_xml(self, drawing):
2779
        # Yield successive n-sized
2780
        # chunks from l.
2781
        def divide_chunks(l, n):
2782
            # looping till length l
2783
            for i in range(0, len(l), n):
2784
                yield l[i:i + n]
2785

    
2786
        def update_items(items):
2787
            for item in items:
2788
                # binding items
2789
                item.owner
2790
                for connector in item.connectors:
2791
                    connector.connectedItem
2792

    
2793
            return items
2794

    
2795
        import concurrent.futures as futures
2796
        from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
2797
        from App import App
2798
        from EngineeringRunItem import QEngineeringRunItem
2799
        from QEngineeringTrimLineNoTextItem import QEngineeringTrimLineNoTextItem
2800
        from EngineeringGraphicsLineItem import QEngineeringGraphicsLineItem
2801

    
2802
        app_doc_data = AppDocData.instance()
2803

    
2804
        try:
2805
            file_name = os.path.splitext(os.path.basename(drawing.file_path))[0]
2806
            path = os.path.join(app_doc_data.getCurrentProject().getTempPath(), file_name + '.xml')
2807
            self.graphicsView.scene().blockSignals(True)
2808

    
2809
            symbols = []
2810
            lines = []
2811

    
2812
            xml = parse(path)
2813
            root = xml.getroot()
2814

    
2815
            maxValue = 0
2816
            maxValue = maxValue + len(list(root.iter('SYMBOL'))) - \
2817
                       len(list(root.iterfind('LINENOS/LINE_NO/RUN/SYMBOL'))) - \
2818
                       len(list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/SYMBOL')))
2819
            maxValue = maxValue + len(list(root.iterfind('TEXTINFOS/ATTRIBUTE')))
2820
            maxValue = maxValue + len(list(root.iterfind('NOTES/ATTRIBUTE')))
2821
            maxValue = maxValue + len(list(root.iter('LINE_NO')))
2822
            maxValue = maxValue + len(list(root.iter('LINE'))) - \
2823
                       len(list(root.iterfind('LINENOS/LINE_NO/RUN/LINE'))) - \
2824
                       len(list(root.iterfind('TRIMLINENOS/TRIM_LINE_NO/RUN/LINE')))
2825
            maxValue = maxValue + len(list(root.iter('GRAPHICS_LINE')))
2826
            maxValue = maxValue + len(list(root.iter('UNKNOWN')))
2827
            # maxValue = maxValue + len(list(root.iter('SIZETEXT')))
2828
            maxValue = maxValue + len(list(root.iter('TRIM_LINE_NO')))
2829
            maxValue *= 2
2830
            self.progress.setMaximum(maxValue) if maxValue > 0 else None
2831

    
2832
            """ parsing all symbols """
2833
            """
2834
            with futures.ThreadPoolExecutor(max_workers=App.THREAD_MAX_WORKER) as pool:
2835
                future_symbol = {pool.submit(SymbolSvgItem.fromXml, symbol): symbol for symbol in root.find('SYMBOLS').iter('SYMBOL')}
2836

2837
                for future in futures.as_completed(future_symbol):
2838
                    try:
2839
                        item = future.result()
2840
                        if item:
2841
                            if item is not None:
2842
                                item.transfer.onRemoved.connect(self.itemRemoved)
2843
                                symbols.append(item)
2844
                                docData.symbols.append(item)
2845
                                self.addSvgItemToScene(item)
2846
                            else:
2847
                                pt = [float(x) for x in symbol.find('LOCATION').text.split(',')]
2848
                                size = [float(x) for x in symbol.find('SIZE').text.split(',')]
2849
                                angle = float(symbol.find('ANGLE').text)
2850
                                item = QGraphicsBoundingBoxItem(pt[0], pt[1], size[0], size[1])
2851
                                item.isSymbol = True
2852
                                item.angle = angle
2853
                                item.setPen(QPen(Qt.red, 5, Qt.SolidLine))
2854
                                self.graphicsView.scene().addItem(item)
2855
                                item.transfer.onRemoved.connect(self.itemRemoved)
2856
                    except Exception as ex:
2857
                        message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
2858
                                                                       sys.exc_info()[-1].tb_lineno)
2859

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

    
2879
                self.progress.setValue(self.progress.value() + 1)
2880

    
2881
            QApplication.processEvents()
2882

    
2883
            # parse texts
2884
            for text in root.find('TEXTINFOS').iter('ATTRIBUTE'):
2885
                item = QEngineeringTextItem.fromXml(text)
2886
                if item is not None:
2887
                    uid = text.find('UID')
2888
                    attributeValue = text.find('ATTRIBUTEVALUE')
2889
                    name = text.find('NAME').text
2890
                    item.transfer.onRemoved.connect(self.itemRemoved)
2891
                    item.addTextItemToScene(self.graphicsView.scene())
2892
                    # docData.texts.append(item)
2893

    
2894
                    if name == 'TEXT':
2895
                        if uid is not None and attributeValue is not None:
2896
                            item.uid = uid.text
2897
                            item.attribute = attributeValue.text
2898

    
2899
                self.progress.setValue(self.progress.value() + 1)
2900

    
2901
            QApplication.processEvents()
2902

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

    
2913
                    if name == 'NOTE':
2914
                        if uid is not None:
2915
                            item.uid = uid.text
2916

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

    
2919
            QApplication.processEvents()
2920

    
2921
            for line in root.find('LINEINFOS').iter('LINE'):
2922
                item = QEngineeringLineItem.fromXml(line)
2923
                if item:
2924
                    item.transfer.onRemoved.connect(self.itemRemoved)
2925
                    self.graphicsView.scene().addItem(item)
2926
                    lines.append(item)
2927

    
2928
                self.progress.setValue(self.progress.value() + 1)
2929

    
2930
            for line in root.find('LINEINFOS').iter('GRAPHICS_LINE'):
2931
                item = QEngineeringGraphicsLineItem.fromXml(line)
2932
                if item:
2933
                    item.transfer.onRemoved.connect(self.itemRemoved)
2934
                    self.graphicsView.scene().addItem(item)
2935

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

    
2938
            QApplication.processEvents()
2939

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

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

    
2948
            QApplication.processEvents()
2949

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

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

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

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

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

    
2984
                # docData.tracerLineNos.append(line_no)
2985

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

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

    
2993
                runs_node = trimLineNo.findall('RUN')
2994
                if runs_node is None: continue
2995
                line_no_tree_item = self.itemTreeWidget.addTreeItem(self.itemTreeWidget.root, line_no)
2996

    
2997
                for run in runs_node:
2998
                    line_run = QEngineeringRunItem()
2999
                    for child in run:
3000
                        uidElement = child.find('UID')
3001
                        if uidElement is not None:
3002
                            uid = uidElement.text
3003
                            run_item = self.graphicsView.findItemByUid(uid)
3004
                            if run_item is not None:
3005
                                run_item.owner = line_no
3006
                                line_run.items.append(run_item)
3007
                    line_run.owner = line_no
3008
                    line_no.runs.append(line_run)
3009

    
3010
                    for run_item in line_run.items:
3011
                        if issubclass(type(run_item), SymbolSvgItem):
3012
                            self.init_add_tree_item(line_no_tree_item, run_item)
3013

    
3014
                app_doc_data.tracerLineNos.append(line_no)
3015

    
3016
                self.progress.setValue(self.progress.value() + 1)
3017
            QApplication.processEvents()
3018

    
3019
            if root.find('VENDORS') is not None:
3020
                for vendor in root.find('VENDORS').iter('VENDOR'):
3021
                    item = QEngineeringVendorItem.fromXml(vendor)
3022
                    item.transfer.onRemoved.connect(self.itemRemoved)
3023
                    self.graphicsView.scene().addItem(item)
3024

    
3025
            # connect flow item to line
3026
            for line in lines:
3027
                line.update_arrow()
3028
                app_doc_data.lines.append(line)
3029
            # for flowMark in [item for item in symbols if type(item) is QEngineeringFlowMarkItem]:
3030
            #    for line in lines:
3031
            #        if flowMark.owner is line:
3032
            #            line._flowMark.append(flowMark)
3033
            #            flowMark.setParentItem(line)
3034
            # up to here
3035

    
3036
            """
3037
            group_box = QGroupBox("Contact Details")
3038
            number_label = QLabel("Telephone number");
3039
            number_edit = QTextEdit('hello\nthis is ....')
3040
            layout = QFormLayout()
3041
            layout.addRow(number_label, number_edit)
3042
            group_box.setLayout(layout)
3043

3044
            proxy = QGraphicsProxyWidget()
3045
            proxy.setWidget(group_box)
3046
            self.graphicsView.scene().addItem(proxy)  # (group_box, QGraphicsItem.ItemIgnoresTransformations)
3047
            """
3048

    
3049
            """ update scene """
3050
            _items = [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'owner') or hasattr(_item, 'connectors')]
3051
            if _items:
3052
                items = divide_chunks(_items, App.THREAD_MAX_WORKER if len(_items) > App.THREAD_MAX_WORKER else len(_items))
3053
                with futures.ThreadPoolExecutor(max_workers=App.THREAD_MAX_WORKER) as pool:
3054
                    future_items = {pool.submit(update_items, _items): _items for _items in items}
3055
                    for future in futures.as_completed(future_items):
3056
                        _items = future.result()
3057
                        self.progress.setValue(self.progress.value() + len(_items))
3058

    
3059
            """
3060
            for item in [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'owner') or hasattr(_item, 'connectors')]:
3061
                up_progress = False
3062
                # binding items
3063
                item.owner
3064
                for connector in item.connectors:
3065
                    connector.connectedItem
3066

3067
                self.progress.setValue(self.progress.value() + 1)
3068
            """
3069

    
3070
            for item in self.graphicsView.scene().items():
3071
                item.setVisible(True)
3072

    
3073
            self.graphicsView.scene().update(self.graphicsView.sceneRect())
3074
        except Exception as ex:
3075
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3076
                                                           sys.exc_info()[-1].tb_lineno)
3077
            self.addMessage.emit(MessageType.Error, message)
3078
        finally:
3079
            self.itemTreeWidget.update_item_count()
3080
            self.itemTreeWidget.expandAll()
3081
            self.graphicsView.scene().blockSignals(False)
3082

    
3083
    '''
3084
        @brief      Remove added item on same place and Add GraphicsItem
3085
        @author     Jeongwoo
3086
        @date       2018.05.29
3087
        @history    2018.06.18  Jeongwoo    Set Z-index
3088
    '''
3089

    
3090
    def addLineItemToScene(self, lineItem):
3091
        self.graphicsView.scene().addItem(lineItem)
3092

    
3093
    '''
3094
        @brief      generate output xml file
3095
        @author     humkyung
3096
        @date       2018.04.23
3097
        @history    2018.05.02  Jeongwoo    Show MessageBox when imageviewer doesn't have image
3098
    '''
3099

    
3100
    def generateOutput(self):
3101
        import XmlGenerator as xg
3102

    
3103
        if not self.graphicsView.hasImage():
3104
            self.showImageSelectionMessageBox()
3105
            return
3106

    
3107
        try:
3108
            appDocData = AppDocData.instance()
3109

    
3110
            # collect items
3111
            appDocData.lines.clear()
3112
            appDocData.lines = [item for item in self.graphicsView.scene().items() if
3113
                                type(item) is QEngineeringLineItem and item.owner is None]
3114

    
3115
            appDocData.symbols.clear()
3116
            appDocData.symbols = [item for item in self.graphicsView.scene().items() if
3117
                                  issubclass(type(item), SymbolSvgItem) and item.owner is None]
3118

    
3119
            appDocData.equipments.clear()
3120
            for item in self.graphicsView.scene().items():
3121
                if type(item) is QEngineeringEquipmentItem:
3122
                    appDocData.equipments.append(item)
3123

    
3124
            appDocData.texts.clear()
3125
            appDocData.texts = [item for item in self.graphicsView.scene().items() if
3126
                                issubclass(type(item), QEngineeringTextItem) and type(
3127
                                    item) is not QEngineeringLineNoTextItem]
3128
            # up to here
3129

    
3130
            appDocData.imgOutput = np.ones((appDocData.activeDrawing.height, appDocData.activeDrawing.width),
3131
                                           np.uint8) * 255
3132
            xg.writeOutputXml(appDocData.imgName, appDocData.activeDrawing.width,
3133
                              appDocData.activeDrawing.height)  # TODO: check
3134
            project = appDocData.getCurrentProject()
3135
            cv2.imwrite(os.path.join(project.getTempPath(), 'OUTPUT.png'), appDocData.imgOutput)
3136
        except Exception as ex:
3137
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
3138
                                                           sys.exc_info()[-1].tb_lineno)
3139
            self.addMessage.emit(MessageType.Error, message)
3140

    
3141
    '''
3142
        @brief      resetting attribute at secne
3143
        @author     kyoyho
3144
        @date       2018.08.21
3145
    '''
3146
    """
3147
    def checkAttribute(self):
3148
        try:
3149

3150
            docData = AppDocData.instance()
3151
            if not self.graphicsView.hasImage():
3152
                return
3153

3154
            # symbol 경우
3155
            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]
3156
            for item in items:
3157
                attrs = item.attrs
3158
                
3159
                removeAttrList = []
3160
                for attr in attrs:
3161
                    if type(attr) is tuple:
3162
                        continue
3163

3164
                    if attr is None:
3165
                        removeAttrList.append(attr)
3166
                        continue
3167

3168
                    attrInfo = docData.getSymbolAttributeByUID(attr.UID)
3169
                    if attrInfo is None:
3170
                        removeAttrList.append(attr)
3171
                    # 해당 attribute가 맞는지 확인
3172
                    else:
3173
                        attrType = attrInfo.AttributeType
3174
                        _type = type(attr)
3175
                        if attrType == 'Symbol Item':
3176
                            if not issubclass(_type, SymbolSvgItem):
3177
                                removeAttrList.append(attr)
3178
                        elif attrType == 'Text Item':
3179
                            if _type is not QEngineeringTextItem:
3180
                                removeAttrList.append(attr)
3181
                        elif attrType == 'Int':
3182
                            if _type is not UserInputAttribute and self.isNumber(attr.text):
3183
                                removeAttrList.append(attr)
3184
                        elif attrType == 'String':
3185
                            if _type is not UserInputAttribute:
3186
                                removeAttrList.append(attr)
3187

3188
                for attr in removeAttrList:
3189
                    del attrs[attr]
3190

3191
            # Line No Text Item의 경우
3192
            items = [item for item in self.graphicsView.scene().items() if issubclass(type(item), QEngineeringLineNoTextItem)]
3193
            for item in items:
3194
                attrs = item.attrs
3195
                
3196
                removeAttrList = []
3197
                for attr in attrs:
3198
                    if type(attr) is UserInputAttribute:
3199
                        attrInfo = docData.getLinePropertiesByUID(attr.attribute)
3200
                        if attrInfo is None:
3201
                            removeAttrList.append(attr)
3202

3203
                for attr in removeAttrList:
3204
                    del attrs[attr]
3205

3206
        except Exception as ex:
3207
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
3208
                self.addMessage.emit(MessageType.Error, message)
3209
    """
3210
    '''
3211
        @brief      Check Number
3212
        @author     kyouho
3213
        @date       2018.08.20
3214
    '''
3215

    
3216
    def isNumber(self, num):
3217
        p = re.compile('(^[0-9]+$)')
3218
        result = p.match(num)
3219

    
3220
        if result:
3221
            return True
3222
        else:
3223
            return False
3224

    
3225
    '''
3226
        @brief      find overlap Connector
3227
        @author     kyouho
3228
        @date       2018.08.28
3229
    '''
3230

    
3231
    def findOverlapConnector(self, connectorItem):
3232
        from shapely.geometry import Point
3233
        from EngineeringConnectorItem import QEngineeringConnectorItem
3234
        itemList = []
3235

    
3236
        x = connectorItem.center()[0]
3237
        y = connectorItem.center()[1]
3238

    
3239
        connectors = [item for item in self.graphicsView.scene().items() if
3240
                      type(item) is QEngineeringConnectorItem and item != connectorItem]
3241
        for connector in connectors:
3242
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
3243
                itemList.append(connector.parent)
3244

    
3245
        return itemList
3246

    
3247
    def make_diff_image(self):
3248
        """ make diff image """
3249
        # test
3250

    
3251
        from RecognitionDialog import Worker
3252
        from symbol import Symbol
3253
        import math
3254
        from PIL import Image
3255

    
3256
        app_doc_data = AppDocData.instance()
3257
        img = app_doc_data.imgSrc.copy()
3258

    
3259
        # check break
3260
        symbols = [item for item in self.graphicsView.scene().items() if issubclass(type(item), SymbolSvgItem)]
3261

    
3262
        for symbol in symbols:
3263
            rect = symbol.sceneBoundingRect()
3264
            sName = symbol.name
3265
            sType = symbol.type
3266
            sp = (rect.x(), rect.y())
3267
            w, h = rect.width(), rect.height()
3268
            rotatedAngle = round(math.degrees(symbol.angle))
3269
            detectFlip = symbol.flip
3270

    
3271
            dummySym = Symbol(sName, sType, sp, w, h, 0, 0, 0, rotatedAngle,
3272
                                   1, 0, 1, 0,
3273
                                   ','.join(str(x) for x in [0, 0]),
3274
                                   '/'.join('{},{},{},{}'.format(param[0], param[1], param[2], param[3]) for param in
3275
                                            []),
3276
                                   'dummy', 'dummy', 0, detectFlip=detectFlip,
3277
                                   hasInstrumentLabel=0, text_area='')
3278

    
3279
            Worker.remove_detected_symbol_image(dummySym, img, lock=False)
3280

    
3281
        Image.fromarray(img).show()
3282

    
3283
if __name__ == '__main__':
3284
    import locale
3285
    from PyQt5.QtCore import QTranslator
3286
    from License import QLicenseDialog
3287
    from ProjectDialog import Ui_Dialog
3288
    from App import App
3289

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