프로젝트

일반

사용자정보

개정판 517925eb

ID517925ebc7681590c5b974042031a8ee6fb4c936
상위 a3da2d97
하위 c891962f

김연진이(가) 약 5년 전에 추가함

issue #1058 : 계산 후 결과 표시 - 메인화면

Change-Id: I1e808f4f7ad02ea64e05d9af5bc86574416aa8aa

차이점 보기:

HYTOS/HYTOS/Commands/HydroCalculationCommand.py
1 1
import os.path
2 2
import sys
3 3
import AbstractCommand
4

  
4 5
try:
5 6
    from PyQt5.QtCore import *
6 7
    from PyQt5.QtGui import *
......
8 9
except ImportError:
9 10
    try:
10 11
        from PyQt4.QtCore import Qt, QPoint, QPointF, QRectF, pyqtSignal, QT_VERSION_STR, QMimeData
11
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QColor, QPen, QBrush, QCursor
12
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QColor, QPen, \
13
            QBrush, QCursor
12 14
    except ImportError:
13 15
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
14 16

  
17

  
15 18
class HydroCalculationCommand(AbstractCommand.AbstractCommand):
16 19
    """ Hydro Calculation class """
17 20

  
......
19 22

  
20 23
    def __init__(self, imageViewer):
21 24
        super(HydroCalculationCommand, self).__init__(imageViewer)
22
        self.name = 'HydroCalculation' 
25
        self.name = 'HydroCalculation'
23 26

  
24 27
        self.loops = []
25 28

  
......
39 42
            pressurized = [item for item in self.imageViewer.scene.items() if type(item) is SymbolSvgItem and
40 43
                           self.is_loop_end_item(item)]
41 44
            for item in pressurized:
42
                matches = [conn for conn in item.connectors if conn.connectedItem and int(conn.connectedItem._conn_index) == 1]
45
                matches = [conn for conn in item.connectors if
46
                           conn.connectedItem and int(conn.connectedItem._conn_index) == 1]
43 47
                for match in matches:
44 48
                    queue.append(QEngineeringLoopItem([match]))
45 49

  
......
59 63
            """ update pressure drop and pressure of stream data """
60 64
            app_doc_data = AppDocData.instance()
61 65
            for hmb in app_doc_data.activeDrawing.hmbTable._hmbs:
62
                matches = [loop for loop in self.loops if [item for item in loop.items if str(item.uid) == str(hmb.components_uid)]]
66
                matches = [loop for loop in self.loops if
67
                           [item for item in loop.items if str(item.uid) == str(hmb.components_uid)]]
63 68
                if matches:
64
                    indices = [index for index in range(len(matches[0].items)) if str(matches[0].items[index].uid) == str(hmb.components_uid)]
69
                    indices = [index for index in range(len(matches[0].items)) if
70
                               str(matches[0].items[index].uid) == str(hmb.components_uid)]
65 71
                    if indices:
66 72
                        if hmb.phase_type == 'Vapor':
67 73
                            hmb.pressure_drop_friction = matches[0].pressure_drops[matches[0].items[indices[0]]]
68 74
                            hmb.density = matches[0].density_elevations[matches[0].items[indices[0]]]
69
                            hmb.pressure_drop = round(matches[0].pressure_drops[matches[0].items[indices[0]]] / hmb.equivalent_length * 100, 3)
75
                            hmb.pressure_drop = round(
76
                                matches[0].pressure_drops[matches[0].items[indices[0]]] / hmb.equivalent_length * 100,
77
                                3)
70 78
                        hmb.pressure_drop_static = matches[0].pressure_drops[matches[0].items[indices[0] - 1]]
71 79
                        hmb.pressure_pipe_end_point = matches[0].pressures[matches[0].items[indices[0] + 1]]
72 80

  
......
74 82
            from App import App
75 83
            from AppDocData import MessageType
76 84

  
77
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
78
            App.mainWnd().addMessage.emit(MessageType.Error, message)            
85
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
86
                                                           sys.exc_info()[-1].tb_lineno)
87
            App.mainWnd().addMessage.emit(MessageType.Error, message)
79 88

  
80 89
    def make_loop(self, loop):
81 90
        """ make a loop """
......
92 101
                        (type(loop.items[-1].parentItem()) is SymbolSvgItem):
93 102
                    # start at connector
94 103
                    if loop.items[-1].connectedItem and int(loop.items[-1].connectedItem._conn_index) == 1:
95
                        loop.items.append(loop.items[-1].connectedItem.parentItem())    # it should be streamline
104
                        loop.items.append(loop.items[-1].connectedItem.parentItem())  # it should be streamline
96 105
                        if type(loop.items[-1]) is QEngineeringStreamlineItem:
97
                            matches = [conn.connectedItem for conn in loop.items[-1].connectors if int(conn._conn_index) == 2 and conn.connectedItem]
106
                            matches = [conn.connectedItem for conn in loop.items[-1].connectors if
107
                                       int(conn._conn_index) == 2 and conn.connectedItem]
98 108
                            if matches:
99 109
                                loop.items.append(matches[0])
100 110
                                if self.is_loop_end_item(matches[0].parentItem()):
......
103 113
                                break
104 114
                    # end at connector
105 115
                    elif loop.items[-1].connectedItem and int(loop.items[-1].connectedItem._conn_index) == 2:
106
                        matches = [conn for conn in loop.items[-1].parentItem().connectors if (not conn in loop.items) and conn.connectedItem and int(conn.connectedItem._conn_index) == 1]
