프로젝트

일반

사용자정보

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

hytos / HYTOS / HYTOS / MainWindow.py @ 70fa5473

이력 | 보기 | 이력해설 | 다운로드 (121 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
from openpyxl.drawing import colors
10

    
11
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
12
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Commands')
13
import CreateCommand
14
import AreaZoomCommand
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 SymbolSvgItem import SymbolSvgItem
32

    
33
from EngineeringTextItem import QEngineeringTextItem
34
from EngineeringErrorItem import QEngineeringErrorItem
35
from EngineeringStreamlineItem import QEngineeringStreamlineItem
36
from AppDocData import *
37
import SymbolTreeWidget
38
import uuid
39
import math
40

    
41

    
42
def is_blank(s):
43
    return not (s and s.strip())
44

    
45
def is_not_blank(s):
46
    return bool(s and s.strip())
47

    
48

    
49
def is_float(s):
50
    try:
51
        if s:
52
            float(s)
53
            return True
54
        else:
55
            return False
56
    except ValueError:
57
        return False
58

    
59

    
60
def set_item_properties(name, alignment, backgroundcolor=None, foregroundcolor=None):
61
    if name is None:
62
        name = ''
63

    
64
    item = QTableWidgetItem(str(name))
65
    item.setTextAlignment(alignment)
66
    if backgroundcolor:
67
        item.setBackground(backgroundcolor)
68
    if foregroundcolor:
69
        item.setForeground(foregroundcolor)  # QBrush(QColor(255, 0, 0)))
70
    return item
71

    
72

    
73
def convert_to_fixed_point(value):
74
    if is_float(str(value)):
75
        tokens = f"{float(value):.10f}".split('.')
76
        if len(tokens) == 2:
77
            # 소수점 아래가 있을 경우 소수점 아래의 trailing zero를 제거한다.
78
            if is_blank(tokens[1].rstrip('0')):
79
                return tokens[0]
80
            else:
81
                tokens[1] = tokens[1].rstrip('0')
82
                return '.'.join(tokens)
83
        else:
84
            return tokens[0]
85
    else:
86
        return value
87

    
88

    
89
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane):
90
    """ This is MainWindow class """
91
    addMessage = pyqtSignal(Enum, str)
92

    
93
    def __init__(self):
94
        """initialize"""
95

    
96
        try:
97
            super(self.__class__, self).__init__()
98
            self.setupUi(self)
99

    
100
            self._label_mouse = QLabel(self.statusbar)
101
            self._label_mouse.setText(self.tr('mouse pos : ({},{})'.format(0, 0)))
102
            self.statusbar.addWidget(self._label_mouse)
103
            self.addMessage.connect(self.onAddMessage)
104
            self.showMaximized()
105

    
106
            self.setMainWindowTitle()
107

    
108
            self.graphicsView = QtImageViewer.QtImageViewer(self)
109
            self.graphicsView.setParent(self.centralwidget)
110
            self.graphicsView.useDefaultCommand()
111
            self.graphicsView.setMouseTracking(True)
112
            self.graphicsView.viewport().installEventFilter(self)
113
            self.verticalLayout.addWidget(self.graphicsView)
114

    
115
            # Add Symbol TreeWidget
116
            self.symbolTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
117
            self.symbolTreeWidget.header().hide()
118
            self.verticalLayoutSymbolList.addWidget(self.symbolTreeWidget)
119

    
120
            # Initialize Action group
121
            self.actionGroup = QActionGroup(self)
122
            self.actionGroup.addAction(self.actionLine)
123
            self.actionGroup.addAction(self.actionZoom)
124
            self.actionGroup.addAction(self.actionFitWindow)
125
            self.actionGroup.addAction(self.actionSave)
126

    
127
            # connect signals and slots
128
            self.actionGroup.triggered.connect(self.actionGroupTriggered)
129
            self.actionClose.triggered.connect(self.close)
130
            self.actionNew.triggered.connect(self.on_new_drawing)
131
            self.actionOpen.triggered.connect(self.on_open_drawing)
132
            self.actionSave.triggered.connect(self.actionSaveCliked)
133
            self.actionCalculation.triggered.connect(self.calculation)
134
            self.actionGenerateReport.triggered.connect(self.generate_report)
135
            self.actionLine.triggered.connect(self.onPlaceLine)
136
            self.actionConfiguration.triggered.connect(self.configuration)
137
            self.actionInitialize.triggered.connect(self.onInitializeScene)
138
            self.actionOptions.triggered.connect(self.onOptions)
139
            self.actionZoom.triggered.connect(self.onAreaZoom)
140
            self.actionFitWindow.triggered.connect(self.fitWindow)
141
            self.actionViewConnector.triggered.connect(self.on_view_connector)
142
            self.actionSymbol_Editor.triggered.connect(self.showSymbolEditor)
143
            self.actionHelp.triggered.connect(self.on_help)
144
            self.actionAbout.triggered.connect(self.on_about)
145
            self.toolButton_ClearLog.clicked.connect(self.clearlogs)
146
            self.graphicsView.scene.selectionChanged.connect(self.onSelectionChanged)
147

    
148
            self.treeWidgetDrawingList.setContextMenuPolicy(Qt.CustomContextMenu)
149
            self.treeWidgetDrawingList.customContextMenuRequested.connect(self.openContextMenu)
150
            self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing)
151

    
152
            self.initTreeWidgetDrawingList()
153
            self.initTableWidgetHMB()
154

    
155
            self.load_drawing_list()
156
            self.load_stylesheet_file()
157
            self.load_language_file()
158

    
159
            self.tabifyDockWidget(self.dockWidgetDrawingExplorer, self.dockWidgetSymbolExplorer)
160
            self.dockWidgetDrawingExplorer.raise_()
161

    
162
            # ToDo..
163
            # Menu bar - Admin Hide
164
            # Loop Tab Hide
165
        except Exception as ex:
166
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
167
                                                           sys.exc_info()[-1].tb_lineno)
168
            self.addMessage.emit(MessageType.Error, message)
169

    
170
    def load_stylesheet_file(self):
171
        # load stylesheet file list
172
        stylesheet_name = QtWidgets.qApp.stylesheet_name
173
        files = [os.path.splitext(file)[0] for file in os.listdir(os.path.dirname(os.path.realpath(__file__))) if
174
                 os.path.splitext(file)[1] == '.qss']
175
        for file in files:
176
            action = self.menuTheme.addAction(file)
177
            action.setCheckable(True)
178
            action.setChecked(True) if stylesheet_name == file else action.setChecked(False)
179
            action.triggered.connect(partial(self.load_stylesheet, file))
180
        # up to here
181

    
182
    def load_language_file(self):
183
        # load language files
184
        language_name = QtWidgets.qApp.language_name
185
        files = ['en_us']  # englisgh is default language
186
        files.extend([os.path.splitext(file)[0] for file in
187
                      os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate')) if
188
                      os.path.splitext(file)[1] == '.qm'])
189
        for file in files:
190
            action = self.menuLanguage.addAction(file)
191
            action.setCheckable(True)
192
            action.setChecked(True) if language_name.lower() == file.lower() else action.setChecked(False)
193
            action.triggered.connect(partial(self.load_language, file))
194
        # up to here
195

    
196
    def setMainWindowTitle(self, drawingName=None):
197
        try:
198
            _translate = QCoreApplication.translate
199

    
200
            version = QCoreApplication.applicationVersion()
201
            if drawingName is None:
202
                self.setWindowTitle(_translate(App.NAME + "({})".format(version), App.NAME + "({})".format(version)))
203
            else:
204
                self.setWindowTitle(
205
                    _translate(App.NAME + "({})".format(version), App.NAME + "({})".format(version)) + ' - {}'.format(
206
                        drawingName))
207
        except Exception as ex:
208
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
209
                                                           sys.exc_info()[-1].tb_lineno)
210
            self.addMessage.emit(MessageType.Error, message)
211

    
212
    def clearlogs(self):
213
        try:
214
            self.listWidgetLogs.clear()
215
        except Exception as ex:
216
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
217
                                                           sys.exc_info()[-1].tb_lineno)
218
            self.addMessage.emit(MessageType.Error, message)
219
        finally:
220
            logs = self.listWidgetLogs.count()
221
            if logs:
222
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs({})'.format(logs))
223
            else:
224
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs')
225

    
226
    def closeEvent(self, a0: QCloseEvent) -> None:
227
        """ask user to save drawing which is modified"""
228
        self.save_drawing_if_necessary()
229
        a0.accept()
230

    
231
    def openContextMenu(self, position):
232
        indexes = self.treeWidgetDrawingList.selectedIndexes()
233
        if len(indexes) > 0:
234
            level = 0
235
            index = indexes[0]
236
            while index.parent().isValid():
237
                index = index.parent()
238
                level += 1
239

    
240
            menu = QMenu()
241

    
242
            itemPosition = self.mapTo(self, position)
243
            item = self.treeWidgetDrawingList.itemAt(itemPosition)
244

    
245
            if level == 0:
246
                newDrawingAction = menu.addAction(self.tr('New...'))
247
                newDrawingAction.triggered.connect(lambda: self.newDrawingActionClickEvent(item))
248
                menu.addAction(newDrawingAction)
249
            elif level == 1:
250
                # saveAsDrawingAction = menu.addAction(self.tr("Save As..."))
251
                # saveAsDrawingAction.triggered.connect(lambda: self.saveAsDrawingActionClickEvent(item))
252
                # menu.addAction(saveAsDrawingAction)
253

    
254
                deleteDrawingAction = menu.addAction(self.tr("Delete"))
255
                deleteDrawingAction.triggered.connect(lambda: self.deleteDrawingActionClickEvent(item))
256
                menu.addAction(deleteDrawingAction)
257

    
258
            menu.exec_(self.treeWidgetDrawingList.viewport().mapToGlobal(position))
259

    
260
    def on_new_drawing(self):
261
        self.new_drawing()
262

    
263
    def newDrawingActionClickEvent(self, item):
264
        self.new_drawing()
265

    
266
    def saveAsDrawingActionClickEvent(self, item):
267
        sourceDb = item.text(2)
268

    
269
        self.saveAs_drawing(sourceDb)
270

    
271
    def deleteDrawingActionClickEvent(self, item):
272
        """ delete selected drawing """
273
        try:
274
            msg = QMessageBox(self)
275
            msg.setIcon(QMessageBox.Question)
276
            msg.setText(self.tr('Do you want to delete drawing on list?\nHowever, Actual drawing is not deleted.'))
277
            msg.setWindowTitle(self.tr("Delete"))
278
            msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
279

    
280
            if QMessageBox.Ok == msg.exec_():
281
                drawingName = item.text(0)
282
                drawingPath = item.text(2)
283

    
284
                app_doc_data = AppDocData.instance()
285
                app_doc_data.deleteDrawingByName(drawingPath)
286

    
287
                if app_doc_data.activeDrawing:
288
                    if drawingName == app_doc_data.activeDrawing.name and drawingPath == app_doc_data.activeDrawing.path:
289
                        app_doc_data.activeDrawing = None
290

    
291
                        if self.graphicsView.hasImage():
292
                            self.graphicsView.clearImage()
293
                            self.graphicsView.scene.clear()
294

    
295
                        self.initTableWidgetHMB()
296

    
297
                self.load_drawing_list()
298
        except Exception as ex:
299
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
300
                                                           sys.exc_info()[-1].tb_lineno)
301
            self.addMessage.emit(MessageType.Error, message)
302

    
303
    def clear_data(self):
304
        self.clear_HMB()
305

    
306
    def eventFilter(self, source, event):
307
        """ display mouse position of graphics view """
308
        if event.type() == QEvent.MouseMove:
309
            pos = self.graphicsView.mapToScene(event.pos())
310
            self._label_mouse.setText('mouse pos : ({},{})'.format(round(pos.x()), round(pos.y())))
311

    
312
        return QWidget.eventFilter(self, source, event)
313

    
314
    def load_stylesheet(self, file):
315
        """load stylesheets"""
316

    
317
        QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
318

    
319
        app_doc_data = AppDocData.instance()
320
        configs = [Config('app', 'stylesheet', file)]
321
        app_doc_data.saveAppConfigs(configs)
322

    
323
        for action in self.menuTheme.actions():
324
            if action.text() == file: continue
325
            action.setChecked(False)
326

    
327
    def load_language(self, file):
328
        """ load language file and then apply selected language """
329
        try:
330

    
331
            qm_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate', '{0}.qm'.format(file))
332
            QtWidgets.qApp.load_language(qm_file)
333

    
334
            app_doc_data = AppDocData.instance()
335
            configs = [Config('app', 'language', file)]
336
            app_doc_data.saveAppConfigs(configs)
337

    
338
            for action in self.menuLanguage.actions():
339
                if action.text().lower() == file.lower(): continue
340
                action.setChecked(False)
341
        finally:
342
            self.retranslateUi(self)
343

    
344
    def initTreeWidgetDrawingList(self):
345

    
346
        self.treeWidgetDrawingList.setHeaderHidden(False)
347
        self.treeWidgetDrawingList.header().setStretchLastSection(True)
348
        self.treeWidgetDrawingList.header().setDefaultAlignment(Qt.AlignCenter)
349
        self.treeWidgetDrawingList.setHeaderLabels([self.tr('Name'), self.tr('DateTime'), self.tr('Path')])
350
        self.treeWidgetDrawingList.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
351
        self.treeWidgetDrawingList.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
352
        self.treeWidgetDrawingList.header().setSectionResizeMode(2, QHeaderView.ResizeToContents)
353
        self.treeWidgetDrawingList.hideColumn(2)
354

    
355
    def clear_output(self):
356
        self.tableWidgetOutput.setColumnCount(0)
