1 # Copyright (C) 2012-2013 EDF
3 # This file is part of SALOME HYDRO module.
5 # SALOME HYDRO module is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # SALOME HYDRO module is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with SALOME HYDRO module. If not, see <http://www.gnu.org/licenses/>.
21 from PyQt5.QtCore import *
22 from PyQt5.QtGui import *
23 from PyQt5.QtWidgets import *
26 from MEDLoader import MEDFileMesh
28 # TODO: get rid of sys.path.append() ?
30 pythonVersion = 'python' + sysconfig.get_python_version()
31 hydro_solver_root = os.path.join(os.environ['HYDROSOLVER_ROOT_DIR'], 'lib', pythonVersion, 'site-packages', 'salome')
33 from salome.hydro import boundaryConditions
35 ROW_PROPERTY_NAME = "row"
37 """Get names of groups on edges from the given MED file"""
38 def get_med_groups_on_edges(file_path):
40 med_file_mesh = MEDFileMesh.New(file_path)
41 groups = list(med_file_mesh.getGroupsOnSpecifiedLev(-1))
42 except Exception as e:
48 """Get preset name corresponding to the given values of LIHBOR, LIUBOR, LIVBOR and LITBOR"""
49 def get_preset_name(presets, lihbor, liubor, livbor, litbor):
51 res = (lihbor, liubor, livbor, litbor)
52 for key, val in presets.items():
58 """Convert string to integer, return None if conversion is not possible"""
67 """Item delegate for LIHBOR, LIUBOR, LIVBOR and LITBOR columns"""
68 class ValueDelegate(QStyledItemDelegate):
70 def __init__(self, parent = None):
71 QStyledItemDelegate.__init__(self, parent)
73 def createEditor(self, parent, option, index):
74 line_edit = QLineEdit(parent)
76 validator = QIntValidator(parent)
77 validator.setRange(0, 6)
79 line_edit.setValidator(validator)
83 def setEditorData(self, editor, index):
84 value = index.model().data(index, Qt.EditRole)
90 def setModelData(self, editor, model, index):
91 model.setData(index, editor.text(), Qt.EditRole)
93 def updateEditorGeometry(self, editor, option, index):
94 editor.setGeometry(option.rect)
96 """Boundary conditions definition dialog"""
97 class BoundaryConditionsDialog(QDialog):
99 def __init__(self, parent = None, modal = 0):
100 QDialog.__init__(self, parent)
101 uic.loadUi(os.path.join(hydro_solver_root, 'BndConditionsDialog.ui'), self )
104 self.medFileButton.clicked.connect(self.on_med_file_browse)
105 self.bndConditionsFileButton.clicked.connect(self.on_bnd_file_browse)
106 self.resultBndConditionsFileButton.clicked.connect(self.on_result_file_browse)
108 self.sameAsInputCB.toggled.connect(self.resultBndConditionsFileEdit.setDisabled)
109 self.sameAsInputCB.toggled.connect(self.resultBndConditionsFileButton.setDisabled)
111 self.boundaryConditionsTable.cellChanged.connect(self.on_cell_changed)
113 self.applyAndCloseButton.clicked.connect(self.on_apply_and_close)
114 self.applyButton.clicked.connect(self.on_apply)
115 self.closeButton.clicked.connect(self.reject)
116 self.helpButton.clicked.connect(self.on_help)
118 # Set widgets properties
122 self.input_conditions = {}
128 """Initialize presets"""
129 def init_presets(self):
130 # TODO: determine another presets path
131 presets_data_root = os.path.join(os.environ['HYDROSOLVER_ROOT_DIR'], 'lib', pythonVersion, 'site-packages', 'salome', 'tests', 'data')
132 file_path = os.path.join(presets_data_root, 'bnd_conditions_presets.txt')
133 reader = boundaryConditions.PresetReader(file_path)
134 self.presets = reader.read()
136 """Initialize widget properties"""
137 def init_widgets(self):
138 self.medFileEdit.setReadOnly(True)
139 self.bndConditionsFileEdit.setReadOnly(True)
140 self.resultBndConditionsFileEdit.setReadOnly(True)
142 delegate = ValueDelegate(self.boundaryConditionsTable)
143 self.boundaryConditionsTable.setItemDelegateForColumn(1, delegate)
144 self.boundaryConditionsTable.setItemDelegateForColumn(2, delegate)
145 self.boundaryConditionsTable.setItemDelegateForColumn(3, delegate)
146 self.boundaryConditionsTable.setItemDelegateForColumn(4, delegate)
148 """Process cell data changes"""
149 def on_cell_changed(self, row, column):
150 #print "on_cell_changed"
151 lihbor = liubor = livbor = litbor = None
153 item = self.boundaryConditionsTable.item(row, 1)
155 lihbor = get_int(str(item.text()))
157 item = self.boundaryConditionsTable.item(row, 2)
159 liubor = get_int(str(item.text()))
161 item = self.boundaryConditionsTable.item(row, 3)
163 livbor = get_int(str(item.text()))
165 item = self.boundaryConditionsTable.item(row, 4)
167 litbor = get_int(str(item.text()))
169 preset_name = get_preset_name(self.presets, lihbor, liubor, livbor, litbor)
170 #print "on_cell_changed ", preset_name, lihbor, liubor, livbor, litbor
172 combo = self.boundaryConditionsTable.cellWidget(row, 0)
173 if isinstance(combo, QComboBox):
174 ind = combo.findText(preset_name)
176 combo.currentIndexChanged.disconnect(self.on_preset_changed)
177 combo.setCurrentIndex(ind)
178 combo.currentIndexChanged.connect(self.on_preset_changed)
180 """Save the user data to boundary conditions file"""
182 # Save boundary conditions file
183 if not self.is_valid():
187 if self.sameAsInputCB.isChecked():
188 file_path = self.bndConditionsFileEdit.text()
190 file_path = self.resultBndConditionsFileEdit.text()
191 print('File path:', file_path)
192 writer = boundaryConditions.BoundaryConditionWriter(file_path)
195 for row_nb in range(0, self.boundaryConditionsTable.rowCount()):
196 lihbor = str(self.boundaryConditionsTable.item(row_nb, 1).text())
197 liubor = str(self.boundaryConditionsTable.item(row_nb, 2).text())
198 livbor = str(self.boundaryConditionsTable.item(row_nb, 3).text())
199 litbor = str(self.boundaryConditionsTable.item(row_nb, 4).text())
200 group_name = str(self.boundaryConditionsTable.item(row_nb, 5).text())
202 conditions.append(boundaryConditions.BoundaryCondition(lihbor, liubor, livbor, litbor, group_name))
204 writer.write(conditions)
208 """Save the user data to boundary conditions file and close the dialog"""
209 def on_apply_and_close(self):
213 """Select MED file"""
214 def on_med_file_browse(self):
216 file_path, filt = QFileDialog.getOpenFileName(self, self.tr("Open MED file"), "", self.tr("MED files (*.med)"))
220 # Get names of groups on edges
221 groups = get_med_groups_on_edges(str(file_path))
225 self.medFileEdit.setText(file_path)
228 self.set_groups(groups)
230 QMessageBox.warning(self, self.tr("Warning"), self.tr("Can't get group names from the selected MED file."))
231 self.boundaryConditionsTable.resizeColumnsToContents()
233 """Select boundary conditions file"""
234 def on_bnd_file_browse(self):
235 file_path, filt = QFileDialog.getOpenFileName(self, self.tr("Open boundary conditions file"))
238 self.bndConditionsFileEdit.setText(file_path)
239 reader = boundaryConditions.BoundaryConditionReader(file_path)
240 conditions = reader.read()
242 self.input_conditions.clear()
243 for cnd in conditions:
244 self.input_conditions[cnd.group] = (cnd.lihbor, cnd.liubor, cnd.livbor, cnd.litbor)
247 read_errors = reader.errors
248 if len( read_errors ) > 0:
249 msg = "\n".join(read_errors)
250 QMessageBox.warning(self, self.tr("Warning"), msg)
252 if len(self.input_conditions) > 0:
255 QMessageBox.warning(self, self.tr("Warning"), self.tr("No conditions have been read from the file."))
257 """Called on preset selection in the first column of the table"""
258 def on_preset_changed(self):
259 #print"on_preset_changed"
260 combo = self.sender()
262 preset = str(combo.currentText())
264 if preset and preset in self.presets:
265 values = self.presets[preset]
266 row_nb = combo.property(ROW_PROPERTY_NAME)
268 if row_nb >= 0 and row_nb < self.boundaryConditionsTable.rowCount():
273 #print "on_preset_changed ", preset, lihbor, liubor, livbor, litbor
275 #if lihbor is not None:
276 self.boundaryConditionsTable.item(row_nb, 1).setText(str(lihbor))
278 #if liubor is not None:
279 self.boundaryConditionsTable.item(row_nb, 2).setText(str(liubor))
281 #if livbor is not None:
282 self.boundaryConditionsTable.item(row_nb, 3).setText(str(livbor))
284 #if litbor is not None:
285 self.boundaryConditionsTable.item(row_nb, 4).setText(str(litbor))
287 if isinstance(combo, QComboBox):
288 ind = combo.findText(preset)
290 combo.setCurrentIndex(ind)
292 """Define result file path"""
293 def on_result_file_browse(self):
294 file_path, filt = QFileDialog.getSaveFileName(self, self.tr("Select output file path"))
297 self.resultBndConditionsFileEdit.setText(file_path)
299 """Set groups list"""
300 def set_groups(self, groups):
302 self.boundaryConditionsTable.setRowCount(0)
305 row_nb = self.boundaryConditionsTable.rowCount()
306 self.boundaryConditionsTable.insertRow(row_nb)
309 combo = QComboBox(self)
311 if len(self.presets) > 0:
312 items = list(self.presets.keys())
314 combo.addItems(items)
316 combo.setProperty(ROW_PROPERTY_NAME, row_nb)
317 combo.currentIndexChanged.connect(self.on_preset_changed)
319 self.boundaryConditionsTable.setCellWidget(row_nb, 0, combo)
322 self.boundaryConditionsTable.setItem(row_nb, 1, QTableWidgetItem(''))
325 self.boundaryConditionsTable.setItem(row_nb, 2, QTableWidgetItem(''))
328 self.boundaryConditionsTable.setItem(row_nb, 3, QTableWidgetItem(''))
331 self.boundaryConditionsTable.setItem(row_nb, 4, QTableWidgetItem(''))
334 item = QTableWidgetItem(group)
338 item.setFlags(Qt.ItemIsEnabled)
339 self.boundaryConditionsTable.setItem(row_nb, 5, item)
343 """Update conditions data in the table from the conditions input file"""
344 def update_table(self):
345 #print "update_table"
348 nb_rows = self.boundaryConditionsTable.rowCount()
349 for row_nb in range(0, nb_rows):
350 group_name = str(self.boundaryConditionsTable.item(row_nb, 5).text())
351 if group_name in self.input_conditions:
353 values = self.input_conditions[group_name]
356 lihbor = str(values[0])
357 liubor = str(values[1])
358 livbor = str(values[2])
359 litbor = str(values[3])
360 #print lihbor, liubor, livbor, litbor
362 self.boundaryConditionsTable.item(row_nb, 1).setText(lihbor)
363 self.boundaryConditionsTable.item(row_nb, 2).setText(liubor)
364 self.boundaryConditionsTable.item(row_nb, 3).setText(livbor)
365 self.boundaryConditionsTable.item(row_nb, 4).setText(litbor)
367 # combo = self.boundaryConditionsTable.cellWidget(row_nb, 0)
368 # if isinstance(combo, QComboBox):
369 # preset_name = get_preset_name(self.presets, lihbor, liubor, livbor, litbor)
370 # ind = combo.findText(preset_name)
372 # combo.setCurrentIndex(ind)
376 if not is_updated and nb_rows > 0 and len(self.input_conditions) > 0:
377 QMessageBox.information(self, self.tr("Information"), self.tr("No one group name from the MED file is presented in the input list of conditions."))
379 """Get output file path"""
380 def get_output_path(self):
381 path = self.bndConditionsFileEdit.text()
383 if not self.sameAsInputCB.isChecked():
384 path = self.resultBndConditionsFileEdit.text()
388 """Check if the input data is valid"""
392 if self.boundaryConditionsTable.rowCount() < 1:
393 QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Boundary conditions list is empty."))
394 elif len(self.get_output_path())==0:
395 QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Output file path is empty."))
397 for row_nb in range(0, self.boundaryConditionsTable.rowCount()):
398 has_empty_cells = True
399 lihbor = str(self.boundaryConditionsTable.item(row_nb, 1).text())
400 liubor = str(self.boundaryConditionsTable.item(row_nb, 2).text())
401 livbor = str(self.boundaryConditionsTable.item(row_nb, 3).text())
402 litbor = str(self.boundaryConditionsTable.item(row_nb, 4).text())
403 #print "test valid: ", lihbor, liubor, livbor, litbor
404 if (lihbor != '') and (liubor != '') and (livbor != '') and (litbor != '') :
405 has_empty_cells = False # Full lines are OK
406 #print "valid: full line"
407 if (lihbor == '') and (liubor == '') and (livbor == '') and (litbor == ''):
408 has_empty_cells = False # Empty lines are OK
409 #print "valid: empty line"
413 QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Table has empty cell(s)."))
419 """Shows help page"""
422 <h2>Boundary conditions dialog</h2>
424 This dialog is used to read and write boundary conditions files.
425 Below is the description of the dialog controls.
428 This field allows selection of a med file (via the standard file open dialog).
429 The file must contain groups of edges, if this is not the case a warning message appears.
430 The filling of this field is mandatory.
432 <h3>Boundary conditions file</h3>
433 This field allows selecting the file of boundary conditions (via the standard file open dialog).
434 The data from this file is displayed in the table "Boundary conditions".
435 This field is optional; if it is not selected the table will not be prefilled.
437 <h3>Result boundary conditions file</h3>
438 This field allows selecting the file in which to save the data (via the standard file save dialog).
439 This field is mandatory if the "Same as the input" check box is unchecked.
441 <h3>Boundary conditions table</h3>
442 Contains data representing the list of boundary conditions.
443 The first column contains a list of presets.
444 The last columns is read-only, it contains names of group of edges from the selected MED file.
445 Other columns is for LIHBOR, LIUBOR, LIVBOR and LITBOR parameters, which can take a value ranging between 0 and 6.
448 When the table is filled and the output file is defined, the user clicks on "Apply" or "Apply and Close" button
449 to perform the data export to the file.
450 Click on "Close" button does not lead to saving the data and just closes the dialog.
452 QMessageBox.about(self, self.tr("About boundary conditions dialog"), msg);