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):
50 res = (lihbor, liubor, livbor, litbor)
51 for key, val in presets.iteritems():
57 """Convert string to integer, return None if conversion is not possible"""
66 """Item delegate for LIHBOR, LIUBOR, LIVBOR and LITBOR columns"""
67 class ValueDelegate(QStyledItemDelegate):
69 def __init__(self, parent = None):
70 QStyledItemDelegate.__init__(self, parent)
72 def createEditor(self, parent, option, index):
73 line_edit = QLineEdit(parent)
75 validator = QIntValidator(parent)
76 validator.setRange(0, 6)
78 line_edit.setValidator(validator)
82 def setEditorData(self, editor, index):
83 value = index.model().data(index, Qt.EditRole)
89 def setModelData(self, editor, model, index):
90 model.setData(index, editor.text(), Qt.EditRole)
92 def updateEditorGeometry(self, editor, option, index):
93 editor.setGeometry(option.rect)
95 """Boundary conditions definition dialog"""
96 class BoundaryConditionsDialog(QDialog):
98 def __init__(self, parent = None, modal = 0):
99 QDialog.__init__(self, parent)
100 uic.loadUi(os.path.join(hydro_solver_root, 'BndConditionsDialog.ui'), self )
103 self.medFileButton.clicked.connect(self.on_med_file_browse)
104 self.bndConditionsFileButton.clicked.connect(self.on_bnd_file_browse)
105 self.resultBndConditionsFileButton.clicked.connect(self.on_result_file_browse)
107 self.sameAsInputCB.toggled.connect(self.resultBndConditionsFileEdit.setDisabled)
108 self.sameAsInputCB.toggled.connect(self.resultBndConditionsFileButton.setDisabled)
110 self.boundaryConditionsTable.cellChanged.connect(self.on_cell_changed)
112 self.applyAndCloseButton.clicked.connect(self.on_apply_and_close)
113 self.applyButton.clicked.connect(self.on_apply)
114 self.closeButton.clicked.connect(self.reject)
115 self.helpButton.clicked.connect(self.on_help)
117 # Set widgets properties
121 self.input_conditions = {}
127 """Initialize presets"""
128 def init_presets(self):
129 # TODO: determine another presets path
130 presets_data_root = os.path.join(os.environ['HYDROSOLVER_ROOT_DIR'], 'lib', 'python2.7', 'site-packages', 'salome', 'tests', 'data')
131 file_path = os.path.join(presets_data_root, 'bnd_conditions_presets.txt')
132 reader = boundaryConditions.PresetReader(file_path)
133 self.presets = reader.read()
135 """Initialize widget properties"""
136 def init_widgets(self):
137 self.medFileEdit.setReadOnly(True)
138 self.bndConditionsFileEdit.setReadOnly(True)
139 self.resultBndConditionsFileEdit.setReadOnly(True)
141 delegate = ValueDelegate(self.boundaryConditionsTable)
142 self.boundaryConditionsTable.setItemDelegateForColumn(1, delegate)
143 self.boundaryConditionsTable.setItemDelegateForColumn(2, delegate)
144 self.boundaryConditionsTable.setItemDelegateForColumn(3, delegate)
145 self.boundaryConditionsTable.setItemDelegateForColumn(4, delegate)
147 """Process cell data changes"""
148 def on_cell_changed(self, row, column):
149 #print "on_cell_changed"
150 lihbor = liubor = livbor = litbor = None
152 item = self.boundaryConditionsTable.item(row, 1)
154 lihbor = get_int(str(item.text()))
156 item = self.boundaryConditionsTable.item(row, 2)
158 liubor = get_int(str(item.text()))
160 item = self.boundaryConditionsTable.item(row, 3)
162 livbor = get_int(str(item.text()))
164 item = self.boundaryConditionsTable.item(row, 4)
166 litbor = get_int(str(item.text()))
168 preset_name = get_preset_name(self.presets, lihbor, liubor, livbor, litbor)
169 #print "on_cell_changed ", preset_name, lihbor, liubor, livbor, litbor
171 combo = self.boundaryConditionsTable.cellWidget(row, 0)
172 if isinstance(combo, QComboBox):
173 ind = combo.findText(preset_name)
175 combo.currentIndexChanged.disconnect(self.on_preset_changed)
176 combo.setCurrentIndex(ind)
177 combo.currentIndexChanged.connect(self.on_preset_changed)
179 """Save the user data to boundary conditions file"""
181 # Save boundary conditions file
182 if not self.is_valid():
186 if self.sameAsInputCB.isChecked():
187 file_path = self.bndConditionsFileEdit.text()
189 file_path = self.resultBndConditionsFileEdit.text()
190 print 'File path:', file_path
191 writer = boundaryConditions.BoundaryConditionWriter(file_path)
194 for row_nb in xrange(0, self.boundaryConditionsTable.rowCount()):
195 lihbor = str(self.boundaryConditionsTable.item(row_nb, 1).text())
196 liubor = str(self.boundaryConditionsTable.item(row_nb, 2).text())
197 livbor = str(self.boundaryConditionsTable.item(row_nb, 3).text())
198 litbor = str(self.boundaryConditionsTable.item(row_nb, 4).text())
199 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 #print"on_preset_changed"
258 combo = self.sender()
260 preset = str(combo.currentText())
262 if preset and self.presets.has_key(preset):
263 values = self.presets[preset]
264 row_nb = combo.property(ROW_PROPERTY_NAME)
266 if row_nb >= 0 and row_nb < self.boundaryConditionsTable.rowCount():
271 #print "on_preset_changed ", preset, lihbor, liubor, livbor, litbor
273 #if lihbor is not None:
274 self.boundaryConditionsTable.item(row_nb, 1).setText(str(lihbor))
276 #if liubor is not None:
277 self.boundaryConditionsTable.item(row_nb, 2).setText(str(liubor))
279 #if livbor is not None:
280 self.boundaryConditionsTable.item(row_nb, 3).setText(str(livbor))
282 #if litbor is not None:
283 self.boundaryConditionsTable.item(row_nb, 4).setText(str(litbor))
285 if isinstance(combo, QComboBox):
286 ind = combo.findText(preset)
288 combo.setCurrentIndex(ind)
290 """Define result file path"""
291 def on_result_file_browse(self):
292 file_path, filt = QFileDialog.getSaveFileName(self, self.tr("Select output file path"))
295 self.resultBndConditionsFileEdit.setText(file_path)
297 """Set groups list"""
298 def set_groups(self, groups):
300 self.boundaryConditionsTable.setRowCount(0)
303 row_nb = self.boundaryConditionsTable.rowCount()
304 self.boundaryConditionsTable.insertRow(row_nb)
307 combo = QComboBox(self)
309 if len(self.presets) > 0:
310 items = self.presets.keys()
312 combo.addItems(items)
314 combo.setProperty(ROW_PROPERTY_NAME, row_nb)
315 combo.currentIndexChanged.connect(self.on_preset_changed)
317 self.boundaryConditionsTable.setCellWidget(row_nb, 0, combo)
320 self.boundaryConditionsTable.setItem(row_nb, 1, QTableWidgetItem(''))
323 self.boundaryConditionsTable.setItem(row_nb, 2, QTableWidgetItem(''))
326 self.boundaryConditionsTable.setItem(row_nb, 3, QTableWidgetItem(''))
329 self.boundaryConditionsTable.setItem(row_nb, 4, QTableWidgetItem(''))
332 item = QTableWidgetItem(group)
336 item.setFlags(Qt.ItemIsEnabled)
337 self.boundaryConditionsTable.setItem(row_nb, 5, item)
341 """Update conditions data in the table from the conditions input file"""
342 def update_table(self):
343 #print "update_table"
346 nb_rows = self.boundaryConditionsTable.rowCount()
347 for row_nb in xrange(0, nb_rows):
348 group_name = str(self.boundaryConditionsTable.item(row_nb, 5).text())
349 if self.input_conditions.has_key(group_name):
351 values = self.input_conditions[group_name]
354 lihbor = str(values[0])
355 liubor = str(values[1])
356 livbor = str(values[2])
357 litbor = str(values[3])
358 #print lihbor, liubor, livbor, litbor
360 self.boundaryConditionsTable.item(row_nb, 1).setText(lihbor)
361 self.boundaryConditionsTable.item(row_nb, 2).setText(liubor)
362 self.boundaryConditionsTable.item(row_nb, 3).setText(livbor)
363 self.boundaryConditionsTable.item(row_nb, 4).setText(litbor)
365 # combo = self.boundaryConditionsTable.cellWidget(row_nb, 0)
366 # if isinstance(combo, QComboBox):
367 # preset_name = get_preset_name(self.presets, lihbor, liubor, livbor, litbor)
368 # ind = combo.findText(preset_name)
370 # combo.setCurrentIndex(ind)
374 if not is_updated and nb_rows > 0 and len(self.input_conditions) > 0:
375 QMessageBox.information(self, self.tr("Information"), self.tr("No one group name from the MED file is presented in the input list of conditions."))
377 """Get output file path"""
378 def get_output_path(self):
379 path = self.bndConditionsFileEdit.text()
381 if not self.sameAsInputCB.isChecked():
382 path = self.resultBndConditionsFileEdit.text()
386 """Check if the input data is valid"""
390 if self.boundaryConditionsTable.rowCount() < 1:
391 QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Boundary conditions list is empty."))
392 elif len(self.get_output_path())==0:
393 QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Output file path is empty."))
395 has_empty_cells = True
396 for row_nb in xrange(0, self.boundaryConditionsTable.rowCount()):
397 lihbor = str(self.boundaryConditionsTable.item(row_nb, 1).text())
398 liubor = str(self.boundaryConditionsTable.item(row_nb, 2).text())
399 livbor = str(self.boundaryConditionsTable.item(row_nb, 3).text())
400 litbor = str(self.boundaryConditionsTable.item(row_nb, 4).text())
401 #print "valid: ", lihbor, liubor, livbor, litbor
402 if lihbor and liubor and livbor and litbor:
403 has_empty_cells = False # Full lines are OK
404 #print "valid: full line"
405 if (not lihbor) and (not liubor) and (not livbor) and (not litbor):
406 has_empty_cells = False # Empty lines are OK
407 #print "valid: empty line"
410 QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Table has empty cell(s)."))
416 """Shows help page"""
419 <h2>Boundary conditions dialog</h2>
421 This dialog is used to read and write boundary conditions files.
422 Below is the description of the dialog controls.
425 This field allows selection of a med file (via the standard file open dialog).
426 The file must contain groups of edges, if this is not the case a warning message appears.
427 The filling of this field is mandatory.
429 <h3>Boundary conditions file</h3>
430 This field allows selecting the file of boundary conditions (via the standard file open dialog).
431 The data from this file is displayed in the table "Boundary conditions".
432 This field is optional; if it is not selected the table will not be prefilled.
434 <h3>Result boundary conditions file</h3>
435 This field allows selecting the file in which to save the data (via the standard file save dialog).
436 This field is mandatory if the "Same as the input" check box is unchecked.
438 <h3>Boundary conditions table</h3>
439 Contains data representing the list of boundary conditions.
440 The first column contains a list of presets.
441 The last columns is read-only, it contains names of group of edges from the selected MED file.
442 Other columns is for LIHBOR, LIUBOR, LIVBOR and LITBOR parameters, which can take a value ranging between 0 and 6.
445 When the table is filled and the output file is defined, the user clicks on "Apply" or "Apply and Close" button
446 to perform the data export to the file.
447 Click on "Close" button does not lead to saving the data and just closes the dialog.
449 QMessageBox.about(self, self.tr("About boundary conditions dialog"), msg);