Salome HOME
10084641f6d38b386ce7cd77f7a201ff16ef3587
[tools/eficas.git] / InterfaceQT4 / editor.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2013   EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20 from __future__ import absolute_import
21 from __future__ import print_function
22 try :
23    from builtins import str
24    from builtins import range
25 except : pass
26
27 import types,sys,os, re
28 import  subprocess
29 import traceback
30
31 import six
32 from six.moves import range
33 from PyQt5.QtWidgets import QWidget, QMessageBox, QFileDialog, QApplication, QSplitter
34 from PyQt5.QtGui import QPalette
35 from PyQt5.QtCore import QProcess, QFileInfo, QTimer, Qt, QDir, QSize
36 import time
37 import pdb
38 from datetime import date
39 from Extensions.i18n import tr
40
41 import traceback
42
43 # Modules Eficas
44
45 import convert, generator
46 from Editeur        import session
47 from Editeur        import comploader
48 from Editeur        import Objecttreeitem
49 from desBaseWidget  import Ui_baseWidget
50 from InterfaceQT4.monViewTexte   import ViewText
51 from monWidgetCreeParam import MonWidgetCreeParam 
52 from . import browser
53 from . import readercata
54
55 DictExtensions= {"MAP" : ".map", "TELEMAC" : '.comm'}
56
57     
58
59
60 class JDCEditor(Ui_baseWidget,QWidget):
61 # ----------------------------------------- #
62     """
63        Editeur de jdc
64     """
65
66     def __init__ (self,appli,fichier = None, jdc = None, QWParent=None, units = None, include=0 , vm=None):
67     #----------------------------------------------------------------------------------------------------------#
68
69         QWidget.__init__(self,None)
70         self.i=0
71         self.setupUi(self)
72         self.inhibeSplitter=0
73         self.widgetOptionnel=None
74         self.fenetreCentraleAffichee=None
75         self.dejaDansPlieTout=False
76         self.afficheCommandesPliees = True
77         self.listeDesListesOuvertes=set()
78         self.appliEficas = appli
79         self.appli       = appli  #---- attendu par IHM
80         self.vm          = vm
81         self.fichier     = fichier
82         self.jdc         = jdc
83         self.first       = True
84         self.QWParent    = QWParent
85         self.couleur     = Qt.black
86         self.nodeEnCours=None
87          
88         if appli != None :
89            self.salome =  self.appliEficas.salome
90         else :
91            self.salome=0
92            print ("dans JDC pas d appli ????????")
93
94         # ces attributs sont mis a jour par definitCode appelee par newEditor
95         self.code   = self.appliEficas.CONFIGURATION.code
96         self.initSplitterSizes()
97
98         #self.afficheListesPliees=False
99         self.afficheListesPliees=True
100         if self.code == "ASTER" or self.code == "monCode" : self.afficheListesPliees =True
101         if self.code == 'PSEN_N1' : self.afficheListesPliees = False
102
103         self.mode_nouv_commande=self.appliEficas.CONFIGURATION.mode_nouv_commande
104         self.closeAutreCommande=self.appliEficas.CONFIGURATION.closeAutreCommande
105         self.closeFrameRechercheCommande=self.appliEficas.CONFIGURATION.closeFrameRechercheCommande
106         self.closeArbre=self.appliEficas.CONFIGURATION.closeArbre
107         self.affiche=self.appliEficas.CONFIGURATION.affiche
108         self.afficheOptionnelVide=self.appliEficas.CONFIGURATION.afficheOptionnelVide
109         self.nombreDeBoutonParLigne = self.appliEficas.CONFIGURATION.nombreDeBoutonParLigne
110         self.dicoImages = self.appliEficas.CONFIGURATION.dicoImages
111         self.simpleClic = self.appliEficas.CONFIGURATION.simpleClic
112         #self.taille = self.appliEficas.taille
113
114         #if self.code in ['MAP','CARMELCND','PSEN'] : self.afficheCommandesPliees=False
115         if self.code in ['MAP','CARMELCND'] : self.afficheCommandesPliees=False
116         if self.code in ['MAP',]:
117            self.widgetTree.close()
118            self.widgetTree=None
119         if self.closeArbre: self.fermeArbre()
120
121         self.version_code = session.d_env.cata
122
123
124         if not hasattr ( self.appliEficas, 'readercata') or  self.appliEficas.multi==True:
125            self.readercata  = readercata.READERCATA( self, self.appliEficas )
126            self.appliEficas.readercata=self.readercata
127            self.appliEficas.code=self.code
128         else :
129            self.readercata=self.appliEficas.readercata
130         if self.readercata.fic_cata == None : return    #Sortie Salome
131         self.titre=self.readercata.titre
132         self.Ordre_Des_Commandes=self.readercata.Ordre_Des_Commandes
133         self.Classement_Commandes_Ds_Arbre=self.readercata.Classement_Commandes_Ds_Arbre
134
135         self.format =  self.appliEficas.format_fichier
136
137         self.dict_reels={}
138         self.liste_simp_reel=[]
139         self.ihm="QT"
140         self.dicoNouveauxMC={}
141
142         nameConf='configuration_'+self.code
143         configuration=__import__(nameConf)
144         self.CONFIGURATION = self.appliEficas.CONFIGURATION
145         self.CONFIGStyle =   self.appliEficas.CONFIGStyle
146
147         try:
148           self.CONFIGURATION.generator_module
149           _module = __import__(self.CONFIGURATION.generator_module)
150           info = _module.entryPoint()
151           generator.plugins.addEntryPoint(info)
152         except:
153           pass
154
155         try:
156           self.CONFIGURATION.convert_module
157           #print self.CONFIGURATION.convert_module
158           _module = __import__(self.CONFIGURATION.convert_module)
159           info = _module.entryPoint()
160           convert.plugins.addEntryPoint(info)
161         except :
162           pass
163
164         self.sb = None
165         if hasattr(self.appliEficas,"statusBar"):
166            self.sb = self.appliEficas.statusBar()
167
168         self.fileInfo       = None
169         self.lastModified   = 0
170
171         self.modified   = False
172         self.isReadOnly = False
173         self.node_selected = []
174         self.deplier = True
175         self.message=''
176         if self.code in ['Adao','ADAO','MAP'] : self.afficheApresInsert=True
177         else :  self.afficheApresInsert=False
178         if self.code in ['TELEMAC',] : self.enteteQTree='premier'
179         else : self.enteteQTree='complet'
180         if self.code in ['Adao','ADAO','TELEMAC'] : self.affichePlie=True
181         else : self.affichePlie=False
182
183         self.Commandes_Ordre_Catalogue =self.readercata.Commandes_Ordre_Catalogue
184
185         #------- construction du jdc --------------
186
187         jdc_item = None
188
189         self.nouveau=0
190         if self.fichier is not None:        #  fichier jdc fourni
191             self.fileInfo = QFileInfo(self.fichier)
192             self.fileInfo.setCaching(0)
193             if jdc==None :
194                try :
195                    self.jdc = self.readFile(self.fichier)
196                except :
197                    print ("mauvaise lecture")
198             else :
199                self.jdc=jdc
200             if self.jdc is not None and units is not None:
201                self.jdc.recorded_units=units
202                self.jdc.old_recorded_units=units
203         else:
204             if not self.jdc:                   #  nouveau jdc
205                 if not include :
206                    self.jdc = self._newJDC(units=units)
207                 else :
208                    self.jdc = self._newJDCInclude(units=units)
209                 self.nouveau=1
210
211         if self.jdc:
212             self.jdc.appli = self # a resorber
213             self.jdc.editor = self 
214             self.jdc.lang    = self.appli.langue
215             self.jdc.aReafficher=False
216             txt_exception  = None
217             if not jdc:
218                 self.jdc.analyse()
219                 txt_exception = self.jdc.cr.get_mess_exception()
220             if txt_exception:
221                 self.jdc = None
222                 QApplication.restoreOverrideCursor()
223                 self.affiche_infos(tr("Erreur fatale au chargement de %s",str(fichier)),Qt.red)
224                 if (self.appliEficas.ssIhm == False) : QMessageBox.critical( self, tr("Erreur fatale au chargement d'un fichier"), txt_exception)
225             else:
226                 comploader.charger_composants("QT")
227                 jdc_item=Objecttreeitem.make_objecttreeitem( self, "nom", self.jdc )
228                 if (not self.jdc.isvalid()) and (not self.nouveau) and (self.appliEficas.ssIhm == False):
229                     self.viewJdcRapport()
230  
231
232
233         if jdc_item and self.appliEficas.ssIhm==False:
234             self.tree = browser.JDCTree( jdc_item,  self )
235         self.appliEficas.construitMenu()
236
237         
238         #############
239         self.adjustSize()
240
241
242     #-------------------#  Pour execution avec output et error dans le bash
243     def runPSEN(self):
244     #-------------------#
245     
246       #if self.modified or self.fichier==None  : self.saveFile()
247       self.saveFile()
248         
249       #lancement avec le .bat
250       path1 = os.path.abspath(os.path.join(os.path.abspath(__file__), '../','../','PSEN_Eficas','PSEN'))
251       WrapperFilePath = os.path.join(path1, 'PSSEWrapper.py') 
252       import subprocess
253       p = subprocess.Popen(['python',WrapperFilePath])
254       (out,err)=p.communicate()        
255       print (out)
256       print (err)
257
258     #-------------------#  Pour execution avec output et error dans le bash
259     def runPSEN_N1(self):
260     #-------------------#
261       
262
263       self.saveFile()
264       path1 = os.path.abspath(os.path.join(os.path.abspath(__file__), '../','../','ProcessOutputs_Eficas','TreatOutputs'))
265       sys.path.append(path1)
266
267       if not(self.jdc.isvalid()):
268          QMessageBox.information( self, tr( "Unvalid JDC"),tr("incorrect keywords will be ignored"))
269       if 'dicoImbrique' in generator.plugins:
270          self.generator=generator.plugins['dicoImbrique']()
271          jdc_formate=self.generator.gener(self.jdc)
272          dico=self.generator.Dico 
273          
274          ###to delete
275          #fileDico =  r'C:\Logiciels DER\PSEN_V16\Code\ProcessOutputs_Eficas\TreatOutputs\dicoN1.py'
276          fileDico =  os.path.join(path1, 'dicoN1.py') #r'C:\Logiciels DER\PSEN_V16\Code\ProcessOutputs_Eficas\TreatOutputs\dicoN1.py'
277          f = open( str(fileDico), 'w')
278          f.write("Dico =" + str(dico) )
279          f.close()
280          ###
281          
282       
283       #print ('in runPSEN_N1', dico)
284       from Run import run 
285       run(dico)
286       #res,txt_exception=run(dico)
287       #if res : QMessageBox.information( self, tr("fin de script run"), txt_exception)
288       #else  : QMessageBox.critical( self, tr("Erreur fatale script run"), txt_exception)
289        
290     #-------------------#  Pour execution avec output et error dans le bash
291     def process_N1(self):
292     #-------------------#
293
294       path1 = os.path.abspath(os.path.join(os.path.abspath(__file__), '../','../','ProcessOutputs_Eficas','TreatOutputs'))
295       sys.path.append(path1)
296
297
298       if 'dicoImbrique' in generator.plugins:
299          self.generator=generator.plugins['dicoImbrique']()
300          jdc_formate=self.generator.gener(self.jdc)
301          dico=self.get_Dico() #generator.Dico
302
303
304          for k in dico['CONTINGENCY_PROCESSING']:
305              #print (k)
306              if k[0:19] == 'Component_List_For_' or k[0:21] =='Contingency_List_For_' :
307                 newK=k.replace('___',' ')
308                 l="'"+str(newK)+"'"
309                 dico['CONTINGENCY_PROCESSING'][l]=dico['CONTINGENCY_PROCESSING'][k]
310                 del dico['CONTINGENCY_PROCESSING'][k]
311
312          ###to delete
313          fileDico =  os.path.join(path1, 'dicoN1_process.py')
314          f = open( str(fileDico), 'w')
315          f.write("Dico =" + str(dico) )
316          f.close()
317          ###
318          return dico
319
320         #return self.get_Dico()
321
322     #-------------------#  Pour execution avec output et error dans le bash
323     def process_VP(self):
324     #-------------------#
325       if 'dicoImbrique' in generator.plugins:
326          self.generator=generator.plugins['dicoImbrique']()
327          jdc_formate=self.generator.gener(self.jdc)
328          dico=self.get_Dico() #generator.Dico
329          return dico
330
331    
332     #--------------------------------#
333     def ajoutCommentaire(self):
334     #--------------------------------#
335         if self.tree.selectedItems()==[] :
336           QMessageBox.warning( self, tr("Pas de noeud selectionne"),tr("Selectionnez un Noeud \nLe commentaire sera place apres le noeud selectionne"))
337           return 
338         noeudAvantCommentaire=self.tree.selectedItems()[0]
339         if noeudAvantCommentaire ==self.tree.racine : 
340             self.tree.racine.append_child("COMMENTAIRE",pos=0)
341             return
342         noeudAvantCommentaire.addComment(True)
343         
344
345
346     #--------------------------------#
347     def _newJDC( self ,units = None):
348     #--------------------------------#
349         """
350         Initialise un nouveau JDC vierge
351         """
352         self.modified=1
353         CONTEXT.unset_current_step()
354
355         texte=""
356         if self.code == "CARMELCND" : texte=self._newJDCCND()
357         if self.code == "ZCRACKS" : texte=self._newZCRACKS()
358         if self.code == "TELEMAC" : texte=self._newTELEMAC()
359         if self.code == "PSEN"    : texte = self._newPSEN()
360         if self.code == "PSEN_N1" : texte = self._newPSEN_N1()
361
362         if hasattr(self.readercata.cata[0],'TEXTE_NEW_JDC') : texte=self.readercata.cata[0].TEXTE_NEW_JDC
363
364         #if self.code == "CF" : texte = self._new_CF()
365         #   texte=self.newTexteCND
366        
367         jdc=self.readercata.cata[0].JdC( procedure =texte,
368                                          appli=self,
369                                          cata=self.readercata.cata,
370                                          cata_ord_dico=self.readercata.cata_ordonne_dico,
371                                          rep_mat=self.CONFIGURATION.rep_mat
372                                         )
373         jdc.lang    = self.appli.langue
374         if units is not None:
375            jdc.recorded_units=units
376            jdc.old_recorded_units=units
377         ## PNPN est ce que la ligne suivante est bien utile ?
378         if texte == "" :jdc.analyse()
379         return jdc
380
381     #--------------------------------#
382     def _newJDCInclude( self ,units = None):
383     #--------------------------------#
384         """
385         Initialise un nouveau JDC vierge
386         """
387         import Extensions.jdc_include
388         JdC_aux=Extensions.jdc_include.JdC_include
389         CONTEXT.unset_current_step()
390
391         jaux=self.readercata.cata[0].JdC( procedure="",
392                                appli=self,
393                                cata=self.readercata.cata,
394                                cata_ord_dico=self.readercata.cata_ordonne_dico,
395                                rep_mat=self.CONFIGURATION.rep_mat,
396                               )
397         jaux.analyse()
398
399         J=JdC_aux( procedure="",
400                    appli=self,
401                    cata=self.readercata.cata,
402                    cata_ord_dico=self.readercata.cata_ordonne_dico,
403                    jdc_pere=jaux,
404                    rep_mat=self.CONFIGURATION.rep_mat,
405                    )
406         J.analyse()
407         if units is not None:
408            J.recorded_units=units
409            J.old_recorded_units=units
410         return J
411
412
413     #-------------------------------#
414     def readFile(self, fn):
415     #--------------------------------#
416         """
417         Public slot to read the text from a file.
418         @param fn filename to read from (string or QString)
419         """
420         fn = six.text_type(fn)
421
422         # ------------------------------------------------------------------------------------
423         #                         charge le JDC
424         # ------------------------------------------------------------------------------------
425
426         jdcName=os.path.basename(fn)
427         # Il faut convertir le contenu du fichier en fonction du format
428         if self.appliEficas.format_fichier_in in convert.plugins:
429              # Le convertisseur existe on l'utilise
430              #appli = self
431              p=convert.plugins[self.appliEficas.format_fichier_in]()
432              p.readfile(fn)
433              if p.text=="" : self.nouveau=1
434              pareil,texteNew=self.verifieCHECKSUM(p.text)
435              #if texteNew == ""
436              if pareil == False and (self.appliEficas.ssIhm == False) :
437                 QMessageBox.warning( self, tr("fichier modifie"),tr("Attention! fichier change hors EFICAS"))
438              p.text=texteNew
439              memeVersion,texteNew=self.verifieVersionCataDuJDC(p.text)
440              if memeVersion == 0 : texteNew=self.traduitCatalogue(texteNew)
441              p.text=texteNew
442              text=p.convert('exec',self.appliEficas)
443              if not p.cr.estvide():
444                 self.affiche_infos("Erreur a la conversion",Qt.red)
445         else :
446             self.affiche_infos("Type de fichier non reconnu",Qt.red)
447             if self.appliEficas.ssIhm == False:
448                     QMessageBox.critical( self, tr("Type de fichier non reconnu"),
449                     tr("EFICAS ne sait pas ouvrir le type de fichier %s" ,self.appliEficas.format_fichier_in))
450             return None
451
452         CONTEXT.unset_current_step()
453         jdc=self.readercata.cata[0].JdC(procedure=text,
454                                     appli=self,
455                                     cata=self.readercata.cata,
456                                     cata_ord_dico=self.readercata.cata_ordonne_dico,
457                                     nom=jdcName,
458                                     rep_mat=self.CONFIGURATION.rep_mat
459                                    )
460         # ----------------------------------------------------
461         #      charge le JDC fin
462         # ----------------------------------------------------
463         self.modified = False
464
465 #        qApp.restoreOverrideCursor()
466         if self.fileInfo!= None :
467            self.lastModified = self.fileInfo.lastModified()
468         else :
469            self.lastModified = 1
470         nouveauTitre=self.titre+"              "+str(os.path.basename(self.fichier))
471         self.appliEficas.setWindowTitle(nouveauTitre)
472         return jdc
473
474
475     #-----------------------#
476     def get_source(self,file):
477     #-----------------------#
478
479         # Il faut convertir le contenu du fichier en fonction du format
480         if self.format in convert.plugins :
481             # Le convertisseur existe on l'utilise
482             p=convert.plugins[self.format]()
483             p.readfile(file)
484             text=p.convert('execnoparseur')
485             if not p.cr.estvide():
486                 self.affiche_infos("Erreur a la conversion",Qt.red)
487             return text
488         else:
489             # Il n'existe pas c'est une erreur
490             self.affiche_infos("Type de fichier non reconnu",Qt.red)
491             QMessageBox.critical( self, tr("Type de fichier non reconnu"),tr("EFICAS ne sait pas ouvrir ce type de fichier"))
492             return None
493
494     #-----------------------------------------------------------------------#
495     def _viewText(self, txt, caption = "FILE_VIEWER",largeur=1200,hauteur=600):
496     #--------------------------------------------------------------------#
497         w = ViewText( self.QWParent,self ,caption,txt,largeur,hauteur)
498         w.show()
499     #
500
501     #----------------------------------------------#
502     def __generateTempFilename(self, prefix, suffix):
503     #----------------------------------------------#
504         import tempfile
505         (fd, filename) = tempfile.mkstemp(prefix=prefix, suffix=suffix)
506         os.close(fd)
507         return filename
508     #
509
510
511     #----------------------------------------------#
512     def _viewTextExecute(self, txt, prefix, suffix):
513     #----------------------------------------------#
514         self.w = ViewText( self.QWParent )
515         self.w.setWindowTitle( "execution" )
516         self.monExe=QProcess(self.w)
517         pid=self.monExe.pid()
518         nomFichier = self.__generateTempFilename(prefix, suffix = ".sh")
519         f=open(nomFichier,'w')
520         f.write(txt)
521         f.close()
522         self.monExe.readyReadStandardOutput.connect( self.readFromStdOut)
523         self.monExe.readyReadStandardError.connect( self.readFromStdErr)
524         exe='sh ' + nomFichier
525         self.monExe.start(exe)
526         self.monExe.closeWriteChannel()
527         self.w.exec_()
528         try:
529           commande="rm  "+ nomFichier
530           os.system(commande)
531         except :
532           pass
533
534     def readFromStdErr(self):
535         a=self.monExe.readAllStandardError()
536         self.w.view.append(str(a.data()))
537
538     def readFromStdOut(self) :
539         a=self.monExe.readAllStandardOutput()
540         self.w.view.append(str(a.data()))
541
542     def readFromStdErrQT4(self):
543         a=self.monExe.readAllStandardError()
544         self.w.view.append(QString.fromUtf8(a.data(),len(a))) ;
545
546     def readFromStdOutQT4(self) :
547         a=self.monExe.readAllStandardOutput()
548         self.w.view.append(QString.fromUtf8(a.data(),len(a))) ;
549         
550     #-----------------------#
551     def generDico(self):
552     #-----------------------#
553        if 'dico' in generator.plugins:
554          self.generator=generator.plugins['dico']()
555          jdc_formate=self.generator.gener(self.jdc)
556          dico=self.generator.Dico
557          return dico
558
559     #-----------------------#
560     def gestionParam(self):
561     #-----------------------#
562         w = MonWidgetCreeParam( self)
563         w.show()
564
565     #-----------------------#
566     def viewJdcSource(self):
567     #-----------------------#
568         if self.fichier == None : return
569         f=open(self.fichier,'r')
570         texteSource=f.read()
571         f.close()
572         self._viewText(texteSource, "JDC_SOURCE")
573
574     #-----------------------#
575     def viewJdcPy(self):
576     #-----------------------#
577         strSource = str( self.get_text_JDC(self.format) )
578         self._viewText(strSource, "JDC_RESULTAT")
579
580     #-----------------------#
581     def viewJdcRapport(self):
582     #-----------------------#
583         strRapport = six.text_type( self.jdc.report() )
584         # on ajoute les regles
585         
586         self._viewText(strRapport, "JDC_RAPPORT")
587
588     #-----------------------#
589     def viewJdcRegles(self):
590     #-----------------------#
591         if self.tree :self.tree.AppelleBuildLBRegles()
592
593
594     #----------------#
595     def closeIt(self):
596     #----------------#
597         """
598         Public method called by the viewmanager to finally get rid of us.
599         """
600         if self.jdc:
601             self.jdc.supprime()
602         self.close()
603
604     #----------------------------------------------#
605     def affiche_infos(self,message,couleur=Qt.black):
606     #----------------------------------------------#
607         if self.sb:
608            mapalette=self.sb.palette()
609            mapalette.setColor( QPalette.WindowText, couleur )
610            self.sb.setPalette( mapalette );
611            self.sb.showMessage(message,4000)
612            self.couleur=couleur
613
614     #------------------------------#
615     def affiche_alerte(self,titre,message):
616     #------------------------------#
617     # appele par I_MACRO_ETAPE
618         QMessageBox.information( self, titre, message)
619
620     #-----------------------------------#
621     def affiche_commentaire(self,message):
622     #-----------------------------------#
623         self.labelCommentaire.setText(message)
624         QTimer.singleShot(6000, self.rendInvisible)
625
626     #----------------------#
627     def rendInvisible(self):
628     #----------------------#
629         self.labelCommentaire.setText("")
630
631     #-------------------#
632     def init_modif(self):
633     #-------------------#
634       """
635           Met l'attribut modified a 'o' : utilise par Eficas pour savoir
636           si un JDC doit etre sauvegarde avant destruction ou non
637       """
638       self.modified = True
639
640     #---------------------------------------#
641     def chercheNoeudSelectionne(self,copie=1):
642     #---------------------------------------#
643       """
644         appele par Cut et Copy pour positionner self.node_selected
645       """
646       self.node_selected=[]
647       if len(self.tree.selectedItems()) == 0 : return
648       self.node_selected=self.tree.selectedItems()
649
650
651     #---------------------#
652     def handleSupprimer(self):
653     #---------------------#
654       self.chercheNoeudSelectionne()
655       if len(self.node_selected) == 0 : return
656       self.QWParent.noeud_a_editer = []
657       if self.node_selected[0]==self.tree.racine: return
658       if len(self.node_selected) == 1 : self.node_selected[0].delete()
659       else : self.node_selected[0].deleteMultiple(self.node_selected)
660
661     #---------------------#
662     def handleRechercher(self):
663     #---------------------#
664       from .monRecherche import DRecherche
665       monRechercheDialg=DRecherche(parent=self,fl=0)
666       monRechercheDialg.show()
667
668
669     #--------------------------------#
670     def handleRechercherDsCatalogue(self):
671     #-----------------------------#
672       from .monRechercheCatalogue import DRechercheCatalogue
673       monRechercheDialg=DRechercheCatalogue(self.QWParent,self)
674       monRechercheDialg.show()
675
676     #---------------------#
677     def handleDeplier(self):
678     #---------------------#
679        if self.tree == None : return
680        #self.tree.collapseAll()
681        if self.deplier :
682           #print "je plie"
683           self.tree.expandItem(self.tree.topLevelItem(0))
684           self.deplier = False
685           if self.fenetreCentraleAffichee != None  :
686              if hasattr(self.fenetreCentraleAffichee.node,'plieToutEtReaffiche'):
687                  self.fenetreCentraleAffichee.node.plieToutEtReaffiche()
688        else:
689           #print "je deplie"
690           self.tree.expandItem(self.tree.topLevelItem(0))
691           self.deplier = True
692           if self.fenetreCentraleAffichee != None  :
693              if hasattr(self.fenetreCentraleAffichee.node,'deplieToutEtReaffiche'):
694                  self.fenetreCentraleAffichee.node.deplieToutEtReaffiche()
695
696     #---------------------#
697     def handleEditCut(self):
698     #---------------------#
699       """
700       Stocke dans Eficas.noeud_a_editer le noeud a couper
701       """
702       #print "handleEditCut"
703       self.chercheNoeudSelectionne()
704       self.QWParent.edit="couper"
705       self.QWParent.noeud_a_editer = self.node_selected
706
707     #-----------------------#
708     def handleEditCopy(self):
709     #-----------------------#
710       """
711       Stocke dans Eficas.noeud_a_editer le noeud a copier
712       """
713       self.chercheNoeudSelectionne()
714       if len(self.node_selected) == 0 : return
715       if len(self.node_selected) == 1 : self.node_selected[0].update_node_label_in_blue()
716       else :  self.node_selected[0].update_plusieurs_node_label_in_blue(self.node_selected)
717       self.QWParent.edit="copier"
718       self.QWParent.noeud_a_editer = self.node_selected
719
720     #------------------------#
721     def handleEditPaste(self):
722     #------------------------#
723       """
724       Lance la copie de l'objet place dans self.QWParent.noeud_a_editer
725       Ne permet que la copie d'objets de type Commande ou MCF
726       """
727       self.chercheNoeudSelectionne()
728       if (not(hasattr(self.QWParent,'noeud_a_editer'))) or len(self.QWParent.noeud_a_editer)==0:
729           QMessageBox.information( self,
730                       tr("Copie impossible"),
731                       tr("Veuillez selectionner un objet a copier"))
732           return
733       if len(self.node_selected) != 1 :
734           QMessageBox.information( self,
735                       tr("Copie impossible"),
736                       tr("Veuillez selectionner un seul objet : la copie se fera apres le noeud selectionne"))
737           return
738       noeudOuColler=self.node_selected[0]
739
740       if len(self.QWParent.noeud_a_editer)!=1:
741          #self.handleEditPasteMultiple()
742          QMessageBox.information( self, tr("Copie impossible"), tr("Aucun Objet n a ete copie ou coupe"))
743          return
744
745       noeudACopier=self.QWParent.noeud_a_editer[0]
746
747       if (self.QWParent.edit != "couper"):
748         #print   (noeudOuColler.item.parent.get_child(noeudOuColler.item.nom)) 
749         try:
750            if noeudOuColler == self.tree.racine :
751                child=noeudOuColler.doPastePremier(noeudACopier)
752            else :
753                child=noeudACopier.doPaste(noeudOuColler,'after')
754
755            if child==None or child==0:
756                QMessageBox.critical( self,tr( "Copie refusee"),tr('Eficas n a pas reussi a copier l objet'))
757                self.message = ''
758                self.affiche_infos("Copie refusee",Qt.red)
759            if noeudACopier.treeParent.editor != noeudOuColler.treeParent.editor:
760                try :
761                  nom=noeudACopier.item.sd.nom
762                  child.item.nomme_sd(nom)
763                except :
764                  pass
765            return
766            self.init_modif()
767            child.select()
768         except  :
769            traceback.print_exc()
770            QMessageBox.critical( self,tr( "Copie refusee"),tr('Copie refusee pour ce type d objet'))
771            self.message = ''
772            self.affiche_infos("Copie refusee",Qt.red)
773            return
774
775       # il faut declarer le JDCDisplay_courant modifie
776       # suppression eventuelle du noeud selectionne
777       # si possible on renomme l objet comme le noeud couper
778
779       if (self.QWParent.edit == "couper"):
780          print ('je pass la')
781          if noeudACopier.treeParent.editor != noeudOuColler.treeParent.editor:
782            QMessageBox.critical( self, tr("Deplacement refuse"),tr('Deplacement refuse entre 2 fichiers. Seule la copie est autorisee '))
783
784          #if 1:
785          try :
786            # indexNoeudACopier=noeudACopier.treeParent.children.index(noeudACopier)
787             indexNoeudACopier=self.getTreeIndex(noeudACopier)
788             noeudACopier.treeParent.item.deplaceEntite(indexNoeudACopier,indexNoeudOuColler,pos)
789             noeudACopier.treeParent.build_children()
790
791          #else:
792          except:
793             pass
794          self.QWParent.noeud_a_editer=[]
795
796       # on rend la copie a nouveau possible en liberant le flag edit
797       self.QWParent.edit="copier"
798       noeudACopier.select()
799
800     #----------------------------------#
801     def handleDeplaceMultiple(self):
802     #----------------------------------#
803        pass
804
805     #----------------------------------#
806     def handleEditPasteMultiple(self):
807     #----------------------------------#
808
809     # On ne garde que les niveaux "Etape"
810     # On insere dans l'ordre du JDC
811      listeNoeudsACouper=[]
812      listeIndex=[]
813      listeChild=[]
814      listeItem=[]
815      from InterfaceQT4 import compojdc
816      noeudOuColler=self.node_selected[0]
817      if not (isinstance(noeudOuColler.treeParent, compojdc.Node)):
818         QMessageBox.information( self,
819                   tr("Copie impossible a cet endroit",),
820                   tr("Veuillez selectionner une commande, un parametre, un commentaire ou une macro"))
821         return
822      indexNoeudOuColler=noeudOuColler.treeParent.children.index(noeudOuColler)
823
824      for noeud in self.QWParent.noeud_a_editer :
825         if not (isinstance(noeud.treeParent, compojdc.Node)): continue
826         indexInTree=noeud.treeParent.children.index(noeud)
827         indice = 0
828         for index in listeIndex:
829             if index < indexInTree : indice = indice +1
830         listeIndex.insert(indice, indexInTree)
831         listeNoeudsACouper.insert(indice, noeud)
832
833      noeudJdc=noeudOuColler.treeParent
834      dejaCrees=0
835      # on les cree a l'envers parcequ'on ajoute a NoeudOuColler
836      listeIndex.reverse()
837      for index in listeIndex:
838          indexTravail=index
839          if indexNoeudOuColler < index:
840             indexTravail=indexTravail+dejaCrees
841          noeudOuColler=noeudJdc.children[indexNoeudOuColler]
842          noeud=noeudJdc.children[indexTravail]
843          child=noeud.doPaste(noeudOuColler)
844          listeChild.append(child)
845          dejaCrees=dejaCrees+1
846
847      self.QWParent.noeud_a_editer = []
848      for i in range(len(listeIndex)):
849         noeud=noeudJdc.children[indexNoeudOuColler+1+i]
850         self.QWParent.noeud_a_editer.append(noeud)
851
852      listeASupprimer=[]
853      if self.QWParent.edit !="couper" : return
854
855      for index in listeIndex:
856          indexTravail=index
857          if indexNoeudOuColler < index:
858             indexTravail=indexTravail+(len(listeIndex))
859          noeud=noeudJdc.children[indexTravail]
860
861          listeItem.append(noeud.item)
862          listeASupprimer.append(noeud)
863
864      for i in range(len(listeChild)):
865          self.tree.item.suppitem(listeItem[i])
866          listeChild[i].item.update(listeItem[i])
867
868      self.QWParent.noeud_a_editer = []
869
870
871     #---------------------#
872     def getFileName(self):
873     #---------------------#
874       return self.fichier
875
876     #---------------------------#
877     def get_file_variable(self) :
878     #---------------------------#
879      titre = tr("Choix d'un fichier XML")
880      texte = tr("Le fichier contient une commande MODEL\n")
881      texte = texte+tr('Donnez le nom du fichier XML qui contient la description des variables')
882      QMessageBox.information( self, titre,tr(texte))
883
884      fichier = QFileDialog.getOpenFileName(self.appliEficas,
885                    tr('Ouvrir Fichier'),
886                    self.appliEficas.CONFIGURATION.savedir,
887                    tr('Wrapper Files (*.xml);;''All Files (*)'))
888      return  fichier
889
890     #--------------------------------------------------#
891     def writeFile(self, fn, txt = None,formatLigne="beautifie"):
892     #--------------------------------------------------#
893         """
894         Public slot to write the text to a file.
895
896         @param fn filename to write to string
897         @return flag indicating success
898         """
899
900         fn = six.text_type(fn)
901        
902         if txt == None :
903             txt = self.get_text_JDC(self.format,formatLigne=formatLigne)
904             eol = '\n'
905             if len(txt) >= len(eol):
906                if txt[-len(eol):] != eol:
907                   txt += eol
908             else:
909                 txt += eol
910             txt=self.ajoutVersionCataDsJDC(txt)
911             checksum=self.get_checksum(txt)
912             txt=txt+checksum
913         if self.code=="TELEMAC" : return 1
914         try:
915             f = open(fn, 'w')
916             f.write(txt)
917             f.close()
918             return 1
919         except IOError as why:
920             if (self.appliEficas.ssIhm == False):
921                 QMessageBox.critical(self, tr('Sauvegarde du Fichier'),
922                 tr('Le fichier')+str(fn) + tr('n a pas pu etre sauvegarde : ') + str(why))
923             else :
924                 print (why)
925             return 0
926
927     #-----------------------------------------------------------#
928     def get_text_JDC(self,format,pourRun=0,formatLigne="beautifie"):
929     #-----------------------------------------------------------#
930       if self.code == "MAP" and not(format in generator.plugins): format = "MAP"
931       if format in generator.plugins:
932          
933          # Le generateur existe on l'utilise
934          self.generator=generator.plugins[format]()
935          try :
936             jdc_formate=self.generator.gener(self.jdc,format=formatLigne,config=self.appliEficas.CONFIGURATION,appli=self.appliEficas)
937             if pourRun : jdc_formate=self.generator.textePourRun
938             if self.code == 'TELEMAC' : jdc_formate=self.generator.texteDico
939          except ValueError as e:
940             QMessageBox.critical(self, tr("Erreur a la generation"),str(e))
941             return
942
943          if not self.generator.cr.estvide():
944             self.affiche_infos(tr("Erreur a la generation"),Qt.red)
945             QMessageBox.critical( self, tr("Erreur a la generation"),tr("EFICAS ne sait pas convertir ce JDC"))
946             return ""
947          else:
948             return jdc_formate
949       else:
950          # Il n'existe pas c'est une erreur
951          self.affiche_infos(tr("Format %s non reconnu" , self.format),Qt.red)
952          QMessageBox.critical( self, "Format  non reconnu" ,tr("EFICAS ne sait pas convertir le JDC selon le format "+ self.format))
953          return ""
954
955     #----------------------#
956     def get_Dico(self):
957     #---------------------#
958       if 'dicoImbrique' in generator.plugins:
959          self.generator=generator.plugins['dicoImbrique']()
960          jdc_formate=self.generator.gener(self.jdc)
961          dico=self.generator.Dico 
962          return dico
963       else : 
964          self.affiche_infos(tr("Format %s non reconnu" , self.format),Qt.red)
965          QMessageBox.critical( self, "Format  non reconnu" ,tr("EFICAS ne sait pas convertir le JDC selon le format "+ self.format))
966          return ""
967
968
969     #------------#
970     def run(self):
971     #------------#
972       fonction="run"+self.code
973       #print fonction
974       if fonction in JDCEditor.__dict__: JDCEditor.__dict__[fonction],(self,)
975
976     #------------#
977     def saveRun(self):
978     #------------#
979       fonction="saveRun"+self.code
980       if fonction in JDCEditor.__dict__: JDCEditor.__dict__[fonction],(self,)
981
982     #---------------#
983     def runMAP(self):
984     #---------------#
985
986       if not(self.jdc.isvalid()):
987          QMessageBox.critical( self, tr( "Execution impossible "),tr("le JDC doit etre valide pour une execution MAP"))
988          return
989       if len(self.jdc.etapes) != 1 :
990          QMessageBox.critical( self, tr("Execution impossible "),tr("le JDC doit contenir un et un seul composant"))
991          return
992       if self.modified or self.fichier==None  :
993          self.fichierMapInput = self.__generateTempFilename(prefix = "map_run", suffix = ".map")
994          texte=self.get_text_JDC("MAP")
995          self.writeFile( self.fichierMapInput, txt = texte)
996       else :
997          self.fichierMapInput=self.fichier
998       composant=self.jdc.etapes[0].nom.lower()[0:-5]
999
1000
1001       # :TRICKY: to determine if a component requires SALOME, loads the component from Eficas catalog
1002       # then instantiate corresponding class and call getUseSalome() method
1003       try:
1004           from mapengine.spec import factory
1005           mapComponent = factory.new(composant)[0]
1006
1007           command = "map"
1008           if mapComponent.getUseSalome():
1009               command += " -r sappli"
1010           textePython=(command + " run -n "+composant +" -i "+self.fichierMapInput)
1011
1012           #textePython="ls -l"
1013           self._viewTextExecute( textePython,"map_run",".sh")
1014           #try:
1015           #  commande="rm  "+self.fichierMapInput
1016           #   os.system(commande)
1017           #except :
1018           #   pass
1019       except Exception as e:
1020           print((traceback.print_exc()))
1021
1022     #-------------------#
1023     def runZCRACKS(self):
1024     #-------------------#
1025       if not(self.jdc.isvalid()):
1026          QMessageBox.critical( self, tr( "Execution impossible "),tr("le JDC doit etre valide pour une execution "))
1027          return
1028       if self.modified or self.fichier==None  :
1029       #if 1:
1030          self.fichierZcracksInput = self.__generateTempFilename(prefix = "zcracks_run", suffix = ".z7p")
1031          texte=self.get_text_JDC("ZCRACKS",pourRun=1)
1032          self.writeFile( self.fichierZcracksInput, txt = texte)
1033       else :
1034          self.fichierZcracksInput=self.fichier
1035       try :
1036           #commande ="Zrun -zp "
1037           commande="more "
1038           textePython=(commande + self.fichierZcracksInput)
1039           self._viewTextExecute( textePython,"run_zcracks",".sh")
1040       except Exception as e:
1041           print((traceback.print_exc()))
1042
1043     #-------------------#
1044     def runCARMELCND(self):
1045     #-------------------#
1046       #if not(self.jdc.isvalid()):
1047       #   QMessageBox.critical( self, tr( "Execution impossible "),tr("le JDC doit etre valide pour une execution "))
1048       #   return
1049       if self.modified or self.fichier==None  :
1050          QMessageBox.critical( self, tr( "Execution impossible "),tr("Sauvegarder SVP avant l'execution "))
1051          return
1052       if not hasattr(self,'generator'): texte=self.get_text_JDC(self.format)
1053       from PrepareRunCarmel import prepareRunCarmel
1054       fichierGenerique=os.path.basename(self.fichier).split(".")[0]
1055       repMed=os.path.dirname(self.fichier)
1056       repExeCarmel=self.generator.get_repExeCarmel()
1057       textePython=prepareRunCarmel(repExeCarmel,repMed,fichierGenerique)
1058       nomFichier = self.__generateTempFilename("carmel_run", suffix = ".sh")
1059       f=open(nomFichier,'w')
1060       f.write(textePython)
1061       f.close()
1062       commande="xterm -e sh "+nomFichier +"\n"
1063       os.system(commande)
1064
1065     #-------------------#
1066     def runCarmelCS(self):
1067     #-------------------#
1068       try :
1069           commande="runSession pilotyacsCS.py"
1070           os.system(commande)
1071       except Exception as e:
1072           print((traceback.print_exc()))
1073
1074     #-----------------------------------------------------#
1075     def determineNomFichier(self,path,extension):
1076     #-----------------------------------------------------#
1077       if self.appli.code in DictExtensions:
1078          chaine1="JDC (*"+DictExtensions[self.appli.code]+");;"
1079          extensions= tr(chaine1+ "All Files (*)")
1080       else :
1081          extensions= tr("JDC (*.comm);;" "All Files (*)")
1082
1083       if self.appli.code == "MAP" :
1084          extensions = extensions + ";; Run (*.input);;"
1085
1086       fn = QFileDialog.getSaveFileName( self,
1087              tr("sauvegarde"), path,
1088              extensions,None,
1089              QFileDialog.DontConfirmOverwrite)
1090       if fn == None : return (0, None)
1091       fn=fn[0]
1092       if fn=='': return (0, None)
1093
1094       ext = QFileInfo(fn).suffix()
1095       if ext == '': fn+=extension
1096
1097       if QFileInfo(fn).exists():
1098            msgBox = QMessageBox(self)
1099            msgBox.setWindowTitle(tr("Sauvegarde du Fichier"))
1100            msgBox.setText(tr("Le fichier <b>%s</b> existe deja.", six.text_type(fn)))
1101            msgBox.addButton(tr("&Ecraser"),0)
1102            msgBox.addButton(tr("&Abandonner"),1)
1103            abort=msgBox.exec_()
1104            if abort == 1 :  return (0, "")
1105       return (1,fn)
1106
1107     #-----------------#
1108     def saveRunMAP(self):
1109     #-----------------#
1110         extension=".input"
1111         if not(self.jdc.isvalid()):
1112            QMessageBox.critical( self, tr( "Sauvegarde de l'input impossible "),
1113                                 tr("Un JdC valide est necessaire pour creer un .input")
1114                                  )
1115            return
1116         try :
1117           composant=self.jdc.etapes[0].nom.lower()[0:-5]
1118         except :
1119            QMessageBox.critical( self, tr( "Sauvegarde de l'input impossible "),
1120                                 tr("Choix du composant obligatoire")
1121                                  )
1122            return
1123         if hasattr(self.CONFIGURATION, "savedir"): path=self.CONFIGURATION.savedir
1124         else : path='C:/'
1125
1126         monNomFichier=""
1127         if self.fichier is not None and self.fichier != "" :
1128              maBase=str(QFileInfo(self.fichier).baseName())+".input"
1129              monPath=str(QFileInfo(self.fichier).absolutePath())
1130              monNomFichier=os.path.join(monPath,maBase)
1131         elif hasattr(self,'monNomFichierInput'):
1132             monNomFichier=self.monNomFichierInput
1133
1134
1135         monDialog=QFileDialog(self.appliEficas)
1136         monDialog.setDirectory (path)
1137         monDialog.setWindowTitle ("Save")
1138
1139         for c in monDialog.children():
1140             if isinstance(c,QDialogButtonBox):
1141                for b in c.children():
1142                   if isinstance(b,QPushButton):
1143                      avant=b.text()
1144                      if avant=="&Open": b.setText("Save")
1145         mesFiltres= "input Map (*.input);;All Files (*)"
1146         monDialog.setNameFilters(mesFiltres)
1147         if monNomFichier!="" : monDialog.selectFile(monNomFichier)
1148         BOk=monDialog.exec_()
1149         if BOk==0: return
1150         fn=str(monDialog.selectedFiles()[0])
1151         if fn == "" or fn == None : return
1152         if not fn.endswith(".input"):
1153             fn += ".input"
1154         self.monNomFichierInput=fn
1155
1156         if not hasattr(self, 'fichierMapInput') or not self.fichierMapInput or not os.path.exists(self.fichierMapInput):
1157             self.fichierMapInput = self.__generateTempFilename(prefix = "map_run", suffix = ".map")
1158             texte=self.get_text_JDC("MAP")
1159             self.writeFile( self.fichierMapInput, txt = texte)
1160
1161         cmd = ("map gen -t dat -n " + composant + " -i " + self.fichierMapInput + " -o " + fn)
1162         p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
1163         (output, err) = p.communicate()
1164
1165
1166     #-----------------#
1167     def saveRunPSEN(self):
1168     #-----------------#
1169         #print ("saveRunPSEN")
1170         self.saveFile()
1171
1172
1173     #-----------------------------------------#
1174     def cherche_Groupes(self):
1175     #-----------------------------------------#
1176         listeMA,listeNO=self.get_text_JDC("GroupMA")
1177         return listeMA,listeNO
1178
1179     #-----------------------------------------#
1180     def cherche_Dico(self):
1181     #-----------------------------------------#
1182         dicoCourant={}
1183         format =  self.appliEficas.format_fichier
1184         if format in generator.plugins:
1185            # Le generateur existe on l'utilise
1186            self.generator=generator.plugins[format]()
1187            jdc_formate=self.generator.gener(self.jdc,format='beautifie',config=self.appliEficas.CONFIGURATION)
1188            dicoCourant=self.generator.dico
1189         return dicoCourant
1190
1191          
1192
1193     #-----------------------------------------#
1194     def handleAjoutGroup(self,listeGroup):
1195     #-----------------------------------------#
1196         try :
1197         #if 1:
1198            from ajoutGroupe import handleAjoutGroupFiltre
1199            #print listeGroup
1200            handleAjoutGroupFiltre(self,listeGroup)
1201            #print "apres handleAjoutGroupFiltre"
1202         except :
1203         #else :
1204            pass
1205
1206     #-----------------------------------------------------------------#
1207     def saveFileLeger(self, path = None, saveas= 0,formatLigne="beautifie"):
1208     #-----------------------------------------------------------------#
1209         extension='.casR'
1210         fn = self.fichier
1211         #saveas=True # Pour forcer le nom
1212         self.generator=generator.plugins[self.format]()
1213         if self.fichier is None or saveas:
1214           if path is None: path=self.CONFIGURATION.savedir
1215           bOK, fn=self.determineNomFichier(path,extension)
1216           if bOK == 0 : return (0, None)
1217           if fn == None : return (0, None)
1218           if fn== '' : return (0, None)
1219
1220           ulfile = os.path.abspath(six.text_type(fn))
1221           self.appliEficas.CONFIGURATION.savedir=os.path.split(ulfile)[0]
1222           fn = six.text_type(QDir.toNativeSeparators(fn))
1223
1224         self.fichier = os.path.splitext(fn)[0]+extension
1225
1226         if hasattr(self.generator, "writeLeger"):
1227             self.generator.writeLeger(self.fichier,self.jdc,config=self.appliEficas.CONFIGURATION,appli=self.appliEficas)
1228
1229         if self.salome : self.appliEficas.addJdcInSalome( self.fichier)
1230
1231         self.modified = 0
1232         nouveauTitre=self.titre+"              "+str(os.path.basename(self.fichier))
1233         self.appliEficas.setWindowTitle(nouveauTitre)
1234         return (1, self.fichier)
1235
1236     #-----------------------------------------------------------------#
1237     def saveFile(self, path = None, saveas= 0,formatLigne="beautifie"):
1238     #-----------------------------------------------------------------#
1239         """
1240         Public slot to save the text to a file.
1241
1242         @param path directory to save the file in (string or QString)
1243         @return tuple of two values (boolean, string) giving a success indicator and
1244             the name of the saved file
1245         """
1246
1247         self.modified=1
1248         if not self.modified and not saveas:
1249             return (0, None)      # do nothing if text wasn't changed
1250
1251         if self.appli.code in DictExtensions :
1252            extension=DictExtensions[self.appli.code]
1253         else :
1254            extension='.comm'
1255
1256         newName = None
1257         fn = self.fichier
1258         if self.fichier is None or saveas:
1259           if path is None: path=self.CONFIGURATION.savedir
1260           bOK, fn=self.determineNomFichier(path,extension)
1261           if bOK == 0 : return (0, None)
1262           if fn == None : return (0, None)
1263           if fn== '' : return (0, None)
1264
1265           ulfile = os.path.abspath(six.text_type(fn))
1266           self.appliEficas.CONFIGURATION.savedir=os.path.split(ulfile)[0]
1267           fn = six.text_type(QDir.toNativeSeparators(fn))
1268           newName = fn
1269
1270
1271         if not (self.writeFile(fn,formatLigne=formatLigne)): return (0, None)
1272         self.fichier = fn
1273         self.modified  = False
1274         if self.fileInfo is None or saveas:
1275            self.fileInfo = QFileInfo(self.fichier)
1276            self.fileInfo.setCaching(0)
1277         self.lastModified = self.fileInfo.lastModified()
1278         if newName is not None:
1279            self.appliEficas.addToRecentList(newName)
1280            self.tree.racine.item.getObject().nom=os.path.basename(newName)
1281            self.tree.racine.update_node_label()
1282
1283         if self.jdc.isvalid() != 0 and hasattr(self.generator, "writeDefault"):
1284             self.generator.writeDefault(fn)
1285         elif self.code=="TELEMAC" and hasattr(self.generator, "writeDefault"):
1286             self.generator.writeDefault(fn)
1287
1288         if self.salome :
1289                self.appliEficas.addJdcInSalome( self.fichier)
1290         self.modified = 0
1291         nouveauTitre=self.titre+"              "+str(os.path.basename(self.fichier))
1292         self.appliEficas.setWindowTitle(nouveauTitre)
1293
1294         return (1, self.fichier)
1295 #
1296
1297     #----------------------------------------------#
1298     def sauveLigneFile(self):
1299     #----------------------------------------------#
1300         self.modified=1
1301         return self.saveFile(formatLigne="Ligne")
1302
1303
1304     #----------------------------------------------#
1305     def saveFileAs(self, path = None,fileName=None):
1306     #----------------------------------------------#
1307         """
1308         Public slot to save a file with a new name.
1309
1310         @param path directory to save the file in (string or QString)
1311         @return tuple of two values (boolean, string) giving a success indicator and
1312             the name of the saved file
1313         """
1314         if fileName != None :
1315            self.fichier = fileName
1316            return self.saveFile()
1317         return self.saveFile(path,1,"beautifie")
1318
1319
1320
1321     #---------------------------------------------#
1322     def get_file(self,unite=None,fic_origine = ''):
1323     #---------------------------------------------#
1324     # appele par I_JDC
1325         ulfile  = None
1326         jdcText = ""
1327
1328         titre  = ""
1329
1330         if unite :
1331             titre = tr("Choix unite %d ", unite)
1332             texte = tr("Le fichier %s contient une commande INCLUDE \n",  str(fic_origine)) +"\n"
1333             texte = texte+ tr("Donnez le nom du fichier correspondant a l unite logique ") + repr(unite)
1334             labeltexte = tr('Fichier pour unite ') + repr( unite)
1335         else:
1336             titre = tr("Choix d'un fichier de poursuite")
1337             texte = tr("Le fichier %s contient une commande POURSUITE\n", fic_origine)
1338             texte = texte+tr('Donnez le nom du fichier dont vous \n voulez faire une poursuite')
1339
1340         QMessageBox.information( self, titre,texte)
1341         fn = QFileDialog.getOpenFileName(self.appliEficas,
1342                    titre,
1343                    self.appliEficas.CONFIGURATION.savedir)
1344
1345         # ce retour est impose par le get_file d'I_JDC
1346         if fn== '' : return None," "
1347         if not fn : return (0, " ")
1348         fn=fn[0]
1349
1350         ulfile = os.path.abspath(six.text_type(fn))
1351         self.appliEficas.CONFIGURATION.savedir=os.path.split(ulfile)[0]
1352
1353         # On utilise le convertisseur defini par format_fichier
1354         source=self.get_source(ulfile)
1355         if source:
1356             # On a reussia convertir le fichier self.ulfile
1357             jdcText = source
1358         else:
1359             # Une erreur a ete rencontree
1360             jdcText = ''
1361         return ulfile, jdcText
1362
1363     #-------------------------------#
1364     def updateJdc(self, itemApres,texte):
1365     #--------------------------------#
1366         monItem=itemApres
1367         etape=monItem.item.object
1368
1369         CONTEXT.set_current_step(etape)
1370         etape.build_includeInclude(texte)
1371         self.tree.racine.build_children()
1372
1373     #-------------------------------------#
1374     def deleteEtape(self,etape):
1375     #-------------------------------------#
1376         self.jdc.suppentite(etape)
1377
1378     #-------------------------------------#
1379     def deleteMC(self,etape,MCFils,listeAvant=()):
1380     #-------------------------------------#
1381         ouChercher=etape
1382         for mot in listeAvant :
1383               ouChercher=ouChercher.get_child(mot,restreint="oui")
1384         monMC=ouChercher.get_child(MCFils,restreint="oui")
1385         if monMC != None :  ouChercher.suppentite(monMC)
1386         ouChercher.state='changed'
1387         ouChercher.isvalid()
1388
1389     #-------------------------------------#
1390     def ajoutMC(self,etape,MCFils,valeurs,listeAvant=()):
1391     #-------------------------------------#
1392         ouChercher=etape
1393         for mot in listeAvant :
1394               ouChercher=ouChercher.get_child(mot,restreint="oui")
1395         monMC=etape.get_child(ouChercher,restreint="oui")
1396         if monMC== None : monMC= ouChercher.addentite(MCFils)
1397         monMC.valeur=valeurs
1398         monMC.val=valeurs
1399         monMC.state='changed'
1400         monMC.isvalid()
1401
1402     #-------------------------------------#
1403     def getValeur(self,nomEtape,MCFils,listeAvant=()):
1404     #-------------------------------------#
1405
1406         ouChercher=None
1407         for e in self.jdc.etapes:
1408             if e.nom == nomEtape : ouChercher=e; break
1409         if ouChercher==None : return None
1410         for mot in listeAvant :
1411               ouChercher=ouChercher.get_child(mot,restreint="oui")
1412               if ouChercher==None : return None
1413         print ('apres', ouChercher)
1414         monMC=ouChercher.get_child(MCFils,restreint="oui")
1415         if monMC== None : return None
1416         return monMC.valeur
1417
1418     #-----------------------------------------------------------#
1419     def changeIntoMC(self,etape,MCFils,valeurs, listeAvant=()):
1420     #-----------------------------------------------------------#
1421         ouChercher=etape
1422         if isinstance (etape, str):
1423            ouChercher=None
1424            for e in self.jdc.etapes:
1425               if e.nom == etape : ouChercher=e; break
1426         if ouChercher==None : return
1427  
1428         for mot in listeAvant :
1429               ouChercher=ouChercher.get_child(mot,restreint="oui")
1430               if ouChercher==None : return 
1431         monMC=ouChercher.get_child(MCFils,restreint="oui")
1432         if monMC== None : monMC= ouChercher.addentite(MCFils)
1433
1434         monMC.definition.into=valeurs
1435         from Noyau.N_VALIDATOR import  IntoProtocol
1436         monMC.definition.intoProto = IntoProtocol("into", into=monMC.definition.into, val_min=monMC.definition.val_min, val_max=monMC.definition.val_max)
1437         monMC.state='changed'
1438         monMC.isvalid()
1439
1440     #----------------------------------------------------#
1441     def reCalculeValiditeMCApresChgtInto(self,nomEtape,MCFils,listeAvant=()):
1442     #----------------------------------------------------#
1443         for e in self.jdc.etapes:
1444             if e.nom == nomEtape : ouChercher=e; break
1445         
1446         for mot in listeAvant :
1447             try :
1448               ouChercher=ouChercher.get_child(mot,restreint="oui")
1449             # Le mot clef n est pas la
1450             except : return 0
1451         try :
1452            monMC=ouChercher.get_child(MCFils,restreint="oui")
1453         # Le mot clef n est pas la
1454         except : return 0
1455
1456         #print ('________',monMC)
1457         if hasattr(monMC.definition,'into') :
1458            if type(monMC.definition.into) ==types.FunctionType : maListeDeValeur=monMC.definition.into()
1459            else : maListeDeValeur=monMC.definition.into
1460         else :
1461            return 0
1462         
1463         monMC.state='changed'
1464         return 1
1465
1466     #-------------------------------------#
1467     def changeDefautDefMC(self,nomEtape,listeMC,valeurs):
1468     #-------------------------------------#
1469
1470         #if isinstance (etape, str):
1471         #  for e in self.jdc.etapes:
1472         #    if e.nom == etape : etape=e; break
1473         #if etape == None : return
1474         definitionEtape=getattr(self.jdc.cata[0],etape)
1475         ouChercher=definitionEtape
1476         if len(listeMC) > 1 :
1477
1478            for mc in listeMC[0:-1]:
1479              mcfact=ouChercher.entites[mc]
1480              ouChercher=mcfact
1481            
1482         print (ouChercher)
1483         mcAccas=ouChercher.entites[listeMC[-1]]
1484         mcAccas.defaut=valeurs
1485         print (mcAccas.defaut)
1486         return 1
1487
1488     #------------------------------------------------#
1489     def changeIntoDefMC(self,nomEtape,listeMC,valeurs):
1490     #------------------------------------------------#
1491         definitionEtape=getattr(self.jdc.cata[0],nomEtape)
1492         ouChercher=definitionEtape
1493
1494         if len(listeMC) > 1 :
1495            for mc in listeMC[0:-1]:
1496              mcfact=ouChercher.entites[mc]
1497              ouChercher=mcfact
1498         mcAccas=ouChercher.entites[listeMC[-1]]
1499
1500         if hasattr(mcAccas,'into') : oldValeurs=mcAccas.into
1501         else : oldValeurs=None
1502         if oldValeurs==valeurs : return 0
1503
1504         mcAccas.into=valeurs
1505         from Noyau.N_VALIDATOR import  IntoProtocol
1506         mcAccas.intoProto = IntoProtocol("into", into=valeurs, val_min=mcAccas.val_min, val_max=mcAccas.val_max)
1507         return 1
1508
1509     #-------------------------------------------------------------#
1510     def deleteDefinitionMC(self,etape,listeAvant,nomDuMC):
1511     #-------------------------------------------------------------#
1512         #print 'in deleteDefinitionMC', etape,listeAvant,nomDuMC
1513         if isinstance (etape, str):
1514           for e in self.jdc.etapes:
1515             if e.nom == etape : etape=e; break
1516         if etape == None : return
1517         definitionEtape=getattr(self.jdc.cata[0],etape)
1518         ouChercher=definitionEtape
1519         for k in listeAvant : 
1520             ouChercher=ouChercher.entites[k]
1521         MCADetruire=ouChercher.entites[nomDuMC]
1522         ouChercher.ordre_mc.remove(nomDuMC)
1523         del ouChercher.entites[nomDuMC]
1524         del self.dicoNouveauxMC[nomDuMC]
1525
1526
1527     #-------------------------------------------------------------#
1528     def ajoutDefinitionMC(self,etape,listeAvant,nomDuMC,typ,**args):
1529     #-------------------------------------------------------------#
1530         if isinstance (etape, str):
1531           for e in self.jdc.etapes:
1532             if e.nom == etape : etape=e; break
1533         if etape == None : return
1534         definitionEtape=getattr(self.jdc.cata[0],etape)
1535         ouChercher=definitionEtape
1536         for k in listeAvant : 
1537             ouChercher=ouChercher.entites[k]
1538         from Accas import A_SIMP
1539         Nouveau=A_SIMP.SIMP(typ,**args)
1540         Nouveau.pere=ouChercher
1541         Nouveau.nom=nomDuMC
1542         Nouveau.ordre_mc=[]
1543         ouChercher.entites[nomDuMC]=Nouveau
1544         ouChercher.ordre_mc.append(nomDuMC)
1545         self.dicoNouveauxMC[nomDuMC]=('ajoutDefinitionMC',etape,listeAvant,nomDuMC,typ,args)
1546         #print self.dicoNouveauxMC
1547
1548     #----------------------------------------------------#
1549     def changeIntoMCandSet(self,etape,listeMC,into,valeurs):
1550     #----------------------------------------------------#
1551
1552         self.changeIntoDefMC(etape,listeMC,into)
1553
1554         if isinstance (etape, str):
1555           for e in self.jdc.etapes:
1556             if e.nom == etape : etape=e; break
1557         if etape == None : return
1558
1559         ouChercher = etape
1560         for mot in listeMC[:-1] :
1561             ouChercher=ouChercher.get_child(mot,restreint="oui")
1562             if ouChercher==None : return 
1563         MCFils=listeMC[-1]
1564         print (MCFils)
1565         monMC=ouChercher.get_child(MCFils,restreint="oui")
1566         if monMC== None : monMC= etape.addentite(MCFils)
1567         print (monMC)
1568
1569         monMC.definition.into=into
1570         monMC.valeur=valeurs
1571         monMC.val=valeurs
1572         monMC.state='changed'
1573         monMC.isvalid() 
1574
1575     #-------------------------------------#
1576     def ajoutVersionCataDsJDC(self,txt):
1577     #-------------------------------------#
1578         if not hasattr(self.readercata.cata[0],'VERSION_CATALOGUE'): return txt
1579         ligneVersion="#VERSION_CATALOGUE:"+self.readercata.cata[0].VERSION_CATALOGUE+":FIN VERSION_CATALOGUE\n"
1580         texte=txt+ligneVersion
1581         return texte
1582
1583     #-------------------------------------#
1584     def verifieVersionCataDuJDC(self,text):
1585     #-------------------------------------#
1586         memeVersion=False
1587         indexDeb=text.find("#VERSION_CATALOGUE:")
1588         indexFin=text.find(":FIN VERSION_CATALOGUE")
1589         if indexDeb < 0 :
1590            self.versionCataDuJDC="sans"
1591            textJDC=text
1592         else :
1593            self.versionCataDuJDC=text[indexDeb+19:indexFin]
1594            textJDC=text[0:indexDeb]+text[indexFin+23:-1]
1595
1596         self.versionCata="sans"
1597         if hasattr(self.readercata.cata[0],'VERSION_CATALOGUE'): self.versionCata=self.readercata.cata[0].VERSION_CATALOGUE
1598
1599         if self.versionCata==self.versionCataDuJDC : memeVersion=True
1600         return memeVersion,textJDC
1601
1602     #-------------------------------#
1603     def traduitCatalogue(self,texte):
1604     #-------------------------------#
1605         nomTraducteur="traduit"+self.readercata.code+self.versionCataDuJDC+"To"+self.versionCata
1606         sys.path.append(os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),"../Traducteur")))
1607         try :
1608             traducteur=__import__(nomTraducteur)
1609             monTraducteur=traducteur.MonTraducteur(texte)
1610             nouveauTexte=monTraducteur.traduit()
1611             return nouveauTexte
1612         except :
1613             return texte
1614
1615
1616     #------------------------------#
1617     def verifieCHECKSUM(self,text):
1618     #------------------------------#
1619         indexDeb=text.find("#CHECKSUM:")
1620         if indexDeb < 0 :
1621            return 1, text
1622         indexFin=text.find(":FIN CHECKSUM")
1623         checkAvant=text[indexDeb:indexFin+13]
1624         textJDC=text[0:indexDeb]+text[indexFin+13:-1]
1625         checksum=self.get_checksum(textJDC)
1626         pareil=(checkAvant==checksum)
1627         return pareil, textJDC
1628
1629     #---------------------------#
1630     def get_checksum(self,texte):
1631     #---------------------------#
1632         newtexte=texte.replace('"','\\"')
1633         commande='echo "'+newtexte+'"|md5sum'
1634         a=os.popen(commande)
1635         checksum=a.read()
1636         a.close()
1637         ligne="#CHECKSUM:"+checksum[0:-1]+":FIN CHECKSUM"
1638         return ligne
1639
1640
1641     #---------------------------#
1642     def _new_CF(self):
1643     #---------------------------#
1644         texte="CONDUITE_FORCEE();"
1645         return texte
1646
1647
1648     #---------------------------#
1649     def _newTELEMAC(self):
1650     #---------------------------#
1651         #texte="INITIALIZATION();BOUNDARY_CONDITIONS();GENERAL_PARAMETERS();PHYSICAL_PARAMETERS();NUMERICAL_PARAMETERS();"
1652         texte="COMPUTATION_ENVIRONMENT();HYDRO();GENERAL_PARAMETERS();NUMERICAL_PARAMETERS()"
1653         #texte="TRACERS();"
1654         return texte
1655
1656     #---------------------------#
1657     def _newPSEN(self):
1658     #---------------------------#
1659         texte="DIRECTORY() ; PSSE_PARAMETERS() ; SIMULATION() ; sansnom=DISTRIBUTION() ; sansnom=DISTRIBUTION() ; CORRELATION() ;"
1660         #texte=""
1661         return texte
1662
1663     #---------------------------#
1664     def _newPSEN_N1(self):
1665     #---------------------------#
1666         texte="CASE_SELECTION();N_PROCESSING_OPTIONS();CONTINGENCY_OPTIONS();CONTINGENCY_SELECTION();\nCONTINGENCY_PROCESSING(); "
1667         texte="CONTINGENCY_SELECTION();\nCONTINGENCY_PROCESSING(); "
1668         return texte
1669
1670     #---------------------------#
1671
1672     #---------------------------#
1673     def _newZCRACKS(self):
1674     #---------------------------#
1675         texte="MAILLAGES();REMESHING();"
1676         return texte
1677
1678     #---------------------------#
1679     def _newJDCCND(self):
1680     #---------------------------#
1681       extensions=tr('Fichiers Med (*.med);;''Tous les Fichiers (*)')
1682       
1683       #if self.salome == 0 :
1684       QMessageBox.information( self,
1685                       tr("Fichier Med"),
1686                       tr("Veuillez selectionner un fichier Med"))
1687       QSfichier = QFileDialog.getOpenFileName(self.appliEficas,
1688                         caption='Fichier Med',
1689                         filter=extensions)
1690       QSfichier=QSfichier[0]
1691       self.fichierMED=QSfichier
1692       from acquiertGroupes import getGroupes
1693       erreur,self.listeGroupes,self.nomMaillage,self.dicoCoord=getGroupes(self.fichierMED)
1694       if erreur != "" : print ("a traiter")
1695       texteComm="COMMENTAIRE(u'Cree - fichier : "+self.fichierMED +" - Nom Maillage : "+self.nomMaillage+"');\nPARAMETRES()\n"
1696       texteSources=""
1697       texteCond=""
1698       texteNoCond=""
1699       texteVcut=""
1700       texteZs=""
1701       for groupe in self.listeGroupes :
1702           if groupe[0:8]=='CURRENT_': 
1703              texteSources +=groupe[8:]+"=SOURCE("
1704              texteSources +="VecteurDirecteur=(1.0,2.0,3.0,),);\n"
1705           if groupe[0:5]=='COND_':    texteCond    +=groupe[5:]+"=CONDUCTEUR();\n"
1706           if groupe[0:7]=='NOCOND_':  texteNoCond  +=groupe[7:]+"=NOCOND();\n"
1707           if groupe[0:5]=='VCUT_':    texteVcut    +='V_'+groupe[5:]+"=VCUT();\n"
1708           if groupe[0:3]=='ZS_':      texteZs      +=groupe[3:]+"=ZS();\n"
1709       texte=texteComm+texteSources+texteCond+texteNoCond+texteVcut+texteZs
1710       self.newTexteCND=texte
1711       self.modified=1
1712       return texte
1713
1714
1715     #---------------------------#
1716     def  BoutonFileSelected(self):
1717     #---------------------------#
1718
1719       QSfichier=self.openfile.selectedFiles()[0]
1720       self.fichierMED=str(QSfichier)
1721       from acquiertGroupes import getGroupes
1722       erreur,self.listeGroupes,self.nomMaillage=getGroupes(self.fichierMED)
1723       if erreur != "" : print ("a traiter")
1724
1725     #-----------------------------
1726     def BoutonSalomePressed(self):
1727     #----------------------------
1728       Msg,self.listeGroupes=self.appliEficas.ChercheGrpMailleInSalome()
1729       self.fichierMED="A_partir_de_SMESH"
1730       self.nomMaillage="A_partir_de_SMESH"
1731       self.openfile.close()
1732
1733
1734     #-----------------------------------------
1735     def initSplitterSizes(self, nbWidget=3):
1736     #-----------------------------------------
1737        #print ("je passe ds initSplitterSizes", nbWidget)
1738
1739        if   self.code in [ 'Adao', 'ADAO', ] : self.splitterSizes3=[1,1550,150]
1740        elif self.code in [ 'MAP']            : self.splitterSizes3=[700,300]
1741        else                                  : self.splitterSizes3=[150,1000,300]
1742
1743        if   self.code in [ 'Adao', 'ADAO', ] : self.splitterSizes2=[5,1500]
1744        else                                  : self.splitterSizes2=[300,1000]
1745
1746
1747
1748     #-----------------------------------------
1749     def restoreSplitterSizes(self,nbWidget=3):
1750     #----------------------------------------
1751       
1752       #traceback.print_stack()
1753       #print ("je passe ds restoreSplitterSizes")
1754       if not(hasattr(self,'splitter')) : return
1755       if nbWidget==2  : newSizes=self.splitterSizes2
1756       if nbWidget==3  : newSizes=self.splitterSizes3
1757       #self.inhibeSplitter = 1
1758       self.splitter.setSizes(newSizes)
1759       #self.inhibeSplitter = 0
1760       QApplication.processEvents()
1761       # seule la fentetre du milieu est necessaire
1762       self.splitter.widget(1).resizeEvent=self.saveSplitterSizes
1763    
1764     #-----------------------------------------
1765     def saveSplitterSizes(self,event):
1766     #-----------------------------------------
1767       #print ("je passe ds saveSplitterSizes")
1768       if self.inhibeSplitter : return
1769       if self.widgetOptionnel == None  : self.splitterSizes2 = self.splitter.sizes()[0:2]
1770       else                             : self.splitterSizes3 = self.splitter.sizes()[0:3]
1771
1772     #------------------------
1773     def fermeOptionnel(self):
1774     #------------------------
1775       if self.widgetOptionnel == None : return
1776
1777       self.inhibeSplitter=1
1778       self.widgetOptionnel.setParent(None)
1779       self.widgetOptionnel.close()
1780       self.widgetOptionnel.deleteLater()
1781       self.widgetOptionnel=None
1782       self.inhibeSplitter=0
1783       self.restoreSplitterSizes(2)
1784
1785     #------------------------
1786     def ajoutOptionnel(self):
1787     #------------------------
1788       #if len(self.splitterSizes) == 2 : self.splitterSizes.append(self.oldSizeWidgetOptionnel)
1789       #else : self.splitterSizes[2] = self.oldSizeWidgetOptionnel # ceinture pour les close bizarres
1790       #self.splitterSizes[1] = self.splitterSizes[1] - self.splitterSizes[2]
1791       
1792       self.restoreSplitterSizes(3)
1793
1794
1795     #------------------------
1796     def fermeArbre(self):
1797     #------------------------
1798        #print (self.widgetTree)
1799        self.oldWidgetTree=self.widgetTree
1800        self.widgetTree.hide()
1801        #self.widgetTree=None
1802
1803     #------------------------
1804     def ouvreArbre(self):
1805     #------------------------
1806        #print ('je passe la')
1807        #print (self.widgetTree)
1808        #self.widgetTree=self.oldWidgetTree
1809        self.widgetTree.show()
1810        #self.restoreSplitterSizes(3)
1811
1812     #-----------------------------
1813     def getTreeIndex(self,noeud):
1814     #----------------------------
1815       indexNoeud=-1
1816       if noeud in noeud.treeParent.children :
1817           indexNoeud=noeud.treeParent.children.index(noeud)
1818       else :
1819           if hasattr(noeud,'vraiParent') :
1820               noeudVrai = noeud
1821               noeudVraiParent = noeud.vraiParent
1822               while noeudVraiParent != noeud.treeParent and hasattr(noeudVraiParent,'vraiParent') :
1823                   noeudVrai = noeudVraiParent
1824                   noeudVraiParent = noeudVraiParent.vraiParent
1825                   pass
1826               if noeudVraiParent == noeud.treeParent :
1827                   indexNoeud=noeud.treeParent.children.index(noeudVrai)
1828                   pass
1829               pass
1830           pass
1831       return indexNoeud
1832
1833 if __name__ == "__main__":
1834     self.code='ASTER'
1835     name='prefs_'+prefs.code
1836     prefsCode=__import__(name)
1837
1838
1839     if hasattr(prefsCode,'encoding'):
1840        # Hack pour changer le codage par defaut des strings
1841        import sys
1842        reload(sys)
1843        sys.setdefaultencoding(prefs.encoding)
1844        del sys.setdefaultencoding
1845        # Fin hack
1846
1847 #    code=options.code
1848 #
1849     app = QApplication(sys.argv)
1850     mw = JDCEditor(None,'azAster.comm')
1851     app.setMainWidget(mw)
1852     app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
1853     mw.show()
1854
1855     res = app.exec_loop()
1856     sys.exit(res)