프로젝트

일반

사용자정보

통계
| 개정판:

hytos / HYTOS / HYTOS / MainWindow.py @ 5bcb1a4f

이력 | 보기 | 이력해설 | 다운로드 (61.8 KB)

1
# -*- coding: utf-8 -*-
2
""" This is MainWindow module """
3

    
4
import sys
5
import os
6
import subprocess
7
from functools import partial
8

    
9
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
10
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Commands')
11
import CreateCommand
12
import CropCommand
13
import AreaZoomCommand
14
import FenceCommand
15
import PlaceStreamlineCommand
16

    
17
import numpy as np
18

    
19
from PyQt5.QtCore import *
20
from PyQt5.QtGui import *
21
from PyQt5.QtWidgets import *
22
from PyQt5.QtSvg import *
23

    
24
from PIL import Image
25

    
26
import MainWindow_UI
27
import QtImageViewer
28
from SingletonInstance import SingletonInstane
29

    
30
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Shapes')
31
from EngineeringPolylineItem import QEngineeringPolylineItem
32
from SymbolSvgItem import SymbolSvgItem
33

    
34
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
35
from EngineeringTextItem import QEngineeringTextItem
36
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
37
from QEngineeringSizeTextItem import QEngineeringSizeTextItem
38
from EngineeringErrorItem import QEngineeringErrorItem
39
from EngineeringStreamlineItem import QEngineeringStreamlineItem
40
from AppDocData import *
41
import SymbolTreeWidget
42
import uuid
43

    
44

    
45
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane):
46
    """ This is MainWindow class """
47
    addMessage = pyqtSignal(Enum, str)
48

    
49
    '''
50
        @brief      initialize
51
        @author 
52
        @date   
53
        @history    humkyung 2018.04.12 add splitter widget
54
                    Jeongwoo 2018.04.27 Add Signal/Slot Connection 'noteNoSingleClicked'
55
                    Jeongwoo 2018.05.09 Initialize Action group
56
                    Jeongwoo 2018.05.10 Add Signal/Slot Connection 'lineNoSingleClicked'
57
                                        Add QActionGroup for managing checkable action
58
                    Jeongwoo 2018.06.27 Add Action [Zoom, Fit Window] and Add new actions into ActionGroup
59
                    humkyung 2018.08.23 add labelStatus to statusbar
60

61
    '''
62

    
63
    def __init__(self):
64
        try:
65
            super(self.__class__, self).__init__()
66
            self.setupUi(self)
67

    
68
            self._label_mouse = QLabel(self.statusbar)
69
            self._label_mouse.setText(self.tr('mouse pos : ({},{})'.format(0, 0)))
70
            self.statusbar.addWidget(self._label_mouse)
71
            self.addMessage.connect(self.onAddMessage)
72
            self.showMaximized()
73

    
74
            self.setMainWindowTitle()
75

    
76
            self.graphicsView = QtImageViewer.QtImageViewer(self)
77
            self.graphicsView.setParent(self.centralwidget)
78
            self.graphicsView.useDefaultCommand()
79
            self.graphicsView.setMouseTracking(True)
80
            self.graphicsView.viewport().installEventFilter(self)
81
            self.verticalLayout.addWidget(self.graphicsView)
82

    
83
            # Add Symbol TreeWidget
84
            self.symbolTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
85
            self.symbolTreeWidget.header().hide()
86
            self.verticalLayoutSymbolList.addWidget(self.symbolTreeWidget)
87

    
88
            # Initialize Action group
89
            self.actionGroup = QActionGroup(self)
90
            self.actionGroup.addAction(self.actionLine)
91
            self.actionGroup.addAction(self.actionZoom)
92
            self.actionGroup.addAction(self.actionFitWindow)
93
            self.actionGroup.addAction(self.actionSave)
94

    
95
            # connect signals and slots
96
            self.actionGroup.triggered.connect(self.actionGroupTriggered)
97
            self.actionClose.triggered.connect(self.close)
98
            self.actionNew.triggered.connect(self.on_new_drawing)
99
            self.actionOpen.triggered.connect(self.on_open_drawing)
100
            self.actionSave.triggered.connect(self.actionSaveCliked)
101
            self.actionCalculation.triggered.connect(self.calculation)
102
            self.actionLine.triggered.connect(self.onPlaceLine)
103
            self.actionConfiguration.triggered.connect(self.configuration)
104
            self.actionInitialize.triggered.connect(self.onInitializeScene)
105
            self.actionOptions.triggered.connect(self.onOptions)
106
            self.actionZoom.triggered.connect(self.onAreaZoom)
107
            self.actionFitWindow.triggered.connect(self.fitWindow)
108
            self.actionSymbol_Editor.triggered.connect(self.showSymbolEditor)
109
            self.toolButton_ClearLog.clicked.connect(self.clearlogs)
110
            self.graphicsView.scene.selectionChanged.connect(self.onSelectionChanged)
111

    
112
            self.treeWidgetDrawingList.setContextMenuPolicy(Qt.CustomContextMenu)
113
            self.treeWidgetDrawingList.customContextMenuRequested.connect(self.openContextMenu)
114
            self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing)
115

    
116
            self.initTreeWidgetDrawingList()
117
            self.initTableWidgetHMB()
118
            self.load_drawing_list()
119

    
120
            self.load_stylesheet_file()
121
            self.load_language_file()
122
        except Exception as ex:
123
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
124
                                                           sys.exc_info()[-1].tb_lineno)
125
            self.addMessage.emit(MessageType.Error, message)
126

    
127
    def load_stylesheet_file(self):
128
        # load stylesheet file list
129
        stylesheet_name = QtWidgets.qApp.stylesheet_name
130
        files = [os.path.splitext(file)[0] for file in os.listdir(os.path.dirname(os.path.realpath(__file__))) if
131
                 os.path.splitext(file)[1] == '.qss']
132
        for file in files:
133
            action = self.menuTheme.addAction(file)
134
            action.setCheckable(True)
135
            action.setChecked(True) if stylesheet_name == file else action.setChecked(False)
136
            action.triggered.connect(partial(self.load_stylesheet, file))
137
        # up to here
138

    
139
    def load_language_file(self):
140
        # load language files
141
        language_name = QtWidgets.qApp.language_name
142
        files = ['en_us']  # englisgh is default language
143
        files.extend([os.path.splitext(file)[0] for file in
144
                      os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate')) if
145
                      os.path.splitext(file)[1] == '.qm'])
146
        for file in files:
147
            action = self.menuLanguage.addAction(file)
148
            action.setCheckable(True)
149
            action.setChecked(True) if language_name.lower() == file.lower() else action.setChecked(False)
150
            action.triggered.connect(partial(self.load_language, file))
151
        # up to here
152

    
153
    def setMainWindowTitle(self, drawingName=None):
154
        try:
155
            _translate = QCoreApplication.translate
156

    
157
            version = QCoreApplication.applicationVersion()
158
            if drawingName is None:
159
                self.setWindowTitle(_translate(App.NAME + "({})".format(version), App.NAME + "({})".format(version)))
160
            else:
161
                self.setWindowTitle(
162
                    _translate(App.NAME + "({})".format(version), App.NAME + "({})".format(version)) + ' - {}'.format(
163
                        drawingName))