357
        self.tableWidgetOutput.setRowCount(0)
358

    
359
        self.tableWidgetDeviation.setColumnCount(0)
360
        self.tableWidgetDeviation.setRowCount(0)
361

    
362
    def clear_loop(self):
363
        self.tableWidgetLoop.setColumnCount(0)
364

    
365
    def initTableWidgetHMB(self):
366
        app_doc_data = AppDocData.instance()
367

    
368
        column_infos = app_doc_data.getHMBDisplayNameAndUnitsExpression()
369
        count = len(column_infos)
370
        self.tableWidgetHMB.setRowCount(count)
371
        if len(column_infos) > 0:
372
            self.tableWidgetHMB.setColumnCount(2)
373
        else:
374
            self.tableWidgetHMB.setColumnCount(0)
375

    
376
        self.tableWidgetHMB.hideRow(0)  # UID
377
        self.tableWidgetHMB.hideRow(1)  # Components_UID
378
        self.tableWidgetHMB.hideRow(2)  # Stream_No
379
        # self.tableWidgetHMB.hideRow(3)  # Phase_Type
380
        # self.tableWidgetHMB.hideRow(4)  # Flowrate_Mass
381
        # self.tableWidgetHMB.hideRow(5)  # Flowrate_Volume
382
        # self.tableWidgetHMB.hideRow(6)  # Density
383
        # self.tableWidgetHMB.hideRow(7)  # Viscosity
384
        # self.tableWidgetHMB.hideRow(8)  # Temperature
385
        # self.tableWidgetHMB.hideRow(9)  # Molecular_Weight
386
        # self.tableWidgetHMB.hideRow(10)  # Specific_Heat_Ratio
387
        # self.tableWidgetHMB.hideRow(11)  # Compress_Factor
388
        # self.tableWidgetHMB.hideRow(12)  # Nominal_Pipe_Size
389
        # self.tableWidgetHMB.hideRow(13)  # Inside_Pipe_Size
390
        # self.tableWidgetHMB.hideRow(14)  # Schedule_No
391
        # self.tableWidgetHMB.hideRow(15)  # Straight_Length
392
        # self.tableWidgetHMB.hideRow(16)  # Equivalent_Length
393
        self.tableWidgetHMB.hideRow(17)  # Equivalent_Length_Input
394
        self.tableWidgetHMB.hideRow(18)  # Fitting_Length
395
        self.tableWidgetHMB.hideRow(19)  # Fitting_K
396
        self.tableWidgetHMB.hideRow(20)  # Equivalent_Length_Cal
397
        # self.tableWidgetHMB.hideRow(21)  # Roughness
398
        # self.tableWidgetHMB.hideRow(22)  # Limitation_Velocity
399
        # self.tableWidgetHMB.hideRow(23)  # Limitation_Pressure_Drop
400
        # self.tableWidgetHMB.hideRow(24)  # Separator
401
        # self.tableWidgetHMB.hideRow(25)  # Velocity
402
        # self.tableWidgetHMB.hideRow(26)  # Reynolds
403
        # self.tableWidgetHMB.hideRow(27)  # Friction_Factor
404
        # self.tableWidgetHMB.hideRow(28)  # Pressure_Drop
405
        # self.tableWidgetHMB.hideRow(29)  # Pressure_Drop_Friction
406
        # self.tableWidgetHMB.hideRow(30)  # Pressure_Drop_Static
407
        # self.tableWidgetHMB.hideRow(31)  # Pressure_Pipe_End_Point
408
        self.tableWidgetHMB.hideRow(32)  # Power
409

    
410
        self.tableWidgetHMB.setEditTriggers(QAbstractItemView.NoEditTriggers)
411
        self.tableWidgetHMB.verticalHeader().setVisible(False)
412

    
413
        col_names = ['Stream No.', 'Unit']
414
        self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
415

    
416
        rowIndex = 0
417
        for columnInfo in column_infos:
418
            name = columnInfo[0]
419
            unit = self.convertToUnits(columnInfo[1])
420

    
421
            self.tableWidgetHMB.setItem(rowIndex, 0, set_item_properties(name, Qt.AlignLeft | Qt.AlignVCenter,
422
                                                                         QColor(51, 153, 102)))
423
            self.tableWidgetHMB.setItem(rowIndex, 1, set_item_properties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
424
                                                                         QColor(204, 255, 204)))
425

    
426
            rowIndex += 1
427

    
428
        self.tableWidgetHMB.resizeColumnsToContents()
429
        self.tableWidgetHMB.resizeRowsToContents()
430

    
431
    def copy_selection(self, table_widget):
432
        """copy selected text to clipboard"""
433

    
434
        import io
435
        import csv
436

    
437
        selection = table_widget.selectedIndexes()
438
        if selection:
439
            rows = sorted(index.row() for index in selection)
440
            columns = sorted(index.column() for index in selection)
441
            rowcount = rows[-1] - rows[0] + 1
442
            colcount = columns[-1] - columns[0] + 1
443
            table = [[''] * colcount for _ in range(rowcount)]
444
            for index in selection:
445
                row = index.row() - rows[0]
446
                column = index.column() - columns[0]
447
                table[row][column] = index.data()
448
            stream = io.StringIO()
449
            csv.writer(stream, delimiter='\t').writerows(table)
450
            QApplication.clipboard().setText(stream.getvalue())
451

    
452
    def paste_selection(self, table_widget):
453
        """paste text of clipboard to table widget"""
454

    
455
        import io
456
        import csv
457

    
458
        selection = table_widget.selectedIndexes()
459
        if selection:
460
            model = table_widget.model()
461

    
462
            buffer = QApplication.clipboard().text()
463
            rows = sorted(index.row() for index in selection)
464
            columns = sorted(index.column() for index in selection)
465
            reader = csv.reader(io.StringIO(buffer), delimiter='\t')
466
            if len(rows) == 1 and len(columns) == 1:
467
                for i, line in enumerate(reader):
468
                    for j, cell in enumerate(line):
469
                        model.setData(model.index(rows[0] + i, columns[0] + j), cell)
470
            else:
471
                arr = [[cell for cell in row] for row in reader]
472
                for index in selection:
473
                    row = index.row() - rows[0]
474
                    column = index.column() - columns[0]
475
                    model.setData(model.index(index.row(), index.column()), arr[row][column])
476

    
477
    '''
478
        @brief      Drawing 속성의 Units 에서 Key값을 이용하여 Value를 찾음
479
        @author     yeonjin
480
        @date       19.08.30
481
    '''
482

    
483
    def findValue(self, key):
484
        value = None
485

    
486
        key = key.replace("{", "").replace("}", "")
487
        for attr in AppDocData.instance().activeDrawing.attrs:
488
            if attr[0] == 'Units':
489
                if key in attr[1]:
490
                    value = attr[1][key]
491
                    break
492

    
493
        return value
494

    
495
    '''
496
        @brief      Convert UnitsExpression To Units Value
497
        @author     yeonjin
498
        @date       19.08.29
499
    '''
500

    
501
    def convertToUnits(self, unitsExpression):
502
        import re
503

    
504
        if unitsExpression is None or AppDocData.instance().activeDrawing is None:
505
            return ''
506

    
507
        found = re.findall('{.*?}', unitsExpression)
508
        for f in found:
509
            key = f
510
            val = self.findValue(key)
511
            if val:
512
                unitsExpression = unitsExpression.replace(key, val)
513

    
514
        return unitsExpression
515

    
516
    '''
517
        @brief      Clear TreeWidget and Set Current PID
518
        @author     Jeongwoo
519
        @date       18.04.11
520
        @history    2018.04.26  Jeongwoo    Add Child [SYMBOLS, NOTES] into root item
521
                    2018.05.09  Jeongwoo    Change method to add default tree items
522
                    humkyung 2018.06.10 add tree item for Line No and Unknown Item
523
    '''
524

    
525
    def load_drawing_list(self):
526
        """load pfd drawing list"""
527

    
528
        try:
529
            app_doc_data = AppDocData.instance()
530
            drawings = app_doc_data.getDrawings()
531

    
532
            self.treeWidgetDrawingList.clear()
533
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList, [self.tr('Drawings'), ''])
534

    
535
            for drawing in drawings:
536
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [drawing.name, drawing.date_time, drawing.path])
537
                item.setIcon(0, QIcon(':images/PFD.png'))
538
                item.setData(0, Qt.UserRole, drawing)
539

    
540
            self.treeWidgetDrawingList.root.setText(0, self.tr('Drawings') + '({})'.format(
541
                self.treeWidgetDrawingList.root.childCount()))
542
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
543
            self.treeWidgetDrawingList.sortByColumn(1, Qt.DescendingOrder)
544
            self.treeWidgetDrawingList.resizeColumnToContents(0)
545

    
546
        except Exception as ex:
547
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
548
                                                           sys.exc_info()[-1].tb_lineno)
549
            self.addMessage.emit(MessageType.Error, message)
550

    
551
    def save_drawing_if_necessary(self):
552
        """ask user to save drawing or not when drawing is modified"""
553

    
554
        app_doc_data = AppDocData.instance()
555
        if app_doc_data.activeDrawing and app_doc_data.activeDrawing.modified:
556
            if QMessageBox.Yes == QMessageBox.question(self, self.tr("Question"),
557
                                                       self.tr("Do you want to save drawing?"),
558
                                                       QMessageBox.Yes | QMessageBox.No):
559
                self.actionSaveCliked(False)
560

    
561
    def open_selected_drawing(self, item):
562
        """ open selected drawing """
563
        try:
564
            path = item.text(2)
565
            if os.path.exists(path):
566
                self.save_drawing_if_necessary()
567
                self.open_drawing(path)
568

    
569
        except Exception as ex:
570
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
571
                                                           sys.exc_info()[-1].tb_lineno)
572
            self.addMessage.emit(MessageType.Error, message)
573

    
574
    '''
575
        @brief      action save click event
576
        @author     kyouho
577
        @date       2018.08.09
578
        @history    2018.11.02      euisung     add line data list db update
579
                    humkyung save saved time to database
580
                    2018.11.05      euisung     add note data list db update
581
                    2018.11.05      euisung     add db delete process before save
582
                    2018.11.12      euisung     db part move new method to dbUpdate
583
    '''
584

    
585
    def actionSaveCliked(self, show_message=True):
586
        from datetime import datetime
587
        from AppDocData import AppDocData
588
        from EngineeringAbstractItem import QEngineeringAbstractItem
589

    
590
        try:
591
            app_doc_data = AppDocData.instance()
592
            if app_doc_data.activeDrawing is None:
593
                self.showImageSelectionMessageBox()
594
                return
595

    
596
            app_doc_data.activeDrawing.clearItemList()
597

    
598
            items = self.graphicsView.scene.items()
599
            for item in items:
600
                if issubclass(type(item), QEngineeringAbstractItem):
601
                    app_doc_data.activeDrawing.allItems.append(item)
602
                    if issubclass(type(item), QEngineeringTextItem):
603
                        app_doc_data.texts.append(item)
604

    
605
            count = len(app_doc_data.activeDrawing.allItems)
606
            if count > 0:
607
                try:
608
                    self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
609
                                                    self) if not hasattr(self, 'progress') else self.progress
610
                    self.progress.setWindowModality(Qt.WindowModal)
611
                    self.progress.setAutoReset(True)
612
                    self.progress.setAutoClose(True)
613
                    self.progress.setMinimum(0)
614
                    self.progress.resize(600, 100)
615
                    self.progress.setWindowTitle(self.tr("Save"))
616
                    self.progress.show()
617

    
618
                    self.save_drawing_data()
619
                finally:
620
                    self.load_drawing_list()
621
                    self.progress.setValue(self.progress.maximum())
622
                    self.progress.hide()
623
                    if show_message:
624
                        QMessageBox.information(self, self.tr("Information"), self.tr("Save completed successfully."))
625

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

    
631
    def save_drawing_data(self):
632
        """ save drawing data """
633

    
634
        from datetime import datetime
635
        from AppDocData import AppDocData
636
        from SymbolSvgItem import SymbolSvgItem
637
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
638

    
639
        try:
640
            app_doc_data = AppDocData.instance()
641
            items = app_doc_data.activeDrawing.allItems
642

    
643
            maxValue = len(items)
644
            self.progress.setMaximum(maxValue)
645

    
646
            app_doc_data.saveToDatabase([item for item in items
647
                                         if type(item) is SymbolSvgItem or type(item) is QEngineeringStreamlineItem],
648
                                        self.progress.setValue)
649

    
650
            if app_doc_data.activeDrawing:
651
                app_doc_data.activeDrawing.hmbTable.saveData()
652
                app_doc_data.save_sheet_history('Save')
653

    
654
            """ update drawing's modified time """
655
            drawings = app_doc_data.getDrawings()
656
            drawing = [drawing for drawing in drawings if app_doc_data.activeDrawing == drawing]
657
            if drawing:
658
                drawing.date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
659
                app_doc_data.updateDrawing(drawing)
660

    
661
            app_doc_data.activeDrawing.modified = False
662
            self.setMainWindowTitle(f"{app_doc_data.activeDrawing.path}")
663

    
664
        except Exception as ex:
665
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
666
                                                           sys.exc_info()[-1].tb_lineno)
667
            self.addMessage.emit(MessageType.Error, message)
668

    
669
    '''
670
        @brief  add message listwidget
671
        @author humkyung
672
        @date   2018.07.31
673
    '''
674

    
675
    def onAddMessage(self, messageType, message):
676
        from AppDocData import MessageType
677

    
678
        try:
679
            current = QDateTime.currentDateTime()
680

    
681
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
682
            if messageType == MessageType.Error:
683
                item.setForeground(Qt.red)
684
            elif messageType == MessageType.Information:
685
                item.setForeground(Qt.blue)
