프로젝트

일반

사용자정보

통계
| 개정판:

hytos / HYTOS / HYTOS / MainWindow.py @ a307208a

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

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

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

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

    
15
import numpy as np
16

    
17
from PyQt5.QtCore import *
18
from PyQt5.QtGui import *
19
from PyQt5.QtWidgets import *
20
from PyQt5.QtSvg import *
21

    
22
from PIL import Image
23

    
24
import MainWindow_UI
25
import QtImageViewer
26
from SingletonInstance import SingletonInstane
27

    
28
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Shapes')
29
from SymbolSvgItem import SymbolSvgItem
30

    
31
from EngineeringTextItem import QEngineeringTextItem
32
from EngineeringErrorItem import QEngineeringErrorItem
33
from EngineeringStreamlineItem import QEngineeringStreamlineItem
34
from AppDocData import *
35
import SymbolTreeWidget
36
import uuid
37

    
38

    
39
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane):
40
    """ This is MainWindow class """
41
    addMessage = pyqtSignal(Enum, str)
42

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

55
    '''
56

    
57
    def __init__(self):
58
        try:
59
            super(self.__class__, self).__init__()
60
            self.setupUi(self)
61

    
62
            self._label_mouse = QLabel(self.statusbar)
63
            self._label_mouse.setText(self.tr('mouse pos : ({},{})'.format(0, 0)))
64
            self.statusbar.addWidget(self._label_mouse)
65
            self.addMessage.connect(self.onAddMessage)
66
            self.showMaximized()
67

    
68
            self.setMainWindowTitle()
69

    
70
            self.graphicsView = QtImageViewer.QtImageViewer(self)
71
            self.graphicsView.setParent(self.centralwidget)
72
            self.graphicsView.useDefaultCommand()
73
            self.graphicsView.setMouseTracking(True)
74
            self.graphicsView.viewport().installEventFilter(self)
75
            self.verticalLayout.addWidget(self.graphicsView)
76

    
77
            # Add Symbol TreeWidget
78
            self.symbolTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
79
            self.symbolTreeWidget.header().hide()
80
            self.verticalLayoutSymbolList.addWidget(self.symbolTreeWidget)
81

    
82
            # Initialize Action group
83
            self.actionGroup = QActionGroup(self)
84
            self.actionGroup.addAction(self.actionLine)
85
            self.actionGroup.addAction(self.actionZoom)
86
            self.actionGroup.addAction(self.actionFitWindow)
87
            self.actionGroup.addAction(self.actionSave)
88

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

    
107
            self.treeWidgetDrawingList.setContextMenuPolicy(Qt.CustomContextMenu)
108
            self.treeWidgetDrawingList.customContextMenuRequested.connect(self.openContextMenu)
109
            self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing)
110

    
111
            self.initTreeWidgetDrawingList()
112
            self.initTableWidgetHMB()
113
            self.load_drawing_list()
114

    
115
            self.load_stylesheet_file()
116
            self.load_language_file()
117

    
118
            self.tabifyDockWidget(self.dockWidgetDrawingExplorer, self.dockWidgetSymbolExplorer)
119
            self.dockWidgetDrawingExplorer.raise_()
120

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

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

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

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

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

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

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

    
191
            menu = QMenu()
192

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

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

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

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

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

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

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

    
220
        self.saveAs_drawing(sourceDb)
221

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

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

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

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

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

    
246
                        self.initTableWidgetHMB()
247

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

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

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

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

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

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

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

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

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

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

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

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

    
301
    def initTreeWidgetDrawingList(self):
302

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

    
312
    def clear_loop(self):
313
        self.tableWidgetLoop.setColumnCount(0)
314

    
315
    def initTableWidgetHMB(self):
316
        app_doc_data = AppDocData.instance()
317

    
318
        columnInfos = app_doc_data.getHMBDisplayNameAndUnitsExpression()
319
        count = len(columnInfos)
320
        self.tableWidgetHMB.setRowCount(count)
321
        if len(columnInfos) > 0:
322
            self.tableWidgetHMB.setColumnCount(2)
323
        else:
324
            self.tableWidgetHMB.setColumnCount(0)
325

    
326
        self.tableWidgetHMB.hideRow(0)  # UID
327
        self.tableWidgetHMB.hideRow(1)  # Components_UID
328
        self.tableWidgetHMB.hideRow(2)  # Stream_No
329
        # self.tableWidgetHMB.hideRow(3)  # Phase_Type
330
        # self.tableWidgetHMB.hideRow(4)  # Flowrate_Mass
331
        # self.tableWidgetHMB.hideRow(5)  # Flowrate_Volume
332
        # self.tableWidgetHMB.hideRow(6)  # Density
333
        # self.tableWidgetHMB.hideRow(7)  # Viscosity
334
        # self.tableWidgetHMB.hideRow(8)  # Temperature
335
        # self.tableWidgetHMB.hideRow(9)  # Molecular_Weight
336
        # self.tableWidgetHMB.hideRow(10)  # Specific_Heat_Ratio
337
        # self.tableWidgetHMB.hideRow(11)  # Compress_Factor
338
        # self.tableWidgetHMB.hideRow(12)  # Nominal_Pipe_Size
339
        # self.tableWidgetHMB.hideRow(13)  # Inside_Pipe_Size
340
        # self.tableWidgetHMB.hideRow(14)  # Schedule_No
341
        # self.tableWidgetHMB.hideRow(15)  # Straight_Length
342
        # self.tableWidgetHMB.hideRow(16)  # Equivalent_Length
343
        self.tableWidgetHMB.hideRow(17)  # Equivalent_Length_Input
344
        self.tableWidgetHMB.hideRow(18)  # Fitting_Length
345
        self.tableWidgetHMB.hideRow(19)  # Fitting_K
346
        self.tableWidgetHMB.hideRow(20)  # Equivalent_Length_Cal
347
        # self.tableWidgetHMB.hideRow(21)  # Roughness
348
        # self.tableWidgetHMB.hideRow(22)  # Limitation_Velocity
349
        # self.tableWidgetHMB.hideRow(23)  # Limitation_Pressure_Drop
350
        # self.tableWidgetHMB.hideRow(24)  # Separator
351
        # self.tableWidgetHMB.hideRow(25)  # Velocity
352
        # self.tableWidgetHMB.hideRow(26)  # Reynolds
353
        # self.tableWidgetHMB.hideRow(27)  # Friction_Factor
354
        # self.tableWidgetHMB.hideRow(28)  # Pressure_Drop
355
        # self.tableWidgetHMB.hideRow(29)  # Pressure_Drop_Friction
356
        # self.tableWidgetHMB.hideRow(30)  # Pressure_Drop_Static
357
        # self.tableWidgetHMB.hideRow(31)  # Pressure_Pipe_End_Point
358
        self.tableWidgetHMB.hideRow(32)  # Power
359

    
360
        self.tableWidgetHMB.setEditTriggers(QAbstractItemView.NoEditTriggers)
361
        self.tableWidgetHMB.verticalHeader().setVisible(False)
362

    
363
        col_names = ['Stream No.', 'Unit']
364
        self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
365

    
366
        rowIndex = 0
367
        for columnInfo in columnInfos:
368
            name = columnInfo[0]
369
            unit = self.convertToUnits(columnInfo[1])
370

    
371
            self.tableWidgetHMB.setItem(rowIndex, 0,
372
                                        self.setTableWidgetItemProperties(name, Qt.AlignLeft | Qt.AlignVCenter,
373
                                                                          QColor(51, 153,
374
                                                                                 102)))  # QColor(230, 230, 230)))
375
            self.tableWidgetHMB.setItem(rowIndex, 1,
376
                                        self.setTableWidgetItemProperties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
377
                                                                          QColor(204, 255,
378
                                                                                 204)))  # QColor(230, 230, 230)))
379

    
380
            rowIndex += 1
381

    
382
        self.tableWidgetHMB.resizeColumnsToContents()
383
        self.tableWidgetHMB.resizeRowsToContents()
384

    
385
    '''
