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