1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2013 EDF R&D
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.
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.
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
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
25 from YamsPlugDialog import Ui_YamsPlugDialog
26 from monViewText import MonViewText
27 from PyQt4.QtGui import *
28 from PyQt4.QtCore import *
31 class MonYamsPlugDialog(Ui_YamsPlugDialog,QWidget):
35 QWidget.__init__(self)
37 self.connecterSignaux()
43 self.__selectedMesh=None
45 # complex whith QResources: not used
46 # The icon are supposed to be located in the $SMESH_ROOT_DIR/share/salome/resources/smesh folder,
47 # other solution could be in the same folder than this python module file:
48 # iconfolder=os.path.dirname(os.path.abspath(__file__))
50 self.iconfolder=os.environ["SMESH_ROOT_DIR"]+"/share/salome/resources/smesh"
51 #print "monYamsPlugDialog iconfolder",iconfolder
53 icon.addFile(os.path.join(self.iconfolder,"select1.png"))
54 self.PB_LoadHyp.setIcon(icon)
55 self.PB_LoadHyp.setToolTip("hypothesis from Salome Object Browser")
56 self.PB_SaveHyp.setIcon(icon)
57 self.PB_SaveHyp.setToolTip("hypothesis to Salome Object Browser")
58 self.PB_MeshSmesh.setIcon(icon)
59 self.PB_MeshSmesh.setToolTip("source mesh from Salome Object Browser")
61 icon.addFile(os.path.join(self.iconfolder,"open.png"))
62 self.PB_ParamsFileExplorer.setIcon(icon)
63 self.PB_Load.setIcon(icon)
64 self.PB_Load.setToolTip("hypothesis from file")
65 self.PB_Save.setIcon(icon)
66 self.PB_Save.setToolTip("hypothesis to file")
67 self.PB_MeshFile.setIcon(icon)
68 self.PB_MeshFile.setToolTip("source mesh from a file in disk")
70 #Ces parametres ne sont pas remis à rien par le clean
71 self.paramsFile= os.path.abspath(os.path.join(os.environ["HOME"],".yams.dat"))
72 self.LE_ParamsFile.setText(self.paramsFile)
73 self.LE_MeshFile.setText("")
74 self.LE_MeshSmesh.setText("")
76 v1=QDoubleValidator(self)
78 #v1.setTop(1000.) #per thousand... only if relative
80 self.SP_Tolerance.setValidator(v1)
81 self.SP_Tolerance.titleForWarning="Chordal Tolerance"
86 def connecterSignaux(self) :
87 self.connect(self.PB_Cancel,SIGNAL("clicked()"),self.PBCancelPressed)
88 self.connect(self.PB_Default,SIGNAL("clicked()"),self.clean)
89 self.connect(self.PB_Help,SIGNAL("clicked()"),self.PBHelpPressed)
90 self.connect(self.PB_OK,SIGNAL("clicked()"),self.PBOKPressed)
92 self.connect(self.PB_Load,SIGNAL("clicked()"),self.PBLoadPressed)
93 self.connect(self.PB_Save,SIGNAL("clicked()"),self.PBSavePressed)
94 self.connect(self.PB_LoadHyp,SIGNAL("clicked()"),self.PBLoadHypPressed)
95 self.connect(self.PB_SaveHyp,SIGNAL("clicked()"),self.PBSaveHypPressed)
97 self.connect(self.PB_MeshFile,SIGNAL("clicked()"),self.PBMeshFilePressed)
98 self.connect(self.PB_MeshSmesh,SIGNAL("clicked()"),self.PBMeshSmeshPressed)
99 self.connect(self.LE_MeshSmesh,SIGNAL("returnPressed()"),self.meshSmeshNameChanged)
100 self.connect(self.PB_ParamsFileExplorer,SIGNAL("clicked()"),self.setParamsFileName)
101 self.connect(self.LE_MeshFile,SIGNAL("returnPressed()"),self.meshFileNameChanged)
102 self.connect(self.LE_ParamsFile,SIGNAL("returnPressed()"),self.paramsFileNameChanged)
104 def PBHelpPressed(self):
106 mydir=os.environ["SMESH_ROOT_DIR"]
108 QMessageBox.warning(self, "Help", "Help unavailable $SMESH_ROOT_DIR not found")
110 maDoc=mydir+"/share/doc/salome/gui/SMESH/yams/_downloads/YamsWhitePaper_3.2.pdf"
111 command="xdg-open "+maDoc+";"
112 subprocess.call(command, shell=True)
114 def PBOKPressed(self):
115 if not(self.PrepareLigneCommande()):
117 #QMessageBox.warning(self, "Compute", "Command not found")
119 maFenetre=MonViewText(self,self.commande)
121 def enregistreResultat(self):
125 from salome.kernel import studyedit
127 if not os.path.isfile(self.fichierOut):
128 QMessageBox.warning(self, "Compute", "Result file "+self.fichierOut+" not found")
130 maStudy=studyedit.getActiveStudy()
131 smesh.SetCurrentStudy(maStudy)
132 (outputMesh, status) = smesh.CreateMeshesFromGMF(self.fichierOut)
133 name=str(self.LE_MeshSmesh.text())
135 initialMeshObject=None
137 a=str(self.fichierIn)
138 name=os.path.basename(os.path.splitext(a)[0])
141 initialMeshObject=maStudy.FindObjectByName(name ,"SMESH")[0]
143 meshname = name+"_YAMS_"+str(self.num)
144 smesh.SetName(outputMesh.GetMesh(), meshname)
145 outputMesh.Compute() #no algorithms message for "Mesh_x" has been computed with warnings: - global 1D algorithm is missing
147 self.editor = studyedit.getStudyEditor() #
148 moduleEntry=self.editor.findOrCreateComponent("SMESH","SMESH")
149 HypReMeshEntry = self.editor.findOrCreateItem(
150 moduleEntry, name = "Plugins Hypotheses", icon="mesh_tree_hypo.png") #, comment = "HypoForRemeshing" )
152 monStudyBuilder=maStudy.NewBuilder()
153 monStudyBuilder.NewCommand()
154 newStudyIter=monStudyBuilder.NewObject(HypReMeshEntry)
155 self.editor.setAttributeValue(newStudyIter, "AttributeName", "YAMS Parameters_"+str(self.num))
156 self.editor.setAttributeValue(newStudyIter, "AttributeComment", self.getResumeData(separator=" ; "))
158 SOMesh=maStudy.FindObjectByName(meshname ,"SMESH")[0]
160 if initialMeshFile!=None:
161 newStudyFileName=monStudyBuilder.NewObject(SOMesh)
162 self.editor.setAttributeValue(newStudyFileName, "AttributeName", "meshFile")
163 self.editor.setAttributeValue(newStudyFileName, "AttributeExternalFileDef", initialMeshFile)
164 self.editor.setAttributeValue(newStudyFileName, "AttributeComment", initialMeshFile)
166 if initialMeshObject!=None:
167 newLink=monStudyBuilder.NewObject(SOMesh)
168 monStudyBuilder.Addreference(newLink, initialMeshObject)
170 newLink=monStudyBuilder.NewObject(SOMesh)
171 monStudyBuilder.Addreference(newLink, newStudyIter)
173 if salome.sg.hasDesktop(): salome.sg.updateObjBrowser(0)
177 def PBSavePressed(self,NomHypo=False):
178 from datetime import datetime
179 if not(self.PrepareLigneCommande()): return
180 text = "# YAMS hypothesis parameters\n"
181 text += "# Params for mesh : " + self.LE_MeshSmesh.text() +"\n"
182 text += datetime.now().strftime("# Date : %d/%m/%y %H:%M:%S\n")
183 text += "# Command : "+self.commande+"\n"
184 text += self.getResumeData(separator="\n")
188 f=open(self.paramsFile,"a")
190 QMessageBox.warning(self, "File", "Unable to open "+self.paramsFile)
195 QMessageBox.warning(self, "File", "Unable to write "+self.paramsFile)
199 def PBSaveHypPressed(self):
200 """save hypothesis in Object Browser"""
201 #QMessageBox.warning(self, "save Object Browser YAMS Hypothesis", "TODO")
206 from salome.kernel import studyedit
208 maStudy=studyedit.getActiveStudy()
209 smesh.SetCurrentStudy(maStudy)
211 self.editor = studyedit.getStudyEditor()
212 moduleEntry=self.editor.findOrCreateComponent("SMESH","SMESH")
213 HypReMeshEntry = self.editor.findOrCreateItem(
214 moduleEntry, name = "Plugins Hypotheses", icon="mesh_tree_hypo.png") #, comment = "HypoForRemeshing" )
216 monStudyBuilder=maStudy.NewBuilder()
217 monStudyBuilder.NewCommand()
218 newStudyIter=monStudyBuilder.NewObject(HypReMeshEntry)
219 self.editor.setAttributeValue(newStudyIter, "AttributeName", "YAMS Parameters_"+str(self.num))
220 self.editor.setAttributeValue(newStudyIter, "AttributeComment", self.getResumeData(separator=" ; "))
222 if salome.sg.hasDesktop(): salome.sg.updateObjBrowser(0)
226 def SP_toStr(self, widget):
227 """only for a QLineEdit widget"""
228 #cr, pos=widget.validator().validate(res, 0) #n.b. "1,3" is acceptable !locale!
230 val=float(widget.text())
232 QMessageBox.warning(self, widget.titleForWarning, "float value is incorrect: '"+widget.text()+"'")
233 res=str(widget.validator().bottom())
234 widget.setProperty("text", res)
236 valtest=widget.validator().bottom()
239 QMessageBox.warning(self, widget.titleForWarning, "float value is under minimum: "+str(val)+" < "+str(valtest))
241 widget.setProperty("text", res)
243 valtest=widget.validator().top()
246 QMessageBox.warning(self, widget.titleForWarning, "float value is over maximum: "+str(val)+" > "+str(valtest))
248 widget.setProperty("text", res)
252 def getResumeData(self, separator="\n"):
254 for RB in self.GBOptim.findChildren(QRadioButton,):
255 if RB.isChecked()==True:
256 text+="Optimisation="+RB.text()+separator
258 if self.RB_Absolute.isChecked():
259 text+="Units=absolute"+separator
261 text+="Units=relative"+separator
262 v=self.SP_toStr(self.SP_Tolerance)
263 text+="ChordalToleranceDeviation="+v+separator
264 text+="RidgeDetection="+str(self.CB_Ridge.isChecked())+separator
265 text+="SplitEdge="+str(self.CB_SplitEdge.isChecked())+separator
266 text+="PointSmoothing="+str(self.CB_Point.isChecked())+separator
267 text+="GeometricalApproximation="+str(self.SP_Geomapp.value())+separator
268 text+="RidgeAngle="+str(self.SP_Ridge.value())+separator
269 text+="MaximumSize="+str(self.SP_MaxSize.value())+separator
270 text+="MinimumSize="+str(self.SP_MinSize.value())+separator
271 text+="MeshGradation="+str(self.SP_Gradation.value())+separator
272 text+="Verbosity="+str(self.SP_Verbosity.value())+separator
273 text+="Memory="+str(self.SP_Memory.value())+separator
276 def loadResumeData(self, hypothesis, separator="\n"):
279 for slig in reversed(text.split(separator)):
281 #print "load ResumeData",lig
282 if lig=="": continue #skip blanck lines
283 if lig[0]=="#": break
285 tit,value=lig.split("=")
286 if tit=="Optimisation":
287 for RB in self.GBUnit.findChildren(QRadioButton,):
289 for RB in self.GBUnit.findChildren(QRadioButton,):
290 if RB.text()==value :
294 if value=="absolute":
295 self.RB_Absolute.setChecked(True)
296 self.RB_Relative.setChecked(False)
298 self.RB_Absolute.setChecked(False)
299 self.RB_Relative.setChecked(True)
300 if tit=="ChordalToleranceDeviation": self.SP_Tolerance.setProperty("text", float(value))
301 if tit=="RidgeDetection": self.CB_Ridge.setChecked(value=="True")
302 if tit=="SplitEdge": self.CB_SplitEdge.setChecked(value=="True")
303 if tit=="PointSmoothing": self.CB_Point.setChecked(value=="True")
304 if tit=="GeometricalApproximation": self.SP_Geomapp.setProperty("value", float(value))
305 if tit=="RidgeAngle": self.SP_Ridge.setProperty("value", float(value))
306 if tit=="MaximumSize": self.SP_MaxSize.setProperty("value", float(value))
307 if tit=="MinimumSize": self.SP_MinSize.setProperty("value", float(value))
308 if tit=="MeshGradation": self.SP_Gradation.setProperty("value", float(value))
309 if tit=="Verbosity": self.SP_Verbosity.setProperty("value", int(float(value)))
310 if tit=="Memory": self.SP_Memory.setProperty("value", float(value))
312 QMessageBox.warning(self, "load YAMS Hypothesis", "Problem on '"+lig+"'")
314 def PBLoadPressed(self):
315 """load last hypothesis saved in tail of file"""
317 f=open(self.paramsFile,"r")
319 QMessageBox.warning(self, "File", "Unable to open "+self.paramsFile)
324 QMessageBox.warning(self, "File", "Unable to read "+self.paramsFile)
327 self.loadResumeData(text, separator="\n")
329 def PBLoadHypPressed(self):
330 """load hypothesis saved in Object Browser"""
331 #QMessageBox.warning(self, "load Object Browser YAMS hypothesis", "TODO")
333 from salome.kernel import studyedit
334 from salome.smesh.smeshstudytools import SMeshStudyTools
335 from salome.gui import helper as guihelper
336 from omniORB import CORBA
338 mySObject, myEntry = guihelper.getSObjectSelected()
339 if CORBA.is_nil(mySObject) or mySObject==None:
340 QMessageBox.critical(self, "Hypothese", "select an Object Browser YAMS hypothesis")
343 text=mySObject.GetComment()
346 if "Optimisation=" not in text:
347 QMessageBox.critical(self, "Load Hypothese", "Object Browser selection not a YAMS Hypothesis")
349 self.loadResumeData(text, separator=" ; ")
352 def PBCancelPressed(self):
355 def PBMeshFilePressed(self):
356 fd = QFileDialog(self, "select an existing Mesh file", self.LE_MeshFile.text(), "Mesh-Files (*.mesh);;All Files (*)")
358 infile = fd.selectedFiles()[0]
359 self.LE_MeshFile.setText(infile)
360 self.fichierIn=infile.toLatin1()
362 self.LE_MeshSmesh.setText("")
364 def setParamsFileName(self):
365 fd = QFileDialog(self, "select a file", self.LE_ParamsFile.text(), "dat Files (*.dat);;All Files (*)")
367 infile = fd.selectedFiles()[0]
368 self.LE_ParamsFile.setText(infile)
369 self.paramsFile=infile.toLatin1()
371 def meshFileNameChanged(self):
372 self.fichierIn=str(self.LE_MeshFile.text())
373 #print "meshFileNameChanged", self.fichierIn
374 if os.path.exists(self.fichierIn):
375 self.__selectedMesh=None
377 self.LE_MeshSmesh.setText("")
379 QMessageBox.warning(self, "Mesh file", "File doesn't exist")
381 def meshSmeshNameChanged(self):
382 """only change by GUI mouse selection, otherwise clear"""
383 self.__selectedMesh = None
385 self.LE_MeshSmesh.setText("")
389 def paramsFileNameChanged(self):
390 self.paramsFile=self.LE_ParamsFile.text()
392 def PBMeshSmeshPressed(self):
395 from salome.kernel import studyedit
396 from salome.smesh.smeshstudytools import SMeshStudyTools
397 from salome.gui import helper as guihelper
398 from omniORB import CORBA
400 mySObject, myEntry = guihelper.getSObjectSelected()
401 if CORBA.is_nil(mySObject) or mySObject==None:
402 QMessageBox.critical(self, "Mesh", "select an input mesh")
404 self.smeshStudyTool = SMeshStudyTools()
406 self.__selectedMesh = self.smeshStudyTool.getMeshObjectFromSObject(mySObject)
408 QMessageBox.critical(self, "Mesh", "select an input mesh")
410 if CORBA.is_nil(self.__selectedMesh):
411 QMessageBox.critical(self, "Mesh", "select an input mesh")
413 myName = mySObject.GetName()
414 #print "MeshSmeshNameChanged", myName
416 self.LE_MeshSmesh.setText(myName)
417 self.LE_MeshFile.setText("")
420 def prepareFichier(self):
421 self.fichierIn="/tmp/ForYams_"+str(self.num)+".mesh"
423 self.__selectedMesh.ExportGMF(self.__selectedMesh, self.fichierIn, True)
425 def PrepareLigneCommande(self):
426 if self.fichierIn=="" and self.MeshIn=="":
427 QMessageBox.critical(self, "Mesh", "select an input mesh")
429 if self.__selectedMesh!=None: self.prepareFichier()
430 if not (os.path.isfile(self.fichierIn)):
431 QMessageBox.critical(self, "File", "unable to read GMF Mesh in "+str(self.fichierIn))
435 verbosity=str(self.SP_Verbosity.value())
436 self.commande+=" -v "+verbosity
437 for obj in self.GBOptim.findChildren(QRadioButton,):
440 self.style=obj.objectName().remove(0,3)
441 self.style.replace("_","-")
445 self.commande+=" -O "+self.style.toLatin1()
447 deb=os.path.splitext(self.fichierIn)
448 self.fichierOut=deb[0] + ".d.meshb"
450 if self.RB_Absolute.isChecked()==True :
451 self.commande+=" -Dabsolute"
453 self.commande+=" -Drelative"
455 v=self.SP_toStr(self.SP_Tolerance)
456 self.commande+=",tolerance="+v
457 if self.CB_Ridge.isChecked()==False : self.commande+=",-nr"
458 if self.CB_Point.isChecked()==False : self.commande+=",-ns"
459 if self.SP_Geomapp.value()!=0.04 : self.commande+=",geomapp=%f"%self.SP_Geomapp.value()
460 if self.SP_Ridge.value()!=45.0 : self.commande+=",ridge=%f"%self.SP_Ridge.value()
461 if self.SP_MaxSize.value()!=100 : self.commande+=",maxsize=%f"%self.SP_MaxSize.value()
462 if self.SP_MinSize.value()!=5 : self.commande+=",minsize=%f"%self.SP_MinSize.value()
463 if self.SP_Gradation.value()!=1.3 : self.commande+=",gradation=%f"%self.SP_MaxSize.value()
464 if self.CB_SplitEdge.isChecked()==True : self.commande+=",splitedge=1"
466 if self.SP_Verbosity.value()!=3 : self.commande+=" -v %d"%self.SP_Verbosity.value()
467 if self.SP_Memory.value()!=0 : self.commande+=" -m %d"%self.SP_Memory.value()
469 self.commande+=" "+self.fichierIn
473 self.RB_0.setChecked(True)
474 self.RB_G.setChecked(False)
475 self.RB_U.setChecked(False)
476 self.RB_S.setChecked(False)
477 self.RB_2.setChecked(False)
478 self.RB_1.setChecked(False)
479 self.RB_Absolute.setChecked(False)
480 self.RB_Relative.setChecked(True)
481 self.SP_Tolerance.setProperty("text", "10.")
482 self.SP_Geomapp.setProperty("value", 0.04)
483 self.SP_Ridge.setProperty("value", 45.0)
484 self.SP_Gradation.setProperty("value", 1.3)
485 self.CB_Ridge.setChecked(True)
486 self.CB_Point.setChecked(True)
487 self.CB_SplitEdge.setChecked(False)
488 self.SP_MaxSize.setProperty("value", -2.0)
489 self.SP_MinSize.setProperty("value", -2.0)
490 self.SP_Verbosity.setProperty("value", 3)
491 self.SP_Memory.setProperty("value", 0)
496 This function returns a singleton instance of the plugin dialog.
497 c est obligatoire pour faire un show sans parent...
501 __dialog = MonYamsPlugDialog()
507 # ==============================================================================
508 # Basic use cases and unit test functions
509 # ==============================================================================
511 def TEST_MonYamsPlugDialog():
512 #print "TEST_YamsMonPlugDialog"
514 from PyQt4.QtGui import QApplication
515 from PyQt4.QtCore import QObject, SIGNAL, SLOT
516 app = QApplication(sys.argv)
517 QObject.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
519 dlg=MonYamsPlugDialog()
521 sys.exit(app.exec_())
523 if __name__ == "__main__":
524 TEST_MonYamsPlugDialog()