386
        @brief      Drawing 속성의 Units 에서 Key값을 이용하여 Value를 찾음
387
        @author     yeonjin
388
        @date       19.08.30
389
    '''
390

    
391
    def findValue(self, key):
392
        value = None
393

    
394
        key = key.replace("{", "").replace("}", "")
395
        for attr in AppDocData.instance().activeDrawing.attrs:
396
            if attr[0] == 'Units':
397
                if key in attr[1]:
398
                    value = attr[1][key]
399
                    break
400

    
401
        return value
402

    
403
    '''
404
        @brief      Convert UnitsExpression To Units Value
405
        @author     yeonjin
406
        @date       19.08.29
407
    '''
408

    
409
    def convertToUnits(self, unitsExpression):
410
        import re
411

    
412
        if unitsExpression is None or AppDocData.instance().activeDrawing is None:
413
            return ''
414

    
415
        found = re.findall('{.*?}', unitsExpression)
416
        for f in found:
417
            key = f
418
            val = self.findValue(key)
419
            if val:
420
                unitsExpression = unitsExpression.replace(key, val)
421

    
422
        return unitsExpression
423

    
424
    '''
425
        @brief      Clear TreeWidget and Set Current PID
426
        @author     Jeongwoo
427
        @date       18.04.11
428
        @history    2018.04.26  Jeongwoo    Add Child [SYMBOLS, NOTES] into root item
429
                    2018.05.09  Jeongwoo    Change method to add default tree items
430
                    humkyung 2018.06.10 add tree item for Line No and Unknown Item
431
    '''
432

    
433
    def load_drawing_list(self):
434
        """
435
        @brief      load p&id drawing list
436
        @author     humkyung
437
        @date       18.11.02
438
        """
439

    
440
        try:
441
            app_doc_data = AppDocData.instance()
442
            drawings = app_doc_data.getDrawings()
443

    
444
            self.treeWidgetDrawingList.clear()
445
            self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList, [self.tr('Drawings'), ''])
446

    
447
            for drawing in drawings:
448
                item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [drawing.name, drawing.date_time, drawing.path])
449
                item.setData(0, Qt.UserRole, drawing)
450

    
451
            self.treeWidgetDrawingList.root.setText(0, self.tr('Drawings') + '({})'.format(
452
                self.treeWidgetDrawingList.root.childCount()))
453
            self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root)
454
            self.treeWidgetDrawingList.sortByColumn(1, Qt.DescendingOrder)
455
            self.treeWidgetDrawingList.resizeColumnToContents(0)
456

    
457
        except Exception as ex:
458
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
459
                                                           sys.exc_info()[-1].tb_lineno)
460
            self.addMessage.emit(MessageType.Error, message)
461

    
462
    def open_selected_drawing(self, item):
463
        """ open selected drawing """
464
        try:
465
            path = item.text(2)
466
            if os.path.exists(path):
467
                self.open_drawing(path)
468

    
469
        except Exception as ex:
470
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
471
                                                           sys.exc_info()[-1].tb_lineno)
472
            self.addMessage.emit(MessageType.Error, message)
473

    
474
    '''
475
        @brief      action save click event
476
        @author     kyouho
477
        @date       2018.08.09
478
        @history    2018.11.02      euisung     add line data list db update
479
                    humkyung save saved time to database
480
                    2018.11.05      euisung     add note data list db update
481
                    2018.11.05      euisung     add db delete process before save
482
                    2018.11.12      euisung     db part move new method to dbUpdate
483
    '''
484

    
485
    def actionSaveCliked(self):
486
        from datetime import datetime
487
        from AppDocData import AppDocData
488
        from EngineeringAbstractItem import QEngineeringAbstractItem
489
        from SaveWorkCommand import SaveWorkCommand
490

    
491
        try:
492
            app_doc_data = AppDocData.instance()
493
            if app_doc_data.activeDrawing is None:
494
                self.showImageSelectionMessageBox()
495
                return
496

    
497
            app_doc_data.activeDrawing.clearItemList()
498

    
499
            items = self.graphicsView.scene.items()
500
            for item in items:
501
                if issubclass(type(item), QEngineeringAbstractItem):
502
                    app_doc_data.activeDrawing.allItems.append(item)
503
                    if issubclass(type(item), QEngineeringTextItem):
504
                        app_doc_data.texts.append(item)
505

    
506
            count = len(app_doc_data.activeDrawing.allItems)
507
            if count > 0:
508
                try:
509
                    self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
510
                                                    self) if not hasattr(self, 'progress') else self.progress
511
                    self.progress.setWindowModality(Qt.WindowModal)
512
                    self.progress.setAutoReset(True)
513
                    self.progress.setAutoClose(True)
514
                    self.progress.setMinimum(0)
515
                    self.progress.resize(600, 100)
516
                    self.progress.setWindowTitle(self.tr("Save"))
517
                    self.progress.show()
518

    
519
                    self.save_drawing_data()
520
                finally:
521
                    self.load_drawing_list()
522
                    self.progress.setValue(self.progress.maximum())
523
                    self.progress.hide()
524

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

    
530
    def save_drawing_data(self):
531
        """ save drawing data """
532
        from datetime import datetime
533
        from AppDocData import AppDocData
534
        from SymbolSvgItem import SymbolSvgItem
535
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
536

    
537
        try:
538
            app_doc_data = AppDocData.instance()
539
            items = app_doc_data.activeDrawing.allItems
540

    
541
            maxValue = len(items)
542
            self.progress.setMaximum(maxValue)
543

    
544
            index = 0
545
            for item in items:
546
                if type(item) is SymbolSvgItem or type(item) is QEngineeringStreamlineItem:
547
                    app_doc_data.saveToDatabase(item, index)
548
                    self.progress.setValue(index)
549
                    index += 1
550

    
551
                QApplication.processEvents()
552

    
553
            if app_doc_data.activeDrawing:
554
                app_doc_data.activeDrawing.hmbTable.saveData()
555

    
556
            """ update drawing's modified time """
557
            drawings = app_doc_data.getDrawings()
558
            drawing = [drawing for drawing in drawings if app_doc_data.activeDrawing == drawing]
559
            if drawing:
560
                drawing.date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
561
                appDocData.updateDrawing(drawing)
562

    
563
        except Exception as ex:
564
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
565
                                                           sys.exc_info()[-1].tb_lineno)
566
            self.addMessage.emit(MessageType.Error, message)
567

    
568
    '''
