프로젝트

일반

사용자정보

통계
| 개정판:

hytos / HYTOS / HYTOS / MainWindow.py @ b95146ca

이력 | 보기 | 이력해설 | 다운로드 (131 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

    
105
            self.setMainWindowTitle()
106

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

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

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

    
126
            # connect signals and slots
127
            self.actionGroup.triggered.connect(self.actionGroupTriggered)
128
            self.actionClose.triggered.connect(self.close)
129
            self.actionNew.triggered.connect(self.on_new_drawing)
130
            self.actionOpen.triggered.connect(self.on_open_drawing)
131
            self.actionSave.triggered.connect(self.on_save) #self.actionSaveCliked)
132
            self.actionSave_As.triggered.connect(self.on_save_as)
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.actionPlaceTextBox.triggered.connect(self.on_place_callout_textbox)
144
            self.actionPlaceDimension.triggered.connect(self.on_place_dimension)
145
            self.actionPlaceCloud.triggered.connect(self.on_place_cloud)
146
            self.actionHelp.triggered.connect(self.on_help)
147
            self.actionAbout.triggered.connect(self.on_about)
148
            self.toolButton_ClearLog.clicked.connect(self.clearlogs)
149
            self.graphicsView.scene.selectionChanged.connect(self.onSelectionChanged)
150

    
151
            self.treeWidgetDrawingList.setContextMenuPolicy(Qt.CustomContextMenu)
152
            self.treeWidgetDrawingList.customContextMenuRequested.connect(self.openContextMenu)
153
            self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing)
154

    
155
            self.initTreeWidgetDrawingList()
156
            self.initTableWidgetHMB()
157

    
158
            self.load_drawing_list()
159
            self.load_stylesheet_file()
160
            self.load_language_file()
161

    
162
            self.tabifyDockWidget(self.dockWidgetDrawingExplorer, self.dockWidgetSymbolExplorer)
163
            self.dockWidgetDrawingExplorer.raise_()
164

    
165
            self.read_settings()
166

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

    
175
    def read_settings(self):
176
        """read geometry and state"""
177
        from App import App
178

    
179
        try:
180
            self.settings = QSettings(App.COMPANY, App.NAME)
181
            self.restoreGeometry(self.settings.value("geometry", ""))
182
            self.restoreState(self.settings.value("windowState", ""))
183
        except Exception as ex:
184
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
185
                                                           sys.exc_info()[-1].tb_lineno)
186
            self.addMessage.emit(MessageType.Error, message)
187

    
188
    def load_stylesheet_file(self):
189
        # load stylesheet file list
190
        stylesheet_name = QtWidgets.qApp.stylesheet_name
191
        files = [os.path.splitext(file)[0] for file in os.listdir(os.path.dirname(os.path.realpath(__file__))) if
192
                 os.path.splitext(file)[1] == '.qss']
193
        for file in files:
194
            action = self.menuTheme.addAction(file)
195
            action.setCheckable(True)
196
            action.setChecked(True) if stylesheet_name == file else action.setChecked(False)
197
            action.triggered.connect(partial(self.load_stylesheet, file))
198
        # up to here
199

    
200
    def load_language_file(self):
201
        # load language files
202
        language_name = QtWidgets.qApp.language_name
203
        files = ['en_us']  # englisgh is default language
204
        files.extend([os.path.splitext(file)[0] for file in
205
                      os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate')) if
206
                      os.path.splitext(file)[1] == '.qm'])
207
        for file in files:
208
            action = self.menuLanguage.addAction(file)
209
            action.setCheckable(True)
210
            action.setChecked(True) if language_name.lower() == file.lower() else action.setChecked(False)
211
            action.triggered.connect(partial(self.load_language, file))
212
        # up to here
213

    
214
    def setMainWindowTitle(self, drawingName=None):
215
        try:
216
            _translate = QCoreApplication.translate
217

    
218
            version = QCoreApplication.applicationVersion()
219
            if drawingName is None:
220
                self.setWindowTitle(_translate(App.NAME + "({})".format(version), App.NAME + "({})".format(version)))
221
            else:
222
                self.setWindowTitle(
223
                    _translate(App.NAME + "({})".format(version), App.NAME + "({})".format(version)) + ' - {}'.format(
224
                        drawingName))
225
        except Exception as ex:
226
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
227
                                                           sys.exc_info()[-1].tb_lineno)
228
            self.addMessage.emit(MessageType.Error, message)
229

    
230
    def clearlogs(self):
231
        try:
232
            self.listWidgetLogs.clear()
233
        except Exception as ex:
234
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
235
                                                           sys.exc_info()[-1].tb_lineno)
236
            self.addMessage.emit(MessageType.Error, message)
237
        finally:
238
            logs = self.listWidgetLogs.count()
239
            if logs:
240
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs({})'.format(logs))
241
            else:
242
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs')
243

    
244
    def closeEvent(self, a0: QCloseEvent) -> None:
245
        """save geometry and state and then ask user to save drawing which is modified"""
246

    
247
        self.settings.setValue('geometry', self.saveGeometry())
248
        self.settings.setValue('windowState', self.saveState())
249

    
250
        self.save_drawing_if_necessary()
251
        a0.accept()
252

    
253
    def openContextMenu(self, position):
254
        indexes = self.treeWidgetDrawingList.selectedIndexes()
255
        if len(indexes) > 0:
256
            level = 0
257
            index = indexes[0]
258
            while index.parent().isValid():
259
                index = index.parent()
260
                level += 1
261

    
262
            menu = QMenu()
263

    
264
            itemPosition = self.mapTo(self, position)
265
            item = self.treeWidgetDrawingList.itemAt(itemPosition)
266

    
267
            if level == 0:
268
                newDrawingAction = menu.addAction(self.tr('New...'))
269
                newDrawingAction.triggered.connect(lambda: self.newDrawingActionClickEvent(item))
270
                menu.addAction(newDrawingAction)
271
            elif level == 1:
272
                # saveAsDrawingAction = menu.addAction(self.tr("Save As..."))
273
                # saveAsDrawingAction.triggered.connect(lambda: self.saveAsDrawingActionClickEvent(item))
274
                # menu.addAction(saveAsDrawingAction)
275

    
276
                deleteDrawingAction = menu.addAction(self.tr("Delete"))
277
                deleteDrawingAction.triggered.connect(lambda: self.deleteDrawingActionClickEvent(item))
278
                menu.addAction(deleteDrawingAction)
279

    
280
            menu.exec_(self.treeWidgetDrawingList.viewport().mapToGlobal(position))
281

    
282
    def on_new_drawing(self):
283
        self.new_drawing()
284

    
285
    def newDrawingActionClickEvent(self, item):
286
        self.new_drawing()
287

    
288
    def saveAsDrawingActionClickEvent(self, item):
289
        sourceDb = item.text(2)
290

    
291
        self.saveAs_drawing(sourceDb)
292

    
293
    def deleteDrawingActionClickEvent(self, item):
294
        """ delete selected drawing """
295
        try:
296
            msg = QMessageBox(self)
297
            msg.setIcon(QMessageBox.Question)
298
            msg.setText(self.tr('Do you want to delete drawing on list?\nHowever, Actual drawing is not deleted.'))
299
            msg.setWindowTitle(self.tr("Delete"))
300
            msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
301

    
302
            if QMessageBox.Ok == msg.exec_():
303
                drawingName = item.text(0)
304
                drawingPath = item.text(2)
305

    
306
                app_doc_data = AppDocData.instance()
307
                app_doc_data.deleteDrawingByName(drawingPath)
308

    
309
                if app_doc_data.activeDrawing:
310
                    if drawingName == app_doc_data.activeDrawing.name and drawingPath == app_doc_data.activeDrawing.path:
311
                        app_doc_data.activeDrawing = None
312

    
313
                        if self.graphicsView.hasImage():
314
                            self.graphicsView.clearImage()
315
                            self.graphicsView.scene.clear()
316

    
317
                        self.initTableWidgetHMB()
318

    
319
                self.load_drawing_list()
320
        except Exception as ex:
321
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
322
                                                           sys.exc_info()[-1].tb_lineno)
323
            self.addMessage.emit(MessageType.Error, message)
324

    
325
    def clear_data(self):
326
        self.clear_HMB()
327

    
328
    def eventFilter(self, source, event):
329
        """ display mouse position of graphics view """
330
        if event.type() == QEvent.MouseMove:
331
            pos = self.graphicsView.mapToScene(event.pos())
332
            self._label_mouse.setText('mouse pos : ({},{})'.format(round(pos.x()), round(pos.y())))
333

    
334
        return QWidget.eventFilter(self, source, event)
335

    
336
    def load_stylesheet(self, file):
337
        """load stylesheets"""
338

    
339
        QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
340

    
341
        app_doc_data = AppDocData.instance()
342
        configs = [Config('app', 'stylesheet', file)]
343
        app_doc_data.saveAppConfigs(configs)
344

    
345
        for action in self.menuTheme.actions():
346
            if action.text() == file: continue
347
            action.setChecked(False)
348

    
349
    def load_language(self, file):
350
        """ load language file and then apply selected language """
351
        try:
352

    
353
            qm_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate', '{0}.qm'.format(file))
354
            QtWidgets.qApp.load_language(qm_file)
355

    
356
            app_doc_data = AppDocData.instance()
357
            configs = [Config('app', 'language', file)]
358
            app_doc_data.saveAppConfigs(configs)
359

    
360
            for action in self.menuLanguage.actions():
361
                if action.text().lower() == file.lower(): continue
362
                action.setChecked(False)
363
        finally:
364
            self.retranslateUi(self)
365

    
366
    def initTreeWidgetDrawingList(self):
367

    
368
        self.treeWidgetDrawingList.setHeaderHidden(False)
369
        self.treeWidgetDrawingList.header().setStretchLastSection(True)
370
        self.treeWidgetDrawingList.header().setDefaultAlignment(Qt.AlignCenter)
371
        self.treeWidgetDrawingList.setHeaderLabels([self.tr('Name'), self.tr('DateTime'), self.tr('Path')])
372
        self.treeWidgetDrawingList.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
373
        self.treeWidgetDrawingList.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
374
        self.treeWidgetDrawingList.header().setSectionResizeMode(2, QHeaderView.ResizeToContents)
375
        self.treeWidgetDrawingList.hideColumn(2)
376

    
377
    def clear_output(self):
378
        self.tableWidgetOutput.setColumnCount(0)
379
        self.tableWidgetOutput.setRowCount(0)
380

    
381
        self.tableWidgetDeviation.setColumnCount(0)
382
        self.tableWidgetDeviation.setRowCount(0)
383

    
384
    def clear_loop(self):
385
        self.tableWidgetLoop.setColumnCount(0)
386

    
387
    def initTableWidgetHMB(self):
388
        app_doc_data = AppDocData.instance()
389

    
390
        column_infos = app_doc_data.getHMBDisplayNameAndUnitsExpression()
391
        count = len(column_infos)
392
        self.tableWidgetHMB.setRowCount(count)
393
        if len(column_infos) > 0:
394
            self.tableWidgetHMB.setColumnCount(2)
395
        else:
396
            self.tableWidgetHMB.setColumnCount(0)
397

    
398
        self.tableWidgetHMB.hideRow(0)  # UID
399
        self.tableWidgetHMB.hideRow(1)  # Components_UID
400
        self.tableWidgetHMB.hideRow(2)  # Stream_No
401
        # self.tableWidgetHMB.hideRow(3)  # Phase_Type
402
        # self.tableWidgetHMB.hideRow(4)  # Flowrate_Mass
403
        # self.tableWidgetHMB.hideRow(5)  # Flowrate_Volume
404
        # self.tableWidgetHMB.hideRow(6)  # Density
405
        # self.tableWidgetHMB.hideRow(7)  # Viscosity
406
        # self.tableWidgetHMB.hideRow(8)  # Temperature
407
        # self.tableWidgetHMB.hideRow(9)  # Molecular_Weight
408
        # self.tableWidgetHMB.hideRow(10)  # Specific_Heat_Ratio
409
        # self.tableWidgetHMB.hideRow(11)  # Compress_Factor
410
        # self.tableWidgetHMB.hideRow(12)  # Nominal_Pipe_Size
411
        # self.tableWidgetHMB.hideRow(13)  # Inside_Pipe_Size
412
        # self.tableWidgetHMB.hideRow(14)  # Schedule_No
413
        # self.tableWidgetHMB.hideRow(15)  # Straight_Length
414
        # self.tableWidgetHMB.hideRow(16)  # Equivalent_Length
415
        self.tableWidgetHMB.hideRow(17)  # Equivalent_Length_Input
416
        self.tableWidgetHMB.hideRow(18)  # Fitting_Length
417
        self.tableWidgetHMB.hideRow(19)  # Fitting_K
418
        self.tableWidgetHMB.hideRow(20)  # Equivalent_Length_Cal
419
        # self.tableWidgetHMB.hideRow(21)  # Roughness
420
        # self.tableWidgetHMB.hideRow(22)  # Limitation_Velocity
421
        # self.tableWidgetHMB.hideRow(23)  # Limitation_Pressure_Drop
422
        # self.tableWidgetHMB.hideRow(24)  # Separator
423
        # self.tableWidgetHMB.hideRow(25)  # Velocity
424
        # self.tableWidgetHMB.hideRow(26)  # Reynolds
425
        # self.tableWidgetHMB.hideRow(27)  # Friction_Factor
426
        # self.tableWidgetHMB.hideRow(28)  # Pressure_Drop
427
        # self.tableWidgetHMB.hideRow(29)  # Pressure_Drop_Friction
428
        # self.tableWidgetHMB.hideRow(30)  # Pressure_Drop_Static
429
        # self.tableWidgetHMB.hideRow(31)  # Pressure_Pipe_End_Point
430
        self.tableWidgetHMB.hideRow(32)  # Power
431

    
432
        self.tableWidgetHMB.setEditTriggers(QAbstractItemView.NoEditTriggers)
433
        self.tableWidgetHMB.verticalHeader().setVisible(False)
434

    
435
        col_names = ['Stream No.', 'Unit']
436
        self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
437

    
438
        rowIndex = 0
439
        for columnInfo in column_infos:
440
            name = columnInfo[0]
441
            unit = self.convertToUnits(columnInfo[1])
442

    
443
            self.tableWidgetHMB.setItem(rowIndex, 0, set_item_properties(name, Qt.AlignLeft | Qt.AlignVCenter,
444
                                                                         QColor(51, 153, 102)))
445
            self.tableWidgetHMB.setItem(rowIndex, 1, set_item_properties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
446
                                                                         QColor(204, 255, 204)))
