1 # -*- coding: utf-8 -*-
2 # ======================================================================
3 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
4 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
5 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
6 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
7 # (AT YOUR OPTION) ANY LATER VERSION.
9 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
10 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
11 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
12 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
15 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
16 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
19 # ======================================================================
21 import types,sys,os, re
24 from PyQt4.QtGui import *
25 from PyQt4.QtCore import *
27 from datetime import date
32 import convert, generator
33 from Editeur import session
34 from Editeur import comploader
35 from Editeur import Objecttreeitem
40 DictExtensions= {"MAP" : ".map"}
44 class JDCEditor(QSplitter):
45 # -------------------------- #
50 def __init__ (self,appli,fichier = None, jdc = None, QWParent=None, units = None, include=0 , vm=None):
51 #----------------------------------------------------------------------------------------------------------#
53 QSplitter.__init__(self, QWParent)
54 self.appliEficas = appli
55 self.appli = appli #---- attendu par IHM
57 self.fichier = fichier
59 self.QWParent = QWParent
62 self.salome = self.appliEficas.salome
65 print "dans JDC pas d appli ????????"
67 # ces attributs sont mis a jour par definitCode appelee par newEditor
68 self.code = self.appliEficas.CONFIGURATION.code
69 self.version_code = session.d_env.cata
71 if not hasattr ( self.appliEficas, 'readercata') or self.appliEficas.multi==True:
72 self.readercata = readercata.READERCATA( self, self.appliEficas )
73 self.appliEficas.readercata=self.readercata
75 self.readercata=self.appliEficas.readercata
76 if self.readercata.fic_cata == None : return #Sortie Salome
78 self.format = self.appliEficas.format_fichier
79 self.titre=self.appliEficas.VERSION_EFICAS + ' pour '+ self.code
82 self.liste_simp_reel=[]
85 nameConf='configuration_'+self.code
86 configuration=__import__(nameConf)
87 self.CONFIGURATION = self.appliEficas.CONFIGURATION
88 self.CONFIGStyle = self.appliEficas.CONFIGStyle
91 self.CONFIGURATION.generator_module
92 _module = __import__(self.CONFIGURATION.generator_module)
93 info = _module.entryPoint()
94 generator.plugins.addEntryPoint(info)
99 self.CONFIGURATION.convert_module
100 _module = __import__(self.CONFIGURATION.convert_module)
101 info = _module.entryPoint()
102 convert.plugins.addEntryPoint(info)
107 if hasattr(self.appliEficas,"statusBar"):
108 self.sb = self.appliEficas.statusBar()
111 self.lastModified = 0
113 self.modified = False
114 self.isReadOnly = False
116 self.node_selected = None
119 self.Commandes_Ordre_Catalogue =self.readercata.Commandes_Ordre_Catalogue
121 #------- construction du jdc --------------
124 self.mode_nouv_commande=self.readercata.mode_nouv_commande
127 if self.fichier is not None: # fichier jdc fourni
128 self.fileInfo = QFileInfo(self.fichier)
129 self.fileInfo.setCaching(0)
131 self.jdc = self.readFile(self.fichier)
134 if self.jdc is not None and units is not None:
135 self.jdc.recorded_units=units
136 self.jdc.old_recorded_units=units
138 if not self.jdc: # nouveau jdc
140 self.jdc = self._newJDC(units=units)
142 self.jdc = self._newJDCInclude(units=units)
146 self.jdc.appli = self
149 if self.appli.code == "CARMEL3D" and self.jdc.procedure == "" :
151 self.jdc.procedure="LINEAR=L_LAW()"
153 print self.jdc.cr.get_mess_exception()
154 if self.jdc.cr.get_mess_exception()!="" :
155 self.jdc = self._newJDC(units=units)
158 self.jdc = self._newJDC(units=units)
162 txt_exception = self.jdc.cr.get_mess_exception()
165 qApp.restoreOverrideCursor()
166 self.affiche_infos("Erreur fatale au chargement de %s" %fichier,Qt.red)
167 QMessageBox.critical( self, "Erreur fatale au chargement d'un fichier", txt_exception)
169 comploader.charger_composants("QT")
170 jdc_item=Objecttreeitem.make_objecttreeitem( self, "nom", self.jdc )
172 if (not self.jdc.isvalid()) and (not nouveau) :
173 self.viewJdcRapport()
175 self.tree = browser.JDCTree( jdc_item, self )
177 #--------------------------------#
178 def _newJDC( self ,units = None):
179 #--------------------------------#
181 Initialise un nouveau JDC vierge
183 CONTEXT.unset_current_step()
185 jdc=self.readercata.cata[0].JdC( procedure ="",
187 cata=self.readercata.cata,
188 cata_ord_dico=self.readercata.cata_ordonne_dico,
189 rep_mat=self.CONFIGURATION.rep_mat
191 if units is not None:
192 jdc.recorded_units=units
193 jdc.old_recorded_units=units
197 #--------------------------------#
198 def _newJDCInclude( self ,units = None):
199 #--------------------------------#
201 Initialise un nouveau JDC vierge
203 import Extensions.jdc_include
204 JdC_aux=Extensions.jdc_include.JdC_include
205 CONTEXT.unset_current_step()
207 jaux=self.readercata.cata[0].JdC( procedure="",
209 cata=self.readercata.cata,
210 cata_ord_dico=self.readercata.cata_ordonne_dico,
211 rep_mat=self.CONFIGURATION.rep_mat,
215 J=JdC_aux( procedure="",
217 cata=self.readercata.cata,
218 cata_ord_dico=self.readercata.cata_ordonne_dico,
220 rep_mat=self.CONFIGURATION.rep_mat,
223 if units is not None:
224 J.recorded_units=units
225 J.old_recorded_units=units
228 #-------------------------------#
229 def readFile(self, fn):
230 #--------------------------------#
232 Public slot to read the text from a file.
233 @param fn filename to read from (string or QString)
237 # ------------------------------------------------------------------------------------
239 # ------------------------------------------------------------------------------------
241 jdcName=os.path.basename(fn)
242 # Il faut convertir le contenu du fichier en fonction du format
243 if convert.plugins.has_key( self.appliEficas.format_fichier_in ):
244 # Le convertisseur existe on l'utilise
246 p=convert.plugins[self.appliEficas.format_fichier_in]()
248 pareil,texteNew=self.verifieCHECKSUM(p.text)
250 QMessageBox.warning( self, "fichier modifie","Attention! fichier change hors EFICAS")
252 text=p.convert('exec',self.appliEficas)
253 if not p.cr.estvide():
254 self.affiche_infos("Erreur à la conversion",Qt.red)
256 self.affiche_infos("Type de fichier non reconnu",Qt.red)
257 QMessageBox.critical( self, "Type de fichier non reconnu","EFICAS ne sait pas ouvrir le type de fichier %s" % self.appliEficas.format_fichier_in)
260 CONTEXT.unset_current_step()
261 jdc=self.readercata.cata[0].JdC(procedure=text,
263 cata=self.readercata.cata,
264 cata_ord_dico=self.readercata.cata_ordonne_dico,
266 rep_mat=self.CONFIGURATION.rep_mat
268 # ----------------------------------------------------
270 # ----------------------------------------------------
271 self.modified = False
273 # qApp.restoreOverrideCursor()
274 if self.fileInfo!= None :
275 self.lastModified = self.fileInfo.lastModified()
277 self.lastModified = 1
281 #-----------------------#
282 def get_source(self,file):
283 #-----------------------#
285 # Il faut convertir le contenu du fichier en fonction du format
286 if convert.plugins.has_key(self.format):
287 # Le convertisseur existe on l'utilise
288 p=convert.plugins[self.format]()
290 text=p.convert('execnoparseur')
291 if not p.cr.estvide():
292 self.affiche_infos("Erreur a la conversion",Qt.red)
295 # Il n'existe pas c'est une erreur
296 self.affiche_infos("Type de fichier non reconnu",Qt.red)
297 QMessageBox.critical( self, "Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
300 #----------------------------------------------#
301 def _viewText(self, txt, caption = "FILE_VIEWER"):
302 #----------------------------------------------#
303 w = qtCommun.ViewText( self.QWParent )
304 w.setWindowTitle( caption )
308 #-----------------------#
309 def viewJdcSource(self):
310 #-----------------------#
311 f=open(self.fichier,'r')
314 self._viewText(texteSource, "JDC_SOURCE")
316 #-----------------------#
318 #-----------------------#
319 strSource = str( self.get_text_JDC(self.format) )
320 self._viewText(strSource, "JDC_RESULTAT")
322 #-----------------------#
323 def viewJdcRapport(self):
324 #-----------------------#
325 strRapport = str( self.jdc.report() )
326 self._viewText(strRapport, "JDC_RAPPORT")
332 Public method called by the viewmanager to finally get rid of us.
338 #----------------------------------------------#
339 def affiche_infos(self,message,couleur=Qt.black):
340 #----------------------------------------------#
342 mapalette=self.sb.palette()
343 from PyQt4.QtGui import QPalette
344 mapalette.setColor( QPalette.WindowText, couleur )
345 self.sb.setPalette( mapalette );
346 self.sb.showMessage(QString.fromUtf8(message))#,2000)
348 #------------------------------#
349 def affiche_alerte(self,titre,message):
350 #------------------------------#
351 # appele par I_MACRO_ETAPE
352 QMessageBox.information( self, titre, message)
354 #-------------------#
355 def init_modif(self):
356 #-------------------#
358 Met l'attribut modified a 'o' : utilise par Eficas pour savoir
359 si un JDC doit etre sauvegarde avant destruction ou non
363 #---------------------------------------#
364 def chercheNoeudSelectionne(self,copie=1):
365 #---------------------------------------#
367 appele par Cut et Copy pour positionner self.node_selected
369 self.node_selected=None
370 if len(self.tree.selectedItems()) == 0 : return
371 if len(self.tree.selectedItems()) != 1 :
372 QMessageBox.information( self,
374 "Cette version d'EFICAS permet uniquement la copie d un seul objet")
376 self.node_selected=self.tree.selectedItems()[0]
377 if copie == 0 : return
380 #---------------------#
381 def handleSupprimer(self):
382 #---------------------#
383 #print "handleSupprimer"
384 self.chercheNoeudSelectionne()
385 self.node_selected.delete()
387 #---------------------#
388 def handleEditCut(self):
389 #---------------------#
391 Stocke dans Eficas.noeud_a_editer le noeud à couper
393 #print "handleEditCut"
394 self.chercheNoeudSelectionne()
395 self.QWParent.edit="couper"
396 self.QWParent.noeud_a_editer = self.node_selected
398 #-----------------------#
399 def handleEditCopy(self):
400 #-----------------------#
402 Stocke dans Eficas.noeud_a_editer le noeud a copier
404 self.chercheNoeudSelectionne()
405 self.node_selected.update_node_label_in_blue()
406 self.QWParent.edit="copier"
407 self.QWParent.noeud_a_editer = self.node_selected
409 #------------------------#
410 def handleEditPaste(self):
411 #------------------------#
413 Lance la copie de l'objet place dans self.QWParent.noeud_a_editer
414 Ne permet que la copie d'objets de type Commande ou MCF
416 #print "handleEditPaste"
417 self.chercheNoeudSelectionne()
419 index_noeud_a_couper=self.QWParent.noeud_a_editer.treeParent.children.index(self.QWParent.noeud_a_editer)
421 QMessageBox.information( self,
423 "Aucun Objet n a ete copie ou coupe ")
427 child=self.QWParent.noeud_a_editer.doPaste(self.node_selected)
429 traceback.print_exc()
430 QMessageBox.information( self,
432 "Copie refusee pour ce type d objet a cet endroit")
434 self.affiche_infos("Copie refusée")
437 if child == 0 or child == None:
438 QMessageBox.critical( self, "Copie refusee",'Copie refusee pour ce type d objet')
440 self.affiche_infos("Copie refusée",Qt.red)
443 # il faut declarer le JDCDisplay_courant modifie
445 # suppression eventuelle du noeud selectionne
446 # si possible on renomme l objet comme le noeud couper
448 if self.QWParent.edit == "couper":
449 index_ajoute=child.treeParent.children.index(child)
450 if index_ajoute <= index_noeud_a_couper :
451 index_noeud_a_couper=index_noeud_a_couper + 1
452 item=self.QWParent.noeud_a_editer.item
453 noeud_a_supprimer=self.QWParent.noeud_a_editer.treeParent.children[index_noeud_a_couper]
454 noeud_a_supprimer.delete()
455 child.item.update(item)
456 #test,mess = child.item.nomme_sd(nom)
459 # on rend la copie a nouveau possible en liberant le flag edit
460 self.QWParent.edit="copier"
461 self.QWParent.noeud_a_editer=child
463 #---------------------#
464 def getFileName(self):
465 #---------------------#
468 #---------------------------#
469 def get_file_variable(self) :
470 #---------------------------#
471 titre = "Choix d'un fichier XML"
472 texte = "Le fichier contient une commande MODEL\n"
473 texte = texte+'Donnez le nom du fichier XML qui contient la description des variables'
474 QMessageBox.information( self, titre,texte)
476 fichier = QFileDialog.getOpenFileName(self.appliEficas,
477 self.appliEficas.trUtf8('Ouvrir Fichier'),
478 self.appliEficas.CONFIGURATION.savedir,
479 self.appliEficas.trUtf8('Wrapper Files (*.xml);;''All Files (*)'))
482 #----------------------------------#
483 def writeFile(self, fn, txt = None):
484 #----------------------------------#
486 Public slot to write the text to a file.
488 @param fn filename to write to (string or QString)
489 @return flag indicating success
495 txt = self.get_text_JDC(self.format)
497 if len(txt) >= len(eol):
498 if txt[-len(eol):] != eol:
502 checksum=self.get_checksum(txt)
510 QMessageBox.critical(self, self.trUtf8('Save File'),
511 self.trUtf8('The file <b>%1</b> could not be saved.<br>Reason: %2')
512 .arg(unicode(fn)).arg(str(why)))
515 #-----------------------------#
516 def get_text_JDC(self,format):
517 #-----------------------------#
518 if generator.plugins.has_key(format):
519 # Le generateur existe on l'utilise
520 self.generator=generator.plugins[format]()
521 jdc_formate=self.generator.gener(self.jdc,format='beautifie',config=self.appliEficas.CONFIGURATION)
522 if not self.generator.cr.estvide():
523 self.affiche_infos("Erreur à la generation",Qt.red)
524 QMessageBox.critical( self, "Erreur a la generation","EFICAS ne sait pas convertir ce JDC")
529 # Il n'existe pas c'est une erreur
530 self.affiche_infos("Format %s non reconnu" % self.format,Qt.red)
531 QMessageBox.critical( self, "Format "+self.format+" non reconnu","EFICAS ne sait pas convertir le JDC selon le format "+self.format)
534 #-----------------------------#
535 def run(self,execution="oui"):
536 #-----------------------------#
538 if generator.plugins.has_key(self.format):
539 # Le generateur existe on l'utilise
540 self.generator=generator.plugins[self.format]()
541 self.textePython =self.generator.generRUN(self.jdc,format='beautifie',config=self.appliEficas.CONFIGURATION)
542 if execution=="oui" :
543 exec self.textePython
545 return self.textePython
547 #------------------------------------------------#
548 def runYACS(self,execution="oui",nomFichier=None):
549 #------------------------------------------------#
550 if generator.plugins.has_key(self.format):
551 # Le generateur existe on l'utilise
552 self.generator=generator.plugins[self.format]()
553 self.generator.generRUNYACS(self.jdc,format='beautifie',config=self.appliEficas.CONFIGURATION,nomFichier=nomFichier)
554 if execution=="oui" :
555 print "il faut faire le run dans Salome"
558 #-----------------------------------------------------#
559 def determineNomFichier(self,path,extension):
560 #-----------------------------------------------------#
561 if DictExtensions.has_key(self.appli.code) :
562 chaine1="JDC (*"+DictExtensions[self.appli.code]+");;"
563 extensions= self.trUtf8(chaine1+ "All Files (*)")
565 extensions= self.trUtf8("JDC (*.comm);;" "All Files (*)")
567 if self.appli.code == "MAP" :
568 extensions = extensions + ";;Schema Yacs (*.xml);; Run (*.py);;"
570 fn = QFileDialog.getSaveFileName( self,
571 self.trUtf8("sauvegarde"), path,
573 QFileDialog.DontConfirmOverwrite)
574 if fn.isNull(): return (0, None)
575 ext = QFileInfo(fn).suffix()
576 if ext.isEmpty(): fn.append(extension)
578 if QFileInfo(fn).exists():
579 abort = QMessageBox.warning(self,
580 self.trUtf8("Sauvegarde du Fichier"),
581 self.trUtf8("Le fichier <b>%1</b> existe deja.").arg(fn),
582 self.trUtf8("&Ecraser"),
583 self.trUtf8("&Abandonner"))
584 if abort == 1 : return (0, "")
589 texte=self.run(execution="non")
592 if hasattr(self,'fichierRun'):
593 self.writeFile( self.fichierRun, txt = texte)
596 if self.fichier == None :
597 path=self.CONFIGURATION.savedir
599 path=QFileInfo(self.fichier).absolutePath()+"/"+QFileInfo(self.fichier).baseName()+".py"
600 bOK, fn=self.determineNomFichier(path,extension)
602 self.fichierRun = unicode(QDir.convertSeparators(fn))
603 self.writeFile( self.fichierRun, txt = texte)
605 #-----------------------------#
607 #-----------------------------#
608 if hasattr(self,'fichierYACS'):
609 self.runYACS(execution="non",nomFichier=self.fichierYACS)
612 today = str(date.today())
613 today = today.replace('-', '')
614 today+="-"+time.strftime("%H%M%S", time.localtime())
615 path=self.CONFIGURATION.PATH_STUDY+"/"+self.CONFIGURATION.NAME_SCHEME+"_"+today+".xml"
618 bOK, fn=self.determineNomFichier(path,extension)
620 self.runYACS(execution="non",nomFichier=fn)
623 #-----------------------------------------#
624 def cherche_Groupes(self):
625 #-----------------------------------------#
626 listeMA,listeNO=self.get_text_JDC("GroupMA")
627 return listeMA,listeNO
629 #-----------------------------------------#
630 def handleAjoutGroup(self,listeGroup):
631 #-----------------------------------------#
632 dernier=self.tree.racine.children[-1]
633 for groupe in listeGroup :
634 new_node = dernier.append_brother("MESH_GROUPE",'after')
635 test,mess = new_node.item.nomme_sd(groupe)
636 new_node.append_child('Material')
639 #-----------------------------------------#
640 def saveFile(self, path = None, saveas= 0):
641 #-----------------------------------------#
643 Public slot to save the text to a file.
645 @param path directory to save the file in (string or QString)
646 @return tuple of two values (boolean, string) giving a success indicator and
647 the name of the saved file
650 if not self.modified and not saveas:
651 return (0, None) # do nothing if text wasn't changed
654 if DictExtensions.has_key(self.appli.code) :
655 extension=DictExtensions[self.appli.code]
661 if self.fichier is None or saveas:
663 path=self.CONFIGURATION.savedir
664 bOK, fn=self.determineNomFichier(path,extension)
665 if fn == None : return (0, None)
666 if fn.isNull(): return (0, None)
668 ulfile = os.path.abspath(unicode(fn))
669 self.appliEficas.CONFIGURATION.savedir=os.path.split(ulfile)[0]
670 fn = unicode(QDir.convertSeparators(fn))
673 if not (self.writeFile(fn)): return (0, None)
675 self.modified = False
676 if self.fileInfo is None or saveas:
677 self.fileInfo = QFileInfo(self.fichier)
678 self.fileInfo.setCaching(0)
679 self.lastModified = self.fileInfo.lastModified()
680 if newName is not None:
681 self.appliEficas.addToRecentList(newName)
682 self.tree.racine.item.getObject().nom=os.path.basename(newName)
683 self.tree.racine.update_node_label()
685 if self.jdc.isvalid() != 0 and hasattr(self.generator, "writeDefault"):
686 self.generator.writeDefault(fn)
689 self.appliEficas.addJdcInSalome( self.fichier)
690 return (1, self.fichier)
692 #---------------------------------#
693 def saveFileAs(self, path = None):
694 #---------------------------------#
696 Public slot to save a file with a new name.
698 @param path directory to save the file in (string or QString)
699 @return tuple of two values (boolean, string) giving a success indicator and
700 the name of the saved file
702 return self.saveFile(path,1)
706 #---------------------------------------------#
707 def get_file(self,unite=None,fic_origine = ''):
708 #---------------------------------------------#
716 titre = "Choix unite %d " %unite
717 texte = "Le fichier %s contient une commande INCLUDE \n" % fic_origine
718 texte = texte+'Donnez le nom du fichier correspondant\n à l unité logique %d' % unite
719 labeltexte = 'Fichier pour unite %d :' % unite
721 titre = "Choix d'un fichier de poursuite"
722 texte = "Le fichier %s contient une commande %s\n" %(fic_origine,'POURSUITE')
723 texte = texte+'Donnez le nom du fichier dont vous \n voulez faire une poursuite'
725 QMessageBox.information( self, titre,QString.fromUtf8(texte))
726 fn = QFileDialog.getOpenFileName(self.appliEficas,
728 self.appliEficas.CONFIGURATION.savedir)
731 # ce retour est impose par le get_file d'I_JDC
734 ulfile = os.path.abspath(unicode(fn))
735 self.appliEficas.CONFIGURATION.savedir=os.path.split(ulfile)[0]
737 # On utilise le convertisseur défini par format_fichier
738 source=self.get_source(ulfile)
740 # On a réussi à convertir le fichier self.ulfile
743 # Une erreur a été rencontrée
745 return ulfile, jdcText
749 #------------------------------#
750 def verifieCHECKSUM(self,text):
751 #------------------------------#
752 indexDeb=text.find("#CHECKSUM:")
755 indexFin=text.find(":FIN CHECKSUM")
756 checkAvant=text[indexDeb:indexFin+13]
757 textJDC=text[0:indexDeb]+text[indexFin+13:-1]
758 checksum=self.get_checksum(textJDC)
759 pareil=(checkAvant==checksum)
760 return pareil, textJDC
761 #---------------------------#
762 def get_checksum(self,texte):
763 #---------------------------#
764 newtexte=texte.replace('"','\\"')
765 commande='echo "'+newtexte+'"|md5sum'
769 ligne="#CHECKSUM:"+checksum[0:-1]+":FIN CHECKSUM"
772 if __name__=='__main__':
774 name='prefs_'+prefs.code
775 prefsCode=__import__(name)
777 if hasattr(prefsCode,'encoding'):
778 # Hack pour changer le codage par defaut des strings
781 sys.setdefaultencoding(prefs.encoding)
782 del sys.setdefaultencoding
785 # #CS_pbruno note: fait implicitement des trucs ces imports (grr)
790 # # Analyse des arguments de la ligne de commande
791 # options=session.parse(sys.argv)
794 app = QApplication(sys.argv)
795 mw = JDCEditor(None,'azAster.comm')
796 app.setMainWidget(mw)
797 app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
800 res = app.exec_loop()