116
                        matches = [conn for conn in loop.items[-1].parentItem().connectors if
117
                                   (not conn in loop.items) and conn.connectedItem and int(
118
                                       conn.connectedItem._conn_index) == 1]
107 119
                        if matches:
108 120
                            for match in matches[1:]:
109 121
                                res.append(QEngineeringLoopItem(loop.items + [match]))
......
113 125
        except Exception as ex:
114 126
            from App import App
115 127
            from AppDocData import MessageType
116
                        
117
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
128

  
129
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
130
                                                           sys.exc_info()[-1].tb_lineno)
118 131
            App.mainWnd().addMessage.emit(MessageType.Error, message)
119 132
        finally:
120 133
            loop.name = 'Loop{}'.format(len(self.loops) + 1)
......
126 139
        pass
127 140

  
128 141
    def redo(self):
129
        pass
142
        pass
HYTOS/HYTOS/MainWindow.py
36 36
import uuid
37 37

  
38 38

  
39
def set_table_widget_item_properties(name, alignment, color=None):
40
    if name is None:
41
        name = ''
42

  
43
    item = QTableWidgetItem(str(name))
44
    item.setTextAlignment(alignment)
45
    if color:
46
        item.setBackground(color)
47

  
48
    return item
49

  
50

  
39 51
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane):
40 52
    """ This is MainWindow class """
41 53
    addMessage = pyqtSignal(Enum, str)
......
309 321
        self.treeWidgetDrawingList.header().setSectionResizeMode(2, QHeaderView.ResizeToContents)
310 322
        self.treeWidgetDrawingList.hideColumn(2)
311 323

  
324
    def clear_output(self):
325
        self.tableWidgetLoop.setColumnCount(0)
326
        self.tableWidgetOutput.setRowCount(0)
327

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

  
......
369 385
            unit = self.convertToUnits(columnInfo[1])