164
        except Exception as ex:
165
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
166
                                                           sys.exc_info()[-1].tb_lineno)
167
            self.addMessage.emit(MessageType.Error, message)
168

    
169
    def clearlogs(self):
170
        try:
171
            self.listWidgetLogs.clear()
172
        except Exception as ex:
173
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
174
                                                           sys.exc_info()[-1].tb_lineno)
175
            self.addMessage.emit(MessageType.Error, message)
176
        finally:
177
            logs = self.listWidgetLogs.count()
178
            if logs:
179
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs({})'.format(logs))
180
            else:
181
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs')
182

    
183
    def openContextMenu(self, position):
184
        indexes = self.treeWidgetDrawingList.selectedIndexes()
185
        if len(indexes) > 0:
186
            level = 0
187
            index = indexes[0]
188
            while index.parent().isValid():
189
                index = index.parent()
190
                level += 1
191

    
192
            menu = QMenu()
193

    
194
            itemPosition = self.mapTo(self, position)
195
            item = self.treeWidgetDrawingList.itemAt(itemPosition)
196

    
197
            if level == 0:
198
                newDrawingAction = menu.addAction(self.tr('New...'))
199
                newDrawingAction.triggered.connect(lambda: self.newDrawingActionClickEvent(item))
200
                menu.addAction(newDrawingAction)
201
            elif level == 1:
202
                # saveAsDrawingAction = menu.addAction(self.tr("Save As..."))
203
                # saveAsDrawingAction.triggered.connect(lambda: self.saveAsDrawingActionClickEvent(item))
204
                # menu.addAction(saveAsDrawingAction)
205

    
206
                deleteDrawingAction = menu.addAction(self.tr("Delete"))
207
                deleteDrawingAction.triggered.connect(lambda: self.deleteDrawingActionClickEvent(item))
208
                menu.addAction(deleteDrawingAction)
209

    
210
            menu.exec_(self.treeWidgetDrawingList.viewport().mapToGlobal(position))
211

    
212
    def on_new_drawing(self):
213
        self.new_drawing()
214

    
215
    def newDrawingActionClickEvent(self, item):
216
        self.new_drawing()
217

    
218
    def saveAsDrawingActionClickEvent(self, item):
219
        sourceDb = item.text(2)
220

    
221
        self.saveAs_drawing(sourceDb)
222

    
223
    def deleteDrawingActionClickEvent(self, item):
224
        """ delete selected drawing """
225
        try:
226
            msg = QMessageBox(self)
227
            msg.setIcon(QMessageBox.Question)
228
            msg.setText(self.tr('Do you want to delete drawing on list?\nHowever, Actual drawing is not deleted.'))
229
            msg.setWindowTitle(self.tr("Delete"))
230
            msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
231

    
232
            if QMessageBox.Ok == msg.exec_():
233
                drawingName = item.text(0)
234
                drawingPath = item.text(2)
235

    
236
                app_doc_data = AppDocData.instance()
237
                app_doc_data.deleteDrawingByName(drawingPath)
238

    
239
                if app_doc_data.activeDrawing:
240
                    if drawingName == app_doc_data.activeDrawing.name and drawingPath == app_doc_data.activeDrawing.path:
241
                        app_doc_data.activeDrawing = None
242

    
243
                        if self.graphicsView.hasImage():
244
                            self.graphicsView.clearImage()
245
                            self.graphicsView.scene.clear()
246

    
247
                        self.initTableWidgetHMB()
248

    
249
                self.load_drawing_list()
250
        except Exception as ex:
251
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
252
                                                           sys.exc_info()[-1].tb_lineno)
253
            self.addMessage.emit(MessageType.Error, message)
254

    
255
    def clear_data(self):
256
        self.clear_HMB()
257

    
258
    def eventFilter(self, source, event):
259
        """ display mouse position of graphics view """
260
        if (event.type() == QEvent.MouseMove):
261
            pos = self.graphicsView.mapToScene(event.pos())
262
            self._label_mouse.setText('mouse pos : ({},{})'.format(round(pos.x()), round(pos.y())))
263

    
264
        return QWidget.eventFilter(self, source, event)
265

    
266
    def load_stylesheet(self, file):
267
        """
268
        @brief  load stylesheets
269
        @author humkyung
270
        @date   2018.10.29
271
        """
272

    
273
        QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
274

    
275
        app_doc_data = AppDocData.instance()
276
        configs = [Config('app', 'stylesheet', file)]
277
        app_doc_data.saveAppConfigs(configs)
278

    
279
        for action in self.menuTheme.actions():
280
            if action.text() == file: continue
281
            action.setChecked(False)
282

    
283
    def load_language(self, file):
284
        """
285
        load language file and then apply selected language 
286
        """
287
        try:
288

    
289
            qm_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate', '{0}.qm'.format(file))
290
            QtWidgets.qApp.load_language(qm_file)
291

    
292
            app_doc_data = AppDocData.instance()
293
            configs = [Config('app', 'language', file)]
294
            app_doc_data.saveAppConfigs(configs)
295

    
296
            for action in self.menuLanguage.actions():
297
                if action.text().lower() == file.lower(): continue
298
                action.setChecked(False)
299
        finally:
300
            self.retranslateUi(self)
301

    
302
    def initTreeWidgetDrawingList(self):
303

    
304
        self.treeWidgetDrawingList.setHeaderHidden(False)
305
        self.treeWidgetDrawingList.header().setStretchLastSection(True)
306
        self.treeWidgetDrawingList.header().setDefaultAlignment(Qt.AlignCenter)
307
        self.treeWidgetDrawingList.setHeaderLabels([self.tr('Name'), self.tr('DateTime'), self.tr('Path')])
308
        self.treeWidgetDrawingList.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
309
        self.treeWidgetDrawingList.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
310
        self.treeWidgetDrawingList.header().setSectionResizeMode(2, QHeaderView.ResizeToContents)
311
        self.treeWidgetDrawingList.hideColumn(2)
312

    
313
    def initTableWidgetHMB(self):
314
        app_doc_data = AppDocData.instance()
315

    
316
        columnInfos = app_doc_data.getHMBDisplayNameAndUnitsExpression()
317
        count = len(columnInfos)
318
        self.tableWidgetHMB.setRowCount(count)
319
        if len(columnInfos) > 0:
320
            self.tableWidgetHMB.setColumnCount(2)
321
        else:
322
            self.tableWidgetHMB.setColumnCount(0)
323
        self.tableWidgetHMB.hideRow(0)  # uid
324
        self.tableWidgetHMB.hideRow(1)  # components_uid
325
        self.tableWidgetHMB.hideRow(2)  # stream no
326
        self.tableWidgetHMB.setEditTriggers(QAbstractItemView.NoEditTriggers)
327
        self.tableWidgetHMB.verticalHeader().setVisible(False)
328

    
329
        col_names = ['Stream No.', 'Unit']
330
        self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
331

    
332
        rowIndex = 0
333
        for columnInfo in columnInfos:
334
            name = columnInfo[0]
335
            unit = self.convertToUnits(columnInfo[1])
336

    
337
            self.tableWidgetHMB.setItem(rowIndex, 0,
338
                                        self.setTableWidgetItemProperties(name, Qt.AlignLeft | Qt.AlignVCenter,
339
                                                                          QColor(230, 230, 230)))