686

    
687
            self.listWidgetLogs.insertItem(0, item)
688
        except Exception as ex:
689
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
690
                                                       sys.exc_info()[-1].tb_lineno))
691
        finally:
692
            logs = self.listWidgetLogs.count()
693
            if logs:
694
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs({})'.format(logs))
695
            else:
696
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs')
697

    
698
    '''
699
        @brief      Area Zoom
700
        @author     Jeongwoo
701
        @date       2018.06.27
702
        @history    connect command's rejected signal
703
    '''
704

    
705
    def onAreaZoom(self, action):
706
        if self.actionZoom.isChecked():
707
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
708
            cmd.onRejected.connect(self.onCommandRejected)
709
            self.graphicsView.command = cmd
710

    
711
    '''
712
        @brief      Fit Window
713
        @author     Jeongwoo
714
        @date       2018.06.27
715
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
716
    '''
717

    
718
    def fitWindow(self, action):
719
        self.graphicsView.useDefaultCommand()
720
        self.graphicsView.zoomImageInit()
721

    
722
    def on_view_connector(self, checked):
723
        """turn on/off connector"""
724
        for item in self.graphicsView.scene.items():
725
            if not hasattr(item, 'connectors'):
726
                continue
727
            for connector in item.connectors:
728
                connector.setVisible(True) if checked else connector.hide()
729

    
730
    def scene_changed(self):
731
        """update modified flag"""
732

    
733
        app_doc_data = AppDocData.instance()
734
        app_doc_data.activeDrawing.modified = True
735
        self.setMainWindowTitle(f"{app_doc_data.activeDrawing.path}*")
736

    
737
    '''
738
        @brief      selection changed
739
        @author     humkyung
740
        @date       2018.06.27
741
        @history    humkung 2018.07.08 call tree widget's findItem
742
    '''
743

    
744
    def onSelectionChanged(self):
745
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
746

    
747
        items = [item for item in self.graphicsView.scene.selectedItems() if
748
                 issubclass(type(item), SymbolSvgItem) or type(item) is QEngineeringStreamlineItem]
749
        if items:
750
            item = items[-1]
751

    
752
            if type(item) is QEngineeringErrorItem:
753
                for index in range(self.tableWidgetHMB.rowCount()):
754

    
755
                    if self.tableWidgetHMB.item(index, 1).tag is item:
756
                        self.tableWidgetHMB.selectRow(index)
757
                        break
758

    
759
    '''
760
        @brief      Initialize scene and itemTreeWidget
761
        @author     Jeongwoo
762

763
        @date       2018.06.14
764
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
765
    '''
766

    
767
    def onInitializeScene(self, action):
768

    
769
        if not self.graphicsView.hasImage():
770
            self.showImageSelectionMessageBox()
771
            return
772

    
773
        try:
774
            msg = QMessageBox(self)
775
            msg.setIcon(QMessageBox.Question)
776
            msg.setText(self.tr('Do you want to remove all items?\nThis work cannot be recovered.'))
777
            msg.setWindowTitle(self.tr("Clear Screen"))
778
            msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
779
            if QMessageBox.Ok == msg.exec_():
780

    
781
                appDocData = AppDocData.instance()
782
                appDocData.activeDrawing.hmbTable.reset()
783
                appDocData.clearItemList(True)
784

    
785
                items = self.graphicsView.scene.items()
786
                for item in items:
787
                    if type(item) is not QGraphicsPixmapItem and item.scene() is not None:
788
                        self.graphicsView.scene.removeItem(item)
789

    
790
                appDocData.initializeDataByDrawingUID(appDocData.activeDrawing.UID)
791

    
792
                self.initTableWidgetHMB()
793

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

    
799
    '''
800
        @brief      Manage Checkable Action statement
801
        @author     Jeongwoo
802
        @date       2018.05.10
803
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
804
    '''
805

    
806
    def actionGroupTriggered(self, action):
807
        if hasattr(self.actionLine, 'tag'):
808
            self.actionLine.tag.onRejected.emit(None)
809

    
810
        if self.graphicsView.command is not None:
811
            self.graphicsView.useDefaultCommand()
812

    
813
        for _action in [x for x in self.actionGroup.actions() if x is not action]:
814
            _action.setChecked(False)
815
            if _action is self.actionLine:
816
                for item in self.graphicsView.scene.items():
817
                    if not hasattr(item, 'connectors'): continue
818
                    for connector in item.connectors: connector.hide()
819

    
820
        action.setChecked(True)
821
        if action is self.actionLine:
822
            for item in self.graphicsView.scene.items():
823
                if not hasattr(item, 'connectors'): continue
824
                for connector in item.connectors: connector.setVisible(True)
825

    
826
    def showSymbolEditor(self):
827
        from SymbolEditorDialog import QSymbolEditorDialog
828

    
829
        dlg = QSymbolEditorDialog()
830
        dlg.exec_()
831

    
832
    def on_help(self):
833
        """open user manual"""
834
        import os
835

    
836
        try:
837
            help_file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'HYTOS User Manual.pdf')
838
            os.startfile(f"\"{help_file_path}\"")
839
            # os.system(f"\"{help_file_path}\"")
840
        except Exception as ex:
841
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
842
                                                           sys.exc_info()[-1].tb_lineno)
843
            self.addMessage.emit(MessageType.Error, message)
844

    
845
    def on_about(self):
846
        """show about dialog"""
847
        from AboutDialog import QAboutDialog
848

    
849
        dlg = QAboutDialog()
850
        dlg.exec_()
851

    
852
    def rebuild_label(self):
853

    
854
        items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem)]
855
        for item in items:
856
            item.build_label()
857

    
858
    def onOptions(self):
859
        from OptionsDialog import QOptionsDialog
860
        try:
861
            app_doc_data = AppDocData.instance()
862
            configs = app_doc_data.getAppConfigs('option', 'TagFontSize')
863
            if configs and len(configs) == 1:
864
                old_tag_font_size = configs[0].value
865
            else:
866
                old_tag_font_size = 6
867

    
868
            configs = app_doc_data.getAppConfigs('option', 'TagFontColor')
869
            if configs and len(configs) == 1:
870
                old_tag_font_color = configs[0].value
871
            else:
872
                old_tag_font_color = '#000000'
873

    
874
            dlg = QOptionsDialog(self)
875
            (isAccepted, new_tag_font_size, new_tag_font_color) = dlg.show_dialog()
876
            if isAccepted == True:
877
                if app_doc_data.activeDrawing:
878
                    if str(old_tag_font_size) != str(new_tag_font_size) or old_tag_font_color != new_tag_font_color:
879
                        self.rebuild_label()
880

    
881
        except Exception as ex:
882
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
883
                                                           sys.exc_info()[-1].tb_lineno)
884
            self.addMessage.emit(MessageType.Error, message)
885

    
886
    def calculation(self):
887
        """execute hydro calculation"""
888
        from AppDocData import AppDocData
889
        from Calculation import Calculation
890
        from HydroCalculationCommand import HydroCalculationCommand
891
        from ValidationDialog import QValidationDialog
892

    
893
        try:
894
            app_doc_data = AppDocData.instance()
895
            if app_doc_data.activeDrawing is None:
896
                self.showImageSelectionMessageBox()
897
                return
898

    
899
            hmbs = app_doc_data.activeDrawing.hmbTable._hmbs
900
            if hmbs is not None:
901
                try:
902
                    errors = []
903
                    items = [item for item in self.graphicsView.scene.items() if type(item) is SymbolSvgItem or
904
                             type(item) is QEngineeringStreamlineItem]
905
                    for item in items:
906
                        error = item.validate()
907
                        if error: errors.extend(error)
908

    
909
                    if errors:
910
                        dlg = QValidationDialog(self, errors)
911
                        dlg.show()
912
                    else:
913
                        self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, self) \
914
                            if not hasattr(self, 'progress') else self.progress
915
                        self.progress.setWindowModality(Qt.WindowModal)
916
                        self.progress.setAutoReset(True)
917
                        self.progress.setAutoClose(True)
918
                        self.progress.setMinimum(0)
919
                        self.progress.resize(600, 100)
920
                        self.progress.setWindowTitle(self.tr("Calculate data..."))
921
                        self.progress.show()
922

    
923
                        maxValue = len(hmbs)
924
                        self.progress.setMaximum(maxValue)
925

    
926
                        for hmb in hmbs:
927
                            self.progress.setValue(self.progress.value() + 1)
928

    
929
                            if hmb.phase_type:
930
                                Calculation(hmb)
931

    
932
                            QApplication.processEvents()
933

    
934
                        """ generate loop """
935
                        cmd = HydroCalculationCommand(self.graphicsView)
936
                        cmd.execute(None)
937
                        cmd.execute_second(None)
938

    
939
                        app_doc_data.activeDrawing.loops = cmd.loops
940

    
941
                        self.display_loops()
942
                        self.display_output()
943

    
944
                        self.load_HMB()
945

    
946
                        app_doc_data.save_sheet_history('Calculation')
947
                finally:
948
                    self.progress.setValue(self.progress.maximum())
949
                    self.progress.hide()
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 generate_report(self):
956
        """generate calculation report"""
957
        from tempfile import NamedTemporaryFile
958
        import openpyxl
959
        from DrawImage import DrawImage
960
        from openpyxl.styles import Font
961
        from datetime import datetime
962
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
963

    
964
        try:
965
            app_doc_data = AppDocData.instance()
966
            if app_doc_data.activeDrawing is None:
967
                self.showImageSelectionMessageBox()
968
                return
969

    
970
            image_path = None
971
            with NamedTemporaryFile() as f:
972
                image_path = f.name + '.png'
973

    
974
            if image_path:
975
                self.graphicsView.save_as_image(image_path)
976

    
977
                workspace = self.get_work_space()
978
                file_name = os.path.join(workspace, app_doc_data.activeDrawing.name + '.xlsx')
979
                options = QFileDialog.Options()
980
                options |= QFileDialog.DontUseNativeDialog
981
                file_name, _ = QFileDialog.getSaveFileName(self, self.tr('Report'), file_name, 'Excel(*.xlsx)',
982
                                                           options=options)
983

    
984
                template = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME, 'Report_Template.xlsx')
985

    
986
                # get image file path
987
                company_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME, 'Company.png')
988
                horizontal_flow_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME, 'Horizontal_Flow.png')
989
                vertical_upward_flow_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME,
990
                                                               'Vertical_Upward_Flow.png')
991
                vertical_downward_flow_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME,
992
                                                                 'Vertical_Downward_Flow.png')
993
                # up to here
994
                if file_name and os.path.exists(template):
995
                    units = [attr[1] for attr in app_doc_data.activeDrawing.attrs if attr[0] == 'Units'][0]
996

    
997
                    wb = openpyxl.load_workbook(template)
998

    
999
                    page_no = 1
1000
                    pages = math.ceil(len(list(app_doc_data.activeDrawing.hmbTable.streamNos())) / 20)
1001
                    for page in range(pages):
1002
                        ws = wb.copy_worksheet(wb.get_sheet_by_name('Page'))
1003
                        ws.title = 'Page ({})'.format(page_no)
1004

    
1005
                        cal_image = openpyxl.drawing.image.Image(image_path)
1006
                        x_scale, y_scale = 1, 1
1007
                        cal_image.width *= x_scale
1008
                        cal_image.height *= y_scale
1009
                        ws.add_image(cal_image, 'C4')
1010

    
1011
                        company_image = openpyxl.drawing.image.Image(company_image_path)
1012
                        company_image.width *= 0.8
1013
                        company_image.height *= 0.7
1014
                        ws.add_image(company_image, 'W53')
1015

    
1016
                        """write sheet information"""
1017
                        configs = app_doc_data.getConfigs('Sheet')
1018
                        for config in configs:
1019
                            if config.key == 'JobNo' and config.value:
1020
                                ws['Z58'].value = config.value
1021
                            elif config.key == 'JobName' and config.value:
1022
                                ws['W59'].value = config.value
1023
                            elif config.key == 'Description' and config.value:
1024
                                ws['W73'].value = config.value
1025
                            elif config.key == 'RevStatus' and config.value:
1026
                                ws['Y68'].value = config.value
1027
                            elif config.key == 'CheckedBy' and config.value:
1028
                                ws['Z78'].value = config.value
1029
                            elif config.key == 'ApprovedBy' and config.value:
1030
                                ws['Z79'].value = config.value
1031

    
1032
                        configs = app_doc_data.getAppConfigs('app', 'SingleID')
1033
                        if configs and configs[0].value:
1034
                            ws['Z77'].value = configs[0].value
1035
                        ws['Z68'].value = str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1036
                        """up to here"""
1037

    
1038
                        # Output [Pump, Compressor, Control Valve]
1039
                        ws['X1'].value = 'Loop_Deviation'
1040
                        ws['X1'].font = Font(bold=True, underline='single', size=11)
1041

    
1042
                        loops = app_doc_data.activeDrawing.loops
1043
                        strmsg = None
1044
                        row_no = 2
1045
                        for loop in loops:
1046
                            deviation = loop.deviation
1047
                            if round(deviation, 9) == 0:
1048
                                continue
1049

    
1050
                            for i in range(1, len(loop.items) - 1, 3):
1051
                                if i == 1:
1052
                                    loop_no = loop.name.replace('Loop', '')
1053
                                    if len(loop_no) > 1:
1054
                                        strmsg = '({}) {}'.format(loop_no, loop.items[i].stream_no)
1055
                                    else:
1056
                                        strmsg = '(0{}) {}'.format(loop_no, loop.items[i].stream_no)
1057
                                else:
1058
                                    if len(str(loop.items[i - 1])) > 13 and str(loop.items[i - 1])[
1059
                                                                            :13] == 'Line_Splitter':
