]> SALOME platform Git repositories - tools/eficas.git/blob - InterfaceQT/editor.py
Salome HOME
Modif V6_4_°
[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.17"
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         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.width() < 300:
141             sh.setWidth(300)
142         if sh.height() < 300:
143             sh.setHeight(300)
144         self.resize(sh)
145             
146         # Make sure tabbing through a QWorkspace works.
147         self.setFocusPolicy(QWidget.StrongFocus)
148         self._updateReadOnly(1)
149         
150         # Set the editors size if it is too big for the parent.
151         if parent is not None:
152             req = self.size()
153             bnd = req.boundedTo(parent.size())
154         
155             if bnd.width() < req.width() or bnd.height() < req.height():
156                 self.resize(bnd)
157         
158         self.panel = QWidget(self)        
159         #self.connect(self, SIGNAL('modificationChanged(bool)'), self.handleModificationChanged)
160                 
161         
162     #-------------------------------------------------------------------#
163     def _updateReadOnly(self, bForce=1):
164     #-------------------------------------------------------------------#
165         """
166         Private method to update the readOnly information for this editor. 
167         
168         If bForce is True, then updates everything regardless if
169         the attributes have actually changed, such as during
170         initialization time.  A signal is emitted after the
171         caption change.
172
173         @param bForce 1 to force change, 0 to only update and emit
174                 signal if there was an attribute change.
175         """
176
177         if self.fileName is None:
178             return
179         readOnly = not QFileInfo(self.fileName).isWritable() and 1 or 0
180         if not bForce and (readOnly == self.isReadOnly):
181             return
182         cap = self.fileName
183         if readOnly:
184             cap = "%s (ro)" % unicode(cap)
185         self.isReadOnly = readOnly
186         self.setCaption(cap)
187         self.emit(PYSIGNAL('captionChanged'), (cap, self))
188         
189     #--------------------------------#
190     def _newJDC( self ,units = None):        
191     #--------------------------------#
192         """
193         Initialise un nouveau JDC vierge
194         """
195         CONTEXT.unset_current_step()        
196         jdc=self.readercata.cata[0].JdC( procedure="",
197                                          appli=self,
198                                          cata=self.readercata.cata,
199                                          cata_ord_dico=self.readercata.cata_ordonne_dico,
200                                          rep_mat=self.CONFIGURATION.rep_mat
201                                         )                         
202         if units is not None:
203            jdc.recorded_units=units
204            jdc.old_recorded_units=units
205         jdc.analyse()        
206         return jdc
207         
208     #--------------------------------#
209     def _newJDCInclude( self ,units = None):        
210     #--------------------------------#
211         """
212         Initialise un nouveau JDC vierge
213         """
214         import Extensions.jdc_include
215         JdC_aux=Extensions.jdc_include.JdC_include
216         CONTEXT.unset_current_step()        
217
218         jaux=self.readercata.cata[0].JdC( procedure="",
219                                appli=self,
220                                cata=self.readercata.cata,
221                                cata_ord_dico=self.readercata.cata_ordonne_dico,
222                                rep_mat=self.CONFIGURATION.rep_mat,
223                               )
224         jaux.analyse()
225
226         J=JdC_aux( procedure="",
227                    appli=self,
228                    cata=self.readercata.cata,
229                    cata_ord_dico=self.readercata.cata_ordonne_dico,
230                    jdc_pere=jaux,
231                    rep_mat=self.CONFIGURATION.rep_mat,
232                    )
233         J.analyse()
234         if units is not None:
235            J.recorded_units=units
236            J.old_recorded_units=units
237         return J
238
239             
240     #-----------------------#
241     def get_source(self,file):
242     #-----------------------#
243         import convert
244         format=self.format_fichier
245
246         # Il faut convertir le contenu du fichier en fonction du format
247         if convert.plugins.has_key(format):
248             # Le convertisseur existe on l'utilise
249             p=convert.plugins[format]()
250             p.readfile(file)
251             text=p.convert('execnoparseur')
252             if not p.cr.estvide():
253                 self.affiche_infos("Erreur a la conversion")
254             return text
255         else:
256             # Il n'existe pas c'est une erreur
257             self.affiche_infos("Type de fichier non reconnu")
258             QMessageBox.critical( self, "Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")            
259             return None
260         
261     #---------------------------------------------#
262     def get_file(self,unite=None,fic_origine = ''):
263     #---------------------------------------------#
264         ulfile  = None
265         jdcText = ""
266       
267         titre  = ""
268         
269         if unite :
270             titre = "Choix unite %d " %unite
271             texte = "Le fichier %s contient une commande INCLUDE \n" % fic_origine
272             texte = texte+'Donnez le nom du fichier correspondant à l unité logique %d' % unite
273             labeltexte = 'Fichier pour unite %d :' % unite
274         else:
275             titre = "Choix d'un fichier de poursuite"
276             texte = "Le fichier %s contient une commande %s\n" %(fic_origine,'POURSUITE')
277             texte = texte+'Donnez le nom du fichier dont vous  voulez faire une poursuite'
278                                         
279         QMessageBox.information( self, titre,texte)
280         fn = QFileDialog.getOpenFileName( self.CONFIGURATION.savedir,"", self, titre, "" )
281         
282         if fn.isNull():
283             return
284             
285         ulfile = os.path.abspath(unicode(fn))
286         # On utilise le convertisseur défini par format_fichier
287         source=self.get_source(ulfile)
288         if source:
289             # On a réussi à convertir le fichier self.ulfile                
290             jdcText = source
291         else:
292             # Une erreur a été rencontrée
293             jdcText = ''
294         return ulfile, jdcText
295         
296         
297     #-----------------------#
298     def readFile(self, fn):
299     #-----------------------#
300         """
301         Public slot to read the text from a file.
302         
303         @param fn filename to read from (string or QString)
304         """        
305         fn = unicode(fn)        
306             
307         qApp.setOverrideCursor(Qt.waitCursor)
308                         
309         # ------------------------------------------------------------------------------------
310         #                         charge le JDC
311         # ------------------------------------------------------------------------------------      
312         
313         jdcName=os.path.basename(fn)
314         # Il faut convertir le contenu du fichier en fonction du format
315         if convert.plugins.has_key( self.format_fichier ):
316              # Le convertisseur existe on l'utilise
317              appli = self # CS_pbruno compatiblity parseur_python: self.appli.liste_simp_reel, self.appli.dict_reels
318              p=convert.plugins[self.format_fichier]()
319              p.readfile(fn)         
320              text=p.convert('exec',appli)
321              if not p.cr.estvide():                 
322                 self.affiche_infos("Erreur à la conversion")
323         
324         CONTEXT.unset_current_step()
325         ##   os.chdir(self.initialdir)
326         jdc=self.readercata.cata[0].JdC(procedure=text,
327                                     appli=self,
328                                     cata=self.readercata.cata,
329                                     cata_ord_dico=self.readercata.cata_ordonne_dico,
330                                     nom=jdcName,
331                                     rep_mat=self.CONFIGURATION.rep_mat
332                                    )
333         # ----------------------------------------------------
334         #      charge le JDC fin
335         # ----------------------------------------------------
336         self.modified = False
337                         
338         qApp.restoreOverrideCursor()        
339         if self.fileInfo!= None : 
340            self.lastModified = self.fileInfo.lastModified()
341         else :
342            self.lastModified = 1
343         return jdc
344         
345     #----------------------------------------------#
346     def _viewText(self, txt, caption = "FILE_VIEWER"):    
347     #----------------------------------------------#
348         w = qtCommun.ViewText( self.parent )
349         w.setCaption( caption )
350         w.setText(txt)
351         w.show()
352         
353     #-----------------------#
354     def viewJdcSource(self):        
355     #-----------------------#
356         format = self.format_fichier
357         f=open(self.fileName,'r')
358         texteSource=f.read()
359         f.close()
360         self._viewText(texteSource, "JDC_SOURCE")
361                 
362     #-----------------------#
363     def viewJdcPy(self):        
364     #-----------------------#
365         format = self.format_fichier
366         strSource = str( self.get_text_JDC(format) )       
367         self._viewText(strSource, "JDC_RESULTAT")
368                 
369     #-----------------------#
370     def viewJdcRapport(self):
371     #-----------------------#
372         strRapport = str( self.jdc.report() )
373         self._viewText(strRapport, "JDC_RAPPORT")        
374         
375     #-----------------------#
376     def handleRenamed(self, fn):
377     #-----------------------#
378         """
379         Public slot to handle the editorRenamed signal.
380         
381         @param fn filename to be set for the editor (QString or string).
382         """
383         self.fileName = unicode(fn)
384         self.setCaption(self.fileName)
385         
386         if self.fileInfo is None:
387             self.fileInfo = QFileInfo(self.fileName)
388             self.fileInfo.setCaching(0)
389         
390         self.lastModified = self.fileInfo.lastModified()
391         self.vm.setEditorName(self, self.fileName)
392         self._updateReadOnly(1)        
393
394     #-----------------------#
395     def handleNewView(self):
396     #-----------------------#
397         """
398         Private slot to create a new view to an open document.
399         """
400         self.vm.newEditorView(self.fileName, self)#, self.isPythonFile)
401
402     #------------------------------------#
403     def handleModificationChanged(self, m):
404     #------------------------------------#
405         """
406         Private slot to handle the modificationChanged signal. 
407         
408         It emits the signal modificationStatusChanged with parameters
409         m and self.
410         
411         @param m modification status
412         """
413         if not m and self.fileInfo is not None:
414             self.lastModified = self.fileInfo.lastModified()
415         self.emit(PYSIGNAL('modificationStatusChanged'), (m, self))
416         
417     #------------------------#
418     def hasSyntaxErrors(self):        
419     #------------------------#
420         return False #CS_pbruno todo
421         
422     #----------------#
423     def closeIt(self):
424     #----------------#
425         """
426         Public method called by the viewmanager to finally get rid of us.
427         """
428
429         if self.jdc:
430             self.jdc.supprime()
431         self.close()
432     
433
434     #------------------------------#
435     def affiche_infos(self,message):
436     #------------------------------#
437         if self.salome :
438            if not hasattr(self.appliEficas,'MessageLabel') :
439               self.appliEficas.leLayout=QDockWindow(self.appliEficas)
440               self.appliEficas.MessageLabel = QLabel(self.appliEficas.leLayout,"MessageLabel")
441               self.appliEficas.MessageLabel.setAlignment(Qt.AlignBottom)
442               self.appliEficas.leLayout.setWidget(self.appliEficas.MessageLabel)
443               self.appliEficas.moveDockWindow(self.appliEficas.leLayout,Qt.DockBottom)
444            self.appliEficas.MessageLabel.setText(message)
445            self.appliEficas.MessageLabel.show()
446            self.appliEficas.leLayout.show()
447         if self.sb:
448            self.sb.message(message)#,2000)
449
450     #------------------------------#
451     def updatePanel(self, jdcNode):
452     #------------------------------#
453         """
454         Appele a chaque changement de noeud
455         """
456         self.node_selected = jdcNode
457         if self.panel:
458             self.panel.close()
459             del self.panel
460             self.panel = None
461             
462         if jdcNode.item.isactif():
463             self.panel = jdcNode.getPanel()
464             #print self.panel.__class__
465         else:
466             self.panel = panelsQT.PanelInactif(self.node_selected,self)
467             
468         if not self.panel:
469             self.panel = panelsQT.NoPanel(self)
470         
471         self.panel.show()
472         
473     
474     #-------------------#
475     def init_modif(self):
476     #-------------------#
477       """
478           Met l'attribut modified a 'o' : utilise par Eficas pour savoir 
479           si un JDC doit etre sauvegarde avant destruction ou non
480       """
481       self.modified = True
482       self.emit(PYSIGNAL('modificationStatusChanged'), (True, self))
483     
484     #-------------------#
485     def stop_modif(self):
486     #-------------------#
487       """
488           Met l'attribut modified à 'n' : utilisé par Eficas pour savoir 
489           si un JDC doit etre sauvegardé avant destruction ou non
490       """      
491       self.modified = False
492       self.emit(PYSIGNAL('modificationStatusChanged'), (False, self))
493     
494     
495     #-------------------#
496     def cut(self):
497     #-------------------#
498       """
499       Stocke dans Eficas.noeud_a_editer le noeud à couper
500       """
501       if not self.node_selected.item.iscopiable():
502           QMessageBox.information( self, "Copie impossible",
503                 "Cette version d'EFICAS ne permet que la copie d'objets de type 'Commande' ou mot-clé facteur")          
504           return
505       self.parent.edit="couper"
506       self.parent.noeud_a_editer = self.node_selected      
507     
508     #-------------------#
509     def copy(self):
510     #-------------------#
511       """
512       Stocke dans Eficas.noeud_a_editer le noeud a copier
513       """
514       if not self.node_selected.item.iscopiable():
515           QMessageBox.information( self, "Copie impossible",
516                    "La copie d'un tel objet n'est pas permise")          
517           return
518       self.parent.edit="copier"
519       self.parent.noeud_a_editer = self.node_selected
520     
521     #-------------------#
522     def paste(self):
523     #-------------------#
524       """
525       Lance la copie de l'objet place dans self.parent.noeud_a_editer
526       Ne permet que la copie d'objets de type Commande ou MCF
527       """
528       try:
529          child=self.parent.noeud_a_editer.doPaste(self.node_selected)
530       except:
531          traceback.print_exc()
532          QMessageBox.information( self, "Copie impossible",         
533                                         "L'action de coller apres un tel objet n'est pas permise")
534          return
535     
536       if child == 0:
537           if self.message != '':             
538              QMessageBox.critical( self, "Copie refusee", self.message)
539              self.message = ''
540           self.affiche_infos("Copie refusée")
541           return
542     
543       # il faut declarer le JDCDisplay_courant modifie
544       self.init_modif()
545       # suppression eventuelle du noeud selectionne
546       # si possible on renomme l objet comme le noeud couper
547
548       if self.parent.edit == "couper":
549          #nom = self.parent.noeud_a_editer.item.object.sd.nom
550          item=self.parent.noeud_a_editer.item
551          self.parent.noeud_a_editer.delete()
552          child.item.update(item)
553          #test,mess = child.item.nomme_sd(nom)
554          child.select()
555
556       # on rend la copie a nouveau possible en liberant le flag edit
557       self.parent.edit="copier"
558           
559     #---------------------#
560     def getFileName(self):
561     #---------------------#
562       return self.fileName
563       
564     #---------------------------#
565     def writeFile(self, fn, txt = None):
566     #------------------------------#
567         """
568         Public slot to write the text to a file.
569         
570         @param fn filename to write to (string or QString)
571         @return flag indicating success
572         """
573
574         fn = unicode(fn)
575
576         if txt == None :
577             txt = self.get_text_JDC(self.format_fichier)
578             eol = '\n'        
579             if len(txt) >= len(eol):
580                if txt[-len(eol):] != eol:
581                   txt += eol
582             else:
583                 txt += eol        
584
585         try:
586             f = open(fn, 'wb')
587             f.write(txt)
588             f.close()
589             return 1
590         except IOError, why:
591             QMessageBox.critical(self, self.trUtf8('Save File'),
592                 self.trUtf8('The file <b>%1</b> could not be saved.<br>Reason: %2')
593                     .arg(unicode(fn)).arg(str(why)))
594             return 0
595
596     #------------------------------------ 
597     def writeFilesOpenturns(self,fn) :
598     #------------------------------------ 
599         base=fn[:fn.rfind(".")]
600         fileXML=base + '.xml'
601         fileSTD=base + '_std.py'
602         self.writeFile(fileXML,self.jdc_openturn_xml)
603         self.writeFile(fileSTD,self.jdc_openturn_std)
604
605
606     #-----------------------------#
607     def get_text_JDC(self,format):
608     #-----------------------------#
609       if generator.plugins.has_key(format):
610          # Le generateur existe on l'utilise
611          g=generator.plugins[format]()
612          jdc_formate=g.gener(self.jdc,format='beautifie')
613          if format == "openturns" :
614             self.jdc_openturn_xml=g.getOpenturnsXML()
615             self.jdc_openturn_std=g.getOpenturnsSTD()
616          if not g.cr.estvide():            
617             self.affiche_infos("Erreur à la generation")
618             QMessageBox.critical( self, "Erreur a la generation","EFICAS ne sait pas convertir ce JDC")
619             return
620          else:
621             return jdc_formate
622       else:         
623          # Il n'existe pas c'est une erreur
624          self.affiche_infos("Format %s non reconnu" % format)
625          QMessageBox.critical( self, "Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
626          return
627       
628       
629     #-------------------------------------------#
630     def saveFile(self, saveas = 0, path = None):
631     #-------------------------------------------#
632         """
633         Public slot to save the text to a file.
634         
635         @param saveas flag indicating a 'save as' action
636         @param path directory to save the file in (string or QString)
637         @return tuple of two values (boolean, string) giving a success indicator and
638             the name of the saved file
639         """        
640         self.modified = True #CS_pbruno test
641                 
642         if not saveas and not self.modified:#self.isModified():
643             return (0, None)      # do nothing if text wasn't changed
644             
645         newName = None
646         if saveas or self.fileName is None:
647             if path is None and self.fileName is not None:
648                 path = os.path.dirname(unicode(self.fileName))
649             else :
650                 path=self.CONFIGURATION.savedir
651             fn = QFileDialog.getSaveFileName(path,
652                 self.trUtf8("JDC (*.comm);;" "All Files (*)"),self, None,
653                 self.trUtf8("Save File"), '', 0)
654
655             if not fn.isNull():
656                 ext = QFileInfo(fn).extension()
657                 if ext.isEmpty():
658                     ex =  ".comm"
659                     fn.append(ex)
660                 if QFileInfo(fn).exists():
661                     abort = QMessageBox.warning(
662                         self,
663                         self.trUtf8("Sauvegarde Fichier"),
664                         self.trUtf8("Le fichier <b>%1</b> existe deja.").arg(fn),
665                         self.trUtf8("&Remplacer"),
666                         self.trUtf8("&Abandonner") )
667                     print abort
668                     if abort:
669                         return (0, None)
670                 fn = unicode(QDir.convertSeparators(fn))
671                 newName = fn
672             else:
673                 return (0, None)
674         else:
675             fn = self.fileName
676         
677         if self.writeFile(fn):
678             self.fileName = fn
679             self.modified  = False                        
680             self.setCaption(self.fileName)                
681             if self.fileInfo is None or saveas:
682                 self.fileInfo = QFileInfo(self.fileName)
683                 self.fileInfo.setCaching(0)
684                 self.emit(PYSIGNAL('editorRenamed'), (self.fileName,))
685             self.lastModified = self.fileInfo.lastModified()
686             if newName is not None:
687                 self.vm.addToRecentList(newName)
688             self.emit(PYSIGNAL('editorSaved'), (self.fileName,))
689             self.stop_modif()            
690             if self.code == "OPENTURNS" :
691                self.writeFilesOpenturns(fn)
692             if self.salome : 
693                self.parent.appli.addJdcInSalome( self.fileName)
694                if self.code == 'ASTER':
695                   self.parent.appli.createOrUpdateMesh(self)
696                #PN ; TODO
697
698
699             return (1, self.fileName)
700         else:
701             return (0, None)
702
703     #---------------------------------#
704     def saveFileAs(self, path = None):
705     #---------------------------------#
706         """
707         Public slot to save a file with a new name.
708         
709         @param path directory to save the file in (string or QString)
710         @return tuple of two values (boolean, string) giving a success indicator and
711             the name of the saved file
712         """
713         return self.saveFile(1, path)
714
715    
716 if __name__=='__main__':    
717     if hasattr(prefs,'encoding'):
718        # Hack pour changer le codage par defaut des strings
719        import sys
720        reload(sys)
721        sys.setdefaultencoding(prefs.encoding)
722        del sys.setdefaultencoding
723        # Fin hack
724
725     #CS_pbruno note: fait implicitement des trucs ces imports (grr)
726     import styles
727     import import_code
728     import session
729
730     # Analyse des arguments de la ligne de commande
731     options=session.parse(sys.argv)
732     code=options.code
733         
734     app = QApplication(sys.argv)    
735     mw = JDCEditor('azAster.comm')
736     app.setMainWidget(mw)
737     app.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
738     mw.show()
739             
740     res = app.exec_loop()
741     sys.exit(res)
742