hytos / HYTOS / HYTOS / MainWindow.py @ b95146ca
이력 | 보기 | 이력해설 | 다운로드 (131 KB)
1 |
# -*- coding: utf-8 -*-
|
---|---|
2 |
""" This is MainWindow module """
|
3 |
|
4 |
import sys |
5 |
import os |
6 |
import subprocess |
7 |
from functools import partial |
8 |
|
9 |
from openpyxl.drawing import colors |
10 |
|
11 |
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
12 |
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Commands') |
13 |
import CreateCommand |
14 |
import AreaZoomCommand |
15 |
import PlaceStreamlineCommand |
16 |
|
17 |
import numpy as np |
18 |
|
19 |
from PyQt5.QtCore import * |
20 |
from PyQt5.QtGui import * |
21 |
from PyQt5.QtWidgets import * |
22 |
from PyQt5.QtSvg import * |
23 |
|
24 |
from PIL import Image |
25 |
|
26 |
import MainWindow_UI |
27 |
import QtImageViewer |
28 |
from SingletonInstance import SingletonInstane |
29 |
|
30 |
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\Shapes') |
31 |
from SymbolSvgItem import SymbolSvgItem |
32 |
|
33 |
from EngineeringTextItem import QEngineeringTextItem |
34 |
from EngineeringErrorItem import QEngineeringErrorItem |
35 |
from EngineeringStreamlineItem import QEngineeringStreamlineItem |
36 |
from AppDocData import * |
37 |
import SymbolTreeWidget |
38 |
import uuid |
39 |
import math |
40 |
|
41 |
|
42 |
def is_blank(s): |
43 |
return not (s and s.strip()) |
44 |
|
45 |
def is_not_blank(s): |
46 |
return bool(s and s.strip()) |
47 |
|
48 |
|
49 |
def is_float(s): |
50 |
try:
|
51 |
if s:
|
52 |
float(s)
|
53 |
return True |
54 |
else:
|
55 |
return False |
56 |
except ValueError: |
57 |
return False |
58 |
|
59 |
|
60 |
def set_item_properties(name, alignment, backgroundcolor=None, foregroundcolor=None): |
61 |
if name is None: |
62 |
name = ''
|
63 |
|
64 |
item = QTableWidgetItem(str(name))
|
65 |
item.setTextAlignment(alignment) |
66 |
if backgroundcolor:
|
67 |
item.setBackground(backgroundcolor) |
68 |
if foregroundcolor:
|
69 |
item.setForeground(foregroundcolor) # QBrush(QColor(255, 0, 0)))
|
70 |
return item
|
71 |
|
72 |
|
73 |
def convert_to_fixed_point(value): |
74 |
if is_float(str(value)): |
75 |
tokens = f"{float(value):.10f}".split('.') |
76 |
if len(tokens) == 2: |
77 |
# 소수점 아래가 있을 경우 소수점 아래의 trailing zero를 제거한다.
|
78 |
if is_blank(tokens[1].rstrip('0')): |
79 |
return tokens[0] |
80 |
else:
|
81 |
tokens[1] = tokens[1].rstrip('0') |
82 |
return '.'.join(tokens) |
83 |
else:
|
84 |
return tokens[0] |
85 |
else:
|
86 |
return value
|
87 |
|
88 |
|
89 |
class MainWindow(QMainWindow, MainWindow_UI.Ui_MainWindow, SingletonInstane): |
90 |
""" This is MainWindow class """
|
91 |
addMessage = pyqtSignal(Enum, str)
|
92 |
|
93 |
def __init__(self): |
94 |
"""initialize"""
|
95 |
|
96 |
try:
|
97 |
super(self.__class__, self).__init__() |
98 |
self.setupUi(self) |
99 |
|
100 |
self._label_mouse = QLabel(self.statusbar) |
101 |
self._label_mouse.setText(self.tr('mouse pos : ({},{})'.format(0, 0))) |
102 |
self.statusbar.addWidget(self._label_mouse) |
103 |
self.addMessage.connect(self.onAddMessage) |
104 |
|
105 |
self.setMainWindowTitle()
|
106 |
|
107 |
self.graphicsView = QtImageViewer.QtImageViewer(self) |
108 |
self.graphicsView.setParent(self.centralwidget) |
109 |
self.graphicsView.useDefaultCommand()
|
110 |
self.graphicsView.setMouseTracking(True) |
111 |
self.graphicsView.viewport().installEventFilter(self) |
112 |
self.verticalLayout.addWidget(self.graphicsView) |
113 |
|
114 |
# Add Symbol TreeWidget
|
115 |
self.symbolTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
|
116 |
self.symbolTreeWidget.header().hide()
|
117 |
self.verticalLayoutSymbolList.addWidget(self.symbolTreeWidget) |
118 |
|
119 |
# Initialize Action group
|
120 |
self.actionGroup = QActionGroup(self) |
121 |
self.actionGroup.addAction(self.actionLine) |
122 |
self.actionGroup.addAction(self.actionZoom) |
123 |
self.actionGroup.addAction(self.actionFitWindow) |
124 |
self.actionGroup.addAction(self.actionSave) |
125 |
|
126 |
# connect signals and slots
|
127 |
self.actionGroup.triggered.connect(self.actionGroupTriggered) |
128 |
self.actionClose.triggered.connect(self.close) |
129 |
self.actionNew.triggered.connect(self.on_new_drawing) |
130 |
self.actionOpen.triggered.connect(self.on_open_drawing) |
131 |
self.actionSave.triggered.connect(self.on_save) #self.actionSaveCliked) |
132 |
self.actionSave_As.triggered.connect(self.on_save_as) |
133 |
self.actionCalculation.triggered.connect(self.calculation) |
134 |
self.actionGenerateReport.triggered.connect(self.generate_report) |
135 |
self.actionLine.triggered.connect(self.onPlaceLine) |
136 |
self.actionConfiguration.triggered.connect(self.configuration) |
137 |
self.actionInitialize.triggered.connect(self.onInitializeScene) |
138 |
self.actionOptions.triggered.connect(self.onOptions) |
139 |
self.actionZoom.triggered.connect(self.onAreaZoom) |
140 |
self.actionFitWindow.triggered.connect(self.fitWindow) |
141 |
self.actionViewConnector.triggered.connect(self.on_view_connector) |
142 |
self.actionSymbol_Editor.triggered.connect(self.showSymbolEditor) |
143 |
self.actionPlaceTextBox.triggered.connect(self.on_place_callout_textbox) |
144 |
self.actionPlaceDimension.triggered.connect(self.on_place_dimension) |
145 |
self.actionPlaceCloud.triggered.connect(self.on_place_cloud) |
146 |
self.actionHelp.triggered.connect(self.on_help) |
147 |
self.actionAbout.triggered.connect(self.on_about) |
148 |
self.toolButton_ClearLog.clicked.connect(self.clearlogs) |
149 |
self.graphicsView.scene.selectionChanged.connect(self.onSelectionChanged) |
150 |
|
151 |
self.treeWidgetDrawingList.setContextMenuPolicy(Qt.CustomContextMenu)
|
152 |
self.treeWidgetDrawingList.customContextMenuRequested.connect(self.openContextMenu) |
153 |
self.treeWidgetDrawingList.itemDoubleClicked.connect(self.open_selected_drawing) |
154 |
|
155 |
self.initTreeWidgetDrawingList()
|
156 |
self.initTableWidgetHMB()
|
157 |
|
158 |
self.load_drawing_list()
|
159 |
self.load_stylesheet_file()
|
160 |
self.load_language_file()
|
161 |
|
162 |
self.tabifyDockWidget(self.dockWidgetDrawingExplorer, self.dockWidgetSymbolExplorer) |
163 |
self.dockWidgetDrawingExplorer.raise_()
|
164 |
|
165 |
self.read_settings()
|
166 |
|
167 |
# ToDo..
|
168 |
# Menu bar - Admin Hide
|
169 |
# Loop Tab Hide
|
170 |
except Exception as ex: |
171 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
172 |
sys.exc_info()[-1].tb_lineno)
|
173 |
self.addMessage.emit(MessageType.Error, message)
|
174 |
|
175 |
def read_settings(self): |
176 |
"""read geometry and state"""
|
177 |
from App import App |
178 |
|
179 |
try:
|
180 |
self.settings = QSettings(App.COMPANY, App.NAME)
|
181 |
self.restoreGeometry(self.settings.value("geometry", "")) |
182 |
self.restoreState(self.settings.value("windowState", "")) |
183 |
except Exception as ex: |
184 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
185 |
sys.exc_info()[-1].tb_lineno)
|
186 |
self.addMessage.emit(MessageType.Error, message)
|
187 |
|
188 |
def load_stylesheet_file(self): |
189 |
# load stylesheet file list
|
190 |
stylesheet_name = QtWidgets.qApp.stylesheet_name |
191 |
files = [os.path.splitext(file)[0] for file in os.listdir(os.path.dirname(os.path.realpath(__file__))) if |
192 |
os.path.splitext(file)[1] == '.qss'] |
193 |
for file in files: |
194 |
action = self.menuTheme.addAction(file) |
195 |
action.setCheckable(True)
|
196 |
action.setChecked(True) if stylesheet_name == file else action.setChecked(False) |
197 |
action.triggered.connect(partial(self.load_stylesheet, file)) |
198 |
# up to here
|
199 |
|
200 |
def load_language_file(self): |
201 |
# load language files
|
202 |
language_name = QtWidgets.qApp.language_name |
203 |
files = ['en_us'] # englisgh is default language |
204 |
files.extend([os.path.splitext(file)[0] for file in |
205 |
os.listdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate')) if |
206 |
os.path.splitext(file)[1] == '.qm']) |
207 |
for file in files: |
208 |
action = self.menuLanguage.addAction(file) |
209 |
action.setCheckable(True)
|
210 |
action.setChecked(True) if language_name.lower() == file.lower() else action.setChecked(False) |
211 |
action.triggered.connect(partial(self.load_language, file)) |
212 |
# up to here
|
213 |
|
214 |
def setMainWindowTitle(self, drawingName=None): |
215 |
try:
|
216 |
_translate = QCoreApplication.translate |
217 |
|
218 |
version = QCoreApplication.applicationVersion() |
219 |
if drawingName is None: |
220 |
self.setWindowTitle(_translate(App.NAME + "({})".format(version), App.NAME + "({})".format(version))) |
221 |
else:
|
222 |
self.setWindowTitle(
|
223 |
_translate(App.NAME + "({})".format(version), App.NAME + "({})".format(version)) + ' - {}'.format( |
224 |
drawingName)) |
225 |
except Exception as ex: |
226 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
227 |
sys.exc_info()[-1].tb_lineno)
|
228 |
self.addMessage.emit(MessageType.Error, message)
|
229 |
|
230 |
def clearlogs(self): |
231 |
try:
|
232 |
self.listWidgetLogs.clear()
|
233 |
except Exception as ex: |
234 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
235 |
sys.exc_info()[-1].tb_lineno)
|
236 |
self.addMessage.emit(MessageType.Error, message)
|
237 |
finally:
|
238 |
logs = self.listWidgetLogs.count()
|
239 |
if logs:
|
240 |
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs({})'.format(logs)) |
241 |
else:
|
242 |
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs') |
243 |
|
244 |
def closeEvent(self, a0: QCloseEvent) -> None: |
245 |
"""save geometry and state and then ask user to save drawing which is modified"""
|
246 |
|
247 |
self.settings.setValue('geometry', self.saveGeometry()) |
248 |
self.settings.setValue('windowState', self.saveState()) |
249 |
|
250 |
self.save_drawing_if_necessary()
|
251 |
a0.accept() |
252 |
|
253 |
def openContextMenu(self, position): |
254 |
indexes = self.treeWidgetDrawingList.selectedIndexes()
|
255 |
if len(indexes) > 0: |
256 |
level = 0
|
257 |
index = indexes[0]
|
258 |
while index.parent().isValid():
|
259 |
index = index.parent() |
260 |
level += 1
|
261 |
|
262 |
menu = QMenu() |
263 |
|
264 |
itemPosition = self.mapTo(self, position) |
265 |
item = self.treeWidgetDrawingList.itemAt(itemPosition)
|
266 |
|
267 |
if level == 0: |
268 |
newDrawingAction = menu.addAction(self.tr('New...')) |
269 |
newDrawingAction.triggered.connect(lambda: self.newDrawingActionClickEvent(item)) |
270 |
menu.addAction(newDrawingAction) |
271 |
elif level == 1: |
272 |
# saveAsDrawingAction = menu.addAction(self.tr("Save As..."))
|
273 |
# saveAsDrawingAction.triggered.connect(lambda: self.saveAsDrawingActionClickEvent(item))
|
274 |
# menu.addAction(saveAsDrawingAction)
|
275 |
|
276 |
deleteDrawingAction = menu.addAction(self.tr("Delete")) |
277 |
deleteDrawingAction.triggered.connect(lambda: self.deleteDrawingActionClickEvent(item)) |
278 |
menu.addAction(deleteDrawingAction) |
279 |
|
280 |
menu.exec_(self.treeWidgetDrawingList.viewport().mapToGlobal(position))
|
281 |
|
282 |
def on_new_drawing(self): |
283 |
self.new_drawing()
|
284 |
|
285 |
def newDrawingActionClickEvent(self, item): |
286 |
self.new_drawing()
|
287 |
|
288 |
def saveAsDrawingActionClickEvent(self, item): |
289 |
sourceDb = item.text(2)
|
290 |
|
291 |
self.saveAs_drawing(sourceDb)
|
292 |
|
293 |
def deleteDrawingActionClickEvent(self, item): |
294 |
""" delete selected drawing """
|
295 |
try:
|
296 |
msg = QMessageBox(self)
|
297 |
msg.setIcon(QMessageBox.Question) |
298 |
msg.setText(self.tr('Do you want to delete drawing on list?\nHowever, Actual drawing is not deleted.')) |
299 |
msg.setWindowTitle(self.tr("Delete")) |
300 |
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) |
301 |
|
302 |
if QMessageBox.Ok == msg.exec_():
|
303 |
drawingName = item.text(0)
|
304 |
drawingPath = item.text(2)
|
305 |
|
306 |
app_doc_data = AppDocData.instance() |
307 |
app_doc_data.deleteDrawingByName(drawingPath) |
308 |
|
309 |
if app_doc_data.activeDrawing:
|
310 |
if drawingName == app_doc_data.activeDrawing.name and drawingPath == app_doc_data.activeDrawing.path: |
311 |
app_doc_data.activeDrawing = None
|
312 |
|
313 |
if self.graphicsView.hasImage(): |
314 |
self.graphicsView.clearImage()
|
315 |
self.graphicsView.scene.clear()
|
316 |
|
317 |
self.initTableWidgetHMB()
|
318 |
|
319 |
self.load_drawing_list()
|
320 |
except Exception as ex: |
321 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
322 |
sys.exc_info()[-1].tb_lineno)
|
323 |
self.addMessage.emit(MessageType.Error, message)
|
324 |
|
325 |
def clear_data(self): |
326 |
self.clear_HMB()
|
327 |
|
328 |
def eventFilter(self, source, event): |
329 |
""" display mouse position of graphics view """
|
330 |
if event.type() == QEvent.MouseMove:
|
331 |
pos = self.graphicsView.mapToScene(event.pos())
|
332 |
self._label_mouse.setText('mouse pos : ({},{})'.format(round(pos.x()), round(pos.y()))) |
333 |
|
334 |
return QWidget.eventFilter(self, source, event) |
335 |
|
336 |
def load_stylesheet(self, file): |
337 |
"""load stylesheets"""
|
338 |
|
339 |
QtWidgets.qApp.loadStyleSheet(os.path.join(os.path.dirname(os.path.realpath(__file__)), file))
|
340 |
|
341 |
app_doc_data = AppDocData.instance() |
342 |
configs = [Config('app', 'stylesheet', file)] |
343 |
app_doc_data.saveAppConfigs(configs) |
344 |
|
345 |
for action in self.menuTheme.actions(): |
346 |
if action.text() == file: continue |
347 |
action.setChecked(False)
|
348 |
|
349 |
def load_language(self, file): |
350 |
""" load language file and then apply selected language """
|
351 |
try:
|
352 |
|
353 |
qm_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'translate', '{0}.qm'.format(file)) |
354 |
QtWidgets.qApp.load_language(qm_file) |
355 |
|
356 |
app_doc_data = AppDocData.instance() |
357 |
configs = [Config('app', 'language', file)] |
358 |
app_doc_data.saveAppConfigs(configs) |
359 |
|
360 |
for action in self.menuLanguage.actions(): |
361 |
if action.text().lower() == file.lower(): continue |
362 |
action.setChecked(False)
|
363 |
finally:
|
364 |
self.retranslateUi(self) |
365 |
|
366 |
def initTreeWidgetDrawingList(self): |
367 |
|
368 |
self.treeWidgetDrawingList.setHeaderHidden(False) |
369 |
self.treeWidgetDrawingList.header().setStretchLastSection(True) |
370 |
self.treeWidgetDrawingList.header().setDefaultAlignment(Qt.AlignCenter)
|
371 |
self.treeWidgetDrawingList.setHeaderLabels([self.tr('Name'), self.tr('DateTime'), self.tr('Path')]) |
372 |
self.treeWidgetDrawingList.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) |
373 |
self.treeWidgetDrawingList.header().setSectionResizeMode(1, QHeaderView.ResizeToContents) |
374 |
self.treeWidgetDrawingList.header().setSectionResizeMode(2, QHeaderView.ResizeToContents) |
375 |
self.treeWidgetDrawingList.hideColumn(2) |
376 |
|
377 |
def clear_output(self): |
378 |
self.tableWidgetOutput.setColumnCount(0) |
379 |
self.tableWidgetOutput.setRowCount(0) |
380 |
|
381 |
self.tableWidgetDeviation.setColumnCount(0) |
382 |
self.tableWidgetDeviation.setRowCount(0) |
383 |
|
384 |
def clear_loop(self): |
385 |
self.tableWidgetLoop.setColumnCount(0) |
386 |
|
387 |
def initTableWidgetHMB(self): |
388 |
app_doc_data = AppDocData.instance() |
389 |
|
390 |
column_infos = app_doc_data.getHMBDisplayNameAndUnitsExpression() |
391 |
count = len(column_infos)
|
392 |
self.tableWidgetHMB.setRowCount(count)
|
393 |
if len(column_infos) > 0: |
394 |
self.tableWidgetHMB.setColumnCount(2) |
395 |
else:
|
396 |
self.tableWidgetHMB.setColumnCount(0) |
397 |
|
398 |
self.tableWidgetHMB.hideRow(0) # UID |
399 |
self.tableWidgetHMB.hideRow(1) # Components_UID |
400 |
self.tableWidgetHMB.hideRow(2) # Stream_No |
401 |
# self.tableWidgetHMB.hideRow(3) # Phase_Type
|
402 |
# self.tableWidgetHMB.hideRow(4) # Flowrate_Mass
|
403 |
# self.tableWidgetHMB.hideRow(5) # Flowrate_Volume
|
404 |
# self.tableWidgetHMB.hideRow(6) # Density
|
405 |
# self.tableWidgetHMB.hideRow(7) # Viscosity
|
406 |
# self.tableWidgetHMB.hideRow(8) # Temperature
|
407 |
# self.tableWidgetHMB.hideRow(9) # Molecular_Weight
|
408 |
# self.tableWidgetHMB.hideRow(10) # Specific_Heat_Ratio
|
409 |
# self.tableWidgetHMB.hideRow(11) # Compress_Factor
|
410 |
# self.tableWidgetHMB.hideRow(12) # Nominal_Pipe_Size
|
411 |
# self.tableWidgetHMB.hideRow(13) # Inside_Pipe_Size
|
412 |
# self.tableWidgetHMB.hideRow(14) # Schedule_No
|
413 |
# self.tableWidgetHMB.hideRow(15) # Straight_Length
|
414 |
# self.tableWidgetHMB.hideRow(16) # Equivalent_Length
|
415 |
self.tableWidgetHMB.hideRow(17) # Equivalent_Length_Input |
416 |
self.tableWidgetHMB.hideRow(18) # Fitting_Length |
417 |
self.tableWidgetHMB.hideRow(19) # Fitting_K |
418 |
self.tableWidgetHMB.hideRow(20) # Equivalent_Length_Cal |
419 |
# self.tableWidgetHMB.hideRow(21) # Roughness
|
420 |
# self.tableWidgetHMB.hideRow(22) # Limitation_Velocity
|
421 |
# self.tableWidgetHMB.hideRow(23) # Limitation_Pressure_Drop
|
422 |
# self.tableWidgetHMB.hideRow(24) # Separator
|
423 |
# self.tableWidgetHMB.hideRow(25) # Velocity
|
424 |
# self.tableWidgetHMB.hideRow(26) # Reynolds
|
425 |
# self.tableWidgetHMB.hideRow(27) # Friction_Factor
|
426 |
# self.tableWidgetHMB.hideRow(28) # Pressure_Drop
|
427 |
# self.tableWidgetHMB.hideRow(29) # Pressure_Drop_Friction
|
428 |
# self.tableWidgetHMB.hideRow(30) # Pressure_Drop_Static
|
429 |
# self.tableWidgetHMB.hideRow(31) # Pressure_Pipe_End_Point
|
430 |
self.tableWidgetHMB.hideRow(32) # Power |
431 |
|
432 |
self.tableWidgetHMB.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
433 |
self.tableWidgetHMB.verticalHeader().setVisible(False) |
434 |
|
435 |
col_names = ['Stream No.', 'Unit'] |
436 |
self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
|
437 |
|
438 |
rowIndex = 0
|
439 |
for columnInfo in column_infos: |
440 |
name = columnInfo[0]
|
441 |
unit = self.convertToUnits(columnInfo[1]) |
442 |
|
443 |
self.tableWidgetHMB.setItem(rowIndex, 0, set_item_properties(name, Qt.AlignLeft | Qt.AlignVCenter, |
444 |
QColor(51, 153, 102))) |
445 |
self.tableWidgetHMB.setItem(rowIndex, 1, set_item_properties(unit, Qt.AlignHCenter | Qt.AlignVCenter, |
446 |
QColor(204, 255, 204))) |
447 |
|
448 |
rowIndex += 1
|
449 |
|
450 |
self.tableWidgetHMB.resizeColumnsToContents()
|
451 |
self.tableWidgetHMB.resizeRowsToContents()
|
452 |
|
453 |
def copy_selection(self, table_widget): |
454 |
"""copy selected text to clipboard"""
|
455 |
|
456 |
import io |
457 |
import csv |
458 |
|
459 |
selection = table_widget.selectedIndexes() |
460 |
if selection:
|
461 |
rows = sorted(index.row() for index in selection) |
462 |
columns = sorted(index.column() for index in selection) |
463 |
rowcount = rows[-1] - rows[0] + 1 |
464 |
colcount = columns[-1] - columns[0] + 1 |
465 |
table = [[''] * colcount for _ in range(rowcount)] |
466 |
for index in selection: |
467 |
row = index.row() - rows[0]
|
468 |
column = index.column() - columns[0]
|
469 |
table[row][column] = index.data() |
470 |
stream = io.StringIO() |
471 |
csv.writer(stream, delimiter='\t').writerows(table)
|
472 |
QApplication.clipboard().setText(stream.getvalue()) |
473 |
|
474 |
def paste_selection(self, table_widget): |
475 |
"""paste text of clipboard to table widget"""
|
476 |
|
477 |
import io |
478 |
import csv |
479 |
|
480 |
selection = table_widget.selectedIndexes() |
481 |
if selection:
|
482 |
model = table_widget.model() |
483 |
|
484 |
buffer = QApplication.clipboard().text() |
485 |
rows = sorted(index.row() for index in selection) |
486 |
columns = sorted(index.column() for index in selection) |
487 |
reader = csv.reader(io.StringIO(buffer), delimiter='\t') |
488 |
if len(rows) == 1 and len(columns) == 1: |
489 |
for i, line in enumerate(reader): |
490 |
for j, cell in enumerate(line): |
491 |
model.setData(model.index(rows[0] + i, columns[0] + j), cell) |
492 |
else:
|
493 |
arr = [[cell for cell in row] for row in reader] |
494 |
for index in selection: |
495 |
row = index.row() - rows[0]
|
496 |
column = index.column() - columns[0]
|
497 |
model.setData(model.index(index.row(), index.column()), arr[row][column]) |
498 |
|
499 |
'''
|
500 |
@brief Drawing 속성의 Units 에서 Key값을 이용하여 Value를 찾음
|
501 |
@author yeonjin
|
502 |
@date 19.08.30
|
503 |
'''
|
504 |
|
505 |
def findValue(self, key): |
506 |
value = None
|
507 |
|
508 |
key = key.replace("{", "").replace("}", "") |
509 |
for attr in AppDocData.instance().activeDrawing.attrs: |
510 |
if attr[0] == 'Units': |
511 |
if key in attr[1]: |
512 |
value = attr[1][key]
|
513 |
break
|
514 |
|
515 |
return value
|
516 |
|
517 |
'''
|
518 |
@brief Convert UnitsExpression To Units Value
|
519 |
@author yeonjin
|
520 |
@date 19.08.29
|
521 |
'''
|
522 |
|
523 |
def convertToUnits(self, unitsExpression): |
524 |
import re |
525 |
|
526 |
if unitsExpression is None or AppDocData.instance().activeDrawing is None: |
527 |
return '' |
528 |
|
529 |
found = re.findall('{.*?}', unitsExpression)
|
530 |
for f in found: |
531 |
key = f |
532 |
val = self.findValue(key)
|
533 |
if val:
|
534 |
unitsExpression = unitsExpression.replace(key, val) |
535 |
|
536 |
return unitsExpression
|
537 |
|
538 |
'''
|
539 |
@brief Clear TreeWidget and Set Current PID
|
540 |
@author Jeongwoo
|
541 |
@date 18.04.11
|
542 |
@history 2018.04.26 Jeongwoo Add Child [SYMBOLS, NOTES] into root item
|
543 |
2018.05.09 Jeongwoo Change method to add default tree items
|
544 |
humkyung 2018.06.10 add tree item for Line No and Unknown Item
|
545 |
'''
|
546 |
|
547 |
def load_drawing_list(self): |
548 |
"""load pfd drawing list"""
|
549 |
|
550 |
try:
|
551 |
app_doc_data = AppDocData.instance() |
552 |
drawings = app_doc_data.getDrawings() |
553 |
|
554 |
self.treeWidgetDrawingList.clear()
|
555 |
self.treeWidgetDrawingList.root = QTreeWidgetItem(self.treeWidgetDrawingList, [self.tr('Drawings'), '']) |
556 |
|
557 |
for drawing in drawings: |
558 |
item = QTreeWidgetItem(self.treeWidgetDrawingList.root, [drawing.name, drawing.date_time, drawing.path])
|
559 |
item.setIcon(0, QIcon(':images/PFD.png')) |
560 |
item.setData(0, Qt.UserRole, drawing)
|
561 |
|
562 |
self.treeWidgetDrawingList.root.setText(0, self.tr('Drawings') + '({})'.format( |
563 |
self.treeWidgetDrawingList.root.childCount()))
|
564 |
self.treeWidgetDrawingList.expandItem(self.treeWidgetDrawingList.root) |
565 |
self.treeWidgetDrawingList.sortByColumn(1, Qt.DescendingOrder) |
566 |
self.treeWidgetDrawingList.resizeColumnToContents(0) |
567 |
|
568 |
except Exception as ex: |
569 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
570 |
sys.exc_info()[-1].tb_lineno)
|
571 |
self.addMessage.emit(MessageType.Error, message)
|
572 |
|
573 |
def save_drawing_if_necessary(self): |
574 |
"""ask user to save drawing or not when drawing is modified"""
|
575 |
|
576 |
app_doc_data = AppDocData.instance() |
577 |
if app_doc_data.activeDrawing and app_doc_data.activeDrawing.modified: |
578 |
if QMessageBox.Yes == QMessageBox.question(self, self.tr("Question"), |
579 |
self.tr("Do you want to save drawing?"), |
580 |
QMessageBox.Yes | QMessageBox.No): |
581 |
self.actionSaveCliked(False) |
582 |
|
583 |
def open_selected_drawing(self, item): |
584 |
""" open selected drawing """
|
585 |
try:
|
586 |
path = item.text(2)
|
587 |
if os.path.exists(path):
|
588 |
self.save_drawing_if_necessary()
|
589 |
self.open_drawing(path)
|
590 |
|
591 |
except Exception as ex: |
592 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
593 |
sys.exc_info()[-1].tb_lineno)
|
594 |
self.addMessage.emit(MessageType.Error, message)
|
595 |
|
596 |
'''
|
597 |
@brief action save click event
|
598 |
@author kyouho
|
599 |
@date 2018.08.09
|
600 |
@history 2018.11.02 euisung add line data list db update
|
601 |
humkyung save saved time to database
|
602 |
2018.11.05 euisung add note data list db update
|
603 |
2018.11.05 euisung add db delete process before save
|
604 |
2018.11.12 euisung db part move new method to dbUpdate
|
605 |
'''
|
606 |
|
607 |
def actionSaveCliked(self, show_message=True): |
608 |
from datetime import datetime |
609 |
from AppDocData import AppDocData |
610 |
from EngineeringAbstractItem import QEngineeringAbstractItem |
611 |
|
612 |
try:
|
613 |
app_doc_data = AppDocData.instance() |
614 |
if app_doc_data.activeDrawing is None: |
615 |
self.showImageSelectionMessageBox()
|
616 |
return
|
617 |
|
618 |
app_doc_data.activeDrawing.clearItemList() |
619 |
|
620 |
items = self.graphicsView.scene.items()
|
621 |
for item in items: |
622 |
if issubclass(type(item), QEngineeringAbstractItem): |
623 |
app_doc_data.activeDrawing.allItems.append(item) |
624 |
if issubclass(type(item), QEngineeringTextItem): |
625 |
app_doc_data.texts.append(item) |
626 |
|
627 |
count = len(app_doc_data.activeDrawing.allItems)
|
628 |
if count > 0: |
629 |
try:
|
630 |
self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, |
631 |
self) if not hasattr(self, 'progress') else self.progress |
632 |
self.progress.setWindowModality(Qt.WindowModal)
|
633 |
self.progress.setAutoReset(True) |
634 |
self.progress.setAutoClose(True) |
635 |
self.progress.setMinimum(0) |
636 |
self.progress.resize(600, 100) |
637 |
self.progress.setWindowTitle(self.tr("Save")) |
638 |
self.progress.show()
|
639 |
|
640 |
self.save_drawing_data()
|
641 |
finally:
|
642 |
self.load_drawing_list()
|
643 |
self.progress.setValue(self.progress.maximum()) |
644 |
self.progress.hide()
|
645 |
if show_message:
|
646 |
QMessageBox.information(self, self.tr("Information"), self.tr("Save completed successfully.")) |
647 |
|
648 |
except Exception as ex: |
649 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
650 |
sys.exc_info()[-1].tb_lineno)
|
651 |
self.addMessage.emit(MessageType.Error, message)
|
652 |
|
653 |
def on_save(self): |
654 |
self.actionSaveCliked()
|
655 |
|
656 |
def on_save_as(self): |
657 |
"""save as drawing file"""
|
658 |
from shutil import copyfile |
659 |
from datetime import datetime |
660 |
from Drawing import Drawing |
661 |
|
662 |
app_doc_data = AppDocData.instance() |
663 |
workspace = self.get_work_space()
|
664 |
|
665 |
file_name = os.path.join(workspace, 'copy of ' + app_doc_data.activeDrawing.name + '.hytos') |
666 |
options = QFileDialog.Options() |
667 |
options |= QFileDialog.DontUseNativeDialog |
668 |
name, _ = QFileDialog.getSaveFileName(self, self.tr('Save As'), file_name, 'HYTOS(*.hytos)', options=options) |
669 |
if name:
|
670 |
try:
|
671 |
if os.path.splitext(name)[1] != '.hytos': name += '.hytos' |
672 |
|
673 |
self.actionSaveCliked() # save current drawing |
674 |
|
675 |
app_doc_data = AppDocData.instance() |
676 |
# copy current drawing file to new drawing file
|
677 |
copyfile(app_doc_data.activeDrawing.path, name) |
678 |
app_doc_data.activeDrawing.path = name |
679 |
|
680 |
matches = [drawing for drawing in app_doc_data.getDrawings() |
681 |
if os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)] |
682 |
if not matches: |
683 |
drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
684 |
app_doc_data.saveDrawing(drawing) |
685 |
else:
|
686 |
drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
687 |
app_doc_data.updateDrawing(drawing) |
688 |
|
689 |
self.load_drawing_list()
|
690 |
self.open_border_file()
|
691 |
self.load_data(drawing)
|
692 |
|
693 |
app_doc_data.activeDrawing.modified = False
|
694 |
self.setMainWindowTitle(f"{app_doc_data.activeDrawing.path}") |
695 |
except Exception as ex: |
696 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
697 |
sys.exc_info()[-1].tb_lineno)
|
698 |
self.addMessage.emit(MessageType.Error, message)
|
699 |
|
700 |
def save_drawing_data(self): |
701 |
""" save drawing data """
|
702 |
|
703 |
from datetime import datetime |
704 |
from AppDocData import AppDocData |
705 |
from SymbolSvgItem import SymbolSvgItem |
706 |
from EngineeringStreamlineItem import QEngineeringStreamlineItem |
707 |
from EngineeringCalloutTextItem import QEngineeringCalloutTextItem |
708 |
from EngineeringCloudItem import QEngineeringCloudItem |
709 |
from EngineeringDimensionItem import QEngineeringDimensionItem |
710 |
|
711 |
try:
|
712 |
app_doc_data = AppDocData.instance() |
713 |
items = app_doc_data.activeDrawing.allItems |
714 |
|
715 |
maxValue = len(items)
|
716 |
self.progress.setMaximum(maxValue)
|
717 |
|
718 |
app_doc_data.saveToDatabase([item for item in self.graphicsView.scene.items() |
719 |
if hasattr(item, 'toSql') and ( |
720 |
type(item) is SymbolSvgItem or |
721 |
type(item) is QEngineeringStreamlineItem or |
722 |
type(item) is QEngineeringCalloutTextItem or |
723 |
type(item) is QEngineeringDimensionItem or |
724 |
type(item) is QEngineeringCloudItem)], |
725 |
self.progress.setValue)
|
726 |
|
727 |
if app_doc_data.activeDrawing:
|
728 |
app_doc_data.activeDrawing.hmbTable.saveData() |
729 |
app_doc_data.save_sheet_history('Save')
|
730 |
|
731 |
""" update drawing's modified time """
|
732 |
drawings = app_doc_data.getDrawings() |
733 |
drawing = [drawing for drawing in drawings if app_doc_data.activeDrawing == drawing] |
734 |
if drawing:
|
735 |
drawing.date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
736 |
app_doc_data.updateDrawing(drawing) |
737 |
|
738 |
app_doc_data.activeDrawing.modified = False
|
739 |
self.setMainWindowTitle(f"{app_doc_data.activeDrawing.path}") |
740 |
|
741 |
except Exception as ex: |
742 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
743 |
sys.exc_info()[-1].tb_lineno)
|
744 |
self.addMessage.emit(MessageType.Error, message)
|
745 |
|
746 |
'''
|
747 |
@brief add message listwidget
|
748 |
@author humkyung
|
749 |
@date 2018.07.31
|
750 |
'''
|
751 |
|
752 |
def onAddMessage(self, messageType, message): |
753 |
from AppDocData import MessageType |
754 |
|
755 |
try:
|
756 |
current = QDateTime.currentDateTime() |
757 |
|
758 |
item = QListWidgetItem('{}: {}'.format(current.toString('hh:mm:ss'), message)) |
759 |
if messageType == MessageType.Error:
|
760 |
item.setForeground(Qt.red) |
761 |
elif messageType == MessageType.Information:
|
762 |
item.setForeground(Qt.blue) |
763 |
|
764 |
self.listWidgetLogs.insertItem(0, item) |
765 |
except Exception as ex: |
766 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
767 |
sys.exc_info()[-1].tb_lineno))
|
768 |
finally:
|
769 |
logs = self.listWidgetLogs.count()
|
770 |
if logs:
|
771 |
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs({})'.format(logs)) |
772 |
else:
|
773 |
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabLogs), 'Logs') |
774 |
|
775 |
'''
|
776 |
@brief Area Zoom
|
777 |
@author Jeongwoo
|
778 |
@date 2018.06.27
|
779 |
@history connect command's rejected signal
|
780 |
'''
|
781 |
|
782 |
def onAreaZoom(self, action): |
783 |
if self.actionZoom.isChecked(): |
784 |
cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsView)
|
785 |
cmd.onRejected.connect(self.onCommandRejected)
|
786 |
self.graphicsView.command = cmd
|
787 |
|
788 |
'''
|
789 |
@brief Fit Window
|
790 |
@author Jeongwoo
|
791 |
@date 2018.06.27
|
792 |
@history 2018.06.27 Jeongwoo Chnage method to initialize command [Set None → DefaultCommand]
|
793 |
'''
|
794 |
|
795 |
def fitWindow(self, action): |
796 |
app_doc_data = AppDocData.instance() |
797 |
if app_doc_data.activeDrawing:
|
798 |
self.graphicsView.useDefaultCommand()
|
799 |
scene_rect = self.graphicsView.scene.itemsBoundingRect()
|
800 |
if scene_rect.left() > 0: |
801 |
scene_rect.setLeft(0)
|
802 |
if scene_rect.top() > 0: |
803 |
scene_rect.setTop(0)
|
804 |
if scene_rect.right() < 1189: |
805 |
scene_rect.setRight(1189)
|
806 |
if scene_rect.bottom() < 841: |
807 |
scene_rect.setBottom(841)
|
808 |
|
809 |
self.graphicsView.setSceneRect(scene_rect)
|
810 |
self.graphicsView.zoomImageInit()
|
811 |
self.graphicsView.scene.invalidate()
|
812 |
|
813 |
def on_view_connector(self, checked): |
814 |
"""turn on/off connector"""
|
815 |
for item in self.graphicsView.scene.items(): |
816 |
if not hasattr(item, 'connectors'): |
817 |
continue
|
818 |
for connector in item.connectors: |
819 |
connector.setVisible(True) if checked else connector.hide() |
820 |
|
821 |
def scene_changed(self): |
822 |
"""update modified flag"""
|
823 |
|
824 |
app_doc_data = AppDocData.instance() |
825 |
app_doc_data.activeDrawing.modified = True
|
826 |
self.setMainWindowTitle(f"{app_doc_data.activeDrawing.path}*") |
827 |
|
828 |
'''
|
829 |
@brief selection changed
|
830 |
@author humkyung
|
831 |
@date 2018.06.27
|
832 |
@history humkung 2018.07.08 call tree widget's findItem
|
833 |
'''
|
834 |
|
835 |
def onSelectionChanged(self): |
836 |
from EngineeringStreamlineItem import QEngineeringStreamlineItem |
837 |
|
838 |
items = [item for item in self.graphicsView.scene.selectedItems() if |
839 |
issubclass(type(item), SymbolSvgItem) or type(item) is QEngineeringStreamlineItem] |
840 |
if items:
|
841 |
item = items[-1]
|
842 |
|
843 |
if type(item) is QEngineeringErrorItem: |
844 |
for index in range(self.tableWidgetHMB.rowCount()): |
845 |
|
846 |
if self.tableWidgetHMB.item(index, 1).tag is item: |
847 |
self.tableWidgetHMB.selectRow(index)
|
848 |
break
|
849 |
|
850 |
'''
|
851 |
@brief Initialize scene and itemTreeWidget
|
852 |
@author Jeongwoo
|
853 |
|
854 |
@date 2018.06.14
|
855 |
@history humkyung 2018.08.16 ask to delete recognized items before remove
|
856 |
'''
|
857 |
|
858 |
def onInitializeScene(self, action): |
859 |
|
860 |
if not self.graphicsView.hasImage(): |
861 |
self.showImageSelectionMessageBox()
|
862 |
return
|
863 |
|
864 |
try:
|
865 |
msg = QMessageBox(self)
|
866 |
msg.setIcon(QMessageBox.Question) |
867 |
msg.setText(self.tr('Do you want to remove all items?\nThis work cannot be recovered.')) |
868 |
msg.setWindowTitle(self.tr("Clear Screen")) |
869 |
msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) |
870 |
if QMessageBox.Ok == msg.exec_():
|
871 |
|
872 |
appDocData = AppDocData.instance() |
873 |
appDocData.activeDrawing.hmbTable.reset() |
874 |
appDocData.clearItemList(True)
|
875 |
|
876 |
items = self.graphicsView.scene.items()
|
877 |
for item in items: |
878 |
if type(item) is not QGraphicsPixmapItem and item.scene() is not None: |
879 |
self.graphicsView.scene.removeItem(item)
|
880 |
|
881 |
appDocData.initializeDataByDrawingUID(appDocData.activeDrawing.UID) |
882 |
|
883 |
self.initTableWidgetHMB()
|
884 |
|
885 |
except Exception as ex: |
886 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
887 |
sys.exc_info()[-1].tb_lineno)
|
888 |
self.addMessage.emit(MessageType.Error, message)
|
889 |
|
890 |
'''
|
891 |
@brief Manage Checkable Action statement
|
892 |
@author Jeongwoo
|
893 |
@date 2018.05.10
|
894 |
@history 2018.06.27 Jeongwoo Chnage method to initialize command [Set None → DefaultCommand]
|
895 |
'''
|
896 |
|
897 |
def actionGroupTriggered(self, action): |
898 |
if hasattr(self.actionLine, 'tag'): |
899 |
self.actionLine.tag.onRejected.emit(None) |
900 |
|
901 |
if self.graphicsView.command is not None: |
902 |
self.graphicsView.useDefaultCommand()
|
903 |
|
904 |
for _action in [x for x in self.actionGroup.actions() if x is not action]: |
905 |
_action.setChecked(False)
|
906 |
if _action is self.actionLine: |
907 |
for item in self.graphicsView.scene.items(): |
908 |
if not hasattr(item, 'connectors'): continue |
909 |
for connector in item.connectors: connector.hide() |
910 |
|
911 |
action.setChecked(True)
|
912 |
if action is self.actionLine: |
913 |
for item in self.graphicsView.scene.items(): |
914 |
if not hasattr(item, 'connectors'): continue |
915 |
for connector in item.connectors: connector.setVisible(True) |
916 |
|
917 |
def showSymbolEditor(self): |
918 |
from SymbolEditorDialog import QSymbolEditorDialog |
919 |
|
920 |
dlg = QSymbolEditorDialog() |
921 |
dlg.exec_() |
922 |
|
923 |
def editor_lost_focus(self, item): |
924 |
cursor = item.textCursor() |
925 |
cursor.clearSelection() |
926 |
item.setTextCursor(cursor) |
927 |
|
928 |
"""
|
929 |
if item.toPlainText():
|
930 |
self.removeItem(item)
|
931 |
item.deleteLater()
|
932 |
"""
|
933 |
|
934 |
def item_selected(self, item): |
935 |
pass
|
936 |
"""
|
937 |
font = item.font()
|
938 |
color = item.defaultTextColor()
|
939 |
self.fontCombo.setCurrentFont(font)
|
940 |
self.fontSizeCombo.setEditText(str(font.pointSize()))
|
941 |
self.boldAction.setChecked(font.weight() == QFont.Bold)
|
942 |
self.italicAction.setChecked(font.italic())
|
943 |
self.underlineAction.setChecked(font.underline())
|
944 |
"""
|
945 |
|
946 |
def on_callout_created(self): |
947 |
try:
|
948 |
QApplication.restoreOverrideCursor() |
949 |
|
950 |
callout = self.actionPlaceTextBox.tag.callout
|
951 |
callout.setTextInteractionFlags(Qt.TextEditorInteraction) |
952 |
callout.setFocus() |
953 |
callout.lost_focus.connect(self.editor_lost_focus)
|
954 |
callout.selected_change.connect(self.item_selected)
|
955 |
finally:
|
956 |
self.actionPlaceTextBox.tag.reset()
|
957 |
|
958 |
def on_place_callout_textbox(self): |
959 |
"""place callout textbox"""
|
960 |
from PlaceCalloutCommand import PlaceCalloutCommand |
961 |
|
962 |
if not hasattr(self.actionPlaceTextBox, 'tag'): |
963 |
self.actionPlaceTextBox.tag = PlaceCalloutCommand(self.graphicsView) |
964 |
|
965 |
self.actionPlaceTextBox.tag.onSuccess.connect(self.on_callout_created) |
966 |
self.actionPlaceTextBox.tag.onRejected.connect(self.onCommandRejected) |
967 |
|
968 |
self.graphicsView.command = self.actionPlaceTextBox.tag |
969 |
|
970 |
def on_dimension_created(self): |
971 |
try:
|
972 |
QApplication.restoreOverrideCursor() |
973 |
|
974 |
dimension = self.actionPlaceDimension.tag.dimension
|
975 |
dimension.transfer.onRemoved.connect(self.on_item_removed)
|
976 |
finally:
|
977 |
self.actionPlaceDimension.tag.reset()
|
978 |
|
979 |
def on_place_dimension(self): |
980 |
"""place dimension"""
|
981 |
from PlaceDimensionCommand import PlaceDimensionCommand |
982 |
|
983 |
if not hasattr(self.actionPlaceDimension, 'tag'): |
984 |
self.actionPlaceDimension.tag = PlaceDimensionCommand(self.graphicsView) |
985 |
|
986 |
self.actionPlaceDimension.tag.onSuccess.connect(self.on_dimension_created) |
987 |
self.actionPlaceDimension.tag.onRejected.connect(self.onCommandRejected) |
988 |
|
989 |
self.graphicsView.command = self.actionPlaceDimension.tag |
990 |
|
991 |
def on_place_cloud(self): |
992 |
"""place a cloud"""
|
993 |
from PlaceCloudCommand import PlaceCloudCommand |
994 |
|
995 |
def on_cloud_created(): |
996 |
try:
|
997 |
QApplication.restoreOverrideCursor() |
998 |
|
999 |
cloud = self.actionPlaceCloud.tag.cloud
|
1000 |
finally:
|
1001 |
self.actionPlaceCloud.tag.reset()
|
1002 |
|
1003 |
if not hasattr(self.actionPlaceCloud, 'tag'): |
1004 |
self.actionPlaceCloud.tag = PlaceCloudCommand(self.graphicsView) |
1005 |
|
1006 |
self.actionPlaceCloud.tag.onSuccess.connect(on_cloud_created)
|
1007 |
self.actionPlaceCloud.tag.onRejected.connect(self.onCommandRejected) |
1008 |
|
1009 |
self.graphicsView.command = self.actionPlaceCloud.tag |
1010 |
|
1011 |
def on_help(self): |
1012 |
"""open user manual"""
|
1013 |
import os |
1014 |
|
1015 |
try:
|
1016 |
help_file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'HYTOS User Manual.pdf')
|
1017 |
os.startfile(f"\"{help_file_path}\"")
|
1018 |
# os.system(f"\"{help_file_path}\"")
|
1019 |
except Exception as ex: |
1020 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1021 |
sys.exc_info()[-1].tb_lineno)
|
1022 |
self.addMessage.emit(MessageType.Error, message)
|
1023 |
|
1024 |
def on_about(self): |
1025 |
"""show about dialog"""
|
1026 |
from AboutDialog import QAboutDialog |
1027 |
|
1028 |
dlg = QAboutDialog() |
1029 |
dlg.exec_() |
1030 |
|
1031 |
def update_label_contents(self): |
1032 |
from EngineeringCalloutTextItem import QEngineeringCalloutTextItem |
1033 |
|
1034 |
items = [item for item in self.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem) or |
1035 |
type(item) is QEngineeringStreamlineItem or type(item) is QEngineeringCalloutTextItem] |
1036 |
for item in items: |
1037 |
item.update_label_contents() |
1038 |
|
1039 |
def onOptions(self): |
1040 |
from OptionsDialog import QOptionsDialog |
1041 |
try:
|
1042 |
app_doc_data = AppDocData.instance() |
1043 |
configs = app_doc_data.getAppConfigs('option', 'TagFontSize') |
1044 |
old_tag_font_size = configs[0].value if configs and len(configs) == 1 else 6 |
1045 |
|
1046 |
configs = app_doc_data.getAppConfigs('option', 'TagFontColor') |
1047 |
old_tag_font_color = configs[0].value if configs and len(configs) == 1 else '#000000' |
1048 |
|
1049 |
configs = app_doc_data.getAppConfigs('option', 'CalloutFontSize') |
1050 |
old_callout_font_size = configs[0].value if configs and len(configs) == 1 else 6 |
1051 |
|
1052 |
configs = app_doc_data.getAppConfigs('option', 'CalloutTextColor') |
1053 |
old_callout_text_color = configs[0].value if configs and len(configs) == 1 else '#000000' |
1054 |
|
1055 |
dlg = QOptionsDialog(self)
|
1056 |
dlg.setWindowFlags(dlg.windowFlags() & ~Qt.WindowContextHelpButtonHint) |
1057 |
if QDialog.Accepted == dlg.exec_():
|
1058 |
if app_doc_data.activeDrawing:
|
1059 |
if str(old_tag_font_size) != str(dlg.tag_font_size) or \ |
1060 |
old_tag_font_color != dlg.tag_text_color or \
|
1061 |
str(old_callout_font_size) != str(dlg.callout_font_size) or \ |
1062 |
old_callout_text_color != dlg.callout_text_color: |
1063 |
self.update_label_contents()
|
1064 |
|
1065 |
except Exception as ex: |
1066 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1067 |
sys.exc_info()[-1].tb_lineno)
|
1068 |
self.addMessage.emit(MessageType.Error, message)
|
1069 |
|
1070 |
def calculation(self): |
1071 |
"""execute hydro calculation"""
|
1072 |
from AppDocData import AppDocData |
1073 |
from Calculation import Calculation |
1074 |
from HydroCalculationCommand import HydroCalculationCommand |
1075 |
from ValidationDialog import QValidationDialog |
1076 |
|
1077 |
try:
|
1078 |
app_doc_data = AppDocData.instance() |
1079 |
if app_doc_data.activeDrawing is None: |
1080 |
self.showImageSelectionMessageBox()
|
1081 |
return
|
1082 |
|
1083 |
hmbs = app_doc_data.activeDrawing.hmbTable._hmbs |
1084 |
if hmbs is not None: |
1085 |
try:
|
1086 |
errors = [] |
1087 |
items = [item for item in self.graphicsView.scene.items() if type(item) is SymbolSvgItem or |
1088 |
type(item) is QEngineeringStreamlineItem] |
1089 |
for item in items: |
1090 |
error = item.validate() |
1091 |
if error: errors.extend(error)
|
1092 |
|
1093 |
if errors:
|
1094 |
dlg = QValidationDialog(self, errors)
|
1095 |
dlg.show() |
1096 |
else:
|
1097 |
self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, self) \ |
1098 |
if not hasattr(self, 'progress') else self.progress |
1099 |
self.progress.setWindowModality(Qt.WindowModal)
|
1100 |
self.progress.setAutoReset(True) |
1101 |
self.progress.setAutoClose(True) |
1102 |
self.progress.setMinimum(0) |
1103 |
self.progress.resize(600, 100) |
1104 |
self.progress.setWindowTitle(self.tr("Calculate data...")) |
1105 |
self.progress.show()
|
1106 |
|
1107 |
maxValue = len(hmbs)
|
1108 |
self.progress.setMaximum(maxValue)
|
1109 |
|
1110 |
for hmb in hmbs: |
1111 |
self.progress.setValue(self.progress.value() + 1) |
1112 |
|
1113 |
if hmb.phase_type:
|
1114 |
Calculation(hmb) |
1115 |
|
1116 |
QApplication.processEvents() |
1117 |
|
1118 |
""" generate loop """
|
1119 |
cmd = HydroCalculationCommand(self.graphicsView)
|
1120 |
cmd.execute(None)
|
1121 |
cmd.execute_second(None)
|
1122 |
|
1123 |
app_doc_data.activeDrawing.loops = cmd.loops |
1124 |
|
1125 |
self.display_loops()
|
1126 |
self.display_output()
|
1127 |
|
1128 |
self.load_HMB()
|
1129 |
|
1130 |
app_doc_data.save_sheet_history('Calculation')
|
1131 |
finally:
|
1132 |
self.progress.setValue(self.progress.maximum()) |
1133 |
self.progress.hide()
|
1134 |
except Exception as ex: |
1135 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1136 |
sys.exc_info()[-1].tb_lineno)
|
1137 |
self.addMessage.emit(MessageType.Error, message)
|
1138 |
|
1139 |
def generate_report(self): |
1140 |
"""generate calculation report"""
|
1141 |
from tempfile import NamedTemporaryFile |
1142 |
import openpyxl |
1143 |
from DrawImage import DrawImage |
1144 |
from openpyxl.styles import Font |
1145 |
from datetime import datetime |
1146 |
from EngineeringStreamlineItem import QEngineeringStreamlineItem |
1147 |
|
1148 |
try:
|
1149 |
app_doc_data = AppDocData.instance() |
1150 |
if app_doc_data.activeDrawing is None: |
1151 |
self.showImageSelectionMessageBox()
|
1152 |
return
|
1153 |
|
1154 |
image_path = None
|
1155 |
with NamedTemporaryFile() as f: |
1156 |
image_path = f.name + '.png'
|
1157 |
|
1158 |
if image_path:
|
1159 |
self.on_view_connector(False) # hide connector |
1160 |
self.graphicsView.save_as_image(image_path)
|
1161 |
|
1162 |
workspace = self.get_work_space()
|
1163 |
file_name = os.path.join(workspace, app_doc_data.activeDrawing.name + '.xlsx')
|
1164 |
options = QFileDialog.Options() |
1165 |
options |= QFileDialog.DontUseNativeDialog |
1166 |
file_name, _ = QFileDialog.getSaveFileName(self, self.tr('Report'), file_name, 'Excel(*.xlsx)', |
1167 |
options=options) |
1168 |
|
1169 |
template = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME, 'Report_Template.xlsx') |
1170 |
|
1171 |
# get image file path
|
1172 |
company_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME, 'Company.png') |
1173 |
horizontal_flow_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME, 'Horizontal_Flow.png') |
1174 |
vertical_upward_flow_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME,
|
1175 |
'Vertical_Upward_Flow.png')
|
1176 |
vertical_downward_flow_image_path = os.path.join(os.getenv('ALLUSERSPROFILE'), App.NAME,
|
1177 |
'Vertical_Downward_Flow.png')
|
1178 |
# up to here
|
1179 |
if file_name and os.path.exists(template): |
1180 |
units = [attr[1] for attr in app_doc_data.activeDrawing.attrs if attr[0] == 'Units'][0] |
1181 |
|
1182 |
wb = openpyxl.load_workbook(template) |
1183 |
|
1184 |
page_no = 1
|
1185 |
pages = math.ceil(len(list(app_doc_data.activeDrawing.hmbTable.streamNos())) / 20) |
1186 |
for page in range(pages): |
1187 |
ws = wb.copy_worksheet(wb.get_sheet_by_name('Page'))
|
1188 |
ws.title = 'Page ({})'.format(page_no)
|
1189 |
|
1190 |
cal_image = openpyxl.drawing.image.Image(image_path) |
1191 |
x_scale, y_scale = 1, 1 |
1192 |
cal_image.width *= x_scale |
1193 |
cal_image.height *= y_scale |
1194 |
ws.add_image(cal_image, 'C4')
|
1195 |
|
1196 |
company_image = openpyxl.drawing.image.Image(company_image_path) |
1197 |
company_image.width *= 0.8
|
1198 |
company_image.height *= 0.7
|
1199 |
ws.add_image(company_image, 'W53')
|
1200 |
|
1201 |
"""write sheet information"""
|
1202 |
configs = app_doc_data.getConfigs('Sheet')
|
1203 |
for config in configs: |
1204 |
if config.key == 'JobNo' and config.value: |
1205 |
ws['Z58'].value = config.value
|
1206 |
elif config.key == 'JobName' and config.value: |
1207 |
ws['W59'].value = config.value
|
1208 |
elif config.key == 'Description' and config.value: |
1209 |
ws['W73'].value = config.value
|
1210 |
elif config.key == 'RevStatus' and config.value: |
1211 |
ws['Y68'].value = config.value
|
1212 |
elif config.key == 'CheckedBy' and config.value: |
1213 |
ws['Z78'].value = config.value
|
1214 |
elif config.key == 'ApprovedBy' and config.value: |
1215 |
ws['Z79'].value = config.value
|
1216 |
|
1217 |
configs = app_doc_data.getAppConfigs('app', 'SingleID') |
1218 |
if configs and configs[0].value: |
1219 |
ws['Z77'].value = configs[0].value |
1220 |
ws['Z68'].value = str(datetime.now().strftime('%Y-%m-%d %H:%M:%S')) |
1221 |
"""up to here"""
|
1222 |
|
1223 |
# Output [Pump, Compressor, Control Valve]
|
1224 |
ws['X1'].value = 'Loop_Deviation' |
1225 |
ws['X1'].font = Font(bold=True, underline='single', size=11) |
1226 |
|
1227 |
loops = app_doc_data.activeDrawing.loops |
1228 |
strmsg = None
|
1229 |
row_no = 2
|
1230 |
for loop in loops: |
1231 |
deviation = loop.deviation |
1232 |
if round(deviation, 9) == 0: |
1233 |
continue
|
1234 |
|
1235 |
for i in range(1, len(loop.items) - 1, 3): |
1236 |
if i == 1: |
1237 |
loop_no = loop.name.replace('Loop', '') |
1238 |
if len(loop_no) > 1: |
1239 |
strmsg = '({}) {}'.format(loop_no, loop.items[i].stream_no)
|
1240 |
else:
|
1241 |
strmsg = '(0{}) {}'.format(loop_no, loop.items[i].stream_no)
|
1242 |
else:
|
1243 |
if len(str(loop.items[i - 1])) > 13 and str(loop.items[i - 1])[ |
1244 |
:13] == 'Line_Splitter': |
1245 |
pre_stream_num = loop.items[i - 3].stream_no
|
1246 |
cur_stream_num = loop.items[i].stream_no |
1247 |
|
1248 |
if strmsg.__contains__('-'): |
1249 |
last_stream_num = str(strmsg).rsplit('-', 1)[1] |
1250 |
else:
|
1251 |
last_stream_num = str(strmsg).rsplit(' ', 1)[1] |
1252 |
|
1253 |
if pre_stream_num != int(last_stream_num): |
1254 |
strmsg = '{}-{}-{}'.format(strmsg, pre_stream_num, cur_stream_num)
|
1255 |
|
1256 |
last_stream_num = loop.items[len(loop.items) - 2].stream_no |
1257 |
strmsg = '{}-{}'.format(strmsg, last_stream_num)
|
1258 |
|
1259 |
value = '{} = {} {}'.format(strmsg, round(deviation, 3), units['Pressure']) |
1260 |
if round(deviation, 3) < 0: |
1261 |
ws.cell(row_no, 24, value).font = Font(underline='single', |
1262 |
size=10,
|
1263 |
color='FF0000')
|
1264 |
|
1265 |
elif round(deviation, 3) > 0: |
1266 |
ws.cell(row_no, 24, value).font = Font(size=10) |
1267 |
else:
|
1268 |
ws.cell(row_no, 24, value).font = Font(underline='single', |
1269 |
size=10)
|
1270 |
row_no += 1
|
1271 |
|
1272 |
start_row_no = row_no + 1
|
1273 |
start_col_no = 24
|
1274 |
# Pump
|
1275 |
pumps = [] |
1276 |
row_no = start_row_no |
1277 |
col_no = start_col_no |
1278 |
for loop in loops: |
1279 |
for item in loop.items: |
1280 |
parent = item.parent |
1281 |
if parent:
|
1282 |
name = str(item).replace(
|
1283 |
'_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '') |
1284 |
if name in pumps: |
1285 |
continue
|
1286 |
if name[:3] == 'R_P' or name[:3] == 'L_P' or name[:3] == 'V_P': |
1287 |
pumps.append(name) |
1288 |
|
1289 |
attr = item.parent.attribute |
1290 |
ws.cell(row_no, col_no, attr['Tag_No']).font = Font(bold=True, |
1291 |
underline='single',
|
1292 |
size=11)
|
1293 |
|
1294 |
row_no += 1
|
1295 |
ws.cell(row_no, col_no, 'Suct.P :')
|
1296 |
col_no += 2
|
1297 |
ws.cell(row_no, col_no, round(attr['Suct.P'], 3)) |
1298 |
col_no += 1
|
1299 |
ws.cell(row_no, col_no, '{}.g'.format(units['Pressure'])) |
1300 |
|
1301 |
row_no += 1
|
1302 |
col_no = 24 if col_no == 27 else 28 |
1303 |
ws.cell(row_no, col_no, 'Disc.P :')
|
1304 |
col_no += 2
|
1305 |
ws.cell(row_no, col_no, round(attr['Disc.P'], 3)) |
1306 |
col_no += 1
|
1307 |
ws.cell(row_no, col_no, '{}.g'.format(units['Pressure'])) |
1308 |
|
1309 |
row_no += 1
|
1310 |
col_no = 24 if col_no == 27 else 28 |
1311 |
ws.cell(row_no, col_no, 'Diff.P :')
|
1312 |
col_no += 2
|
1313 |
ws.cell(row_no, col_no, round(attr['Diff.P'], 3)) |
1314 |
col_no += 1
|
1315 |
ws.cell(row_no, col_no, units['Pressure'])
|
1316 |
|
1317 |
row_no += 1
|
1318 |
col_no = 24 if col_no == 27 else 28 |
1319 |
ws.cell(row_no, col_no, 'Head :')
|
1320 |
col_no += 2
|
1321 |
ws.cell(row_no, col_no, round(attr['Head'], 3)) |
1322 |
col_no += 1
|
1323 |
ws.cell(row_no, col_no, units['Length'])
|
1324 |
|
1325 |
row_no += 1
|
1326 |
col_no = 24 if col_no == 27 else 28 |
1327 |
ws.cell(row_no, col_no, 'NPSHa :')
|
1328 |
col_no += 2
|
1329 |
ws.cell(row_no, col_no, round(attr['NPSHa'], 3)) |
1330 |
col_no += 1
|
1331 |
ws.cell(row_no, col_no, units['Length'])
|
1332 |
|
1333 |
row_no += 1
|
1334 |
col_no = 24 if col_no == 27 else 28 |
1335 |
ws.cell(row_no, col_no, 'Vap. P :')
|
1336 |
col_no += 2
|
1337 |
ws.cell(row_no, col_no, attr['Vap. P'])
|
1338 |
col_no += 1
|
1339 |
ws.cell(row_no, col_no, '{}.a'.format(units['Pressure'])) |
1340 |
|
1341 |
row_no += 1
|
1342 |
col_no = 24 if col_no == 27 else 28 |
1343 |
ws.cell(row_no, col_no, 'HHP :')
|
1344 |
col_no += 2
|
1345 |
ws.cell(row_no, col_no, round(attr['HHP'], 3)) |
1346 |
col_no += 1
|
1347 |
ws.cell(row_no, col_no, units['Power'])
|
1348 |
|
1349 |
col_no = 28 if col_no == 27 else 24 |
1350 |
row_no = row_no - 7 if col_no == 28 else row_no + 2 |
1351 |
|
1352 |
start_row_no += math.ceil(len(pumps)) * 9 |
1353 |
|
1354 |
# Compressor
|
1355 |
compressors = [] |
1356 |
row_no = start_row_no |
1357 |
col_no = start_col_no |
1358 |
for loop in loops: |
1359 |
for item in loop.items: |
1360 |
parent = item.parent |
1361 |
if parent:
|
1362 |
name = str(item).replace(
|
1363 |
'_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '') |
1364 |
if name in compressors: |
1365 |
continue
|
1366 |
if name[:3] == 'R_K' or name[:3] == 'L_K': |
1367 |
compressors.append(name) |
1368 |
|
1369 |
attr = item.parent.attribute |
1370 |
ws.cell(row_no, col_no, attr['Tag_No']).font = Font(bold=True, |
1371 |
underline='single',
|
1372 |
size=11)
|
1373 |
|
1374 |
row_no += 1
|
1375 |
ws.cell(row_no, col_no, 'Suct.P :')
|
1376 |
col_no += 2
|
1377 |
ws.cell(row_no, col_no, round(attr['Suct.P'], 3)) |
1378 |
col_no += 1
|
1379 |
ws.cell(row_no, col_no, '{}.g'.format(units['Pressure'])) |
1380 |
|
1381 |
row_no += 1
|
1382 |
col_no = 24 if col_no == 27 else 28 |
1383 |
ws.cell(row_no, col_no, 'Disc.P :')
|
1384 |
col_no += 2
|
1385 |
ws.cell(row_no, col_no, round(attr['Disc.P'], 3)) |
1386 |
col_no += 1
|
1387 |
ws.cell(row_no, col_no, '{}.g'.format(units['Pressure'])) |
1388 |
|
1389 |
row_no += 1
|
1390 |
col_no = 24 if col_no == 27 else 28 |
1391 |
ws.cell(row_no, col_no, 'Diff.P :')
|
1392 |
col_no += 2
|
1393 |
ws.cell(row_no, col_no, round(attr['Diff.P'], 3)) |
1394 |
col_no += 1
|
1395 |
ws.cell(row_no, col_no, units['Pressure'])
|
1396 |
|
1397 |
row_no += 1
|
1398 |
col_no = 24 if col_no == 27 else 28 |
1399 |
ws.cell(row_no, col_no, 'HHP :')
|
1400 |
col_no += 2
|
1401 |
ws.cell(row_no, col_no, round(attr['HHP'], 3)) |
1402 |
col_no += 1
|
1403 |
ws.cell(row_no, col_no, units['Power'])
|
1404 |
|
1405 |
col_no = 28 if col_no == 27 else 24 |
1406 |
row_no = row_no - 4 if col_no == 28 else row_no + 2 |
1407 |
|
1408 |
start_row_no += math.ceil(len(compressors)) * 9 |
1409 |
|
1410 |
# Control Valve
|
1411 |
control_valves = [] |
1412 |
row_no = start_row_no |
1413 |
col_no = start_col_no |
1414 |
for loop in loops: |
1415 |
for item in loop.items: |
1416 |
parent = item.parent |
1417 |
if parent:
|
1418 |
name = str(item).replace(
|
1419 |
'_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '') |
1420 |
if name in control_valves: |
1421 |
continue
|
1422 |
if name[:3] == 'CV_': |
1423 |
control_valves.append(name) |
1424 |
|
1425 |
attr = item.parent.attribute |
1426 |
ws.cell(row_no, col_no, attr['Tag_No']).font = Font(bold=True, |
1427 |
underline='single',
|
1428 |
size=11)
|
1429 |
|
1430 |
row_no += 1
|
1431 |
ws.cell(row_no, col_no, 'Inlet P :')
|
1432 |
col_no += 2
|
1433 |
ws.cell(row_no, col_no, round(attr['Suct.P'], 3)) |
1434 |
col_no += 1
|
1435 |
ws.cell(row_no, col_no, '{}.g'.format(units['Pressure'])) |
1436 |
|
1437 |
row_no += 1
|
1438 |
col_no = 24 if col_no == 27 else 28 |
1439 |
ws.cell(row_no, col_no, 'Outlet P :')
|
1440 |
col_no += 2
|
1441 |
ws.cell(row_no, col_no, round(attr['Disc.P'], 3)) |
1442 |
col_no += 1
|
1443 |
ws.cell(row_no, col_no, '{}.g'.format(units['Pressure'])) |
1444 |
|
1445 |
row_no += 1
|
1446 |
col_no = 24 if col_no == 27 else 28 |
1447 |
ws.cell(row_no, col_no, 'Diff.P :')
|
1448 |
col_no += 2
|
1449 |
ws.cell(row_no, col_no, round(attr['Diff.P'], 3)) |
1450 |
col_no += 1
|
1451 |
ws.cell(row_no, col_no, units['Pressure'])
|
1452 |
|
1453 |
row_no += 1
|
1454 |
col_no = 24 if col_no == 27 else 28 |
1455 |
ws.cell(row_no, col_no, 'dP Ratio :')
|
1456 |
col_no += 2
|
1457 |
ws.cell(row_no, col_no, round(attr['dP Ratio'] * 100, 2)) |
1458 |
col_no += 1
|
1459 |
ws.cell(row_no, col_no, '%')
|
1460 |
|
1461 |
col_no = 28 if col_no == 27 else 24 |
1462 |
row_no = row_no - 4 if col_no == 28 else row_no + 2 |
1463 |
|
1464 |
# write hmb unit
|
1465 |
ws['B54'].value = '-' |
1466 |
ws['B55'].value = units['Pipe_Diameter'] |
1467 |
ws['B56'].value = units['Flowrate_Mass'] |
1468 |
ws['B57'].value = units['Flowrate_Volume'] |
1469 |
ws['B58'].value = units['Density'] |
1470 |
ws['B59'].value = units['Viscosity'] |
1471 |
ws['B60'].value = units['Temperature'] # Hidden |
1472 |
ws['B61'].value = '' # Hidden |
1473 |
ws['B62'].value = '' # Hidden |
1474 |
ws['B63'].value = '' # Hidden |
1475 |
ws['B64'].value = units['Pipe_Diameter'] # Hidden |
1476 |
ws['B65'].value = units['Pipe_Diameter'] # Hidden |
1477 |
ws['B66'].value = '' # Hidden |
1478 |
ws['B67'].value = units['Length'] |
1479 |
ws['B68'].value = units['Length'] |
1480 |
ws['B69'].value = units['Roughness'] |
1481 |
ws['B70'].value = units['Velocity'] # Hidden |
1482 |
ws['B71'].value = '{}/100{})'.format(units['Pressure'], units['Length']) # Hidden |
1483 |
ws['B73'].value = units['Velocity'] |
1484 |
ws['B74'].value = '' # Hidden |
1485 |
ws['B75'].value = '' # Hidden |
1486 |
ws['B76'].value = '{}/100{}'.format(units['Pressure'], units['Length']) |
1487 |
ws['B77'].value = units['Pressure'] |
1488 |
ws['B78'].value = units['Pressure'] |
1489 |
ws['B79'].value = '{}(g)'.format(units['Pressure']) |
1490 |
|
1491 |
page_no += 1
|
1492 |
|
1493 |
current_ws = wb.get_sheet_by_name('Page (1)')
|
1494 |
# write hmb data
|
1495 |
drawing = app_doc_data.activeDrawing |
1496 |
hmbs = drawing.hmbTable._hmbs |
1497 |
if hmbs is not None: |
1498 |
stream_count = 1
|
1499 |
col_no = 3
|
1500 |
for hmb in hmbs: |
1501 |
if hmb.isDeleted == True: |
1502 |
continue
|
1503 |
|
1504 |
ws = self.get_work_sheet(wb, stream_count)
|
1505 |
if ws != current_ws:
|
1506 |
current_ws = ws |
1507 |
col_no = 3
|
1508 |
|
1509 |
row_no = 53
|
1510 |
ws.cell(row_no, col_no, hmb.stream_no) |
1511 |
row_no += 1
|
1512 |
ws.cell(row_no, col_no, hmb.phase_type) |
1513 |
row_no += 1
|
1514 |
ws.cell(row_no, col_no, hmb.inside_pipe_size) |
1515 |
row_no += 1
|
1516 |
ws.cell(row_no, col_no, hmb.flowrate_mass) |
1517 |
row_no += 1
|
1518 |
ws.cell(row_no, col_no, hmb.flowrate_volume) |
1519 |
row_no += 1
|
1520 |
ws.cell(row_no, col_no, hmb.density) |
1521 |
row_no += 1
|
1522 |
ws.cell(row_no, col_no, hmb.viscosity) |
1523 |
row_no += 1
|
1524 |
ws.cell(row_no, col_no, hmb.temperature) |
1525 |
row_no += 1
|
1526 |
ws.cell(row_no, col_no, hmb.molecular_weight) |
1527 |
row_no += 1
|
1528 |
ws.cell(row_no, col_no, hmb.specific_heat_ratio) |
1529 |
row_no += 1
|
1530 |
ws.cell(row_no, col_no, hmb.compress_factor) |
1531 |
row_no += 1
|
1532 |
ws.cell(row_no, col_no, hmb.nominal_pipe_size) |
1533 |
row_no += 1
|
1534 |
ws.cell(row_no, col_no, hmb.inside_pipe_size) |
1535 |
row_no += 1
|
1536 |
ws.cell(row_no, col_no, hmb.schedule_no) |
1537 |
row_no += 1
|
1538 |
ws.cell(row_no, col_no, hmb.straight_length) |
1539 |
row_no += 1
|
1540 |
ws.cell(row_no, col_no, hmb.equivalent_length) |
1541 |
row_no += 1
|
1542 |
ws.cell(row_no, col_no, hmb.roughness) |
1543 |
row_no += 1
|
1544 |
ws.cell(row_no, col_no, hmb.limitation_velocity) |
1545 |
row_no += 1
|
1546 |
ws.cell(row_no, col_no, hmb.limitation_pressure_drop) |
1547 |
row_no += 2
|
1548 |
ws.cell(row_no, col_no, hmb.velocity) |
1549 |
row_no += 1
|
1550 |
ws.cell(row_no, col_no, hmb.reynolds) |
1551 |
row_no += 1
|
1552 |
ws.cell(row_no, col_no, hmb.friction_factor) |
1553 |
row_no += 1
|
1554 |
ws.cell(row_no, col_no, hmb.pressure_drop) |
1555 |
row_no += 1
|
1556 |
ws.cell(row_no, col_no, hmb.pressure_drop_friction) |
1557 |
row_no += 1
|
1558 |
ws.cell(row_no, col_no, hmb.pressure_drop_static) |
1559 |
row_no += 1
|
1560 |
ws.cell(row_no, col_no, hmb.pressure_pipe_end_point) |
1561 |
|
1562 |
col_no += 1
|
1563 |
stream_count += 1
|
1564 |
|
1565 |
# two_phase
|
1566 |
if hmbs is not None: |
1567 |
for hmb in hmbs: |
1568 |
if hmb.phase_type == 'Mixed': |
1569 |
lines = [item for item in self.graphicsView.scene.items() if type( |
1570 |
item) is QEngineeringStreamlineItem and str(item.uid) == str(hmb.components_uid)] |
1571 |
if lines:
|
1572 |
ws = wb.copy_worksheet(wb.get_sheet_by_name('Two_phase'))
|
1573 |
ws.title = 'Two Phase {}'.format(str(lines[0])) |
1574 |
|
1575 |
# Information
|
1576 |
ws['B5'].value = 'File : Two_Phase' |
1577 |
ws['B6'].value = 'Line : {}'.format(lines[0].stream_no) |
1578 |
ws['G6'].value = 'Made by : {}'.format(configs[0].value) |
1579 |
|
1580 |
# Process Data
|
1581 |
ws['C10'].value = units['Flowrate_Mass'] |
1582 |
ws['D10'].value = units['Density'] |
1583 |
ws['E10'].value = units['Viscosity'] |
1584 |
ws['F10'].value = '{}(g)'.format(units['Pressure']) |
1585 |
ws['G10'].value = units['Temperature'] |
1586 |
|
1587 |
ws['C11'].value = lines[0].data.liquid_flowrate_mass |
1588 |
ws['D11'].value = lines[0].data.liquid_density |
1589 |
ws['E11'].value = lines[0].data.liquid_viscosity |
1590 |
|
1591 |
ws['C12'].value = lines[0].data.vapor_flowrate_mass |
1592 |
ws['D12'].value = lines[0].data.vapor_density |
1593 |
ws['E12'].value = lines[0].data.vapor_viscosity |
1594 |
ws['F12'].value = lines[0].data.vapor_pressure |
1595 |
ws['G12'].value = lines[0].data.vapor_temperature |
1596 |
ws['H12'].value = lines[0].data.vapor_molecular_weight |
1597 |
ws['I12'].value = lines[0].data.vapor_compress_factor |
1598 |
|
1599 |
# Geometry Data
|
1600 |
ws['D16'].value = units['Pipe_Diameter'] |
1601 |
ws['E16'].value = units['Roughness'] |
1602 |
ws['F16'].value = units['Length'] |
1603 |
|
1604 |
row_no = 17
|
1605 |
for geometry in lines[0].mixed_geometry: |
1606 |
col_no = 3
|
1607 |
ws.cell(row_no, col_no, str(geometry[0])) # Element |
1608 |
col_no += 1
|
1609 |
ws.cell(row_no, col_no, |
1610 |
float(geometry[3]) if is_float(geometry[3]) else None) # ID |
1611 |
col_no += 1
|
1612 |
ws.cell(row_no, col_no, |
1613 |
float(geometry[4]) if is_float(geometry[4]) else None) # Roughness |
1614 |
col_no += 1
|
1615 |
ws.cell(row_no, col_no, |
1616 |
float(geometry[5]) if is_float(geometry[5]) else None) # Length |
1617 |
col_no += 1
|
1618 |
ws.cell(row_no, col_no, |
1619 |
float(geometry[6]) if is_float(geometry[6]) else None) # Angle |
1620 |
col_no += 1
|
1621 |
ws.cell(row_no, col_no, |
1622 |
float(geometry[7]) if is_float(geometry[7]) else None) # R/D |
1623 |
col_no += 1
|
1624 |
ws.cell(row_no, col_no, |
1625 |
float(geometry[9]) if is_float(geometry[9]) else None) # K |
1626 |
|
1627 |
row_no += 1
|
1628 |
|
1629 |
|
1630 |
# horizontal_flow_image = openpyxl.drawing.image.Image(horizontal_flow_image_path)
|
1631 |
# horizontal_flow_image.width *= 0.6
|
1632 |
# horizontal_flow_image.height *= 0.6
|
1633 |
# ws.add_image(horizontal_flow_image, 'L3')
|
1634 |
|
1635 |
# vertical_upward_flow_image = openpyxl.drawing.image.Image(
|
1636 |
# vertical_upward_flow_image_path)
|
1637 |
# vertical_upward_flow_image.width *= 0.6
|
1638 |
# vertical_upward_flow_image.height *= 0.6
|
1639 |
# ws.add_image(vertical_upward_flow_image, 'R3')
|
1640 |
|
1641 |
# vertical_downward_flow_image = openpyxl.drawing.image.Image(
|
1642 |
# vertical_downward_flow_image_path)
|
1643 |
# vertical_downward_flow_image.width *= 0.6
|
1644 |
# vertical_downward_flow_image.height *= 0.6
|
1645 |
# ws.add_image(vertical_downward_flow_image, 'Z3')
|
1646 |
|
1647 |
horizontal = DrawImage(horizontal_flow_image_path) |
1648 |
vertical_upward = DrawImage(vertical_upward_flow_image_path) |
1649 |
vertical_downward = DrawImage(vertical_downward_flow_image_path) |
1650 |
# Calculation Result
|
1651 |
row_no = 37
|
1652 |
for row in lines[0].mixed_pressure_variation: |
1653 |
col_no = 12
|
1654 |
ws.cell(row_no, col_no, str(row[0])) # Element |
1655 |
col_no += 1
|
1656 |
ws.cell(row_no, col_no, row[1]) # ID |
1657 |
col_no += 1
|
1658 |
ws.cell(row_no, col_no, row[2]) # Length |
1659 |
col_no += 1
|
1660 |
ws.cell(row_no, col_no, row[3]) # Angle |
1661 |
col_no += 1
|
1662 |
ws.cell(row_no, col_no, row[4]) # K |
1663 |
col_no += 1
|
1664 |
ws.cell(row_no, col_no, row[5]) # Pressure |
1665 |
col_no += 1
|
1666 |
ws.cell(row_no, col_no, row[6]) # Void |
1667 |
col_no += 1
|
1668 |
ws.cell(row_no, col_no, row[7]) # Quality |
1669 |
col_no += 1
|
1670 |
ws.cell(row_no, col_no, row[8]) # Density |
1671 |
col_no += 1
|
1672 |
ws.cell(row_no, col_no, row[9]) # V.Density |
1673 |
col_no += 1
|
1674 |
ws.cell(row_no, col_no, row[10]) # Mean.Vel |
1675 |
col_no += 1
|
1676 |
ws.cell(row_no, col_no, row[11]) # Max.Vel |
1677 |
col_no += 1
|
1678 |
ws.cell(row_no, col_no, row[12]) # Ero.Vel |
1679 |
col_no += 1
|
1680 |
ws.cell(row_no, col_no, row[13]) # X |
1681 |
col_no += 1
|
1682 |
ws.cell(row_no, col_no, row[14]) # Y |
1683 |
col_no += 1
|
1684 |
ws.cell(row_no, col_no, str(row[15]) if row[15] else '') # Regime |
1685 |
col_no += 1
|
1686 |
ws.cell(row_no, col_no, row[16]) # Friction |
1687 |
col_no += 1
|
1688 |
ws.cell(row_no, col_no, row[17]) # Gravity |
1689 |
col_no += 1
|
1690 |
ws.cell(row_no, col_no, row[18]) # Moment |
1691 |
col_no += 1
|
1692 |
ws.cell(row_no, col_no, row[19]) # Total |
1693 |
|
1694 |
# load_regime
|
1695 |
length = row[2]
|
1696 |
if length is not None: |
1697 |
x = float(row[13]) |
1698 |
y = float(row[14]) |
1699 |
|
1700 |
angle = float(row[3]) |
1701 |
if angle == 0: |
1702 |
# Horizontal
|
1703 |
left = 57 + (546 / (7 + 5)) * (math.log10(x) + 5) |
1704 |
top = 651 - (649 / (5 + 9)) * (math.log10(y) + 9) |
1705 |
horizontal.draw_regime(left, top, 8)
|
1706 |
elif angle > 0: |
1707 |
# Vertical Upward
|
1708 |
left = 59 + (538 / (7 - (-2))) * (math.log10(x) - (-2)) |
1709 |
top = 681 - (653 / (8 - (-5))) * (math.log10(y) - (-5)) |
1710 |
vertical_upward.draw_regime(left, top, 8)
|
1711 |
elif angle < 0: |
1712 |
# Vertical Downward
|
1713 |
left = 55 + (517 / (20 - 0)) * (x - 0) |
1714 |
top = 656 - (635 / (24 - 2)) * (y - 2) |
1715 |
vertical_downward.draw_regime(left, top, 8)
|
1716 |
row_no += 1
|
1717 |
|
1718 |
with NamedTemporaryFile() as f: |
1719 |
horizontal_image_path = f.name + '.png'
|
1720 |
horizontal.save_as(horizontal_image_path) |
1721 |
|
1722 |
horizontal_flow_image = openpyxl.drawing.image.Image(horizontal_image_path) |
1723 |
horizontal_flow_image.width *= 0.6
|
1724 |
horizontal_flow_image.height *= 0.6
|
1725 |
ws.add_image(horizontal_flow_image, 'L3')
|
1726 |
|
1727 |
with NamedTemporaryFile() as f: |
1728 |
vertical_upward_image_path = f.name + '.png'
|
1729 |
vertical_upward.save_as(vertical_upward_image_path) |
1730 |
|
1731 |
vertical_upward_flow_image = openpyxl.drawing.image.Image( |
1732 |
vertical_upward_image_path) |
1733 |
vertical_upward_flow_image.width *= 0.6
|
1734 |
vertical_upward_flow_image.height *= 0.6
|
1735 |
ws.add_image(vertical_upward_flow_image, 'R3')
|
1736 |
|
1737 |
with NamedTemporaryFile() as f: |
1738 |
vertical_downward_image_path = f.name + '.png'
|
1739 |
vertical_downward.save_as(vertical_downward_image_path) |
1740 |
|
1741 |
vertical_downward_flow_image = openpyxl.drawing.image.Image( |
1742 |
vertical_downward_image_path) |
1743 |
vertical_downward_flow_image.width *= 0.6
|
1744 |
vertical_downward_flow_image.height *= 0.6
|
1745 |
ws.add_image(vertical_downward_flow_image, 'Z3')
|
1746 |
|
1747 |
active_sheet = wb.get_sheet_by_name('Page (1)')
|
1748 |
if active_sheet:
|
1749 |
wb.active = active_sheet |
1750 |
|
1751 |
wb.get_sheet_by_name('Page').sheet_state = 'hidden' |
1752 |
wb.get_sheet_by_name('Two_phase').sheet_state = 'hidden' |
1753 |
|
1754 |
name_without_ext, ext = os.path.splitext(file_name) |
1755 |
save_file_name = file_name if ext.upper() == '.XLSX' else name_without_ext + '.xlsx' |
1756 |
wb.save(filename=save_file_name) |
1757 |
|
1758 |
os.startfile(save_file_name) |
1759 |
|
1760 |
QMessageBox.information(self, self.tr('Information'), self.tr('Report is done')) |
1761 |
except Exception as ex: |
1762 |
message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1763 |
sys.exc_info()[-1].tb_lineno)
|
1764 |
self.addMessage.emit(MessageType.Error, message)
|
1765 |
|
1766 |
def get_work_sheet(self, work_book, count): |
1767 |
page_no = math.ceil(count / 20)
|
1768 |
return work_book.get_sheet_by_name('Page ({})'.format(page_no)) |
1769 |
|
1770 |
def display_output(self): |
1771 |
try:
|
1772 |
""" display output """
|
1773 |
drawing = AppDocData.instance().activeDrawing |
1774 |
if drawing is None: |
1775 |
return
|
1776 |
|
1777 |
self.clear_output()
|
1778 |
|
1779 |
self.tableWidgetOutput.setColumnCount(3) |
1780 |
self.tableWidgetOutput.horizontalHeader().setVisible(False) |
1781 |
self.tableWidgetOutput.verticalHeader().setVisible(False) |
1782 |
self.tableWidgetOutput.setSelectionMode(QAbstractItemView.SingleSelection)
|
1783 |
self.tableWidgetOutput.setSelectionBehavior(QAbstractItemView.SelectRows)
|
1784 |
self.tableWidgetOutput.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
1785 |
self.tableWidgetOutput.horizontalHeader().setStretchLastSection(True) |
1786 |
|
1787 |
self.tableWidgetDeviation.setColumnCount(1) |
1788 |
self.tableWidgetDeviation.horizontalHeader().setVisible(False) |
1789 |
self.tableWidgetDeviation.verticalHeader().setVisible(False) |
1790 |
self.tableWidgetDeviation.setSelectionMode(QAbstractItemView.SingleSelection)
|
1791 |
self.tableWidgetDeviation.setSelectionBehavior(QAbstractItemView.SelectRows)
|
1792 |
self.tableWidgetDeviation.setEditTriggers(QAbstractItemView.NoEditTriggers)
|
1793 |
self.tableWidgetDeviation.horizontalHeader().setStretchLastSection(True) |
1794 |
self.tableWidgetDeviation.resizeRowsToContents()
|
1795 |
self.tableWidgetDeviation.resizeColumnsToContents()
|
1796 |
|
1797 |
units = [attr[1] for attr in drawing.attrs if attr[0] == 'Units'][0] |
1798 |
|
1799 |
loops = drawing.loops |
1800 |
|
1801 |
# Deviation
|
1802 |
self.add_data(self.tableWidgetDeviation, 'Loop_Deviation', None, None, True, None, None) |
1803 |
strmsg = None
|
1804 |
for loop in loops: |
1805 |
deviation = loop.deviation |
1806 |
if round(deviation, 9) == 0: |
1807 |
continue
|
1808 |
|
1809 |
for i in range(1, len(loop.items) - 1, 3): |
1810 |
if i == 1: |
1811 |
loop_no = loop.name.replace('Loop', '') |
1812 |
if len(loop_no) > 1: |
1813 |
strmsg = '({}) {}'.format(loop_no, loop.items[i].stream_no)
|
1814 |
else:
|
1815 |
strmsg = '(0{}) {}'.format(loop_no, loop.items[i].stream_no)
|
1816 |
else:
|
1817 |
if len(str(loop.items[i - 1])) > 13 and str(loop.items[i - 1])[:13] == 'Line_Splitter': |
1818 |
pre_stream_num = loop.items[i - 3].stream_no
|
1819 |
cur_stream_num = loop.items[i].stream_no |
1820 |
|
1821 |
if strmsg.__contains__('-'): |
1822 |
last_stream_num = str(strmsg).rsplit('-', 1)[1] |
1823 |
else:
|
1824 |
last_stream_num = str(strmsg).rsplit(' ', 1)[1] |
1825 |
|
1826 |
if pre_stream_num != int(last_stream_num): |
1827 |
strmsg = '{}-{}-{}'.format(strmsg, pre_stream_num, cur_stream_num)
|
1828 |
|
1829 |
last_stream_num = loop.items[len(loop.items) - 2].stream_no |
1830 |
strmsg = '{}-{}'.format(strmsg, last_stream_num)
|
1831 |
|
1832 |
if round(deviation, 3) < 0: |
1833 |
self.add_data(self.tableWidgetDeviation, |
1834 |
'{} = {} {}'.format(strmsg, round(deviation, 3), units['Pressure']), None, None, None, |
1835 |
None, QBrush(QColor(255, 0, 0))) |
1836 |
else:
|
1837 |
self.add_data(self.tableWidgetDeviation, |
1838 |
'{} = {} {}'.format(strmsg, round(deviation, 3), units['Pressure']), None, None, None, |
1839 |
None)
|
1840 |
|
1841 |
names = [] |
1842 |
# Pump
|
1843 |
for loop in loops: |
1844 |
for item in loop.items: |
1845 |
parent = item.parent |
1846 |
if parent:
|
1847 |
name = str(item).replace('_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '') |
1848 |
if name in names: |
1849 |
continue
|
1850 |
if name[:3] == 'R_P' or name[:3] == 'L_P' or name[:3] == 'V_P': |
1851 |
names.append(name) |
1852 |
attr = item.parent.attribute |
1853 |
if len(attr) > 0: |
1854 |
self.add_data(self.tableWidgetOutput, attr['Tag_No'], None, None, True, True) |
1855 |
self.add_data(self.tableWidgetOutput, 'Suct.P :', round(attr['Suct.P'], 3), |
1856 |
'{}.g'.format(units['Pressure'])) |
1857 |
self.add_data(self.tableWidgetOutput, 'Disc.P :', round(attr['Disc.P'], 3), |
1858 |
'{}.g'.format(units['Pressure'])) |
1859 |
self.add_data(self.tableWidgetOutput, 'Diff.P :', round(attr['Diff.P'], 3), |
1860 |
units['Pressure'])
|
1861 |
self.add_data(self.tableWidgetOutput, 'Head :', round(attr['Head'], 3), units['Length']) |
1862 |
self.add_data(self.tableWidgetOutput, 'NPSHa :', round(attr['NPSHa'], 3), units['Length']) |
1863 |
self.add_data(self.tableWidgetOutput, 'Vap. P :', attr['Vap. P'], |
1864 |
'{}.a'.format(units['Pressure'])) |
1865 |
self.add_data(self.tableWidgetOutput, 'HHP :', round(attr['HHP'], 3), units['Power']) |
1866 |
|
1867 |
# Compressor
|
1868 |
for loop in loops: |
1869 |
for item in loop.items: |
1870 |
parent = item.parent |
1871 |
if parent:
|
1872 |
name = str(item).replace('_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '') |
1873 |
if name in names: |
1874 |
continue
|
1875 |
if name[:3] == 'R_K' or name[:3] == 'L_K': |
1876 |
names.append(name) |
1877 |
|
1878 |
attr = item.parent.attribute |
1879 |
if len(attr) > 0: |
1880 |
self.add_data(self.tableWidgetOutput, attr['Tag_No'], None, None, True, True) |
1881 |
self.add_data(self.tableWidgetOutput, 'Suct.P :', round(attr['Suct.P'], 3), |
1882 |
'{}.g'.format(units['Pressure'])) |
1883 |
self.add_data(self.tableWidgetOutput, 'Disc.P :', round(attr['Disc.P'], 3), |
1884 |
'{}.g'.format(units['Pressure'])) |
1885 |
self.add_data(self.tableWidgetOutput, 'Diff.P :', round(attr['Diff.P'], 3), |
1886 |
units['Pressure'])
|
1887 |
self.add_data(self.tableWidgetOutput, 'HHP :', round(attr['HHP'], 3), units['Power']) |
1888 |
|
1889 |
# Control Valve
|
1890 |
for loop in loops: |
1891 |
for item in loop.items: |
1892 |
parent = item.parent |
1893 |
if parent:
|
1894 |
name = str(item).replace('_{}'.format(str(item).split('_')[len(str(item).split('_')) - 1]), '') |
1895 |
if name in names: |
1896 |
continue
|
1897 |
if name[:3] == 'CV_': |
1898 |
names.append(name) |
1899 |
|
1900 |
attr = item.parent.attribute |
1901 |
if len(attr) > 0: |
1902 |
self.add_data(self.tableWidgetOutput, attr['Tag_No'], None, None, True, True) |
1903 |
self.add_data(self.tableWidgetOutput, 'Inlet P :', round(attr['Suct.P'], 3), |
1904 |
'{}.g'.format(units['Pressure'])) |
1905 |
self.add_data(self.tableWidgetOutput, 'Outlet P :', round(attr['Disc.P'], 3), |
1906 |
'{}.g'.format(units['Pressure'])) |
1907 |
self.add_data(self.tableWidgetOutput, 'Diff.P :', round(attr['Diff.P'], 3), |
1908 |
units['Pressure'])
|
1909 |
self.add_data(self.tableWidgetOutput, 'dP Ratio :', round(attr['dP Ratio'] * 100, 2), '%') |
1910 |
|
1911 |
except Exception as ex: |
1912 |
message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1913 |
sys.exc_info()[-1].tb_lineno)
|
1914 |
self.addMessage.emit(MessageType.Error, message)
|
1915 |
|
1916 |
def display_loops(self): |
1917 |
""" display loops """
|
1918 |
drawing = AppDocData.instance().activeDrawing |
1919 |
if drawing is None: return |
1920 |
|
1921 |
loops = drawing.loops |
1922 |
if loops:
|
1923 |
self.tableWidgetLoop.clear()
|
1924 |
self.tableWidgetLoop.setColumnCount(len(loops) * 5) |
1925 |
|
1926 |
_col_names = [[loop.name, 'pressure', 'Static\nLine\ndP_Eq', 'El.\nDensity\nEl.', 'Extra'] for loop in |
1927 |
loops] |
1928 |
col_names = [] |
1929 |
for col_name in _col_names: col_names.extend(col_name) |
1930 |
self.tableWidgetLoop.setHorizontalHeaderLabels(col_names)
|
1931 |
self.tableWidgetLoop.horizontalHeader().setVisible(True) |
1932 |
|
1933 |
max_rows = 0
|
1934 |
for col in range(len(loops)): |
1935 |
rows = len(loops[col].items)
|
1936 |
max_rows = max(max_rows, rows)
|
1937 |
self.tableWidgetLoop.setRowCount(max_rows)
|
1938 |
|
1939 |
for row in range(len(loops[col].items)): |
1940 |
item = QTableWidgetItem(str(loops[col].items[row]))
|
1941 |
item.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter) |
1942 |
self.tableWidgetLoop.setItem(row, col * 5, item) |
1943 |
|
1944 |
# display calcuation values
|
1945 |
for row in range(len(loops[col].items)): |
1946 |
if loops[col].items[row] in loops[col].pressures: |
1947 |
item = QTableWidgetItem(str(round(loops[col].pressures[loops[col].items[row]], 8))) |
1948 |
item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) |
1949 |
# if not loops[col].pressures[loops[col].items[row]]: item.setBackground(Qt.red)
|
1950 |
self.tableWidgetLoop.setItem(row, col * 5 + 1, item) |
1951 |
|
1952 |
if loops[col].items[row] in loops[col].pressure_drops: |
1953 |
item = QTableWidgetItem(str(round(loops[col].pressure_drops[loops[col].items[row]], 9))) |
1954 |
item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) |
1955 |
# if not loops[col].pressure_drops[loops[col].items[row]]: item.setBackground(Qt.red)
|
1956 |
self.tableWidgetLoop.setItem(row, col * 5 + 2, item) |
1957 |
|
1958 |
if loops[col].items[row] in loops[col].density_elevations: |
1959 |
item = QTableWidgetItem(str(round(loops[col].density_elevations[loops[col].items[row]], 8))) |
1960 |
item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) |
1961 |
# if not loops[col].density_elevations[loops[col].items[row]]: item.setBackground(Qt.red)
|
1962 |
self.tableWidgetLoop.setItem(row, col * 5 + 3, item) |
1963 |
|
1964 |
if loops[col].items[row] in loops[col].extras: |
1965 |
item = QTableWidgetItem(str(loops[col].extras[loops[col].items[row]]))
|
1966 |
item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter) |
1967 |
# if not loops[col].density_elevations[loops[col].items[row]]: item.setBackground(Qt.red)
|
1968 |
self.tableWidgetLoop.setItem(row, col * 5 + 4, item) |
1969 |
|
1970 |
self.tableWidgetLoop.resizeColumnsToContents()
|
1971 |
self.tableWidgetLoop.resizeRowsToContents()
|
1972 |
|
1973 |
'''
|
1974 |
@brief configuration
|
1975 |
'''
|
1976 |
|
1977 |
def configuration(self): |
1978 |
from ConfigurationDialog import QConfigurationDialog |
1979 |
try:
|
1980 |
appDocData = AppDocData.instance() |
1981 |
if appDocData.activeDrawing is None: |
1982 |
self.showImageSelectionMessageBox()
|
1983 |
return
|
1984 |
|
1985 |
dlg = QConfigurationDialog(self)
|
1986 |
(isAccepted, isDataConversion, decimal) = dlg.show_dialog() |
1987 |
if isAccepted == True: |
1988 |
if isDataConversion == True: |
1989 |
self.data_conversion(decimal)
|
1990 |
else:
|
1991 |
self.reload_units()
|
1992 |
|
1993 |
except Exception as ex: |
1994 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
1995 |
sys.exc_info()[-1].tb_lineno)
|
1996 |
self.addMessage.emit(MessageType.Error, message)
|
1997 |
|
1998 |
def data_conversion(self, decimal): |
1999 |
from Drawing import Drawing |
2000 |
from Calculation import Conversion |
2001 |
|
2002 |
try:
|
2003 |
Conversion(decimal) |
2004 |
|
2005 |
self.load_HMB()
|
2006 |
self.reload_units()
|
2007 |
|
2008 |
except Exception as ex: |
2009 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
2010 |
sys.exc_info()[-1].tb_lineno)
|
2011 |
self.addMessage.emit(MessageType.Error, message)
|
2012 |
|
2013 |
'''
|
2014 |
@brief Show Image Selection Guide MessageBox
|
2015 |
@author Jeongwoo
|
2016 |
@date 2018.05.02
|
2017 |
'''
|
2018 |
|
2019 |
def showImageSelectionMessageBox(self): |
2020 |
QMessageBox.information(self, self.tr("Information"), self.tr("First select image drawing")) |
2021 |
|
2022 |
def display_colors(self, value): |
2023 |
""" display colors """
|
2024 |
from DisplayColors import DisplayColors |
2025 |
from DisplayColors import DisplayOptions |
2026 |
|
2027 |
DisplayColors.instance().option = DisplayOptions.DisplayByLineNo if value == True else DisplayOptions.DisplayByLineType |
2028 |
if hasattr(self, 'graphicsView'): |
2029 |
self.graphicsView.scene.update(self.graphicsView.sceneRect()) |
2030 |
DisplayColors.instance().save_data() |
2031 |
|
2032 |
'''
|
2033 |
@brief Open Border file
|
2034 |
@author yeonjin
|
2035 |
@date 2019.07.10
|
2036 |
'''
|
2037 |
|
2038 |
def open_border_file(self): |
2039 |
self.fitWindow(None) |
2040 |
|
2041 |
def patch_data(self): |
2042 |
try:
|
2043 |
# 2020.01.30 이전에 배포한 Template.db 업데이트 해주어야 함
|
2044 |
# Fitting K 값 Patch
|
2045 |
data = [] |
2046 |
data.append(['43d331ea-f66f-4ced-8a22-e94d43f2c74a', 40]) |
2047 |
data.append(['8b3224e1-784f-4203-9df5-14970f93d5d7', 28]) |
2048 |
data.append(['76d7a533-8bb2-42aa-a58a-b5a57fc1f73d', 24]) |
2049 |
data.append(['b2da93f1-c0d0-4592-897e-f55eeef8c472', 24]) |
2050 |
data.append(['6dada552-aed7-466b-b465-fa0de44a2160', 28]) |
2051 |
data.append(['ec1a9e7c-e2d9-4ebd-ac60-88fcec5a8eb3', 34]) |
2052 |
data.append(['8cbe9c68-5b05-470f-a39c-d271d7f63996', 48]) |
2053 |
data.append(['94d8bdc9-a044-4531-b6eb-f481396f1b9c', 60]) |
2054 |
data.append(['c8e9448f-e3e3-4b8a-b29c-2a75eeec3a33', 68]) |
2055 |
data.append(['92b6fe36-8af8-49cc-a760-4506592bcc0e', 76]) |
2056 |
data.append(['f83ce443-431e-44c0-9aab-2640b15c828c', 84]) |
2057 |
data.append(['65a9d9b2-adde-48d4-87bb-4288ade1c195', 100]) |
2058 |
|
2059 |
app_doc_data = AppDocData.instance() |
2060 |
app_doc_data.update_fittings(data) |
2061 |
|
2062 |
except Exception as ex: |
2063 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
2064 |
sys.exc_info()[-1].tb_lineno)
|
2065 |
self.addMessage.emit(MessageType.Error, message)
|
2066 |
|
2067 |
def setAttributes(self, drawing): |
2068 |
drawing.setAttributes() |
2069 |
|
2070 |
'''
|
2071 |
@brief Reload HMB Units
|
2072 |
@author yeonjin
|
2073 |
@date 2019.07.10
|
2074 |
'''
|
2075 |
|
2076 |
def reload_units(self): |
2077 |
from Drawing import Drawing |
2078 |
|
2079 |
try:
|
2080 |
app_doc_data = AppDocData.instance() |
2081 |
drawing = app_doc_data.activeDrawing |
2082 |
|
2083 |
self.setAttributes(drawing)
|
2084 |
|
2085 |
columnInfos = app_doc_data.getHMBDisplayNameAndUnitsExpression() |
2086 |
|
2087 |
rowIndex = 0
|
2088 |
for columnInfo in columnInfos: |
2089 |
name = columnInfo[0]
|
2090 |
unit = self.convertToUnits(columnInfo[1]) |
2091 |
|
2092 |
self.tableWidgetHMB.setItem(rowIndex, 0, |
2093 |
set_item_properties(name, Qt.AlignLeft | Qt.AlignVCenter, |
2094 |
QColor(51, 153, |
2095 |
102)))
|
2096 |
# QColor(230, 230, 230)))
|
2097 |
self.tableWidgetHMB.setItem(rowIndex, 1, |
2098 |
set_item_properties(unit, Qt.AlignHCenter | Qt.AlignVCenter, |
2099 |
QColor(204, 255, 204))) |
2100 |
# QColor(230, 230, 230)))
|
2101 |
|
2102 |
rowIndex += 1
|
2103 |
|
2104 |
self.tableWidgetHMB.resizeColumnsToContents()
|
2105 |
self.tableWidgetHMB.resizeRowsToContents()
|
2106 |
|
2107 |
except Exception as ex: |
2108 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
2109 |
sys.exc_info()[-1].tb_lineno)
|
2110 |
self.addMessage.emit(MessageType.Error, message)
|
2111 |
|
2112 |
def load_data(self, drawing): |
2113 |
""" load data from drawing """
|
2114 |
from AppDocData import AppDocData |
2115 |
from Calculation import Calculation |
2116 |
from HydroCalculationCommand import HydroCalculationCommand |
2117 |
from Drawing import Drawing |
2118 |
|
2119 |
try:
|
2120 |
app_doc_data = AppDocData.instance() |
2121 |
|
2122 |
self.graphicsView.scene.clear()
|
2123 |
# Set appDocData
|
2124 |
app_doc_data.clear() |
2125 |
self.onCommandRejected()
|
2126 |
app_doc_data.activeDrawing = drawing |
2127 |
|
2128 |
app_doc_data.build_drawing_database(drawing.path) |
2129 |
self.patch_data()
|
2130 |
|
2131 |
self.setAttributes(drawing)
|
2132 |
self.setMainWindowTitle(drawing.path)
|
2133 |
self.initTableWidgetHMB()
|
2134 |
self.clear_loop()
|
2135 |
self.clearlogs()
|
2136 |
self.clear_output()
|
2137 |
# Load data on database
|
2138 |
|
2139 |
self.symbolTreeWidget.initSymbolTreeWidget()
|
2140 |
|
2141 |
components = app_doc_data.getComponentListByDrawingUID() |
2142 |
count = len(components)
|
2143 |
|
2144 |
if count > 0: |
2145 |
try:
|
2146 |
self.progress = QProgressDialog(self.tr("Please wait for a while"), self.tr("Cancel"), 0, 100, |
2147 |
self) if not hasattr(self, 'progress') else self.progress |
2148 |
self.progress.setWindowModality(Qt.WindowModal)
|
2149 |
self.progress.setAutoReset(True) |
2150 |
self.progress.setAutoClose(True) |
2151 |
self.progress.setMinimum(0) |
2152 |
self.progress.resize(600, 100) |
2153 |
self.progress.setWindowTitle(self.tr("Load data...")) |
2154 |
self.progress.show()
|
2155 |
|
2156 |
self.load_components(components)
|
2157 |
|
2158 |
# Loops 와 Output 을 만들기 위해 Calculation 을 한다
|
2159 |
for hmb in app_doc_data.activeDrawing.hmbTable._hmbs: |
2160 |
if hmb.phase_type:
|
2161 |
Calculation(hmb) |
2162 |
cmd = HydroCalculationCommand(self.graphicsView)
|
2163 |
cmd.execute(None)
|
2164 |
cmd.execute_second(None)
|
2165 |
|
2166 |
app_doc_data.activeDrawing.loops = cmd.loops |
2167 |
|
2168 |
self.display_loops()
|
2169 |
self.display_output()
|
2170 |
|
2171 |
self.load_HMB()
|
2172 |
finally:
|
2173 |
self.progress.setValue(self.progress.maximum()) |
2174 |
self.progress.hide()
|
2175 |
|
2176 |
# self.changeViewCheckedState(False)
|
2177 |
|
2178 |
except Exception as ex: |
2179 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
2180 |
sys.exc_info()[-1].tb_lineno)
|
2181 |
self.addMessage.emit(MessageType.Error, message)
|
2182 |
|
2183 |
def saveAs_drawing(self, sourceDb): |
2184 |
import uuid |
2185 |
from shutil import copyfile |
2186 |
from datetime import datetime |
2187 |
from Drawing import Drawing |
2188 |
|
2189 |
workspace = self.get_work_space()
|
2190 |
|
2191 |
options = QFileDialog.Options() |
2192 |
options |= QFileDialog.DontUseNativeDialog |
2193 |
name, _ = QFileDialog.getSaveFileName(self, self.tr('Save As'), workspace, 'HYTOS Files (*.hytos)', |
2194 |
options=options) |
2195 |
if name:
|
2196 |
if os.path.splitext(name)[1] != '.hytos': name += '.hytos' |
2197 |
|
2198 |
app_doc_data = AppDocData.instance() |
2199 |
# copy template.db to name
|
2200 |
copyfile(sourceDb, name) |
2201 |
|
2202 |
matches = [drawing for drawing in app_doc_data.getDrawings() if |
2203 |
os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
|
2204 |
if not matches: |
2205 |
drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
2206 |
app_doc_data.saveDrawing(drawing) |
2207 |
else:
|
2208 |
drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
2209 |
app_doc_data.updateDrawing(drawing) |
2210 |
|
2211 |
self.load_drawing_list()
|
2212 |
self.load_data(drawing)
|
2213 |
self.open_border_file()
|
2214 |
|
2215 |
'''
|
2216 |
@brief create new drawing
|
2217 |
@author yeonjin
|
2218 |
@date 2019.07.03
|
2219 |
'''
|
2220 |
|
2221 |
def new_drawing(self): |
2222 |
import uuid |
2223 |
from shutil import copyfile |
2224 |
from datetime import datetime |
2225 |
from Drawing import Drawing |
2226 |
|
2227 |
self.save_drawing_if_necessary()
|
2228 |
|
2229 |
workspace = self.get_work_space()
|
2230 |
|
2231 |
options = QFileDialog.Options() |
2232 |
options |= QFileDialog.DontUseNativeDialog |
2233 |
name, _ = QFileDialog.getSaveFileName(self, self.tr('New'), workspace, 'HYTOS Files (*.hytos)', options=options) |
2234 |
if name:
|
2235 |
if os.path.splitext(name)[1] != '.hytos': name += '.hytos' |
2236 |
|
2237 |
app_doc_data = AppDocData.instance() |
2238 |
# copy template.db to name
|
2239 |
copyfile(app_doc_data.getTemplateDbPath(), name) |
2240 |
|
2241 |
matches = [drawing for drawing in app_doc_data.getDrawings() if |
2242 |
os.path.exists(drawing.path) and os.path.samefile(drawing.path, name)]
|
2243 |
if not matches: |
2244 |
drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
2245 |
app_doc_data.saveDrawing(drawing) |
2246 |
else:
|
2247 |
drawing = Drawing(str(matches[0].UID), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
2248 |
app_doc_data.updateDrawing(drawing) |
2249 |
|
2250 |
self.load_drawing_list()
|
2251 |
self.open_border_file()
|
2252 |
self.load_data(drawing)
|
2253 |
|
2254 |
def on_open_drawing(self): |
2255 |
"""open selected drawing by user"""
|
2256 |
|
2257 |
self.save_drawing_if_necessary()
|
2258 |
|
2259 |
workspace = self.get_work_space()
|
2260 |
options = QFileDialog.Options() |
2261 |
options |= QFileDialog.DontUseNativeDialog |
2262 |
name, _ = QFileDialog.getOpenFileName(self, self.tr('Open'), workspace, 'HYTOS File(*.hytos)', options=options) |
2263 |
if name:
|
2264 |
self.open_drawing(name)
|
2265 |
|
2266 |
def open_drawing(self, name): |
2267 |
"""open given drawing has name"""
|
2268 |
import uuid |
2269 |
from Drawing import Drawing |
2270 |
from datetime import datetime |
2271 |
|
2272 |
app_doc_data = AppDocData.instance() |
2273 |
drawings = app_doc_data.getDrawings() |
2274 |
matches = [drawing for drawing in drawings if os.path.samefile(drawing.path, name)] |
2275 |
if not matches: |
2276 |
drawing = Drawing(str(uuid.uuid4()), name, str(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) |
2277 |
app_doc_data.saveDrawing(drawing) |
2278 |
|
2279 |
self.load_drawing_list()
|
2280 |
else:
|
2281 |
drawing = matches[0]
|
2282 |
|
2283 |
# disconnect scene changed if signal is connected
|
2284 |
if self.graphicsView.scene.receivers(self.graphicsView.scene.contents_changed) > 0: |
2285 |
self.graphicsView.scene.contents_changed.disconnect()
|
2286 |
|
2287 |
self.load_data(drawing)
|
2288 |
self.open_border_file()
|
2289 |
|
2290 |
# connect scene changed signal
|
2291 |
self.graphicsView.scene.contents_changed.connect(self.scene_changed) |
2292 |
|
2293 |
def get_work_space(self): |
2294 |
"""get work space path"""
|
2295 |
app_doc_data = AppDocData.instance() |
2296 |
|
2297 |
configs = app_doc_data.getAppConfigs('option', 'WorkSpace') |
2298 |
if configs and len(configs) == 1: |
2299 |
return configs[0].value |
2300 |
else:
|
2301 |
return os.getcwd()
|
2302 |
|
2303 |
def changeViewCheckedState(self, checked, clear=True): |
2304 |
'''change view checked state'''
|
2305 |
if clear:
|
2306 |
self.initTableWidgetHMB()
|
2307 |
# self.clear_data()
|
2308 |
|
2309 |
'''
|
2310 |
@brief create a line
|
2311 |
@author humkyung
|
2312 |
@history Jeongwoo 2018.05.10 Change method for Checkable action
|
2313 |
'''
|
2314 |
|
2315 |
def onPlaceLine(self): |
2316 |
self.actionLine.setChecked(True) |
2317 |
if not hasattr(self.actionLine, 'tag'): |
2318 |
self.actionLine.tag = PlaceStreamlineCommand.PlaceStreamlineCommand(self.graphicsView) |
2319 |
self.actionLine.tag.onSuccess.connect(self.onLineCreated) |
2320 |
self.actionLine.tag.onRejected.connect(self.onCommandRejected) |
2321 |
|
2322 |
self.graphicsView.command = self.actionLine.tag |
2323 |
|
2324 |
'''
|
2325 |
@brief add created lines to scene
|
2326 |
@author humkyung
|
2327 |
@date 2018.07.23
|
2328 |
'''
|
2329 |
|
2330 |
def onLineCreated(self): |
2331 |
try:
|
2332 |
count = len(self.actionLine.tag.streamline._vertices) |
2333 |
if count > 1: |
2334 |
self.add_hmb_data(self.actionLine.tag.streamline) |
2335 |
self.actionLine.tag.streamline.transfer.onRemoved.connect(self.on_item_removed) |
2336 |
self.load_HMB()
|
2337 |
finally:
|
2338 |
self.actionLine.tag.reset()
|
2339 |
|
2340 |
def on_stream_line_deleted(self, stream_line): |
2341 |
""" callback after stream line is deleted """
|
2342 |
app_doc_data = AppDocData.instance() |
2343 |
activeDrawing = app_doc_data.activeDrawing |
2344 |
if activeDrawing:
|
2345 |
activeDrawing.hmbTable.deleteByUID(stream_line.uid) |
2346 |
|
2347 |
self.load_HMB()
|
2348 |
|
2349 |
def add_hmb_data(self, stream_line): |
2350 |
""" add a new hmb data associated with given stream line """
|
2351 |
from HMBTable import HMBTable |
2352 |
import uuid |
2353 |
|
2354 |
try:
|
2355 |
drawing = AppDocData.instance().activeDrawing |
2356 |
if drawing:
|
2357 |
components_uid = stream_line.uid |
2358 |
stream_no = self.get_next_stream_no(drawing)
|
2359 |
stream_line.stream_no = stream_no |
2360 |
drawing.hmbTable.add(components_uid, stream_no) |
2361 |
except Exception as ex: |
2362 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
2363 |
sys.exc_info()[-1].tb_lineno)
|
2364 |
self.addMessage.emit(MessageType.Error, message)
|
2365 |
|
2366 |
def get_next_stream_no(self, drawing): |
2367 |
|
2368 |
if len(list(drawing.hmbTable.streamNos())) == 0: |
2369 |
return 1 |
2370 |
else:
|
2371 |
streamNos = sorted(list(drawing.hmbTable.streamNos())) |
2372 |
lastStreamNo = streamNos[-1]
|
2373 |
return lastStreamNo + 1 |
2374 |
|
2375 |
def clear_HMB(self): |
2376 |
self.tableWidgetHMB.clearContents()
|
2377 |
self.tableWidgetHMB.setColumnCount(0) |
2378 |
|
2379 |
def load_HMB(self): |
2380 |
drawing = AppDocData.instance().activeDrawing |
2381 |
if drawing is None: return |
2382 |
|
2383 |
hmbs = drawing.hmbTable._hmbs |
2384 |
if hmbs is not None: |
2385 |
self.tableWidgetHMB.setColumnCount(2) |
2386 |
|
2387 |
col_names = ['Stream No.', 'Unit'] |
2388 |
for hmb in hmbs: |
2389 |
columnCount = self.tableWidgetHMB.columnCount()
|
2390 |
self.tableWidgetHMB.setColumnCount(columnCount + 1) |
2391 |
col_names.append(str(hmb.stream_no))
|
2392 |
|
2393 |
self.tableWidgetHMB.setItem(0, columnCount, set_item_properties(hmb.uid, |
2394 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2395 |
self.tableWidgetHMB.setItem(1, columnCount, set_item_properties(hmb.components_uid, |
2396 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2397 |
self.tableWidgetHMB.setItem(2, columnCount, set_item_properties(hmb.stream_no, |
2398 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2399 |
self.tableWidgetHMB.setItem(3, columnCount, set_item_properties(hmb.phase_type, |
2400 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2401 |
self.tableWidgetHMB.setItem(4, columnCount, |
2402 |
set_item_properties(convert_to_fixed_point(hmb.flowrate_mass), |
2403 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2404 |
self.tableWidgetHMB.setItem(5, columnCount, |
2405 |
set_item_properties(convert_to_fixed_point(hmb.flowrate_volume), |
2406 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2407 |
self.tableWidgetHMB.setItem(6, columnCount, |
2408 |
set_item_properties(convert_to_fixed_point(hmb.density), |
2409 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2410 |
self.tableWidgetHMB.setItem(7, columnCount, |
2411 |
set_item_properties(convert_to_fixed_point(hmb.viscosity), |
2412 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2413 |
self.tableWidgetHMB.setItem(8, columnCount, |
2414 |
set_item_properties(convert_to_fixed_point(hmb.temperature), |
2415 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2416 |
self.tableWidgetHMB.setItem(9, columnCount, |
2417 |
set_item_properties(convert_to_fixed_point(hmb.molecular_weight), |
2418 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2419 |
self.tableWidgetHMB.setItem(10, columnCount, |
2420 |
set_item_properties(convert_to_fixed_point(hmb.specific_heat_ratio), |
2421 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2422 |
self.tableWidgetHMB.setItem(11, columnCount, |
2423 |
set_item_properties(convert_to_fixed_point(hmb.compress_factor), |
2424 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2425 |
self.tableWidgetHMB.setItem(12, columnCount, |
2426 |
set_item_properties(convert_to_fixed_point(hmb.nominal_pipe_size), |
2427 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2428 |
self.tableWidgetHMB.setItem(13, columnCount, |
2429 |
set_item_properties(convert_to_fixed_point(hmb.inside_pipe_size), |
2430 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2431 |
self.tableWidgetHMB.setItem(14, columnCount, |
2432 |
set_item_properties(convert_to_fixed_point(hmb.schedule_no), |
2433 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2434 |
self.tableWidgetHMB.setItem(15, columnCount, |
2435 |
set_item_properties(convert_to_fixed_point(hmb.straight_length), |
2436 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2437 |
self.tableWidgetHMB.setItem(16, columnCount, |
2438 |
set_item_properties(convert_to_fixed_point(hmb.equivalent_length), |
2439 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2440 |
|
2441 |
self.tableWidgetHMB.setItem(17, columnCount, |
2442 |
set_item_properties( |
2443 |
convert_to_fixed_point(hmb.equivalent_length_input), |
2444 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2445 |
self.tableWidgetHMB.setItem(18, columnCount, |
2446 |
set_item_properties(convert_to_fixed_point(hmb.fitting_length), |
2447 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2448 |
self.tableWidgetHMB.setItem(19, columnCount, |
2449 |
set_item_properties(convert_to_fixed_point(hmb.fitting_K), |
2450 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2451 |
self.tableWidgetHMB.setItem(20, columnCount, |
2452 |
set_item_properties(convert_to_fixed_point(hmb.equivalent_length_cal), |
2453 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2454 |
self.tableWidgetHMB.setItem(21, columnCount, |
2455 |
set_item_properties(convert_to_fixed_point(hmb.roughness), |
2456 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2457 |
self.tableWidgetHMB.setItem(22, columnCount, |
2458 |
set_item_properties(convert_to_fixed_point(hmb.limitation_velocity), |
2459 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2460 |
self.tableWidgetHMB.setItem(23, columnCount, |
2461 |
set_item_properties( |
2462 |
convert_to_fixed_point(hmb.limitation_pressure_drop), |
2463 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2464 |
|
2465 |
self.tableWidgetHMB.setItem(24, columnCount, set_item_properties(None, |
2466 |
Qt.AlignHCenter | Qt.AlignVCenter, |
2467 |
QColor(153, 204, 255))) |
2468 |
|
2469 |
self.tableWidgetHMB.setItem(25, columnCount, |
2470 |
set_item_properties(convert_to_fixed_point(hmb.velocity), |
2471 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2472 |
self.tableWidgetHMB.setItem(26, columnCount, |
2473 |
set_item_properties(convert_to_fixed_point(hmb.reynolds), |
2474 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2475 |
self.tableWidgetHMB.setItem(27, columnCount, |
2476 |
set_item_properties(convert_to_fixed_point(hmb.friction_factor), |
2477 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2478 |
self.tableWidgetHMB.setItem(28, columnCount, |
2479 |
set_item_properties(convert_to_fixed_point(hmb.pressure_drop), |
2480 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2481 |
self.tableWidgetHMB.setItem(29, columnCount, |
2482 |
set_item_properties(convert_to_fixed_point(hmb.pressure_drop_friction), |
2483 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2484 |
self.tableWidgetHMB.setItem(30, columnCount, |
2485 |
set_item_properties(convert_to_fixed_point(hmb.pressure_drop_static), |
2486 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2487 |
self.tableWidgetHMB.setItem(31, columnCount, |
2488 |
set_item_properties( |
2489 |
convert_to_fixed_point(hmb.pressure_pipe_end_point), |
2490 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2491 |
self.tableWidgetHMB.setItem(32, columnCount, set_item_properties(convert_to_fixed_point(hmb.power), |
2492 |
Qt.AlignHCenter | Qt.AlignVCenter)) |
2493 |
|
2494 |
if hmb.isDeleted: self.tableWidgetHMB.hideColumn(columnCount) |
2495 |
|
2496 |
self.tableWidgetHMB.setHorizontalHeaderLabels(col_names)
|
2497 |
|
2498 |
self.tableWidgetHMB.resizeColumnsToContents()
|
2499 |
self.tableWidgetHMB.resizeRowsToContents()
|
2500 |
|
2501 |
'''
|
2502 |
@brief refresh scene
|
2503 |
@author humkyung
|
2504 |
@date 2018.07.23
|
2505 |
'''
|
2506 |
|
2507 |
def onCommandRejected(self, cmd=None): |
2508 |
try:
|
2509 |
if type(cmd) is PlaceStreamlineCommand.PlaceStreamlineCommand: |
2510 |
if self.actionLine.tag.streamline: |
2511 |
self.graphicsView.scene.removeItem(self.actionLine.tag.streamline) |
2512 |
self.graphicsView.scene.update()
|
2513 |
self.actionLine.tag.reset()
|
2514 |
|
2515 |
self.actionLine.setChecked(False) |
2516 |
elif type(cmd) is AreaZoomCommand.AreaZoomCommand: |
2517 |
self.actionZoom.setChecked(False) |
2518 |
else:
|
2519 |
if hasattr(self.actionLine, 'tag') and self.actionLine.tag.streamline: |
2520 |
self.graphicsView.scene.removeItem(self.actionLine.tag.streamline) |
2521 |
self.graphicsView.scene.update()
|
2522 |
self.actionLine.tag.reset()
|
2523 |
|
2524 |
self.actionLine.setChecked(False) |
2525 |
self.actionZoom.setChecked(False) |
2526 |
finally:
|
2527 |
self.graphicsView.useDefaultCommand()
|
2528 |
|
2529 |
'''
|
2530 |
@brief restore to default command when user press Escape key
|
2531 |
@author humkyung
|
2532 |
@date 2018.08.09
|
2533 |
|
2534 |
'''
|
2535 |
|
2536 |
def keyPressEvent(self, event): |
2537 |
try:
|
2538 |
if event.key() == Qt.Key_Escape:
|
2539 |
self.graphicsView.useDefaultCommand()
|
2540 |
elif (event.key() == Qt.Key_C) and (event.modifiers() & Qt.ControlModifier): |
2541 |
if self.tableWidgetHMB.hasFocus(): |
2542 |
self.copy_selection(self.tableWidgetHMB) |
2543 |
elif (event.key() == Qt.Key_V) and (event.modifiers() & Qt.ControlModifier): |
2544 |
if self.tableWidgetHMB.hasFocus(): |
2545 |
self.paste_selection(self.tableWidgetHMB) |
2546 |
|
2547 |
QMainWindow.keyPressEvent(self, event)
|
2548 |
except Exception as ex: |
2549 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
2550 |
sys.exc_info()[-1].tb_lineno)
|
2551 |
self.addMessage.emit(MessageType.Error, message)
|
2552 |
|
2553 |
def on_item_removed(self, item): |
2554 |
"""remove item from tree widget and then remove from scene"""
|
2555 |
|
2556 |
try:
|
2557 |
matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'connectors') and \ |
2558 |
[connector for connector in _item.connectors if |
2559 |
connector.connectedItem is not None and connector.connectedItem.parentItem() is item]] |
2560 |
# disconnect deleted item
|
2561 |
for match in matches: |
2562 |
for connector in match.connectors: |
2563 |
if connector.connectedItem and connector.connectedItem.parentItem() is item: |
2564 |
connector.connect(None)
|
2565 |
|
2566 |
matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'owner')] |
2567 |
for match in matches: |
2568 |
if match.owner is item: |
2569 |
match.owner = None
|
2570 |
|
2571 |
matches = [_item for _item in self.graphicsView.scene.items() if hasattr(_item, 'attrs')] |
2572 |
done = False
|
2573 |
for match in matches: |
2574 |
for assoc in match.associations(): |
2575 |
if item is assoc: |
2576 |
match.remove_assoc_item(item) |
2577 |
for attr in match.attrs.keys(): |
2578 |
if str(item.uid) == str(attr.AssocItem.uid): |
2579 |
attr.AssocItem = None
|
2580 |
match.attrs[attr] = ''
|
2581 |
done = True
|
2582 |
break
|
2583 |
break
|
2584 |
if done: break |
2585 |
|
2586 |
if type(item) is QEngineeringStreamlineItem: |
2587 |
self.on_stream_line_deleted(item)
|
2588 |
|
2589 |
if item.scene() is not None: |
2590 |
item.scene().removeItem(item) |
2591 |
del item
|
2592 |
except Exception as ex: |
2593 |
message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename, |
2594 |
sys.exc_info()[-1].tb_lineno)
|
2595 |
self.addMessage.emit(MessageType.Error, message)
|
2596 |
|
2597 |
'''
|
2598 |
@brief load components
|
2599 |
@author yeonjin
|
2600 |
@date 2019.07.30.
|
2601 |
'''
|
2602 |
|
2603 |
def load_components(self, componentsUID): |
2604 |
from EngineeringStreamlineItem import QEngineeringStreamlineItem |
2605 |
from EngineeringCalloutTextItem import QEngineeringCalloutTextItem |
2606 |
from EngineeringDimensionItem import QEngineeringDimensionItem |
2607 |
from EngineeringCloudItem import QEngineeringCloudItem |
2608 |
|
2609 |
try:
|
2610 |
app_doc_data = AppDocData.instance() |
2611 |
|
2612 |
maxValue = len(componentsUID)
|
2613 |
self.progress.setMaximum(maxValue)
|
2614 |
|
2615 |
for componentUID in componentsUID: |
2616 |
componentInfos = app_doc_data.getComponentByComponentUID(componentUID) |
2617 |
if (len(componentInfos)) > 0: |
2618 |
category = componentInfos[0]['Category'] # Category@SymbolType |
2619 |
symbol_name = componentInfos[0]['Symbol_Name'] # Name@Symbols |
2620 |
|
2621 |
if category == 'Stream Line': |
2622 |
item = QEngineeringStreamlineItem.fromDatabase(componentInfos) |
2623 |
if item is not None: |
2624 |
item.transfer.onRemoved.connect(self.on_item_removed)
|
2625 |
self.graphicsView.scene.addItem(item)
|
2626 |
elif symbol_name == 'Callout': |
2627 |
item = QEngineeringCalloutTextItem.fromDatabase(componentInfos) |
2628 |
if item:
|
2629 |
item.transfer.onRemoved.connect(self.on_item_removed)
|
2630 |
item.lost_focus.connect(self.editor_lost_focus)
|
2631 |
item.selected_change.connect(self.item_selected)
|
2632 |
self.graphicsView.scene.addItem(item)
|
2633 |
elif symbol_name == 'Dimension': |
2634 |
item = QEngineeringDimensionItem.fromDatabase(componentInfos) |
2635 |
if item:
|
2636 |
item.transfer.onRemoved.connect(self.on_item_removed)
|
2637 |
self.graphicsView.scene.addItem(item)
|
2638 |
elif symbol_name == 'Cloud': |
2639 |
item = QEngineeringCloudItem.fromDatabase(componentInfos) |
2640 |
if item:
|
2641 |
self.graphicsView.scene.addItem(item)
|
2642 |
else:
|
2643 |
item = SymbolSvgItem.fromDatabase(componentInfos) |
2644 |
if item is not None: |
2645 |
item.transfer.onRemoved.connect(self.on_item_removed)
|
2646 |
app_doc_data.symbols.append(item) |
2647 |
self.addSvgItemToScene(item)
|
2648 |
|
2649 |
self.progress.setValue(self.progress.value() + 1) |
2650 |
|
2651 |
QApplication.processEvents() |
2652 |
|
2653 |
#self.rebuild_label()
|
2654 |
|
2655 |
# """ update scene """
|
2656 |
self.graphicsView.scene.update(self.graphicsView.sceneRect()) |
2657 |
for item in self.graphicsView.scene.items(): |
2658 |
item.setVisible(True)
|
2659 |
|
2660 |
except Exception as ex: |
2661 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
2662 |
sys.exc_info()[-1].tb_lineno)
|
2663 |
self.addMessage.emit(MessageType.Error, message)
|
2664 |
finally:
|
2665 |
pass
|
2666 |
|
2667 |
'''
|
2668 |
@brief Remove added item on same place and Add GraphicsItem
|
2669 |
@author Jeongwoo
|
2670 |
@date 2018.05.25
|
2671 |
@history 2018.05.29 Jeongwoo Moved from QRecognitionDialog
|
2672 |
2018.06.18 Jeongwoo Set Z-index
|
2673 |
'''
|
2674 |
|
2675 |
def addSvgItemToScene(self, svgItem): |
2676 |
svgItem.addSvgItemToScene(self.graphicsView.scene)
|
2677 |
|
2678 |
'''
|
2679 |
@brief Remove added item on same place and Add GraphicsItem
|
2680 |
@author Jeongwoo
|
2681 |
@date 2018.05.25
|
2682 |
@history 2018.05.29 Jeongwoo Moved from QRecognitionDialog
|
2683 |
2018.06.05 Jeongwoo Remove Size condition
|
2684 |
2018.06.18 Jeongwoo Set Z-index
|
2685 |
'''
|
2686 |
|
2687 |
def addTextItemToScene(self, textItem): |
2688 |
textItem.addTextItemToScene(self.graphicsView.scene)
|
2689 |
|
2690 |
'''
|
2691 |
@brief Remove added item on same place and Add GraphicsItem
|
2692 |
@author Jeongwoo
|
2693 |
@date 2018.05.29
|
2694 |
@history 2018.06.18 Jeongwoo Set Z-index
|
2695 |
'''
|
2696 |
|
2697 |
def addLineItemToScene(self, lineItem): |
2698 |
self.graphicsView.scene.addItem(lineItem)
|
2699 |
|
2700 |
'''
|
2701 |
@brief Check Number
|
2702 |
@author kyouho
|
2703 |
@date 2018.08.20
|
2704 |
'''
|
2705 |
|
2706 |
def isNumber(self, num): |
2707 |
p = re.compile('(^[0-9]+$)')
|
2708 |
result = p.match(num) |
2709 |
|
2710 |
if result:
|
2711 |
return True |
2712 |
else:
|
2713 |
return False |
2714 |
|
2715 |
'''
|
2716 |
@brief find overlap Connector
|
2717 |
@author kyouho
|
2718 |
@date 2018.08.28
|
2719 |
'''
|
2720 |
|
2721 |
def findOverlapConnector(self, connectorItem): |
2722 |
from shapely.geometry import Point |
2723 |
from EngineeringConnectorItem import QEngineeringConnectorItem |
2724 |
itemList = [] |
2725 |
|
2726 |
x = connectorItem.center()[0]
|
2727 |
y = connectorItem.center()[1]
|
2728 |
|
2729 |
connectors = [item for item in self.graphicsView.scene.items() if |
2730 |
type(item) is QEngineeringConnectorItem and item != connectorItem] |
2731 |
for connector in connectors: |
2732 |
if Point(x, y).distance(Point(connector.center()[0], connector.center()[1])) < 5: |
2733 |
itemList.append(connector.parent) |
2734 |
|
2735 |
return itemList
|
2736 |
|
2737 |
def add_data(self, table_widget, name, value, unit, separation=None, is_cell_merge=None, foregroundcolor=None): |
2738 |
row = table_widget.rowCount() |
2739 |
table_widget.setRowCount(row + 1)
|
2740 |
|
2741 |
if separation:
|
2742 |
if is_cell_merge:
|
2743 |
table_widget.setSpan(row, 0, 1, 3) |
2744 |
table_widget.setItem(row, 0, set_item_properties(name,
|
2745 |
Qt.AlignLeft | Qt.AlignVCenter, |
2746 |
QColor(153, 204, 255), foregroundcolor)) |
2747 |
else:
|
2748 |
table_widget.setItem(row, 0, set_item_properties(name,
|
2749 |
Qt.AlignLeft | Qt.AlignVCenter, |
2750 |
QColor(153, 204, 255), foregroundcolor)) |
2751 |
table_widget.setItem(row, 1, set_item_properties(value,
|
2752 |
Qt.AlignHCenter | Qt.AlignVCenter, |
2753 |
QColor(153, 204, 255), foregroundcolor)) |
2754 |
table_widget.setItem(row, 2, set_item_properties(unit,
|
2755 |
Qt.AlignHCenter | Qt.AlignVCenter, |
2756 |
QColor(153, 204, 255), foregroundcolor)) |
2757 |
else:
|
2758 |
if is_cell_merge:
|
2759 |
table_widget.setSpan(row, 0, 1, 3) |
2760 |
table_widget.setItem(row, 0, set_item_properties(name,
|
2761 |
Qt.AlignLeft | Qt.AlignVCenter, None,
|
2762 |
foregroundcolor)) |
2763 |
else:
|
2764 |
table_widget.setItem(row, 0, set_item_properties(name,
|
2765 |
Qt.AlignLeft | Qt.AlignVCenter, None,
|
2766 |
foregroundcolor)) |
2767 |
table_widget.setItem(row, 1, set_item_properties(value,
|
2768 |
Qt.AlignRight | Qt.AlignVCenter, None,
|
2769 |
foregroundcolor)) |
2770 |
table_widget.setItem(row, 2, set_item_properties(unit,
|
2771 |
Qt.AlignLeft | Qt.AlignVCenter, None,
|
2772 |
foregroundcolor)) |
2773 |
|
2774 |
table_widget.resizeRowsToContents() |
2775 |
table_widget.resizeColumnsToContents() |
2776 |
|
2777 |
|
2778 |
if __name__ == '__main__': |
2779 |
pass
|