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 PyQt4 import QtCore, QtGui, uic
23 from MEDLoader import MEDFileMesh
25 # TODO: get rid of sys.path.append() ?
26 hydro_solver_root = os.path.join(os.environ['HYDROSOLVER_ROOT_DIR'], 'lib', 'python2.7', 'site-packages', 'salome')
27 sys.path.append(os.path.join(hydro_solver_root, 'salome', 'hydrotools'))
29 import boundaryConditions
31 ROW_PROPERTY_NAME = "row"
33 """Get names of groups on edges from the given MED file"""
34 def get_med_groups_on_edges(file_path):
36 med_file_mesh = MEDFileMesh.New(file_path)
37 groups = list(med_file_mesh.getGroupsOnSpecifiedLev(-1))
43 """Get preset name corresponding to the given values of LIHBOR, LIUBOR, LIVBOR and LITBOR"""
44 def get_preset_name(presets, lihbor, liubor, livbor, litbor):
47 for preset_name in presets:
48 values = presets[preset_name]
55 if not p_lihbor or p_lihbor == lihbor:
56 if not p_liubor or p_liubor == liubor:
57 if not p_livbor or p_livbor == livbor:
58 if not p_litbor or p_litbor == litbor:
63 """Convert string to integer, return None if conversion is not possible"""
72 """Item delegate for LIHBOR, LIUBOR, LIVBOR and LITBOR columns"""
73 class ValueDelegate(QtGui.QStyledItemDelegate):
75 def __init__(self, parent = None):
76 QtGui.QStyledItemDelegate.__init__(self, parent)
78 def createEditor(self, parent, option, index):
79 line_edit = QtGui.QLineEdit(parent)
81 validator = QtGui.QIntValidator(parent)
82 validator.setRange(0, 6)
84 line_edit.setValidator(validator)
88 def setEditorData(self, editor, index):
89 value, is_ok = index.model().data(index, QtCore.Qt.EditRole).toInt()
92 editor.setText(str(value))
96 def setModelData(self, editor, model, index):
97 model.setData(index, editor.text(), QtCore.Qt.EditRole)
99 def updateEditorGeometry(self, editor, option, index):
100 editor.setGeometry(option.rect)
102 """Boundary conditions definition dialog"""
103 class BoundaryConditionsDialog(QtGui.QDialog):
105 def __init__(self, parent = None, modal = 0):
106 QtGui.QDialog.__init__(self, parent)
107 uic.loadUi(os.path.join(hydro_solver_root, 'BndConditionsDialog.ui'), self )
110 self.medFileButton.clicked.connect(self.on_med_file_browse)
111 self.bndConditionsFileButton.clicked.connect(self.on_bnd_file_browse)
112 self.resultBndConditionsFileButton.clicked.connect(self.on_result_file_browse)
114 self.sameAsInputCB.toggled.connect(self.resultBndConditionsFileEdit.setDisabled)
115 self.sameAsInputCB.toggled.connect(self.resultBndConditionsFileButton.setDisabled)
117 self.boundaryConditionsTable.cellChanged.connect(self.on_cell_changed)
119 self.applyAndCloseButton.clicked.connect(self.on_apply_and_close)
120 self.applyButton.clicked.connect(self.on_apply)
121 self.closeButton.clicked.connect(self.reject)
122 self.helpButton.clicked.connect(self.on_help)
124 # Set widgets properties
128 self.input_conditions = {}
134 """Initialize presets"""
135 def init_presets(self):
136 # TODO: determine another presets path
137 presets_data_root = os.path.join(os.environ['HYDROSOLVER_ROOT_DIR'], 'lib', 'python2.7', 'site-packages', 'salome', 'tests', 'data')
138 file_path = os.path.join(presets_data_root, 'bnd_conditions_presets.txt')
139 reader = boundaryConditions.PresetReader(file_path)
140 self.presets = reader.read()
142 """Initialize widget properties"""
143 def init_widgets(self):
144 self.medFileEdit.setReadOnly(True)
145 self.bndConditionsFileEdit.setReadOnly(True)
146 self.resultBndConditionsFileEdit.setReadOnly(True)
148 delegate = ValueDelegate(self.boundaryConditionsTable)
149 self.boundaryConditionsTable.setItemDelegateForColumn(1, delegate)
150 self.boundaryConditionsTable.setItemDelegateForColumn(2, delegate)
151 self.boundaryConditionsTable.setItemDelegateForColumn(3, delegate)
152 self.boundaryConditionsTable.setItemDelegateForColumn(4, delegate)
154 """Process cell data changes"""
155 def on_cell_changed(self, row, column):
156 lihbor = liubor = livbor = litbor = None
158 item = self.boundaryConditionsTable.item(row, 1)
160 lihbor = get_int(str(item.text()))
162 item = self.boundaryConditionsTable.item(row, 2)
164 liubor = get_int(str(item.text()))
166 item = self.boundaryConditionsTable.item(row, 3)
168 livbor = get_int(str(item.text()))
170 item = self.boundaryConditionsTable.item(row, 4)
172 litbor = get_int(str(item.text()))
174 preset_name = get_preset_name(self.presets, lihbor, liubor, livbor, litbor)
176 combo = self.boundaryConditionsTable.cellWidget(row, 0)
177 if isinstance(combo, QtGui.QComboBox):
178 ind = combo.findText(preset_name)
180 combo.setCurrentIndex(ind)
182 """Save the user data to boundary conditions file"""
184 # Save boundary conditions file
185 if not self.is_valid():
188 file_path = self.get_output_path()
189 writer = boundaryConditions.BoundaryConditionWriter(file_path)
192 for row_nb in xrange(0, self.boundaryConditionsTable.rowCount()):
193 lihbor = str(self.boundaryConditionsTable.item(row_nb, 1).text())
194 liubor = str(self.boundaryConditionsTable.item(row_nb, 2).text())
195 livbor = str(self.boundaryConditionsTable.item(row_nb, 3).text())
196 litbor = str(self.boundaryConditionsTable.item(row_nb, 4).text())
198 if lihbor and liubor and livbor and litbor:
199 group_name = str(self.boundaryConditionsTable.item(row_nb, 5).text())
200 conditions.append(boundaryConditions.BoundaryCondition(lihbor, liubor, livbor, litbor, group_name))
202 writer.write(conditions)
206 """Save the user data to boundary conditions file and close the dialog"""
207 def on_apply_and_close(self):
211 """Select MED file"""
212 def on_med_file_browse(self):
214 file_path = QtGui.QFileDialog.getOpenFileName(self, self.tr("Open MED file"), "", self.tr("MED files (*.med)"))
218 # Get names of groups on edges
219 groups = get_med_groups_on_edges(str(file_path))
223 self.medFileEdit.setText(file_path)
226 self.set_groups(groups)
228 QtGui.QMessageBox.warning(self, self.tr("Warning"), self.tr("Can't get group names from the selected MED file."))
230 """Select boundary conditions file"""
231 def on_bnd_file_browse(self):
232 file_path = QtGui.QFileDialog.getOpenFileName(self, self.tr("Open boundary conditions file"))
235 self.bndConditionsFileEdit.setText(file_path)
236 reader = boundaryConditions.BoundaryConditionReader(file_path)
237 conditions = reader.read()
239 self.input_conditions.clear()
240 for cnd in conditions:
241 self.input_conditions[cnd.group] = (cnd.lihbor, cnd.liubor, cnd.livbor, cnd.litbor)
244 read_errors = reader.errors
245 if len( read_errors ) > 0:
246 msg = "\n".join(read_errors)
247 QtGui.QMessageBox.warning(self, self.tr("Warning"), msg)
249 if len(self.input_conditions) > 0:
252 QtGui.QMessageBox.warning(self, self.tr("Warning"), self.tr("No conditions have been read from the file."))
254 """Called on preset selection in the first column of the table"""
255 def on_preset_changed(self):
256 combo = self.sender()
258 preset = str(combo.currentText())
260 if preset and self.presets.has_key(preset):
261 values = self.presets[preset]
262 row_nb, is_ok = combo.property(ROW_PROPERTY_NAME).toInt()
264 if is_ok and row_nb >= 0 and row_nb < self.boundaryConditionsTable.rowCount():
271 self.boundaryConditionsTable.item(row_nb, 1).setText(str(lihbor))
274 self.boundaryConditionsTable.item(row_nb, 2).setText(str(liubor))
277 self.boundaryConditionsTable.item(row_nb, 3).setText(str(livbor))
280 self.boundaryConditionsTable.item(row_nb, 4).setText(str(litbor))
282 """Define result file path"""
283 def on_result_file_browse(self):
284 file_path = QtGui.QFileDialog.getSaveFileName(self, self.tr("Select output file path"))
286 self.resultBndConditionsFileEdit.setText(file_path)
288 """Set groups list"""
289 def set_groups(self, groups):
290 self.boundaryConditionsTable.setRowCount(0)
293 row_nb = self.boundaryConditionsTable.rowCount()
294 self.boundaryConditionsTable.insertRow(row_nb)
297 combo = QtGui.QComboBox(self)
299 if len(self.presets) > 0:
300 combo.addItems(self.presets.keys())
302 combo.setProperty(ROW_PROPERTY_NAME, row_nb)
304 combo.currentIndexChanged.connect(self.on_preset_changed)
306 self.boundaryConditionsTable.setCellWidget(row_nb, 0, combo)
309 self.boundaryConditionsTable.setItem(row_nb, 1, QtGui.QTableWidgetItem(''))
312 self.boundaryConditionsTable.setItem(row_nb, 2, QtGui.QTableWidgetItem(''))
315 self.boundaryConditionsTable.setItem(row_nb, 3, QtGui.QTableWidgetItem(''))
318 self.boundaryConditionsTable.setItem(row_nb, 4, QtGui.QTableWidgetItem(''))
321 item = QtGui.QTableWidgetItem(group)
325 item.setFlags(QtCore.Qt.ItemIsEnabled)
326 self.boundaryConditionsTable.setItem(row_nb, 5, item)
330 """Update conditions data in the table from the conditions input file"""
331 def update_table(self):
334 nb_rows = self.boundaryConditionsTable.rowCount()
335 for row_nb in xrange(0, nb_rows):
336 group_name = str(self.boundaryConditionsTable.item(row_nb, 5).text())
337 if self.input_conditions.has_key(group_name):
338 values = self.input_conditions[group_name]
340 lihbor = str(values[0])
341 liubor = str(values[1])
342 livbor = str(values[2])
343 litbor = str(values[3])
345 self.boundaryConditionsTable.item(row_nb, 1).setText(lihbor)
346 self.boundaryConditionsTable.item(row_nb, 2).setText(liubor)
347 self.boundaryConditionsTable.item(row_nb, 3).setText(livbor)
348 self.boundaryConditionsTable.item(row_nb, 4).setText(litbor)
352 if not is_updated and nb_rows > 0 and len(self.input_conditions) > 0:
353 QtGui.QMessageBox.information(self, self.tr("Information"), self.tr("No one group name from the MED file is presented in the input list of conditions."))
355 """Get output file path"""
356 def get_output_path(self):
357 path = self.bndConditionsFileEdit.text()
359 if not self.sameAsInputCB.isChecked():
360 path = self.resultBndConditionsFileEdit.text()
364 """Check if the input data is valid"""
368 if self.boundaryConditionsTable.rowCount() < 1:
369 QtGui.QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Boundary conditions list is empty."))
370 elif self.get_output_path().isEmpty():
371 QtGui.QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Output file path is empty."))
373 has_incomplete_lines = False
374 is_table_empty = True
375 for row_nb in xrange(0, self.boundaryConditionsTable.rowCount()):
376 lihbor = str(self.boundaryConditionsTable.item(row_nb, 1).text())
377 liubor = str(self.boundaryConditionsTable.item(row_nb, 2).text())
378 livbor = str(self.boundaryConditionsTable.item(row_nb, 3).text())
379 litbor = str(self.boundaryConditionsTable.item(row_nb, 4).text())
381 has_filled_cells = True if (lihbor or liubor or livbor or litbor) else False
384 is_table_empty = False
386 all_cells_filled = True if (lihbor and liubor and livbor and litbor) else False
387 if has_filled_cells and (not all_cells_filled):
388 has_incomplete_lines = True
392 QtGui.QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Table is empty."))
393 elif has_incomplete_lines:
394 QtGui.QMessageBox.critical(self, self.tr("Insufficient input data"), self.tr("Table has incomplete line(s)."))
400 """Shows help page"""
403 <h2>Boundary conditions dialog</h2>
405 This dialog is used to read and write boundary conditions files.
406 Below is the description of the dialog controls.
409 This field allows selection of a med file (via the standard file open dialog).
410 The file must contain groups of edges, if this is not the case a warning message appears.
411 The filling of this field is mandatory.
413 <h3>Boundary conditions file</h3>
414 This field allows selecting the file of boundary conditions (via the standard file open dialog).
415 The data from this file is displayed in the table "Boundary conditions".
416 This field is optional; if it is not selected the table will not be prefilled.
418 <h3>Result boundary conditions file</h3>
419 This field allows selecting the file in which to save the data (via the standard file save dialog).
420 This field is mandatory if the "Same as the input" check box is unchecked.
422 <h3>Boundary conditions table</h3>
423 Contains data representing the list of boundary conditions.
424 The first column contains a list of presets.
425 The last columns is read-only, it contains names of group of edges from the selected MED file.
426 Other columns is for LIHBOR, LIUBOR, LIVBOR and LITBOR parameters, which can take a value ranging between 0 and 6.
429 When the table is filled and the output file is defined, the user clicks on "Apply" or "Apply and Close" button
430 to perform the data export to the file.
431 Click on "Close" button does not lead to saving the data and just closes the dialog.
433 QtGui.QMessageBox.about(self, self.tr("About boundary conditions dialog"), msg);