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