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() ?
29 hydro_solver_root = os.path.join(os.environ['HYDROSOLVER_ROOT_DIR'], 'lib', 'python2.7', 'site-packages', 'salome')
30 #sys.path.append(os.path.join(hydro_solver_root, 'salome', 'hydrotools'))
32 from salome.hydro import boundaryConditions
34 ROW_PROPERTY_NAME = "row"
36 """Get names of groups on edges from the given MED file"""
37 def get_med_groups_on_edges(file_path):
39 med_file_mesh = MEDFileMesh.New(file_path)
40 groups = list(med_file_mesh.getGroupsOnSpecifiedLev(-1))
41 except Exception as e:
47 """Get preset name corresponding to the given values of LIHBOR, LIUBOR, LIVBOR and LITBOR"""
48 def get_preset_name(presets, lihbor, liubor, livbor, litbor):
51 for preset_name in presets:
52 values = presets[preset_name]
59 if not p_lihbor or p_lihbor == lihbor:
60 if not p_liubor or p_liubor == liubor:
61 if not p_livbor or p_livbor == livbor:
62 if not p_litbor or p_litbor == litbor:
67 """Convert string to integer, return None if conversion is not possible"""
76 """Item delegate for LIHBOR, LIUBOR, LIVBOR and LITBOR columns"""
77 class ValueDelegate(QStyledItemDelegate):
79 def __init__(self, parent = None):
80 QStyledItemDelegate.__init__(self, parent)
82 def createEditor(self, parent, option, index):
83 line_edit = QLineEdit(parent)
85 validator = QIntValidator(parent)
86 validator.setRange(0, 6)
88 line_edit.setValidator(validator)
92 def setEditorData(self, editor, index):
93 value = index.model().data(index, Qt.EditRole)
99 def setModelData(self, editor, model, index):
100 model.setData(index, editor.text(), Qt.EditRole)
102 def updateEditorGeometry(self, editor, option, index):
103 editor.setGeometry(option.rect)
105 """Boundary conditions definition dialog"""
106 class BoundaryConditionsDialog(QDialog):
108 def __init__(self, parent = None, modal = 0):
109 QDialog.__init__(self, parent)
110 uic.loadUi(os.path.join(hydro_solver_root, 'BndConditionsDialog.ui'), self )
113 self.medFileButton.clicked.connect(self.on_med_file_browse)
114 self.bndConditionsFileButton.clicked.connect(self.on_bnd_file_browse)
115 self.resultBndConditionsFileButton.clicked.connect(self.on_result_file_browse)
117 self.sameAsInputCB.toggled.connect(self.resultBndConditionsFileEdit.setDisabled)
118 self.sameAsInputCB.toggled.connect(self.resultBndConditionsFileButton.setDisabled)
120 self.boundaryConditionsTable.cellChanged.connect(self.on_cell_changed)
122 self.applyAndCloseButton.clicked.connect(self.on_apply_and_close)
123 self.applyButton.clicked.connect(self.on_apply)
124 self.closeButton.clicked.connect(self.reject)
125 self.helpButton.clicked.connect(self.on_help)
127 # Set widgets properties
131 self.input_conditions = {}
137 """Initialize presets"""
138 def init_presets(self):
139 # TODO: determine another presets path
140 presets_data_root = os.path.join(os.environ['HYDROSOLVER_ROOT_DIR'], 'lib', 'python2.7', 'site-packages', 'salome', 'tests', 'data')
141 file_path = os.path.join(presets_data_root, 'bnd_conditions_presets.txt')
142 reader = boundaryConditions.PresetReader(file_path)
143 self.presets = reader.read()
145 """Initialize widget properties"""
146 def init_widgets(self):
147 self.medFileEdit.setReadOnly(True)
148 self.bndConditionsFileEdit.setReadOnly(True)
149 self.resultBndConditionsFileEdit.setReadOnly(True)
151 delegate = ValueDelegate(self.boundaryConditionsTable)
152 self.boundaryConditionsTable.setItemDelegateForColumn(1, delegate)
153 self.boundaryConditionsTable.setItemDelegateForColumn(2, delegate)
154 self.boundaryConditionsTable.setItemDelegateForColumn(3, delegate)
155 self.boundaryConditionsTable.setItemDelegateForColumn(4, delegate)
157 """Process cell data changes"""
158 def on_cell_changed(self, row, column):
159 lihbor = liubor = livbor = litbor = None
161 item = self.boundaryConditionsTable.item(row, 1)
163 lihbor = get_int(str(item.text()))
165 item = self.boundaryConditionsTable.item(row, 2)
167 liubor = get_int(str(item.text()))
169 item = self.boundaryConditionsTable.item(row, 3)
171 livbor = get_int(str(item.text()))
173 item = self.boundaryConditionsTable.item(row, 4)
175 litbor = get_int(str(item.text()))
177 preset_name = get_preset_name(self.presets, lihbor, liubor, livbor, litbor)
179 combo = self.boundaryConditionsTable.cellWidget(row, 0)
180 if isinstance(combo, QComboBox):
181 ind = combo.findText(preset_name)
183 combo.setCurrentIndex(ind)
185 """Save the user data to boundary conditions file"""
187 # Save boundary conditions file
188 if not self.is_valid():
191 file_path = self.resultBndConditionsFileEdit.text()
192 writer = boundaryConditions.BoundaryConditionWriter(file_path)
195 for row_nb in xrange(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())
201 conditions.append(boundaryConditions.BoundaryCondition(lihbor, liubor, livbor, litbor, group_name))
203 writer.write(conditions)
207 """Save the user data to boundary conditions file and close the dialog"""
208 def on_apply_and_close(self):
212 """Select MED file"""
213 def on_med_file_browse(self):
215 file_path, filt = QFileDialog.getOpenFileName(self, self.tr("Open MED file"), "", self.tr("MED files (*.med)"))
219 # Get names of groups on edges
220 groups = get_med_groups_on_edges(str(file_path))
224 self.medFileEdit.setText(file_path)
227 self.set_groups(groups)
229 QMessageBox.warning(self, self.tr("Warning"), self.tr("Can't get group names from the selected MED file."))
231 """Select boundary conditions file"""
232 def on_bnd_file_browse(self):
233 file_path, filt = QFileDialog.getOpenFileName(self, self.tr("Open boundary conditions file"))
236 self.bndConditionsFileEdit.setText(file_path)
237 reader = boundaryConditions.BoundaryConditionReader(file_path)
238 conditions = reader.read()
240 self.input_conditions.clear()
241 for cnd in conditions:
242 self.input_conditions[cnd.group] = (cnd.lihbor, cnd.liubor, cnd.livbor, cnd.litbor)
245 read_errors = reader.errors
246 if len( read_errors ) > 0:
247 msg = "\n".join(read_errors)
248 QMessageBox.warning(self, self.tr("Warning"), msg)
250 if len(self.input_conditions) > 0:
253 QMessageBox.warning(self, self.tr("Warning"), self.tr("No conditions have been read from the file."))
255 """Called on preset selection in the first column of the table"""
256 def on_preset_changed(self):
257 combo = self.sender()
259 preset = str(combo.currentText())
261 if preset and self.presets.has_key(preset):
262 values = self.presets[preset]
263 row_nb, is_ok = combo.property(ROW_PROPERTY_NAME).toInt()
265 if is_ok and row_nb >= 0 and row_nb < self.boundaryConditionsTable.rowCount():
266 #row_nb = combo.property(ROW_PROPERTY_NAME)
268 #if row_nb >= 0 and row_nb < self.boundaryConditionsTable.rowCount():
275 self.boundaryConditionsTable.item(row_nb, 1).setText(str(lihbor))
278 self.boundaryConditionsTable.item(row_nb, 2).setText(str(liubor))
281 self.boundaryConditionsTable.item(row_nb, 3).setText(str(livbor))
284 self.boundaryConditionsTable.item(row_nb, 4).setText(str(litbor))
286 """Define result file path"""
287 def on_result_file_browse(self):
288 file_path, filt = QFileDialog.getSaveFileName(self, self.tr("Select output file path"))
291 self.resultBndConditionsFileEdit.setText(file_path)
293 """Set groups list"""
294 def set_groups(self, groups):
295 self.boundaryConditionsTable.setRowCount(0)
298 row_nb = self.boundaryConditionsTable.rowCount()
299 self.boundaryConditionsTable.insertRow(row_nb)
302 combo = QComboBox(self)
304 if len(self.presets) > 0:
305 combo.addItems(self.presets.keys())
307 combo.setProperty(ROW_PROPERTY_NAME, row_nb)
309 combo.currentIndexChanged.connect(self.on_preset_changed)
311 self.boundaryConditionsTable.setCellWidget(row_nb, 0, combo)
314 self.boundaryConditionsTable.setItem(row_nb, 1, QTableWidgetItem(''))
317 self.boundaryConditionsTable.setItem(row_nb, 2, QTableWidgetItem(''))
320 self.boundaryConditionsTable.setItem(row_nb, 3, QTableWidgetItem(''))
323 self.boundaryConditionsTable.setItem(row_nb, 4, QTableWidgetItem(''))
326 item = QTableWidgetItem(group)
330 item.setFlags(Qt.ItemIsEnabled)
331 self.boundaryConditionsTable.setItem(row_nb, 5, item)
335 """Update conditions data in the table from the conditions input file"""
336 def update_table(self):
339 nb_rows = self.boundaryConditionsTable.rowCount()
340 for row_nb in xrange(0, nb_rows):
341 group_name = str(self.boundaryConditionsTable.item(row_nb, 5).text())
342 if self.input_conditions.has_key(group_name):
343 values = self.input_conditions[group_name]
345 lihbor = str(values[0])
346 liubor = str(values[1])
347 livbor = str(values[2])
348 litbor = str(values[3])
350 self.boundaryConditionsTable.item(row_nb, 1).setText(lihbor)
351 self.boundaryConditionsTable.item(row_nb, 2).setText(liubor)
352 self.boundaryConditionsTable.item(row_nb, 3).setText(livbor)
353 self.boundaryConditionsTable.item(row_nb, 4).setText(litbor)
357 if not is_updated and nb_rows > 0 and len(self.input_conditions) > 0:
358 QMessageBox.information(self, self.tr("Information"), self.tr("No one group name from the MED file is presented in the input list of conditions."))
360 """Get output file path"""
361 def get_output_path(self):
362 path = self.bndConditionsFileEdit.text()
364 if not self.sameAsInputCB.isChecked():
365 path = self.resultBndConditionsFileEdit.text()
369 """Check if the input data is valid"""
373 if self.boundaryConditionsTable.rowCount() < 1:
374 QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Boundary conditions list is empty."))
375 elif len(self.get_output_path())==0:
376 QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Output file path is empty."))
378 has_empty_cells = False
379 for row_nb in xrange(0, self.boundaryConditionsTable.rowCount()):
380 lihbor = str(self.boundaryConditionsTable.item(row_nb, 1).text())
381 liubor = str(self.boundaryConditionsTable.item(row_nb, 2).text())
382 livbor = str(self.boundaryConditionsTable.item(row_nb, 3).text())
383 litbor = str(self.boundaryConditionsTable.item(row_nb, 4).text())
385 if (not lihbor) or (not liubor) or (not livbor) or (not litbor):
386 has_empty_cells = True
390 QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Table has empty cell(s)."))
396 """Shows help page"""
399 <h2>Boundary conditions dialog</h2>
401 This dialog is used to read and write boundary conditions files.
402 Below is the description of the dialog controls.
405 This field allows selection of a med file (via the standard file open dialog).
406 The file must contain groups of edges, if this is not the case a warning message appears.
407 The filling of this field is mandatory.
409 <h3>Boundary conditions file</h3>
410 This field allows selecting the file of boundary conditions (via the standard file open dialog).
411 The data from this file is displayed in the table "Boundary conditions".
412 This field is optional; if it is not selected the table will not be prefilled.
414 <h3>Result boundary conditions file</h3>
415 This field allows selecting the file in which to save the data (via the standard file save dialog).
416 This field is mandatory if the "Same as the input" check box is unchecked.
418 <h3>Boundary conditions table</h3>
419 Contains data representing the list of boundary conditions.
420 The first column contains a list of presets.
421 The last columns is read-only, it contains names of group of edges from the selected MED file.
422 Other columns is for LIHBOR, LIUBOR, LIVBOR and LITBOR parameters, which can take a value ranging between 0 and 6.
425 When the table is filled and the output file is defined, the user clicks on "Apply" or "Apply and Close" button
426 to perform the data export to the file.
427 Click on "Close" button does not lead to saving the data and just closes the dialog.
429 QMessageBox.about(self, self.tr("About boundary conditions dialog"), msg);