1060
                                        pre_stream_num = loop.items[i - 3].stream_no
1061
                                        cur_stream_num = loop.items[i].stream_no
1062

    
1063
                                        if strmsg.__contains__('-'):
1064
                                            last_stream_num = str(strmsg).rsplit('-', 1)[1]
1065
                                        else:
1066
                                            last_stream_num = str(strmsg).rsplit(' ', 1)[1]
1067

    
1068
                                        if pre_stream_num != int(last_stream_num):
1069
                                            strmsg = '{}-{}-{}'.format(strmsg, pre_stream_num, cur_stream_num)
1070

    
1071
                            last_stream_num = loop.items[len(loop.items) - 2].stream_no
1072
                            strmsg = '{}-{}'.format(strmsg, last_stream_num)
1073

    
1074
                            value = '{} = {} {}'.format(strmsg, round(deviation, 3), units['Pressure'])
1075
                            if round(deviation, 3) < 0:
1076
                                ws.cell(row_no, 24, value).font = Font(underline='single',
1077
                                                                       size=10,
1078
                                                                       color='FF0000')
1079

    
1080
                            elif round(deviation, 3) > 0:
1081
                                ws.cell(row_no, 24, value).font = Font(size=10)
1082
                            else:
1083
                                ws.cell(row_no, 24, value).font = Font(underline='single',
1084
                                                                       size=10)
1085
                            row_no += 1
1086

    
1087
                        start_row_no = row_no + 1
1088
                        start_col_no = 24
1089
                        # Pump
1090
                        pumps = []
1091
                        row_no = start_row_no
1092
                        col_no = start_col_no
1093
                        for loop in loops:
1094
                            for item in loop.items:
1095
                                parent = item.parent
1096
                                if parent:
1097
                                    name = str(item).replace(
1098
                                        '_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1099
                                    if name in pumps:
1100
                                        continue
1101
                                    if name[:3] == 'R_P' or name[:3] == 'L_P' or name[:3] == 'V_P':
1102
                                        pumps.append(name)
1103

    
1104
                                        attr = item.parent.attribute
1105
                                        ws.cell(row_no, col_no, attr['Tag_No']).font = Font(bold=True,
1106
                                                                                            underline='single',
1107
                                                                                            size=11)
1108

    
1109
                                        row_no += 1
1110
                                        ws.cell(row_no, col_no, 'Suct.P :')
1111
                                        col_no += 2
1112
                                        ws.cell(row_no, col_no, round(attr['Suct.P'], 3))
1113
                                        col_no += 1
1114
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1115

    
1116
                                        row_no += 1
1117
                                        col_no = 24 if col_no == 27 else 28
1118
                                        ws.cell(row_no, col_no, 'Disc.P :')
1119
                                        col_no += 2
1120
                                        ws.cell(row_no, col_no, round(attr['Disc.P'], 3))
1121
                                        col_no += 1
1122
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1123

    
1124
                                        row_no += 1
1125
                                        col_no = 24 if col_no == 27 else 28
1126
                                        ws.cell(row_no, col_no, 'Diff.P :')
1127
                                        col_no += 2
1128
                                        ws.cell(row_no, col_no, round(attr['Diff.P'], 3))
1129
                                        col_no += 1
1130
                                        ws.cell(row_no, col_no, units['Pressure'])
1131

    
1132
                                        row_no += 1
1133
                                        col_no = 24 if col_no == 27 else 28
1134
                                        ws.cell(row_no, col_no, 'Head :')
1135
                                        col_no += 2
1136
                                        ws.cell(row_no, col_no, round(attr['Head'], 3))
1137
                                        col_no += 1
1138
                                        ws.cell(row_no, col_no, units['Length'])
1139

    
1140
                                        row_no += 1
1141
                                        col_no = 24 if col_no == 27 else 28
1142
                                        ws.cell(row_no, col_no, 'NPSHa :')
1143
                                        col_no += 2
1144
                                        ws.cell(row_no, col_no, round(attr['NPSHa'], 3))
1145
                                        col_no += 1
1146
                                        ws.cell(row_no, col_no, units['Length'])
1147

    
1148
                                        row_no += 1
1149
                                        col_no = 24 if col_no == 27 else 28
1150
                                        ws.cell(row_no, col_no, 'Vap. P :')
1151
                                        col_no += 2
1152
                                        ws.cell(row_no, col_no, attr['Vap. P'])
1153
                                        col_no += 1
1154
                                        ws.cell(row_no, col_no, '{}.a'.format(units['Pressure']))
1155

    
1156
                                        row_no += 1
1157
                                        col_no = 24 if col_no == 27 else 28
1158
                                        ws.cell(row_no, col_no, 'HHP :')
1159
                                        col_no += 2
1160
                                        ws.cell(row_no, col_no, round(attr['HHP'], 3))
1161
                                        col_no += 1
1162
                                        ws.cell(row_no, col_no, units['Power'])
1163

    
1164
                                        col_no = 28 if col_no == 27 else 24
1165
                                        row_no = row_no - 7 if col_no == 28 else row_no + 2
1166

    
1167
                        start_row_no += math.ceil(len(pumps)) * 9
1168

    
1169
                        # Compressor
1170
                        compressors = []
1171
                        row_no = start_row_no
1172
                        col_no = start_col_no
1173
                        for loop in loops:
1174
                            for item in loop.items:
1175
                                parent = item.parent
1176
                                if parent:
1177
                                    name = str(item).replace(
1178
                                        '_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1179
                                    if name in compressors:
1180
                                        continue
1181
                                    if name[:3] == 'R_K' or name[:3] == 'L_K':
1182
                                        compressors.append(name)
1183

    
1184
                                        attr = item.parent.attribute
1185
                                        ws.cell(row_no, col_no, attr['Tag_No']).font = Font(bold=True,
1186
                                                                                            underline='single',
1187
                                                                                            size=11)
1188

    
1189
                                        row_no += 1
1190
                                        ws.cell(row_no, col_no, 'Suct.P :')
1191
                                        col_no += 2
1192
                                        ws.cell(row_no, col_no, round(attr['Suct.P'], 3))
1193
                                        col_no += 1
1194
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1195

    
1196
                                        row_no += 1
1197
                                        col_no = 24 if col_no == 27 else 28
1198
                                        ws.cell(row_no, col_no, 'Disc.P :')
1199
                                        col_no += 2
1200
                                        ws.cell(row_no, col_no, round(attr['Disc.P'], 3))
1201
                                        col_no += 1
1202
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1203

    
1204
                                        row_no += 1
1205
                                        col_no = 24 if col_no == 27 else 28
1206
                                        ws.cell(row_no, col_no, 'Diff.P :')
1207
                                        col_no += 2
1208
                                        ws.cell(row_no, col_no, round(attr['Diff.P'], 3))
1209
                                        col_no += 1
1210
                                        ws.cell(row_no, col_no, units['Pressure'])
1211

    
1212
                                        row_no += 1
1213
                                        col_no = 24 if col_no == 27 else 28
1214
                                        ws.cell(row_no, col_no, 'HHP :')
1215
                                        col_no += 2
1216
                                        ws.cell(row_no, col_no, round(attr['HHP'], 3))
1217
                                        col_no += 1
1218
                                        ws.cell(row_no, col_no, units['Power'])
1219

    
1220
                                        col_no = 28 if col_no == 27 else 24
1221
                                        row_no = row_no - 4 if col_no == 28 else row_no + 2
1222

    
1223
                        start_row_no += math.ceil(len(compressors)) * 9
1224

    
1225
                        # Control Valve
1226
                        control_valves = []
1227
                        row_no = start_row_no
1228
                        col_no = start_col_no
1229
                        for loop in loops:
1230
                            for item in loop.items:
1231
                                parent = item.parent
1232
                                if parent:
1233
                                    name = str(item).replace(
1234
                                        '_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1235
                                    if name in control_valves:
1236
                                        continue
1237
                                    if name[:3] == 'CV_':
1238
                                        control_valves.append(name)
1239

    
1240
                                        attr = item.parent.attribute
1241
                                        ws.cell(row_no, col_no, attr['Tag_No']).font = Font(bold=True,
1242
                                                                                            underline='single',
1243
                                                                                            size=11)
1244

    
1245
                                        row_no += 1
1246
                                        ws.cell(row_no, col_no, 'Inlet P :')
1247
                                        col_no += 2
1248
                                        ws.cell(row_no, col_no, round(attr['Suct.P'], 3))
1249
                                        col_no += 1
1250
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1251

    
1252
                                        row_no += 1
1253
                                        col_no = 24 if col_no == 27 else 28
1254
                                        ws.cell(row_no, col_no, 'Outlet P :')
1255
                                        col_no += 2
1256
                                        ws.cell(row_no, col_no, round(attr['Disc.P'], 3))
1257
                                        col_no += 1
1258
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1259

    
1260
                                        row_no += 1
1261
                                        col_no = 24 if col_no == 27 else 28
1262
                                        ws.cell(row_no, col_no, 'Diff.P :')
1263
                                        col_no += 2
1264
                                        ws.cell(row_no, col_no, round(attr['Diff.P'], 3))
1265
                                        col_no += 1
1266
                                        ws.cell(row_no, col_no, units['Pressure'])
1267

    
1268
                                        row_no += 1
1269
                                        col_no = 24 if col_no == 27 else 28
1270
                                        ws.cell(row_no, col_no, 'dP Ratio :')
1271
                                        col_no += 2
1272
                                        ws.cell(row_no, col_no, round(attr['dP Ratio'] * 100, 2))
1273
                                        col_no += 1
1274
                                        ws.cell(row_no, col_no, '%')
1275

    
1276
                                        col_no = 28 if col_no == 27 else 24
1277
                                        row_no = row_no - 4 if col_no == 28 else row_no + 2
1278

    
1279
                        # write hmb unit
1280
                        ws['B54'].value = '-'
1281
                        ws['B55'].value = units['Pipe_Diameter']
1282
                        ws['B56'].value = units['Flowrate_Mass']
1283
                        ws['B57'].value = units['Flowrate_Volume']
1284
                        ws['B58'].value = units['Density']
1285
                        ws['B59'].value = units['Viscosity']
1286
                        ws['B60'].value = units['Temperature']  # Hidden
1287
                        ws['B61'].value = ''  # Hidden
1288
                        ws['B62'].value = ''  # Hidden
1289
                        ws['B63'].value = ''  # Hidden
1290
                        ws['B64'].value = units['Pipe_Diameter']  # Hidden
1291
                        ws['B65'].value = units['Pipe_Diameter']  # Hidden
1292
                        ws['B66'].value = ''  # Hidden
1293
                        ws['B67'].value = units['Length']
1294
                        ws['B68'].value = units['Length']
1295
                        ws['B69'].value = units['Roughness']
1296
                        ws['B70'].value = units['Velocity']  # Hidden
1297
                        ws['B71'].value = '{}/100{})'.format(units['Pressure'], units['Length'])  # Hidden
1298
                        ws['B73'].value = units['Velocity']
1299
                        ws['B74'].value = ''  # Hidden
1300
                        ws['B75'].value = ''  # Hidden
1301
                        ws['B76'].value = '{}/100{}'.format(units['Pressure'], units['Length'])
1302
                        ws['B77'].value = units['Pressure']
1303
                        ws['B78'].value = units['Pressure']
1304
                        ws['B79'].value = '{}(g)'.format(units['Pressure'])
1305

    
1306
                        page_no += 1
1307

    
1308
                    current_ws = wb.get_sheet_by_name('Page (1)')
1309
                    # write hmb data
1310
                    drawing = app_doc_data.activeDrawing
1311
                    hmbs = drawing.hmbTable._hmbs
1312
                    if hmbs is not None:
1313
                        stream_count = 1
1314
                        col_no = 3
1315
                        for hmb in hmbs:
1316
                            ws = self.get_work_sheet(wb, stream_count)
1317
                            if ws != current_ws:
1318
                                current_ws = ws
1319
                                col_no = 3
1320

    
1321
                            row_no = 53
1322
                            ws.cell(row_no, col_no, hmb.stream_no)
1323
                            row_no += 1
1324
                            ws.cell(row_no, col_no, hmb.phase_type)
1325
                            row_no += 1
1326
                            ws.cell(row_no, col_no, hmb.inside_pipe_size)
1327
                            row_no += 1
1328
                            ws.cell(row_no, col_no, hmb.flowrate_mass)
1329
                            row_no += 1
1330
                            ws.cell(row_no, col_no, hmb.flowrate_volume)
1331
                            row_no += 1
1332
                            ws.cell(row_no, col_no, hmb.density)
1333
                            row_no += 1
1334
                            ws.cell(row_no, col_no, hmb.viscosity)
1335
                            row_no += 1
1336
                            ws.cell(row_no, col_no, hmb.temperature)
1337
                            row_no += 1
1338
                            ws.cell(row_no, col_no, hmb.molecular_weight)
1339
                            row_no += 1
1340
                            ws.cell(row_no, col_no, hmb.specific_heat_ratio)
1341
                            row_no += 1
1342
                            ws.cell(row_no, col_no, hmb.compress_factor)
1343
                            row_no += 1
1344
                            ws.cell(row_no, col_no, hmb.nominal_pipe_size)
1345
                            row_no += 1
1346
                            ws.cell(row_no, col_no, hmb.inside_pipe_size)
1347
                            row_no += 1
1348
                            ws.cell(row_no, col_no, hmb.schedule_no)
1349
                            row_no += 1
1350
                            ws.cell(row_no, col_no, hmb.straight_length)
1351
                            row_no += 1
1352
                            ws.cell(row_no, col_no, hmb.equivalent_length)
1353
                            row_no += 1
1354
                            ws.cell(row_no, col_no, hmb.roughness)
1355
                            row_no += 1
1356
                            ws.cell(row_no, col_no, hmb.limitation_velocity)
1357
                            row_no += 1
1358
                            ws.cell(row_no, col_no, hmb.limitation_pressure_drop)
1359
                            row_no += 2
1360
                            ws.cell(row_no, col_no, hmb.velocity)
1361
                            row_no += 1
1362
                            ws.cell(row_no, col_no, hmb.reynolds)
1363
                            row_no += 1
1364
                            ws.cell(row_no, col_no, hmb.friction_factor)
1365
                            row_no += 1
1366
                            ws.cell(row_no, col_no, hmb.pressure_drop)
1367
                            row_no += 1
1368
                            ws.cell(row_no, col_no, hmb.pressure_drop_friction)
1369
                            row_no += 1
1370
                            ws.cell(row_no, col_no, hmb.pressure_drop_static)
1371
                            row_no += 1
1372
                            ws.cell(row_no, col_no, hmb.pressure_pipe_end_point)
1373

    
1374
                            col_no += 1
1375
                            stream_count += 1
1376

    
1377
                    # two_phase
1378
                    if hmbs is not None:
1379
                        for hmb in hmbs:
1380
                            if hmb.phase_type == 'Mixed':
1381
                                lines = [item for item in self.graphicsView.scene.items() if type(
1382
                                    item) is QEngineeringStreamlineItem and str(item.uid) == str(hmb.components_uid)]
1383
                                if lines:
1384
                                    ws = wb.copy_worksheet(wb.get_sheet_by_name('Two_phase'))
1385
                                    ws.title = 'Two Phase {}'.format(str(lines[0]))
1386

    
1387
                                    # Information
1388
                                    ws['B5'].value = 'File : Two_Phase'
1389
                                    ws['B6'].value = 'Line : {}'.format(lines[0].stream_no)
1390
                                    ws['G6'].value = 'Made by : {}'.format(configs[0].value)
1391

    
1392
                                    # Process Data
1393
                                    ws['C10'].value = units['Flowrate_Mass']
1394
                                    ws['D10'].value = units['Density']
1395
                                    ws['E10'].value = units['Viscosity']
1396
                                    ws['F10'].value = '{}(g)'.format(units['Pressure'])
1397
                                    ws['G10'].value = units['Temperature']
1398

    
1399
                                    ws['C11'].value = lines[0].data.liquid_flowrate_mass
1400
                                    ws['D11'].value = lines[0].data.liquid_density
1401
                                    ws['E11'].value = lines[0].data.liquid_viscosity
1402

    
1403
                                    ws['C12'].value = lines[0].data.vapor_flowrate_mass
1404
                                    ws['D12'].value = lines[0].data.vapor_density
1405
                                    ws['E12'].value = lines[0].data.vapor_viscosity
1406
                                    ws['F12'].value = lines[0].data.vapor_pressure
1407
                                    ws['G12'].value = lines[0].data.vapor_temperature
1408
                                    ws['H12'].value = lines[0].data.vapor_molecular_weight
1409
                                    ws['I12'].value = lines[0].data.vapor_compress_factor
1410

    
1411
                                    # Geometry Data
1412
                                    ws['D16'].value = units['Pipe_Diameter']
1413
                                    ws['E16'].value = units['Roughness']
1414
                                    ws['F16'].value = units['Length']
1415

    
1416
                                    row_no = 17
1417
                                    for geometry in lines[0].mixed_geometry:
1418
                                        col_no = 3
1419
                                        ws.cell(row_no, col_no, str(geometry[0]))  # Element
1420
                                        col_no += 1
1421
                                        ws.cell(row_no, col_no,
1422
                                                float(geometry[3]) if is_float(geometry[3]) else None)  # ID
1423
                                        col_no += 1
1424
                                        ws.cell(row_no, col_no,
1425
                                                float(geometry[4]) if is_float(geometry[4]) else None)  # Roughness
1426
                                        col_no += 1
1427
                                        ws.cell(row_no, col_no,
1428
                                                float(geometry[5]) if is_float(geometry[5]) else None)  # Length
1429
                                        col_no += 1
1430
                                        ws.cell(row_no, col_no,
1431
                                                float(geometry[6]) if is_float(geometry[6]) else None)  # Angle
1432
                                        col_no += 1
1433
                                        ws.cell(row_no, col_no,
1434
                                                float(geometry[7]) if is_float(geometry[7]) else None)  # R/D
1435
                                        col_no += 1
1436
                                        ws.cell(row_no, col_no,
1437
                                                float(geometry[9]) if is_float(geometry[9]) else None)  # K
1438

    
1439
                                        row_no += 1
1440

    
1441

    
1442
                                    # horizontal_flow_image = openpyxl.drawing.image.Image(horizontal_flow_image_path)
1443
                                    # horizontal_flow_image.width *= 0.6
1444
                                    # horizontal_flow_image.height *= 0.6
1445
                                    # ws.add_image(horizontal_flow_image, 'L3')
1446

    
1447
                                    # vertical_upward_flow_image = openpyxl.drawing.image.Image(
1448
                                    #     vertical_upward_flow_image_path)
1449
                                    # vertical_upward_flow_image.width *= 0.6
1450
                                    # vertical_upward_flow_image.height *= 0.6
1451
                                    # ws.add_image(vertical_upward_flow_image, 'R3')
1452

    
1453
                                    # vertical_downward_flow_image = openpyxl.drawing.image.Image(
1454
                                    #     vertical_downward_flow_image_path)
1455
                                    # vertical_downward_flow_image.width *= 0.6
1456
                                    # vertical_downward_flow_image.height *= 0.6
1457
                                    # ws.add_image(vertical_downward_flow_image, 'Z3')
1458

    
1459
                                    horizontal = DrawImage(horizontal_flow_image_path)
1460
                                    vertical_upward = DrawImage(vertical_upward_flow_image_path)
1461
                                    vertical_downward = DrawImage(vertical_downward_flow_image_path)
1462
                                    # Calculation Result
1463
                                    row_no = 37
1464
                                    for row in lines[0].mixed_pressure_variation:
1465
                                        col_no = 12
1466
                                        ws.cell(row_no, col_no, str(row[0]))    # Element
1467
                                        col_no += 1
1468
                                        ws.cell(row_no, col_no, row[1])         # ID
1469
                                        col_no += 1
1470
                                        ws.cell(row_no, col_no, row[2])         # Length
1471
                                        col_no += 1
1472
                                        ws.cell(row_no, col_no, row[3])         # Angle
1473
                                        col_no += 1
1474
                                        ws.cell(row_no, col_no, row[4])         # K
1475
                                        col_no += 1
1476
                                        ws.cell(row_no, col_no, row[5])         # Pressure
1477
                                        col_no += 1
1478
                                        ws.cell(row_no, col_no, row[6])         # Void
1479
                                        col_no += 1
1480
                                        ws.cell(row_no, col_no, row[7])         # Quality
1481
                                        col_no += 1
1482
                                        ws.cell(row_no, col_no, row[8])         # Density
1483
                                        col_no += 1
1484
                                        ws.cell(row_no, col_no, row[9])         # V.Density
1485
                                        col_no += 1
1486
                                        ws.cell(row_no, col_no, row[10])        # Mean.Vel
1487
                                        col_no += 1
1488
                                        ws.cell(row_no, col_no, row[11])        # Max.Vel
1489
                                        col_no += 1
1490
                                        ws.cell(row_no, col_no, row[12])        # Ero.Vel
1491
                                        col_no += 1
1492
                                        ws.cell(row_no, col_no, row[13])        # X
1493
                                        col_no += 1
1494
                                        ws.cell(row_no, col_no, row[14])        # Y
1495
                                        col_no += 1
1496
                                        ws.cell(row_no, col_no, str(row[15]) if row[15] else '')    # Regime
1497
                                        col_no += 1
1498
                                        ws.cell(row_no, col_no, row[16])        # Friction
1499
                                        col_no += 1
1500
                                        ws.cell(row_no, col_no, row[17])        # Gravity
1501
                                        col_no += 1
1502
                                        ws.cell(row_no, col_no, row[18])        # Moment
1503
                                        col_no += 1
1504
                                        ws.cell(row_no, col_no, row[19])        # Total
1505

    
1506
                                        # load_regime
1507
                                        length = row[2]
1508
                                        if length is not None:
1509
                                            x = float(row[13])
1510
                                            y = float(row[14])
1511

    
1512
                                            angle = float(row[3])
1513
                                            if angle == 0:
1514
                                                # Horizontal
1515
                                                left = 57 + (546 / (7 + 5)) * (math.log10(x) + 5)
1516
                                                top = 651 - (649 / (5 + 9)) * (math.log10(y) + 9)
1517
                                                horizontal.draw_regime(left, top, 8)
1518
                                            elif angle > 0:
1519
                                                # Vertical Upward
1520
                                                left = 59 + (538 / (7 - (-2))) * (math.log10(x) - (-2))
1521
                                                top = 681 - (653 / (8 - (-5))) * (math.log10(y) - (-5))
1522
                                                vertical_upward.draw_regime(left, top, 8)
1523
                                            elif angle < 0:
1524
                                                # Vertical Downward
1525
                                                left = 55 + (517 / (20 - 0)) * (x - 0)
1526
                                                top = 656 - (635 / (24 - 2)) * (y - 2)
1527
                                                vertical_downward.draw_regime(left, top, 8)
1528
                                        row_no += 1
1529

    
1530
                                    with NamedTemporaryFile() as f:
1531
                                        horizontal_image_path = f.name + '.png'
1532
                                    horizontal.save_as(horizontal_image_path)
1533

    
1534
                                    horizontal_flow_image = openpyxl.drawing.image.Image(horizontal_image_path)
1535
                                    horizontal_flow_image.width *= 0.6
1536
                                    horizontal_flow_image.height *= 0.6
1537
                                    ws.add_image(horizontal_flow_image, 'L3')
1538

    
1539
                                    with NamedTemporaryFile() as f:
1540
                                        vertical_upward_image_path = f.name + '.png'
1541
                                    vertical_upward.save_as(vertical_upward_image_path)
1542

    
1543
                                    vertical_upward_flow_image = openpyxl.drawing.image.Image(
1544
                                        vertical_upward_image_path)
1545
                                    vertical_upward_flow_image.width *= 0.6
1546
                                    vertical_upward_flow_image.height *= 0.6
1547
                                    ws.add_image(vertical_upward_flow_image, 'R3')
1548

    
1549
                                    with NamedTemporaryFile() as f:
1550
                                        vertical_downward_image_path = f.name + '.png'
1551
                                    vertical_downward.save_as(vertical_downward_image_path)
1552

    
1553
                                    vertical_downward_flow_image = openpyxl.drawing.image.Image(
1554
                                        vertical_downward_image_path)
1555
                                    vertical_downward_flow_image.width *= 0.6
1556
                                    vertical_downward_flow_image.height *= 0.6
1557
                                    ws.add_image(vertical_downward_flow_image, 'Z3')
1558

    
1559
                    active_sheet = wb.get_sheet_by_name('Page (1)')
1560
                    if active_sheet:
1561
                        wb.active = active_sheet
1562

    
1563
                    wb.get_sheet_by_name('Page').sheet_state = 'hidden'
1564
                    wb.get_sheet_by_name('Two_phase').sheet_state = 'hidden'
1565

    
1566
                    name_without_ext, ext = os.path.splitext(file_name)
1567
                    save_file_name = file_name if ext.upper() == '.XLSX' else name_without_ext + '.xlsx'
1568
                    wb.save(filename=save_file_name)
1569

    
1570
                    os.startfile(save_file_name)
1571

    
1572
                    QMessageBox.information(self, self.tr('Information'), self.tr('Report is done'))
1573
        except Exception as ex:
1574
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1575
                                                           sys.exc_info()[-1].tb_lineno)
1576
            self.addMessage.emit(MessageType.Error, message)
1577

    
1578
    def get_work_sheet(self, work_book, count):
1579
        page_no = math.ceil(count / 20)
1580
        return work_book.get_sheet_by_name('Page ({})'.format(page_no))
1581

    
1582
    def display_output(self):
1583
        try:
1584
            """ display output """
1585
            drawing = AppDocData.instance().activeDrawing
1586
            if drawing is None:
1587
                return
1588

    
1589
            self.clear_output()
1590

    
1591
            self.tableWidgetOutput.setColumnCount(3)
1592
            self.tableWidgetOutput.horizontalHeader().setVisible(False)
1593
            self.tableWidgetOutput.verticalHeader().setVisible(False)
1594
            self.tableWidgetOutput.setSelectionMode(QAbstractItemView.SingleSelection)
1595
            self.tableWidgetOutput.setSelectionBehavior(QAbstractItemView.SelectRows)
1596
            self.tableWidgetOutput.setEditTriggers(QAbstractItemView.NoEditTriggers)
1597
            self.tableWidgetOutput.horizontalHeader().setStretchLastSection(True)
1598

    
1599
            self.tableWidgetDeviation.setColumnCount(1)
1600
            self.tableWidgetDeviation.horizontalHeader().setVisible(False)
1601
            self.tableWidgetDeviation.verticalHeader().setVisible(False)
1602
            self.tableWidgetDeviation.setSelectionMode(QAbstractItemView.SingleSelection)
1603
            self.tableWidgetDeviation.setSelectionBehavior(QAbstractItemView.SelectRows)
1604
            self.tableWidgetDeviation.setEditTriggers(QAbstractItemView.NoEditTriggers)
1605
            self.tableWidgetDeviation.horizontalHeader().setStretchLastSection(True)
1606
            self.tableWidgetDeviation.resizeRowsToContents()
1607
            self.tableWidgetDeviation.resizeColumnsToContents()
1608

    
1609
            units = [attr[1] for attr in drawing.attrs if attr[0] == 'Units'][0]
1610

    
1611
            loops = drawing.loops
1612

    
1613
            # Deviation
1614
            self.add_data(self.tableWidgetDeviation, 'Loop_Deviation', None, None, True, None, None)
1615
            strmsg = None
1616
            for loop in loops:
1617
                deviation = loop.deviation
1618
                if round(deviation, 9) == 0:
1619
                    continue
1620

    
1621
                for i in range(1, len(loop.items) - 1, 3):
1622
                    if i == 1:
1623
                        loop_no = loop.name.replace('Loop', '')
1624
                        if len(loop_no) > 1:
1625
                            strmsg = '({}) {}'.format(loop_no, loop.items[i].stream_no)
1626
                        else:
1627
                            strmsg = '(0{}) {}'.format(loop_no, loop.items[i].stream_no)
1628
                    else:
1629
                        if len(str(loop.items[i - 1])) > 13 and str(loop.items[i - 1])[:13] == 'Line_Splitter':
1630
                            pre_stream_num = loop.items[i - 3].stream_no
1631
                            cur_stream_num = loop.items[i].stream_no
1632

    
1633
                            if strmsg.__contains__('-'):
1634
                                last_stream_num = str(strmsg).rsplit('-', 1)[1]
1635
                            else:
1636
                                last_stream_num = str(strmsg).rsplit(' ', 1)[1]
1637

    
1638
                            if pre_stream_num != int(last_stream_num):
1639
                                strmsg = '{}-{}-{}'.format(strmsg, pre_stream_num, cur_stream_num)
1640

    
1641
                last_stream_num = loop.items[len(loop.items) - 2].stream_no
1642
                strmsg = '{}-{}'.format(strmsg, last_stream_num)
1643

    
1644
                if round(deviation, 3) < 0:
1645
                    self.add_data(self.tableWidgetDeviation,
1646
                                  '{} = {} {}'.format(strmsg, round(deviation, 3), units['Pressure']), None, None, None,
1647
                                  None, QBrush(QColor(255, 0, 0)))
1648
                else:
1649
                    self.add_data(self.tableWidgetDeviation,
1650
                                  '{} = {} {}'.format(strmsg, round(deviation, 3), units['Pressure']), None, None, None,
1651
                                  None)
1652

    
1653
            names = []
1654
            # Pump
1655
            for loop in loops:
1656
                for item in loop.items:
1657
                    parent = item.parent
1658
                    if parent:
1659
                        name = str(item).replace('_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1660
                        if name in names:
1661
                            continue
1662
                        if name[:3] == 'R_P' or name[:3] == 'L_P' or name[:3] == 'V_P':
1663
                            names.append(name)
1664
                            attr = item.parent.attribute
1665
                            if len(attr) > 0:
1666
                                self.add_data(self.tableWidgetOutput, attr['Tag_No'], None, None, True, True)
1667
                                self.add_data(self.tableWidgetOutput, 'Suct.P :', round(attr['Suct.P'], 3),
1668
                                              '{}.g'.format(units['Pressure']))
1669
                                self.add_data(self.tableWidgetOutput, 'Disc.P :', round(attr['Disc.P'], 3),
1670
                                              '{}.g'.format(units['Pressure']))
1671
                                self.add_data(self.tableWidgetOutput, 'Diff.P :', round(attr['Diff.P'], 3),
1672
                                              units['Pressure'])
1673
                                self.add_data(self.tableWidgetOutput, 'Head :', round(attr['Head'], 3), units['Length'])
1674
                                self.add_data(self.tableWidgetOutput, 'NPSHa :', round(attr['NPSHa'], 3), units['Length'])
1675
                                self.add_data(self.tableWidgetOutput, 'Vap. P :', attr['Vap. P'],
1676
                                              '{}.a'.format(units['Pressure']))
1677
                                self.add_data(self.tableWidgetOutput, 'HHP :', round(attr['HHP'], 3), units['Power'])
1678

    
1679
            # Compressor
1680
            for loop in loops:
1681
                for item in loop.items:
1682
                    parent = item.parent
1683
                    if parent:
1684
                        name = str(item).replace('_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1685
                        if name in names:
1686
                            continue
1687
                        if name[:3] == 'R_K' or name[:3] == 'L_K':
1688
                            names.append(name)
1689

    
1690
                            attr = item.parent.attribute
1691
                            if len(attr) > 0:
1692
                                self.add_data(self.tableWidgetOutput, attr['Tag_No'], None, None, True, True)
1693
                                self.add_data(self.tableWidgetOutput, 'Suct.P :', round(attr['Suct.P'], 3),
1694
                                              '{}.g'.format(units['Pressure']))
1695
                                self.add_data(self.tableWidgetOutput, 'Disc.P :', round(attr['Disc.P'], 3),
1696
                                              '{}.g'.format(units['Pressure']))
1697
                                self.add_data(self.tableWidgetOutput, 'Diff.P :', round(attr['Diff.P'], 3),
1698
                                              units['Pressure'])
1699
                                self.add_data(self.tableWidgetOutput, 'HHP :', round(attr['HHP'], 3), units['Power'])
1700

    
1701
            # Control Valve
1702
            for loop in loops:
1703
                for item in loop.items:
1704
                    parent = item.parent
1705
                    if parent:
1706
                        name = str(item).replace('_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1707
                        if name in names:
1708
                            continue
1709
                        if name[:3] == 'CV_':
1710
                            names.append(name)
1711

    
1712
                            attr = item.parent.attribute
1713
                            if len(attr) > 0:
1714
                                self.add_data(self.tableWidgetOutput, attr['Tag_No'], None, None, True, True)
1715
                                self.add_data(self.tableWidgetOutput, 'Inlet P :', round(attr['Suct.P'], 3),
1716
                                              '{}.g'.format(units['Pressure']))
1717
                                self.add_data(self.tableWidgetOutput, 'Outlet P :', round(attr['Disc.P'], 3),
1718
                                              '{}.g'.format(units['Pressure']))
1719
                                self.add_data(self.tableWidgetOutput, 'Diff.P :', round(attr['Diff.P'], 3),
1720
                                              units['Pressure'])
1721
                                self.add_data(self.tableWidgetOutput, 'dP Ratio :', round(attr['dP Ratio'] * 100, 2), '%')
1722

    
1723
        except Exception as ex:
1724
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1725
                                                           sys.exc_info()[-1].tb_lineno)
1726
            self.addMessage.emit(MessageType.Error, message)
1727

    
1728
    def display_loops(self):
1729
        """ display loops """
1730
        drawing = AppDocData.instance().activeDrawing
1731
        if drawing is None: return
1732

    
1733
        loops = drawing.loops
1734
        if loops:
1735
            self.tableWidgetLoop.clear()
1736
            self.tableWidgetLoop.setColumnCount(len(loops) * 5)
1737

    
1738
            _col_names = [[loop.name, 'pressure', 'Static\nLine\ndP_Eq', 'El.\nDensity\nEl.', 'Extra'] for loop in
1739
                          loops]
1740
            col_names = []
1741
            for col_name in _col_names: col_names.extend(col_name)
1742
            self.tableWidgetLoop.setHorizontalHeaderLabels(col_names)
1743
            self.tableWidgetLoop.horizontalHeader().setVisible(True)
1744

    
1745
            max_rows = 0
1746
            for col in range(len(loops)):
1747
                rows = len(loops[col].items)
1748
                max_rows = max(max_rows, rows)
1749
                self.tableWidgetLoop.setRowCount(max_rows)
1750

    
1751
                for row in range(len(loops[col].items)):
1752
                    item = QTableWidgetItem(str(loops[col].items[row]))
1753
                    item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
1754
                    self.tableWidgetLoop.setItem(row, col * 5, item)
1755

    
1756
                # display calcuation values
1757
                for row in range(len(loops[col].items)):
1758
                    if loops[col].items[row] in loops[col].pressures:
1759
                        item = QTableWidgetItem(str(round(loops[col].pressures[loops[col].items[row]], 8)))
1760
                        item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
1761
                        # if not loops[col].pressures[loops[col].items[row]]: item.setBackground(Qt.red)
1762
                        self.tableWidgetLoop.setItem(row, col * 5 + 1, item)
1763

    
1764
                    if loops[col].items[row] in loops[col].pressure_drops:
1765
                        item = QTableWidgetItem(str(round(loops[col].pressure_drops[loops[col].items[row]], 9)))
1766
                        item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
1767
                        # if not loops[col].pressure_drops[loops[col].items[row]]: item.setBackground(Qt.red)
1768
                        self.tableWidgetLoop.setItem(row, col * 5 + 2, item)
1769

    
1770
                    if loops[col].items[row] in loops[col].density_elevations:
1771
                        item = QTableWidgetItem(str(round(loops[col].density_elevations[loops[col].items[row]], 8)))
1772
                        item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
1773
                        # if not loops[col].density_elevations[loops[col].items[row]]: item.setBackground(Qt.red)
1774
                        self.tableWidgetLoop.setItem(row, col * 5 + 3, item)
1775

    
1776
                    if loops[col].items[row] in loops[col].extras:
1777
                        item = QTableWidgetItem(str(loops[col].extras[loops[col].items[row]]))
1778
                        item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
1779
                        # if not loops[col].density_elevations[loops[col].items[row]]: item.setBackground(Qt.red)
1780
                        self.tableWidgetLoop.setItem(row, col * 5 + 4, item)
1781

    
1782
            self.tableWidgetLoop.resizeColumnsToContents()
1783
            self.tableWidgetLoop.resizeRowsToContents()
1784

    
1785
    '''
1786
        @brief  configuration
1787
    '''
1788

    
1789
    def configuration(self):
1790
        from ConfigurationDialog import QConfigurationDialog
1791
        try:
1792
            appDocData = AppDocData.instance()
1793
            if appDocData.activeDrawing is None:
1794
                self.showImageSelectionMessageBox()
1795
                return
1796

    
1797
            dlg = QConfigurationDialog(self)
1798
            (isAccepted, isDataConversion, decimal) = dlg.show_dialog()
1799
            if isAccepted == True:
1800
                if isDataConversion == True:
1801
                    self.data_conversion(decimal)
1802
                else:
1803
                    self.reload_units()
1804

    
1805
        except Exception as ex:
1806
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1807
                                                           sys.exc_info()[-1].tb_lineno)
1808
            self.addMessage.emit(MessageType.Error, message)
1809

    
1810
    def data_conversion(self, decimal):
1811
        from Drawing import Drawing
1812
        from Calculation import Conversion
1813

    
1814
        try:
1815
            Conversion(decimal)
1816

    
1817
            self.load_HMB()
1818
            self.reload_units()
1819

    
1820
        except Exception as ex:
1821
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1822
                                                           sys.exc_info()[-1].tb_lineno)
1823
            self.addMessage.emit(MessageType.Error, message)
1824

    
1825
    '''
1826
        @brief  Show Image Selection Guide MessageBox
1827
        @author Jeongwoo
1828
        @date   2018.05.02
1829
    '''
1830

    
1831
    def showImageSelectionMessageBox(self):
1832
        QMessageBox.information(self, self.tr("Information"), self.tr("First select image drawing"))
1833

    
1834
    def display_colors(self, value):
1835
        """ display colors """
1836
        from DisplayColors import DisplayColors
1837
        from DisplayColors import DisplayOptions
1838

    
1839
        DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value == True else DisplayOptions.DisplayByLineType
1840
        if hasattr(self, 'graphicsView'):
1841
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1842
            DisplayColors.instance().save_data()
1843

    
1844
    '''
1845
        @brief      Open Border file 
1846
        @author     yeonjin
1847
        @date       2019.07.10
1848
    '''
1849

    
1850
    def open_border_file(self):
1851
        app_doc_data = AppDocData.instance()
1852
        borderFile = app_doc_data.border_file_path
1853
        if not os.path.exists(borderFile):
1854
            self.create_border_file(borderFile)
1855

    
1856
        self.graphicsView.loadImageFromFile(fileName=borderFile)
1857

    
1858
    '''
1859
        @brief      Create Border file 
1860
        @author     yeonjin
1861
        @date       2019.07.10
1862
    '''
1863

    
1864
    def create_border_file(self, border):
1865

    
1866
        from PIL import Image
1867
        # A4 size : 210, 297
1868
        # A3 size : 297, 420
1869
        # A2 size : 420, 594
1870
        # A1 size : 594, 841
1871
        # A0 size : 841, 1189
1872
        # color : 0, 128, 128 진한 청록
1873
        # color : 255, 255, 255 White
1874
        img = Image.new('RGBA', (1189, 841), (255, 255, 255))
1875
        img.save(border)
1876

    
1877
    def setAttributes(self, drawing):
1878
        drawing.setAttributes()
1879

    
1880
    '''
1881
        @brief      Reload HMB Units 
1882
        @author     yeonjin
1883
        @date       2019.07.10
1884
    '''
1885

    
1886
    def reload_units(self):
1887
        from Drawing import Drawing
1888

    
1889
        try:
1890
            app_doc_data = AppDocData.instance()
1891
            drawing = app_doc_data.activeDrawing
1892

    
1893
            self.setAttributes(drawing)
1894

    
1895
            columnInfos = app_doc_data.getHMBDisplayNameAndUnitsExpression()
1896

    
1897
            rowIndex = 0
1898
            for columnInfo in columnInfos:
1899
                name = columnInfo[0]
1900
                unit = self.convertToUnits(columnInfo[1])
1901

    
1902
                self.tableWidgetHMB.setItem(rowIndex, 0,
1903
                                            set_item_properties(name, Qt.AlignLeft | Qt.AlignVCenter,
1904
                                                                QColor(51, 153,
1905
                                                                       102)))
1906
                # QColor(230, 230, 230)))
1907
                self.tableWidgetHMB.setItem(rowIndex, 1,
1908
                                            set_item_properties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
1909
                                                                QColor(204, 255, 204)))
1910
                # QColor(230, 230, 230)))
1911

    
1912
                rowIndex += 1
1913

    
1914
            self.tableWidgetHMB.resizeColumnsToContents()
1915
            self.tableWidgetHMB.resizeRowsToContents()
1916

    
1917
        except Exception as ex:
1918
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1919
                                                           sys.exc_info()[-1].tb_lineno)