370 386

  
371 387
            self.tableWidgetHMB.setItem(rowIndex, 0,
372
                                        self.setTableWidgetItemProperties(name, Qt.AlignLeft | Qt.AlignVCenter,
373
                                                                          QColor(51, 153,
388
                                        set_table_widget_item_properties(name, Qt.AlignLeft | Qt.AlignVCenter,
389
                                                                              QColor(51, 153,
374 390
                                                                                 102)))  # QColor(230, 230, 230)))
375 391
            self.tableWidgetHMB.setItem(rowIndex, 1,
376
                                        self.setTableWidgetItemProperties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
377
                                                                          QColor(204, 255,
392
                                        set_table_widget_item_properties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
393
                                                                              QColor(204, 255,
378 394
                                                                                 204)))  # QColor(230, 230, 230)))
379 395

  
380 396
            rowIndex += 1
......
760 776
                    cmd = HydroCalculationCommand(self.graphicsView)
761 777
                    cmd.execute(None)
762 778
                    self.display_loops(cmd.loops)
779
                    self.display_output(cmd.loops)
763 780

  
764 781
                    self.load_HMB()
765 782

  
......
915 932
                                                           sys.exc_info()[-1].tb_lineno)
916 933
            self.addMessage.emit(MessageType.Error, message)
917 934

  
935
    def get_barometric_pressure(self, unit):
936
        try:
937
            if unit == 'kg/cm2':
938
                barometric_pressure = 1.033
939
            elif unit == 'bar':
940
                barometric_pressure = 1.01325
941
            elif unit == 'psi':
942
                barometric_pressure = 14.7
943
            elif unit == 'mmHg':
944
                barometric_pressure = 760
945
            elif unit == 'kPa':
946
                barometric_pressure = 101.325
947
            elif unit == 'MPa':
948
                barometric_pressure = 0.101325
949

  
950
            return barometric_pressure
951

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

  
957
    def comp_hydp_hy(self, flowrate_mass, density, diff_p, units):
958
        hydp_den = density
959

  
960
        # 질량유량은 모두 kg/min으로 맞춰야 함
961
        flowrate_mass_unit = units['Flowrate_Mass']
962
        if flowrate_mass_unit == 'kg/h':
963
            mass_4_hydp = flowrate_mass / 60
964
        elif flowrate_mass_unit == 'g/min':
965
            mass_4_hydp = flowrate_mass / 1000
966
        elif flowrate_mass_unit == 'lb/h':
967
            mass_4_hydp = flowrate_mass / 60 * 2.20462
968
        elif flowrate_mass_unit == 't/h':
969
            mass_4_hydp = flowrate_mass / 60 * 1000
970

  
971
        density_unit = units['Density']
972
        if density_unit == 'kg/m3':
973
            com_q = mass_4_hydp / hydp_den
974
        elif density_unit == 'lb/ft3':
975
            com_q = mass_4_hydp / hydp_den * 2.20462 / 3.28 ** 3
976

  
977
        density_unit = units['Density']
978
        if density_unit == 'kg/m3':
979
            com_sg = density / 1000
980
        elif density_unit == 'lb/ft3':
981
            com_sg = density * 16.0185 / 1000
982

  
983
        com_head = diff_p
984

  
985
        # 현재는 압력의 단위로 표시되어 있음
986
        pressure_unit = units['Pressure']
987
        if pressure_unit == 'kg/cm2':
988
            com_head = com_head
989
        elif pressure_unit == 'psi':
990
            com_head = com_head / 14.7 * 1.033
991
        elif pressure_unit == 'bar':
992
            com_head = com_head / 1.013 * 1.033
993
        elif pressure_unit == 'mmHg':
994
            com_head = com_head / 760 * 1.033
995
        elif pressure_unit == 'kPa':
996
            com_head = com_head / 101.325 * 1.033
997
        elif pressure_unit == 'MPa':
998
            com_head = com_head / 0.101325 * 1.033
999

  
1000
        # 현재 head는 kg/cm2으로 통일되어있음
1001
        com_head = com_head * 10 / com_sg
1002

  
1003
        hydp = 0.163 * com_sg * com_head
1004
        # 현재 hydp는 kW 임
1005

  
1006
        # 현재는 압력의 단위로 표시되어있음
1007
        power_unit = units['Power']
1008
        if power_unit == 'kW':
1009
            hydp = hydp
1010
        elif power_unit == 'kcal/h':
1011
            hydp = hydp * 860.421
1012
        elif power_unit == 'btu/h':
1013
            hydp = hydp * 3412.14
1014
        elif power_unit == 'Hp':
1015
            hydp = hydp * 1.34041
1016
        elif power_unit == 'kg.m/sec':
1017
            hydp = hydp * 737.562 / 3.28 / 2.20462
1018
        elif power_unit == 'ft.lb/sec':
1019
            hydp = hydp * 737.562
1020

  
1021
        return hydp
1022

  
1023
    def pump_hydp_hy(self, flowrate_mass, density, head, units):
1024
        hydp_den = density
1025

  
1026
        # 질량유량은 모두 kg/min으로 맞춰야 함
1027
        flowrate_mass_unit = units['Flowrate_Mass']
1028
        if flowrate_mass_unit == 'kg/h':
1029
            mass_4_hydp = flowrate_mass / 60
1030
        elif flowrate_mass_unit == 'g/min':
1031
            mass_4_hydp = flowrate_mass / 1000
1032
        elif flowrate_mass_unit == 'lb/h':
1033
            mass_4_hydp = flowrate_mass / 60 * 2.20462
1034
        elif flowrate_mass_unit == 't/h':
1035
            mass_4_hydp = flowrate_mass / 60 * 1000
1036

  
1037
        density_unit = units['Density']
1038
        if density_unit == 'kg/m3':
1039
            sg = hydp_den / 1000
1040
            q = mass_4_hydp / hydp_den
1041
        elif density_unit == 'lb/ft3':
1042
            sg = hydp_den * 16.0185 / 1000
1043
            q = mass_4_hydp / hydp_den * 2.20462 / 3.28 ** 3
1044

  
1045
        # 현재 hydp는 kW 임
1046
        hydp = 0.163 * sg * q * head
1047

  
1048
        # 현재는 압력의 단위로 표시되어있음
1049
        power_unit = units['Power']
1050
        if power_unit == 'kW':
1051
            hydp = hydp
1052
        elif power_unit == 'kcal/h':
1053
            hydp = hydp * 860.421
1054
        elif power_unit == 'btu/h':
1055
            hydp = hydp * 3412.14
1056
        elif power_unit == 'Hp':
1057
            hydp = hydp * 1.34041
1058
        elif power_unit == 'kg.m/sec':
1059
            hydp = hydp * 737.562 / 3.28 / 2.20462
1060
        elif power_unit == 'ft.lb/sec':
1061
            hydp = hydp * 737.562
1062

  
1063
        return hydp
1064

  
1065
    def pump_head_cal(self, header, density, units):
1066

  
1067
        density_unit = units['Density']
1068
        if density_unit == 'kg/m3':
1069
            sg = density / 1000
1070
        elif density_unit == 'lb/ft3':
1071
            sg = density * 16.0185 / 1000
1072

  
1073
        pressure_unit = units['Pressure']
1074
        if pressure_unit == 'kg/cm2':
1075
            header = header
1076
        elif pressure_unit == 'psi':
1077
            header = header / 14.7 * 1.033
1078
        elif pressure_unit == 'bar':
1079
            header = header / 1.013 * 1.033
1080
        elif pressure_unit == 'mmHg':
1081
            header = header / 760 * 1.033
1082
        elif pressure_unit == 'kPa':
1083
            header = header / 101.325 * 1.033
1084
        elif pressure_unit == 'MPa':
1085
            header = header / 0.101325 * 1.033
1086

  
1087
        # 현재 head는 kg/cm2으로 통일되어있음
1088
        header = header * 10 / sg
1089

  
1090
        # 현재 head는 m로 표시되어있음
1091
        length_unit = units['Length']
1092
        if length_unit == 'm':
1093
            header = header
1094
        elif length_unit == 'in':
1095
            header = header * 39.3701
1096
        elif length_unit == 'ft':
1097
            header = header * 3.28084
1098
        elif length_unit == 'yd':
1099
            header = header * 1.09361
1100
        elif length_unit == 'mile':
1101
            header = header * 0.000621371
1102
        elif length_unit == 'mm':
1103
            header = header * 1000
1104

  
1105
        return header
1106

  
1107
    def npsha_cal_hy(self, suct_p, vapo_p, density, units):
1108
        ref_baro = self.get_barometric_pressure(units['Pressure'])
1109

  
1110
        density_unit = units['Density']
1111
        if density_unit == 'kg/m3':
1112
            sg = density / 1000
1113
        elif density_unit == 'lb/ft3':
1114
            sg = density * 16.0185 / 1000
1115

  
1116
        npsha = suct_p - vapo_p
1117

  
1118
        pressure_unit = units['Pressure']
1119
        if pressure_unit == 'kg/cm2':
1120
            npsha = npsha
1121
        elif pressure_unit == 'psi':
1122
            npsha = npsha / 14.7 * 1.033
1123
        elif pressure_unit == 'bar':
1124
            npsha = npsha / 1.013 * 1.033
1125
        elif pressure_unit == 'mmHg':
1126
            npsha = npsha / 760 * 1.033
1127
        elif pressure_unit == 'kPa':
1128
            npsha = npsha / 101.325 * 1.033
1129
        elif pressure_unit == 'MPa':
1130
            npsha = npsha / 0.101325 * 1.033
1131

  
1132
        npsha = npsha + ref_baro
1133
        # 현재 npsha는 kg/cm2으로 통일되어있음
1134

  
1135
        npsha = npsha * 10 / sg
1136
        # 현재 npsha는 딱 m로 표시되어있음
1137

  
1138
        length_unit = units['Length']
1139
        if length_unit == 'm':
1140
            npsha = npsha
1141
        elif length_unit == 'in':
1142
            npsha = npsha * 39.3701
1143
        elif length_unit == 'ft':
1144
            npsha = npsha * 3.28084
1145
        elif length_unit == 'yd':
1146
            npsha = npsha * 1.09361
1147
        elif length_unit == 'mile':
1148
            npsha = npsha * 0.000621371
1149
        elif length_unit == 'mm':
1150
            npsha = npsha * 1000
1151

  
1152
        return npsha
1153

  
1154

  
1155
    def loop_streams_hy(self):
1156
        try:
1157
            pass
1158
            # self.add_data('Loop_Deviation', None, None)
1159

  
1160
        except Exception as ex:
1161
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1162
                                                           sys.exc_info()[-1].tb_lineno)
