Salome HOME
Merge tag 'V8_3_0a2' into ngr/python3_dev
[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 qtsalome import *
29
30 verbose = True
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 with 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 a 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.PB_Cancel.clicked.connect(self.PBCancelPressed)
110     self.PB_Default.clicked.connect(self.clean)
111     self.PB_Help.clicked.connect(self.PBHelpPressed)
112     self.PB_OK.clicked.connect(self.PBOKPressed)
113     
114     self.PB_Load.clicked.connect(self.PBLoadPressed)
115     self.PB_Save.clicked.connect(self.PBSavePressed)
116     self.PB_LoadHyp.clicked.connect(self.PBLoadHypPressed)
117     self.PB_SaveHyp.clicked.connect(self.PBSaveHypPressed)
118     
119     self.PB_MeshFile.clicked.connect(self.PBMeshFilePressed)
120     self.PB_MeshSmesh.clicked.connect(self.PBMeshSmeshPressed)
121     self.LE_MeshSmesh.returnPressed.connect(self.meshSmeshNameChanged)
122     self.PB_ParamsFileExplorer.clicked.connect(self.setParamsFileName)
123     self.LE_MeshFile.returnPressed.connect(self.meshFileNameChanged)
124     self.LE_ParamsFile.returnPressed.connect(self.paramsFileNameChanged)
125
126     #QtCore.QObject.connect(self.checkBox, QtCore.SIGNAL("stateChanged(int)"), self.change) 
127     self.CB_FillHoles.stateChanged[int].connect(self.SP_MinHoleSize.setEnabled)
128     self.CB_ComputedToleranceDisplacement.stateChanged[int].connect(self.SP_ToleranceDisplacement.setDisabled)
129     self.CB_ComputedResolutionLength.stateChanged[int].connect(self.SP_ResolutionLength.setDisabled)
130     self.CB_ComputedOverlapDistance.stateChanged[int].connect(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(False)
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_risky(self):
235     """
236     save hypothesis in Object Browser outside GEOM ou MESH
237     WARNING: at root of Object Browser is not politically correct
238     """
239     import salome
240     
241     if verbose: print("save hypothesis in Object Browser")
242     
243     name = "MGCleaner"
244     #how ??? icon = "mesh_tree_hypo.png"
245     namei = "MGCleaner Parameters_%i" % self.num
246     datai = self.getResumeData(separator=" ; ")
247     
248     myStudy = salome.myStudy
249     myBuilder = myStudy.NewBuilder()
250     #myStudy.IsStudyLocked()
251     myComponent = myStudy.FindComponent(name)
252     if myComponent == None:
253       print("myComponent not found, create")
254       myComponent = myBuilder.NewComponent(name)
255     AName = myBuilder.FindOrCreateAttribute(myComponent, "AttributeName")
256     AName.SetValue(name)
257     ACmt = myBuilder.FindOrCreateAttribute(myComponent, "AttributeComment")
258     ACmt.SetValue(name)
259     
260     myObject = myBuilder.NewObject(myComponent)
261     AName = myBuilder.FindOrCreateAttribute(myObject, "AttributeName")
262     AName.SetValue(namei)
263     ACmt = myBuilder.FindOrCreateAttribute(myObject, "AttributeComment")
264     ACmt.SetValue(datai)
265
266     if salome.sg.hasDesktop(): salome.sg.updateObjBrowser(False)
267     self.num += 1
268     if verbose: print(("save %s in Object Browser done: %s\n%s" % (name, myObject.GetID(), datai)))
269     return True
270
271   def PBSaveHypPressed(self):
272     """
273     save hypothesis in Object Browser
274     bug: affichage ne marche pas si inclusion dans dans GEOM ou MESH depuis salome 730
275     """
276     import salome
277     import SMESH
278     from salome.kernel import studyedit
279     from salome.smesh import smeshBuilder
280     #[PAL issue tracker:issue1871] Les nouveaux objets ne s'affichent pas dans SMESH
281     QMessageBox.warning(self, "Save", "waiting for fix: Object Browser will not display hypothesis")
282     
283     if verbose: print("save hypothesis in Object Browser")
284     smesh = smeshBuilder.New(salome.myStudy)
285
286     maStudy=studyedit.getActiveStudy()
287     smesh.SetCurrentStudy(maStudy)
288
289     self.editor = studyedit.getStudyEditor()
290     moduleEntry=self.editor.findOrCreateComponent("SMESH","SMESH")
291     HypReMeshEntry = self.editor.findOrCreateItem(
292         moduleEntry, name = "Plugins Hypotheses", icon="mesh_tree_hypo.png")
293     #, comment = "HypothesisForRemeshing" )
294
295     monStudyBuilder=maStudy.NewBuilder()
296     monStudyBuilder.NewCommand()
297     newStudyIter=monStudyBuilder.NewObject(HypReMeshEntry)
298     name = "MGCleaner Parameters_%i" % self.num
299     self.editor.setAttributeValue(newStudyIter, "AttributeName", name)
300     data = self.getResumeData(separator=" ; ")
301     self.editor.setAttributeValue(newStudyIter, "AttributeComment", data)
302
303     """ 
304     # example storing in notebook
305     import salome_notebook
306     notebook = salome_notebook.notebook
307     notebook.set("MGCleaner_%i" % self.num, data)
308     """
309
310     if salome.sg.hasDesktop(): salome.sg.updateObjBrowser(False)
311     self.num += 1
312     if verbose: print(("save %s in Object Browser done:\n%s" % (name, data)))
313     return True
314
315   def SP_toStr(self, widget):
316     """only for a QLineEdit widget"""
317     #cr, pos=widget.validator().validate(res, 0) #n.b. "1,3" is acceptable !locale!
318     try:
319       val=float(widget.text())
320     except:
321       QMessageBox.warning(self, widget.titleForWarning, "float value is incorrect: '"+widget.text()+"'")
322       res=str(widget.validator().bottom())
323       widget.setProperty("text", res)
324       return res
325     valtest=widget.validator().bottom()
326     if valtest!=None:
327       if val<valtest:
328         QMessageBox.warning(self, widget.titleForWarning, "float value is under minimum: "+str(val)+" < "+str(valtest))
329         res=str(valtest)
330         widget.setProperty("text", res)
331         return res
332     valtest=widget.validator().top()
333     if valtest!=None:
334       if val>valtest:
335         QMessageBox.warning(self, widget.titleForWarning, "float value is over maximum: "+str(val)+" > "+str(valtest))
336         res=str(valtest)
337         widget.setProperty("text", res)
338         return res    
339     return str(val)
340
341   def getResumeData(self, separator="\n"):
342     text=""
343     if self.RB_Fix1.isChecked():
344       CheckOrFix="fix1pass"
345     else:
346       if self.RB_Fix2.isChecked():
347         CheckOrFix="fix2pass"
348       else:
349         CheckOrFix="check"
350     text+="CheckOrFix="+CheckOrFix+separator
351     text+="PreserveTopology="+str(self.CB_PreserveTopology.isChecked())+separator
352     text+="FillHoles="+str(self.CB_FillHoles.isChecked())+separator
353     v=self.SP_toStr(self.SP_MinHoleSize)
354     text+="MinHoleSize="+v+separator
355     text+="ComputedToleranceDisplacement="+str(self.CB_ComputedToleranceDisplacement.isChecked())+separator
356     v=self.SP_toStr(self.SP_ToleranceDisplacement)
357     text+="ToleranceDisplacement="+v+separator
358     text+="ComputedResolutionLength="+str(self.CB_ComputedResolutionLength.isChecked())+separator
359     v=self.SP_toStr(self.SP_ResolutionLength)
360     text+="ResolutionLength="+v+separator
361     text+="FoldingAngle="+str(self.SP_FoldingAngle.value())+separator
362     text+="RemeshPlanes="+str(self.CB_RemeshPlanes.isChecked())+separator
363     text+="ComputedOverlapDistance="+str(self.CB_ComputedOverlapDistance.isChecked())+separator
364     v=self.SP_toStr(self.SP_OverlapDistance)
365     text+="OverlapDistance="+v+separator
366     text+="OverlapAngle="+str(self.SP_OverlapAngle.value())+separator
367     text+="Verbosity="+str(self.SP_Verbosity.value())+separator
368     return str(text)
369
370   def loadResumeData(self, hypothesis, separator="\n"):
371     text=str(hypothesis)
372     self.clean()
373     for slig in reversed(text.split(separator)):
374       lig=slig.strip()
375       #print "load ResumeData",lig
376       if lig=="": continue #skip blanck lines
377       if lig[0]=="#": break
378       try:
379         tit,value=lig.split("=")
380         if tit=="CheckOrFix":
381           self.RB_Fix1.setChecked(False)
382           self.RB_Fix2.setChecked(False)
383           self.RB_Check.setChecked(False)
384           if value=="fix1pass": self.RB_Fix1.setChecked(True)
385           if value=="fix2pass": self.RB_Fix2.setChecked(True)
386           if value=="check": self.RB_Check.setChecked(True)
387         if tit=="PreserveTopology": self.CB_PreserveTopology.setChecked(value=="True")
388         if tit=="FillHoles": self.CB_FillHoles.setChecked(value=="True")
389         if tit=="MinHoleSize": self.SP_MinHoleSize.setProperty("text", value)
390         if tit=="ComputedToleranceDisplacement": self.CB_ComputedToleranceDisplacement.setChecked(value=="True")
391         if tit=="ToleranceDisplacement": self.SP_ToleranceDisplacement.setProperty("text", value)
392         if tit=="ComputedResolutionLength": self.CB_ComputedResolutionLength.setChecked(value=="True")
393         if tit=="ResolutionLength": self.SP_ResolutionLength.setProperty("text", value)
394         if tit=="FoldingAngle": self.SP_FoldingAngle.setProperty("value", float(value))
395         if tit=="RemeshPlanes": self.CB_RemeshPlanes.setChecked(value=="True")
396         if tit=="ComputedOverlapDistance": self.CB_ComputedOverlapDistance.setChecked(value=="True")
397         if tit=="OverlapDistance": self.SP_OverlapDistance.setProperty("text", value)
398         if tit=="OverlapAngle": self.SP_OverlapAngle.setProperty("value", float(value))
399         if tit=="Verbosity": self.SP_Verbosity.setProperty("value", int(float(value)))
400       except:
401         QMessageBox.warning(self, "load MGCleaner Hypothesis", "Problem on '"+lig+"'")
402
403   def PBLoadPressed(self):
404     """load last hypothesis saved in tail of file"""
405     try:
406       f=open(self.paramsFile,"r")
407     except:
408       QMessageBox.warning(self, "File", "Unable to open "+self.paramsFile)
409       return
410     try:
411       text=f.read()
412     except:
413       QMessageBox.warning(self, "File", "Unable to read "+self.paramsFile)
414       return
415     f.close()
416     self.loadResumeData(text, separator="\n")
417
418   def PBLoadHypPressed(self):
419     """load hypothesis saved in Object Browser"""
420     #QMessageBox.warning(self, "load Object Browser MGCleaner hypothesis", "TODO")
421     import salome
422     from salome.kernel import studyedit
423     from salome.smesh.smeshstudytools import SMeshStudyTools
424     from salome.gui import helper as guihelper
425     from omniORB import CORBA
426
427     mySObject, myEntry = guihelper.getSObjectSelected()
428     if CORBA.is_nil(mySObject) or mySObject==None:
429       QMessageBox.critical(self, "Hypothese", "select an Object Browser MGCleaner hypothesis")
430       return
431     
432     #for i in dir(mySObject): print "dir mySObject",i
433     #print "GetAllAttributes",mySObject.GetAllAttributes()
434     #print "GetComment",mySObject.GetComment()
435     #print "GetName",mySObject.GetName()
436     
437     #could be renamed...
438     #if mySObject.GetFather().GetName()!="MGCleaner Hypotheses":
439     #  QMessageBox.critical(self, "Hypothese", "not a child of MGCleaner Hypotheses")
440     #  return
441     
442     text=mySObject.GetComment()
443     
444     #a verification
445     if "CheckOrFix=" not in text:
446       QMessageBox.critical(self, "Load Hypothese", "Object Browser selection not a MGCleaner Hypothesis")
447       return
448     self.loadResumeData(text, separator=" ; ")
449     return
450     
451   def PBCancelPressed(self):
452     self.close()
453
454   def PBMeshFilePressed(self):
455     fd = QFileDialog(self, "select an existing Mesh file", self.LE_MeshFile.text(), "Mesh-Files (*.mesh);;All Files (*)")
456     if fd.exec_():
457       infile = fd.selectedFiles()[0]
458       self.LE_MeshFile.setText(infile)
459       self.fichierIn=str(infile).encode("latin-1")
460       self.MeshIn=""
461       self.LE_MeshSmesh.setText("")
462
463   def setParamsFileName(self):
464     fd = QFileDialog(self, "select a file", self.LE_ParamsFile.text(), "dat Files (*.dat);;All Files (*)")
465     if fd.exec_():
466       infile = fd.selectedFiles()[0]
467       self.LE_ParamsFile.setText(infile)
468       self.paramsFile=str(infile).encode("latin-1")
469
470   def meshFileNameChanged(self):
471     self.fichierIn=str(self.LE_MeshFile.text())
472     #print "meshFileNameChanged", self.fichierIn
473     if os.path.exists(self.fichierIn): 
474       self.__selectedMesh=None
475       self.MeshIn=""
476       self.LE_MeshSmesh.setText("")
477       return
478     QMessageBox.warning(self, "Mesh file", "File doesn't exist")
479
480   def meshSmeshNameChanged(self):
481     """only change by GUI mouse selection, otherwise clear"""
482     #self.MeshIn=str(self.LE_MeshSmesh.text())
483     #print "meshSmeshNameChanged", self.MeshIn
484     self.__selectedMesh = None
485     self.MeshIn=""
486     self.LE_MeshSmesh.setText("")
487     self.fichierIn=""
488     return
489
490   def paramsFileNameChanged(self):
491     self.paramsFile=self.LE_ParamsFile.text()
492
493   def PBMeshSmeshPressed(self):
494     from omniORB import CORBA
495     import salome
496     from salome.kernel import studyedit
497     from salome.smesh.smeshstudytools import SMeshStudyTools
498     from salome.gui import helper as guihelper
499     from salome.smesh import smeshBuilder
500     smesh = smeshBuilder.New(salome.myStudy)
501
502     mySObject, myEntry = guihelper.getSObjectSelected()
503     if CORBA.is_nil(mySObject) or mySObject==None:
504       QMessageBox.critical(self, "Mesh", "select an input mesh")
505       #self.LE_MeshSmesh.setText("")
506       #self.MeshIn=""
507       #self.LE_MeshFile.setText("")
508       #self.fichierIn=""
509       return
510     self.smeshStudyTool = SMeshStudyTools()
511     try:
512       self.__selectedMesh = self.smeshStudyTool.getMeshObjectFromSObject(mySObject)
513     except:
514       QMessageBox.critical(self, "Mesh", "select an input mesh")
515       return
516     if CORBA.is_nil(self.__selectedMesh):
517       QMessageBox.critical(self, "Mesh", "select an input mesh")
518       return
519     myName = mySObject.GetName()
520     #print "MeshSmeshNameChanged", myName
521     self.MeshIn=myName
522     self.LE_MeshSmesh.setText(myName)
523     self.LE_MeshFile.setText("")
524     self.fichierIn=""
525
526   def prepareFichier(self):
527     self.fichierIn=tempfile.mktemp(suffix=".mesh",prefix="ForMGCleaner_")
528     if os.path.exists(self.fichierIn):
529         os.remove(self.fichierIn)
530     self.__selectedMesh.ExportGMF(self.__selectedMesh, self.fichierIn, True)
531
532   def PrepareLigneCommande(self):
533     """
534     #use doc examples of mg-cleaner:
535     ls -al /data/tmplgls/salome/prerequis/install/COMMON_64/MeshGems-1.0/bin
536     source /data/tmplgls/salome/prerequis/install/LICENSE/dlim8.var.sh
537     export PATH=/data/tmplgls/salome/prerequis/install/COMMON_64/MeshGems-1.0/bin/Linux_64:$PATH
538     cp -r /data/tmplgls/salome/prerequis/install/COMMON_64/MeshGems-1.0/examples .
539     cd examples
540     mg-cleaner.exe --help
541     mg-cleaner.exe --in case7.mesh --out case7-test.mesh --check
542     mg-cleaner.exe case7.mesh case7-fix.mesh --fix
543     mg-cleaner.exe --in Porsche.mesh --out Porsche-test.mesh --check
544     mg-cleaner.exe --in Porsche.mesh --out Porschefix.mesh --fix
545     mg-cleaner.exe --in Porsche.mesh --out PorscheNewfix.mesh --fix --resolution_length 0.03
546     """
547     
548     #self.commande="mg-cleaner.exe --in " + self.fichierIn + " --out " + self.fichierOut + " --fix2pass" 
549     #return True
550     #print "PrepareLigneCommande '"+self.fichierIn+"' '"+self.MeshIn+"'",self.__selectedMesh
551     if self.fichierIn=="" and self.MeshIn=="":
552       QMessageBox.critical(self, "Mesh", "select an input mesh")
553       return False
554     if self.__selectedMesh!=None: self.prepareFichier()
555     if not (os.path.isfile(self.fichierIn)):
556       QMessageBox.critical(self, "File", "unable to read GMF Mesh in "+str(self.fichierIn))
557       return False
558     
559     self.commande="mg-cleaner.exe"
560     verbosity=str(self.SP_Verbosity.value())
561     self.commande+=" --verbose " + verbosity
562     self.commande+=" --in " + self.fichierIn
563     #print "self.fichierIn",self.fichierIn,type(self.fichierIn)
564     deb=os.path.splitext(str(self.fichierIn))
565     self.fichierOut=deb[0] + "_fix.mesh"
566     self.commande+=" --out "+self.fichierOut
567     if self.RB_Fix1.isChecked():
568       self.commande+=" --fix1pass"
569     else:
570       if self.RB_Fix2.isChecked():
571         self.commande+=" --fix2pass"
572       else:
573         self.commande+=" --check"
574     if self.CB_PreserveTopology.isChecked():
575       self.commande+=" --topology respect"
576     else:
577       self.commande+=" --topology ignore"
578     if self.CB_FillHoles.isChecked(): #no fill holes default
579       self.commande+=" --min_hole_size " + self.SP_toStr(self.SP_MinHoleSize)
580     if not self.CB_ComputedToleranceDisplacement.isChecked(): #computed default
581       self.commande+=" --tolerance_displacement " + self.SP_toStr(self.SP_ToleranceDisplacement)
582     if not self.CB_ComputedResolutionLength.isChecked(): #computed default
583       self.commande+=" --resolution_length " + self.SP_toStr(self.SP_ResolutionLength)
584     self.commande+=" --folding_angle " + str(self.SP_FoldingAngle.value())
585     if self.CB_RemeshPlanes.isChecked(): #no remesh default
586       self.commande+=" --remesh_planes"
587     if not self.CB_ComputedOverlapDistance.isChecked(): #computed default
588       self.commande+=" --overlap_distance " + self.SP_toStr(self.SP_OverlapDistance)
589     self.commande+=" --overlap_angle " + str(self.SP_OverlapAngle.value())
590     if verbose: print(("INFO: MGCCleaner command:\n  %s" % self.commande))
591     return True
592
593   def clean(self):
594     self.RB_Check.setChecked(False)
595     self.RB_Fix1.setChecked(False)
596     self.RB_Fix2.setChecked(True)
597     self.CB_PreserveTopology.setChecked(False)
598     self.CB_FillHoles.setChecked(False)
599     self.CB_RemeshPlanes.setChecked(False)
600     
601     self.SP_MinHoleSize.setProperty("text", 0)
602     self.SP_ToleranceDisplacement.setProperty("text", 0)
603     self.SP_ResolutionLength.setProperty("text", 0)
604     self.SP_FoldingAngle.setProperty("value", 15)
605     self.SP_OverlapDistance.setProperty("text", 0)
606     self.SP_OverlapAngle.setProperty("value", 15)
607     self.SP_Verbosity.setProperty("value", 3)
608     
609     self.CB_ComputedToleranceDisplacement.setChecked(True)
610     self.CB_ComputedResolutionLength.setChecked(True)
611     self.CB_ComputedOverlapDistance.setChecked(True)
612
613 __dialog=None
614 def getDialog():
615   """
616   This function returns a singleton instance of the plugin dialog.
617   It is mandatory in order to call show without a parent ...
618   """
619   global __dialog
620   if __dialog is None:
621     __dialog = MGCleanerMonPlugDialog()
622   #else :
623   #   __dialog.clean()
624   return __dialog
625
626
627 #
628 # ==============================================================================
629 # For memory
630 # ==============================================================================
631 #
632 def TEST_standalone():
633   """
634   works only if a salome is launched yet with a study loaded
635   to launch standalone python do:
636   ./APPLI/runSession
637   python
638   or (do not works)
639   python ./INSTALL/SMESH/share/salome/plugins/smesh/MGCleanerMonPlugDialog.py
640   """
641   import salome
642   import SMESH
643   from salome.kernel import studyedit
644   salome.salome_init()
645   maStudy=studyedit.getActiveStudy()
646   #etc...a mano...
647
648 #
649 # ==============================================================================
650 # Basic use cases and unit test functions
651 # ==============================================================================
652 #
653 def TEST_MGCleanerMonPlugDialog():
654   import sys
655   from qtsalome import QApplication
656   app = QApplication(sys.argv)
657   app.lastWindowClosed.connect(app.quit)
658
659   dlg=MGCleanerMonPlugDialog()
660   dlg.show()
661   sys.exit(app.exec_())
662
663 if __name__ == "__main__":
664   TEST_MGCleanerMonPlugDialog()
665   #TEST_standalone()
666   pass
667