Salome HOME
[PY3] more Swig fix + integer division
[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 salome.smesh.spadder.gui.inputframe_ui import Ui_InputFrame
36 from salome.smesh.spadder.gui.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         # Setup default values for numerical parameters
119         self.__ui.txtParamNbIter.setValue(3)
120
121         # Note that PADDER does not support group name longer than 8
122         # characters. We apply then this limit in the gui field.
123         self.__ui.txtGroupName.setMaxLength(GROUPNAME_MAXLENGTH)
124
125         self.clear()
126
127         self.smeshStudyTool = SMeshStudyTools()
128
129     def clear(self):
130         """
131         This function clears the data gui area and associated values.
132         """
133         self.__ui.txtSmeshObject.setText("")
134         self.__ui.txtGroupName.setText("")
135         self.__inputModel.clear()
136         self.__inputModel.setHorizontalHeaderLabels(InputDialog.TBL_HEADER_LABEL)
137         if not DEBUG_MODE:
138             self.__ui.txtSmeshObject.setEnabled(False)
139             self.__ui.btnAddInput.setEnabled(False)
140         self.__selectedMesh = None
141         self.__dictInputData = {}
142         self.__nbConcreteMesh = 0
143         self.__nbSteelbarMesh = 0
144
145     def accept(self):
146         """
147         This function is the slot connected to the button OK
148         """
149         # The dialog is raised in a non modal mode to get
150         # interactivity with the parents windows. Then we have to emit
151         # a signal to warn the parent observer that the dialog has
152         # been validated so that it can process the event
153         GenericDialog.accept(self)
154         if self.wasOk():
155             self.inputValidated.emit()
156
157     def onSelectSmeshObject(self):
158         '''
159         This function is the slot connected on the mesh selection
160         button. It memorizes the selected mesh and put its name in the
161         text field of the dialog box.
162         '''
163         mySObject, myEntry = guihelper.getSObjectSelected()
164         if CORBA.is_nil(mySObject):
165             self.__ui.txtSmeshObject.setText("You must choose a mesh")
166             self.__ui.txtGroupName.setText("")
167             self.__ui.txtSmeshObject.setEnabled(False)
168             self.__ui.btnAddInput.setEnabled(False)
169             self.__selectedMesh = None
170             return
171
172         self.smeshStudyTool.updateStudy(studyedit.getActiveStudyId())
173         self.__selectedMesh = self.smeshStudyTool.getMeshObjectFromSObject(mySObject)
174         if CORBA.is_nil(self.__selectedMesh):
175             self.__ui.txtSmeshObject.setText("The selected object is not a mesh")
176             self.__ui.txtGroupName.setText("")
177             self.__ui.txtSmeshObject.setEnabled(False)
178             self.__ui.btnAddInput.setEnabled(False)
179             self.__selectedMesh = None
180             return
181         myName = mySObject.GetName()
182         self.__ui.txtSmeshObject.setText(myName)
183         self.__ui.txtSmeshObject.setEnabled(True)
184         self.__ui.btnAddInput.setEnabled(True)
185
186         # We can suggest a default group name from the mesh name
187         self.__ui.txtGroupName.setText(myName)
188
189     def onAddInput(self):
190         """
191         This function is the slot connected to the Add button. It
192         creates a new entry in the list of input data, or updates this
193         entry if it already exists.
194         """
195         meshName   = str(self.__ui.txtSmeshObject.text()).strip()
196         meshObject = self.__selectedMesh
197         meshType   = self.__ui.cmbMeshType.currentIndex()
198         groupName  = str(self.__ui.txtGroupName.text()).strip()
199
200         self.__addInputInGui(meshName, meshObject, meshType, groupName)
201         self.__addInputInMap(meshName, meshObject, meshType, groupName)
202
203     def __addInputInGui(self, meshName, meshObject, meshType, groupName):
204         """
205         This function adds an entry with the specified data int the
206         GUI table (for data visualization purpose).
207         """
208         # The mesh name is used as the key index in the model. We have
209         # to check first if this item already exists in the list.
210         tblItems = self.__inputModel.findItems(meshName)
211         row = self.__inputModel.rowCount()
212         if not tblItems:
213             tblItems = []
214             tblItems.append(QStandardItem()) # input mesh name
215             tblItems.append(QStandardItem()) # output group name
216         else:
217             row = tblItems[0].index().row()
218             tblItems.append(self.__inputModel.item(row,1))
219
220         tblItems[0].setText(meshName)
221         tblItems[0].setIcon(self.MESHTYPE_ICONS[meshType])
222         tblItems[1].setText(groupName)
223         self.__inputModel.setItem(row,0,tblItems[0])
224         self.__inputModel.setItem(row,1,tblItems[1])
225         self.__ui.tblListInput.setCurrentIndex(tblItems[0].index())
226
227     def __addInputInMap(self, meshName, meshObject, meshType, groupName):
228         """
229         This function adds an entry with the specified data in the
230         internal map (for data management purpose).
231         """
232         # if the entry already exists, we remove it to replace by a
233         # new one
234         if meshName in self.__dictInputData:
235             self.__delInputFromMap(meshName)
236
237         inputData = InputData()
238         inputData.meshName   = meshName
239         inputData.meshObject = meshObject
240         inputData.meshType   = meshType
241         inputData.groupName  = groupName
242         # The key of the map is the mesh name
243         self.__dictInputData[meshName] = inputData
244         if inputData.meshType == InputData.MESHTYPES.CONCRETE:
245             self.__nbConcreteMesh += 1
246         else:
247             self.__nbSteelbarMesh += 1
248
249         print(inputData)
250         print("meshType = ",inputData.meshType)
251         print("nb concrete mesh ",self.__nbConcreteMesh)
252         print("nb steelbar mesh ",self.__nbSteelbarMesh)
253
254
255     def onDeleteInput(self):
256         """
257         This function is the slot connected to the Delete button. It
258         remove from the data list the entry selected in the Qt table.
259         """
260         selectedIdx = self.__ui.tblListInput.selectedIndexes()
261         if selectedIdx:
262             row  = selectedIdx[0].row()
263             tblItem  = self.__inputModel.item(row,0)
264             meshName = str(tblItem.text())
265             self.__inputModel.takeRow(row)
266             # Don't forget to remove this entry from the mesh object
267             # internal dictionnary
268             self.__delInputFromMap(meshName)
269
270     def __delInputFromMap(self, meshName):
271         """
272         This function removes the specified entry from the internal
273         map (for data management purpose)
274         """
275         inputData = self.__dictInputData.pop(meshName)
276         if inputData.meshType == InputData.MESHTYPES.CONCRETE:
277             self.__nbConcreteMesh -= 1
278         else:
279             self.__nbSteelbarMesh -= 1
280
281         print(inputData)
282         print("nb concrete mesh ",self.__nbConcreteMesh)
283         print("nb steelbar mesh ",self.__nbSteelbarMesh)
284
285
286     def setData(self, listInputData=[]):
287         """
288         This function fills the dialog widgets with values provided by
289         the specified data list.
290         """
291         self.clear()
292         for inputData in listInputData:
293
294             meshName   = inputData.meshName
295             meshObject = inputData.meshObject
296             meshType   = inputData.meshType
297             groupName  = inputData.groupName
298
299             self.__addInputInGui(meshName, meshObject, meshType, groupName)
300             self.__addInputInMap(meshName, meshObject, meshType, groupName)
301
302             if not DEBUG_MODE:
303                 self.onSelectSmeshObject()
304
305     def getData(self):
306         """
307         This function returns a list of InputData that corresponds to
308         the data in the dialog widgets of the current dialog.
309         """
310         # Note that the values() function returns a copy of the list
311         # of values.
312         return list(self.__dictInputData.values())
313
314     def checkData(self):
315         """
316         This function checks if the data are valid, from the dialog
317         window point of view.
318         """
319         if self.__nbConcreteMesh == 0 and self.__nbSteelbarMesh == 0:
320             self.checkDataMessage = "You must define at least one mesh (CONCRETE or STEELBAR)"
321             return False
322         if self.__nbConcreteMesh > 1:
323             self.checkDataMessage  = "You define multiple CONCRETE meshes."
324             self.checkDataMessage += "You should verify first that your version of PADDER support this configuration."
325             # just warn the user, but don't block
326             QMessageBox.information(self, "Info", self.checkDataMessage)
327             return True
328
329         return True
330
331     #def setParameters(self,
332
333 # ==============================================================================
334 # Basic use case
335 # ==============================================================================
336 #
337 def TEST_InputDialog():
338     import sys
339     from qtsalome import QApplication
340     app = QApplication(sys.argv)
341     app.lastWindowClosed.connect( app.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 qtsalome import QApplication
351     app = QApplication(sys.argv)
352     app.lastWindowClosed.connect( app.quit )
353
354     dlg=InputDialog()
355
356     from .inputdata import InputData
357     inputData = InputData()
358     inputData.meshName   = "myMesh"
359     inputData.meshObject = None
360     inputData.meshType   = InputData.MESHTYPES.CONCRETE
361     inputData.groupName  = "myGroup"
362     listInputData = []
363     listInputData.append(inputData)
364
365     dlg.setData2(listInputData)
366
367     dlg.displayAndWait()
368     if dlg.wasOk():
369         print("OK has been pressed")
370         outputListInputData = dlg.getData2()
371         print(outputListInputData)
372
373
374 if __name__ == "__main__":
375     #TEST_InputDialog()
376     TEST_InputDialog_setData()
377