1163
            self.addMessage.emit(MessageType.Error, message)
1164

  
1165
    def loop_cv_hy(self, loops, units):
1166
        try:
1167
            for loop in loops:
1168
                indices = [index for index in range(len(loop.items)) if str(loop.items[index])[:3] == 'CV_']
1169

  
1170
                if indices:
1171
                    if len(indices) == 2:
1172
                        name = loop.items[indices[0]].parent.tag_no
1173
                        suct_p = loop.pressures[loop.items[indices[0]]]
1174
                        disc_p = loop.pressures[loop.items[indices[1]]]
1175
                        diff_p = loop.pressure_drops[loop.items[indices[0]]]
1176
                        dp_ratio = loop.extras[loop.items[indices[1]]]
1177

  
1178
                        self.add_data(name, None, None, True)
1179
                        self.add_data('Suct.P :', round(suct_p, 3), '{}.g'.format(units['Pressure']))
1180
                        self.add_data('Disc.P :', round(disc_p, 3), '{}.g'.format(units['Pressure']))
1181
                        self.add_data('Diff.P :', round(diff_p, 3), units['Pressure'])
1182
                        self.add_data('dP Ratio :', round(dp_ratio, 3) if dp_ratio else 0, '%')
1183

  
1184
        except Exception as ex:
1185
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1186
                                                           sys.exc_info()[-1].tb_lineno)
1187
            self.addMessage.emit(MessageType.Error, message)
1188

  
1189
    def loop_comps_hy(self, loops, units):
1190
        try:
1191
            for loop in loops:
1192
                indices = [index for index in range(len(loop.items)) if
1193
                           str(loop.items[index])[:3] == 'R_K' or str(loop.items[index])[:3] == 'L_K']
1194

  
1195
                if indices:
1196
                    if len(indices) == 2:
1197
                        name = loop.items[indices[0]].parent.tag_no
1198
                        suct_p = loop.pressures[loop.items[indices[0]]]
1199
                        disc_p = loop.pressures[loop.items[indices[1]]]
1200
                        diff_p = disc_p - suct_p
1201

  
1202
                        flowrate_mass = loop.items[indices[0] - 1].data.flowrate_mass
1203
                        density = loop.density_elevations[loop.items[indices[0] - 1]]
1204
                        hhp = self.comp_hydp_hy(flowrate_mass, density, diff_p, units)
1205

  
1206
                        self.add_data(name, None, None, True)
1207
                        self.add_data('Suct.P :', round(suct_p, 3), '{}.g'.format(units['Pressure']))
1208
                        self.add_data('Disc.P :', round(disc_p, 3), '{}.g'.format(units['Pressure']))
1209
                        self.add_data('Diff.P :', round(diff_p, 3), units['Pressure'])
1210
                        self.add_data('HHP :', round(hhp, 3), units['Power'])
1211

  
1212
        except Exception as ex:
1213
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1214
                                                           sys.exc_info()[-1].tb_lineno)
1215
            self.addMessage.emit(MessageType.Error, message)
1216

  
1217
    def has_duplicate_pump(self, name):
1218
        row_count = self.tableWidgetOutput.rowCount()
1219
        for row in range(row_count):
1220
            if self.tableWidgetOutput.item(row, 0).text() == name:
1221
                return True
1222

  
1223
        return False
1224

  
1225
    def loop_pumps_hy(self, loops, units):
1226
        try:
1227

  
1228
            for loop in loops:
1229
                indices = [index for index in range(len(loop.items)) if
1230
                           str(loop.items[index])[:3] == 'R_P' or str(loop.items[index])[:3] == 'L_P' or str(
1231
                               loop.items[index])[:3] == 'V_P']
1232

  
1233
                if indices:
1234
                    if len(indices) == 2:
1235
                        name = loop.items[indices[0]].parent.tag_no