447

    
448
            rowIndex += 1
449

    
450
        self.tableWidgetHMB.resizeColumnsToContents()
451
        self.tableWidgetHMB.resizeRowsToContents()
452

    
453
    def copy_selection(self, table_widget):
454
        """copy selected text to clipboard"""
455

    
456
        import io
457
        import csv
458

    
459
        selection = table_widget.selectedIndexes()
460
        if selection:
461
            rows = sorted(index.row() for index in selection)
462
            columns = sorted(index.column() for index in selection)
463
            rowcount = rows[-1] - rows[0] + 1
464
            colcount = columns[-1] - columns[0] + 1
465
            table = [[''] * colcount for _ in range(rowcount)]
466
            for index in selection:
467
                row = index.row() - rows[0]
468
                column = index.column() - columns[0]
469
                table[row][column] = index.data()
470
            stream = io.StringIO()
471
            csv.writer(stream, delimiter='\t').writerows(table)
472
            QApplication.clipboard().setText(stream.getvalue())
473

    
474
    def paste_selection(self, table_widget):
475
        """paste text of clipboard to table widget"""
476

    
477
        import io
478
        import csv
479

    
480
        selection = table_widget.selectedIndexes()
481
        if selection:
482
            model = table_widget.model()
483

    
484
            buffer = QApplication.clipboard().text()
485
            rows = sorted(index.row() for index in selection)
486
            columns = sorted(index.column() for index in selection)
487
            reader = csv.reader(io.StringIO(buffer), delimiter='\t')
488
            if len(rows) == 1 and len(columns) == 1:
489
                for i, line in enumerate(reader):
490
                    for j, cell in enumerate(line):
491
                        model.setData(model.index(rows[0] + i, columns[0] + j), cell)
492
            else:
493
                arr = [[cell for cell in row] for row in reader]
494
                for index in selection:
495
                    row = index.row() - rows[0]
496
                    column = index.column() - columns[0]
497
                    model.setData(model.index(index.row(), index.column()), arr[row][column])
498

    
499
    '''
500
        @brief      Drawing 속성의 Units 에서 Key값을 이용하여 Value를 찾음
501
        @author     yeonjin
502
        @date       19.08.30
503
    '''
504

    
505
    def findValue(self, key):
506
        value = None
507

    
508
        key = key.replace("{", "").replace("}", "")
509
        for attr in AppDocData.instance().activeDrawing.attrs:
510
            if attr[0] == 'Units':
511
                if key in attr[1]:
512
                    value = attr[1][key]
513
                    break
514

    
515
        return value
516

    
517
    '''
518
        @brief      Convert UnitsExpression To Units Value
519
        @author     yeonjin
520
        @date       19.08.29
521
    '''
522

    
523
    def convertToUnits(self, unitsExpression):
524
        import re
525

    
526
        if unitsExpression is None or AppDocData.instance().activeDrawing is None:
527
            return ''
528

    
529
        found = re.findall('{.*?}', unitsExpression)
530
        for f in found:
531
            key = f
532
            val = self.findValue(key)
533
            if val:
534
                unitsExpression = unitsExpression.replace(key, val)
535

    
536
        return unitsExpression
537

    
538
    '''
539
        @brief      Clear TreeWidget and Set Current PID
540
        @author     Jeongwoo
541
        @date       18.04.11
542
        @history    2018.04.26  Jeongwoo    Add Child [SYMBOLS, NOTES] into root item
543
                    2018.05.09  Jeongwoo    Change method to add default tree items
544
                    humkyung 2018.06.10 add tree item for Line No and Unknown Item
545
    '''
546

    
547
    def load_drawing_list(self):
548
        """load pfd drawing list"""
549

    
550
        try:
551
            app_doc_data = AppDocData.instance()
552
            drawings = app_doc_data.getDrawings()
553

    
554
            self.treeWidgetDrawingList.clear()
555
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList, [self.tr('Drawings'), ''])
556

    
557
            for drawing in drawings:
558
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [drawing.name, drawing.date_time, drawing.path])
559
                item.setIcon(0, QIcon(':images/PFD.png'))
560
                item.setData(0, Qt.UserRole, drawing)
561

    
562
            self.treeWidgetDrawingList.root.setText(0, self.tr('Drawings') + '({})'.format(
563
                self.treeWidgetDrawingList.root.childCount()))
564
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
565
            self.treeWidgetDrawingList.sortByColumn(1, Qt.DescendingOrder)
566
            self.treeWidgetDrawingList.resizeColumnToContents(0)
567

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

    
573
    def save_drawing_if_necessary(self):
574
        """ask user to save drawing or not when drawing is modified"""
575

    
576
        app_doc_data = AppDocData.instance()
577
        if app_doc_data.activeDrawing and app_doc_data.activeDrawing.modified:
578
            if QMessageBox.Yes == QMessageBox.question(self, self.tr("Question"),
579
                                                       self.tr("Do you want to save drawing?"),
580
                                                       QMessageBox.Yes | QMessageBox.No):
581
                self.actionSaveCliked(False)
582

    
583
    def open_selected_drawing(self, item):
584
        """ open selected drawing """
585
        try:
586
            path = item.text(2)
587
            if os.path.exists(path):
588
                self.save_drawing_if_necessary()
589
                self.open_drawing(path)
590

    
591
        except Exception as ex:
592
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
593
                                                           sys.exc_info()[-1].tb_lineno)
594
            self.addMessage.emit(MessageType.Error, message)
595

    
596
    '''
597
        @brief      action save click event
598
        @author     kyouho
599
        @date       2018.08.09
600
        @history    2018.11.02      euisung     add line data list db update
601
                    humkyung save saved time to database
602
                    2018.11.05      euisung     add note data list db update
603
                    2018.11.05      euisung     add db delete process before save
604
                    2018.11.12      euisung     db part move new method to dbUpdate
605
    '''
606

    
607
    def actionSaveCliked(self, show_message=True):
608
        from datetime import datetime
609
        from AppDocData import AppDocData
610
        from EngineeringAbstractItem import QEngineeringAbstractItem
611

    
612
        try:
613
            app_doc_data = AppDocData.instance()
614
            if app_doc_data.activeDrawing is None:
615
                self.showImageSelectionMessageBox()
616
                return
617

    
618
            app_doc_data.activeDrawing.clearItemList()
619

    
620
            items = self.graphicsView.scene.items()
621
            for item in items:
622
                if issubclass(type(item), QEngineeringAbstractItem):
623
                    app_doc_data.activeDrawing.allItems.append(item)
624
                    if issubclass(type(item), QEngineeringTextItem):
625
                        app_doc_data.texts.append(item)
626

    
627
            count = len(app_doc_data.activeDrawing.allItems)
628
            if count > 0:
629
                try:
630
                    self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
631
                                                    self) if not hasattr(self, 'progress') else self.progress
632
                    self.progress.setWindowModality(Qt.WindowModal)
633
                    self.progress.setAutoReset(True)
634
                    self.progress.setAutoClose(True)
635
                    self.progress.setMinimum(0)
636
                    self.progress.resize(600, 100)
637
                    self.progress.setWindowTitle(self.tr("Save"))
638
                    self.progress.show()
639

    
640
                    self.save_drawing_data()
641
                finally:
642
                    self.load_drawing_list()
643
                    self.progress.setValue(self.progress.maximum())
644
                    self.progress.hide()
645
                    if show_message:
646
                        QMessageBox.information(self, self.tr("Information"), self.tr("Save completed successfully."))
647

    
648
        except Exception as ex:
649
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
650
                                                           sys.exc_info()[-1].tb_lineno)
651
            self.addMessage.emit(MessageType.Error, message)
652

    
653
    def on_save(self):
654
        self.actionSaveCliked()
655

    
656
    def on_save_as(self):
657
        """save as drawing file"""
658
        from shutil import copyfile
659
        from datetime import datetime
660
        from Drawing import Drawing
661

    
662
        app_doc_data = AppDocData.instance()
663
        workspace = self.get_work_space()
664

    
665
        file_name = os.path.join(workspace, 'copy of ' + app_doc_data.activeDrawing.name + '.hytos')
666
        options = QFileDialog.Options()
667
        options |= QFileDialog.DontUseNativeDialog
668
        name, _ = QFileDialog.getSaveFileName(self, self.tr('Save As'), file_name, 'HYTOS(*.hytos)', options=options)
669
        if name:
670
            try:
671
                if os.path.splitext(name)[1] != '.hytos': name += '.hytos'
672

    
673
                self.actionSaveCliked()  # save current drawing
674

    
675
                app_doc_data = AppDocData.instance()
676
                # copy current drawing file to new drawing file
677
                copyfile(app_doc_data.activeDrawing.path, name)
678
                app_doc_data.activeDrawing.path = name
679

    
680
                matches = [drawing for drawing in app_doc_data.getDrawings()
681
                           if os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
682
                if not matches:
683
                    drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
684
                    app_doc_data.saveDrawing(drawing)
685
                else:
686
                    drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
687
                    app_doc_data.updateDrawing(drawing)
688

    
689
                self.load_drawing_list()
690
                self.open_border_file()
691
                self.load_data(drawing)
692

    
693
                app_doc_data.activeDrawing.modified = False
694
                self.setMainWindowTitle(f"{app_doc_data.activeDrawing.path}")
695
            except Exception as ex:
696
                message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
697
                                                               sys.exc_info()[-1].tb_lineno)
698
                self.addMessage.emit(MessageType.Error, message)
699

    
700
    def save_drawing_data(self):
701
        """ save drawing data """
702

    
703
        from datetime import datetime
704
        from AppDocData import AppDocData
705
        from SymbolSvgItem import SymbolSvgItem
706
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
707
        from EngineeringCalloutTextItem import QEngineeringCalloutTextItem
708
        from EngineeringCloudItem import QEngineeringCloudItem
709
        from EngineeringDimensionItem import QEngineeringDimensionItem
710

    
711
        try:
712
            app_doc_data = AppDocData.instance()
713
            items = app_doc_data.activeDrawing.allItems
714

    
715
            maxValue = len(items)
716
            self.progress.setMaximum(maxValue)
717

    
718
            app_doc_data.saveToDatabase([item for item in self.graphicsView.scene.items()
719
                                         if hasattr(item, 'toSql') and (
720
                                                 type(item) is SymbolSvgItem or
721
                                                 type(item) is QEngineeringStreamlineItem or
722
                                                 type(item) is QEngineeringCalloutTextItem or
723
                                                 type(item) is QEngineeringDimensionItem or
724
                                                 type(item) is QEngineeringCloudItem)],
725
                                        self.progress.setValue)
726

    
727
            if app_doc_data.activeDrawing:
728
                app_doc_data.activeDrawing.hmbTable.saveData()
729
                app_doc_data.save_sheet_history('Save')
730

    
731
            """ update drawing's modified time """
732
            drawings = app_doc_data.getDrawings()
733
            drawing = [drawing for drawing in drawings if app_doc_data.activeDrawing == drawing]
734
            if drawing:
735
                drawing.date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
736
                app_doc_data.updateDrawing(drawing)
737

    
738
            app_doc_data.activeDrawing.modified = False
739
            self.setMainWindowTitle(f"{app_doc_data.activeDrawing.path}")
740

    
741
        except Exception as ex:
742
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
743
                                                           sys.exc_info()[-1].tb_lineno)
744
            self.addMessage.emit(MessageType.Error, message)
745

    
746
    '''
747
        @brief  add message listwidget
748
        @author humkyung
749
        @date   2018.07.31
750
    '''
751

    
752
    def onAddMessage(self, messageType, message):
753
        from AppDocData import MessageType
754

    
755
        try:
756
            current = QDateTime.currentDateTime()
757

    
758
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
759
            if messageType == MessageType.Error:
760
                item.setForeground(Qt.red)
761
            elif messageType == MessageType.Information:
762
                item.setForeground(Qt.blue)
763

    
764
            self.listWidgetLogs.insertItem(0, item)
765
        except Exception as ex:
766
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
767
                                                       sys.exc_info()[-1].tb_lineno))
768
        finally:
769
            logs = self.listWidgetLogs.count()
770
            if logs:
771
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs({})'.format(logs))
772
            else:
773
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs')
774

    
775
    '''
776
        @brief      Area Zoom
777
        @author     Jeongwoo
778
        @date       2018.06.27
779
        @history    connect command's rejected signal
780
    '''
781

    
782
    def onAreaZoom(self, action):
783
        if self.actionZoom.isChecked():
784
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
785
            cmd.onRejected.connect(self.onCommandRejected)
786
            self.graphicsView.command = cmd
787

    
788
    '''
789
        @brief      Fit Window
790
        @author     Jeongwoo
791
        @date       2018.06.27
792
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
793
    '''
794

    
795
    def fitWindow(self, action):
796
        app_doc_data = AppDocData.instance()
797
        if app_doc_data.activeDrawing:
798
            self.graphicsView.useDefaultCommand()
799
            scene_rect = self.graphicsView.scene.itemsBoundingRect()
800
            if scene_rect.left() > 0:
801
                scene_rect.setLeft(0)
802
            if scene_rect.top() > 0:
803
                scene_rect.setTop(0)
804
            if scene_rect.right() < 1189:
805
                scene_rect.setRight(1189)
806
            if scene_rect.bottom() < 841:
807
                scene_rect.setBottom(841)
808

    
809
            self.graphicsView.setSceneRect(scene_rect)
810
            self.graphicsView.zoomImageInit()
811
            self.graphicsView.scene.invalidate()
812

    
813
    def on_view_connector(self, checked):
814
        """turn on/off connector"""
815
        for item in self.graphicsView.scene.items():
816
            if not hasattr(item, 'connectors'):
817
                continue
818
            for connector in item.connectors:
819
                connector.setVisible(True) if checked else connector.hide()
820

    
821
    def scene_changed(self):
822
        """update modified flag"""
823

    
824
        app_doc_data = AppDocData.instance()
825
        app_doc_data.activeDrawing.modified = True
826
        self.setMainWindowTitle(f"{app_doc_data.activeDrawing.path}*")
827

    
828
    '''
829
        @brief      selection changed
830
        @author     humkyung
831
        @date       2018.06.27
832
        @history    humkung 2018.07.08 call tree widget's findItem
833
    '''
834

    
835
    def onSelectionChanged(self):
836
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
837

    
838
        items = [item for item in self.graphicsView.scene.selectedItems() if
839
                 issubclass(type(item), SymbolSvgItem) or type(item) is QEngineeringStreamlineItem]
840
        if items:
841
            item = items[-1]