569
        @brief  add message listwidget
570
        @author humkyung
571
        @date   2018.07.31
572
    '''
573

    
574
    def onAddMessage(self, messageType, message):
575
        from AppDocData import MessageType
576

    
577
        try:
578
            current = QDateTime.currentDateTime()
579

    
580
            item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message))
581
            if messageType == MessageType.Error:
582
                item.setForeground(Qt.red)
583
            elif messageType == MessageType.Information:
584
                item.setForeground(Qt.blue)
585

    
586
            self.listWidgetLogs.insertItem(0, item)
587
        except Exception as ex:
588
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
589
                                                       sys.exc_info()[-1].tb_lineno))
590
        finally:
591
            logs = self.listWidgetLogs.count()
592
            if logs:
593
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs({})'.format(logs))
594
            else:
595
                self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs')
596

    
597
    '''
598
        @brief      Area Zoom
599
        @author     Jeongwoo
600
        @date       2018.06.27
601
        @history    connect command's rejected signal
602
    '''
603

    
604
    def onAreaZoom(self, action):
605
        if self.actionZoom.isChecked():
606
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
607
            cmd.onRejected.connect(self.onCommandRejected)
608
            self.graphicsView.command = cmd
609

    
610
    '''
611
        @brief      Fit Window
612
        @author     Jeongwoo
613
        @date       2018.06.27
614
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
615
    '''
616

    
617
    def fitWindow(self, action):
618
        self.graphicsView.useDefaultCommand()
619
        self.graphicsView.zoomImageInit()
620

    
621
    '''
622
        @brief      selection changed
623
        @author     humkyung
624
        @date       2018.06.27
625
        @history    humkung 2018.07.08 call tree widget's findItem
626
    '''
627

    
628
    def onSelectionChanged(self):
629
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
630

    
631
        items = [item for item in self.graphicsView.scene.selectedItems() if
632
                 issubclass(type(item), SymbolSvgItem) or type(item) is QEngineeringStreamlineItem]
633
        if items:
634
            item = items[-1]
635

    
636
            if type(item) is QEngineeringErrorItem:
637
                for index in range(self.tableWidgetHMB.rowCount()):
638

    
639
                    if self.tableWidgetHMB.item(index, 1).tag is item:
640
                        self.tableWidgetHMB.selectRow(index)
641
                        break
642

    
643
    '''
644
        @brief      Initialize scene and itemTreeWidget
645
        @author     Jeongwoo
646

647
        @date       2018.06.14
648
        @history    humkyung 2018.08.16 ask to delete recognized items before remove
649
    '''
650

    
651
    def onInitializeScene(self, action):
652

    
653
        if not self.graphicsView.hasImage():
654
            self.showImageSelectionMessageBox()
655
            return
656

    
657
        try:
658
            msg = QMessageBox(self)
659
            msg.setIcon(QMessageBox.Question)
660
            msg.setText(self.tr('Do you want to remove all items?\nThis work cannot be recovered.'))
661
            msg.setWindowTitle(self.tr("Clear Screen"))
662
            msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
663
            if QMessageBox.Ok == msg.exec_():
664

    
665
                appDocData = AppDocData.instance()
666
                appDocData.activeDrawing.hmbTable.reset()
667
                appDocData.clearItemList(True)
668

    
669
                items = self.graphicsView.scene.items()
670
                for item in items:
671
                    if type(item) is not QGraphicsPixmapItem and item.scene() is not None:
672
                        self.graphicsView.scene.removeItem(item)
673

    
674
                appDocData.initializeDataByDrawingUID(appDocData.activeDrawing.UID)
675

    
676
                self.initTableWidgetHMB()
677

    
678
        except Exception as ex:
679
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
680
                                                           sys.exc_info()[-1].tb_lineno)
681
            self.addMessage.emit(MessageType.Error, message)
682

    
683
    '''
684
        @brief      Manage Checkable Action statement
685
        @author     Jeongwoo
686
        @date       2018.05.10
687
        @history    2018.06.27  Jeongwoo    Chnage method to initialize command [Set None → DefaultCommand]
