1 #i -*- coding: iso-8859-1 -*-
10 import convert,generator
11 from Editeur import session
12 from Editeur import comploader
13 from Editeur import Objecttreeitem
21 VERSION_EFICAS = "EFICAS v1.14"
24 # -------------------------- #
26 class JDCEditor(QSplitter):
28 # -------------------------- #
33 def __init__(self,fn = None, jdc = None ,parent=None, editor = None, units = None, include=0):
34 #-------------------------------------------------------------------------------------------#
36 QSplitter.__init__(self, parent,'')
38 VERSION_CODE = session.d_env.cata
42 self.salome = self.parent.salome
43 self.appliEficas = self.parent.appliEficas
45 self.code = prefs.code
46 self.version_code = VERSION_CODE
47 self.titre=VERSION_EFICAS + ' pour '+ self.code
49 self.liste_simp_reel=[]
50 self.format_fichier='python' # par defaut
51 self.jdc_openturn_xml=""
52 self.jdc_openturn_std=""
55 from Editeur import configuration
56 self.CONFIGURATION = self.appliEficas.CONFIGURATION
57 self.CONFIGStyle = self.appliEficas.CONFIGStyle
60 if hasattr(qApp.mainWidget(),"statusBar"):
61 self.sb = qApp.mainWidget().statusBar()
63 self.vm = parent #viewManager
70 self.panel_courant=None
71 self.node_selected = None
73 self.isReadOnly = False
75 if not hasattr( readercata, 'reader' ) :
76 readercata.reader = readercata.READERCATA( self, self )
77 self.readercata = readercata.reader
79 #------- construction du jdc --------------
84 if self.fileName is not None: # fichier jdc fourni
85 self.fileInfo = QFileInfo(self.fileName)
86 self.fileInfo.setCaching(0)
88 self.jdc = self.readFile(self.fileName)
90 self.jdc.recorded_units=units
91 self.jdc.old_recorded_units=units
94 self.code = editor.code
95 self.version_code = editor.version_code
96 self.titre = editor.titre
97 self.dict_reels = editor.dict_reels
98 self.liste_simp_reel= editor.liste_simp_reel
99 self.format_fichier = editor.format_fichier
100 self.CONFIGURATION = editor.CONFIGURATION
101 self.CONFIGStyle = editor.CONFIGStyle
102 self.jdc = editor.jdc
104 self.lastModified = self.fileInfo.lastModified()
105 elif editor is not None:
106 self.jdc = editor.jdc
108 if not self.jdc: # nouveau jdc
110 self.jdc = self._newJDC(units=units)
112 self.jdc = self._newJDCInclude(units=units)
116 self.jdc.appli = self
120 txt_exception = self.jdc.cr.get_mess_exception()
123 qApp.restoreOverrideCursor()
124 self.affiche_infos("Erreur fatale au chargement de %s" %fn)
125 QMessageBox.critical( self, "Erreur fatale au chargement d'un fichier", txt_exception)
127 comploader.charger_composants("QT")
128 jdc_item=Objecttreeitem.make_objecttreeitem( self, "nom", self.jdc )
130 if (not self.jdc.isvalid()) and (not nouveau) :
131 self.viewJdcRapport()
133 #------- config widget --------------
136 self.tree = browser.JDCTree( jdc_item, self )
137 self.connect(self.tree,SIGNAL('selectionChanged(QListViewItem *)'),self.updatePanel)
140 if sh.height() < 300:
144 # Make sure tabbing through a QWorkspace works.
145 self.setFocusPolicy(QWidget.StrongFocus)
146 self._updateReadOnly(1)
148 # Set the editors size if it is too big for the parent.
149 if parent is not None:
151 bnd = req.boundedTo(parent.size())
153 if bnd.width() < req.width() or bnd.height() < req.height():
156 self.panel = QWidget(self)
157 #self.connect(self, SIGNAL('modificationChanged(bool)'), self.handleModificationChanged)
160 #-------------------------------------------------------------------#
161 def _updateReadOnly(self, bForce=1):
162 #-------------------------------------------------------------------#
164 Private method to update the readOnly information for this editor.
166 If bForce is True, then updates everything regardless if
167 the attributes have actually changed, such as during
168 initialization time. A signal is emitted after the
171 @param bForce 1 to force change, 0 to only update and emit
172 signal if there was an attribute change.
175 if self.fileName is None:
177 readOnly = not QFileInfo(self.fileName).isWritable() and 1 or 0
178 if not bForce and (readOnly == self.isReadOnly):
182 cap = "%s (ro)" % unicode(cap)
183 self.isReadOnly = readOnly
185 self.emit(PYSIGNAL('captionChanged'), (cap, self))
187 #--------------------------------#
188 def _newJDC( self ,units = None):
189 #--------------------------------#
191 Initialise un nouveau JDC vierge
193 CONTEXT.unset_current_step()
194 jdc=self.readercata.cata[0].JdC( procedure="",
196 cata=self.readercata.cata,
197 cata_ord_dico=self.readercata.cata_ordonne_dico,
198 rep_mat=self.CONFIGURATION.rep_mat
200 if units is not None:
201 jdc.recorded_units=units
202 jdc.old_recorded_units=units
206 #--------------------------------#
207 def _newJDCInclude( self ,units = None):
208 #--------------------------------#
210 Initialise un nouveau JDC vierge
212 import Extensions.jdc_include
213 JdC_aux=Extensions.jdc_include.JdC_include
214 CONTEXT.unset_current_step()
216 jaux=self.readercata.cata[0].JdC( procedure="",
218 cata=self.readercata.cata,
219 cata_ord_dico=self.readercata.cata_ordonne_dico,
220 rep_mat=self.CONFIGURATION.rep_mat,
224 J=JdC_aux( procedure="",
226 cata=self.readercata.cata,
227 cata_ord_dico=self.readercata.cata_ordonne_dico,
229 rep_mat=self.CONFIGURATION.rep_mat,
232 if units is not None:
233 J.recorded_units=units
234 J.old_recorded_units=units
238 #-----------------------#
239 def get_source(self,file):
240 #-----------------------#
242 format=self.format_fichier
244 # Il faut convertir le contenu du fichier en fonction du format
245 if convert.plugins.has_key(format):
246 # Le convertisseur existe on l'utilise
247 p=convert.plugins[format]()
249 text=p.convert('execnoparseur')
250 if not p.cr.estvide():
251 self.affiche_infos("Erreur a la conversion")
254 # Il n'existe pas c'est une erreur
255 self.affiche_infos("Type de fichier non reconnu")
256 QMessageBox.critical( self, "Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
259 #---------------------------------------------#
260 def get_file(self,unite=None,fic_origine = ''):
261 #---------------------------------------------#
268 titre = "Choix unite %d " %unite
269 texte = "Le fichier %s contient une commande INCLUDE \n" % fic_origine
270 texte = texte+'Donnez le nom du fichier correspondant\n à l unité logique %d' % unite
271 labeltexte = 'Fichier pour unite %d :' % unite
273 titre = "Choix d'un fichier de poursuite"
274 texte = "Le fichier %s contient une commande %s\n" %(fic_origine,'POURSUITE')
275 texte = texte+'Donnez le nom du fichier dont vous \n voulez faire une poursuite'
277 QMessageBox.information( self, titre,texte)
278 fn = QFileDialog.getOpenFileName( None, "", self, None, titre )
283 ulfile = os.path.abspath(unicode(fn))
284 # On utilise le convertisseur défini par format_fichier
285 source=self.get_source(ulfile)
287 # On a réussi à convertir le fichier self.ulfile
290 # Une erreur a été rencontrée
292 return ulfile, jdcText
295 #-----------------------#
296 def readFile(self, fn):
297 #-----------------------#
299 Public slot to read the text from a file.
301 @param fn filename to read from (string or QString)
305 qApp.setOverrideCursor(Qt.waitCursor)
307 # ------------------------------------------------------------------------------------
309 # ------------------------------------------------------------------------------------
311 jdcName=os.path.basename(fn)
312 # Il faut convertir le contenu du fichier en fonction du format
313 if convert.plugins.has_key( self.format_fichier ):
314 # Le convertisseur existe on l'utilise
315 appli = self # CS_pbruno compatiblity parseur_python: self.appli.liste_simp_reel, self.appli.dict_reels
316 p=convert.plugins[self.format_fichier]()
318 text=p.convert('exec',appli)
319 if not p.cr.estvide():
320 self.affiche_infos("Erreur à la conversion")
322 CONTEXT.unset_current_step()
323 ## os.chdir(self.initialdir)
324 jdc=self.readercata.cata[0].JdC(procedure=text,
326 cata=self.readercata.cata,
327 cata_ord_dico=self.readercata.cata_ordonne_dico,
329 rep_mat=self.CONFIGURATION.rep_mat
331 # ----------------------------------------------------
333 # ----------------------------------------------------
334 self.modified = False
336 qApp.restoreOverrideCursor()
337 if self.fileInfo!= None :
338 self.lastModified = self.fileInfo.lastModified()
340 self.lastModified = 1
343 #----------------------------------------------#
344 def _viewText(self, txt, caption = "FILE_VIEWER"):
345 #----------------------------------------------#
346 w = qtCommun.ViewText( self.parent )
347 w.setCaption( caption )
351 #-----------------------#
352 def viewJdcSource(self):
353 #-----------------------#
354 format = self.format_fichier
355 f=open(self.fileName,'r')
358 self._viewText(texteSource, "JDC_SOURCE")
360 #-----------------------#
362 #-----------------------#
363 format = self.format_fichier
364 strSource = str( self.get_text_JDC(format) )
365 self._viewText(strSource, "JDC_RESULTAT")
367 #-----------------------#
368 def viewJdcRapport(self):
369 #-----------------------#
370 strRapport = str( self.jdc.report() )
371 self._viewText(strRapport, "JDC_RAPPORT")
373 #-----------------------#
374 def handleRenamed(self, fn):
375 #-----------------------#
377 Public slot to handle the editorRenamed signal.
379 @param fn filename to be set for the editor (QString or string).
381 self.fileName = unicode(fn)
382 self.setCaption(self.fileName)
384 if self.fileInfo is None:
385 self.fileInfo = QFileInfo(self.fileName)
386 self.fileInfo.setCaching(0)
388 self.lastModified = self.fileInfo.lastModified()
389 self.vm.setEditorName(self, self.fileName)
390 self._updateReadOnly(1)
392 #-----------------------#
393 def handleNewView(self):
394 #-----------------------#
396 Private slot to create a new view to an open document.
398 self.vm.newEditorView(self.fileName, self)#, self.isPythonFile)
400 #------------------------------------#
401 def handleModificationChanged(self, m):
402 #------------------------------------#
404 Private slot to handle the modificationChanged signal.
406 It emits the signal modificationStatusChanged with parameters
409 @param m modification status
411 if not m and self.fileInfo is not None:
412 self.lastModified = self.fileInfo.lastModified()
413 self.emit(PYSIGNAL('modificationStatusChanged'), (m, self))
415 #------------------------#
416 def hasSyntaxErrors(self):
417 #------------------------#
418 return False #CS_pbruno todo
424 Public method called by the viewmanager to finally get rid of us.
432 #------------------------------#
433 def affiche_infos(self,message):
434 #------------------------------#
436 if not hasattr(self.appliEficas,'MessageLabel') :
437 self.appliEficas.leLayout=QDockWindow(self.appliEficas)
438 self.appliEficas.MessageLabel = QLabel(self.appliEficas.leLayout,"MessageLabel")
439 self.appliEficas.MessageLabel.setAlignment(Qt.AlignBottom)
440 self.appliEficas.leLayout.setWidget(self.appliEficas.MessageLabel)
441 self.appliEficas.moveDockWindow(self.appliEficas.leLayout,Qt.DockBottom)
442 self.appliEficas.MessageLabel.setText(message)
443 self.appliEficas.MessageLabel.show()
444 self.appliEficas.leLayout.show()
446 self.sb.message(message)#,2000)
448 #------------------------------#
449 def updatePanel(self, jdcNode):
450 #------------------------------#
452 Appele a chaque changement de noeud
454 self.node_selected = jdcNode
460 if jdcNode.item.isactif():
461 self.panel = jdcNode.getPanel()
462 #print self.panel.__class__
464 self.panel = panelsQT.PanelInactif(self.node_selected,self)
467 self.panel = panelsQT.NoPanel(self)
472 #-------------------#
473 def init_modif(self):
474 #-------------------#
476 Met l'attribut modified a 'o' : utilise par Eficas pour savoir
477 si un JDC doit etre sauvegarde avant destruction ou non
480 self.emit(PYSIGNAL('modificationStatusChanged'), (True, self))
482 #-------------------#
483 def stop_modif(self):
484 #-------------------#
486 Met l'attribut modified à 'n' : utilisé par Eficas pour savoir
487 si un JDC doit etre sauvegardé avant destruction ou non
489 self.modified = False
490 self.emit(PYSIGNAL('modificationStatusChanged'), (False, self))
493 #-------------------#
495 #-------------------#
497 Stocke dans Eficas.noeud_a_editer le noeud à couper
499 if not self.node_selected.item.iscopiable():
500 QMessageBox.information( self, "Copie impossible",
501 "Cette version d'EFICAS ne permet que la copie d'objets de type 'Commande' ou mot-clé facteur")
503 self.parent.edit="couper"
504 self.parent.noeud_a_editer = self.node_selected
506 #-------------------#
508 #-------------------#
510 Stocke dans Eficas.noeud_a_editer le noeud a copier
512 if not self.node_selected.item.iscopiable():
513 QMessageBox.information( self, "Copie impossible",
514 "La copie d'un tel objet n'est pas permise")
516 self.parent.edit="copier"
517 self.parent.noeud_a_editer = self.node_selected
519 #-------------------#
521 #-------------------#
523 Lance la copie de l'objet place dans self.parent.noeud_a_editer
524 Ne permet que la copie d'objets de type Commande ou MCF
527 child=self.parent.noeud_a_editer.doPaste(self.node_selected)
529 traceback.print_exc()
530 QMessageBox.information( self, "Copie impossible",
531 "L'action de coller apres un tel objet n'est pas permise")
535 if self.message != '':
536 QMessageBox.critical( self, "Copie refusee", self.message)
538 self.affiche_infos("Copie refusée")
541 # il faut declarer le JDCDisplay_courant modifie
543 # suppression eventuelle du noeud selectionne
544 # si possible on renomme l objet comme le noeud couper
546 if self.parent.edit == "couper":
547 #nom = self.parent.noeud_a_editer.item.object.sd.nom
548 item=self.parent.noeud_a_editer.item
549 self.parent.noeud_a_editer.delete()
550 child.item.update(item)
551 #test,mess = child.item.nomme_sd(nom)
554 # on rend la copie a nouveau possible en liberant le flag edit
555 self.parent.edit="copier"
557 #---------------------#
558 def getFileName(self):
559 #---------------------#
562 #---------------------------#
563 def writeFile(self, fn, txt = None):
564 #------------------------------#
566 Public slot to write the text to a file.
568 @param fn filename to write to (string or QString)
569 @return flag indicating success
575 txt = self.get_text_JDC(self.format_fichier)
577 if len(txt) >= len(eol):
578 if txt[-len(eol):] != eol:
589 QMessageBox.critical(self, self.trUtf8('Save File'),
590 self.trUtf8('The file <b>%1</b> could not be saved.<br>Reason: %2')
591 .arg(unicode(fn)).arg(str(why)))
594 #------------------------------------
595 def writeFilesOpenturns(self,fn) :
596 #------------------------------------
597 base=fn[:fn.rfind(".")]
598 fileXML=base + '.xml'
599 fileSTD=base + '_std.py'
600 self.writeFile(fileXML,self.jdc_openturn_xml)
601 self.writeFile(fileSTD,self.jdc_openturn_std)
604 #-----------------------------#
605 def get_text_JDC(self,format):
606 #-----------------------------#
607 if generator.plugins.has_key(format):
608 # Le generateur existe on l'utilise
609 g=generator.plugins[format]()
610 jdc_formate=g.gener(self.jdc,format='beautifie')
611 if format == "openturns" :
612 self.jdc_openturn_xml=g.getOpenturnsXML()
613 self.jdc_openturn_std=g.getOpenturnsSTD()
614 if not g.cr.estvide():
615 self.affiche_infos("Erreur à la generation")
616 QMessageBox.critical( self, "Erreur a la generation","EFICAS ne sait pas convertir ce JDC")
621 # Il n'existe pas c'est une erreur
622 self.affiche_infos("Format %s non reconnu" % format)
623 QMessageBox.critical( self, "Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
627 #-------------------------------------------#
628 def saveFile(self, saveas = 0, path = None):
629 #-------------------------------------------#
631 Public slot to save the text to a file.
633 @param saveas flag indicating a 'save as' action
634 @param path directory to save the file in (string or QString)
635 @return tuple of two values (boolean, string) giving a success indicator and
636 the name of the saved file
638 self.modified = True #CS_pbruno test
640 if not saveas and not self.modified:#self.isModified():
641 return (0, None) # do nothing if text wasn't changed
644 if saveas or self.fileName is None:
645 if path is None and self.fileName is not None:
646 path = os.path.dirname(unicode(self.fileName))
647 selectedFilter = QString('')
648 fn = QFileDialog.getSaveFileName(path,
649 self.trUtf8("JDC (*.comm);;"
650 "All Files (*)"), self, None,
651 self.trUtf8("Save File"), selectedFilter, 0)
654 ext = QFileInfo(fn).extension()
656 ex = selectedFilter.section('(*',1,1).section(')',0,0)
659 if QFileInfo(fn).exists():
660 abort = QMessageBox.warning(self,
661 self.trUtf8("Save File"),
662 self.trUtf8("The file <b>%1</b> already exists.")
664 self.trUtf8("&Overwrite"),
665 self.trUtf8("&Abort"), None, 1)
668 fn = unicode(QDir.convertSeparators(fn))
675 if self.writeFile(fn):
677 self.modified = False
678 self.setCaption(self.fileName)
679 if self.fileInfo is None or saveas:
680 self.fileInfo = QFileInfo(self.fileName)
681 self.fileInfo.setCaching(0)
682 self.emit(PYSIGNAL('editorRenamed'), (self.fileName,))
683 self.lastModified = self.fileInfo.lastModified()
684 if newName is not None:
685 self.vm.addToRecentList(newName)
686 self.emit(PYSIGNAL('editorSaved'), (self.fileName,))
688 if self.code == "OPENTURNS" :
689 self.writeFilesOpenturns(fn)
691 self.parent.appli.addJdcInSalome( self.fileName)
692 if self.code == 'ASTER':
693 self.parent.appli.createOrUpdateMesh(self)
697 return (1, self.fileName)
701 #---------------------------------#
702 def saveFileAs(self, path = None):
703 #---------------------------------#
705 Public slot to save a file with a new name.
707 @param path directory to save the file in (string or QString)
708 @return tuple of two values (boolean, string) giving a success indicator and
709 the name of the saved file
711 return self.saveFile(1, path)
714 if __name__=='__main__':
715 if hasattr(prefs,'encoding'):
716 # Hack pour changer le codage par defaut des strings
719 sys.setdefaultencoding(prefs.encoding)
720 del sys.setdefaultencoding
723 #CS_pbruno note: fait implicitement des trucs ces imports (grr)
728 # Analyse des arguments de la ligne de commande
729 options=session.parse(sys.argv)
732 app = QApplication(sys.argv)
733 mw = JDCEditor('azAster.comm')
734 app.setMainWidget(mw)
735 app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
738 res = app.exec_loop()