842

    
843
            if type(item) is QEngineeringErrorItem:
844
                for index in range(self.tableWidgetHMB.rowCount()):
845

    
846
                    if self.tableWidgetHMB.item(index, 1).tag is item:
847
                        self.tableWidgetHMB.selectRow(index)
848
                        break
849

    
850
    '''
851
        @brief      Initialize scene and itemTreeWidget
852
        @author     Jeongwoo
853

854
        @date       2018.06.14
855
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
856
    '''
857

    
858
    def onInitializeScene(self, action):
859

    
860
        if not self.graphicsView.hasImage():
861
            self.showImageSelectionMessageBox()
862
            return
863

    
864
        try:
865
            msg = QMessageBox(self)
866
            msg.setIcon(QMessageBox.Question)
867
            msg.setText(self.tr('Do you want to remove all items?\nThis work cannot be recovered.'))
868
            msg.setWindowTitle(self.tr("Clear Screen"))
869
            msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
870
            if QMessageBox.Ok == msg.exec_():
871

    
872
                appDocData = AppDocData.instance()
873
                appDocData.activeDrawing.hmbTable.reset()
874
                appDocData.clearItemList(True)
875

    
876
                items = self.graphicsView.scene.items()
877
                for item in items:
878
                    if type(item) is not QGraphicsPixmapItem and item.scene() is not None:
879
                        self.graphicsView.scene.removeItem(item)
880

    
881
                appDocData.initializeDataByDrawingUID(appDocData.activeDrawing.UID)
882

    
883
                self.initTableWidgetHMB()
884

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

    
890
    '''
891
        @brief      Manage Checkable Action statement
892
        @author     Jeongwoo
893
        @date       2018.05.10
894
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
895
    '''
896

    
897
    def actionGroupTriggered(self, action):
898
        if hasattr(self.actionLine, 'tag'):
899
            self.actionLine.tag.onRejected.emit(None)
900

    
901
        if self.graphicsView.command is not None:
902
            self.graphicsView.useDefaultCommand()
903

    
904
        for _action in [x for x in self.actionGroup.actions() if x is not action]:
905
            _action.setChecked(False)
906
            if _action is self.actionLine:
907
                for item in self.graphicsView.scene.items():
908
                    if not hasattr(item, 'connectors'): continue
909
                    for connector in item.connectors: connector.hide()
910

    
911
        action.setChecked(True)
912
        if action is self.actionLine:
913
            for item in self.graphicsView.scene.items():
914
                if not hasattr(item, 'connectors'): continue
915
                for connector in item.connectors: connector.setVisible(True)
916

    
917
    def showSymbolEditor(self):
918
        from SymbolEditorDialog import QSymbolEditorDialog
919

    
920
        dlg = QSymbolEditorDialog()
921
        dlg.exec_()
922

    
923
    def editor_lost_focus(self, item):
924
        cursor = item.textCursor()
925
        cursor.clearSelection()
926
        item.setTextCursor(cursor)
927

    
928
        """
929
        if item.toPlainText():
930
            self.removeItem(item)
931
            item.deleteLater()
932
        """
933

    
934
    def item_selected(self, item):
935
        pass
936
        """
937
        font = item.font()
938
        color = item.defaultTextColor()
939
        self.fontCombo.setCurrentFont(font)
940
        self.fontSizeCombo.setEditText(str(font.pointSize()))
941
        self.boldAction.setChecked(font.weight() == QFont.Bold)
942
        self.italicAction.setChecked(font.italic())
943
        self.underlineAction.setChecked(font.underline())
944
        """
945

    
946
    def on_callout_created(self):
947
        try:
948
            QApplication.restoreOverrideCursor()
949

    
950
            callout = self.actionPlaceTextBox.tag.callout
951
            callout.setTextInteractionFlags(Qt.TextEditorInteraction)
952
            callout.setFocus()
953
            callout.lost_focus.connect(self.editor_lost_focus)
954
            callout.selected_change.connect(self.item_selected)
955
        finally:
956
            self.actionPlaceTextBox.tag.reset()
957

    
958
    def on_place_callout_textbox(self):
959
        """place callout textbox"""
960
        from PlaceCalloutCommand import PlaceCalloutCommand
961

    
962
        if not hasattr(self.actionPlaceTextBox, 'tag'):
963
            self.actionPlaceTextBox.tag = PlaceCalloutCommand(self.graphicsView)
964

    
965
        self.actionPlaceTextBox.tag.onSuccess.connect(self.on_callout_created)
966
        self.actionPlaceTextBox.tag.onRejected.connect(self.onCommandRejected)
967

    
968
        self.graphicsView.command = self.actionPlaceTextBox.tag
969

    
970
    def on_dimension_created(self):
971
        try:
972
            QApplication.restoreOverrideCursor()
973

    
974
            dimension = self.actionPlaceDimension.tag.dimension
975
            dimension.transfer.onRemoved.connect(self.on_item_removed)
976
        finally:
977
            self.actionPlaceDimension.tag.reset()
978

    
979
    def on_place_dimension(self):
980
        """place dimension"""
981
        from PlaceDimensionCommand import PlaceDimensionCommand
982

    
983
        if not hasattr(self.actionPlaceDimension, 'tag'):
984
            self.actionPlaceDimension.tag = PlaceDimensionCommand(self.graphicsView)
985

    
986
        self.actionPlaceDimension.tag.onSuccess.connect(self.on_dimension_created)
987
        self.actionPlaceDimension.tag.onRejected.connect(self.onCommandRejected)
988

    
989
        self.graphicsView.command = self.actionPlaceDimension.tag
990

    
991
    def on_place_cloud(self):
992
        """place a cloud"""
993
        from PlaceCloudCommand import PlaceCloudCommand
994

    
995
        def on_cloud_created():
996
            try:
997
                QApplication.restoreOverrideCursor()
998

    
999
                cloud = self.actionPlaceCloud.tag.cloud
1000
            finally:
1001
                self.actionPlaceCloud.tag.reset()
1002

    
1003
        if not hasattr(self.actionPlaceCloud, 'tag'):
1004
            self.actionPlaceCloud.tag = PlaceCloudCommand(self.graphicsView)
1005

    
1006
        self.actionPlaceCloud.tag.onSuccess.connect(on_cloud_created)
1007
        self.actionPlaceCloud.tag.onRejected.connect(self.onCommandRejected)
1008

    
1009
        self.graphicsView.command = self.actionPlaceCloud.tag
1010

    
1011
    def on_help(self):
1012
        """open user manual"""
1013
        import os
1014

    
1015
        try:
1016
            help_file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'HYTOS User Manual.pdf')
1017
            os.startfile(f"\"{help_file_path}\"")
1018
            # os.system(f"\"{help_file_path}\"")
1019
        except Exception as ex:
1020
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1021
                                                           sys.exc_info()[-1].tb_lineno)
1022
            self.addMessage.emit(MessageType.Error, message)
1023

    
1024
    def on_about(self):
1025
        """show about dialog"""
1026
        from AboutDialog import QAboutDialog
1027

    
1028
        dlg = QAboutDialog()
1029
        dlg.exec_()
1030

    
1031
    def update_label_contents(self):
1032
        from EngineeringCalloutTextItem import QEngineeringCalloutTextItem
1033

    
1034
        items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) or
1035
                 type(item) is QEngineeringStreamlineItem or type(item) is QEngineeringCalloutTextItem]
1036
        for item in items:
1037
            item.update_label_contents()
1038

    
1039
    def onOptions(self):
1040
        from OptionsDialog import QOptionsDialog
1041
        try:
1042
            app_doc_data = AppDocData.instance()
1043
            configs = app_doc_data.getAppConfigs('option', 'TagFontSize')
1044
            old_tag_font_size = configs[0].value if configs and len(configs) == 1 else 6
1045

    
1046
            configs = app_doc_data.getAppConfigs('option', 'TagFontColor')
1047
            old_tag_font_color = configs[0].value if configs and len(configs) == 1 else '#000000'
1048

    
1049
            configs = app_doc_data.getAppConfigs('option', 'CalloutFontSize')
1050
            old_callout_font_size = configs[0].value if configs and len(configs) == 1 else 6
1051

    
1052
            configs = app_doc_data.getAppConfigs('option', 'CalloutTextColor')
1053
            old_callout_text_color = configs[0].value if configs and len(configs) == 1 else '#000000'
1054

    
1055
            dlg = QOptionsDialog(self)
1056
            dlg.setWindowFlags(dlg.windowFlags() & ~Qt.WindowContextHelpButtonHint)
1057
            if QDialog.Accepted == dlg.exec_():
1058
                if app_doc_data.activeDrawing:
1059
                    if str(old_tag_font_size) != str(dlg.tag_font_size) or \
1060
                            old_tag_font_color != dlg.tag_text_color or \
1061
                            str(old_callout_font_size) != str(dlg.callout_font_size) or \
1062
                            old_callout_text_color != dlg.callout_text_color:
1063
                        self.update_label_contents()
1064

    
1065
        except Exception as ex:
1066
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1067
                                                           sys.exc_info()[-1].tb_lineno)
1068
            self.addMessage.emit(MessageType.Error, message)
1069

    
1070
    def calculation(self):
1071
        """execute hydro calculation"""
1072
        from AppDocData import AppDocData
1073
        from Calculation import Calculation
1074
        from HydroCalculationCommand import HydroCalculationCommand
1075
        from ValidationDialog import QValidationDialog
1076

    
1077
        try:
1078
            app_doc_data = AppDocData.instance()
1079
            if app_doc_data.activeDrawing is None:
1080
                self.showImageSelectionMessageBox()
1081
                return
1082

    
1083
            hmbs = app_doc_data.activeDrawing.hmbTable._hmbs
1084
            if hmbs is not None:
1085
                try:
1086
                    errors = []
1087
                    items = [item for item in self.graphicsView.scene.items() if type(item) is SymbolSvgItem or
1088
                             type(item) is QEngineeringStreamlineItem]
1089
                    for item in items:
1090
                        error = item.validate()
1091
                        if error: errors.extend(error)
1092

    
1093
                    if errors:
1094
                        dlg = QValidationDialog(self, errors)
1095
                        dlg.show()
1096
                    else:
1097
                        self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, self) \
1098
                            if not hasattr(self, 'progress') else self.progress
1099
                        self.progress.setWindowModality(Qt.WindowModal)
1100
                        self.progress.setAutoReset(True)
1101
                        self.progress.setAutoClose(True)
1102
                        self.progress.setMinimum(0)
1103
                        self.progress.resize(600, 100)
1104
                        self.progress.setWindowTitle(self.tr("Calculate data..."))
1105
                        self.progress.show()
1106

    
1107
                        maxValue = len(hmbs)
1108
                        self.progress.setMaximum(maxValue)
1109

    
1110
                        for hmb in hmbs:
1111
                            self.progress.setValue(self.progress.value() + 1)
1112

    
1113
                            if hmb.phase_type:
1114
                                Calculation(hmb)
1115

    
1116
                            QApplication.processEvents()
1117

    
1118
                        """ generate loop """
1119
                        cmd = HydroCalculationCommand(self.graphicsView)
1120
                        cmd.execute(None)
1121
                        cmd.execute_second(None)
1122

    
1123
                        app_doc_data.activeDrawing.loops = cmd.loops
1124

    
1125
                        self.display_loops()
1126
                        self.display_output()
1127

    
1128
                        self.load_HMB()
1129

    
1130
                        app_doc_data.save_sheet_history('Calculation')
1131
                finally:
1132
                    self.progress.setValue(self.progress.maximum())
1133
                    self.progress.hide()
1134
        except Exception as ex:
1135
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1136
                                                           sys.exc_info()[-1].tb_lineno)
1137
            self.addMessage.emit(MessageType.Error, message)
1138

    
1139
    def generate_report(self):
1140
        """generate calculation report"""
1141
        from tempfile import NamedTemporaryFile
1142
        import openpyxl
1143
        from DrawImage import DrawImage
1144
        from openpyxl.styles import Font
1145
        from datetime import datetime
1146
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
1147

    
1148
        try:
1149
            app_doc_data = AppDocData.instance()
1150
            if app_doc_data.activeDrawing is None:
1151
                self.showImageSelectionMessageBox()
1152
                return
1153

    
1154
            image_path = None
1155
            with NamedTemporaryFile() as f:
1156
                image_path = f.name + '.png'
1157

    
1158
            if image_path:
1159
                self.on_view_connector(False)  # hide connector
1160
                self.graphicsView.save_as_image(image_path)
1161

    
1162
                workspace = self.get_work_space()
1163
                file_name = os.path.join(workspace, app_doc_data.activeDrawing.name + '.xlsx')
1164
                options = QFileDialog.Options()
1165
                options |= QFileDialog.DontUseNativeDialog
1166
                file_name, _ = QFileDialog.getSaveFileName(self, self.tr('Report'), file_name, 'Excel(*.xlsx)',
1167
                                                           options=options)
1168

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

    
1171
                # get image file path
1172
                company_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME, 'Company.png')
1173
                horizontal_flow_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME, 'Horizontal_Flow.png')
1174
                vertical_upward_flow_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME,
1175
                                                               'Vertical_Upward_Flow.png')
1176
                vertical_downward_flow_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME,
1177
                                                                 'Vertical_Downward_Flow.png')
1178
                # up to here
1179
                if file_name and os.path.exists(template):
1180
                    units = [attr[1] for attr in app_doc_data.activeDrawing.attrs if attr[0] == 'Units'][0]
1181

    
1182
                    wb = openpyxl.load_workbook(template)
1183

    
1184
                    page_no = 1
1185
                    pages = math.ceil(len(list(app_doc_data.activeDrawing.hmbTable.streamNos())) / 20)
1186
                    for page in range(pages):
1187
                        ws = wb.copy_worksheet(wb.get_sheet_by_name('Page'))
1188
                        ws.title = 'Page ({})'.format(page_no)
1189

    
1190
                        cal_image = openpyxl.drawing.image.Image(image_path)
1191
                        x_scale, y_scale = 1, 1
1192
                        cal_image.width *= x_scale
1193
                        cal_image.height *= y_scale
1194
                        ws.add_image(cal_image, 'C4')
1195

    
1196
                        company_image = openpyxl.drawing.image.Image(company_image_path)
1197
                        company_image.width *= 0.8
1198
                        company_image.height *= 0.7
1199
                        ws.add_image(company_image, 'W53')
1200

    
1201
                        """write sheet information"""
1202
                        configs = app_doc_data.getConfigs('Sheet')
1203
                        for config in configs:
1204
                            if config.key == 'JobNo' and config.value:
1205
                                ws['Z58'].value = config.value
1206
                            elif config.key == 'JobName' and config.value:
1207
                                ws['W59'].value = config.value
1208
                            elif config.key == 'Description' and config.value:
1209
                                ws['W73'].value = config.value
1210
                            elif config.key == 'RevStatus' and config.value:
1211
                                ws['Y68'].value = config.value
1212
                            elif config.key == 'CheckedBy' and config.value:
1213
                                ws['Z78'].value = config.value
1214
                            elif config.key == 'ApprovedBy' and config.value:
1215
                                ws['Z79'].value = config.value
1216

    
1217
                        configs = app_doc_data.getAppConfigs('app', 'SingleID')
1218
                        if configs and configs[0].value:
1219
                            ws['Z77'].value = configs[0].value
1220
                        ws['Z68'].value = str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
1221
                        """up to here"""
1222

    
1223
                        # Output [Pump, Compressor, Control Valve]
1224
                        ws['X1'].value = 'Loop_Deviation'
1225
                        ws['X1'].font = Font(bold=True, underline='single', size=11)
1226

    
1227
                        loops = app_doc_data.activeDrawing.loops
1228
                        strmsg = None
1229
                        row_no = 2
1230
                        for loop in loops:
1231
                            deviation = loop.deviation
1232
                            if round(deviation, 9) == 0:
1233
                                continue
1234

    
1235
                            for i in range(1, len(loop.items) - 1, 3):
1236
                                if i == 1:
1237
                                    loop_no = loop.name.replace('Loop', '')
1238
                                    if len(loop_no) > 1:
1239
                                        strmsg = '({}) {}'.format(loop_no, loop.items[i].stream_no)
1240
                                    else:
1241
                                        strmsg = '(0{}) {}'.format(loop_no, loop.items[i].stream_no)
1242
                                else:
1243
                                    if len(str(loop.items[i - 1])) > 13 and str(loop.items[i - 1])[
1244
                                                                            :13] == 'Line_Splitter':
1245
                                        pre_stream_num = loop.items[i - 3].stream_no
1246
                                        cur_stream_num = loop.items[i].stream_no
1247

    
1248
                                        if strmsg.__contains__('-'):
1249
                                            last_stream_num = str(strmsg).rsplit('-', 1)[1]
1250
                                        else:
1251
                                            last_stream_num = str(strmsg).rsplit(' ', 1)[1]
1252

    
1253
                                        if pre_stream_num != int(last_stream_num):
1254
                                            strmsg = '{}-{}-{}'.format(strmsg, pre_stream_num, cur_stream_num)
1255

    
1256
                            last_stream_num = loop.items[len(loop.items) - 2].stream_no
1257
                            strmsg = '{}-{}'.format(strmsg, last_stream_num)
1258

    
1259
                            value = '{} = {} {}'.format(strmsg, round(deviation, 3), units['Pressure'])
1260
                            if round(deviation, 3) < 0:
1261
                                ws.cell(row_no, 24, value).font = Font(underline='single',
1262
                                                                       size=10,
1263
                                                                       color='FF0000')
1264

    
1265
                            elif round(deviation, 3) > 0:
1266
                                ws.cell(row_no, 24, value).font = Font(size=10)
1267
                            else:
1268
                                ws.cell(row_no, 24, value).font = Font(underline='single',
1269
                                                                       size=10)
1270
                            row_no += 1
1271

    
1272
                        start_row_no = row_no + 1
1273
                        start_col_no = 24
1274
                        # Pump
1275
                        pumps = []
1276
                        row_no = start_row_no
1277
                        col_no = start_col_no
1278
                        for loop in loops:
1279
                            for item in loop.items:
1280
                                parent = item.parent
1281
                                if parent:
1282
                                    name = str(item).replace(
1283
                                        '_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1284
                                    if name in pumps:
1285
                                        continue
1286
                                    if name[:3] == 'R_P' or name[:3] == 'L_P' or name[:3] == 'V_P':
1287
                                        pumps.append(name)
1288

    
1289
                                        attr = item.parent.attribute
1290
                                        ws.cell(row_no, col_no, attr['Tag_No']).font = Font(bold=True,
1291
                                                                                            underline='single',
1292
                                                                                            size=11)
1293

    
1294
                                        row_no += 1
1295
                                        ws.cell(row_no, col_no, 'Suct.P :')
1296
                                        col_no += 2
1297
                                        ws.cell(row_no, col_no, round(attr['Suct.P'], 3))
1298
                                        col_no += 1
1299
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1300

    
1301
                                        row_no += 1
1302
                                        col_no = 24 if col_no == 27 else 28
1303
                                        ws.cell(row_no, col_no, 'Disc.P :')
1304
                                        col_no += 2
1305
                                        ws.cell(row_no, col_no, round(attr['Disc.P'], 3))
1306
                                        col_no += 1
1307
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1308

    
1309
                                        row_no += 1
1310
                                        col_no = 24 if col_no == 27 else 28
1311
                                        ws.cell(row_no, col_no, 'Diff.P :')
1312
                                        col_no += 2
1313
                                        ws.cell(row_no, col_no, round(attr['Diff.P'], 3))
1314
                                        col_no += 1
1315
                                        ws.cell(row_no, col_no, units['Pressure'])
1316

    
1317
                                        row_no += 1
1318
                                        col_no = 24 if col_no == 27 else 28
1319
                                        ws.cell(row_no, col_no, 'Head :')
1320
                                        col_no += 2
1321
                                        ws.cell(row_no, col_no, round(attr['Head'], 3))
1322
                                        col_no += 1
1323
                                        ws.cell(row_no, col_no, units['Length'])
1324

    
1325
                                        row_no += 1
1326
                                        col_no = 24 if col_no == 27 else 28
1327
                                        ws.cell(row_no, col_no, 'NPSHa :')
1328
                                        col_no += 2
1329
                                        ws.cell(row_no, col_no, round(attr['NPSHa'], 3))
1330
                                        col_no += 1
1331
                                        ws.cell(row_no, col_no, units['Length'])
1332

    
1333
                                        row_no += 1
1334
                                        col_no = 24 if col_no == 27 else 28
1335
                                        ws.cell(row_no, col_no, 'Vap. P :')
1336
                                        col_no += 2
1337
                                        ws.cell(row_no, col_no, attr['Vap. P'])
1338
                                        col_no += 1
1339
                                        ws.cell(row_no, col_no, '{}.a'.format(units['Pressure']))
1340

    
1341
                                        row_no += 1
1342
                                        col_no = 24 if col_no == 27 else 28
1343
                                        ws.cell(row_no, col_no, 'HHP :')
1344
                                        col_no += 2
1345
                                        ws.cell(row_no, col_no, round(attr['HHP'], 3))
1346
                                        col_no += 1
1347
                                        ws.cell(row_no, col_no, units['Power'])
1348

    
1349
                                        col_no = 28 if col_no == 27 else 24
1350
                                        row_no = row_no - 7 if col_no == 28 else row_no + 2
1351

    
1352
                        start_row_no += math.ceil(len(pumps)) * 9
1353

    
1354
                        # Compressor
1355
                        compressors = []
1356
                        row_no = start_row_no
1357
                        col_no = start_col_no
1358
                        for loop in loops:
1359
                            for item in loop.items:
1360
                                parent = item.parent
1361
                                if parent:
1362
                                    name = str(item).replace(
1363
                                        '_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1364
                                    if name in compressors:
1365
                                        continue
1366
                                    if name[:3] == 'R_K' or name[:3] == 'L_K':
1367
                                        compressors.append(name)
1368

    
1369
                                        attr = item.parent.attribute
1370
                                        ws.cell(row_no, col_no, attr['Tag_No']).font = Font(bold=True,
1371
                                                                                            underline='single',
1372
                                                                                            size=11)
1373

    
1374
                                        row_no += 1
1375
                                        ws.cell(row_no, col_no, 'Suct.P :')
1376
                                        col_no += 2
1377
                                        ws.cell(row_no, col_no, round(attr['Suct.P'], 3))
1378
                                        col_no += 1
1379
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1380

    
1381
                                        row_no += 1
1382
                                        col_no = 24 if col_no == 27 else 28
1383
                                        ws.cell(row_no, col_no, 'Disc.P :')
1384
                                        col_no += 2
1385
                                        ws.cell(row_no, col_no, round(attr['Disc.P'], 3))
1386
                                        col_no += 1
1387
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1388

    
1389
                                        row_no += 1
1390
                                        col_no = 24 if col_no == 27 else 28
1391
                                        ws.cell(row_no, col_no, 'Diff.P :')
1392
                                        col_no += 2
1393
                                        ws.cell(row_no, col_no, round(attr['Diff.P'], 3))
1394
                                        col_no += 1
1395
                                        ws.cell(row_no, col_no, units['Pressure'])
1396

    
1397
                                        row_no += 1
1398
                                        col_no = 24 if col_no == 27 else 28
1399
                                        ws.cell(row_no, col_no, 'HHP :')
1400
                                        col_no += 2
1401
                                        ws.cell(row_no, col_no, round(attr['HHP'], 3))
1402
                                        col_no += 1
1403
                                        ws.cell(row_no, col_no, units['Power'])
1404

    
1405
                                        col_no = 28 if col_no == 27 else 24
1406
                                        row_no = row_no - 4 if col_no == 28 else row_no + 2
1407

    
1408
                        start_row_no += math.ceil(len(compressors)) * 9
1409

    
1410
                        # Control Valve
1411
                        control_valves = []
1412
                        row_no = start_row_no
1413
                        col_no = start_col_no
1414
                        for loop in loops:
1415
                            for item in loop.items:
1416
                                parent = item.parent
1417
                                if parent:
1418
                                    name = str(item).replace(
1419
                                        '_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1420
                                    if name in control_valves:
1421
                                        continue
1422
                                    if name[:3] == 'CV_':
1423
                                        control_valves.append(name)
1424

    
1425
                                        attr = item.parent.attribute
1426
                                        ws.cell(row_no, col_no, attr['Tag_No']).font = Font(bold=True,
1427
                                                                                            underline='single',
1428
                                                                                            size=11)
1429

    
1430
                                        row_no += 1
1431
                                        ws.cell(row_no, col_no, 'Inlet P :')
1432
                                        col_no += 2
1433
                                        ws.cell(row_no, col_no, round(attr['Suct.P'], 3))
1434
                                        col_no += 1
1435
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1436

    
1437
                                        row_no += 1
1438
                                        col_no = 24 if col_no == 27 else 28
1439
                                        ws.cell(row_no, col_no, 'Outlet P :')
1440
                                        col_no += 2
1441
                                        ws.cell(row_no, col_no, round(attr['Disc.P'], 3))
1442
                                        col_no += 1
1443
                                        ws.cell(row_no, col_no, '{}.g'.format(units['Pressure']))
1444

    
1445
                                        row_no += 1
1446
                                        col_no = 24 if col_no == 27 else 28
1447
                                        ws.cell(row_no, col_no, 'Diff.P :')
1448
                                        col_no += 2
1449
                                        ws.cell(row_no, col_no, round(attr['Diff.P'], 3))
1450
                                        col_no += 1
1451
                                        ws.cell(row_no, col_no, units['Pressure'])
1452

    
1453
                                        row_no += 1
1454
                                        col_no = 24 if col_no == 27 else 28
1455
                                        ws.cell(row_no, col_no, 'dP Ratio :')
1456
                                        col_no += 2
1457
                                        ws.cell(row_no, col_no, round(attr['dP Ratio'] * 100, 2))
1458
                                        col_no += 1
1459
                                        ws.cell(row_no, col_no, '%')
1460

    
1461
                                        col_no = 28 if col_no == 27 else 24
1462
                                        row_no = row_no - 4 if col_no == 28 else row_no + 2
1463

    
1464
                        # write hmb unit
1465
                        ws['B54'].value = '-'
1466
                        ws['B55'].value = units['Pipe_Diameter']
1467
                        ws['B56'].value = units['Flowrate_Mass']
1468
                        ws['B57'].value = units['Flowrate_Volume']
1469
                        ws['B58'].value = units['Density']
1470
                        ws['B59'].value = units['Viscosity']
1471
                        ws['B60'].value = units['Temperature']  # Hidden
1472
                        ws['B61'].value = ''  # Hidden
1473
                        ws['B62'].value = ''  # Hidden
1474
                        ws['B63'].value = ''  # Hidden
1475
                        ws['B64'].value = units['Pipe_Diameter']  # Hidden
1476
                        ws['B65'].value = units['Pipe_Diameter']  # Hidden
1477
                        ws['B66'].value = ''  # Hidden
1478
                        ws['B67'].value = units['Length']
1479
                        ws['B68'].value = units['Length']
1480
                        ws['B69'].value = units['Roughness']
1481
                        ws['B70'].value = units['Velocity']  # Hidden
1482
                        ws['B71'].value = '{}/100{})'.format(units['Pressure'], units['Length'])  # Hidden
1483
                        ws['B73'].value = units['Velocity']
1484
                        ws['B74'].value = ''  # Hidden
1485
                        ws['B75'].value = ''  # Hidden
1486
                        ws['B76'].value = '{}/100{}'.format(units['Pressure'], units['Length'])
1487
                        ws['B77'].value = units['Pressure']
1488
                        ws['B78'].value = units['Pressure']
1489
                        ws['B79'].value = '{}(g)'.format(units['Pressure'])
1490

    
1491
                        page_no += 1
1492

    
1493
                    current_ws = wb.get_sheet_by_name('Page (1)')
1494
                    # write hmb data
1495
                    drawing = app_doc_data.activeDrawing
1496
                    hmbs = drawing.hmbTable._hmbs
1497
                    if hmbs is not None:
1498
                        stream_count = 1
1499
                        col_no = 3
1500
                        for hmb in hmbs:
1501
                            if hmb.isDeleted == True:
1502
                                continue
1503

    
1504
                            ws = self.get_work_sheet(wb, stream_count)
1505
                            if ws != current_ws:
1506
                                current_ws = ws
1507
                                col_no = 3
1508

    
1509
                            row_no = 53
1510
                            ws.cell(row_no, col_no, hmb.stream_no)
1511
                            row_no += 1
1512
                            ws.cell(row_no, col_no, hmb.phase_type)
1513
                            row_no += 1
1514
                            ws.cell(row_no, col_no, hmb.inside_pipe_size)
1515
                            row_no += 1
1516
                            ws.cell(row_no, col_no, hmb.flowrate_mass)
1517
                            row_no += 1
1518
                            ws.cell(row_no, col_no, hmb.flowrate_volume)
1519
                            row_no += 1
1520
                            ws.cell(row_no, col_no, hmb.density)
1521
                            row_no += 1
1522
                            ws.cell(row_no, col_no, hmb.viscosity)
1523
                            row_no += 1
1524
                            ws.cell(row_no, col_no, hmb.temperature)
1525
                            row_no += 1
1526
                            ws.cell(row_no, col_no, hmb.molecular_weight)
1527
                            row_no += 1
1528
                            ws.cell(row_no, col_no, hmb.specific_heat_ratio)
1529
                            row_no += 1
1530
                            ws.cell(row_no, col_no, hmb.compress_factor)
1531
                            row_no += 1
1532
                            ws.cell(row_no, col_no, hmb.nominal_pipe_size)
1533
                            row_no += 1
1534
                            ws.cell(row_no, col_no, hmb.inside_pipe_size)
1535
                            row_no += 1
1536
                            ws.cell(row_no, col_no, hmb.schedule_no)
1537
                            row_no += 1
1538
                            ws.cell(row_no, col_no, hmb.straight_length)
1539
                            row_no += 1
1540
                            ws.cell(row_no, col_no, hmb.equivalent_length)
1541
                            row_no += 1
1542
                            ws.cell(row_no, col_no, hmb.roughness)
1543
                            row_no += 1
1544
                            ws.cell(row_no, col_no, hmb.limitation_velocity)
1545
                            row_no += 1
1546
                            ws.cell(row_no, col_no, hmb.limitation_pressure_drop)
1547
                            row_no += 2
1548
                            ws.cell(row_no, col_no, hmb.velocity)
1549
                            row_no += 1
1550
                            ws.cell(row_no, col_no, hmb.reynolds)
1551
                            row_no += 1
1552
                            ws.cell(row_no, col_no, hmb.friction_factor)
1553
                            row_no += 1
1554
                            ws.cell(row_no, col_no, hmb.pressure_drop)
1555
                            row_no += 1
1556
                            ws.cell(row_no, col_no, hmb.pressure_drop_friction)
1557
                            row_no += 1
1558
                            ws.cell(row_no, col_no, hmb.pressure_drop_static)
1559
                            row_no += 1
1560
                            ws.cell(row_no, col_no, hmb.pressure_pipe_end_point)
1561

    
1562
                            col_no += 1
1563
                            stream_count += 1
1564

    
1565
                    # two_phase
1566
                    if hmbs is not None:
1567
                        for hmb in hmbs:
1568
                            if hmb.phase_type == 'Mixed':
1569
                                lines = [item for item in self.graphicsView.scene.items() if type(
1570
                                    item) is QEngineeringStreamlineItem and str(item.uid) == str(hmb.components_uid)]
1571
                                if lines:
1572
                                    ws = wb.copy_worksheet(wb.get_sheet_by_name('Two_phase'))
1573
                                    ws.title = 'Two Phase {}'.format(str(lines[0]))
1574

    
1575
                                    # Information
1576
                                    ws['B5'].value = 'File : Two_Phase'
1577
                                    ws['B6'].value = 'Line : {}'.format(lines[0].stream_no)
1578
                                    ws['G6'].value = 'Made by : {}'.format(configs[0].value)
1579

    
1580
                                    # Process Data
1581
                                    ws['C10'].value = units['Flowrate_Mass']
1582
                                    ws['D10'].value = units['Density']
1583
                                    ws['E10'].value = units['Viscosity']
1584
                                    ws['F10'].value = '{}(g)'.format(units['Pressure'])
1585
                                    ws['G10'].value = units['Temperature']
1586

    
1587
                                    ws['C11'].value = lines[0].data.liquid_flowrate_mass
1588
                                    ws['D11'].value = lines[0].data.liquid_density
1589
                                    ws['E11'].value = lines[0].data.liquid_viscosity
1590

    
1591
                                    ws['C12'].value = lines[0].data.vapor_flowrate_mass
1592
                                    ws['D12'].value = lines[0].data.vapor_density
1593
                                    ws['E12'].value = lines[0].data.vapor_viscosity
1594
                                    ws['F12'].value = lines[0].data.vapor_pressure
1595
                                    ws['G12'].value = lines[0].data.vapor_temperature
1596
                                    ws['H12'].value = lines[0].data.vapor_molecular_weight
1597
                                    ws['I12'].value = lines[0].data.vapor_compress_factor
1598

    
1599
                                    # Geometry Data
1600
                                    ws['D16'].value = units['Pipe_Diameter']
1601
                                    ws['E16'].value = units['Roughness']
1602
                                    ws['F16'].value = units['Length']
1603

    
1604
                                    row_no = 17
1605
                                    for geometry in lines[0].mixed_geometry:
1606
                                        col_no = 3
1607
                                        ws.cell(row_no, col_no, str(geometry[0]))  # Element
1608
                                        col_no += 1
1609
                                        ws.cell(row_no, col_no,
1610
                                                float(geometry[3]) if is_float(geometry[3]) else None)  # ID
1611
                                        col_no += 1
1612
                                        ws.cell(row_no, col_no,
1613
                                                float(geometry[4]) if is_float(geometry[4]) else None)  # Roughness
1614
                                        col_no += 1
1615
                                        ws.cell(row_no, col_no,
1616
                                                float(geometry[5]) if is_float(geometry[5]) else None)  # Length
1617
                                        col_no += 1
1618
                                        ws.cell(row_no, col_no,
1619
                                                float(geometry[6]) if is_float(geometry[6]) else None)  # Angle
1620
                                        col_no += 1
1621
                                        ws.cell(row_no, col_no,
1622
                                                float(geometry[7]) if is_float(geometry[7]) else None)  # R/D
1623
                                        col_no += 1
1624
                                        ws.cell(row_no, col_no,
1625
                                                float(geometry[9]) if is_float(geometry[9]) else None)  # K
1626

    
1627
                                        row_no += 1
1628

    
1629

    
1630
                                    # horizontal_flow_image = openpyxl.drawing.image.Image(horizontal_flow_image_path)
1631
                                    # horizontal_flow_image.width *= 0.6
1632
                                    # horizontal_flow_image.height *= 0.6
1633
                                    # ws.add_image(horizontal_flow_image, 'L3')
1634

    
1635
                                    # vertical_upward_flow_image = openpyxl.drawing.image.Image(
1636
                                    #     vertical_upward_flow_image_path)
1637
                                    # vertical_upward_flow_image.width *= 0.6
1638
                                    # vertical_upward_flow_image.height *= 0.6
1639
                                    # ws.add_image(vertical_upward_flow_image, 'R3')
1640

    
1641
                                    # vertical_downward_flow_image = openpyxl.drawing.image.Image(
1642
                                    #     vertical_downward_flow_image_path)
1643
                                    # vertical_downward_flow_image.width *= 0.6
1644
                                    # vertical_downward_flow_image.height *= 0.6
1645
                                    # ws.add_image(vertical_downward_flow_image, 'Z3')
1646

    
1647
                                    horizontal = DrawImage(horizontal_flow_image_path)
1648
                                    vertical_upward = DrawImage(vertical_upward_flow_image_path)
1649
                                    vertical_downward = DrawImage(vertical_downward_flow_image_path)
1650
                                    # Calculation Result
1651
                                    row_no = 37
1652
                                    for row in lines[0].mixed_pressure_variation:
1653
                                        col_no = 12
1654
                                        ws.cell(row_no, col_no, str(row[0]))    # Element
1655
                                        col_no += 1
1656
                                        ws.cell(row_no, col_no, row[1])         # ID
1657
                                        col_no += 1
1658
                                        ws.cell(row_no, col_no, row[2])         # Length
1659
                                        col_no += 1
1660
                                        ws.cell(row_no, col_no, row[3])         # Angle
1661
                                        col_no += 1
1662
                                        ws.cell(row_no, col_no, row[4])         # K
1663
                                        col_no += 1
1664
                                        ws.cell(row_no, col_no, row[5])         # Pressure
1665
                                        col_no += 1
1666
                                        ws.cell(row_no, col_no, row[6])         # Void
1667
                                        col_no += 1
1668
                                        ws.cell(row_no, col_no, row[7])         # Quality
1669
                                        col_no += 1
1670
                                        ws.cell(row_no, col_no, row[8])         # Density
1671
                                        col_no += 1
1672
                                        ws.cell(row_no, col_no, row[9])         # V.Density
1673
                                        col_no += 1
1674
                                        ws.cell(row_no, col_no, row[10])        # Mean.Vel
1675
                                        col_no += 1
1676
                                        ws.cell(row_no, col_no, row[11])        # Max.Vel
1677
                                        col_no += 1
1678
                                        ws.cell(row_no, col_no, row[12])        # Ero.Vel
1679
                                        col_no += 1
1680
                                        ws.cell(row_no, col_no, row[13])        # X
1681
                                        col_no += 1
1682
                                        ws.cell(row_no, col_no, row[14])        # Y
1683
                                        col_no += 1
1684
                                        ws.cell(row_no, col_no, str(row[15]) if row[15] else '')    # Regime
1685
                                        col_no += 1
1686
                                        ws.cell(row_no, col_no, row[16])        # Friction
1687
                                        col_no += 1
1688
                                        ws.cell(row_no, col_no, row[17])        # Gravity
1689
                                        col_no += 1
1690
                                        ws.cell(row_no, col_no, row[18])        # Moment
1691
                                        col_no += 1
1692
                                        ws.cell(row_no, col_no, row[19])        # Total
1693

    
1694
                                        # load_regime
1695
                                        length = row[2]
1696
                                        if length is not None:
1697
                                            x = float(row[13])
1698
                                            y = float(row[14])
1699

    
1700
                                            angle = float(row[3])
1701
                                            if angle == 0:
1702
                                                # Horizontal
1703
                                                left = 57 + (546 / (7 + 5)) * (math.log10(x) + 5)
1704
                                                top = 651 - (649 / (5 + 9)) * (math.log10(y) + 9)
1705
                                                horizontal.draw_regime(left, top, 8)
1706
                                            elif angle > 0:
1707
                                                # Vertical Upward
1708
                                                left = 59 + (538 / (7 - (-2))) * (math.log10(x) - (-2))
1709
                                                top = 681 - (653 / (8 - (-5))) * (math.log10(y) - (-5))
1710
                                                vertical_upward.draw_regime(left, top, 8)
1711
                                            elif angle < 0:
1712
                                                # Vertical Downward
1713
                                                left = 55 + (517 / (20 - 0)) * (x - 0)
1714
                                                top = 656 - (635 / (24 - 2)) * (y - 2)
1715
                                                vertical_downward.draw_regime(left, top, 8)
1716
                                        row_no += 1
1717

    
1718
                                    with NamedTemporaryFile() as f:
1719
                                        horizontal_image_path = f.name + '.png'
1720
                                    horizontal.save_as(horizontal_image_path)
1721

    
1722
                                    horizontal_flow_image = openpyxl.drawing.image.Image(horizontal_image_path)
1723
                                    horizontal_flow_image.width *= 0.6
1724
                                    horizontal_flow_image.height *= 0.6
1725
                                    ws.add_image(horizontal_flow_image, 'L3')
1726

    
1727
                                    with NamedTemporaryFile() as f:
1728
                                        vertical_upward_image_path = f.name + '.png'
1729
                                    vertical_upward.save_as(vertical_upward_image_path)
1730

    
1731
                                    vertical_upward_flow_image = openpyxl.drawing.image.Image(
1732
                                        vertical_upward_image_path)
1733
                                    vertical_upward_flow_image.width *= 0.6
1734
                                    vertical_upward_flow_image.height *= 0.6
1735
                                    ws.add_image(vertical_upward_flow_image, 'R3')
1736

    
1737
                                    with NamedTemporaryFile() as f:
1738
                                        vertical_downward_image_path = f.name + '.png'
1739
                                    vertical_downward.save_as(vertical_downward_image_path)
1740

    
1741
                                    vertical_downward_flow_image = openpyxl.drawing.image.Image(
1742
                                        vertical_downward_image_path)
1743
                                    vertical_downward_flow_image.width *= 0.6
1744
                                    vertical_downward_flow_image.height *= 0.6
1745
                                    ws.add_image(vertical_downward_flow_image, 'Z3')
1746

    
1747
                    active_sheet = wb.get_sheet_by_name('Page (1)')
1748
                    if active_sheet:
1749
                        wb.active = active_sheet
1750

    
1751
                    wb.get_sheet_by_name('Page').sheet_state = 'hidden'
1752
                    wb.get_sheet_by_name('Two_phase').sheet_state = 'hidden'
1753

    
1754
                    name_without_ext, ext = os.path.splitext(file_name)
1755
                    save_file_name = file_name if ext.upper() == '.XLSX' else name_without_ext + '.xlsx'
1756
                    wb.save(filename=save_file_name)
1757

    
1758
                    os.startfile(save_file_name)
1759

    
1760
                    QMessageBox.information(self, self.tr('Information'), self.tr('Report is done'))
1761
        except Exception as ex:
1762
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1763
                                                           sys.exc_info()[-1].tb_lineno)
1764
            self.addMessage.emit(MessageType.Error, message)
1765

    
1766
    def get_work_sheet(self, work_book, count):
1767
        page_no = math.ceil(count / 20)
1768
        return work_book.get_sheet_by_name('Page ({})'.format(page_no))
1769

    
1770
    def display_output(self):
1771
        try:
1772
            """ display output """
1773
            drawing = AppDocData.instance().activeDrawing
1774
            if drawing is None:
1775
                return
1776

    
1777
            self.clear_output()
1778

    
1779
            self.tableWidgetOutput.setColumnCount(3)
1780
            self.tableWidgetOutput.horizontalHeader().setVisible(False)
1781
            self.tableWidgetOutput.verticalHeader().setVisible(False)
1782
            self.tableWidgetOutput.setSelectionMode(QAbstractItemView.SingleSelection)
1783
            self.tableWidgetOutput.setSelectionBehavior(QAbstractItemView.SelectRows)
1784
            self.tableWidgetOutput.setEditTriggers(QAbstractItemView.NoEditTriggers)
1785
            self.tableWidgetOutput.horizontalHeader().setStretchLastSection(True)
1786

    
1787
            self.tableWidgetDeviation.setColumnCount(1)
1788
            self.tableWidgetDeviation.horizontalHeader().setVisible(False)
1789
            self.tableWidgetDeviation.verticalHeader().setVisible(False)
1790
            self.tableWidgetDeviation.setSelectionMode(QAbstractItemView.SingleSelection)
1791
            self.tableWidgetDeviation.setSelectionBehavior(QAbstractItemView.SelectRows)
1792
            self.tableWidgetDeviation.setEditTriggers(QAbstractItemView.NoEditTriggers)
1793
            self.tableWidgetDeviation.horizontalHeader().setStretchLastSection(True)
1794
            self.tableWidgetDeviation.resizeRowsToContents()
1795
            self.tableWidgetDeviation.resizeColumnsToContents()
1796

    
1797
            units = [attr[1] for attr in drawing.attrs if attr[0] == 'Units'][0]
1798

    
1799
            loops = drawing.loops
1800

    
1801
            # Deviation
1802
            self.add_data(self.tableWidgetDeviation, 'Loop_Deviation', None, None, True, None, None)
1803
            strmsg = None
1804
            for loop in loops:
1805
                deviation = loop.deviation
1806
                if round(deviation, 9) == 0:
1807
                    continue
1808

    
1809
                for i in range(1, len(loop.items) - 1, 3):
1810
                    if i == 1:
1811
                        loop_no = loop.name.replace('Loop', '')
1812
                        if len(loop_no) > 1:
1813
                            strmsg = '({}) {}'.format(loop_no, loop.items[i].stream_no)
1814
                        else:
1815
                            strmsg = '(0{}) {}'.format(loop_no, loop.items[i].stream_no)
1816
                    else:
1817
                        if len(str(loop.items[i - 1])) > 13 and str(loop.items[i - 1])[:13] == 'Line_Splitter':
1818
                            pre_stream_num = loop.items[i - 3].stream_no
1819
                            cur_stream_num = loop.items[i].stream_no
1820

    
1821
                            if strmsg.__contains__('-'):
1822
                                last_stream_num = str(strmsg).rsplit('-', 1)[1]
1823
                            else:
1824
                                last_stream_num = str(strmsg).rsplit(' ', 1)[1]
1825

    
1826
                            if pre_stream_num != int(last_stream_num):
1827
                                strmsg = '{}-{}-{}'.format(strmsg, pre_stream_num, cur_stream_num)
1828

    
1829
                last_stream_num = loop.items[len(loop.items) - 2].stream_no
1830
                strmsg = '{}-{}'.format(strmsg, last_stream_num)
1831

    
1832
                if round(deviation, 3) < 0:
1833
                    self.add_data(self.tableWidgetDeviation,
1834
                                  '{} = {} {}'.format(strmsg, round(deviation, 3), units['Pressure']), None, None, None,
1835
                                  None, QBrush(QColor(255, 0, 0)))
1836
                else:
1837
                    self.add_data(self.tableWidgetDeviation,
1838
                                  '{} = {} {}'.format(strmsg, round(deviation, 3), units['Pressure']), None, None, None,
1839
                                  None)
1840

    
1841
            names = []
1842
            # Pump
1843
            for loop in loops:
1844
                for item in loop.items:
1845
                    parent = item.parent
1846
                    if parent:
1847
                        name = str(item).replace('_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1848
                        if name in names:
1849
                            continue
1850
                        if name[:3] == 'R_P' or name[:3] == 'L_P' or name[:3] == 'V_P':
1851
                            names.append(name)
1852
                            attr = item.parent.attribute
1853
                            if len(attr) > 0:
1854
                                self.add_data(self.tableWidgetOutput, attr['Tag_No'], None, None, True, True)
1855
                                self.add_data(self.tableWidgetOutput, 'Suct.P :', round(attr['Suct.P'], 3),
1856
                                              '{}.g'.format(units['Pressure']))
1857
                                self.add_data(self.tableWidgetOutput, 'Disc.P :', round(attr['Disc.P'], 3),
1858
                                              '{}.g'.format(units['Pressure']))
1859
                                self.add_data(self.tableWidgetOutput, 'Diff.P :', round(attr['Diff.P'], 3),
1860
                                              units['Pressure'])
1861
                                self.add_data(self.tableWidgetOutput, 'Head :', round(attr['Head'], 3), units['Length'])
1862
                                self.add_data(self.tableWidgetOutput, 'NPSHa :', round(attr['NPSHa'], 3), units['Length'])
1863
                                self.add_data(self.tableWidgetOutput, 'Vap. P :', attr['Vap. P'],
1864
                                              '{}.a'.format(units['Pressure']))
1865
                                self.add_data(self.tableWidgetOutput, 'HHP :', round(attr['HHP'], 3), units['Power'])
1866

    
1867
            # Compressor
1868
            for loop in loops:
1869
                for item in loop.items:
1870
                    parent = item.parent
1871
                    if parent:
1872
                        name = str(item).replace('_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1873
                        if name in names:
1874
                            continue
1875
                        if name[:3] == 'R_K' or name[:3] == 'L_K':
1876
                            names.append(name)
1877

    
1878
                            attr = item.parent.attribute
1879
                            if len(attr) > 0:
1880
                                self.add_data(self.tableWidgetOutput, attr['Tag_No'], None, None, True, True)
1881
                                self.add_data(self.tableWidgetOutput, 'Suct.P :', round(attr['Suct.P'], 3),
1882
                                              '{}.g'.format(units['Pressure']))
1883
                                self.add_data(self.tableWidgetOutput, 'Disc.P :', round(attr['Disc.P'], 3),
1884
                                              '{}.g'.format(units['Pressure']))
1885
                                self.add_data(self.tableWidgetOutput, 'Diff.P :', round(attr['Diff.P'], 3),
1886
                                              units['Pressure'])
1887
                                self.add_data(self.tableWidgetOutput, 'HHP :', round(attr['HHP'], 3), units['Power'])
1888

    
1889
            # Control Valve
1890
            for loop in loops:
1891
                for item in loop.items:
1892
                    parent = item.parent
1893
                    if parent:
1894
                        name = str(item).replace('_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '')
1895
                        if name in names:
1896
                            continue
1897
                        if name[:3] == 'CV_':
1898
                            names.append(name)
1899

    
1900
                            attr = item.parent.attribute
1901
                            if len(attr) > 0:
1902
                                self.add_data(self.tableWidgetOutput, attr['Tag_No'], None, None, True, True)
1903
                                self.add_data(self.tableWidgetOutput, 'Inlet P :', round(attr['Suct.P'], 3),
1904
                                              '{}.g'.format(units['Pressure']))
1905
                                self.add_data(self.tableWidgetOutput, 'Outlet P :', round(attr['Disc.P'], 3),
1906
                                              '{}.g'.format(units['Pressure']))
1907
                                self.add_data(self.tableWidgetOutput, 'Diff.P :', round(attr['Diff.P'], 3),
1908
                                              units['Pressure'])
1909
                                self.add_data(self.tableWidgetOutput, 'dP Ratio :', round(attr['dP Ratio'] * 100, 2), '%')
1910

    
1911
        except Exception as ex:
1912
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1913
                                                           sys.exc_info()[-1].tb_lineno)
1914
            self.addMessage.emit(MessageType.Error, message)
1915

    
1916
    def display_loops(self):
1917
        """ display loops """
1918
        drawing = AppDocData.instance().activeDrawing
1919
        if drawing is None: return
1920

    
1921
        loops = drawing.loops
1922
        if loops:
1923
            self.tableWidgetLoop.clear()
1924
            self.tableWidgetLoop.setColumnCount(len(loops) * 5)
1925

    
1926
            _col_names = [[loop.name, 'pressure', 'Static\nLine\ndP_Eq', 'El.\nDensity\nEl.', 'Extra'] for loop in
1927
                          loops]
1928
            col_names = []
1929
            for col_name in _col_names: col_names.extend(col_name)
1930
            self.tableWidgetLoop.setHorizontalHeaderLabels(col_names)
1931
            self.tableWidgetLoop.horizontalHeader().setVisible(True)
1932

    
1933
            max_rows = 0
1934
            for col in range(len(loops)):
1935
                rows = len(loops[col].items)
1936
                max_rows = max(max_rows, rows)
1937
                self.tableWidgetLoop.setRowCount(max_rows)
1938

    
1939
                for row in range(len(loops[col].items)):
1940
                    item = QTableWidgetItem(str(loops[col].items[row]))
1941
                    item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
1942
                    self.tableWidgetLoop.setItem(row, col * 5, item)
1943

    
1944
                # display calcuation values
1945
                for row in range(len(loops[col].items)):
1946
                    if loops[col].items[row] in loops[col].pressures:
1947
                        item = QTableWidgetItem(str(round(loops[col].pressures[loops[col].items[row]], 8)))
1948
                        item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
1949
                        # if not loops[col].pressures[loops[col].items[row]]: item.setBackground(Qt.red)
1950
                        self.tableWidgetLoop.setItem(row, col * 5 + 1, item)
1951

    
1952
                    if loops[col].items[row] in loops[col].pressure_drops:
1953
                        item = QTableWidgetItem(str(round(loops[col].pressure_drops[loops[col].items[row]], 9)))
1954
                        item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
1955
                        # if not loops[col].pressure_drops[loops[col].items[row]]: item.setBackground(Qt.red)
1956
                        self.tableWidgetLoop.setItem(row, col * 5 + 2, item)
1957

    
1958
                    if loops[col].items[row] in loops[col].density_elevations:
1959
                        item = QTableWidgetItem(str(round(loops[col].density_elevations[loops[col].items[row]], 8)))
1960
                        item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
1961
                        # if not loops[col].density_elevations[loops[col].items[row]]: item.setBackground(Qt.red)
1962
                        self.tableWidgetLoop.setItem(row, col * 5 + 3, item)
1963

    
1964
                    if loops[col].items[row] in loops[col].extras:
1965
                        item = QTableWidgetItem(str(loops[col].extras[loops[col].items[row]]))
1966
                        item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
1967
                        # if not loops[col].density_elevations[loops[col].items[row]]: item.setBackground(Qt.red)
1968
                        self.tableWidgetLoop.setItem(row, col * 5 + 4, item)
1969

    
1970
            self.tableWidgetLoop.resizeColumnsToContents()
1971
            self.tableWidgetLoop.resizeRowsToContents()
1972

    
1973
    '''
1974
        @brief  configuration
1975
    '''
1976

    
1977
    def configuration(self):
1978
        from ConfigurationDialog import QConfigurationDialog
1979
        try:
1980
            appDocData = AppDocData.instance()
1981
            if appDocData.activeDrawing is None:
1982
                self.showImageSelectionMessageBox()
1983
                return
1984

    
1985
            dlg = QConfigurationDialog(self)
1986
            (isAccepted, isDataConversion, decimal) = dlg.show_dialog()
1987
            if isAccepted == True:
1988
                if isDataConversion == True:
1989
                    self.data_conversion(decimal)
1990
                else:
1991
                    self.reload_units()
1992

    
1993
        except Exception as ex:
1994
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1995
                                                           sys.exc_info()[-1].tb_lineno)
1996
            self.addMessage.emit(MessageType.Error, message)
1997

    
1998
    def data_conversion(self, decimal):
1999
        from Drawing import Drawing
2000
        from Calculation import Conversion
2001

    
2002
        try:
2003
            Conversion(decimal)
2004

    
2005
            self.load_HMB()
2006
            self.reload_units()
2007

    
2008
        except Exception as ex:
2009
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2010
                                                           sys.exc_info()[-1].tb_lineno)
2011
            self.addMessage.emit(MessageType.Error, message)
2012

    
2013
    '''
2014
        @brief  Show Image Selection Guide MessageBox
2015
        @author Jeongwoo
2016
        @date   2018.05.02
2017
    '''
2018

    
2019
    def showImageSelectionMessageBox(self):
2020
        QMessageBox.information(self, self.tr("Information"), self.tr("First select image drawing"))
2021

    
2022
    def display_colors(self, value):
2023
        """ display colors """
2024
        from DisplayColors import DisplayColors
2025
        from DisplayColors import DisplayOptions
2026

    
2027
        DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value == True else DisplayOptions.DisplayByLineType
2028
        if hasattr(self, 'graphicsView'):
2029
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2030
            DisplayColors.instance().save_data()
2031

    
2032
    '''
2033
        @brief      Open Border file 
2034
        @author     yeonjin
2035
        @date       2019.07.10
2036
    '''
2037

    
2038
    def open_border_file(self):
2039
        self.fitWindow(None)
2040

    
2041
    def patch_data(self):
2042
        try:
2043
            # 2020.01.30 이전에 배포한 Template.db 업데이트 해주어야 함
2044
            # Fitting K 값 Patch
2045
            data = []
2046
            data.append(['43d331ea-f66f-4ced-8a22-e94d43f2c74a', 40])
2047
            data.append(['8b3224e1-784f-4203-9df5-14970f93d5d7', 28])
2048
            data.append(['76d7a533-8bb2-42aa-a58a-b5a57fc1f73d', 24])
2049
            data.append(['b2da93f1-c0d0-4592-897e-f55eeef8c472', 24])
2050
            data.append(['6dada552-aed7-466b-b465-fa0de44a2160', 28])
2051
            data.append(['ec1a9e7c-e2d9-4ebd-ac60-88fcec5a8eb3', 34])
2052
            data.append(['8cbe9c68-5b05-470f-a39c-d271d7f63996', 48])
2053
            data.append(['94d8bdc9-a044-4531-b6eb-f481396f1b9c', 60])
2054
            data.append(['c8e9448f-e3e3-4b8a-b29c-2a75eeec3a33', 68])
2055
            data.append(['92b6fe36-8af8-49cc-a760-4506592bcc0e', 76])
2056
            data.append(['f83ce443-431e-44c0-9aab-2640b15c828c', 84])
2057
            data.append(['65a9d9b2-adde-48d4-87bb-4288ade1c195', 100])
2058

    
2059
            app_doc_data = AppDocData.instance()
2060
            app_doc_data.update_fittings(data)
2061

    
2062
        except Exception as ex:
2063
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2064
                                                           sys.exc_info()[-1].tb_lineno)
2065
            self.addMessage.emit(MessageType.Error, message)
2066

    
2067
    def setAttributes(self, drawing):
2068
        drawing.setAttributes()
2069

    
2070
    '''
2071
        @brief      Reload HMB Units 
2072
        @author     yeonjin
2073
        @date       2019.07.10
2074
    '''
2075

    
2076
    def reload_units(self):
2077
        from Drawing import Drawing
2078

    
2079
        try:
2080
            app_doc_data = AppDocData.instance()
2081
            drawing = app_doc_data.activeDrawing
2082

    
2083
            self.setAttributes(drawing)
2084

    
2085
            columnInfos = app_doc_data.getHMBDisplayNameAndUnitsExpression()
2086

    
2087
            rowIndex = 0
2088
            for columnInfo in columnInfos:
2089
                name = columnInfo[0]
2090
                unit = self.convertToUnits(columnInfo[1])
2091

    
2092
                self.tableWidgetHMB.setItem(rowIndex, 0,
2093
                                            set_item_properties(name, Qt.AlignLeft | Qt.AlignVCenter,
2094
                                                                QColor(51, 153,
2095
                                                                       102)))
2096
                # QColor(230, 230, 230)))
2097
                self.tableWidgetHMB.setItem(rowIndex, 1,
2098
                                            set_item_properties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
2099
                                                                QColor(204, 255, 204)))