1236

  
1237
                        if self.has_duplicate_pump(name):
1238
                            continue
1239

  
1240
                        suct_p = loop.pressures[loop.items[indices[0]]]
1241
                        disc_p = loop.pressures[loop.items[indices[1]]]
1242
                        diff_p = loop.pressure_drops[loop.items[indices[0]]]
1243
                        vapo_p = loop.extras[loop.items[indices[0]]]
1244
                        density = loop.density_elevations[loop.items[indices[0] - 1]]
1245
                        flowrate_mass = loop.items[indices[0] - 1].data.flowrate_mass
1246
                        npsha = self.npsha_cal_hy(suct_p, vapo_p, density, units)
1247
                        head = self.pump_head_cal(diff_p, density, units)
1248
                        hhp = self.pump_hydp_hy(flowrate_mass, density, head, units)
1249

  
1250
                        self.add_data(name, None, None, True)
1251
                        self.add_data('Suct.P :', round(suct_p, 3), '{}.g'.format(units['Pressure']))
1252
                        self.add_data('Disc.P :', round(disc_p, 3), '{}.g'.format(units['Pressure']))
1253
                        self.add_data('Diff.P :', round(diff_p, 3), units['Pressure'])
1254
                        self.add_data('Head :', round(head, 3), units['Length'])
1255
                        self.add_data('NPSHa :', round(npsha, 3), units['Length'])
1256
                        self.add_data('Vap. P :', vapo_p, '{}.a'.format(units['Pressure']))
1257
                        self.add_data('HHP :', round(hhp, 3), units['Power'])
1258

  
1259
        except Exception as ex:
1260
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1261
                                                           sys.exc_info()[-1].tb_lineno)
1262
            self.addMessage.emit(MessageType.Error, message)
1263

  
1264
    def display_output(self, loops):
1265
        try:
1266
            """ display output """
1267
            drawing = AppDocData.instance().activeDrawing
1268
            if drawing is None:
1269
                return
1270

  
1271
            if loops:
1272
                self.tableWidgetOutput.clear()
1273
                self.tableWidgetOutput.setRowCount(0)
1274
                self.tableWidgetOutput.setColumnCount(3)
1275
                self.tableWidgetOutput.horizontalHeader().setVisible(False)
1276
                self.tableWidgetOutput.verticalHeader().setVisible(False)
1277
                self.tableWidgetOutput.setSelectionMode(QAbstractItemView.SingleSelection)
1278
                self.tableWidgetOutput.setSelectionBehavior(QAbstractItemView.SelectRows)
1279
                self.tableWidgetOutput.setEditTriggers(QAbstractItemView.NoEditTriggers)
1280
                self.tableWidgetOutput.horizontalHeader().setStretchLastSection(True)
1281

  
1282
                units = [attr[1] for attr in drawing.attrs if attr[0] == 'Units'][0]
1283
                self.loop_streams_hy()
1284
                self.loop_pumps_hy(loops, units)
1285
                self.loop_comps_hy(loops, units)
1286
                self.loop_cv_hy(loops, units)
1287

  
1288
        except Exception as ex:
1289
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
1290
                                                           sys.exc_info()[-1].tb_lineno)
1291
            self.addMessage.emit(MessageType.Error, message)
1292

  
918 1293
    def display_loops(self, loops):
919 1294
        """ display loops """
920 1295
        drawing = AppDocData.instance().activeDrawing
......
1079 1454
                unit = self.convertToUnits(columnInfo[1])
1080 1455

  
1081 1456
                self.tableWidgetHMB.setItem(rowIndex, 0,
1082
                                            self.setTableWidgetItemProperties(name, Qt.AlignLeft | Qt.AlignVCenter,
1083
                                                                              QColor(51, 153,
1457
                                            set_table_widget_item_properties(name, Qt.AlignLeft | Qt.AlignVCenter,
1458
                                                                                  QColor(51, 153,
1084 1459
                                                                                     102)))
1085 1460
                # QColor(230, 230, 230)))
1086 1461
                self.tableWidgetHMB.setItem(rowIndex, 1,
1087
                                            self.setTableWidgetItemProperties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
1088
                                                                              QColor(204, 255, 204)))
1462
                                            set_table_widget_item_properties(unit, Qt.AlignHCenter | Qt.AlignVCenter,
1463
                                                                                  QColor(204, 255, 204)))
1089 1464
                # QColor(230, 230, 230)))
1090 1465

  
1091 1466
                rowIndex += 1
......
1116 1491
            self.initTableWidgetHMB()
1117 1492
            self.clear_loop()
1118 1493
            self.clearlogs()
1494
            self.clear_output()
1119 1495
            ## Load data on database     
1120 1496

  
1121 1497
            self.symbolTreeWidget.initSymbolTreeWidget()
......
1352 1728
                self.tableWidgetHMB.setColumnCount(columnCount + 1)
1353 1729
                col_names.append(str(hmb.stream_no))