688
    '''
689

    
690
    def actionGroupTriggered(self, action):
691
        if hasattr(self.actionLine, 'tag'):
692
            self.actionLine.tag.onRejected.emit(None)
693

    
694
        if self.graphicsView.command is not None:
695
            self.graphicsView.useDefaultCommand()
696

    
697
        for _action in [x for x in self.actionGroup.actions() if x is not action]:
698
            _action.setChecked(False)
699
            if _action is self.actionLine:
700
                for item in self.graphicsView.scene.items():
701
                    if not hasattr(item, 'connectors'): continue
702
                    for connector in item.connectors: connector.hide()
703

    
704
        action.setChecked(True)
705
        if action is self.actionLine:
706
            for item in self.graphicsView.scene.items():
707
                if not hasattr(item, 'connectors'): continue
708
                for connector in item.connectors: connector.setVisible(True)
709

    
710
    def showSymbolEditor(self):
711
        from SymbolEditorDialog import QSymbolEditorDialog
712

    
713
        dlg = QSymbolEditorDialog()
714
        dlg.exec_()
715

    
716
    def onOptions(self):
717
        from OptionsDialog import QOptionsDialog
718

    
719
        self.dlgOptions = QOptionsDialog(self)
720
        self.dlgOptions.exec_()
721

    
722
    def calculation(self):
723
        """ execute hydro calculation """
724
        from AppDocData import AppDocData
725
        from Calculation import Calculation
726
        from HydroCalculationCommand import HydroCalculationCommand
727

    
728
        try:
729
            app_doc_data = AppDocData.instance()
730
            if app_doc_data.activeDrawing is None:
731
                self.showImageSelectionMessageBox()
732
                return
733

    
734
            hmbs = app_doc_data.activeDrawing.hmbTable._hmbs
735
            if hmbs is not None:
736
                try:
737
                    self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
738
                                                    self) if not hasattr(self, 'progress') else self.progress
739
                    self.progress.setWindowModality(Qt.WindowModal)
740
                    self.progress.setAutoReset(True)
741
                    self.progress.setAutoClose(True)
742
                    self.progress.setMinimum(0)
743
                    self.progress.resize(600, 100)
744
                    self.progress.setWindowTitle(self.tr("Calculate data..."))
745
                    self.progress.show()
746

    
747
                    maxValue = len(hmbs)
748
                    self.progress.setMaximum(maxValue)
749

    
750
                    for hmb in hmbs:
751
                        self.progress.setValue(self.progress.value() + 1)
752

    
753
                        if hmb.phase_type:
754
                            Calculation(hmb)
755

    
756
                        QApplication.processEvents()
757

    
758
                    """ generate loop """
759
                    cmd = HydroCalculationCommand(self.graphicsView)
760
                    cmd.execute(None)
761
                    self.display_loops(cmd.loops)
762

    
763
                    self.load_HMB()
764
                finally:
765
                    self.progress.setValue(self.progress.maximum())
766
                    self.progress.hide()
767
        except Exception as ex:
768
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
769
                                                           sys.exc_info()[-1].tb_lineno)
770
            self.addMessage.emit(MessageType.Error, message)
771

    
772
    def generate_report(self):
773
        """generate calculation report"""
774
        from tempfile import NamedTemporaryFile
775
        import openpyxl
776

    
777
        try:
778
            image_path = None
779
            with NamedTemporaryFile() as f:
780
                image_path = f.name + '.png'
781

    
782
            if image_path:
783
                self.graphicsView.save_as_image(image_path)
784

    
785
                workspace = self.getWorkSpace()
786

    
787
                options = QFileDialog.Options()
788
                options |= QFileDialog.DontUseNativeDialog
789
                name, _ = QFileDialog.getSaveFileName(self, self.tr('Report'), workspace, 'Excel(*.xlsx)',
790
                                                      options=options)
791

    
792
                template = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME, 'Report_Template.xlsx')
793
                if name and os.path.exists(template):
794
                    wb = openpyxl.load_workbook(template)
795
                    ws = wb.active
796
                    cal_image = openpyxl.drawing.image.Image(image_path)
797
                    x_scale, y_scale = 1, 1
798
                    cal_image.width *= x_scale
799
                    cal_image.height *= y_scale
800
                    ws.add_image(cal_image, 'C4')
801
                    wb.save(filename=name)
802

    
803
                    QMessageBox.information(self, self.tr('Information'), self.tr('Report is done'))
804
        except Exception as ex:
805
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
806
                                                           sys.exc_info()[-1].tb_lineno)
807
            self.addMessage.emit(MessageType.Error, message)
808

    
809
    def display_loops(self, loops):
810
        """ display loops """
811
        drawing = AppDocData.instance().activeDrawing
812
        if drawing is None: return
813

    
814
        if loops:
815
            self.tableWidgetLoop.clear()
816
            self.tableWidgetLoop.setColumnCount(len(loops) * 4)
817

    
818
            _col_names = [[loop.name, 'pressure', 'Static\nLine\ndP_Eq', 'El.\nDensity\nEl.'] for loop in loops]
819
            col_names = []
820
            for col_name in _col_names: col_names.extend(col_name)
821
            self.tableWidgetLoop.setHorizontalHeaderLabels(col_names)
822
            self.tableWidgetLoop.horizontalHeader().setVisible(True)
823

    
824
            max_rows = 0
825
            for col in range(len(loops)):
826
                rows = len(loops[col].items)
827
                max_rows = max(max_rows, rows)
828
                self.tableWidgetLoop.setRowCount(max_rows)
829

    
830
                for row in range(len(loops[col].items)):
831
                    item = QTableWidgetItem(str(loops[col].items[row]))
832
                    item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
833
                    self.tableWidgetLoop.setItem(row, col * 4, item)
834

    
835
                # display calcuation values
836
                for row in range(len(loops[col].items)):
837
                    if loops[col].items[row] in loops[col].pressures:
838
                        item = QTableWidgetItem(str(loops[col].pressures[loops[col].items[row]]))
839
                        if not loops[col].pressures[loops[col].items[row]]: item.setBackground(Qt.red)
840
                        self.tableWidgetLoop.setItem(row, col * 4 + 1, item)
841

    
842
                    if loops[col].items[row] in loops[col].pressure_drops:
843
                        item = QTableWidgetItem(str(loops[col].pressure_drops[loops[col].items[row]]))
844
                        if not loops[col].pressure_drops[loops[col].items[row]]: item.setBackground(Qt.red)
845
                        self.tableWidgetLoop.setItem(row, col * 4 + 2, item)
846

    
847
                    if loops[col].items[row] in loops[col].density_elevations:
848
                        item = QTableWidgetItem(str(loops[col].density_elevations[loops[col].items[row]]))
849
                        if not loops[col].density_elevations[loops[col].items[row]]: item.setBackground(Qt.red)
850
                        self.tableWidgetLoop.setItem(row, col * 4 + 3, item)
851

    
852
            self.tableWidgetLoop.resizeColumnsToContents()
853
            self.tableWidgetLoop.resizeRowsToContents()
854

    
855
    '''
856
        @brief  configuration
857
    '''
858

    
859
    def configuration(self):
860
        from ConfigurationDialog import QConfigurationDialog
861
        try:
862
            appDocData = AppDocData.instance()
863
            if appDocData.activeDrawing is None:
864
                self.showImageSelectionMessageBox()
865
                return
866

    
867
            dlg = QConfigurationDialog(self)
868
            (isAccepted, isDataConversion, decimal) = dlg.showDialog()
869
            if isAccepted == True:
870
                if isDataConversion == True:
871
                    self.data_conversion(decimal)
872
                else:
873
                    self.reload_units()
874

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

    
880
    def data_conversion(self, decimal):
881
        from Drawing import Drawing
882
        from Calculation import Conversion
883

    
884
        try:
885
            Conversion(decimal)
886

    
887
            self.load_HMB()
888
            self.reload_units()
889

    
890
        except Exception as ex:
891
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
892
                                                           sys.exc_info()[-1].tb_lineno)
893
            self.addMessage.emit(MessageType.Error, message)
894

    
895
    '''