2100
                # QColor(230, 230, 230)))
2101

    
2102
                rowIndex += 1
2103

    
2104
            self.tableWidgetHMB.resizeColumnsToContents()
2105
            self.tableWidgetHMB.resizeRowsToContents()
2106

    
2107
        except Exception as ex:
2108
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2109
                                                           sys.exc_info()[-1].tb_lineno)
2110
            self.addMessage.emit(MessageType.Error, message)
2111

    
2112
    def load_data(self, drawing):
2113
        """ load data from drawing """
2114
        from AppDocData import AppDocData
2115
        from Calculation import Calculation
2116
        from HydroCalculationCommand import HydroCalculationCommand
2117
        from Drawing import Drawing
2118

    
2119
        try:
2120
            app_doc_data = AppDocData.instance()
2121

    
2122
            self.graphicsView.scene.clear()
2123
            # Set appDocData
2124
            app_doc_data.clear()
2125
            self.onCommandRejected()
2126
            app_doc_data.activeDrawing = drawing
2127

    
2128
            app_doc_data.build_drawing_database(drawing.path)
2129
            self.patch_data()
2130

    
2131
            self.setAttributes(drawing)
2132
            self.setMainWindowTitle(drawing.path)
2133
            self.initTableWidgetHMB()
2134
            self.clear_loop()
