]> SALOME platform Git repositories - tools/eficas.git/blob - InterfaceQT/editor.py
Salome HOME
CCAR: merge de la version 1.14 dans la branche principale
[tools/eficas.git] / InterfaceQT / editor.py
1 #i -*- coding: iso-8859-1 -*-
2
3 # Modules Python
4 import types,sys,os
5 import traceback
6 from qt import *
7
8 # Modules Eficas
9
10 import convert,generator
11 from Editeur     import session
12 from Editeur     import comploader
13 from Editeur     import Objecttreeitem
14 import panelsQT
15 import browser
16 import readercata
17
18 import prefs
19 import qtCommun
20
21 VERSION_EFICAS  = "EFICAS v1.14"
22
23
24 # -------------------------- #
25 #                            #
26 class JDCEditor(QSplitter):
27 #                            #
28 # -------------------------- #
29     """
30        Editeur de jdc
31     """        
32
33     def __init__(self,fn = None, jdc = None ,parent=None, editor = None, units = None, include=0):          
34     #-------------------------------------------------------------------------------------------#
35
36         QSplitter.__init__(self, parent,'')
37         
38         VERSION_CODE    = session.d_env.cata
39         self.salome=0
40         self.parent         = parent
41         if parent != None :
42            self.salome         = self.parent.salome
43         self.appliEficas = self.parent.appliEficas
44         self.top  = None
45         self.code = prefs.code
46         self.version_code = VERSION_CODE
47         self.titre=VERSION_EFICAS + ' pour '+ self.code
48         self.dict_reels={}
49         self.liste_simp_reel=[]        
50         self.format_fichier='python' # par defaut
51         self.jdc_openturn_xml=""
52         self.jdc_openturn_std=""
53         self.ihm="QT"
54         
55         from Editeur import configuration
56         self.CONFIGURATION = self.appliEficas.CONFIGURATION
57         self.CONFIGStyle = self.appliEficas.CONFIGStyle
58         self.test=0
59         self.sb = None
60         if hasattr(qApp.mainWidget(),"statusBar"):
61             self.sb = qApp.mainWidget().statusBar()
62       
63         self.vm             = parent    #viewManager
64         self.fileName       = fn
65         self.fileInfo       = None
66         self.lastModified   = 0
67         self.jdc            = jdc
68         
69         self.fichier=None
70         self.panel_courant=None    
71         self.node_selected = None
72         self.modified   = False
73         self.isReadOnly = False
74         
75         if not hasattr( readercata, 'reader' ) :
76             readercata.reader = readercata.READERCATA( self, self )
77         self.readercata = readercata.reader
78         
79         #------- construction du jdc --------------
80
81         jdc_item = None
82                         
83         nouveau=0
84         if self.fileName is not None:        #  fichier jdc fourni
85             self.fileInfo = QFileInfo(self.fileName)
86             self.fileInfo.setCaching(0)
87             if editor is None:
88                 self.jdc = self.readFile(self.fileName)
89                 if units is not None:
90                    self.jdc.recorded_units=units
91                    self.jdc.old_recorded_units=units
92             else:
93                 self.top            = editor.top
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
103                 
104                 self.lastModified = self.fileInfo.lastModified()                
105         elif editor is not None: 
106             self.jdc = editor.jdc            
107         else: 
108             if not self.jdc:                   #  nouveau jdc
109                 if not include :
110                    self.jdc = self._newJDC(units=units)
111                 else :
112                    self.jdc = self._newJDCInclude(units=units)
113                 nouveau=1
114         
115         if self.jdc:            
116             self.jdc.appli = self
117             txt_exception  = None
118             if not jdc:
119                 self.jdc.analyse()            
120                 txt_exception = self.jdc.cr.get_mess_exception()            
121             if txt_exception:
122                 self.jdc = None
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)                
126             else:
127                 comploader.charger_composants("QT")
128                 jdc_item=Objecttreeitem.make_objecttreeitem( self, "nom", self.jdc )
129
130                 if (not self.jdc.isvalid()) and (not nouveau) :
131                     self.viewJdcRapport()
132
133         #------- config widget --------------
134                 
135         if jdc_item:                        
136             self.tree = browser.JDCTree( jdc_item, self )
137             self.connect(self.tree,SIGNAL('selectionChanged(QListViewItem *)'),self.updatePanel)
138       
139         sh = self.sizeHint()
140         if sh.height() < 300:
141             sh.setHeight(300)
142         self.resize(sh)
143             
144         # Make sure tabbing through a QWorkspace works.
145         self.setFocusPolicy(QWidget.StrongFocus)
146         self._updateReadOnly(1)
147         
148         # Set the editors size if it is too big for the parent.
149         if parent is not None:
150             req = self.size()
151             bnd = req.boundedTo(parent.size())
152         
153             if bnd.width() < req.width() or bnd.height() < req.height():
154                 self.resize(bnd)
155         
156         self.panel = QWidget(self)        
157         #self.connect(self, SIGNAL('modificationChanged(bool)'), self.handleModificationChanged)
158                 
159         
160     #-------------------------------------------------------------------#
161     def _updateReadOnly(self, bForce=1):
162     #-------------------------------------------------------------------#
163         """
164         Private method to update the readOnly information for this editor. 
165         
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
169         caption change.
170
171         @param bForce 1 to force change, 0 to only update and emit
172                 signal if there was an attribute change.
173         """
174
175         if self.fileName is None:
176             return
177         readOnly = not QFileInfo(self.fileName).isWritable() and 1 or 0
178         if not bForce and (readOnly == self.isReadOnly):
179             return
180         cap = self.fileName
181         if readOnly:
182             cap = "%s (ro)" % unicode(cap)
183         self.isReadOnly = readOnly
184         self.setCaption(cap)
185         self.emit(PYSIGNAL('captionChanged'), (cap, self))
186         
187     #--------------------------------#
188     def _newJDC( self ,units = None):        
189     #--------------------------------#
190         """
191         Initialise un nouveau JDC vierge
192         """
193         CONTEXT.unset_current_step()        
194         jdc=self.readercata.cata[0].JdC( procedure="",
195                                          appli=self,
196                                          cata=self.readercata.cata,
197                                          cata_ord_dico=self.readercata.cata_ordonne_dico,
198                                          rep_mat=self.CONFIGURATION.rep_mat
199                                         )                         
200         if units is not None:
201            jdc.recorded_units=units
202            jdc.old_recorded_units=units
203         jdc.analyse()        
204         return jdc
205         
206     #--------------------------------#
207     def _newJDCInclude( self ,units = None):        
208     #--------------------------------#
209         """
210         Initialise un nouveau JDC vierge
211         """
212         import Extensions.jdc_include
213         JdC_aux=Extensions.jdc_include.JdC_include
214         CONTEXT.unset_current_step()        
215
216         jaux=self.readercata.cata[0].JdC( procedure="",
217                                appli=self,
218                                cata=self.readercata.cata,
219                                cata_ord_dico=self.readercata.cata_ordonne_dico,
220                                rep_mat=self.CONFIGURATION.rep_mat,
221                               )
222         jaux.analyse()
223
224         J=JdC_aux( procedure="",
225                    appli=self,
226                    cata=self.readercata.cata,
227                    cata_ord_dico=self.readercata.cata_ordonne_dico,
228                    jdc_pere=jaux,
229                    rep_mat=self.CONFIGURATION.rep_mat,
230                    )
231         J.analyse()
232         if units is not None:
233            J.recorded_units=units
234            J.old_recorded_units=units
235         return J
236
237             
238     #-----------------------#
239     def get_source(self,file):
240     #-----------------------#
241         import convert
242         format=self.format_fichier
243
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]()
248             p.readfile(file)
249             text=p.convert('execnoparseur')
250             if not p.cr.estvide():
251                 self.affiche_infos("Erreur a la conversion")
252             return text
253         else:
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")            
257             return None
258         
259     #---------------------------------------------#
260     def get_file(self,unite=None,fic_origine = ''):
261     #---------------------------------------------#
262         ulfile  = None
263         jdcText = ""
264       
265         titre  = ""
266         
267         if unite :
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
272         else:
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'
276                                         
277         QMessageBox.information( self, titre,texte)
278         fn = QFileDialog.getOpenFileName( None, "", self, None, titre )
279         
280         if fn.isNull():
281             return
282             
283         ulfile = os.path.abspath(unicode(fn))
284         # On utilise le convertisseur défini par format_fichier
285         source=self.get_source(ulfile)
286         if source:
287             # On a réussi à convertir le fichier self.ulfile                
288             jdcText = source
289         else:
290             # Une erreur a été rencontrée
291             jdcText = ''
292         return ulfile, jdcText
293         
294         
295     #-----------------------#
296     def readFile(self, fn):
297     #-----------------------#
298         """
299         Public slot to read the text from a file.
300         
301         @param fn filename to read from (string or QString)
302         """        
303         fn = unicode(fn)        
304             
305         qApp.setOverrideCursor(Qt.waitCursor)
306                         
307         # ------------------------------------------------------------------------------------
308         #                         charge le JDC
309         # ------------------------------------------------------------------------------------      
310         
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]()
317              p.readfile(fn)         
318              text=p.convert('exec',appli)
319              if not p.cr.estvide():                 
320                 self.affiche_infos("Erreur à la conversion")
321         
322         CONTEXT.unset_current_step()
323         ##   os.chdir(self.initialdir)
324         jdc=self.readercata.cata[0].JdC(procedure=text,
325                                     appli=self,
326                                     cata=self.readercata.cata,
327                                     cata_ord_dico=self.readercata.cata_ordonne_dico,
328                                     nom=jdcName,
329                                     rep_mat=self.CONFIGURATION.rep_mat
330                                    )
331         # ----------------------------------------------------
332         #      charge le JDC fin
333         # ----------------------------------------------------
334         self.modified = False
335                         
336         qApp.restoreOverrideCursor()        
337         if self.fileInfo!= None : 
338            self.lastModified = self.fileInfo.lastModified()
339         else :
340            self.lastModified = 1
341         return jdc
342         
343     #----------------------------------------------#
344     def _viewText(self, txt, caption = "FILE_VIEWER"):    
345     #----------------------------------------------#
346         w = qtCommun.ViewText( self.parent )
347         w.setCaption( caption )
348         w.setText(txt)
349         w.show()
350         
351     #-----------------------#
352     def viewJdcSource(self):        
353     #-----------------------#
354         format = self.format_fichier
355         f=open(self.fileName,'r')
356         texteSource=f.read()
357         f.close()
358         self._viewText(texteSource, "JDC_SOURCE")
359                 
360     #-----------------------#
361     def viewJdcPy(self):        
362     #-----------------------#
363         format = self.format_fichier
364         strSource = str( self.get_text_JDC(format) )       
365         self._viewText(strSource, "JDC_RESULTAT")
366                 
367     #-----------------------#
368     def viewJdcRapport(self):
369     #-----------------------#
370         strRapport = str( self.jdc.report() )
371         self._viewText(strRapport, "JDC_RAPPORT")        
372         
373     #-----------------------#
374     def handleRenamed(self, fn):
375     #-----------------------#
376         """
377         Public slot to handle the editorRenamed signal.
378         
379         @param fn filename to be set for the editor (QString or string).
380         """
381         self.fileName = unicode(fn)
382         self.setCaption(self.fileName)
383         
384         if self.fileInfo is None:
385             self.fileInfo = QFileInfo(self.fileName)
386             self.fileInfo.setCaching(0)
387         
388         self.lastModified = self.fileInfo.lastModified()
389         self.vm.setEditorName(self, self.fileName)
390         self._updateReadOnly(1)        
391
392     #-----------------------#
393     def handleNewView(self):
394     #-----------------------#
395         """
396         Private slot to create a new view to an open document.
397         """
398         self.vm.newEditorView(self.fileName, self)#, self.isPythonFile)
399
400     #------------------------------------#
401     def handleModificationChanged(self, m):
402     #------------------------------------#
403         """
404         Private slot to handle the modificationChanged signal. 
405         
406         It emits the signal modificationStatusChanged with parameters
407         m and self.
408         
409         @param m modification status
410         """
411         if not m and self.fileInfo is not None:
412             self.lastModified = self.fileInfo.lastModified()
413         self.emit(PYSIGNAL('modificationStatusChanged'), (m, self))
414         
415     #------------------------#
416     def hasSyntaxErrors(self):        
417     #------------------------#
418         return False #CS_pbruno todo
419         
420     #----------------#
421     def closeIt(self):
422     #----------------#
423         """
424         Public method called by the viewmanager to finally get rid of us.
425         """
426
427         if self.jdc:
428             self.jdc.supprime()
429         self.close()
430     
431
432     #------------------------------#
433     def affiche_infos(self,message):
434     #------------------------------#
435         if self.salome :
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()
445         if self.sb:
446            self.sb.message(message)#,2000)
447
448     #------------------------------#
449     def updatePanel(self, jdcNode):
450     #------------------------------#
451         """
452         Appele a chaque changement de noeud
453         """
454         self.node_selected = jdcNode
455         if self.panel:
456             self.panel.close()
457             del self.panel
458             self.panel = None
459             
460         if jdcNode.item.isactif():
461             self.panel = jdcNode.getPanel()
462             #print self.panel.__class__
463         else:
464             self.panel = panelsQT.PanelInactif(self.node_selected,self)
465             
466         if not self.panel:
467             self.panel = panelsQT.NoPanel(self)
468         
469         self.panel.show()
470         
471     
472     #-------------------#
473     def init_modif(self):
474     #-------------------#
475       """
476           Met l'attribut modified a 'o' : utilise par Eficas pour savoir 
477           si un JDC doit etre sauvegarde avant destruction ou non
478       """
479       self.modified = True
480       self.emit(PYSIGNAL('modificationStatusChanged'), (True, self))
481     
482     #-------------------#
483     def stop_modif(self):
484     #-------------------#
485       """
486           Met l'attribut modified à 'n' : utilisé par Eficas pour savoir 
487           si un JDC doit etre sauvegardé avant destruction ou non
488       """      
489       self.modified = False
490       self.emit(PYSIGNAL('modificationStatusChanged'), (False, self))
491     
492     
493     #-------------------#
494     def cut(self):
495     #-------------------#
496       """
497       Stocke dans Eficas.noeud_a_editer le noeud à couper
498       """
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")          
502           return
503       self.parent.edit="couper"
504       self.parent.noeud_a_editer = self.node_selected      
505     
506     #-------------------#
507     def copy(self):
508     #-------------------#
509       """
510       Stocke dans Eficas.noeud_a_editer le noeud a copier
511       """
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")          
515           return
516       self.parent.edit="copier"
517       self.parent.noeud_a_editer = self.node_selected
518     
519     #-------------------#
520     def paste(self):
521     #-------------------#
522       """
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
525       """
526       try:
527          child=self.parent.noeud_a_editer.doPaste(self.node_selected)
528       except:
529          traceback.print_exc()
530          QMessageBox.information( self, "Copie impossible",         
531                                         "L'action de coller apres un tel objet n'est pas permise")
532          return
533     
534       if child == 0:
535           if self.message != '':             
536              QMessageBox.critical( self, "Copie refusee", self.message)
537              self.message = ''
538           self.affiche_infos("Copie refusée")
539           return
540     
541       # il faut declarer le JDCDisplay_courant modifie
542       self.init_modif()
543       # suppression eventuelle du noeud selectionne
544       # si possible on renomme l objet comme le noeud couper
545
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)
552          child.select()
553
554       # on rend la copie a nouveau possible en liberant le flag edit
555       self.parent.edit="copier"
556           
557     #---------------------#
558     def getFileName(self):
559     #---------------------#
560       return self.fileName
561       
562     #---------------------------#
563     def writeFile(self, fn, txt = None):
564     #------------------------------#
565         """
566         Public slot to write the text to a file.
567         
568         @param fn filename to write to (string or QString)
569         @return flag indicating success
570         """
571
572         fn = unicode(fn)
573
574         if txt == None :
575             txt = self.get_text_JDC(self.format_fichier)
576             eol = '\n'        
577             if len(txt) >= len(eol):
578                if txt[-len(eol):] != eol:
579                   txt += eol
580             else:
581                 txt += eol        
582
583         try:
584             f = open(fn, 'wb')
585             f.write(txt)
586             f.close()
587             return 1
588         except IOError, why:
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)))
592             return 0
593
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)
602
603
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")
617             return
618          else:
619             return jdc_formate
620       else:         
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)
624          return
625       
626       
627     #-------------------------------------------#
628     def saveFile(self, saveas = 0, path = None):
629     #-------------------------------------------#
630         """
631         Public slot to save the text to a file.
632         
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
637         """        
638         self.modified = True #CS_pbruno test
639                 
640         if not saveas and not self.modified:#self.isModified():
641             return (0, None)      # do nothing if text wasn't changed
642             
643         newName = None
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)
652                 
653             if not fn.isNull():
654                 ext = QFileInfo(fn).extension()
655                 if ext.isEmpty():
656                     ex = selectedFilter.section('(*',1,1).section(')',0,0)
657                     if not ex.isEmpty():
658                         fn.append(ex)
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.")
663                             .arg(fn),
664                         self.trUtf8("&Overwrite"),
665                         self.trUtf8("&Abort"), None, 1)
666                     if abort:
667                         return (0, None)
668                 fn = unicode(QDir.convertSeparators(fn))
669                 newName = fn
670             else:
671                 return (0, None)
672         else:
673             fn = self.fileName
674         
675         if self.writeFile(fn):
676             self.fileName = 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,))
687             self.stop_modif()            
688             if self.code == "OPENTURNS" :
689                self.writeFilesOpenturns(fn)
690             if self.salome : 
691                self.parent.appli.addJdcInSalome( self.fileName)
692                if self.code == 'ASTER':
693                   self.parent.appli.createOrUpdateMesh(self)
694                #PN ; TODO
695
696
697             return (1, self.fileName)
698         else:
699             return (0, None)
700
701     #---------------------------------#
702     def saveFileAs(self, path = None):
703     #---------------------------------#
704         """
705         Public slot to save a file with a new name.
706         
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
710         """
711         return self.saveFile(1, path)
712
713    
714 if __name__=='__main__':    
715     if hasattr(prefs,'encoding'):
716        # Hack pour changer le codage par defaut des strings
717        import sys
718        reload(sys)
719        sys.setdefaultencoding(prefs.encoding)
720        del sys.setdefaultencoding
721        # Fin hack
722
723     #CS_pbruno note: fait implicitement des trucs ces imports (grr)
724     import styles
725     import import_code
726     import session
727
728     # Analyse des arguments de la ligne de commande
729     options=session.parse(sys.argv)
730     code=options.code
731         
732     app = QApplication(sys.argv)    
733     mw = JDCEditor('azAster.comm')
734     app.setMainWidget(mw)
735     app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
736     mw.show()
737             
738     res = app.exec_loop()
739     sys.exit(res)
740