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