2135
            self.clearlogs()
2136
            self.clear_output()
2137
            # Load data on database
2138

    
2139
            self.symbolTreeWidget.initSymbolTreeWidget()
2140

    
2141
            components = app_doc_data.getComponentListByDrawingUID()
2142
            count = len(components)
2143

    
2144
            if count > 0:
2145
                try:
2146
                    self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
2147
                                                    self) if not hasattr(self, 'progress') else self.progress
2148
                    self.progress.setWindowModality(Qt.WindowModal)
2149
                    self.progress.setAutoReset(True)
2150
                    self.progress.setAutoClose(True)
2151
                    self.progress.setMinimum(0)
2152
                    self.progress.resize(600, 100)
2153
                    self.progress.setWindowTitle(self.tr("Load data..."))
2154
                    self.progress.show()
2155

    
2156
                    self.load_components(components)
2157

    
2158
                    # Loops 와 Output 을 만들기 위해 Calculation 을 한다
2159
                    for hmb in app_doc_data.activeDrawing.hmbTable._hmbs:
2160
                        if hmb.phase_type:
2161
                            Calculation(hmb)
2162
                    cmd = HydroCalculationCommand(self.graphicsView)
2163
                    cmd.execute(None)
2164
                    cmd.execute_second(None)
2165

    
2166
                    app_doc_data.activeDrawing.loops = cmd.loops
2167

    
2168
                    self.display_loops()
2169
                    self.display_output()
2170

    
2171
                    self.load_HMB()
2172
                finally:
2173
                    self.progress.setValue(self.progress.maximum())
2174
                    self.progress.hide()
2175

    
2176
            # self.changeViewCheckedState(False)
2177

    
2178
        except Exception as ex:
2179
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2180
                                                           sys.exc_info()[-1].tb_lineno)
2181
            self.addMessage.emit(MessageType.Error, message)
2182

    
2183
    def saveAs_drawing(self, sourceDb):
2184
        import uuid
2185
        from shutil import copyfile
2186
        from datetime import datetime
2187
        from Drawing import Drawing
2188

    
2189
        workspace = self.get_work_space()
2190

    
2191
        options = QFileDialog.Options()
2192
        options |= QFileDialog.DontUseNativeDialog
2193
        name, _ = QFileDialog.getSaveFileName(self, self.tr('Save As'), workspace, 'HYTOS Files (*.hytos)',
2194
                                              options=options)
2195
        if name:
2196
            if os.path.splitext(name)[1] != '.hytos': name += '.hytos'
2197

    
2198
            app_doc_data = AppDocData.instance()
2199
            # copy template.db to name
2200
            copyfile(sourceDb, name)
