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