896
        @brief  Show Image Selection Guide MessageBox
897
        @author Jeongwoo
898
        @date   2018.05.02
899
    '''
900

    
901
    def showImageSelectionMessageBox(self):
902
        QMessageBox.information(self, self.tr("Notice"), self.tr("First select image drawing"))
903

    
904
    def display_colors(self, value):
905
        """ display colors """
906
        from DisplayColors import DisplayColors
907
        from DisplayColors import DisplayOptions
908

    
909
        DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value == True else DisplayOptions.DisplayByLineType
910
        if hasattr(self, 'graphicsView'):
911
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
912
            DisplayColors.instance().save_data()
913

    
914
    '''
915
        @brief      Open Border file 
916
        @author     yeonjin
917
        @date       2019.07.10
918
    '''
919

    
920
    def open_border_file(self):
921
        app_doc_data = AppDocData.instance()
922
        borderFile = app_doc_data.border_file_path
923
        if not os.path.exists(borderFile):
924
            self.create_border_file(borderFile)
925

    
926
        self.graphicsView.loadImageFromFile(fileName=borderFile)
927

    
928
    '''
929
        @brief      Create Border file 
930
        @author     yeonjin
931
        @date       2019.07.10
932
    '''
933

    
934
    def create_border_file(self, border):
935

    
936
        from PIL import Image
937
        # A4 size : 210, 297
938
        # A3 size : 297, 420
939
        # A2 size : 420, 594
940
        # A1 size : 594, 841
941
        # A0 size : 841, 1189
942
        # color : 0, 128, 128 진한 청록
943
        # color : 255, 255, 255 White
944
        img = Image.new('RGBA', (1189, 841), (255, 255, 255))
945
        img.save(border)
946

    
947
    def setAttributes(self, drawing):
948
        drawing.setAttributes()
949

    
950
    '''
951
        @brief      Reload HMB Units 
952
        @author     yeonjin
953
        @date       2019.07.10
954
    '''
955

    
956
    def reload_units(self):
957
        from Drawing import Drawing
958

    
959
        try:
960
            app_doc_data = AppDocData.instance()
961
            drawing = app_doc_data.activeDrawing
962

    
963
            self.setAttributes(drawing)
964

    
965
            columnInfos = app_doc_data.getHMBDisplayNameAndUnitsExpression()
966

    
967
            rowIndex = 0
968
            for columnInfo in columnInfos:
969
                name = columnInfo[0]
970
                unit = self.convertToUnits(columnInfo[1])
971

    
972
                self.tableWidgetHMB.setItem(rowIndex, 0,
973
                                            self.setTableWidgetItemProperties(name, Qt.AlignLeft | Qt.AlignVCenter,
974
                                                                              QColor(51, 153,
975
                                                                                     102)))
976
                # QColor(230, 230, 230)))
977
                self.tableWidgetHMB.setItem(rowIndex, 1,
978
                                            self.setTableWidgetItemProperties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
979
                                                                              QColor(204, 255, 204)))
980
                # QColor(230, 230, 230)))
981

    
982
                rowIndex += 1
983

    
984
            self.tableWidgetHMB.resizeColumnsToContents()
985
            self.tableWidgetHMB.resizeRowsToContents()
986

    
987
        except Exception as ex:
988
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
989
                                                           sys.exc_info()[-1].tb_lineno)
990
            self.addMessage.emit(MessageType.Error, message)
991

    
992
    def load_data(self, drawing):
993
        """ load data from drawing """
994
        from Drawing import Drawing
995

    
996
        try:
997
            app_doc_data = AppDocData.instance()
998

    
999
            ## Set appDocData
1000
            app_doc_data.clear()
1001
            self.onCommandRejected()
1002

    
1003
            app_doc_data.activeDrawing = drawing
1004

    
1005
            self.setAttributes(drawing)
1006
            self.setMainWindowTitle(drawing.path)
1007
            self.initTableWidgetHMB()
1008
            self.clear_loop()
1009
            self.clearlogs()
1010
            ## Load data on database     
1011

    
1012
            self.symbolTreeWidget.initSymbolTreeWidget()
1013

    
1014
            components = app_doc_data.getComponentListByDrawingUID(drawing)
1015
            count = len(components)
1016

    
1017
            if count > 0:
1018
                try:
1019
                    self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100,
1020
                                                    self) if not hasattr(self, 'progress') else self.progress
1021
                    self.progress.setWindowModality(Qt.WindowModal)
1022
                    self.progress.setAutoReset(True)
1023
                    self.progress.setAutoClose(True)
1024
                    self.progress.setMinimum(0)
1025
                    self.progress.resize(600, 100)
1026
                    self.progress.setWindowTitle(self.tr("Load data..."))
1027
                    self.progress.show()
1028

    
1029
                    self.load_components(components)
1030

    
1031
                    self.load_HMB()
1032
                finally:
1033
                    self.progress.setValue(self.progress.maximum())
1034
                    self.progress.hide()
1035

    
1036
            # self.changeViewCheckedState(False)
1037

    
1038
        except Exception as ex:
1039
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1040
                                                           sys.exc_info()[-1].tb_lineno)
1041
            self.addMessage.emit(MessageType.Error, message)
1042

    
1043
    def saveAs_drawing(self, sourceDb):
1044
        import uuid
1045
        from shutil import copyfile
1046
        from datetime import datetime
1047
        from Drawing import Drawing
1048

    
1049
        workspace = self.getWorkSpace()
1050

    
1051
        options = QFileDialog.Options()
1052
        options |= QFileDialog.DontUseNativeDialog
1053
        name, _ = QFileDialog.getSaveFileName(self, self.tr('Save As'), workspace, 'HYTOS Files (*.hytos)',
1054
                                              options=options)
1055
        if name:
1056
            if os.path.splitext(name)[1] != '.hytos': name += '.hytos'
1057

    
1058
            app_doc_data = AppDocData.instance()
1059
            # copy template.db to name
1060
            copyfile(sourceDb, name)
1061

    
1062
            matches = [drawing for drawing in app_doc_data.getDrawings() if
1063
                       os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
1064
            if not matches:
1065
                drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
1066
                app_doc_data.saveDrawing(drawing)
1067
            else:
1068
                drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
1069
                app_doc_data.updateDrawing(drawing)
1070

    
1071
            self.load_drawing_list()
1072
            self.open_border_file()
1073
            self.load_data(drawing)
1074

    
1075
    '''
1076
        @brief      create new drawing
1077
        @author     yeonjin
1078
        @date       2019.07.03