1920
            self.addMessage.emit(MessageType.Error, message)
1921

    
1922
    def load_data(self, drawing):
1923
        """ load data from drawing """
1924
        from AppDocData import AppDocData
1925
        from Calculation import Calculation
1926
        from HydroCalculationCommand import HydroCalculationCommand
1927
        from Drawing import Drawing
1928

    
1929
        try:
1930
            app_doc_data = AppDocData.instance()
1931

    
1932
            # Set appDocData
1933
            app_doc_data.clear()
1934
            self.onCommandRejected()
1935
            app_doc_data.activeDrawing = drawing
1936

    
1937
            self.setAttributes(drawing)
1938
            self.setMainWindowTitle(drawing.path)
1939
            self.initTableWidgetHMB()
1940
            self.clear_loop()
1941
            self.clearlogs()
1942
            self.clear_output()
1943
            # Load data on database
1944

    
1945
            self.symbolTreeWidget.initSymbolTreeWidget()
1946

    
1947
            components = app_doc_data.getComponentListByDrawingUID()
1948
            count = len(components)
1949

    
1950
            if count > 0:
1951
                try:
1952
                    self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
1953
                                                    self) if not hasattr(self, 'progress') else self.progress
1954
                    self.progress.setWindowModality(Qt.WindowModal)
