Salome HOME
add SMESH plugin MGCleaner
[modules/smesh.git] / src / Tools / MGCleanerPlug / MGCleanerMonPlugDialog.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2013  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
21 # Modules Python
22 # Modules Eficas
23
24 import os, subprocess
25 from MGCleanerPlugDialog import Ui_MGCleanerPlugDialog
26 from MGCleanerMonViewText import MGCleanerMonViewText
27 from PyQt4.QtGui import *
28 from PyQt4.QtCore import *
29
30
31 class MGCleanerMonPlugDialog(Ui_MGCleanerPlugDialog,QWidget):
32   """
33   """
34   def __init__(self):
35     QWidget.__init__(self)
36     self.setupUi(self)
37     self.connecterSignaux()
38     self.fichierIn=""
39     self.fichierOut=""
40     self.MeshIn=""
41     self.commande=""
42     self.num=1
43     self.__selectedMesh=None
44     
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__))
49
50     self.iconfolder=os.environ["SMESH_ROOT_DIR"]+"/share/salome/resources/smesh"
51     #print "MGCleanerMonPlugDialog iconfolder",iconfolder
52     icon = QIcon()
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")
60     icon = QIcon()
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")
69     
70     #Ces parametres ne sont pas remis à rien par le clean
71     self.paramsFile= os.path.abspath(os.path.join(os.environ["HOME"],".MGCleaner.dat"))
72     self.LE_ParamsFile.setText(self.paramsFile)
73     self.LE_MeshFile.setText("")
74     self.LE_MeshSmesh.setText("")
75
76     v1=QDoubleValidator(self)
77     v1.setBottom(0.)
78     #v1.setTop(10000.)
79     v1.setDecimals(4)
80     self.SP_MinHoleSize.setValidator(v1)
81
82     v2=QDoubleValidator(self)
83     v2.setBottom(0.)
84     #v2.setTop(10000.)
85     v2.setDecimals(4)
86     self.SP_ToleranceDisplacement.setValidator(v2)
87
88     v3=QDoubleValidator(self)
89     v3.setBottom(0.)
90     #v3.setTop(10000.)
91     v3.setDecimals(4)
92     self.SP_ResolutionLength.setValidator(v3)
93     
94     v4=QDoubleValidator(self)
95     v4.setBottom(0.)
96     #v4.setTop(10000.)
97     v4.setDecimals(4)
98     self.SP_OverlapDistance.setValidator(v4)
99     
100     self.resize(800, 500)
101     self.clean()
102
103   def connecterSignaux(self) :
104     self.connect(self.PB_Cancel,SIGNAL("clicked()"),self.PBCancelPressed)
105     self.connect(self.PB_Default,SIGNAL("clicked()"),self.clean)
106     self.connect(self.PB_Help,SIGNAL("clicked()"),self.PBHelpPressed)
107     self.connect(self.PB_OK,SIGNAL("clicked()"),self.PBOKPressed)
108     
109     self.connect(self.PB_Load,SIGNAL("clicked()"),self.PBLoadPressed)
110     self.connect(self.PB_Save,SIGNAL("clicked()"),self.PBSavePressed)
111     self.connect(self.PB_LoadHyp,SIGNAL("clicked()"),self.PBLoadHypPressed)
112     self.connect(self.PB_SaveHyp,SIGNAL("clicked()"),self.PBSaveHypPressed)
113     
114     self.connect(self.PB_MeshFile,SIGNAL("clicked()"),self.PBMeshFilePressed)
115     self.connect(self.PB_MeshSmesh,SIGNAL("clicked()"),self.PBMeshSmeshPressed)
116     self.connect(self.LE_MeshSmesh,SIGNAL("returnPressed()"),self.meshSmeshNameChanged)
117     self.connect(self.PB_ParamsFileExplorer,SIGNAL("clicked()"),self.setParamsFileName)
118     self.connect(self.LE_MeshFile,SIGNAL("returnPressed()"),self.meshFileNameChanged)
119     self.connect(self.LE_ParamsFile,SIGNAL("returnPressed()"),self.paramsFileNameChanged)
120
121     #QtCore.QObject.connect(self.checkBox, QtCore.SIGNAL("stateChanged(int)"), self.change) 
122     self.connect(self.CB_FillHoles,SIGNAL("stateChanged(int)"),self.SP_MinHoleSize.setEnabled)
123     self.connect(self.CB_ComputedToleranceDisplacement,SIGNAL("stateChanged(int)"),self.SP_ToleranceDisplacement.setDisabled)
124     self.connect(self.CB_ComputedResolutionLength,SIGNAL("stateChanged(int)"),self.SP_ResolutionLength.setDisabled)
125     self.connect(self.CB_ComputedOverlapDistance,SIGNAL("stateChanged(int)"),self.SP_OverlapDistance.setDisabled)
126
127   def PBHelpPressed(self):
128     try:
129       mydir=os.environ["SMESH_ROOT_DIR"]
130     except Exception:
131       QMessageBox.warning( self, "Help", "Help unavailable $SMESH_ROOT_DIR not found")
132       return
133     maDoc=mydir+"/share/doc/salome/gui/SMESH/MGCleaner/_downloads/mg-cleaner_user_manual.pdf"
134     command="xdg-open "+maDoc+";"
135     subprocess.call(command, shell=True)
136
137   def PBOKPressed(self):
138     if not(self.PrepareLigneCommande()):
139       #warning done yet
140       #QMessageBox.warning(self, "Compute", "Command not found")
141       return
142     maFenetre=MGCleanerMonViewText(self, self.commande)
143
144   def enregistreResultat(self):
145     import smesh
146     import SMESH
147     import salome
148     from salome.kernel import studyedit
149
150     if not os.path.isfile(self.fichierOut):
151       QMessageBox.warning(self, "Compute", "Result file "+self.fichierOut+" not found")
152
153     maStudy=studyedit.getActiveStudy()
154     smesh.SetCurrentStudy(maStudy)
155     (outputMesh, status) = smesh.CreateMeshesFromGMF(self.fichierOut)
156     name=str(self.LE_MeshSmesh.text())
157     initialMeshFile=None
158     initialMeshObject=None
159     if name=="":
160       a=str(self.fichierIn)
161       name=os.path.basename(os.path.splitext(a)[0])
162       initialMeshFile=a
163     else:
164       initialMeshObject=maStudy.FindObjectByName(name ,"SMESH")[0]
165
166     meshname = name+"_MGC_"+str(self.num)
167     smesh.SetName(outputMesh.GetMesh(), meshname)
168     outputMesh.Compute() #no algorithms message for "Mesh_x" has been computed with warnings: -  global 1D algorithm is missing
169
170     self.editor = studyedit.getStudyEditor()
171     moduleEntry=self.editor.findOrCreateComponent("SMESH","SMESH")
172     HypReMeshEntry = self.editor.findOrCreateItem(
173         moduleEntry, name = "Plugins Hypotheses", icon="mesh_tree_hypo.png") #, comment = "HypoForRemeshing" )
174     
175     monStudyBuilder=maStudy.NewBuilder()
176     monStudyBuilder.NewCommand()
177     newStudyIter=monStudyBuilder.NewObject(HypReMeshEntry)
178     self.editor.setAttributeValue(newStudyIter, "AttributeName", "MGCleaner Parameters_"+str(self.num))
179     self.editor.setAttributeValue(newStudyIter, "AttributeComment", self.getResumeData(separator=" ; "))
180     
181     SOMesh=maStudy.FindObjectByName(meshname ,"SMESH")[0]
182     
183     if initialMeshFile!=None:
184       newStudyFileName=monStudyBuilder.NewObject(SOMesh)
185       self.editor.setAttributeValue(newStudyFileName, "AttributeName", "meshFile")
186       self.editor.setAttributeValue(newStudyFileName, "AttributeExternalFileDef", initialMeshFile)
187       self.editor.setAttributeValue(newStudyFileName, "AttributeComment", initialMeshFile)
188
189     if initialMeshObject!=None:
190       newLink=monStudyBuilder.NewObject(SOMesh)
191       monStudyBuilder.Addreference(newLink, initialMeshObject)
192
193     newLink=monStudyBuilder.NewObject(SOMesh)
194     monStudyBuilder.Addreference(newLink, newStudyIter)
195
196     if salome.sg.hasDesktop(): salome.sg.updateObjBrowser(0)
197     self.num+=1
198     return True
199
200   def PBSavePressed(self):
201     from datetime import datetime
202     if not(self.PrepareLigneCommande()): return
203     text = "# MGCleaner hypothesis parameters\n"
204     text += "# Params for mesh : " +  self.LE_MeshSmesh.text() +"\n"
205     text += datetime.now().strftime("# Date : %d/%m/%y %H:%M:%S\n")
206     text += "# Command : "+self.commande+"\n"
207     text += self.getResumeData(separator="\n")
208     text += "\n\n"
209
210     try:
211       f=open(self.paramsFile,"a")
212     except:
213       QMessageBox.warning(self, "File", "Unable to open "+self.paramsFile)
214       return
215     try:
216       f.write(text)
217     except:
218       QMessageBox.warning(self, "File", "Unable to write "+self.paramsFile)
219       return
220     f.close()
221
222   def PBSaveHypPressed(self):
223     """save hypothesis in Object Browser"""
224     #QMessageBox.warning(self, "save Object Browser MGCleaner Hypothesis", "TODO")
225     
226     import smesh
227     import SMESH
228     import salome
229     from salome.kernel import studyedit
230
231     maStudy=studyedit.getActiveStudy()
232     smesh.SetCurrentStudy(maStudy)
233     
234     self.editor = studyedit.getStudyEditor()
235     moduleEntry=self.editor.findOrCreateComponent("SMESH","SMESH")
236     HypReMeshEntry = self.editor.findOrCreateItem(
237         moduleEntry, name = "Plugins Hypotheses", icon="mesh_tree_hypo.png") #, comment = "HypoForRemeshing" )
238     
239     monStudyBuilder=maStudy.NewBuilder()
240     monStudyBuilder.NewCommand()
241     newStudyIter=monStudyBuilder.NewObject(HypReMeshEntry)
242     self.editor.setAttributeValue(newStudyIter, "AttributeName", "MGCleaner Parameters_"+str(self.num))
243     self.editor.setAttributeValue(newStudyIter, "AttributeComment", self.getResumeData(separator=" ; "))
244     
245     if salome.sg.hasDesktop(): salome.sg.updateObjBrowser(0)
246     self.num+=1
247     return True
248
249     """
250     import salome_pluginsmanager
251     print "salome_pluginsmanager.plugins",salome_pluginsmanager.plugins
252     print "salome_pluginsmanager.current_plugins_manager",salome_pluginsmanager.current_plugins_manager
253     """
254   
255   def SP_toStr(self, widget):
256     #cr, pos=widget.validator().validate(res, 0) #n.b. "1,3" is acceptable !locale!
257     try:
258       return str(float(widget.text()))
259     except:
260       widget.setProperty("text", "0.0")
261       return "0.0"
262
263   def getResumeData(self, separator="\n"):
264     text=""
265     if self.RB_Fix1.isChecked():
266       CheckOrFix="fix1pass"
267     else:
268       if self.RB_Fix2.isChecked():
269         CheckOrFix="fix2pass"
270       else:
271         CheckOrFix="check"
272     text+="CheckOrFix="+CheckOrFix+separator
273     text+="PreserveTopology="+str(self.CB_PreserveTopology.isChecked())+separator
274     text+="FillHoles="+str(self.CB_FillHoles.isChecked())+separator
275     v=self.SP_toStr(self.SP_MinHoleSize)
276     text+="MinHoleSize="+v+separator
277     text+="ComputedToleranceDisplacement="+str(self.CB_ComputedToleranceDisplacement.isChecked())+separator
278     v=self.SP_toStr(self.SP_ToleranceDisplacement)
279     text+="ToleranceDisplacement="+v+separator
280     text+="ComputedResolutionLength="+str(self.CB_ComputedResolutionLength.isChecked())+separator
281     v=self.SP_toStr(self.SP_ResolutionLength)
282     text+="ResolutionLength="+v+separator
283     text+="FoldingAngle="+str(self.SP_FoldingAngle.value())+separator
284     text+="RemeshPlanes="+str(self.CB_RemeshPlanes.isChecked())+separator
285     text+="ComputedOverlapDistance="+str(self.CB_ComputedOverlapDistance.isChecked())+separator
286     v=self.SP_toStr(self.SP_OverlapDistance)
287     text+="OverlapDistance="+v+separator
288     text+="OverlapAngle="+str(self.SP_OverlapAngle.value())+separator
289     text+="Verbosity="+str(self.SP_Verbosity.value())+separator
290     return str(text)
291
292   def loadResumeData(self, hypothesis, separator="\n"):
293     text=str(hypothesis)
294     self.clean()
295     for slig in reversed(text.split(separator)):
296       lig=slig.strip()
297       #print "load ResumeData",lig
298       if lig=="": continue #skip blanck lines
299       if lig[0]=="#": break
300       try:
301         tit,value=lig.split("=")
302         if tit=="CheckOrFix":
303           self.RB_Fix1.setChecked(False)
304           self.RB_Fix2.setChecked(False)
305           self.RB_Check.setChecked(False)
306           if value=="fix1pass": self.RB_Fix1.setChecked(True)
307           if value=="fix2pass": self.RB_Fix2.setChecked(True)
308           if value=="check": self.RB_Check.setChecked(True)
309         if tit=="PreserveTopology": self.CB_PreserveTopology.setChecked(value=="True")
310         if tit=="FillHoles": self.CB_FillHoles.setChecked(value=="True")
311         if tit=="MinHoleSize": self.SP_MinHoleSize.setProperty("text", value)
312         if tit=="ComputedToleranceDisplacement": self.CB_ComputedToleranceDisplacement.setChecked(value=="True")
313         if tit=="ToleranceDisplacement": self.SP_ToleranceDisplacement.setProperty("text", value)
314         if tit=="ComputedResolutionLength": self.CB_ComputedResolutionLength.setChecked(value=="True")
315         if tit=="ResolutionLength": self.SP_ResolutionLength.setProperty("text", value)
316         if tit=="FoldingAngle": self.SP_FoldingAngle.setProperty("value", float(value))
317         if tit=="RemeshPlanes": self.CB_RemeshPlanes.setChecked(value=="True")
318         if tit=="ComputedOverlapDistance": self.CB_ComputedOverlapDistance.setChecked(value=="True")
319         if tit=="OverlapDistance": self.SP_OverlapDistance.setProperty("text", value)
320         if tit=="OverlapAngle": self.SP_OverlapAngle.setProperty("value", float(value))
321         if tit=="Verbosity": self.SP_Verbosity.setProperty("value", int(float(value)))
322       except:
323         QMessageBox.warning(self, "load MGCleaner Hypothesis", "Problem on '"+lig+"'")
324
325   def PBLoadPressed(self):
326     """load last hypothesis saved in tail of file"""
327     try:
328         f=open(self.paramsFile,"r")
329     except :
330         QMessageBox.warning(self, "File", "Unable to open "+self.paramsFile)
331         return
332     try:
333         text=f.read()
334     except :
335         QMessageBox.warning(self, "File", "Unable to read "+self.paramsFile)
336         return
337     f.close()
338     self.loadResumeData(text, separator="\n")
339
340   def PBLoadHypPressed(self):
341     """load hypothesis saved in Object Browser"""
342     #QMessageBox.warning(self, "load Object Browser MGCleaner hypothesis", "TODO")
343     import salome
344     from salome.kernel import studyedit
345     from salome.smesh.smeshstudytools import SMeshStudyTools
346     from salome.gui import helper as guihelper
347     from omniORB import CORBA
348
349     mySObject, myEntry = guihelper.getSObjectSelected()
350     if CORBA.is_nil(mySObject) or mySObject==None:
351       QMessageBox.critical(self, "Hypothese", "select an Object Browser MGCleaner hypothesis")
352       return
353     
354     #for i in dir(mySObject): print "dir mySObject",i
355     #print "GetAllAttributes",mySObject.GetAllAttributes()
356     #print "GetComment",mySObject.GetComment()
357     #print "GetName",mySObject.GetName()
358     
359     #could be renamed...
360     #if mySObject.GetFather().GetName()!="MGCleaner Hypotheses":
361     #  QMessageBox.critical(self, "Hypothese", "not a child of MGCleaner Hypotheses")
362     #  return
363     
364     text=mySObject.GetComment()
365     
366     #a verification
367     if "CheckOrFix=" not in text:
368       QMessageBox.critical(self, "Load Hypothese", "Object Browser selection not a MGCleaner Hypothesis")
369       return
370     self.loadResumeData(text, separator=" ; ")
371     return
372     
373   def PBCancelPressed(self):
374     self.close()
375
376   def PBMeshFilePressed(self):
377     fd = QFileDialog(self, "select an existing Mesh file", self.LE_MeshFile.text(), "Mesh-Files (*.mesh);;All Files (*)")
378     if fd.exec_():
379       infile = fd.selectedFiles()[0]
380       self.LE_MeshFile.setText(infile)
381       self.fichierIn=infile.toLatin1()
382       self.MeshIn=""
383       self.LE_MeshSmesh.setText("")
384
385   def setParamsFileName(self):
386     fd = QFileDialog(self, "select a file", self.LE_ParamsFile.text(), "dat Files (*.dat);;All Files (*)")
387     if fd.exec_():
388       infile = fd.selectedFiles()[0]
389       self.LE_ParamsFile.setText(infile)
390       self.paramsFile=infile.toLatin1()
391
392   def meshFileNameChanged(self):
393     self.fichierIn=str(self.LE_MeshFile.text())
394     #print "meshFileNameChanged", self.fichierIn
395     if os.path.exists(self.fichierIn): 
396       self.__selectedMesh=None
397       self.MeshIn=""
398       self.LE_MeshSmesh.setText("")
399       return
400     QMessageBox.warning(self, "Mesh file", "File doesn't exist")
401
402   def meshSmeshNameChanged(self):
403     """only change by GUI mouse selection, otherwise clear"""
404     #self.MeshIn=str(self.LE_MeshSmesh.text())
405     #print "meshSmeshNameChanged", self.MeshIn
406     self.__selectedMesh = None
407     self.MeshIn=""
408     self.LE_MeshSmesh.setText("")
409     self.fichierIn=""
410     return
411
412   def paramsFileNameChanged(self):
413     self.paramsFile=self.LE_ParamsFile.text()
414
415   def PBMeshSmeshPressed(self):
416     import salome
417     import smesh
418     from salome.kernel import studyedit
419     from salome.smesh.smeshstudytools import SMeshStudyTools
420     from salome.gui import helper as guihelper
421     from omniORB import CORBA
422
423     mySObject, myEntry = guihelper.getSObjectSelected()
424     if CORBA.is_nil(mySObject) or mySObject==None:
425       QMessageBox.critical(self, "Mesh", "select an input mesh")
426       return
427     self.smeshStudyTool = SMeshStudyTools()
428     try:
429       self.__selectedMesh = self.smeshStudyTool.getMeshObjectFromSObject(mySObject)
430     except:
431       QMessageBox.critical(self, "Mesh", "select an input mesh")
432       return
433     if CORBA.is_nil(self.__selectedMesh):
434       QMessageBox.critical(self, "Mesh", "select an input mesh")
435       return
436     myName = mySObject.GetName()
437     #print "MeshSmeshNameChanged", myName
438     self.MeshIn=myName
439     self.LE_MeshSmesh.setText(myName)
440     self.LE_MeshFile.setText("")
441     self.fichierIn=""
442
443   def prepareFichier(self):
444     self.fichierIn="/tmp/ForMGCleaner_"+str(self.num)+".mesh"
445     #print "prepareFichier"
446     import SMESH
447     self.__selectedMesh.ExportGMF(self.__selectedMesh, self.fichierIn, True)
448
449   def PrepareLigneCommande(self):
450     """
451     #use doc examples of mg-cleaner:
452     ls -al /data/tmplgls/salome/prerequis/install/COMMON_64/MeshGems-1.0/bin
453     source /data/tmplgls/salome/prerequis/install/LICENSE/dlim8.var.sh
454     export PATH=/data/tmplgls/salome/prerequis/install/COMMON_64/MeshGems-1.0/bin/Linux_64:$PATH
455     cp -r /data/tmplgls/salome/prerequis/install/COMMON_64/MeshGems-1.0/examples .
456     cd examples
457     mg-cleaner.exe --help
458     mg-cleaner.exe --in case7.mesh --out case7-test.mesh --check
459     mg-cleaner.exe case7.mesh case7-fix.mesh --fix
460     mg-cleaner.exe --in Porsche.mesh --out Porsche-test.mesh --check
461     mg-cleaner.exe --in Porsche.mesh --out Porschefix.mesh --fix
462     mg-cleaner.exe --in Porsche.mesh --out PorscheNewfix.mesh --fix --resolution_length 0.03
463     """
464     
465     #self.commande="mg-cleaner.exe --in " + self.fichierIn + " --out " + self.fichierOut + " --fix2pass" 
466     #return True
467     #print "PrepareLigneCommande '"+self.fichierIn+"' '"+self.MeshIn+"'",self.__selectedMesh
468     if self.fichierIn=="" and self.MeshIn=="":
469       QMessageBox.critical(self, "Mesh", "select an input mesh")
470       return False
471     if self.__selectedMesh!=None: self.prepareFichier()
472     if not (os.path.isfile(self.fichierIn)):
473       QMessageBox.critical(self, "File", "unable to read GMF Mesh in "+str(self.fichierIn))
474       return False
475     
476     self.commande="mg-cleaner.exe"
477     verbosity=str(self.SP_Verbosity.value())
478     self.commande+=" --verbose " + verbosity
479     self.commande+=" --in " + self.fichierIn
480     #print "self.fichierIn",self.fichierIn,type(self.fichierIn)
481     deb=os.path.splitext(str(self.fichierIn))
482     self.fichierOut=deb[0] + "_fix.mesh"
483     self.commande+=" --out "+self.fichierOut
484     if self.RB_Fix1.isChecked():
485       self.commande+=" --fix1pass"
486     else:
487       if self.RB_Fix2.isChecked():
488         self.commande+=" --fix2pass"
489       else:
490         self.commande+=" --check"
491     if self.CB_PreserveTopology.isChecked():
492       self.commande+=" --topology respect"
493     else:
494       self.commande+=" --topology ignore"
495     if self.CB_FillHoles.isChecked(): #no fill holes default
496       self.commande+=" --min_hole_size " + self.SP_toStr(self.SP_MinHoleSize)
497     if not self.CB_ComputedToleranceDisplacement.isChecked(): #computed default
498       self.commande+=" --tolerance_displacement " + self.SP_toStr(self.SP_ToleranceDisplacement)
499     if not self.CB_ComputedResolutionLength.isChecked(): #computed default
500       self.commande+=" --resolution_length " + self.SP_toStr(self.SP_ResolutionLength)
501     self.commande+=" --folding_angle " + str(self.SP_FoldingAngle.value())
502     if self.CB_RemeshPlanes.isChecked(): #no remesh default
503       self.commande+=" --remesh_planes"
504     if not self.CB_ComputedOverlapDistance.isChecked(): #computed default
505       self.commande+=" --overlap_distance " + self.SP_toStr(self.SP_OverlapDistance)
506     self.commande+=" --overlap_angle " + str(self.SP_OverlapAngle.value())
507     return True
508     
509   def clean(self):
510     self.RB_Check.setChecked(False)
511     self.RB_Fix1.setChecked(False)
512     self.RB_Fix2.setChecked(True)
513     self.CB_PreserveTopology.setChecked(False)
514     self.CB_FillHoles.setChecked(False)
515     self.CB_RemeshPlanes.setChecked(False)
516     
517     self.SP_MinHoleSize.setProperty("text", 0)
518     self.SP_ToleranceDisplacement.setProperty("text", 0)
519     self.SP_ResolutionLength.setProperty("text", 0)
520     self.SP_FoldingAngle.setProperty("value", 15)
521     self.SP_OverlapDistance.setProperty("text", 0)
522     self.SP_OverlapAngle.setProperty("value", 15)
523     self.SP_Verbosity.setProperty("value", 3)
524     
525     self.CB_ComputedToleranceDisplacement.setChecked(True)
526     self.CB_ComputedResolutionLength.setChecked(True)
527     self.CB_ComputedOverlapDistance.setChecked(True)
528
529 __dialog=None
530 def getDialog():
531   """
532   This function returns a singleton instance of the plugin dialog.
533   c est obligatoire pour faire un show sans parent...
534   """
535   global __dialog
536   if __dialog is None:
537       __dialog = MGCleanerMonPlugDialog()
538   #else :
539   #   __dialog.clean()
540   return __dialog
541
542
543 #
544 # ==============================================================================
545 # For memory
546 # ==============================================================================
547 #
548 def TEST_standalone():
549   """
550   works only if a salome is launched yet with a study loaded
551   to launch standalone python do:
552   /export/home/wambeke/2013/V6_main_MGC_CO6.4_64/APPLI/runSession
553   python
554   or (do not works)
555   python /export/home/wambeke/2013/V6_main_MGC_CO6.4_64/INSTALL/SMESH/share/salome/plugins/smesh/MGCleanerMonPlugDialog.py
556   """
557   import salome
558   import smesh
559   import SMESH
560   from salome.kernel import studyedit
561   salome.salome_init()
562   maStudy=studyedit.getActiveStudy()
563   #etc...a mano...
564
565 #
566 # ==============================================================================
567 # Basic use cases and unit test functions
568 # ==============================================================================
569 #
570 def TEST_MGCleanerMonPlugDialog():
571   #print "TEST_MGCleanerMonPlugDialog"
572   import sys
573   from PyQt4.QtGui import QApplication
574   from PyQt4.QtCore import QObject, SIGNAL, SLOT
575   app = QApplication(sys.argv)
576   QObject.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
577
578   dlg=MGCleanerMonPlugDialog()
579   dlg.show()
580   sys.exit(app.exec_())
581
582 if __name__ == "__main__":
583   TEST_MGCleanerMonPlugDialog()
584   #TEST_standalone()
585   pass