2201

    
2202
            matches = [drawing for drawing in app_doc_data.getDrawings() if
2203
                       os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
2204
            if not matches:
2205
                drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
2206
                app_doc_data.saveDrawing(drawing)
2207
            else:
2208
                drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
2209
                app_doc_data.updateDrawing(drawing)
2210

    
2211
            self.load_drawing_list()
2212
            self.load_data(drawing)
2213
            self.open_border_file()
2214

    
2215
    '''
2216
        @brief      create new drawing
2217
        @author     yeonjin
2218
        @date       2019.07.03
2219
    '''
2220

    
2221
    def new_drawing(self):
2222
        import uuid
2223
        from shutil import copyfile
2224
        from datetime import datetime
2225
        from Drawing import Drawing
2226

    
2227
        self.save_drawing_if_necessary()
2228

    
2229
        workspace = self.get_work_space()
2230

    
2231
        options = QFileDialog.Options()
2232
        options |= QFileDialog.DontUseNativeDialog
2233
        name, _ = QFileDialog.getSaveFileName(self, self.tr('New'), workspace, 'HYTOS Files (*.hytos)', options=options)
2234
        if name:
2235
            if os.path.splitext(name)[1] != '.hytos': name += '.hytos'
2236

    
2237
            app_doc_data = AppDocData.instance()
2238
            # copy template.db to name
2239
            copyfile(app_doc_data.getTemplateDbPath(), name)
2240

    
2241
            matches = [drawing for drawing in app_doc_data.getDrawings() if
2242
                       os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
2243
            if not matches:
2244
                drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
2245
                app_doc_data.saveDrawing(drawing)
2246
            else:
2247
                drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
2248
                app_doc_data.updateDrawing(drawing)
2249

    
2250
            self.load_drawing_list()
2251
            self.open_border_file()
2252
            self.load_data(drawing)
2253

    
2254
    def on_open_drawing(self):
2255
        """open selected drawing by user"""
2256

    
2257
        self.save_drawing_if_necessary()
2258

    
2259
        workspace = self.get_work_space()
2260
        options = QFileDialog.Options()
2261
        options |= QFileDialog.DontUseNativeDialog
2262
        name, _ = QFileDialog.getOpenFileName(self, self.tr('Open'), workspace, 'HYTOS File(*.hytos)', options=options)
2263
        if name:
2264
            self.open_drawing(name)
2265

    
2266
    def open_drawing(self, name):
2267
        """open given drawing has name"""
2268
        import uuid
2269
        from Drawing import Drawing
2270
        from datetime import datetime
2271

    
2272
        app_doc_data = AppDocData.instance()
2273
        drawings = app_doc_data.getDrawings()
2274
        matches = [drawing for drawing in drawings if os.path.samefile(drawing.path, name)]
2275
        if not matches:
2276
            drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
2277
            app_doc_data.saveDrawing(drawing)
2278

    
2279
            self.load_drawing_list()
2280
        else:
2281
            drawing = matches[0]
2282

    
2283
        # disconnect scene changed if signal is connected
2284
        if self.graphicsView.scene.receivers(self.graphicsView.scene.contents_changed) > 0:
2285
            self.graphicsView.scene.contents_changed.disconnect()
2286

    
2287
        self.load_data(drawing)
2288
        self.open_border_file()
2289

    
2290
        # connect scene changed signal
2291
        self.graphicsView.scene.contents_changed.connect(self.scene_changed)
2292

    
2293
    def get_work_space(self):
2294
        """get work space path"""
2295
        app_doc_data = AppDocData.instance()
2296

    
2297
        configs = app_doc_data.getAppConfigs('option', 'WorkSpace')
2298
        if configs and len(configs) == 1:
2299
            return configs[0].value
2300
        else:
2301
            return os.getcwd()
2302

    
2303
    def changeViewCheckedState(self, checked, clear=True):
2304
        '''change view checked state'''
2305
        if clear:
2306
            self.initTableWidgetHMB()
2307
            # self.clear_data()
2308

    
2309
    '''
2310
        @brief      create a line
2311
        @author     humkyung
2312
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
2313
    '''
2314

    
2315
    def onPlaceLine(self):
2316
        self.actionLine.setChecked(True)
2317
        if not hasattr(self.actionLine, 'tag'):
2318
            self.actionLine.tag = PlaceStreamlineCommand.PlaceStreamlineCommand(self.graphicsView)
2319
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
2320
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
2321

    
2322
        self.graphicsView.command = self.actionLine.tag
2323

    
2324
    '''
2325
        @brief      add created lines to scene
2326
        @author     humkyung
2327
        @date       2018.07.23
2328
    '''
2329

    
2330
    def onLineCreated(self):
2331
        try:
2332
            count = len(self.actionLine.tag.streamline._vertices)
2333
            if count > 1:
2334
                self.add_hmb_data(self.actionLine.tag.streamline)
2335
                self.actionLine.tag.streamline.transfer.onRemoved.connect(self.on_item_removed)
2336
                self.load_HMB()
2337
        finally:
2338
            self.actionLine.tag.reset()
2339

    
2340
    def on_stream_line_deleted(self, stream_line):
2341
        """ callback after stream line is deleted """
2342
        app_doc_data = AppDocData.instance()
2343
        activeDrawing = app_doc_data.activeDrawing
2344
        if activeDrawing:
2345
            activeDrawing.hmbTable.deleteByUID(stream_line.uid)
2346

    
2347
        self.load_HMB()
2348

    
2349
    def add_hmb_data(self, stream_line):
2350
        """ add a new hmb data associated with given stream line """
2351
        from HMBTable import HMBTable
2352
        import uuid
2353

    
2354
        try:
2355
            drawing = AppDocData.instance().activeDrawing
2356
            if drawing:
2357
                components_uid = stream_line.uid
2358
                stream_no = self.get_next_stream_no(drawing)
2359
                stream_line.stream_no = stream_no
2360
                drawing.hmbTable.add(components_uid, stream_no)
2361
        except Exception as ex:
2362
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2363
                                                           sys.exc_info()[-1].tb_lineno)
2364
            self.addMessage.emit(MessageType.Error, message)
2365

    
2366
    def get_next_stream_no(self, drawing):
2367

    
2368
        if len(list(drawing.hmbTable.streamNos())) == 0:
2369
            return 1
2370
        else:
2371
            streamNos = sorted(list(drawing.hmbTable.streamNos()))
2372
            lastStreamNo = streamNos[-1]
2373
            return lastStreamNo + 1
2374

    
2375
    def clear_HMB(self):
2376
        self.tableWidgetHMB.clearContents()
2377
        self.tableWidgetHMB.setColumnCount(0)
2378

    
2379
    def load_HMB(self):
2380
        drawing = AppDocData.instance().activeDrawing
2381
        if drawing is None: return
2382

    
2383
        hmbs = drawing.hmbTable._hmbs
2384
        if hmbs is not None:
2385
            self.tableWidgetHMB.setColumnCount(2)
2386

    
2387
            col_names = ['Stream No.', 'Unit']
2388
            for hmb in hmbs:
2389
                columnCount = self.tableWidgetHMB.columnCount()
2390
                self.tableWidgetHMB.setColumnCount(columnCount + 1)
2391
                col_names.append(str(hmb.stream_no))
2392

    
2393
                self.tableWidgetHMB.setItem(0, columnCount, set_item_properties(hmb.uid,
2394
                                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2395
                self.tableWidgetHMB.setItem(1, columnCount, set_item_properties(hmb.components_uid,
2396
                                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2397
                self.tableWidgetHMB.setItem(2, columnCount, set_item_properties(hmb.stream_no,
2398
                                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2399
                self.tableWidgetHMB.setItem(3, columnCount, set_item_properties(hmb.phase_type,
2400
                                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2401
                self.tableWidgetHMB.setItem(4, columnCount,
2402
                                            set_item_properties(convert_to_fixed_point(hmb.flowrate_mass),
2403
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2404
                self.tableWidgetHMB.setItem(5, columnCount,
2405
                                            set_item_properties(convert_to_fixed_point(hmb.flowrate_volume),
2406
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2407
                self.tableWidgetHMB.setItem(6, columnCount,
2408
                                            set_item_properties(convert_to_fixed_point(hmb.density),
2409
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2410
                self.tableWidgetHMB.setItem(7, columnCount,
2411
                                            set_item_properties(convert_to_fixed_point(hmb.viscosity),
2412
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2413
                self.tableWidgetHMB.setItem(8, columnCount,
2414
                                            set_item_properties(convert_to_fixed_point(hmb.temperature),
2415
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2416
                self.tableWidgetHMB.setItem(9, columnCount,
2417
                                            set_item_properties(convert_to_fixed_point(hmb.molecular_weight),
2418
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2419
                self.tableWidgetHMB.setItem(10, columnCount,
2420
                                            set_item_properties(convert_to_fixed_point(hmb.specific_heat_ratio),
2421
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2422
                self.tableWidgetHMB.setItem(11, columnCount,
2423
                                            set_item_properties(convert_to_fixed_point(hmb.compress_factor),
2424
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2425
                self.tableWidgetHMB.setItem(12, columnCount,
2426
                                            set_item_properties(convert_to_fixed_point(hmb.nominal_pipe_size),
2427
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2428
                self.tableWidgetHMB.setItem(13, columnCount,
2429
                                            set_item_properties(convert_to_fixed_point(hmb.inside_pipe_size),
2430
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2431
                self.tableWidgetHMB.setItem(14, columnCount,
2432
                                            set_item_properties(convert_to_fixed_point(hmb.schedule_no),
2433
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2434
                self.tableWidgetHMB.setItem(15, columnCount,
2435
                                            set_item_properties(convert_to_fixed_point(hmb.straight_length),
2436
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2437
                self.tableWidgetHMB.setItem(16, columnCount,
2438
                                            set_item_properties(convert_to_fixed_point(hmb.equivalent_length),
2439
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2440

    
2441
                self.tableWidgetHMB.setItem(17, columnCount,
2442
                                            set_item_properties(
2443
                                                convert_to_fixed_point(hmb.equivalent_length_input),
2444
                                                Qt.AlignHCenter | Qt.AlignVCenter))
2445
                self.tableWidgetHMB.setItem(18, columnCount,
2446
                                            set_item_properties(convert_to_fixed_point(hmb.fitting_length),
2447
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2448
                self.tableWidgetHMB.setItem(19, columnCount,
2449
                                            set_item_properties(convert_to_fixed_point(hmb.fitting_K),
2450
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2451
                self.tableWidgetHMB.setItem(20, columnCount,
2452
                                            set_item_properties(convert_to_fixed_point(hmb.equivalent_length_cal),
2453
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2454
                self.tableWidgetHMB.setItem(21, columnCount,
2455
                                            set_item_properties(convert_to_fixed_point(hmb.roughness),
2456
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2457
                self.tableWidgetHMB.setItem(22, columnCount,
2458
                                            set_item_properties(convert_to_fixed_point(hmb.limitation_velocity),
2459
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2460
                self.tableWidgetHMB.setItem(23, columnCount,
2461
                                            set_item_properties(
2462
                                                convert_to_fixed_point(hmb.limitation_pressure_drop),
2463
                                                Qt.AlignHCenter | Qt.AlignVCenter))
2464

    
2465
                self.tableWidgetHMB.setItem(24, columnCount, set_item_properties(None,
2466
                                                                                 Qt.AlignHCenter | Qt.AlignVCenter,
2467
                                                                                 QColor(153, 204, 255)))
2468

    
2469
                self.tableWidgetHMB.setItem(25, columnCount,
2470
                                            set_item_properties(convert_to_fixed_point(hmb.velocity),
2471
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2472
                self.tableWidgetHMB.setItem(26, columnCount,
2473
                                            set_item_properties(convert_to_fixed_point(hmb.reynolds),
2474
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2475
                self.tableWidgetHMB.setItem(27, columnCount,
2476
                                            set_item_properties(convert_to_fixed_point(hmb.friction_factor),
2477
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2478
                self.tableWidgetHMB.setItem(28, columnCount,
2479
                                            set_item_properties(convert_to_fixed_point(hmb.pressure_drop),
2480
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2481
                self.tableWidgetHMB.setItem(29, columnCount,
2482
                                            set_item_properties(convert_to_fixed_point(hmb.pressure_drop_friction),
2483
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2484
                self.tableWidgetHMB.setItem(30, columnCount,
2485
                                            set_item_properties(convert_to_fixed_point(hmb.pressure_drop_static),
2486
                                                                Qt.AlignHCenter | Qt.AlignVCenter))
2487
                self.tableWidgetHMB.setItem(31, columnCount,
2488
                                            set_item_properties(
2489
                                                convert_to_fixed_point(hmb.pressure_pipe_end_point),
2490
                                                Qt.AlignHCenter | Qt.AlignVCenter))
2491
                self.tableWidgetHMB.setItem(32, columnCount, set_item_properties(convert_to_fixed_point(hmb.power),
2492
                                                                                 Qt.AlignHCenter | Qt.AlignVCenter))
2493

    
2494
                if hmb.isDeleted: self.tableWidgetHMB.hideColumn(columnCount)
2495

    
2496
            self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
2497

    
2498
            self.tableWidgetHMB.resizeColumnsToContents()
2499
            self.tableWidgetHMB.resizeRowsToContents()
2500

    
2501
    '''
2502
        @brief      refresh scene
2503
        @author     humkyung
2504
        @date       2018.07.23
2505
    '''
2506

    
2507
    def onCommandRejected(self, cmd=None):
2508
        try:
2509
            if type(cmd) is PlaceStreamlineCommand.PlaceStreamlineCommand:
2510
                if self.actionLine.tag.streamline:
2511
                    self.graphicsView.scene.removeItem(self.actionLine.tag.streamline)
2512
                self.graphicsView.scene.update()
2513
                self.actionLine.tag.reset()
2514

    
2515
                self.actionLine.setChecked(False)
2516
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
2517
                self.actionZoom.setChecked(False)
2518
            else:
2519
                if hasattr(self.actionLine, 'tag') and self.actionLine.tag.streamline:
2520
                    self.graphicsView.scene.removeItem(self.actionLine.tag.streamline)
2521
                    self.graphicsView.scene.update()
2522
                    self.actionLine.tag.reset()
2523

    
2524
                self.actionLine.setChecked(False)
2525
                self.actionZoom.setChecked(False)
2526
        finally:
2527
            self.graphicsView.useDefaultCommand()
2528

    
2529
    '''
2530
        @brief      restore to default command when user press Escape key
2531
        @author     humkyung 
2532
        @date       2018.08.09
2533
        
2534
    '''
2535

    
2536
    def keyPressEvent(self, event):
2537
        try:
2538
            if event.key() == Qt.Key_Escape:
2539
                self.graphicsView.useDefaultCommand()
2540
            elif (event.key() == Qt.Key_C) and (event.modifiers() & Qt.ControlModifier):
2541
                if self.tableWidgetHMB.hasFocus():
2542
                    self.copy_selection(self.tableWidgetHMB)
2543
            elif (event.key() == Qt.Key_V) and (event.modifiers() & Qt.ControlModifier):
2544
                if self.tableWidgetHMB.hasFocus():
2545
                    self.paste_selection(self.tableWidgetHMB)
2546

    
2547
            QMainWindow.keyPressEvent(self, event)
2548
        except Exception as ex:
2549
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2550
                                                           sys.exc_info()[-1].tb_lineno)
2551
            self.addMessage.emit(MessageType.Error, message)
2552

    
2553
    def on_item_removed(self, item):
2554
        """remove item from tree widget and then remove from scene"""
2555

    
2556
        try:
2557
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'connectors') and \
2558
                       [connector for connector in _item.connectors if
2559
                        connector.connectedItem is not None and connector.connectedItem.parentItem() is item]]
2560
            # disconnect deleted item
2561
            for match in matches:
2562
                for connector in match.connectors:
2563
                    if connector.connectedItem and connector.connectedItem.parentItem() is item:
2564
                        connector.connect(None)
2565

    
2566
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'owner')]
2567
            for match in matches:
2568
                if match.owner is item:
2569
                    match.owner = None
2570

    
2571
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'attrs')]
2572
            done = False
2573
            for match in matches:
2574
                for assoc in match.associations():
2575
                    if item is assoc:
2576
                        match.remove_assoc_item(item)
2577
                        for attr in match.attrs.keys():
2578
                            if str(item.uid) == str(attr.AssocItem.uid):
2579
                                attr.AssocItem = None
2580
                                match.attrs[attr] = ''
2581
                                done = True
2582
                                break
2583
                        break
2584
                if done: break
2585

    
2586
            if type(item) is QEngineeringStreamlineItem:
2587
                self.on_stream_line_deleted(item)
2588

    
2589
            if item.scene() is not None:
2590
                item.scene().removeItem(item)
2591
                del item
2592
        except Exception as ex:
2593
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
2594
                                                           sys.exc_info()[-1].tb_lineno)
2595
            self.addMessage.emit(MessageType.Error, message)
2596

    
2597
    '''
2598
        @brief      load components
2599
        @author     yeonjin
2600
        @date       2019.07.30.
2601
    '''
2602

    
2603
    def load_components(self, componentsUID):
2604
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
2605
        from EngineeringCalloutTextItem import QEngineeringCalloutTextItem
2606
        from EngineeringDimensionItem import QEngineeringDimensionItem
2607
        from EngineeringCloudItem import QEngineeringCloudItem
2608

    
2609
        try:
2610
            app_doc_data = AppDocData.instance()
2611

    
2612
            maxValue = len(componentsUID)
2613
            self.progress.setMaximum(maxValue)
2614

    
2615
            for componentUID in componentsUID:
2616
                componentInfos = app_doc_data.getComponentByComponentUID(componentUID)
2617
                if (len(componentInfos)) > 0:
2618
                    category = componentInfos[0]['Category']  # Category@SymbolType
2619
                    symbol_name = componentInfos[0]['Symbol_Name']  # Name@Symbols
2620

    
2621
                    if category == 'Stream Line':
2622
                        item = QEngineeringStreamlineItem.fromDatabase(componentInfos)
2623
                        if item is not None:
2624
                            item.transfer.onRemoved.connect(self.on_item_removed)
2625
                            self.graphicsView.scene.addItem(item)
2626
                    elif symbol_name == 'Callout':
2627
                        item = QEngineeringCalloutTextItem.fromDatabase(componentInfos)
2628
                        if item:
2629
                            item.transfer.onRemoved.connect(self.on_item_removed)
2630
                            item.lost_focus.connect(self.editor_lost_focus)
2631
                            item.selected_change.connect(self.item_selected)
2632
                            self.graphicsView.scene.addItem(item)
2633
                    elif symbol_name == 'Dimension':
2634
                        item = QEngineeringDimensionItem.fromDatabase(componentInfos)
2635
                        if item:
2636
                            item.transfer.onRemoved.connect(self.on_item_removed)
2637
                            self.graphicsView.scene.addItem(item)
2638
                    elif symbol_name == 'Cloud':
2639
                        item = QEngineeringCloudItem.fromDatabase(componentInfos)
2640
                        if item:
2641
                            self.graphicsView.scene.addItem(item)
2642
                    else:
2643
                        item = SymbolSvgItem.fromDatabase(componentInfos)
2644
                        if item is not None:
2645
                            item.transfer.onRemoved.connect(self.on_item_removed)
2646
                            app_doc_data.symbols.append(item)
2647
                            self.addSvgItemToScene(item)
2648

    
2649
                    self.progress.setValue(self.progress.value() + 1)
2650

    
2651
                QApplication.processEvents()
2652

    
2653
            #self.rebuild_label()
2654

    
2655
            # """ update scene """
2656
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
2657
            for item in self.graphicsView.scene.items():
2658
                item.setVisible(True)
2659

    
2660
        except Exception as ex:
2661
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
2662
                                                           sys.exc_info()[-1].tb_lineno)
2663
            self.addMessage.emit(MessageType.Error, message)
2664
        finally:
2665
            pass
2666

    
2667
    '''
2668
        @brief      Remove added item on same place and Add GraphicsItem
2669
        @author     Jeongwoo
2670
        @date       2018.05.25
2671
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2672
                    2018.06.18  Jeongwoo    Set Z-index
2673
    '''
2674

    
2675
    def addSvgItemToScene(self, svgItem):
2676
        svgItem.addSvgItemToScene(self.graphicsView.scene)
2677

    
2678
    '''
2679
        @brief      Remove added item on same place and Add GraphicsItem
2680
        @author     Jeongwoo
2681
        @date       2018.05.25
2682
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
2683
                    2018.06.05  Jeongwoo    Remove Size condition
2684
                    2018.06.18  Jeongwoo    Set Z-index
2685
    '''
2686

    
2687
    def addTextItemToScene(self, textItem):
2688
        textItem.addTextItemToScene(self.graphicsView.scene)
2689

    
2690
    '''
2691
        @brief      Remove added item on same place and Add GraphicsItem
2692
        @author     Jeongwoo
2693
        @date       2018.05.29
2694
        @history    2018.06.18  Jeongwoo    Set Z-index
2695
    '''
2696

    
2697
    def addLineItemToScene(self, lineItem):
2698
        self.graphicsView.scene.addItem(lineItem)
2699

    
2700
    '''
2701
        @brief      Check Number
2702
        @author     kyouho
2703
        @date       2018.08.20
2704
    '''
2705

    
2706
    def isNumber(self, num):
2707
        p = re.compile('(^[0-9]+$)')
2708
        result = p.match(num)
2709

    
2710
        if result:
2711
            return True
2712
        else:
2713
            return False
2714

    
2715
    '''
2716
        @brief      find overlap Connector
2717
        @author     kyouho
2718
        @date       2018.08.28
2719
    '''
2720

    
2721
    def findOverlapConnector(self, connectorItem):
2722
        from shapely.geometry import Point
2723
        from EngineeringConnectorItem import QEngineeringConnectorItem
2724
        itemList = []
2725

    
2726
        x = connectorItem.center()[0]
2727
        y = connectorItem.center()[1]
2728

    
2729
        connectors = [item for item in self.graphicsView.scene.items() if
2730
                      type(item) is QEngineeringConnectorItem and item != connectorItem]
2731
        for connector in connectors:
2732
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
2733
                itemList.append(connector.parent)
2734

    
2735
        return itemList
2736

    
2737
    def add_data(self, table_widget, name, value, unit, separation=None, is_cell_merge=None, foregroundcolor=None):
2738
        row = table_widget.rowCount()
2739
        table_widget.setRowCount(row + 1)
2740

    
2741
        if separation:
2742
            if is_cell_merge:
2743
                table_widget.setSpan(row, 0, 1, 3)
2744
                table_widget.setItem(row, 0, set_item_properties(name,
2745
                                                                 Qt.AlignLeft | Qt.AlignVCenter,
2746
                                                                 QColor(153, 204, 255), foregroundcolor))
2747
            else:
2748
                table_widget.setItem(row, 0, set_item_properties(name,
2749
                                                                 Qt.AlignLeft | Qt.AlignVCenter,
2750
                                                                 QColor(153, 204, 255), foregroundcolor))
2751
                table_widget.setItem(row, 1, set_item_properties(value,
2752
                                                                 Qt.AlignHCenter | Qt.AlignVCenter,
2753
                                                                 QColor(153, 204, 255), foregroundcolor))
2754
                table_widget.setItem(row, 2, set_item_properties(unit,
2755
                                                                 Qt.AlignHCenter | Qt.AlignVCenter,
2756
                                                                 QColor(153, 204, 255), foregroundcolor))
2757
        else:
2758
            if is_cell_merge:
2759
                table_widget.setSpan(row, 0, 1, 3)
2760
                table_widget.setItem(row, 0, set_item_properties(name,
2761
                                                                 Qt.AlignLeft | Qt.AlignVCenter, None,
2762
                                                                 foregroundcolor))
2763
            else:
2764
                table_widget.setItem(row, 0, set_item_properties(name,
2765
                                                                 Qt.AlignLeft | Qt.AlignVCenter, None,
2766
                                                                 foregroundcolor))
2767
                table_widget.setItem(row, 1, set_item_properties(value,
2768
                                                                 Qt.AlignRight | Qt.AlignVCenter, None,
2769
                                                                 foregroundcolor))
2770
                table_widget.setItem(row, 2, set_item_properties(unit,
2771
                                                                 Qt.AlignLeft | Qt.AlignVCenter, None,
2772
                                                                 foregroundcolor))
2773

    
2774
        table_widget.resizeRowsToContents()
2775
        table_widget.resizeColumnsToContents()
2776

    
2777

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