1955
                    self.progress.setAutoReset(True)
1956
                    self.progress.setAutoClose(True)
1957
                    self.progress.setMinimum(0)
1958
                    self.progress.resize(600, 100)
1959
                    self.progress.setWindowTitle(self.tr("Load data..."))
1960
                    self.progress.show()
1961

    
1962
                    self.load_components(components)
1963

    
1964
                    # Loops 와 Output 을 만들기 위해 Calculation 을 한다
1965
                    for hmb in app_doc_data.activeDrawing.hmbTable._hmbs:
1966
                        if hmb.phase_type:
1967
                            Calculation(hmb)
1968
                    cmd = HydroCalculationCommand(self.graphicsView)
1969
                    cmd.execute(None)
1970
                    cmd.execute_second(None)
1971

    
1972
                    app_doc_data.activeDrawing.loops = cmd.loops
1973

    
1974
                    self.display_loops()
1975
                    self.display_output()
1976

    
1977
                    self.load_HMB()
1978
                finally:
1979
                    self.progress.setValue(self.progress.maximum())
1980
                    self.progress.hide()
1981

    
1982
            # self.changeViewCheckedState(False)
1983

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

    
1989
    def saveAs_drawing(self, sourceDb):
1990
        import uuid
1991
        from shutil import copyfile
1992
        from datetime import datetime
1993
        from Drawing import Drawing
1994

    
1995
        workspace = self.get_work_space()
1996

    
1997
        options = QFileDialog.Options()
1998
        options |= QFileDialog.DontUseNativeDialog
1999
        name, _ = QFileDialog.getSaveFileName(self, self.tr('Save As'), workspace, 'HYTOS Files (*.hytos)',
2000
                                              options=options)
2001
        if name:
2002
            if os.path.splitext(name)[1] != '.hytos': name += '.hytos'
2003

    
2004
            app_doc_data = AppDocData.instance()
2005
            # copy template.db to name
2006
            copyfile(sourceDb, name)