1079
    '''
1080

    
1081
    def new_drawing(self):
1082
        import uuid
1083
        from shutil import copyfile
1084
        from datetime import datetime
1085
        from Drawing import Drawing
1086

    
1087
        workspace = self.getWorkSpace()
1088

    
1089
        options = QFileDialog.Options()
1090
        options |= QFileDialog.DontUseNativeDialog
1091
        name, _ = QFileDialog.getSaveFileName(self, self.tr('New'), workspace, 'HYTOS Files (*.hytos)', options=options)
1092
        if name:
1093

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

    
1096
            app_doc_data = AppDocData.instance()
1097
            # copy template.db to name
1098
            copyfile(app_doc_data.getTemplateDbPath(), name)
1099

    
1100
            matches = [drawing for drawing in app_doc_data.getDrawings() if
1101
                       os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
1102
            if not matches:
1103
                drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
1104
                app_doc_data.saveDrawing(drawing)
1105
            else:
1106
                drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
1107
                app_doc_data.updateDrawing(drawing)
1108

    
1109
            self.load_drawing_list()
1110
            self.open_border_file()
1111
            self.load_data(drawing)
1112

    
1113
    def on_open_drawing(self):
1114
        """ open selected drawing by user """
1115
        workspace = self.getWorkSpace()
1116

    
1117
        options = QFileDialog.Options()
1118
        options |= QFileDialog.DontUseNativeDialog
1119
        name, _ = QFileDialog.getOpenFileName(self, self.tr('Open'), workspace, 'HYTOS File(*.hytos)', options=options)
1120
        if name: self.open_drawing(name)
1121

    
1122
    def open_drawing(self, name):
1123
        """ open given drawing has name """
1124
        import uuid
1125
        from Drawing import Drawing
1126
        from datetime import datetime
1127

    
1128
        app_doc_data = AppDocData.instance()
1129
        drawings = app_doc_data.getDrawings()
1130
        matches = [drawing for drawing in drawings if os.path.samefile(drawing.path, name)]
1131
        if not matches:
1132
            drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
1133
            app_doc_data.saveDrawing(drawing)
1134

    
1135
            self.load_drawing_list()
1136
        else:
1137
            drawing = matches[0]
1138

    
1139
        self.open_border_file()
1140
        self.load_data(drawing)
1141

    
1142
    def getWorkSpace(self):
1143
        """ get work space path """
1144
        app_doc_data = AppDocData.instance()
1145

    
1146
        configs = app_doc_data.getAppConfigs('option', 'WorkSpace')
1147
        if configs and len(configs) == 1:
1148
            return configs[0].value
1149
        else:
1150
            return os.getcwd()
1151

    
1152
    def changeViewCheckedState(self, checked, clear=True):
1153
        '''
1154
            @brief      change view checked state
1155
            @author     euisung
1156
            @date       2019.03.06
1157
        '''
1158
        if clear:
1159
            self.initTableWidgetHMB()
1160
            # self.clear_data()
1161

    
1162
    '''
1163
        @brief      create a line
1164
        @author     humkyung
1165
        @history    Jeongwoo 2018.05.10 Change method for Checkable action
1166
    '''
1167

    
1168
    def onPlaceLine(self):
1169
        self.actionLine.setChecked(True)
1170
        if not hasattr(self.actionLine, 'tag'):
1171
            self.actionLine.tag = PlaceStreamlineCommand.PlaceStreamlineCommand(self.graphicsView)
1172
            self.actionLine.tag.onSuccess.connect(self.onLineCreated)
1173
            self.actionLine.tag.onRejected.connect(self.onCommandRejected)
1174

    
1175
        self.graphicsView.command = self.actionLine.tag
1176

    
1177
    '''
1178
        @brief      add created lines to scene
1179
        @author     humkyung
1180
        @date       2018.07.23