340
            self.tableWidgetHMB.setItem(rowIndex, 1,
341
                                        self.setTableWidgetItemProperties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
342
                                                                          QColor(230, 230, 230)))
343

    
344
            rowIndex += 1
345

    
346
        self.tableWidgetHMB.resizeColumnsToContents()
347
        self.tableWidgetHMB.resizeRowsToContents()
348

    
349
    '''
350
        @brief      Drawing 속성의 Units 에서 Key값을 이용하여 Value를 찾음
351
        @author     yeonjin
352
        @date       19.08.30
353
    '''
354

    
355
    def findValue(self, key):
356
        value = None
357

    
358
        key = key.replace("{", "").replace("}", "")
359
        for attr in AppDocData.instance().activeDrawing.attrs:
360
            if attr[0] == 'Units':
361
                if key in attr[1]:
362
                    value = attr[1][key]
363
                    break
364

    
365
        return value
366

    
367
    '''
368
        @brief      Convert UnitsExpression To Units Value
369
        @author     yeonjin
370
        @date       19.08.29
371
    '''
372

    
373
    def convertToUnits(self, unitsExpression):
374
        import re
375

    
376
        if unitsExpression is None or AppDocData.instance().activeDrawing is None:
377
            return ''
378

    
379
        found = re.findall('{.*?}', unitsExpression)
380
        for f in found:
381
            key = f
382
            val = self.findValue(key)
383
            if val:
384
                unitsExpression = unitsExpression.replace(key, val)
385

    
386
        return unitsExpression
387

    
388
    '''
389
        @brief      Clear TreeWidget and Set Current PID
390
        @author     Jeongwoo
391
        @date       18.04.11
392
        @history    2018.04.26  Jeongwoo    Add Child [SYMBOLS, NOTES] into root item
393
                    2018.05.09  Jeongwoo    Change method to add default tree items
394
                    humkyung 2018.06.10 add tree item for Line No and Unknown Item
395
    '''
396

    
397
    def load_drawing_list(self):
398
        """
399
        @brief      load p&id drawing list
400
        @author     humkyung
401
        @date       18.11.02
402
        """
403

    
404
        try:
405
            app_doc_data = AppDocData.instance()
406
            drawings = app_doc_data.getDrawings()
407

    
408
            self.treeWidgetDrawingList.clear()
409
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList, [self.tr('Drawings'), ''])
410

    
411
            for drawing in drawings:
412
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [drawing.name, drawing.date_time, drawing.path])
413
                item.setData(0, Qt.UserRole, drawing)
414

    
415
            self.treeWidgetDrawingList.root.setText(0, self.tr('Drawings') + '({})'.format(
416
                self.treeWidgetDrawingList.root.childCount()))
417
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
418
            self.treeWidgetDrawingList.sortByColumn(1, Qt.DescendingOrder)
419
            self.treeWidgetDrawingList.resizeColumnToContents(0)
420

    
421
        except Exception as ex:
422
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
423
                                                           sys.exc_info()[-1].tb_lineno)
424
            self.addMessage.emit(MessageType.Error, message)
425

    
426
    def open_selected_drawing(self, item):
427
        """ open selected drawing """
428
        path = item.text(2)
429
        if os.path.exists(path):
430
            self.open_drawing(path)
431

    
432
    '''
433
        @brief      action save click event
434
        @author     kyouho
435
        @date       2018.08.09
436
        @history    2018.11.02      euisung     add line data list db update
437
                    humkyung save saved time to database
438
                    2018.11.05      euisung     add note data list db update
439
                    2018.11.05      euisung     add db delete process before save
440
                    2018.11.12      euisung     db part move new method to dbUpdate
441
    '''
442

    
443
    def actionSaveCliked(self):
444
        from datetime import datetime
445
        from AppDocData import AppDocData
446
        from EngineeringAbstractItem import QEngineeringAbstractItem
447
        from SaveWorkCommand import SaveWorkCommand
448

    
449
        try:
450
            app_doc_data = AppDocData.instance()
451
            if app_doc_data.activeDrawing is None:
452
                self.showImageSelectionMessageBox()
453
                return
454

    
455
            app_doc_data.activeDrawing.clearItemList()
456

    
457
            items = self.graphicsView.scene.items()
458
            for item in items:
459
                if issubclass(type(item), QEngineeringAbstractItem):
460
                    app_doc_data.activeDrawing.allItems.append(item)
461
                    if issubclass(type(item), QEngineeringTextItem):
462
                        app_doc_data.texts.append(item)
463

    
464
            count = len(app_doc_data.activeDrawing.allItems)
465
            if count > 0:
466
                try:
467
                    self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
468
                                                    self) if not hasattr(self, 'progress') else self.progress
469
                    self.progress.setWindowModality(Qt.WindowModal)
470
                    self.progress.setAutoReset(True)
471
                    self.progress.setAutoClose(True)
472
                    self.progress.setMinimum(0)
473
                    self.progress.resize(600, 100)
474
                    self.progress.setWindowTitle(self.tr("Save"))
475
                    self.progress.show()
476

    
477
                    self.save_drawing_data()
478
                finally:
479
                    self.load_drawing_list()
480
                    self.progress.setValue(self.progress.maximum())
481
                    self.progress.hide()
482

    
483
        except Exception as ex:
484
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
485
                                                           sys.exc_info()[-1].tb_lineno)
486
            self.addMessage.emit(MessageType.Error, message)
487

    
488
    def save_drawing_data(self):
489
        """ save drawing data """
490
        from datetime import datetime
491
        from AppDocData import AppDocData
492
        from SymbolSvgItem import SymbolSvgItem
493
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
494

    
495
        try:
496
            app_doc_data = AppDocData.instance()
497
            items = app_doc_data.activeDrawing.allItems
498

    
499
            maxValue = len(items)
500
            self.progress.setMaximum(maxValue)
501

    
502
            index = 0
503
            for item in items:
504
                if type(item) is SymbolSvgItem or type(item) is QEngineeringStreamlineItem:
505
                    app_doc_data.saveToDatabase(item, index)
506
                    self.progress.setValue(index)
507
                    index += 1
508

    
509
                QApplication.processEvents()
510

    
511
            if app_doc_data.activeDrawing:
512
                app_doc_data.activeDrawing.hmbTable.saveData()
513

    
514
            """ update drawing's modified time """
515
            drawings = app_doc_data.getDrawings()
516
            drawing = [drawing for drawing in drawings if app_doc_data.activeDrawing == drawing]
517
            if drawing:
518
                drawing.date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
519
                appDocData.updateDrawing(drawing)
520

    
521
        except Exception as ex:
522
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
523
                                                           sys.exc_info()[-1].tb_lineno)
524
            self.addMessage.emit(MessageType.Error, message)
525

    
526
    '''
527
        @brief  add message listwidget
528
        @author humkyung
529
        @date   2018.07.31
530
    '''
531

    
532
    def onAddMessage(self, messageType, message):
533
        from AppDocData import MessageType
534

    
535
        try:
536
            current = QDateTime.currentDateTime()
537

    
538
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
539
            if messageType == MessageType.Error:
540
                item.setForeground(Qt.red)
541
            elif messageType == MessageType.Information:
542
                item.setForeground(Qt.blue)
543

    
544
            self.listWidgetLogs.insertItem(0, item)
545
        except Exception as ex:
546
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
547
                                                       sys.exc_info()[-1].tb_lineno))
548
        finally:
549
            logs = self.listWidgetLogs.count()
550
            if logs:
551
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs({})'.format(logs))
552
            else:
553
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs')
554

    
555
    '''
556
        @brief      Area Zoom
557
        @author     Jeongwoo
558
        @date       2018.06.27
559
        @history    connect command's rejected signal
560
    '''
561

    
562
    def onAreaZoom(self, action):
563
        if self.actionZoom.isChecked():
564
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
565
            cmd.onRejected.connect(self.onCommandRejected)
566
            self.graphicsView.command = cmd
567

    
568
    '''
569
        @brief      Fit Window
570
        @author     Jeongwoo
571
        @date       2018.06.27
572
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
573
    '''
574

    
575
    def fitWindow(self, action):
576
        self.graphicsView.useDefaultCommand()
577
        self.graphicsView.zoomImageInit()
578

    
579
    '''
580
        @brief      selection changed
581
        @author     humkyung
582
        @date       2018.06.27
583
        @history    humkung 2018.07.08 call tree widget's findItem
584
    '''
585

    
586
    def onSelectionChanged(self):
587
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
588

    
589
        items = [item for item in self.graphicsView.scene.selectedItems() if
590
                 issubclass(type(item), SymbolSvgItem) or type(item) is QEngineeringStreamlineItem]
591
        if items:
592
            item = items[-1]
593

    
594
            if type(item) is QEngineeringErrorItem:
595
                for index in range(self.tableWidgetHMB.rowCount()):
596

    
597
                    if self.tableWidgetHMB.item(index, 1).tag is item:
598
                        self.tableWidgetHMB.selectRow(index)
599
                        break
600

    
601
    '''
602
        @brief      Initialize scene and itemTreeWidget
603
        @author     Jeongwoo
604

605
        @date       2018.06.14
606
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
607
    '''
608

    
609
    def onInitializeScene(self, action):
610

    
611
        if not self.graphicsView.hasImage():
612
            self.showImageSelectionMessageBox()
613
            return
614

    
615
        try:
616
            msg = QMessageBox(self)
617
            msg.setIcon(QMessageBox.Question)
618
            msg.setText(self.tr('Do you want to remove all items?\nThis work cannot be recovered.'))
619
            msg.setWindowTitle(self.tr("Clear Screen"))
620
            msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
621
            if QMessageBox.Ok == msg.exec_():
622

    
623
                appDocData = AppDocData.instance()
624
                appDocData.activeDrawing.hmbTable.reset()
625
                appDocData.clearItemList(True)
626

    
627
                items = self.graphicsView.scene.items()
628
                for item in items:
629
                    if type(item) is not QGraphicsPixmapItem and item.scene() is not None:
630
                        self.graphicsView.scene.removeItem(item)
631

    
632
                appDocData.initializeDataByDrawingUID(appDocData.activeDrawing.UID)
633

    
634
                self.initTableWidgetHMB()
635

    
636
        except Exception as ex:
637
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
638
                                                           sys.exc_info()[-1].tb_lineno)
639
            self.addMessage.emit(MessageType.Error, message)
640

    
641
    '''
642
        @brief      Manage Checkable Action statement
643
        @author     Jeongwoo
644
        @date       2018.05.10
645
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
646
    '''
647

    
648
    def actionGroupTriggered(self, action):
649
        if hasattr(self.actionLine, 'tag'):
650
            self.actionLine.tag.onRejected.emit(None)
651

    
652
        if self.graphicsView.command is not None:
653
            self.graphicsView.useDefaultCommand()
654

    
655
        for _action in [x for x in self.actionGroup.actions() if x is not action]:
656
            _action.setChecked(False)
657
            if _action is self.actionLine:
658
                for item in self.graphicsView.scene.items():
659
                    if not hasattr(item, 'connectors'): continue
660
                    for connector in item.connectors: connector.hide()
661

    
662
        action.setChecked(True)
663
        if action is self.actionLine:
664
            for item in self.graphicsView.scene.items():
665
                if not hasattr(item, 'connectors'): continue
666
                for connector in item.connectors: connector.setVisible(True)
667

    
668
    def showSymbolEditor(self):
669
        from SymbolEditorDialog import QSymbolEditorDialog
670

    
671
        dlg = QSymbolEditorDialog()
672
        dlg.exec_()
673

    
674
    def onOptions(self):
675
        from OptionsDialog import QOptionsDialog
676

    
677
        self.dlgOptions = QOptionsDialog(self)
678
        self.dlgOptions.exec_()
679

    
680
    def calculation(self):
681
        """ execute hydro calculation """
682
        from AppDocData import AppDocData
683
        from Calculation import Calculation
684
        from HydroCalculationCommand import HydroCalculationCommand
685

    
686
        try:
687
            appDocData = AppDocData.instance()
688
            if appDocData.activeDrawing is None:
689
                self.showImageSelectionMessageBox()
690
                return
691

    
692
            hmbs = appDocData.activeDrawing.hmbTable._hmbs
693
            if hmbs is not None:
694
                try:
695
                    self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
696
                                                    self) if not hasattr(self, 'progress') else self.progress
697
                    self.progress.setWindowModality(Qt.WindowModal)
698
                    self.progress.setAutoReset(True)
699
                    self.progress.setAutoClose(True)
700
                    self.progress.setMinimum(0)
701
                    self.progress.resize(600, 100)
702
                    self.progress.setWindowTitle(self.tr("Calculate data..."))
703
                    self.progress.show()
704

    
705
                    maxValue = len(hmbs)
706
                    self.progress.setMaximum(maxValue)
707

    
708
                    for hmb in hmbs:
709
                        self.progress.setValue(self.progress.value() + 1)
710

    
711
                        if hmb.phase_type:
712
                            Calculation(hmb)
713

    
714
                        QApplication.processEvents()
715

    
716
                    """ generate loop """
717
                    cmd = HydroCalculationCommand(self.graphicsView)
718
                    cmd.execute(None)
719
                    self.display_loops(cmd.loops)
720

    
721
                    self.load_HMB()
722
                finally:
723
                    self.progress.setValue(self.progress.maximum())
724
                    self.progress.hide()
725
        except Exception as ex:
726
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
727
                                                           sys.exc_info()[-1].tb_lineno)
728
            self.addMessage.emit(MessageType.Error, message)
729

    
730
    def display_loops(self, loops):
731
        """ display loops """
732
        drawing = AppDocData.instance().activeDrawing
733
        if drawing is None: return
734

    
735
        if loops:
736
            self.tableWidgetLoop.clear()
737
            self.tableWidgetLoop.setColumnCount(len(loops) * 4)
738

    
739
            _col_names = [[loop.name, 'pressure', 'dP', 'density\nelevation'] for loop in loops]
740
            col_names = []
741
            for col_name in _col_names: col_names.extend(col_name)
742
            self.tableWidgetLoop.setHorizontalHeaderLabels(col_names)
743

    
744
            max_rows = 0