2007

    
2008
            matches = [drawing for drawing in app_doc_data.getDrawings() if
2009
                       os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
2010
            if not matches:
2011
                drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
2012
                app_doc_data.saveDrawing(drawing)
2013
            else:
2014
                drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
2015
                app_doc_data.updateDrawing(drawing)
2016

    
2017
            self.load_drawing_list()
2018
            self.open_border_file()
2019
            self.load_data(drawing)
2020

    
2021
    '''
2022
        @brief      create new drawing
2023
        @author     yeonjin
2024
        @date       2019.07.03
2025
    '''
2026

    
2027
    def new_drawing(self):
2028
        import uuid
2029
        from shutil import copyfile
2030
        from datetime import datetime
2031
        from Drawing import Drawing
2032

    
2033
        self.save_drawing_if_necessary()
2034

    
2035
        workspace = self.get_work_space()
2036

    
2037
        options = QFileDialog.Options()
2038
        options |= QFileDialog.DontUseNativeDialog
2039
        name, _ = QFileDialog.getSaveFileName(self, self.tr('New'), workspace, 'HYTOS Files (*.hytos)', options=options)
2040
        if name:
2041

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

    
2044
            app_doc_data = AppDocData.instance()
2045
            # copy template.db to name
2046
            copyfile(app_doc_data.getTemplateDbPath(), name)
2047

    
2048
            matches = [drawing for drawing in app_doc_data.getDrawings() if
2049
                       os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
2050
            if not matches:
2051
                drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
2052
                app_doc_data.saveDrawing(drawing)
2053
            else:
2054
                drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
2055
                app_doc_data.updateDrawing(drawing)
2056

    
2057
            self.load_drawing_list()
2058
            self.open_border_file()
2059
            self.load_data(drawing)
2060

    
2061
    def on_open_drawing(self):
2062
        """open selected drawing by user"""
2063

    
2064
        self.save_drawing_if_necessary()
2065

    
2066
        workspace = self.get_work_space()
2067
        options = QFileDialog.Options()
2068
        options |= QFileDialog.DontUseNativeDialog
2069
        name, _ = QFileDialog.getOpenFileName(self, self.tr('Open'), workspace, 'HYTOS File(*.hytos)', options=options)
2070
        if name:
2071
            self.open_drawing(name)
2072

    
2073
    def open_drawing(self, name):
2074
        """open given drawing has name"""
2075
        import uuid
2076
        from Drawing import Drawing
2077
        from datetime import datetime
2078

    
2079
        app_doc_data = AppDocData.instance()
2080
        drawings = app_doc_data.getDrawings()
2081
        matches = [drawing for drawing in drawings if os.path.samefile(drawing.path, name)]
2082
        if not matches:
2083
            drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
2084
            app_doc_data.saveDrawing(drawing)
2085

    
2086
            self.load_drawing_list()
2087
        else:
2088
            drawing = matches[0]
2089

    
2090
        # disconnect scene changed if signal is connected
2091
        if self.graphicsView.scene.receivers(self.graphicsView.scene.contents_changed) > 0:
2092
            self.graphicsView.scene.contents_changed.disconnect()
2093

    
2094
        self.open_border_file()
2095
        self.load_data(drawing)
2096

    
2097
        # connect scene changed signal
2098
        self.graphicsView.scene.contents_changed.connect(self.scene_changed)
2099

    
2100
    def get_work_space(self):
2101
        """get work space path"""
2102
        app_doc_data = AppDocData.instance()
2103

    
2104
        configs = app_doc_data.getAppConfigs('option', 'WorkSpace')
2105
        if configs and len(configs) == 1:
2106
            return configs[0].value
2107
        else:
2108
            return os.getcwd()
2109

    
2110
    def changeViewCheckedState(self, checked, clear=True):
2111
        '''change view checked state'''
2112
        if clear:
2113
            self.initTableWidgetHMB()
2114
            # self.clear_data()
2115

    
2116
    '''
2117
        @brief      create a line
2118
        @author     humkyung
2119
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
2120
    '''
2121

    
2122
    def onPlaceLine(self):
2123
        self.actionLine.setChecked(True)
2124
        if not hasattr(self.actionLine, 'tag'):
2125
            self.actionLine.tag = PlaceStreamlineCommand.PlaceStreamlineCommand(self.graphicsView)
2126
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
2127
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
2128

    
2129
        self.graphicsView.command = self.actionLine.tag
2130

    
2131
    '''
2132
        @brief      add created lines to scene
2133
        @author     humkyung
2134
        @date       2018.07.23
2135
    '''
2136

    
2137
    def onLineCreated(self):
2138
        try:
2139
            count = len(self.actionLine.tag.streamline._vertices)
2140
            if count > 1:
2141
                self.add_hmb_data(self.actionLine.tag.streamline)
2142
                self.actionLine.tag.streamline.transfer.onRemoved.connect(self.on_item_removed)
2143
                self.load_HMB()
2144
        finally:
2145
            self.actionLine.tag.reset()
2146

    
2147
    def on_stream_line_deleted(self, stream_line):
2148
        """ callback after stream line is deleted """
2149
        app_doc_data = AppDocData.instance()
2150
        activeDrawing = app_doc_data.activeDrawing
2151
        if activeDrawing:
2152
            activeDrawing.hmbTable.deleteByUID(stream_line.uid)
2153

    
2154
        self.load_HMB()
2155

    
2156
    def add_hmb_data(self, stream_line):
2157
        """ add a new hmb data associated with given stream line """
2158
        from HMBTable import HMBTable
2159
        import uuid
2160

    
2161
        try:
2162
            drawing = AppDocData.instance().activeDrawing
2163
            if drawing:
2164
                components_uid = stream_line.uid
2165
                stream_no = self.get_next_stream_no(drawing)
2166
                stream_line.stream_no = stream_no
2167
                drawing.hmbTable.add(components_uid, stream_no)
2168
        except Exception as ex:
2169
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2170
                                                           sys.exc_info()[-1].tb_lineno)
2171
            self.addMessage.emit(MessageType.Error, message)
2172

    
2173
    def get_next_stream_no(self, drawing):
2174

    
2175
        if len(list(drawing.hmbTable.streamNos())) == 0:
2176
            return 1
2177
        else:
2178
            streamNos = sorted(list(drawing.hmbTable.streamNos()))
2179
            lastStreamNo = streamNos[-1]
2180
            return lastStreamNo + 1
2181

    
2182
    def clear_HMB(self):
2183
        self.tableWidgetHMB.clearContents()
2184
        self.tableWidgetHMB.setColumnCount(0)
2185

    
2186
    def load_HMB(self):
2187
        drawing = AppDocData.instance().activeDrawing
2188
        if drawing is None: return
2189

    
2190
        hmbs = drawing.hmbTable._hmbs
2191
        if hmbs is not None:
2192
            self.tableWidgetHMB.setColumnCount(2)
2193

    
2194
            col_names = ['Stream No.', 'Unit']
2195
            for hmb in hmbs:
2196
                columnCount = self.tableWidgetHMB.columnCount()
2197
                self.tableWidgetHMB.setColumnCount(columnCount + 1)
2198
                col_names.append(str(hmb.stream_no))
2199

    
2200
                self.tableWidgetHMB.setItem(0, columnCount, set_item_properties(hmb.uid,
2201
                                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2202
                self.tableWidgetHMB.setItem(1, columnCount, set_item_properties(hmb.components_uid,
2203
                                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2204
                self.tableWidgetHMB.setItem(2, columnCount, set_item_properties(hmb.stream_no,
2205
                                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2206
                self.tableWidgetHMB.setItem(3, columnCount, set_item_properties(hmb.phase_type,
2207
                                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2208
                self.tableWidgetHMB.setItem(4, columnCount,
2209
                                            set_item_properties(convert_to_fixed_point(hmb.flowrate_mass),
2210
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2211
                self.tableWidgetHMB.setItem(5, columnCount,
2212
                                            set_item_properties(convert_to_fixed_point(hmb.flowrate_volume),
2213
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2214
                self.tableWidgetHMB.setItem(6, columnCount,
2215
                                            set_item_properties(convert_to_fixed_point(hmb.density),
2216
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2217
                self.tableWidgetHMB.setItem(7, columnCount,
2218
                                            set_item_properties(convert_to_fixed_point(hmb.viscosity),
2219
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2220
                self.tableWidgetHMB.setItem(8, columnCount,
2221
                                            set_item_properties(convert_to_fixed_point(hmb.temperature),
2222
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2223
                self.tableWidgetHMB.setItem(9, columnCount,
2224
                                            set_item_properties(convert_to_fixed_point(hmb.molecular_weight),
2225
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2226
                self.tableWidgetHMB.setItem(10, columnCount,
2227
                                            set_item_properties(convert_to_fixed_point(hmb.specific_heat_ratio),
2228
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2229
                self.tableWidgetHMB.setItem(11, columnCount,
2230
                                            set_item_properties(convert_to_fixed_point(hmb.compress_factor),
2231
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2232
                self.tableWidgetHMB.setItem(12, columnCount,
2233
                                            set_item_properties(convert_to_fixed_point(hmb.nominal_pipe_size),
2234
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2235
                self.tableWidgetHMB.setItem(13, columnCount,
2236
                                            set_item_properties(convert_to_fixed_point(hmb.inside_pipe_size),
2237
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2238
                self.tableWidgetHMB.setItem(14, columnCount,
2239
                                            set_item_properties(convert_to_fixed_point(hmb.schedule_no),
2240
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2241
                self.tableWidgetHMB.setItem(15, columnCount,
2242
                                            set_item_properties(convert_to_fixed_point(hmb.straight_length),
2243
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2244
                self.tableWidgetHMB.setItem(16, columnCount,
2245
                                            set_item_properties(convert_to_fixed_point(hmb.equivalent_length),
2246
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2247

    
2248
                self.tableWidgetHMB.setItem(17, columnCount,
2249
                                            set_item_properties(
2250
                                                convert_to_fixed_point(hmb.equivalent_length_input),
2251
                                                Qt.AlignHCenter | Qt.AlignVCenter))
2252
                self.tableWidgetHMB.setItem(18, columnCount,
2253
                                            set_item_properties(convert_to_fixed_point(hmb.fitting_length),
2254
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2255
                self.tableWidgetHMB.setItem(19, columnCount,
2256
                                            set_item_properties(convert_to_fixed_point(hmb.fitting_K),
2257
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2258
                self.tableWidgetHMB.setItem(20, columnCount,
2259
                                            set_item_properties(convert_to_fixed_point(hmb.equivalent_length_cal),
2260
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2261
                self.tableWidgetHMB.setItem(21, columnCount,
2262
                                            set_item_properties(convert_to_fixed_point(hmb.roughness),
2263
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2264
                self.tableWidgetHMB.setItem(22, columnCount,
2265
                                            set_item_properties(convert_to_fixed_point(hmb.limitation_velocity),
2266
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2267
                self.tableWidgetHMB.setItem(23, columnCount,
2268
                                            set_item_properties(
2269
                                                convert_to_fixed_point(hmb.limitation_pressure_drop),
2270
                                                Qt.AlignHCenter | Qt.AlignVCenter))
2271

    
2272
                self.tableWidgetHMB.setItem(24, columnCount, set_item_properties(None,
2273
                                                                                 Qt.AlignHCenter | Qt.AlignVCenter,
2274
                                                                                 QColor(153, 204, 255)))
2275

    
2276
                self.tableWidgetHMB.setItem(25, columnCount,
2277
                                            set_item_properties(convert_to_fixed_point(hmb.velocity),
2278
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2279
                self.tableWidgetHMB.setItem(26, columnCount,
2280
                                            set_item_properties(convert_to_fixed_point(hmb.reynolds),
2281
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2282
                self.tableWidgetHMB.setItem(27, columnCount,
2283
                                            set_item_properties(convert_to_fixed_point(hmb.friction_factor),
2284
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2285
                self.tableWidgetHMB.setItem(28, columnCount,
2286
                                            set_item_properties(convert_to_fixed_point(hmb.pressure_drop),
2287
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2288
                self.tableWidgetHMB.setItem(29, columnCount,
2289
                                            set_item_properties(convert_to_fixed_point(hmb.pressure_drop_friction),
2290
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2291
                self.tableWidgetHMB.setItem(30, columnCount,
2292
                                            set_item_properties(convert_to_fixed_point(hmb.pressure_drop_static),
2293
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2294
                self.tableWidgetHMB.setItem(31, columnCount,
2295
                                            set_item_properties(
2296
                                                convert_to_fixed_point(hmb.pressure_pipe_end_point),
2297
                                                Qt.AlignHCenter | Qt.AlignVCenter))
2298
                self.tableWidgetHMB.setItem(32, columnCount, set_item_properties(convert_to_fixed_point(hmb.power),
2299
                                                                                 Qt.AlignHCenter | Qt.AlignVCenter))
2300

    
2301
                if hmb.isDeleted: self.tableWidgetHMB.hideColumn(columnCount)
2302

    
2303
            self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
2304

    
2305
            self.tableWidgetHMB.resizeColumnsToContents()
2306
            self.tableWidgetHMB.resizeRowsToContents()
2307

    
2308
    '''
2309
        @brief      refresh scene
2310
        @author     humkyung
2311
        @date       2018.07.23
2312
    '''
2313

    
2314
    def onCommandRejected(self, cmd=None):
2315
        try:
2316
            if type(cmd) is PlaceStreamlineCommand.PlaceStreamlineCommand:
2317
                if self.actionLine.tag.streamline:
2318
                    self.graphicsView.scene.removeItem(self.actionLine.tag.streamline)
2319
                self.graphicsView.scene.update()
2320
                self.actionLine.tag.reset()
2321

    
2322
                self.actionLine.setChecked(False)
2323
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
2324
                self.actionZoom.setChecked(False)
2325
            else:
2326
                if hasattr(self.actionLine, 'tag') and self.actionLine.tag.streamline:
2327
                    self.graphicsView.scene.removeItem(self.actionLine.tag.streamline)
2328
                    self.graphicsView.scene.update()
2329
                    self.actionLine.tag.reset()
2330

    
2331
                self.actionLine.setChecked(False)
2332
                self.actionZoom.setChecked(False)
2333
        finally:
2334
            self.graphicsView.useDefaultCommand()
2335

    
2336
    '''
2337
        @brief      restore to default command when user press Escape key
2338
        @author     humkyung 
2339
        @date       2018.08.09
2340
        
2341
    '''
2342

    
2343
    def keyPressEvent(self, event):
2344
        try:
2345
            if event.key() == Qt.Key_Escape:
2346
                # already catched in command
2347
                pass
2348
                # checked = self.actionGroup.checkedAction()
2349
                # if checked:
2350
                #    checked.setChecked(False)
2351
                #    self.graphicsView.useDefaultCommand()
2352
            elif (event.key() == Qt.Key_C) and (event.modifiers() & Qt.ControlModifier):
2353
                if self.tableWidgetHMB.hasFocus():
2354
                    self.copy_selection(self.tableWidgetHMB)
2355
            elif (event.key() == Qt.Key_V) and (event.modifiers() & Qt.ControlModifier):
2356
                if self.tableWidgetHMB.hasFocus():
2357
                    self.paste_selection(self.tableWidgetHMB)
2358

    
2359
            QMainWindow.keyPressEvent(self, event)
2360
        except Exception as ex:
2361
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2362
                                                           sys.exc_info()[-1].tb_lineno)
2363
            self.addMessage.emit(MessageType.Error, message)
2364

    
2365
    def on_item_removed(self, item):
2366
        """remove item from tree widget and then remove from scene"""
2367

    
2368
        try:
2369
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'connectors') and \
2370
                       [connector for connector in _item.connectors if
2371
                        connector.connectedItem is not None and connector.connectedItem.parentItem() is item]]
2372
            # disconnect deleted item
2373
            for match in matches:
2374
                for connector in match.connectors:
2375
                    if connector.connectedItem and connector.connectedItem.parentItem() is item:
2376
                        connector.connect(None)
2377

    
2378
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'owner')]
2379
            for match in matches:
2380
                if match.owner is item:
2381
                    match.owner = None
2382

    
2383
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'attrs')]
2384
            done = False
2385
            for match in matches:
2386
                for assoc in match.associations():
2387
                    if item is assoc:
2388
                        match.remove_assoc_item(item)
2389
                        for attr in match.attrs.keys():
2390
                            if str(item.uid) == str(attr.AssocItem.uid):
2391
                                attr.AssocItem = None
2392
                                match.attrs[attr] = ''
2393
                                done = True
2394
                                break
2395
                        break
2396
                if done: break
2397

    
2398
            if type(item) is QEngineeringStreamlineItem:
2399
                self.on_stream_line_deleted(item)
2400

    
2401
            if item.scene() is not None:
2402
                item.scene().removeItem(item)
2403
                del item
2404
        except Exception as ex:
2405
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
2406
                                                           sys.exc_info()[-1].tb_lineno)
2407
            self.addMessage.emit(MessageType.Error, message)
2408

    
2409
    '''
2410
        @brief      load components
2411
        @author     yeonjin
2412
        @date       2019.07.30.
2413
    '''
2414

    
2415
    def load_components(self, componentsUID):
2416
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
2417
        from EngineeringConnectorItem import QEngineeringConnectorItem
2418

    
2419
        try:
2420
            app_doc_data = AppDocData.instance()
2421

    
2422
            maxValue = len(componentsUID)
2423
            self.progress.setMaximum(maxValue)
2424

    
2425
            for componentUID in componentsUID:
2426
                componentInfos = app_doc_data.getComponentByComponentUID(componentUID)
2427
                if (len(componentInfos)) > 0:
2428
                    category = componentInfos[0]['Category']  # Category@SymbolType
2429

    
2430
                    if category == 'Stream Line':
2431
                        item = QEngineeringStreamlineItem.fromDatabase(componentInfos)
2432
                        if item is not None:
2433
                            item.transfer.onRemoved.connect(self.on_item_removed)
2434
                            self.graphicsView.scene.addItem(item)
2435
                    else:
2436
                        item = SymbolSvgItem.fromDatabase(componentInfos)
2437
                        if item is not None:
2438
                            item.transfer.onRemoved.connect(self.on_item_removed)
2439
                            app_doc_data.symbols.append(item)
2440
                            self.addSvgItemToScene(item)
2441

    
2442
                    self.progress.setValue(self.progress.value() + 1)
2443

    
2444
                QApplication.processEvents()
2445

    
2446
            self.rebuild_label()
2447

    
2448
            # """ update scene """
2449
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2450
            for item in self.graphicsView.scene.items():
2451
                item.setVisible(True)
2452

    
2453
        except Exception as ex:
2454
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2455
                                                           sys.exc_info()[-1].tb_lineno)
2456
            self.addMessage.emit(MessageType.Error, message)
2457
        finally:
2458
            pass
2459

    
2460
    '''
2461
        @brief      Remove added item on same place and Add GraphicsItem
2462
        @author     Jeongwoo
2463
        @date       2018.05.25
2464
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2465
                    2018.06.18  Jeongwoo    Set Z-index
2466
    '''
2467

    
2468
    def addSvgItemToScene(self, svgItem):
2469
        svgItem.addSvgItemToScene(self.graphicsView.scene)
2470

    
2471
    '''
2472
        @brief      Remove added item on same place and Add GraphicsItem
2473
        @author     Jeongwoo
2474
        @date       2018.05.25
2475
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2476
                    2018.06.05  Jeongwoo    Remove Size condition
2477
                    2018.06.18  Jeongwoo    Set Z-index
2478
    '''
2479

    
2480
    def addTextItemToScene(self, textItem):
2481
        textItem.addTextItemToScene(self.graphicsView.scene)
2482

    
2483
    '''
2484
        @brief      Remove added item on same place and Add GraphicsItem
2485
        @author     Jeongwoo
2486
        @date       2018.05.29
2487
        @history    2018.06.18  Jeongwoo    Set Z-index
2488
    '''
2489

    
2490
    def addLineItemToScene(self, lineItem):
2491
        self.graphicsView.scene.addItem(lineItem)
2492

    
2493
    '''
2494
        @brief      Check Number
2495
        @author     kyouho
2496
        @date       2018.08.20
2497
    '''
2498

    
2499
    def isNumber(self, num):
2500
        p = re.compile('(^[0-9]+$)')
2501
        result = p.match(num)
2502

    
2503
        if result:
2504
            return True
2505
        else:
2506
            return False
2507

    
2508
    '''
2509
        @brief      find overlap Connector
2510
        @author     kyouho
2511
        @date       2018.08.28
2512
    '''
2513

    
2514
    def findOverlapConnector(self, connectorItem):
2515
        from shapely.geometry import Point
2516
        from EngineeringConnectorItem import QEngineeringConnectorItem
2517
        itemList = []
2518

    
2519
        x = connectorItem.center()[0]
2520
        y = connectorItem.center()[1]
2521

    
2522
        connectors = [item for item in self.graphicsView.scene.items() if
2523
                      type(item) is QEngineeringConnectorItem and item != connectorItem]
2524
        for connector in connectors:
2525
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
2526
                itemList.append(connector.parent)
2527

    
2528
        return itemList
2529

    
2530
    def add_data(self, table_widget, name, value, unit, separation=None, is_cell_merge=None, foregroundcolor=None):
2531
        row = table_widget.rowCount()
2532
        table_widget.setRowCount(row + 1)
2533

    
2534
        if separation:
2535
            if is_cell_merge:
2536
                table_widget.setSpan(row, 0, 1, 3)
2537
                table_widget.setItem(row, 0, set_item_properties(name,
2538
                                                                 Qt.AlignLeft | Qt.AlignVCenter,
2539
                                                                 QColor(153, 204, 255), foregroundcolor))
2540
            else:
2541
                table_widget.setItem(row, 0, set_item_properties(name,
2542
                                                                 Qt.AlignLeft | Qt.AlignVCenter,
2543
                                                                 QColor(153, 204, 255), foregroundcolor))
2544
                table_widget.setItem(row, 1, set_item_properties(value,
2545
                                                                 Qt.AlignHCenter | Qt.AlignVCenter,
2546
                                                                 QColor(153, 204, 255), foregroundcolor))
2547
                table_widget.setItem(row, 2, set_item_properties(unit,
2548
                                                                 Qt.AlignHCenter | Qt.AlignVCenter,
2549
                                                                 QColor(153, 204, 255), foregroundcolor))
2550
        else:
2551
            if is_cell_merge:
2552
                table_widget.setSpan(row, 0, 1, 3)
2553
                table_widget.setItem(row, 0, set_item_properties(name,
2554
                                                                 Qt.AlignLeft | Qt.AlignVCenter, None,
2555
                                                                 foregroundcolor))
2556
            else:
2557
                table_widget.setItem(row, 0, set_item_properties(name,
2558
                                                                 Qt.AlignLeft | Qt.AlignVCenter, None,
2559
                                                                 foregroundcolor))
2560
                table_widget.setItem(row, 1, set_item_properties(value,
2561
                                                                 Qt.AlignRight | Qt.AlignVCenter, None,
2562
                                                                 foregroundcolor))
2563
                table_widget.setItem(row, 2, set_item_properties(unit,
2564
                                                                 Qt.AlignLeft | Qt.AlignVCenter, None,
2565
                                                                 foregroundcolor))
2566

    
2567
        table_widget.resizeRowsToContents()
2568
        table_widget.resizeColumnsToContents()
2569

    
2570

    
2571
if __name__ == '__main__':
2572
    pass
클립보드 이미지 추가 (최대 크기: 500 MB)