1354 1730

  
1355
                self.tableWidgetHMB.setItem(0, columnCount, self.setTableWidgetItemProperties(hmb.uid,
1356
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1357
                self.tableWidgetHMB.setItem(1, columnCount, self.setTableWidgetItemProperties(hmb.components_uid,
1358
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1359
                self.tableWidgetHMB.setItem(2, columnCount, self.setTableWidgetItemProperties(hmb.stream_no,
1360
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1361
                self.tableWidgetHMB.setItem(3, columnCount, self.setTableWidgetItemProperties(hmb.phase_type,
1362
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1363
                self.tableWidgetHMB.setItem(4, columnCount, self.setTableWidgetItemProperties(hmb.flowrate_mass,
1364
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1365
                self.tableWidgetHMB.setItem(5, columnCount, self.setTableWidgetItemProperties(hmb.flowrate_volume,
1366
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1367
                self.tableWidgetHMB.setItem(6, columnCount, self.setTableWidgetItemProperties(hmb.density,
1368
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1369
                self.tableWidgetHMB.setItem(7, columnCount, self.setTableWidgetItemProperties(hmb.viscosity,
1370
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1371
                self.tableWidgetHMB.setItem(8, columnCount, self.setTableWidgetItemProperties(hmb.temperature,
1372
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1373
                self.tableWidgetHMB.setItem(9, columnCount, self.setTableWidgetItemProperties(hmb.molecular_weight,
1374
                                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1375
                self.tableWidgetHMB.setItem(10, columnCount, self.setTableWidgetItemProperties(hmb.specific_heat_ratio,
1376
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1377
                self.tableWidgetHMB.setItem(11, columnCount, self.setTableWidgetItemProperties(hmb.compress_factor,
1378
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1379
                self.tableWidgetHMB.setItem(12, columnCount, self.setTableWidgetItemProperties(hmb.nominal_pipe_size,
1380
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1381
                self.tableWidgetHMB.setItem(13, columnCount, self.setTableWidgetItemProperties(hmb.inside_pipe_size,
1382
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1383
                self.tableWidgetHMB.setItem(14, columnCount, self.setTableWidgetItemProperties(hmb.schedule_no,
1384
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1385
                self.tableWidgetHMB.setItem(15, columnCount, self.setTableWidgetItemProperties(hmb.straight_length,
1386
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1387
                self.tableWidgetHMB.setItem(16, columnCount, self.setTableWidgetItemProperties(hmb.equivalent_length,
1388
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1731
                self.tableWidgetHMB.setItem(0, columnCount, set_table_widget_item_properties(hmb.uid,
1732
                                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1733
                self.tableWidgetHMB.setItem(1, columnCount, set_table_widget_item_properties(hmb.components_uid,
1734
                                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1735
                self.tableWidgetHMB.setItem(2, columnCount, set_table_widget_item_properties(hmb.stream_no,
1736
                                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1737
                self.tableWidgetHMB.setItem(3, columnCount, set_table_widget_item_properties(hmb.phase_type,
1738
                                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1739
                self.tableWidgetHMB.setItem(4, columnCount, set_table_widget_item_properties(hmb.flowrate_mass,
1740
                                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1741
                self.tableWidgetHMB.setItem(5, columnCount, set_table_widget_item_properties(hmb.flowrate_volume,
1742
                                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1743
                self.tableWidgetHMB.setItem(6, columnCount, set_table_widget_item_properties(hmb.density,
1744
                                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1745
                self.tableWidgetHMB.setItem(7, columnCount, set_table_widget_item_properties(hmb.viscosity,
1746
                                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1747
                self.tableWidgetHMB.setItem(8, columnCount, set_table_widget_item_properties(hmb.temperature,
1748
                                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1749
                self.tableWidgetHMB.setItem(9, columnCount, set_table_widget_item_properties(hmb.molecular_weight,
1750
                                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1751
                self.tableWidgetHMB.setItem(10, columnCount, set_table_widget_item_properties(hmb.specific_heat_ratio,
1752
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1753
                self.tableWidgetHMB.setItem(11, columnCount, set_table_widget_item_properties(hmb.compress_factor,
1754
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1755
                self.tableWidgetHMB.setItem(12, columnCount, set_table_widget_item_properties(hmb.nominal_pipe_size,
1756
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1757
                self.tableWidgetHMB.setItem(13, columnCount, set_table_widget_item_properties(hmb.inside_pipe_size,
1758
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1759
                self.tableWidgetHMB.setItem(14, columnCount, set_table_widget_item_properties(hmb.schedule_no,
1760
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1761
                self.tableWidgetHMB.setItem(15, columnCount, set_table_widget_item_properties(hmb.straight_length,
1762
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1763
                self.tableWidgetHMB.setItem(16, columnCount, set_table_widget_item_properties(hmb.equivalent_length,
1764
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1389 1765

  
1390 1766
                self.tableWidgetHMB.setItem(17, columnCount,
1391
                                            self.setTableWidgetItemProperties(hmb.equivalent_length_input,
1392
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1393
                self.tableWidgetHMB.setItem(18, columnCount, self.setTableWidgetItemProperties(hmb.fitting_length,
1394
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1395
                self.tableWidgetHMB.setItem(19, columnCount, self.setTableWidgetItemProperties(hmb.fitting_K,
1396
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1767
                                            set_table_widget_item_properties(hmb.equivalent_length_input,
1768
                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1769
                self.tableWidgetHMB.setItem(18, columnCount, set_table_widget_item_properties(hmb.fitting_length,
1770
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1771
                self.tableWidgetHMB.setItem(19, columnCount, set_table_widget_item_properties(hmb.fitting_K,
1772
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1397 1773
                self.tableWidgetHMB.setItem(20, columnCount,
1398
                                            self.setTableWidgetItemProperties(hmb.equivalent_length_cal,
1399
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1400
                self.tableWidgetHMB.setItem(21, columnCount, self.setTableWidgetItemProperties(hmb.roughness,
1401
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1402
                self.tableWidgetHMB.setItem(22, columnCount, self.setTableWidgetItemProperties(hmb.limitation_velocity,
1403
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1774
                                            set_table_widget_item_properties(hmb.equivalent_length_cal,
1775
                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1776
                self.tableWidgetHMB.setItem(21, columnCount, set_table_widget_item_properties(hmb.roughness,
1777
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1778
                self.tableWidgetHMB.setItem(22, columnCount, set_table_widget_item_properties(hmb.limitation_velocity,
1779
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1404 1780
                self.tableWidgetHMB.setItem(23, columnCount,
1405
                                            self.setTableWidgetItemProperties(hmb.limitation_pressure_drop,
1406
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1407

  
1408
                self.tableWidgetHMB.setItem(24, columnCount, self.setTableWidgetItemProperties(None,
1409
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter,
1410
                                                                                               QColor(153, 204, 255)))
1411

  
1412
                self.tableWidgetHMB.setItem(25, columnCount, self.setTableWidgetItemProperties(hmb.velocity,
1413
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1414
                self.tableWidgetHMB.setItem(26, columnCount, self.setTableWidgetItemProperties(hmb.reynolds,
1415
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1416
                self.tableWidgetHMB.setItem(27, columnCount, self.setTableWidgetItemProperties(hmb.friction_factor,
1417
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1418
                self.tableWidgetHMB.setItem(28, columnCount, self.setTableWidgetItemProperties(hmb.pressure_drop,
1419
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1781
                                            set_table_widget_item_properties(hmb.limitation_pressure_drop,
1782
                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1783

  
1784
                self.tableWidgetHMB.setItem(24, columnCount, set_table_widget_item_properties(None,
1785
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter,
1786
                                                                                                   QColor(153, 204, 255)))
1787

  
1788
                self.tableWidgetHMB.setItem(25, columnCount, set_table_widget_item_properties(hmb.velocity,
1789
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1790
                self.tableWidgetHMB.setItem(26, columnCount, set_table_widget_item_properties(hmb.reynolds,
1791
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1792
                self.tableWidgetHMB.setItem(27, columnCount, set_table_widget_item_properties(hmb.friction_factor,
1793
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1794
                self.tableWidgetHMB.setItem(28, columnCount, set_table_widget_item_properties(hmb.pressure_drop,
1795
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1420 1796
                self.tableWidgetHMB.setItem(29, columnCount,
1421
                                            self.setTableWidgetItemProperties(hmb.pressure_drop_friction,
1422
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1423
                self.tableWidgetHMB.setItem(30, columnCount, self.setTableWidgetItemProperties(hmb.pressure_drop_static,
1424
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1797
                                            set_table_widget_item_properties(hmb.pressure_drop_friction,
1798
                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1799
                self.tableWidgetHMB.setItem(30, columnCount, set_table_widget_item_properties(hmb.pressure_drop_static,
1800
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1425 1801
                self.tableWidgetHMB.setItem(31, columnCount,
1426
                                            self.setTableWidgetItemProperties(hmb.pressure_pipe_end_point,
1427
                                                                              Qt.AlignHCenter | Qt.AlignVCenter))
1428
                self.tableWidgetHMB.setItem(32, columnCount, self.setTableWidgetItemProperties(hmb.power,
1429
                                                                                               Qt.AlignHCenter | Qt.AlignVCenter))
1802
                                            set_table_widget_item_properties(hmb.pressure_pipe_end_point,
1803
                                                                                  Qt.AlignHCenter | Qt.AlignVCenter))
1804
                self.tableWidgetHMB.setItem(32, columnCount, set_table_widget_item_properties(hmb.power,
1805
                                                                                                   Qt.AlignHCenter | Qt.AlignVCenter))
1430 1806

  
1431 1807
                if hmb.isDeleted: self.tableWidgetHMB.hideColumn(columnCount)
1432 1808

  
......
1651 2027

  
1652 2028
        return itemList
1653 2029

  
1654
    def setTableWidgetItemProperties(self, name, alignment, color=None):
1655
        if name is None:
1656
            name = ''
1657

  
1658
        item = QTableWidgetItem(str(name))
1659
        item.setTextAlignment(alignment)
1660
        if color:
1661
            item.setBackground(color)
1662

  
1663
        return item
2030
    def add_data(self, name, value, unit, separation=None):
2031
        row = self.tableWidgetOutput.rowCount()
2032
        self.tableWidgetOutput.setRowCount(row + 1)
2033

  
2034
        if separation:
2035
            self.tableWidgetOutput.setItem(row, 0, set_table_widget_item_properties(name,
2036
                                                                                    Qt.AlignLeft | Qt.AlignVCenter,
2037
                                                                                    QColor(153, 204, 255)))
2038
            self.tableWidgetOutput.setItem(row, 1, set_table_widget_item_properties(value,
2039
                                                                                    Qt.AlignHCenter | Qt.AlignVCenter,
2040
                                                                                    QColor(153, 204, 255)))
2041
            self.tableWidgetOutput.setItem(row, 2, set_table_widget_item_properties(unit,
2042
                                                                                    Qt.AlignHCenter | Qt.AlignVCenter,
2043
                                                                                    QColor(153, 204, 255)))
2044
        else:
2045
            self.tableWidgetOutput.setItem(row, 0, set_table_widget_item_properties(name,
2046
                                                                                    Qt.AlignLeft | Qt.AlignVCenter))
2047
            self.tableWidgetOutput.setItem(row, 1, set_table_widget_item_properties(value,
2048
                                                                                    Qt.AlignRight | Qt.AlignVCenter))
2049
            self.tableWidgetOutput.setItem(row, 2, set_table_widget_item_properties(unit,
2050
                                                                                    Qt.AlignLeft | Qt.AlignVCenter))
2051

  
2052
        self.tableWidgetOutput.resizeRowsToContents()
2053
        self.tableWidgetOutput.resizeColumnsToContents()
1664 2054

  
1665 2055

  
1666 2056
if __name__ == '__main__':
HYTOS/HYTOS/MainWindow_UI.py
62 62
        self.verticalLayoutSymbolList.setObjectName("verticalLayoutSymbolList")
63 63
        self.gridLayout_2.addLayout(self.verticalLayoutSymbolList, 2, 0, 1, 1)
64 64
        self.dockWidgetSymbolExplorer.setWidget(self.dockWidgetContents)
65
        MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.dockWidgetSymbolExplorer)
65
        MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockWidgetSymbolExplorer)
66 66
        self.dockWidgetDrawingExplorer = QtWidgets.QDockWidget(MainWindow)
67 67
        self.dockWidgetDrawingExplorer.setMinimumSize(QtCore.QSize(300, 328))
68 68
        self.dockWidgetDrawingExplorer.setObjectName("dockWidgetDrawingExplorer")
......
151 151
        self.toolBar.setIconSize(QtCore.QSize(32, 32))
152 152
        self.toolBar.setObjectName("toolBar")
153 153
        MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
154
        self.dockWidget = QtWidgets.QDockWidget(MainWindow)
155
        self.dockWidget.setObjectName("dockWidget")
156
        self.dockWidgetContents_4 = QtWidgets.QWidget()
157
        self.dockWidgetContents_4.setObjectName("dockWidgetContents_4")
158
        self.gridLayout_7 = QtWidgets.QGridLayout(self.dockWidgetContents_4)
159
        self.gridLayout_7.setObjectName("gridLayout_7")
160
        self.tableWidgetOutput = QtWidgets.QTableWidget(self.dockWidgetContents_4)
161
        self.tableWidgetOutput.setObjectName("tableWidgetOutput")
162
        self.tableWidgetOutput.setColumnCount(0)
163
        self.tableWidgetOutput.setRowCount(0)
164
        self.gridLayout_7.addWidget(self.tableWidgetOutput, 0, 0, 1, 1)
165
        self.dockWidget.setWidget(self.dockWidgetContents_4)
166
        MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.dockWidget)
154 167
        self.actionClose = QtWidgets.QAction(MainWindow)
155 168
        icon2 = QtGui.QIcon()
156 169
        icon2.addPixmap(QtGui.QPixmap(":/images/Exit.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
......
507 520
        self.toolButton_ClearLog.setToolTip(_translate("MainWindow", "Clear logs"))
508 521
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), _translate("MainWindow", "Logs"))
509 522
        self.toolBar.setWindowTitle(_translate("MainWindow", "Main Toolbar"))
523
        self.dockWidget.setWindowTitle(_translate("MainWindow", "Output Explorer"))
510 524
        self.actionClose.setText(_translate("MainWindow", "Exit"))
511 525
        self.actionClose.setToolTip(_translate("MainWindow", "Exit"))
512 526
        self.actionRecognition.setText(_translate("MainWindow", "Recognize Eng. Info."))
HYTOS/HYTOS/StreamDataDialog.py
512 512
    def mixed_type_calculation(self):
513 513
        from Calculation import Calculation_2Phase
514 514
        try:
515

  
516
            self.ui.tableWidget_Mixed_DB.setRowCount(0)
515 517
            process = {}
516 518

  
517 519
            process['l_flowrate'] = self.ui.lineEdit_Mixed_Flowrate_Mass_Liquid.text()
......
542 544
                            process['v_mw']) and is_not_blank(process['v_z']):
543 545
                        cal = Calculation_2Phase(self.item, process, self.ui.tableWidget_GeometryData_Mixed)
544 546
                        self.load_mixed_result(cal.result())
545

  
546

  
547 547
                    else:
548 548
                        QMessageBox.information(self, self.tr("Notice"), self.tr("Please input [Vapor property] !"))
549 549
                        return
HYTOS/HYTOS/UI/MainWindow.ui
109 109
    <string>Symbol Explorer</string>
110 110
   </property>
111 111
   <attribute name="dockWidgetArea">
112
    <number>2</number>
112
    <number>1</number>
113 113
   </attribute>
114 114
   <widget class="QWidget" name="dockWidgetContents">
115 115
    <layout class="QGridLayout" name="gridLayout_2">
......
308 308
   <addaction name="actionZoom"/>
309 309
   <addaction name="actionFitWindow"/>
310 310
  </widget>
311
  <widget class="QDockWidget" name="dockWidget">
312
   <property name="windowTitle">
313
    <string>Output Explorer</string>
314
   </property>
315
   <attribute name="dockWidgetArea">
316
    <number>2</number>
317
   </attribute>
318
   <widget class="QWidget" name="dockWidgetContents_4">
319
    <layout class="QGridLayout" name="gridLayout_7">
320
     <item row="0" column="0">
321
      <widget class="QTableWidget" name="tableWidgetOutput"/>
322
     </item>
323
    </layout>
324
   </widget>
325
  </widget>
311 326
  <action name="actionClose">
312 327
   <property name="icon">
313 328
    <iconset resource="../res/Resource.qrc">

내보내기 Unified diff

클립보드 이미지 추가 (최대 크기: 500 MB)