745
            for col in range(len(loops)):
746
                rows = len(loops[col].items)
747
                max_rows = max(max_rows, rows)
748
                self.tableWidgetLoop.setRowCount(max_rows)
749

    
750
                for row in range(len(loops[col].items)):
751
                    item = QTableWidgetItem(str(loops[col].items[row]))
752
                    item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
753
                    self.tableWidgetLoop.setItem(row, col * 4, item)
754

    
755
                # display calcuation values
756
                for row in range(len(loops[col].items)):
757
                    if loops[col].items[row] in loops[col].pressures:
758
                        item = QTableWidgetItem(str(loops[col].pressures[loops[col].items[row]]))
759
                        if not loops[col].pressures[loops[col].items[row]]: item.setBackground(Qt.red)
760
                        self.tableWidgetLoop.setItem(row, col * 4 + 1, item)
761

    
762
                    if loops[col].items[row] in loops[col].pressure_drops:
763
                        item = QTableWidgetItem(str(loops[col].pressure_drops[loops[col].items[row]]))
764
                        if not loops[col].pressure_drops[loops[col].items[row]]: item.setBackground(Qt.red)
765
                        self.tableWidgetLoop.setItem(row, col * 4 + 2, item)
766

    
767
                    if loops[col].items[row] in loops[col].density_elevations:
768
                        item = QTableWidgetItem(str(loops[col].density_elevations[loops[col].items[row]]))
769
                        if not loops[col].density_elevations[loops[col].items[row]]: item.setBackground(Qt.red)
770
                        self.tableWidgetLoop.setItem(row, col * 4 + 3, item)
771

    
772
    '''
773
        @brief  configuration
774
    '''
775

    
776
    def configuration(self):
777
        from ConfigurationDialog import QConfigurationDialog
778
        try:
779
            appDocData = AppDocData.instance()
780
            if appDocData.activeDrawing is None:
781
                self.showImageSelectionMessageBox()
782
                return
783

    
784
            dlg = QConfigurationDialog(self)
785
            (isAccepted, isDataConversion, decimal) = dlg.showDialog()
786
            if isAccepted == True:
787
                if isDataConversion == True:
788
                    self.data_conversion(decimal)
789
                else:
790
                    self.reload_units()
791

    
792
        except Exception as ex:
793
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
794
                                                           sys.exc_info()[-1].tb_lineno)
795
            self.addMessage.emit(MessageType.Error, message)
796

    
797
    def data_conversion(self, decimal):
798
        from Drawing import Drawing
799
        from Calculation import Conversion
800

    
801
        try:
802
            Conversion(decimal)
803

    
804
            self.load_HMB()
805
            self.reload_units()
806

    
807
        except Exception as ex:
808
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
809
                                                           sys.exc_info()[-1].tb_lineno)
810
            self.addMessage.emit(MessageType.Error, message)
811

    
812
    '''
813
        @brief  Show Image Selection Guide MessageBox
814
        @author Jeongwoo
815
        @date   2018.05.02
816
    '''
817

    
818
    def showImageSelectionMessageBox(self):
819
        QMessageBox.information(self, self.tr("Notice"), self.tr("First select image drawing"))
820

    
821
    def display_colors(self, value):
822
        """ display colors """
823
        from DisplayColors import DisplayColors
824
        from DisplayColors import DisplayOptions
825

    
826
        DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value == True else DisplayOptions.DisplayByLineType
827
        if hasattr(self, 'graphicsView'):
828
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
829
            DisplayColors.instance().save_data()
830

    
831
    '''
832
        @brief      Open Border file 
833
        @author     yeonjin
834
        @date       2019.07.10
835
    '''
836

    
837
    def open_border_file(self):
838
        app_doc_data = AppDocData.instance()
839
        borderFile = app_doc_data.border_file_path
840
        if not os.path.exists(borderFile):
841
            self.create_border_file(borderFile)
842

    
843
        self.graphicsView.loadImageFromFile(fileName=borderFile)
844

    
845
    '''
846
        @brief      Create Border file 
847
        @author     yeonjin
848
        @date       2019.07.10
849
    '''
850

    
851
    def create_border_file(self, border):
852

    
853
        from PIL import Image
854
        # A4 size : 210, 297
855
        # A3 size : 297, 420
856
        # A2 size : 420, 594
857
        # A1 size : 594, 841
858
        # A0 size : 841, 1189
859
        # color : 0, 128, 128 진한 청록
860
        # color : 255, 255, 255 White
861
        img = Image.new('RGBA', (1189, 841), (255, 255, 255))
862
        img.save(border)
863

    
864
    def setAttributes(self, drawing):
865
        drawing.setAttributes()
866

    
867
    '''
868
        @brief      Reload HMB Units 
869
        @author     yeonjin
870
        @date       2019.07.10
871
    '''
872

    
873
    def reload_units(self):
874
        from Drawing import Drawing
875

    
876
        try:
877
            app_doc_data = AppDocData.instance()
878
            drawing = app_doc_data.activeDrawing
879

    
880
            self.setAttributes(drawing)
881

    
882
            columnInfos = app_doc_data.getHMBDisplayNameAndUnitsExpression()
883

    
884
            rowIndex = 0
885
            for columnInfo in columnInfos:
886
                name = columnInfo[0]
887
                unit = self.convertToUnits(columnInfo[1])
888

    
889
                self.tableWidgetHMB.setItem(rowIndex, 0,
890
                                            self.setTableWidgetItemProperties(name, Qt.AlignLeft | Qt.AlignVCenter,
891
                                                                              QColor(230, 230, 230)))
892
                self.tableWidgetHMB.setItem(rowIndex, 1,
893
                                            self.setTableWidgetItemProperties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
894
                                                                              QColor(230, 230, 230)))
895

    
896
                rowIndex += 1
897

    
898
            self.tableWidgetHMB.resizeColumnsToContents()
899
            self.tableWidgetHMB.resizeRowsToContents()
900

    
901
        except Exception as ex:
902
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
903
                                                           sys.exc_info()[-1].tb_lineno)
904
            self.addMessage.emit(MessageType.Error, message)
905

    
906
    def load_data(self, drawing):
907
        """ load data from drawing """
908
        from Drawing import Drawing
909

    
910
        try:
911
            app_doc_data = AppDocData.instance()
912

    
913
            ## Set appDocData
914
            app_doc_data.clear()
915
            self.onCommandRejected()
916

    
917
            app_doc_data.activeDrawing = drawing
918

    
919
            self.setAttributes(drawing)
920
            self.setMainWindowTitle(drawing.path)
921
            self.initTableWidgetHMB()
922
            ## Load data on database     
923

    
924
            self.symbolTreeWidget.initSymbolTreeWidget()
925

    
926
            components = app_doc_data.getComponentListByDrawingUID(drawing)
927
            count = len(components)
928

    
929
            if count > 0:
930
                try:
931
                    self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
932
                                                    self) if not hasattr(self, 'progress') else self.progress
933
                    self.progress.setWindowModality(Qt.WindowModal)
934
                    self.progress.setAutoReset(True)
935
                    self.progress.setAutoClose(True)
936
                    self.progress.setMinimum(0)
937
                    self.progress.resize(600, 100)