1181
    '''
1182

    
1183
    def onLineCreated(self):
1184
        try:
1185
            count = len(self.actionLine.tag.streamline._vertices)
1186
            if count > 1:
1187
                self.add_hmb_data(self.actionLine.tag.streamline)
1188
                self.actionLine.tag.streamline.transfer.onRemoved.connect(self.on_item_removed)
1189
                self.load_HMB()
1190
        finally:
1191
            self.actionLine.tag.reset()
1192

    
1193
    def on_stream_line_deleted(self, stream_line):
1194
        """ callback after stream line is deleted """
1195
        app_doc_data = AppDocData.instance()
1196
        activeDrawing = app_doc_data.activeDrawing
1197
        if activeDrawing:
1198
            activeDrawing.hmbTable.deleteByUID(stream_line.uid)
1199

    
1200
        self.load_HMB()
1201

    
1202
    def add_hmb_data(self, stream_line):
1203
        """ add a new hmb data associated with given stream line """
1204
        from HMBTable import HMBTable
1205
        import uuid
1206

    
1207
        try:
1208
            drawing = AppDocData.instance().activeDrawing
1209
            if drawing:
1210
                components_uid = stream_line.uid
1211
                stream_no = self.get_next_stream_no(drawing)
1212
                stream_line.stream_no = stream_no
1213
                drawing.hmbTable.add(components_uid, stream_no)
1214
        except Exception as ex:
1215
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1216
                                                           sys.exc_info()[-1].tb_lineno)
1217
            self.addMessage.emit(MessageType.Error, message)
1218

    
1219
    def get_next_stream_no(self, drawing):
1220

    
1221
        if len(list(drawing.hmbTable.streamNos())) == 0:
1222
            return 1
1223
        else:
1224
            streamNos = sorted(list(drawing.hmbTable.streamNos()))
1225
            lastStreamNo = streamNos[-1]
1226
            return lastStreamNo + 1
1227

    
1228
    def clear_HMB(self):
1229
        self.tableWidgetHMB.clearContents()
1230
        self.tableWidgetHMB.setColumnCount(0)
1231

    
1232
    def load_HMB(self):
1233
        drawing = AppDocData.instance().activeDrawing
1234
        if drawing is None: return
1235

    
1236
        hmbs = drawing.hmbTable._hmbs
1237
        if hmbs is not None:
1238
            self.tableWidgetHMB.setColumnCount(2)
1239

    
1240
            col_names = ['Stream No.', 'Unit']
1241
            for hmb in hmbs:
1242
                columnCount = self.tableWidgetHMB.columnCount()
1243
                self.tableWidgetHMB.setColumnCount(columnCount + 1)
1244
                col_names.append(str(hmb.stream_no))
1245

    
1246
                self.tableWidgetHMB.setItem(0, columnCount, self.setTableWidgetItemProperties(hmb.uid,
1247
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1248
                self.tableWidgetHMB.setItem(1, columnCount, self.setTableWidgetItemProperties(hmb.components_uid,
1249
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1250
                self.tableWidgetHMB.setItem(2, columnCount, self.setTableWidgetItemProperties(hmb.stream_no,
1251
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1252
                self.tableWidgetHMB.setItem(3, columnCount, self.setTableWidgetItemProperties(hmb.phase_type,
1253
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1254
                self.tableWidgetHMB.setItem(4, columnCount, self.setTableWidgetItemProperties(hmb.flowrate_mass,
1255
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1256
                self.tableWidgetHMB.setItem(5, columnCount, self.setTableWidgetItemProperties(hmb.flowrate_volume,
1257
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1258
                self.tableWidgetHMB.setItem(6, columnCount, self.setTableWidgetItemProperties(hmb.density,
1259
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1260
                self.tableWidgetHMB.setItem(7, columnCount, self.setTableWidgetItemProperties(hmb.viscosity,
1261
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1262
                self.tableWidgetHMB.setItem(8, columnCount, self.setTableWidgetItemProperties(hmb.temperature,
1263
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1264
                self.tableWidgetHMB.setItem(9, columnCount, self.setTableWidgetItemProperties(hmb.molecular_weight,
1265
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1266
                self.tableWidgetHMB.setItem(10, columnCount, self.setTableWidgetItemProperties(hmb.specific_heat_ratio,
1267
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1268
                self.tableWidgetHMB.setItem(11, columnCount, self.setTableWidgetItemProperties(hmb.compress_factor,
1269
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1270
                self.tableWidgetHMB.setItem(12, columnCount, self.setTableWidgetItemProperties(hmb.nominal_pipe_size,
1271
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1272
                self.tableWidgetHMB.setItem(13, columnCount, self.setTableWidgetItemProperties(hmb.inside_pipe_size,
1273
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1274
                self.tableWidgetHMB.setItem(14, columnCount, self.setTableWidgetItemProperties(hmb.schedule_no,
1275
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1276
                self.tableWidgetHMB.setItem(15, columnCount, self.setTableWidgetItemProperties(hmb.straight_length,
1277
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1278
                self.tableWidgetHMB.setItem(16, columnCount, self.setTableWidgetItemProperties(hmb.equivalent_length,
1279
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1280

    
1281
                self.tableWidgetHMB.setItem(17, columnCount,
1282
                                            self.setTableWidgetItemProperties(hmb.equivalent_length_input,
1283
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1284
                self.tableWidgetHMB.setItem(18, columnCount, self.setTableWidgetItemProperties(hmb.fitting_length,
1285
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1286
                self.tableWidgetHMB.setItem(19, columnCount, self.setTableWidgetItemProperties(hmb.fitting_K,
1287
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1288
                self.tableWidgetHMB.setItem(20, columnCount,
1289
                                            self.setTableWidgetItemProperties(hmb.equivalent_length_cal,
1290
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1291
                self.tableWidgetHMB.setItem(21, columnCount, self.setTableWidgetItemProperties(hmb.roughness,
1292
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1293
                self.tableWidgetHMB.setItem(22, columnCount, self.setTableWidgetItemProperties(hmb.limitation_velocity,
1294
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1295
                self.tableWidgetHMB.setItem(23, columnCount,
1296
                                            self.setTableWidgetItemProperties(hmb.limitation_pressure_drop,
1297
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1298

    
1299
                self.tableWidgetHMB.setItem(24, columnCount, self.setTableWidgetItemProperties(None,
1300
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter,
1301
                                                                                               QColor(153, 204, 255)))
1302

    
1303
                self.tableWidgetHMB.setItem(25, columnCount, self.setTableWidgetItemProperties(hmb.velocity,
1304
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1305
                self.tableWidgetHMB.setItem(26, columnCount, self.setTableWidgetItemProperties(hmb.reynolds,
1306
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1307
                self.tableWidgetHMB.setItem(27, columnCount, self.setTableWidgetItemProperties(hmb.friction_factor,
1308
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1309
                self.tableWidgetHMB.setItem(28, columnCount, self.setTableWidgetItemProperties(hmb.pressure_drop,
1310
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1311
                self.tableWidgetHMB.setItem(29, columnCount,
1312
                                            self.setTableWidgetItemProperties(hmb.pressure_drop_friction,
1313
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1314
                self.tableWidgetHMB.setItem(30, columnCount, self.setTableWidgetItemProperties(hmb.pressure_drop_static,
1315
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1316
                self.tableWidgetHMB.setItem(31, columnCount,
1317
                                            self.setTableWidgetItemProperties(hmb.pressure_pipe_end_point,
1318
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1319
                self.tableWidgetHMB.setItem(32, columnCount, self.setTableWidgetItemProperties(hmb.power,
1320
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1321

    
1322
                if hmb.isDeleted: self.tableWidgetHMB.hideColumn(columnCount)
1323

    
1324
            self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
1325

    
1326
            self.tableWidgetHMB.resizeColumnsToContents()
1327
            self.tableWidgetHMB.resizeRowsToContents()
1328

    
1329
    '''
1330
        @brief      refresh scene
1331
        @author     humkyung
1332
        @date       2018.07.23
1333
    '''
1334

    
1335
    def onCommandRejected(self, cmd=None):
1336
        try:
1337
            if type(cmd) is PlaceStreamlineCommand.PlaceStreamlineCommand:
1338
                if self.actionLine.tag.streamline:
1339
                    self.graphicsView.scene.removeItem(self.actionLine.tag.streamline)
1340
                self.graphicsView.scene.update()
1341
                self.actionLine.tag.reset()
1342

    
1343
                self.actionLine.setChecked(False)
1344
            elif type(cmd) is AreaZoomCommand.AreaZoomCommand:
1345
                self.actionZoom.setChecked(False)
1346
            else:
1347
                if hasattr(self.actionLine, 'tag') and self.actionLine.tag.streamline:
1348
                    self.graphicsView.scene.removeItem(self.actionLine.tag.streamline)
1349
                    self.graphicsView.scene.update()
1350
                    self.actionLine.tag.reset()
1351

    
1352
                self.actionLine.setChecked(False)
1353
                self.actionZoom.setChecked(False)
1354
        finally:
1355
            self.graphicsView.useDefaultCommand()
1356

    
1357
    '''
1358
        @brief      restore to default command when user press Escape key
1359
        @author     humkyung 
1360
        @date       2018.08.09
1361
        
