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