938
                    self.progress.setWindowTitle(self.tr("Load data..."))
939
                    self.progress.show()
940

    
941
                    self.load_components(components)
942

    
943
                    self.load_HMB()
944
                finally:
945
                    self.progress.setValue(self.progress.maximum())
946
                    self.progress.hide()
947

    
948
            # self.changeViewCheckedState(False)
949

    
950
        except Exception as ex:
951
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
952
                                                           sys.exc_info()[-1].tb_lineno)
953
            self.addMessage.emit(MessageType.Error, message)
954

    
955
    def saveAs_drawing(self, sourceDb):
956
        import uuid
957
        from shutil import copyfile
958
        from datetime import datetime
959
        from Drawing import Drawing
960

    
961
        workspace = self.getWorkSpace()
962

    
963
        options = QFileDialog.Options()
964
        options |= QFileDialog.DontUseNativeDialog
965
        name, _ = QFileDialog.getSaveFileName(self, self.tr('Save As'), workspace, 'HYTOS Files (*.hytos)',
966
                                              options=options)
967
        if name:
968
            if os.path.splitext(name)[1] != '.hytos': name += '.hytos'
969

    
970
            app_doc_data = AppDocData.instance()
971
            # copy template.db to name
972
            copyfile(sourceDb, name)
973

    
974
            matches = [drawing for drawing in app_doc_data.getDrawings() if
975
                       os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
976
            if not matches:
977
                drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
978
                app_doc_data.saveDrawing(drawing)
979
            else:
980
                drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
981
                app_doc_data.updateDrawing(drawing)
982

    
983
            self.load_drawing_list()
984
            self.open_border_file()
985
            self.load_data(drawing)
986

    
987
    '''
988
        @brief      create new drawing
989
        @author     yeonjin
990
        @date       2019.07.03
991
    '''
992

    
993
    def new_drawing(self):
994
        import uuid
995
        from shutil import copyfile
996
        from datetime import datetime
997
        from Drawing import Drawing
998

    
999
        workspace = self.getWorkSpace()
1000

    
1001
        options = QFileDialog.Options()
1002
        options |= QFileDialog.DontUseNativeDialog
1003
        name, _ = QFileDialog.getSaveFileName(self, self.tr('New'), workspace, 'HYTOS Files (*.hytos)', options=options)
1004
        if name:
1005

    
1006
            if os.path.splitext(name)[1] != '.hytos': name += '.hytos'
1007

    
1008
            app_doc_data = AppDocData.instance()
1009
            # copy template.db to name
1010
            copyfile(app_doc_data.getTemplateDbPath(), name)
1011

    
1012
            matches = [drawing for drawing in app_doc_data.getDrawings() if
1013
                       os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
1014
            if not matches:
1015
                drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
1016
                app_doc_data.saveDrawing(drawing)
1017
            else:
1018
                drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
1019
                app_doc_data.updateDrawing(drawing)
1020

    
1021
            self.load_drawing_list()
1022
            self.open_border_file()
1023
            self.load_data(drawing)
1024

    
1025
    def on_open_drawing(self):
1026
        """ open selected drawing by user """
1027
        workspace = self.getWorkSpace()
1028

    
1029
        options = QFileDialog.Options()
1030
        options |= QFileDialog.DontUseNativeDialog
1031
        name, _ = QFileDialog.getOpenFileName(self, self.tr('Open'), workspace, 'HYTOS File(*.hytos)', options=options)
1032
        if name: self.open_drawing(name)
1033

    
1034
    def open_drawing(self, name):
1035
        """ open given drawing has name """
1036
        import uuid
1037
        from Drawing import Drawing
1038
        from datetime import datetime
1039

    
1040
        app_doc_data = AppDocData.instance()
1041
        drawings = app_doc_data.getDrawings()
1042
        matches = [drawing for drawing in drawings if os.path.samefile(drawing.path, name)]
1043
        if not matches:
1044
            drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
1045
            app_doc_data.saveDrawing(drawing)
1046

    
1047
            self.load_drawing_list()
1048
        else:
1049
            drawing = matches[0]
1050

    
1051
        self.open_border_file()
1052
        self.load_data(drawing)
1053

    
1054
    def getWorkSpace(self):
1055
        """ get work space path """
1056
        app_doc_data = AppDocData.instance()
1057

    
1058
        configs = app_doc_data.getAppConfigs('option', 'WorkSpace')
1059
        if configs and len(configs) == 1:
1060
            return configs[0].value
1061
        else:
1062
            return os.getcwd()
1063

    
1064
    def changeViewCheckedState(self, checked, clear=True):
1065
        '''
1066
            @brief      change view checked state
1067
            @author     euisung
1068
            @date       2019.03.06
1069
        '''
1070
        if clear:
1071
            self.initTableWidgetHMB()
1072
            # self.clear_data()
1073

    
1074
    '''
1075
        @brief      create a line
1076
        @author     humkyung
1077
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
1078
    '''
1079

    
1080
    def onPlaceLine(self):
1081
        self.actionLine.setChecked(True)
1082
        if not hasattr(self.actionLine, 'tag'):
1083
            self.actionLine.tag = PlaceStreamlineCommand.PlaceStreamlineCommand(self.graphicsView)
1084
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
1085
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
1086

    
1087
        self.graphicsView.command = self.actionLine.tag
1088

    
1089
    '''
1090
        @brief      add created lines to scene
1091
        @author     humkyung
1092
        @date       2018.07.23
1093
    '''
1094

    
1095
    def onLineCreated(self):
1096
        try:
1097
            count = len(self.actionLine.tag.streamline._vertices)
1098
            if count > 1:
1099
                self.add_hmb_data(self.actionLine.tag.streamline)
1100
                self.actionLine.tag.streamline.transfer.onRemoved.connect(self.on_item_removed)
1101
                self.load_HMB()
1102
        finally:
1103
            self.actionLine.tag.reset()
1104

    
1105
    def on_stream_line_deleted(self, stream_line):
1106
        """ callback after stream line is deleted """
1107
        app_doc_data = AppDocData.instance()
1108
        activeDrawing = app_doc_data.activeDrawing
1109
        if activeDrawing:
1110
            activeDrawing.hmbTable.deleteByUID(stream_line.uid)
1111

    
1112
        self.load_HMB()
1113

    
1114
    def add_hmb_data(self, stream_line):
1115
        """ add a new hmb data associated with given stream line """
1116
        from HMBTable import HMBTable
1117
        import uuid
1118

    
1119
        try:
1120
            drawing = AppDocData.instance().activeDrawing
1121
            if drawing:
1122
                components_uid = stream_line.uid
1123
                stream_no = self.getNextStreamNo(drawing)
1124
                stream_line.stream_no = stream_no
1125
                drawing.hmbTable.add(components_uid, stream_no)
1126
        except Exception as ex:
1127
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1128
                                                           sys.exc_info()[-1].tb_lineno)
1129
            self.addMessage.emit(MessageType.Error, message)
1130

    
1131
    def getNextStreamNo(self, drawing):
1132

    
1133
        if len(list(drawing.hmbTable.streamNos())) == 0:
1134
            return 1
1135
        else:
1136
            streamNos = sorted(list(drawing.hmbTable.streamNos()))
1137
            lastStreamNo = streamNos[-1]
1138
            return lastStreamNo + 1
1139

    
1140
    def clear_HMB(self):
1141
        self.tableWidgetHMB.clearContents()
1142
        self.tableWidgetHMB.setColumnCount(0)
1143

    
1144
    def load_HMB(self):
1145
        drawing = AppDocData.instance().activeDrawing
1146
        if drawing is None: return
1147

    
1148
        hmbs = drawing.hmbTable._hmbs
1149
        if hmbs is not None:
1150
            self.tableWidgetHMB.setColumnCount(2)
1151

    
1152
            col_names = ['Stream No.', 'Unit']
1153
            for hmb in hmbs:
1154
                columnCount = self.tableWidgetHMB.columnCount()
1155
                self.tableWidgetHMB.setColumnCount(columnCount + 1)
1156
                col_names.append(str(hmb.stream_no))
1157

    
1158
                self.tableWidgetHMB.setItem(0, columnCount, self.setTableWidgetItemProperties(hmb.uid,
1159
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1160
                self.tableWidgetHMB.setItem(1, columnCount, self.setTableWidgetItemProperties(hmb.components_uid,
1161
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1162
                self.tableWidgetHMB.setItem(2, columnCount, self.setTableWidgetItemProperties(hmb.stream_no,
1163
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1164
                self.tableWidgetHMB.setItem(3, columnCount, self.setTableWidgetItemProperties(hmb.phase_type,
1165
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1166
                self.tableWidgetHMB.setItem(4, columnCount, self.setTableWidgetItemProperties(hmb.flowrate_mass,
1167
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1168
                self.tableWidgetHMB.setItem(5, columnCount, self.setTableWidgetItemProperties(hmb.flowrate_volume,
1169
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1170
                self.tableWidgetHMB.setItem(6, columnCount, self.setTableWidgetItemProperties(hmb.density,
1171
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1172
                self.tableWidgetHMB.setItem(7, columnCount, self.setTableWidgetItemProperties(hmb.viscosity,
1173
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1174
                self.tableWidgetHMB.setItem(8, columnCount, self.setTableWidgetItemProperties(hmb.temperature,
1175
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1176
                self.tableWidgetHMB.setItem(9, columnCount, self.setTableWidgetItemProperties(hmb.molecular_weight,
1177
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1178
                self.tableWidgetHMB.setItem(10, columnCount, self.setTableWidgetItemProperties(hmb.specific_heat_ratio,
1179
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1180
                self.tableWidgetHMB.setItem(11, columnCount, self.setTableWidgetItemProperties(hmb.compress_factor,
1181
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1182
                self.tableWidgetHMB.setItem(12, columnCount, self.setTableWidgetItemProperties(hmb.nominal_pipe_size,
1183
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1184
                self.tableWidgetHMB.setItem(13, columnCount, self.setTableWidgetItemProperties(hmb.inside_pipe_size,
1185
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1186
                self.tableWidgetHMB.setItem(14, columnCount, self.setTableWidgetItemProperties(hmb.schedule_no,
1187
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1188
                self.tableWidgetHMB.setItem(15, columnCount, self.setTableWidgetItemProperties(hmb.straight_length,
1189
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1190
                self.tableWidgetHMB.setItem(16, columnCount,
1191
                                            self.setTableWidgetItemProperties(hmb.equivalent_length_input,
1192
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1193
                self.tableWidgetHMB.setItem(17, columnCount, self.setTableWidgetItemProperties(hmb.fitting_length,
1194
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1195
                self.tableWidgetHMB.setItem(18, columnCount, self.setTableWidgetItemProperties(hmb.fitting_K,
1196
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1197
                self.tableWidgetHMB.setItem(19, columnCount,
1198
                                            self.setTableWidgetItemProperties(hmb.equivalent_length_cal,
1199
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1200
                self.tableWidgetHMB.setItem(20, columnCount, self.setTableWidgetItemProperties(hmb.roughness,
1201
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1202
                self.tableWidgetHMB.setItem(21, columnCount, self.setTableWidgetItemProperties(hmb.limitation_velocity,
1203
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1204
                self.tableWidgetHMB.setItem(22, columnCount,
1205
                                            self.setTableWidgetItemProperties(hmb.limitation_pressure_drop,
1206
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1207
                self.tableWidgetHMB.setItem(23, columnCount, self.setTableWidgetItemProperties(hmb.velocity,
1208
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1209
                self.tableWidgetHMB.setItem(24, columnCount, self.setTableWidgetItemProperties(hmb.reynolds,
1210
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1211
                self.tableWidgetHMB.setItem(25, columnCount, self.setTableWidgetItemProperties(hmb.friction_factor,
1212
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1213
                self.tableWidgetHMB.setItem(26, columnCount, self.setTableWidgetItemProperties(hmb.pressure_drop,
1214
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1215
                self.tableWidgetHMB.setItem(27, columnCount,
1216
                                            self.setTableWidgetItemProperties(hmb.pressure_drop_friction,
1217
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1218
                self.tableWidgetHMB.setItem(28, columnCount, self.setTableWidgetItemProperties(hmb.pressure_drop_static,
1219
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1220
                self.tableWidgetHMB.setItem(29, columnCount,
1221
                                            self.setTableWidgetItemProperties(hmb.pressure_pipe_end_point,
1222
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1223
                self.tableWidgetHMB.setItem(30, columnCount, self.setTableWidgetItemProperties(hmb.power,
1224
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1225

    
1226
                if hmb.isDeleted: self.tableWidgetHMB.hideColumn(columnCount)
1227

    
1228
            self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
1229

    
1230
            self.tableWidgetHMB.resizeColumnsToContents()
1231
            self.tableWidgetHMB.resizeRowsToContents()
1232

    
1233
    '''
1234
        @brief      refresh scene
1235
        @author     humkyung
1236
        @date       2018.07.23
1237
    '''
1238

    
1239
    def onCommandRejected(self, cmd=None):
1240
        try:
1241
            if type(cmd) is PlaceStreamlineCommand.PlaceStreamlineCommand:
1242
                if self.actionLine.tag.streamline:
1243
                    self.graphicsView.scene.removeItem(self.actionLine.tag.streamline)
1244
                self.graphicsView.scene.update()
1245
                self.actionLine.tag.reset()
1246

    
1247
                self.actionLine.setChecked(False)
1248
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
1249
                self.actionZoom.setChecked(False)
1250
            else:
1251
                if hasattr(self.actionLine, 'tag') and self.actionLine.tag.streamline:
1252
                    self.graphicsView.scene.removeItem(self.actionLine.tag.streamline)
1253
                    self.graphicsView.scene.update()
1254
                    self.actionLine.tag.reset()
1255

    
1256
                self.actionLine.setChecked(False)
1257
                self.actionZoom.setChecked(False)
1258
        finally:
1259
            self.graphicsView.useDefaultCommand()
1260

    
1261
    '''
1262
        @brief      restore to default command when user press Escape key
1263
        @author     humkyung 
1264
        @date       2018.08.09
1265
        
1266
    '''
1267

    
1268
    def keyPressEvent(self, event):
1269
        try:
1270
            if event.key() == Qt.Key_Escape:
1271
                # already catched in command
1272
                pass
1273
                # checked = self.actionGroup.checkedAction()
1274
                # if checked:
1275
                #    checked.setChecked(False)
1276
                #    self.graphicsView.useDefaultCommand()                                                           
1277

    
1278
            QMainWindow.keyPressEvent(self, event)
1279
        except Exception as ex:
1280
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1281
                                                           sys.exc_info()[-1].tb_lineno)
1282
            self.addMessage.emit(MessageType.Error, message)
1283

    
1284
    '''
1285
        @brief      remove item from tree widget and then remove from scene
1286
        @date       2018.05.25
1287
        @author     Jeongwoo
1288
    '''
1289

    
1290
    def on_item_removed(self, item):
1291
        try:
1292
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'connectors') and \
1293
                       [connector for connector in _item.connectors if
1294
                        connector.connectedItem is not None and connector.connectedItem.parentItem() is item]]
1295
            for match in matches:
1296
                for connector in match.connectors:
1297
                    if connector.connectedItem is item: connector.connect(None)
1298

    
1299
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'owner')]
1300
            for match in matches:
1301
                if match.owner is item:
1302
                    match.owner = None
1303

    
1304
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'attrs')]
1305
            done = False
1306
            for match in matches:
1307
                for assoc in match.associations():
1308
                    if item is assoc:
1309
                        match.remove_assoc_item(item)
1310
                        for attr in match.attrs.keys():
1311
                            if str(item.uid) == str(attr.AssocItem.uid):
1312
                                attr.AssocItem = None
1313
                                match.attrs[attr] = ''
1314
                                done = True
1315
                                break
1316
                        break
1317
                if done: break
1318

    
1319
            if type(item) is QEngineeringStreamlineItem:
1320
                self.on_stream_line_deleted(item)
1321

    
1322
            if item.scene() is not None:
1323
                item.scene().removeItem(item)
1324
                del item
1325
        except Exception as ex:
1326
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1327
                                                           sys.exc_info()[-1].tb_lineno)
1328
            self.addMessage.emit(MessageType.Error, message)
1329

    
1330
    '''
1331
        @brief      load components
1332
        @author     yeonjin
1333
        @date       2019.07.30.
1334
    '''
1335

    
1336
    def load_components(self, componentsUID):
1337
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
1338
        from EngineeringConnectorItem import QEngineeringConnectorItem
1339

    
1340
        try:
1341
            app_doc_data = AppDocData.instance()
1342

    
1343
            maxValue = len(componentsUID)
1344
            self.progress.setMaximum(maxValue)
1345

    
1346
            for componentUID in componentsUID:
1347
                componentInfos = app_doc_data.getComponentByComponentUID(componentUID)
1348
                if (len(componentInfos)) > 0:
1349
                    category = componentInfos[0][3]  # Category@SymbolType
1350

    
1351
                    if category == 'Stream Line':
1352
                        item = QEngineeringStreamlineItem.fromDatabase(componentInfos)
1353
                        if item is not None:
1354
                            item.transfer.onRemoved.connect(self.on_item_removed)
1355
                            self.graphicsView.scene.addItem(item)
1356
                    else:
1357
                        item = SymbolSvgItem.fromDatabase(componentInfos)
1358
                        if item is not None:
1359
                            item.transfer.onRemoved.connect(self.on_item_removed)
1360
                            app_doc_data.symbols.append(item)
1361
                            self.addSvgItemToScene(item)
1362

    
1363
                    self.progress.setValue(self.progress.value() + 1)
1364

    
1365
                QApplication.processEvents()
1366

    
1367
            # """ update scene """
1368
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1369
            for item in self.graphicsView.scene.items():
1370
                item.setVisible(True)
1371

    
1372
        except Exception as ex:
1373
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1374
                                                           sys.exc_info()[-1].tb_lineno)
1375
            self.addMessage.emit(MessageType.Error, message)
1376
        finally:
1377
            pass
1378

    
1379
    '''
1380
        @brief      Remove added item on same place and Add GraphicsItem
1381
        @author     Jeongwoo
1382
        @date       2018.05.25
1383
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
1384
                    2018.06.18  Jeongwoo    Set Z-index
1385
    '''
1386

    
1387
    def addSvgItemToScene(self, svgItem):
1388
        svgItem.addSvgItemToScene(self.graphicsView.scene)
1389

    
1390
    '''
1391
        @brief      Remove added item on same place and Add GraphicsItem
1392
        @author     Jeongwoo
1393
        @date       2018.05.25
1394
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
1395
                    2018.06.05  Jeongwoo    Remove Size condition
1396
                    2018.06.18  Jeongwoo    Set Z-index
1397
    '''
1398

    
1399
    def addTextItemToScene(self, textItem):
1400
        textItem.addTextItemToScene(self.graphicsView.scene)
1401

    
1402
    '''
1403
        @brief      Remove added item on same place and Add GraphicsItem
1404
        @author     Jeongwoo
1405
        @date       2018.05.29
1406
        @history    2018.06.18  Jeongwoo    Set Z-index
1407
    '''
1408

    
1409
    def addLineItemToScene(self, lineItem):
1410
        self.graphicsView.scene.addItem(lineItem)
1411

    
1412
    '''
1413
        @brief      Check Number
1414
        @author     kyouho
1415
        @date       2018.08.20
1416
    '''
1417

    
1418
    def isNumber(self, num):
1419
        p = re.compile('(^[0-9]+$)')
1420
        result = p.match(num)
1421

    
1422
        if result:
1423
            return True
1424
        else:
1425
            return False
1426

    
1427
    '''
1428
        @brief      find overlap Connector
1429
        @author     kyouho
1430
        @date       2018.08.28
1431
    '''
1432

    
1433
    def findOverlapConnector(self, connectorItem):
1434
        from shapely.geometry import Point
1435
        from EngineeringConnectorItem import QEngineeringConnectorItem
1436
        itemList = []
1437

    
1438
        x = connectorItem.center()[0]
1439
        y = connectorItem.center()[1]
1440

    
1441
        connectors = [item for item in self.graphicsView.scene.items() if
1442
                      type(item) is QEngineeringConnectorItem and item != connectorItem]
1443
        for connector in connectors:
1444
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
1445
                itemList.append(connector.parent)
1446

    
1447
        return itemList
1448

    
1449
    def setTableWidgetItemProperties(self, name, alignment, color=None):
1450
        if name is None:
1451
            name = ''
1452

    
1453
        item = QTableWidgetItem(str(name))
1454
        item.setTextAlignment(alignment)
1455
        if color:
1456
            item.setBackground(color)
1457

    
1458
        return item
1459

    
1460

    
1461
if __name__ == '__main__':
1462
    import locale
1463
    from PyQt5.QtCore import QTranslator
1464
    from App import App
1465

    
1466
    app = App(sys.argv)
1467
    try:
1468
        app._mainWnd = MainWindow.instance()
1469
        if len(sys.argv) == 2: app._mainWnd.open_drawing(sys.argv[1])
1470
        app._mainWnd.show()
1471
        sys.exit(app.exec_())
1472
    except Exception as ex:
1473
        print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1474
                                                   sys.exc_info()[-1].tb_lineno))
1475
    finally:
1476
        pass
클립보드 이미지 추가 (최대 크기: 500 MB)