Salome HOME
Padder : bug fix for RmaxRmin paramete
[modules/smesh.git] / src / Tools / padder / spadderpy / gui / inputdialog.py
1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2011-2016  EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20 # Author : Guillaume Boulant (EDF)
21 #
22
23 import os
24
25 import salome
26 from salome.kernel import studyedit
27 from salome.gui.genericdialog import GenericDialog
28 from salome.gui import helper as guihelper
29 from salome.smesh.smeshstudytools import SMeshStudyTools
30
31 from omniORB import CORBA
32
33 from qtsalome import QIcon, QStandardItemModel, QStandardItem, QMessageBox, pyqtSignal
34
35 from inputframe_ui import Ui_InputFrame
36 from inputdata import InputData
37
38 DEBUG_MODE=True
39 GROUPNAME_MAXLENGTH=8
40
41 INPUTDATA_KEY_FILES="meshfiles"
42 INPUTDATA_KEY_PARAM="parameters"
43
44 PARAM_KEY_NBITER   = "NbIteration"
45 PARAM_KEY_RMAXRMIN = "RmaxRmin"
46 PARAM_NBITER_DEFAULT_VALUE = 10
47 PARAM_RMAXRMIN_DEFAULT_VALUE = 3
48
49 class InputDialog(GenericDialog):
50
51     TBL_HEADER_LABEL=["Input Mesh", "Output group name"]
52
53     inputValidated = pyqtSignal()
54
55     def __init__(self, parent=None, name="InputDialog", modal=0):
56         """
57         This initializes a dialog windows to define the input data of
58         the plugin function. The input data consist in a list of
59         meshes characterizes each by a name, a pointer to the smesh
60         servant object, a type and a group name (see data model in the
61         inputdata.py).
62         """
63         GenericDialog.__init__(self, parent, name, modal)
64         # Set up the user interface from Designer.
65         self.__ui = Ui_InputFrame()
66         # BE CAREFULL HERE, the ui form is NOT drawn in the global
67         # dialog (already containing some generic widgets) but in the
68         # center panel created in the GenericDialog as a void
69         # container for the form. The InputFrame form is supposed
70         # here to create only the widgets to be placed in the center
71         # panel. Then, the setupUi function of this form draws itself
72         # in the specified panel, i.e. the panel returned by
73         # self.getPanel().
74         self.__ui.setupUi(self.getPanel())
75
76         self.setWindowTitle("Specification of input files")
77
78         # The icon are supposed to be located in the plugin folder,
79         # i.e. in the same folder than this python module file
80         iconfolder=os.path.dirname(os.path.abspath(__file__))
81         icon = QIcon()
82         icon.addFile(os.path.join(iconfolder,"select.png"))
83         self.__ui.btnSmeshObject.setIcon(icon)
84         icon = QIcon()
85         icon.addFile(os.path.join(iconfolder,"addinput.png"))
86         self.__ui.btnAddInput.setIcon(icon)
87         icon = QIcon()
88         icon.addFile(os.path.join(iconfolder,"deleteinput.png"))
89         self.__ui.btnDeleteInput.setIcon(icon)
90
91         # We specify here the items in the combo box (even if already
92         # defined in the designer) so that we can be sure of the item
93         # indexation.
94         self.MESHTYPE_ICONS = {}
95         meshTypeIndex = InputData.MESHTYPES.CONCRETE
96         self.__ui.cmbMeshType.setItemText(meshTypeIndex, "Béton")
97         icon = QIcon()
98         icon.addFile(os.path.join(iconfolder,"concrete.png"))
99         self.__ui.cmbMeshType.setItemIcon(meshTypeIndex, icon)
100         self.MESHTYPE_ICONS[meshTypeIndex] = icon
101
102         meshTypeIndex = InputData.MESHTYPES.STEELBAR
103         self.__ui.cmbMeshType.setItemText(meshTypeIndex, "Acier")
104         icon = QIcon()
105         icon.addFile(os.path.join(iconfolder,"steelbar.png"))
106         self.__ui.cmbMeshType.setItemIcon(meshTypeIndex, icon)
107         self.MESHTYPE_ICONS[meshTypeIndex] = icon
108
109         # The click on btnSmeshObject (signal clicked() emitted by the
110         # button btnSmeshObject) is connected to the slot
111         # onSelectSmeshObject, etc ...
112         self.__ui.btnSmeshObject.clicked.connect( self.onSelectSmeshObject )
113         self.__ui.btnAddInput.clicked.connect( self.onAddInput )
114         self.__ui.btnDeleteInput.clicked.connect(  self.onDeleteInput )
115
116         # Set up the model of the Qt table list
117         self.__inputModel = QStandardItemModel(0,2)
118         self.__inputModel.setHorizontalHeaderLabels(InputDialog.TBL_HEADER_LABEL)
119         self.__ui.tblListInput.setModel(self.__inputModel)
120         self.__ui.tblListInput.verticalHeader().hide()
121         self.__ui.tblListInput.horizontalHeader().setStretchLastSection(True)
122         # Note that the type is not display explicitly in the Qt table
123         # because it is specified using an icon on the text of the
124         # name item.
125
126         # Setup default values for numerical parameters
127         self.__ui.txtParamNbIter.setValue(PARAM_NBITER_DEFAULT_VALUE)
128         self.__ui.txtParamRmaxRmin.setValue(PARAM_RMAXRMIN_DEFAULT_VALUE)
129
130         # Note that PADDER does not support group name longer than 8
131         # characters. We apply then this limit in the gui field.
132         self.__ui.txtGroupName.setMaxLength(GROUPNAME_MAXLENGTH)
133
134         self.clear()
135
136         self.smeshStudyTool = SMeshStudyTools()
137
138     def clear(self):
139         """
140         This function clears the data gui area and associated values.
141         """
142         self.__ui.txtSmeshObject.setText("")
143         self.__ui.txtGroupName.setText("")
144         self.__inputModel.clear()
145         self.__inputModel.setHorizontalHeaderLabels(InputDialog.TBL_HEADER_LABEL)
146         if not DEBUG_MODE:
147             self.__ui.txtSmeshObject.setEnabled(False)
148             self.__ui.btnAddInput.setEnabled(False)
149         self.__selectedMesh = None
150         self.__dictInputFiles = {}
151         self.__nbConcreteMesh = 0
152         self.__nbSteelbarMesh = 0
153
154     def accept(self):
155         """
156         This function is the slot connected to the button OK
157         """
158         # The dialog is raised in a non modal mode to get
159         # interactivity with the parents windows. Then we have to emit
160         # a signal to warn the parent observer that the dialog has
161         # been validated so that it can process the event
162         GenericDialog.accept(self)
163         if self.wasOk():
164             self.inputValidated.emit()
165
166     def onSelectSmeshObject(self):
167         '''
168         This function is the slot connected on the mesh selection
169         button. It memorizes the selected mesh and put its name in the
170         text field of the dialog box.
171         '''
172         mySObject, myEntry = guihelper.getSObjectSelected()
173         if CORBA.is_nil(mySObject):
174             self.__ui.txtSmeshObject.setText("You must choose a mesh")
175             self.__ui.txtGroupName.setText("")
176             self.__ui.txtSmeshObject.setEnabled(False)
177             self.__ui.btnAddInput.setEnabled(False)
178             self.__selectedMesh = None
179             return
180
181         self.smeshStudyTool.updateStudy(studyedit.getActiveStudyId())
182         self.__selectedMesh = self.smeshStudyTool.getMeshObjectFromSObject(mySObject)
183         if CORBA.is_nil(self.__selectedMesh):
184             self.__ui.txtSmeshObject.setText("The selected object is not a mesh")
185             self.__ui.txtGroupName.setText("")
186             self.__ui.txtSmeshObject.setEnabled(False)
187             self.__ui.btnAddInput.setEnabled(False)
188             self.__selectedMesh = None
189             return
190         myName = mySObject.GetName()
191         self.__ui.txtSmeshObject.setText(myName)
192         self.__ui.txtSmeshObject.setEnabled(True)
193         self.__ui.btnAddInput.setEnabled(True)
194
195         # We can suggest a default group name from the mesh name
196         self.__ui.txtGroupName.setText(myName)
197
198     def onAddInput(self):
199         """
200         This function is the slot connected to the Add button. It
201         creates a new entry in the list of input data, or updates this
202         entry if it already exists.
203         """
204         meshName   = str(self.__ui.txtSmeshObject.text()).strip()
205         meshObject = self.__selectedMesh
206         meshType   = self.__ui.cmbMeshType.currentIndex()
207         groupName  = str(self.__ui.txtGroupName.text()).strip()
208
209         self.__addInputInGui(meshName, meshObject, meshType, groupName)
210         self.__addInputInMap(meshName, meshObject, meshType, groupName)
211
212     def __addInputInGui(self, meshName, meshObject, meshType, groupName):
213         """
214         This function adds an entry with the specified data int the
215         GUI table (for data visualization purpose).
216         """
217         # The mesh name is used as the key index in the model. We have
218         # to check first if this item already exists in the list.
219         tblItems = self.__inputModel.findItems(meshName)
220         row = self.__inputModel.rowCount()
221         if not tblItems:
222             tblItems = []
223             tblItems.append(QStandardItem()) # input mesh name
224             tblItems.append(QStandardItem()) # output group name
225         else:
226             row = tblItems[0].index().row()
227             tblItems.append(self.__inputModel.item(row,1))
228
229         tblItems[0].setText(meshName)
230         tblItems[0].setIcon(self.MESHTYPE_ICONS[meshType])
231         tblItems[1].setText(groupName)
232         self.__inputModel.setItem(row,0,tblItems[0])
233         self.__inputModel.setItem(row,1,tblItems[1])
234         self.__ui.tblListInput.setCurrentIndex(tblItems[0].index())
235
236     def __addInputInMap(self, meshName, meshObject, meshType, groupName):
237         """
238         This function adds an entry with the specified data in the
239         internal map (for data management purpose).
240         """
241         # if the entry already exists, we remove it to replace by a
242         # new one
243         if self.__dictInputFiles.has_key(meshName):
244             self.__delInputFromMap(meshName)
245
246         inputData = InputData()
247         inputData.meshName   = meshName
248         inputData.meshObject = meshObject
249         inputData.meshType   = meshType
250         inputData.groupName  = groupName
251         # The key of the map is the mesh name
252         self.__dictInputFiles[meshName] = inputData
253         if inputData.meshType == InputData.MESHTYPES.CONCRETE:
254             self.__nbConcreteMesh += 1
255         else:
256             self.__nbSteelbarMesh += 1
257
258         print inputData
259         print "meshType = ",inputData.meshType
260         print "nb concrete mesh ",self.__nbConcreteMesh
261         print "nb steelbar mesh ",self.__nbSteelbarMesh
262
263
264     def onDeleteInput(self):
265         """
266         This function is the slot connected to the Delete button. It
267         remove from the data list the entry selected in the Qt table.
268         """
269         selectedIdx = self.__ui.tblListInput.selectedIndexes()
270         if selectedIdx:
271             row  = selectedIdx[0].row()
272             tblItem  = self.__inputModel.item(row,0)
273             meshName = str(tblItem.text())
274             self.__inputModel.takeRow(row)
275             # Don't forget to remove this entry from the mesh object
276             # internal dictionnary
277             self.__delInputFromMap(meshName)
278
279     def __delInputFromMap(self, meshName):
280         """
281         This function removes the specified entry from the internal
282         map (for data management purpose)
283         """
284         inputData = self.__dictInputFiles.pop(meshName)
285         if inputData.meshType == InputData.MESHTYPES.CONCRETE:
286             self.__nbConcreteMesh -= 1
287         else:
288             self.__nbSteelbarMesh -= 1
289
290         print inputData
291         print "nb concrete mesh ",self.__nbConcreteMesh
292         print "nb steelbar mesh ",self.__nbSteelbarMesh
293
294
295     def setData(self, dictInputData={}):
296         """
297         This function fills the dialog widgets with values provided by
298         the specified data list.
299         """
300         self.clear()
301         if dictInputData.has_key(INPUTDATA_KEY_FILES):
302             listInputData = dictInputData["meshfiles"]
303             for inputData in listInputData:
304
305                 meshName   = inputData.meshName
306                 meshObject = inputData.meshObject
307                 meshType   = inputData.meshType
308                 groupName  = inputData.groupName
309
310                 self.__addInputInGui(meshName, meshObject, meshType, groupName)
311                 self.__addInputInMap(meshName, meshObject, meshType, groupName)
312
313                 if not DEBUG_MODE:
314                     self.onSelectSmeshObject()
315
316             if dictInputData.has_key(INPUTDATA_KEY_PARAM):
317                 dictInputParameters = dictInputData[INPUTDATA_KEY_PARAM]
318             if dictInputParameters.has_key(PARAM_KEY_NBITER):
319                 self.__ui.txtParamNbIter.setValue(dictInputParameters[PARAM_KEY_NBITER])
320             if dictInputParameters.has_key(PARAM_KEY_RMAXRMIN):
321                 self.__ui.txtParamRmaxRmin.setValue(dictInputParameters[PARAM_KEY_RMAXRMIN])
322
323     def getData(self):
324         """
325         This function returns a list of InputData that corresponds to
326         the data in the dialog widgets of the current dialog.
327         """
328         # Get the list of mesh files
329         # Note that the values() function returns a copy of the list
330         # of values.
331         dictInputData={}
332         dictInputData[INPUTDATA_KEY_FILES] = self.__dictInputFiles.values()
333
334         # Get the list of additionnal parameters
335         dictInputParameters = {}
336         dictInputParameters[PARAM_KEY_NBITER] = self.__ui.txtParamNbIter.value()
337         dictInputParameters[PARAM_KEY_RMAXRMIN] = self.__ui.txtParamRmaxRmin.value()
338         dictInputData[INPUTDATA_KEY_PARAM] = dictInputParameters
339         return dictInputData
340
341     def checkData(self):
342         """
343         This function checks if the data are valid, from the dialog
344         window point of view.
345         """
346         if self.__nbConcreteMesh == 0 and self.__nbSteelbarMesh == 0:
347             self.checkDataMessage = "You must define at least one mesh (CONCRETE or STEELBAR)"
348             return False
349         if self.__nbConcreteMesh > 1:
350             self.checkDataMessage  = "You define multiple CONCRETE meshes."
351             self.checkDataMessage += "You should verify first that your version of PADDER support this configuration."
352             # just warn the user, but don't block
353             QMessageBox.information(self, "Info", self.checkDataMessage)
354             return True
355
356         return True
357
358
359 # ==============================================================================
360 # Basic use case
361 # ==============================================================================
362 #
363 def TEST_InputDialog():
364     import sys
365     from qtsalome import QApplication
366     app = QApplication(sys.argv)
367     app.lastWindowClosed.connect( app.quit )
368
369     dlg=InputDialog()
370     dlg.displayAndWait()
371     if dlg.wasOk():
372         print "OK has been pressed"
373
374 def TEST_InputDialog_setData():
375     import sys
376     from qtsalome import QApplication
377     app = QApplication(sys.argv)
378     app.lastWindowClosed.connect( app.quit )
379
380     dlg=InputDialog()
381
382     from inputdata import InputData
383     inputData = InputData()
384     inputData.meshName   = "myMesh"
385     inputData.meshObject = None
386     inputData.meshType   = InputData.MESHTYPES.CONCRETE
387     inputData.groupName  = "myGroup"
388     listInputData = []
389     listInputData.append(inputData)
390
391     dlg.setData2(listInputData)
392
393     dlg.displayAndWait()
394     if dlg.wasOk():
395         print "OK has been pressed"
396         outputListInputData = dlg.getData2()
397         print outputListInputData
398
399
400 if __name__ == "__main__":
401     #TEST_InputDialog()
402     TEST_InputDialog_setData()
403