1362
    '''
1363

    
1364
    def keyPressEvent(self, event):
1365
        try:
1366
            if event.key() == Qt.Key_Escape:
1367
                # already catched in command
1368
                pass
1369
                # checked = self.actionGroup.checkedAction()
1370
                # if checked:
1371
                #    checked.setChecked(False)
1372
                #    self.graphicsView.useDefaultCommand()                                                           
1373

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

    
1380
    '''
1381
        @brief      remove item from tree widget and then remove from scene
1382
        @date       2018.05.25
1383
        @author     Jeongwoo
1384
    '''
1385

    
1386
    def on_item_removed(self, item):
1387
        try:
1388
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'connectors') and \
1389
                       [connector for connector in _item.connectors if
1390
                        connector.connectedItem is not None and connector.connectedItem.parentItem() is item]]
1391
            for match in matches:
1392
                for connector in match.connectors:
1393
                    if connector.connectedItem is item: connector.connect(None)
1394

    
1395
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'owner')]
1396
            for match in matches:
1397
                if match.owner is item:
1398
                    match.owner = None
1399

    
1400
            matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'attrs')]
1401
            done = False
1402
            for match in matches:
1403
                for assoc in match.associations():
1404
                    if item is assoc:
1405
                        match.remove_assoc_item(item)
1406
                        for attr in match.attrs.keys():
1407
                            if str(item.uid) == str(attr.AssocItem.uid):
1408
                                attr.AssocItem = None
1409
                                match.attrs[attr] = ''
1410
                                done = True
1411
                                break
1412
                        break
1413
                if done: break
1414

    
1415
            if type(item) is QEngineeringStreamlineItem:
1416
                self.on_stream_line_deleted(item)
1417

    
1418
            if item.scene() is not None:
1419
                item.scene().removeItem(item)
1420
                del item
1421
        except Exception as ex:
1422
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1423
                                                           sys.exc_info()[-1].tb_lineno)
1424
            self.addMessage.emit(MessageType.Error, message)
1425

    
1426
    '''
1427
        @brief      load components
1428
        @author     yeonjin
1429
        @date       2019.07.30.
1430
    '''
1431

    
1432
    def load_components(self, componentsUID):
1433
        from EngineeringStreamlineItem import QEngineeringStreamlineItem
1434
        from EngineeringConnectorItem import QEngineeringConnectorItem
1435

    
1436
        try:
1437
            app_doc_data = AppDocData.instance()
1438

    
1439
            maxValue = len(componentsUID)
1440
            self.progress.setMaximum(maxValue)
1441

    
1442
            for componentUID in componentsUID:
1443
                componentInfos = app_doc_data.getComponentByComponentUID(componentUID)
1444
                if (len(componentInfos)) > 0:
1445
                    category = componentInfos[0][3]  # Category@SymbolType
1446

    
1447
                    if category == 'Stream Line':
1448
                        item = QEngineeringStreamlineItem.fromDatabase(componentInfos)
1449
                        if item is not None:
1450
                            item.transfer.onRemoved.connect(self.on_item_removed)
1451
                            self.graphicsView.scene.addItem(item)
1452
                    else:
1453
                        item = SymbolSvgItem.fromDatabase(componentInfos)
1454
                        if item is not None:
1455
                            item.transfer.onRemoved.connect(self.on_item_removed)
1456
                            app_doc_data.symbols.append(item)
1457
                            self.addSvgItemToScene(item)
1458

    
1459
                    self.progress.setValue(self.progress.value() + 1)
1460

    
1461
                QApplication.processEvents()
1462

    
1463
            # """ update scene """
1464
            self.graphicsView.scene.update(self.graphicsView.sceneRect())
1465
            for item in self.graphicsView.scene.items():
1466
                item.setVisible(True)
1467

    
1468
        except Exception as ex:
1469
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
1470
                                                           sys.exc_info()[-1].tb_lineno)
1471
            self.addMessage.emit(MessageType.Error, message)
1472
        finally:
1473
            pass
1474

    
1475
    '''
1476
        @brief      Remove added item on same place and Add GraphicsItem
1477
        @author     Jeongwoo
1478
        @date       2018.05.25
1479
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
1480
                    2018.06.18  Jeongwoo    Set Z-index
1481
    '''
1482

    
1483
    def addSvgItemToScene(self, svgItem):
1484
        svgItem.addSvgItemToScene(self.graphicsView.scene)
1485

    
1486
    '''
1487
        @brief      Remove added item on same place and Add GraphicsItem
1488
        @author     Jeongwoo
1489
        @date       2018.05.25
1490
        @history    2018.05.29  Jeongwoo    Moved from QRecognitionDialog
1491
                    2018.06.05  Jeongwoo    Remove Size condition
1492
                    2018.06.18  Jeongwoo    Set Z-index
1493
    '''
1494

    
1495
    def addTextItemToScene(self, textItem):
1496
        textItem.addTextItemToScene(self.graphicsView.scene)
1497

    
1498
    '''
1499
        @brief      Remove added item on same place and Add GraphicsItem
1500
        @author     Jeongwoo
1501
        @date       2018.05.29
1502
        @history    2018.06.18  Jeongwoo    Set Z-index
1503
    '''
1504

    
1505
    def addLineItemToScene(self, lineItem):
1506
        self.graphicsView.scene.addItem(lineItem)
1507

    
1508
    '''
1509
        @brief      Check Number
1510
        @author     kyouho
1511
        @date       2018.08.20
1512
    '''
1513

    
1514
    def isNumber(self, num):
1515
        p = re.compile('(^[0-9]+$)')
1516
        result = p.match(num)
1517

    
1518
        if result:
1519
            return True
1520
        else:
1521
            return False
1522

    
1523
    '''
1524
        @brief      find overlap Connector
1525
        @author     kyouho
1526
        @date       2018.08.28
1527
    '''
1528

    
1529
    def findOverlapConnector(self, connectorItem):
1530
        from shapely.geometry import Point
1531
        from EngineeringConnectorItem import QEngineeringConnectorItem
1532
        itemList = []
1533

    
1534
        x = connectorItem.center()[0]
1535
        y = connectorItem.center()[1]
1536

    
1537
        connectors = [item for item in self.graphicsView.scene.items() if
1538
                      type(item) is QEngineeringConnectorItem and item != connectorItem]
1539
        for connector in connectors:
1540
            if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5:
1541
                itemList.append(connector.parent)
1542

    
1543
        return itemList
1544

    
1545
    def setTableWidgetItemProperties(self, name, alignment, color=None):
1546
        if name is None:
1547
            name = ''
1548

    
1549
        item = QTableWidgetItem(str(name))
1550
        item.setTextAlignment(alignment)
1551
        if color:
1552
            item.setBackground(color)
1553

    
1554
        return item
1555

    
1556

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