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