1 # -*- coding: utf-8 -*-
2 # CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
20 # ======================================================================
21 # ----------------------------------------------------------
22 # Cette classe sert à définir les widgets utilisés par
24 # ----------------------------------------------------------
29 import os,sys,re,string
32 from tkFileDialog import *
33 from tkMessageBox import showinfo,askyesno,showerror,askretrycancel
37 from Editeur.utils import save_in_file
38 from centerwindow import centerwindow
40 from Noyau.N_utils import repr_float
41 from Accas import AsException
43 # Surcharge de la fonction askyesno qui retourne un resultat errone en Python 2.3 avec Tk 8.4
44 # et Tkinter.wantobject==1
46 def askyesno(title=None, message=None, **options):
47 "Ask a question; return true if the answer is yes"
48 s = tkMessageBox._show(title, message, tkMessageBox.QUESTION, tkMessageBox.YESNO, **options)
49 if s == tkMessageBox.YES:return 1
50 if s == tkMessageBox.NO:return 0
56 """ Cette classe permet de créer une fenêtre Toplevel dans laquelle
57 on peut afficher un texte et qui permet de le sauver"""
58 def __init__(self,appli,titre="",texte="",wrap=WORD,width=100,height=30):
60 if self.appli.test==1 : return
61 self.fenetre = Toplevel()
62 self.fenetre.withdraw()
63 #self.fenetre.configure(width = 800,height=500)
64 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
65 self.fenetre.title("Visualisation du "+titre)
66 self.texte = string.replace(texte,'\r\n','\n')
68 fonte=fontes.standardcourier10
69 # définition des frames
70 self.frame_texte = Frame(self.fenetre)
71 self.frame_boutons = Frame(self.fenetre)
72 # définition de la zone texte et du scrollbar
73 self.zone_texte = Text(self.frame_texte,font=fonte,wrap=wrap,
74 height=height,width=width)
75 self.zone_texte.bind("<Key-Prior>", self.page_up)
76 self.zone_texte.bind("<Key-Next>", self.page_down)
77 self.zone_texte.bind("<Key-Up>", self.unit_up)
78 self.zone_texte.bind("<Key-Down>", self.unit_down)
79 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
80 #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
81 self.scroll_v.pack(side='right',fill ='y')
82 #self.scroll_h.pack(side='bottom',fill ='x')
83 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
84 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
85 # définition des boutons
86 self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit,
88 self.but_save = Button(self.frame_boutons,text = "Sauver",command = self.save)
89 self.but_quit.pack(side='left',padx=25, pady=5)
90 self.but_save.pack(side='right',padx=25, pady=5)
91 self.frame_boutons.pack(side='bottom',padx=5,pady=5)
92 self.frame_texte.pack(side='top',fill='both',expand=1,padx=5,pady=5)
93 self.zone_texte.focus_set()
94 self.fenetre.bind('<Return>',self.quit) #dismiss window
97 self.affiche_texte(self.texte)
98 self.zone_texte.config(state=DISABLED)
99 centerwindow(self.fenetre)
100 self.fenetre.deiconify()
102 def page_up(self,event):
103 event.widget.yview_scroll(-1, "page")
104 return "break" #Pour eviter la propagation de l'evenement a la fenetre principale
105 def page_down(self,event):
106 event.widget.yview_scroll(1, "page")
107 return "break" #Pour eviter la propagation de l'evenement a la fenetre principale
108 def unit_up(self,event):
109 event.widget.yview_scroll(-1, "unit")
110 return "break" #Pour eviter la propagation de l'evenement a la fenetre principale
111 def unit_down(self,event):
112 event.widget.yview_scroll(1, "unit")
113 return "break" #Pour eviter la propagation de l'evenement a la fenetre principale
116 self.fenetre.grab_set()
117 self.zone_texte.focus_set()
118 self.fenetre.wait_window(self.fenetre)
120 def quit(self,event=None):
121 self.fenetre.destroy()
122 return "break" #Pour eviter la propagation de l'evenement a la fenetre principale
124 def efface_scroll(self):
125 """ Efface le scroll lorsqu'il n'est pas nécessaire : ne marche pas"""
126 self.scroll_v.pack_forget()
127 #self.scroll_h.pack_forget()
129 def affiche_texte(self,texte):
130 """ Affiche le texte dans la fenêtre """
132 self.zone_texte.insert(END,texte)
133 self.fenetre.update_idletasks()
134 curline = int(self.zone_texte.index("insert").split('.')[0])
135 if curline < int(self.zone_texte["height"]):
139 """ Permet de sauvegarder le texte dans un fichier dont on a demandé le nom
141 file = asksaveasfilename(parent=self.fenetre,defaultextension = '.comm',
142 #initialdir = self.appli.CONFIGURATION.rep_user,
143 initialdir = self.appli.CONFIGURATION.savedir,
144 title="Sauvegarde du "+self.titre)
146 if not save_in_file(file,self.texte,None) :
147 showerror("Sauvegarde impossible",
148 "Impossible de sauvegarder le texte dans le fichier spécifié\n"+
149 "Vérifiez les droits d'écriture",parent=self.fenetre)
151 showinfo("Sauvegarde effectuée","Sauvegarde effectuée dans le fichier %s" %file,parent=self.fenetre)
155 self.fenetre.destroy()
159 class FenetreSurLigneWarning(Fenetre):
161 def affiche_texte(self,texte):
162 """ Affiche le texte dans la fenêtre """
165 texte_cr=texte.splitlines()
169 self.zone_texte.insert(END,l)
170 if (l.find("WARNING") > -1) or (l.find("ERROR") > -1) :
171 self.zone_texte.tag_add( "Rouge", str(ligne)+".0", "end-1c" )
172 self.zone_texte.tag_config("Rouge", foreground='red')
174 self.fenetre.update_idletasks()
175 x0,y0,x1,y1 = self.zone_texte.bbox(END)
176 if (y1-y0) < 300 : self.efface_scroll()
180 class FenetreYesNo(Fenetre):
181 def __init__(self,appli,titre="",texte="",yes="Yes",no="No"):
183 self.fenetre = Toplevel()
184 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
185 self.fenetre.title(titre)
186 self.texte = string.replace(texte,'\r\n','\n')
188 fonte=fontes.standardcourier10
189 # définition des frames
190 self.frame_texte = Frame(self.fenetre)
191 self.frame_boutons = Frame(self.fenetre)
192 # définition de la zone texte et du scrollbar
193 self.zone_texte = Text(self.frame_texte,font=fonte)
194 self.zone_texte.bind("<Key-Prior>", self.page_up)
195 self.zone_texte.bind("<Key-Next>", self.page_down)
196 self.zone_texte.bind("<Key-Up>", self.unit_up)
197 self.zone_texte.bind("<Key-Down>", self.unit_down)
198 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
199 #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
200 self.scroll_v.pack(side='right',fill ='y')
201 #self.scroll_h.pack(side='bottom',fill ='x')
202 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
203 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
204 # définition des boutons
205 self.but_yes = Button(self.frame_boutons,text = yes,command=self.yes)
206 self.but_no = Button(self.frame_boutons,text = no,command = self.no)
207 self.but_yes.pack(side="left",padx=5,pady=5)
208 self.but_no.pack(side="left",padx=5,pady=5)
209 self.frame_boutons.pack(side="top",padx=5,pady=5)
211 self.affiche_texte(self.texte)
212 self.frame_texte.pack(side="top",fill='both',padx=5,pady=5,expand=1)
213 centerwindow(self.fenetre)
223 class FenetreDeSelection(Fenetre):
224 """ Classe dérivée de Fenêtre permettant la récupération d'une zone de texte sélectionnée.
225 Cette classe est utilisée pour affecter une liste de valeurs à un mot-clé.
227 def __init__(self,panel,item,appli,titre="",texte="",cardinal=1):
228 Fenetre.__init__(self,appli,titre=titre,texte=texte,width=20,height=15)
230 self.cardinal=cardinal
231 #self.fenetre.configure(width = 320,height=400)
234 self.fenetre.title(titre)
235 self.but_save.configure(text="Ajouter",command=self.traite_selection)
236 # séparateur par défaut
237 self.separateur = ';'
238 # création de la zone de saisie du séparateur
239 l_separateurs_autorises = self.get_separateurs_autorises()
240 self.choix_sep = Pmw.ComboBox(self.frame_boutons,
241 label_text = "Séparateur :",
244 selectioncommand = self.choose_separateur,
245 scrolledlist_items = l_separateurs_autorises)
246 self.choix_sep.component('entry').configure(width=6)
247 self.choix_sep.grid(row=0,rowspan=2,padx=5,pady=5)
248 #self.choix_sep.selectitem(self.separateur)
250 self.but_quit.pack_forget()
251 self.but_save.pack_forget()
252 self.but_all = Button(self.frame_boutons,text = "Tout Sélectionner", command=self.tout)
253 self.but_save.grid(row=1,column=1,padx=5,pady=5)
254 self.but_quit.grid(row=1,column=2,padx=5,pady=5)
255 self.but_all.grid(row=0,column=1,columnspan=2,padx=5,pady=5)
256 self.choose_separateur('espace')
257 centerwindow(self.fenetre)
260 def get_separateurs_autorises(self):
262 Retourne la liste des séparateurs autorisés
264 return ['espace',';',',']
266 def choose_separateur(self,nom_sep):
268 Affecte à self.separateur le caractère séparateur correspondant à nom_sep
270 if nom_sep == 'espace' :
271 self.separateur = ' '
273 self.separateur = nom_sep
277 texte=self.texte.splitlines()
279 for mot in string.split(l,self.separateur):
280 if mot != '' and mot != ' ' and mot != self.separateur :
282 self.traite_selection(liste)
284 def traite_selection(self,liste=None):
285 """ Cette méthode effectue tous les traitements nécessaires pour vérifier
286 et affecter la liste de valeurs à l'objet réprésenté par self.item
288 # Récupère la liste des chaines de caractères de la zone sélectionnée
291 message,liste = self.recupere_liste()
292 if self.test_probleme(message,"Sélectionnez des données") == 0:
294 # Vérifie que le nombre de données est dans les limites attendues
295 message = self.verif_liste(liste)
296 if self.test_probleme(message,"Vérifiez le nombre de données") == 0:
298 # Crée une liste de valeurs du type attendu
299 message,liste_valeurs = self.creation_liste_valeurs(liste)
300 if self.test_probleme(message,"Vérifiez le type des données") == 0:
302 # Vérifie que chaque valeur est dans le domaine exigé
303 message = self.verif_valeurs(liste_valeurs)
304 if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:
306 # Ajoute les valeurs dans la liste de valeurs du mot-clé
307 if self.cardinal != 1 :
311 if (len(liste_valeurs)%nb != 0):
312 message="La cardinalité n'est pas correcte"
313 self.test_probleme(message,"On attend des tuples")
315 for i in range(len(liste_valeurs)/nb) :
317 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1])
319 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1], liste_valeurs[i*nb+2])
321 print "probleme : prevenir la maintenance Eficas"
324 liste_valeurs=l_valeurs
325 self.ajouter_valeurs(liste_valeurs)
326 self.appli.affiche_infos("Liste de valeurs acceptée")
328 def test_probleme(self, message, message_eficas):
329 """ Cette méthode affiche un message d'erreur si message != ''
330 et retourne 0, sinon retourne 1 sans rien afficher.
333 showinfo("Problème",message,parent=self.fenetre)
334 self.fenetre.tkraise()
335 self.appli.affiche_infos(message_eficas)
340 def recupere_liste(self):
341 """ Cette méthode récupère le texte de la zone sélectionnée, construit et
342 retourne une liste avec les chaines qui se trouvent entre les séparateurs.
343 S'il n'y a pas de données selectionnées, elle retourne un message d'erreur
348 selection=self.fenetre.selection_get()
350 message = "Pas de donnée sélectionnée"
352 # les retours chariots doivent être interprétés comme des séparateurs
353 selection = string.replace(selection,'\n',self.separateur)
354 # on splitte la sélection suivant le caractère séparateur
355 liste_chaines = string.split(selection,self.separateur)
357 for chaine in liste_chaines:
358 chaine = string.strip(chaine)
359 if chaine != '' : l_chaines.append(chaine)
360 return message,l_chaines
362 def verif_liste(self, liste):
363 """ Cette méthode effectue des tests sur le nombre d'éléments de la liste
364 et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur
368 # nombre d'éléments sélectionnés
369 nombre_elements = len(liste)
370 # nombre d'éléments déja dans la liste du panel
371 nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())
372 multiplicite = self.item.GetMultiplicite()
373 if (nombre_elements % multiplicite) != 0:
374 message = "Vous devez sélectionner "+str(multiplicite)+" * n données"
376 nombre_valeurs = nombre_elements / multiplicite
377 cardinalite = self.item.GetMinMax()
378 if nombre_valeurs < cardinalite[0]:
379 message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"
381 if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):
382 message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"
387 def creation_liste_valeurs(self, liste):
388 """ Cette méthode crée et retourne une liste de valeurs du type attendu
389 par le mot-clé. La liste de valeurs est créée à partir de la liste
390 de chaines de caractères transmise.
392 type_attendu = self.item.GetType()[0]
393 if type_attendu == 'R':
394 return self.convertir(liste, f_conversion= float)
395 elif type_attendu == 'I':
396 return self.convertir(liste, f_conversion= int)
397 elif type_attendu == 'TXM':
398 return self.convertir(liste)
400 message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"
403 def convertir(self, liste, f_conversion=None):
404 """ Cette méthode essaie de convertir les éléments de la liste avec la
405 fonction f_conversion si elle existe, et retourne la liste des
406 éléments dans le type voulu en cas de succès, sinon retourne None.
413 liste_valeurs.append(f_conversion(chaine))
415 message = "Impossible de convertir "+chaine+" dans le type attendu"
418 liste_valeurs.append(chaine)
419 return message,liste_valeurs
421 def verif_valeurs(self, liste_valeurs):
422 """ Cette méthode teste la validité de tous les éléments de la liste,
423 retourne un message vide s'ils sont valides
424 ou un message non vide au premier élément non valide rencontré
427 for valeur in liste_valeurs:
428 test,message = self.item.object.verif_type(valeur)
429 if test == 0: return message
432 def ajouter_valeurs(self, liste_valeurs):
433 """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""
434 liste = self.panel.Liste_valeurs.get_liste()
435 liste.extend(liste_valeurs)
436 self.panel.Liste_valeurs.put_liste(liste)
438 class FenetreDeParametre(Fenetre) :
439 def __init__(self,parent,item,appli,texte):
442 self.fenetre = Toplevel()
443 #self.fenetre.configure(width = 250,height=100)
444 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
445 self.fenetre.title("Parametres")
446 self.titre = "Parametres"
447 self.texte = string.replace(texte,'\r\n','\n')
448 fonte=fontes.standardcourier10
450 # définition des frames
451 self.frame_texte = Frame(self.fenetre)
452 # définition de la zone texte et du scrollbar
453 self.zone_texte = Text(self.frame_texte,font=fonte,width=40)
454 self.zone_texte.bind("<Key-Prior>", self.page_up)
455 self.zone_texte.bind("<Key-Next>", self.page_down)
456 self.zone_texte.bind("<Key-Up>", self.unit_up)
457 self.zone_texte.bind("<Key-Down>", self.unit_down)
458 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
459 self.scroll_v.pack(side='right',fill ='y')
460 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
461 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
463 self.affiche_texte(self.texte)
464 self.zone_texte.config(state="disabled")
466 # définition des boutons
467 self.frame_boutons = Frame(self.fenetre)
468 self.label1 = Label(self.frame_boutons,text="surligner la\nligne entière",justify=LEFT)
469 self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
470 self.but_save = Button(self.frame_boutons,text = "Choisir",command = self.Choisir)
471 self.but_quit.pack(side='right',padx=5, pady=5)
472 self.but_save.pack(side='right',padx=5, pady=5)
473 self.label1.pack(side='right',padx=5, pady=5)
474 self.frame_boutons.pack(side='bottom')
475 self.frame_texte.pack(side='top',expand=1,fill='both')
480 selection=self.zone_texte.selection_get()
482 showerror("Pas de donnée sélectionnée",
483 "Selectionner un parametre")
485 for param in selection.splitlines():
486 nomparam=param[0:param.find("=")-1]
488 l_param=l_param+nomparam+','
489 self.parent.entry.delete(0,Tkinter.END)
490 self.parent.entry.insert(0,l_param[0:-1])
491 self.parent.valid_valeur()
494 def affiche_texte(self,texte):
495 """ Affiche le texte dans la fenêtre """
497 self.zone_texte.insert(END,texte)
498 self.fenetre.update_idletasks()
499 curline = int(self.zone_texte.index("insert").split('.')[0])
500 if curline < int(self.zone_texte["height"]):
501 self.zone_texte["height"]=curline
506 Cette classe permet de créer une boîte Dialog dans laquelle
507 on affiche un formulaire à remplir par l'utilisateur
509 def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
511 if items in ((),[]) : return
515 self.fen_pere = fen_pere
516 self.obj_pere = obj_pere
518 self.command = commande
522 self.init_validateurs()
525 self.init_items_formulaire()
526 self.fenetre.activate(geometry='centerscreenalways')
528 def init_validateurs(self):
530 Crée le dictionnaire des validateurs des objets reconnus par le formulaire
532 self.d_validateurs = {}
533 self.d_validateurs['rep'] = self.repvalidator
534 self.d_validateurs['file'] = self.filevalidator
535 self.d_validateurs['cata']= self.catavalidator
536 self.d_validateurs['mot']= self.motvalidator
537 self.d_validateurs['mot2']= self.mot2validator
538 self.d_validateurs['mot3']= self.mot3validator
539 self.d_validateurs['mot4']= self.mot4validator
541 def init_fenetre(self):
543 Crée la fenêtre Dialog
545 if self.mode == 'query':
546 buttons=('Valider','Annuler')
547 defaultbutton = 'Valider'
548 elif self.mode == 'display':
550 buttons=(self.command[0],'OK')
555 self.fenetre = Pmw.Dialog(self.fen_pere,
557 defaultbutton = defaultbutton,
559 command = self.execute)
560 self.fenetre.withdraw()
562 def init_texte(self):
564 Crée le label qui affiche le texte à l'intérieur du panneau
566 fonte=fontes.standard
567 fr_texte = Frame(self.fenetre.interior(),height=60)
568 fr_texte.pack(side='top',fill='x',expand=1)
569 Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
571 def init_items_formulaire(self):
573 Crée et affiche les items dans la boîte de dialogue
577 self.item_widgets = {}
579 for item in self.items:
580 if len(item[0])>length_maxi : length_maxi = len(item[0])
581 window = self.fenetre.interior()
582 for item in self.items :
584 label,nature,nom_var,defaut = item
588 label,nature,nom_var,defaut,chaine,chaine2 = item
590 # création de la frame
591 fr_item = Frame(window,height=40,width=700)
592 fr_item.pack(side='top',fill='x',expand=1)
594 Label(fr_item,text = label).place(relx=0.05,rely=0.4)
595 if nature in ('rep','file','cata','mot','mot2','mot3','mot4'):
596 # création de l'entry
597 e_item = Entry(fr_item)
598 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
599 self.widgets.append(e_item)
600 self.item_widgets[item] = e_item
601 if defaut : e_item.insert(0,str(defaut))
602 elif nature == 'YesNo':
603 # création de la StringVar
605 setattr(self,'item_'+nom_var,var)
607 # création du radiobouton
608 rb1 = Radiobutton(fr_item,text=chaine,variable=var,value='OUI')
609 rb2 = Radiobutton(fr_item,text=chaine2,variable=var,value='NON')
610 rb1.place(relx=0.65,rely=0.5,anchor='center')
611 rb2.place(relx=0.80,rely=0.5,anchor='center')
612 self.widgets.append((rb1,rb2))
613 self.item_widgets[item] = var
614 # détermination de la méthode à appliquer sur les boutons
615 if self.mode == 'query':
616 function = self.active
617 elif self.mode == 'display':
618 function = self.inactive
621 # on applique la méthode sur les boutons (activation ou désactivation)
622 for widget in self.widgets :
623 if type(widget) == types.TupleType:
625 apply(function,(widg,),{})
627 apply(function,(widget,),{})
629 def active(self,widget):
631 Active le widget passé en argument
633 widget.configure(state='normal',bg='white')
635 def inactive(self,widget):
637 Inactive le widget passé en argument
639 if not isinstance(widget,Radiobutton) :
640 widget.configure(state='disabled',bg='gray95')
642 widget.configure(state='disabled')
644 # --------------------------------------------------------------------------------
645 # Validateurs des noms de répertoire, de fichiers et de catalogues
646 # -------------------------------------------------------------------------------
648 def motvalidator(self,text):
650 return self.motlongueurvalidator(text2,1)
652 def mot2validator(self,text):
653 return self.motlongueurvalidator(text,2)
655 def mot3validator(self,text):
656 return self.motlongueurvalidator(text,3)
658 def mot4validator(self,text):
659 return self.motlongueurvalidator(text,4)
661 def motlongueurvalidator(self,text,longueur):
663 if ((text[0] != "(") or (text[-1] != ")")) : return 0
664 if len(text.split(",")) != longueur : return 0
669 def repvalidator(self,text):
671 Teste si text peut faire référence à un répertoire ou non
672 Retourne 1 si valide, 0 sinon
674 return os.path.isdir(text),'Répertoire introuvable : %s' %text
676 def filevalidator(self,text):
678 Teste si text peut faire référence à un fichier ou non
679 Retourne 1 si valide, 0 sinon
681 return os.path.isfile(text),'Fichier introuvable : %s' %text
683 def catavalidator(self,text):
685 Teste si text est un chemin d'accès valide à un catalogue
686 Retourne 1 si valide, 0 sinon
688 return os.path.isfile(text),"Catalogue introuvable : %s" %text
690 # --------------------------------------------------------------------------------
691 # Méthodes callbacks des boutons et de fin
692 # --------------------------------------------------------------------------------
694 def execute(self,txt):
696 Cette commande est activée à chaque clic sur un bouton.
697 Redirige l'action sur la bonne méthode en fonction du bouton activé
701 elif txt in ('OK','Annuler'):
703 elif txt == 'Modifier':
704 self.resultat = apply(self.command[1],(),{})
705 self.fenetre.destroy()
711 Commande qui termine le panneau et sauvegarde les nouvelles options
712 dans l'objet resultat (dictionnaire)
715 for item,widget in self.item_widgets.items():
718 valeur = widget.get()
719 if self.d_validateurs.has_key(type_var):
720 test = self.d_validateurs[type_var](valeur)
722 # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
723 # sans tuer la fenêtre bien sûr
724 widget.selection_range(0,END)
726 dico[nom_var] = valeur
727 self.fenetre.destroy()
731 self.fenetre.destroy()
735 """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
736 en passant les commandes à lancer suivant différents bindings """
737 def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre='',
738 optionReturn=None, fonte_titre=fontes.standard_gras_souligne):
747 self.selection = None
748 self.liste_commandes = liste_commandes
749 self.liste_marques = liste_marques
754 self.optionReturn = optionReturn
755 self.fonte_titre=fonte_titre
759 self.make_label_titre()
760 self.make_entry_filtre()
763 self.entry.component('entry').focus()
767 def make_label_titre(self):
768 """ Crée le label correspondant au titre """
769 if self.titre == '' : return
770 self.label = Label(self.page,
772 font = self.fonte_titre)
773 self.label.pack(side='top',pady=2)
775 def make_entry_filtre(self):
776 """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
777 if self.filtre != 'oui' : return
778 self.entry = Pmw.EntryField(self.page,labelpos='w',
779 label_text="Filtre :",
780 command=self.entry_changed)
781 self.entry.pack(side='top',pady=2)
783 def make_text_box(self):
784 """ Crée la fenêtre texte dans laquelle sera affichée la liste """
785 self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
786 self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
787 self.MCscroll.pack(side='right',fill ='y',pady=2)
788 self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
789 self.MCbox.configure(yscrollcommand=self.MCscroll.set)
792 def affiche_liste(self):
793 """ Affiche la liste dans la fenêtre"""
795 self.MCbox.config(state=NORMAL)
796 self.MCbox.delete(1.0,END)
799 for objet in self.liste :
800 if type(objet) == types.InstanceType:
805 elif type(objet) in (types.StringType,types.IntType):
807 elif type(objet) == types.FloatType :
808 mot = self.parent.get_valeur_texte(objet)
811 elif type(objet) == types.TupleType :
819 valtexte = self.parent.get_valeur_texte(val)
825 elif string.find(str(type(objet)),".SD.") :
829 label = Label(self.MCbox,
831 fg = 'black',bg = 'gray95',justify = 'left')
832 self.dico_labels[mot]=label
833 self.dico_place[mot]=self.nBlabel
834 self.dico_mots[label]=mot
835 self.nBlabel=self.nBlabel+1
836 liste_labels.append(label)
837 self.MCbox.window_create(END,
840 self.MCbox.insert(END,'\n')
841 if self.optionReturn != None :
842 label.bind("<Return>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
843 label.bind("<KP_Enter>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
844 label.bind("<Key-Right>",lambda e,s=self,x=objet,l=label : s.selectNextItem(x,l))
845 label.bind("<Key-Down>",lambda e, s=self,x=objet,l=label : s.selectNextItem(x,l))
846 label.bind("<Key-Left>" ,lambda e,s=self,x=objet,l=label : s.selectPrevItem(x,l))
847 label.bind("<Key-Up>" ,lambda e,s=self,x=objet,l=label : s.selectPrevItem(x,l))
848 if self.active == 'oui':
849 label.bind(self.liste_commandes[0][0],lambda e,s=self,c=self.liste_commandes[0][1],x=objet,l=label : s.selectitem(x,l,c))
850 label.bind(self.liste_commandes[1][0],lambda e,s=self,c=self.liste_commandes[1][1],x=objet,l=label : s.deselectitem(l,x,c))
851 label.bind(self.liste_commandes[2][0],lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitem(x,l,c))
853 for marque in self.liste_marques:
855 self.markitem(liste_labels[marque])
859 self.MCbox.config(state=DISABLED)
860 self.selection = None
862 for event,callback in self.liste_commandes:
863 if event == "<Enter>":
864 self.selection=None,None,callback
867 def clear_marque(self):
869 self.dico_labels[self.arg_selected].configure(bg='gray95',fg='black')
870 self.arg_selected = ''
874 def surligne(self,marque):
876 self.highlightitem(self.dico_labels[marque])
877 self.arg_selected = marque
881 def chooseitemsurligne(self,mot,label,commande):
882 """ Active la méthode de choix passée en argument"""
884 mot=self.arg_selected
886 except AsException,e:
888 showerror(raison.split('\n')[0],raison)
890 def chooseitem(self,mot,label,commande):
891 """ Active la méthode de choix passée en argument"""
894 except AsException,e:
896 showerror(raison.split('\n')[0],raison)
898 def afficheMot(self,mot):
899 """ Pour contourner le bug sur l index
900 on commence par la methode dite normale
901 puis par la methode de contournement
905 labelsuivant=self.dico_labels[mot]
906 index = self.MCbox.index(labelsuivant)
907 self.MCbox.see(index)
909 posmot=self.dico_place[mot]
910 totale=self.nBlabel + 0.0
911 self.MCbox.yview_moveto(posmot/totale)
913 def selectNextItem(self,mot,label):
914 index=self.liste.index(mot)
916 if indexsuivant > len(self.liste) -1:
918 motsuivant=self.liste[indexsuivant]
919 labelsuivant=self.dico_labels[motsuivant]
920 self.afficheMot(motsuivant)
921 self.selectthis(motsuivant,labelsuivant,self.selection[2],)
924 def selectPrevItem(self,mot,label):
925 index=self.liste.index(mot)
927 motprec=self.liste[indexprec]
928 labelprec=self.dico_labels[motprec]
929 self.afficheMot(motprec)
930 self.selectthis(motprec,labelprec,self.selection[2],)
933 def selectthis(self,mot,label,commande) :
935 if self.selection != None :
936 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
937 self.highlightitem(label)
938 self.selection = (mot,label,commande)
939 self.arg_selected = mot
940 if commande : commande(mot)
942 def selectitem(self,mot,label,commande) :
943 """ Met l'item sélectionné (représenté par son label) en surbrillance
944 et lance la commande associée au double-clic"""
948 self.selectthis(mot,label,commande)
950 def highlightitem(self,label) :
951 """ Met l'item représenté par son label en surbrillance """
953 label.configure(bg='#00008b',fg='white')
955 def markitem(self,label):
956 """ Met l'item (représenté par son label) en rouge """
957 label.configure(bg='gray95',fg='red')
959 def deselectitem(self,label,mot='',commande=None) :
960 """ Remet l'item (représenté par son label) en noir"""
961 if label:label.configure(bg='gray95',fg='black')
962 self.arg_selected = ''
963 if commande and mot : commande(mot)
965 def cherche_selected_item(self):
967 index=self.MCbox.index(self.selection[1])
968 lign,col=map(int,string.split(index,'.'))
970 label=self.dico_labels[self.arg_selected]
971 mot=self.dico_mots[label]
972 lign=self.dico_place[mot]+1
975 def remove_selected_item(self):
977 index=self.MCbox.index(self.selection[1])
978 lign,col=map(int,string.split(index,'.'))
980 label=self.dico_labels[self.arg_selected]
981 mot=self.dico_mots[label]
982 lign=self.dico_place[mot]+1
983 del self.liste[lign-1]
986 def entry_changed(self,event=None):
987 """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
988 de l'entry et frappe <Return>"""
989 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
990 filtre = self.entry.get()+"*"
991 FILTRE = string.upper(filtre)
993 for arg in self.liste :
994 if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
995 label=self.dico_labels[arg]
997 self.selectitem(arg,label,self.selection[2])
1001 #self.dico_labels[self.arg_selected].focus_set()
1006 # PN attention à la gestion des paramétres
1007 # cela retourne H = 1 , et ni H, ni 1
1009 # print val.__class__.__name__
1010 def get_liste(self):
1012 for val in self.liste:
1020 def put_liste(self,liste):
1022 self.affiche_liste()
1025 """ Cette classe permet d'afficher au lancement d'EFICAS le message
1026 d'attente et la barre de progression"""
1027 def __init__(self,master,message,barre ='oui'):
1028 from Tools.foztools.foztools import Slider
1029 fonte=fontes.standard12_gras
1031 self.frame = Frame(self.master)
1032 self.frame.pack(expand=1,fill='both')
1033 self.mess = Label(self.frame,text=message,justify='center',
1034 bd=2,relief='groove',font=fonte)
1035 self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
1036 self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
1037 fillColor='#00008b',width=200,height=30,
1038 background='white',labelColor='red')
1040 self.progress.frame.pack(in_=self.frame,side='top')
1041 self.master.update()
1043 self.progress.frame.after(1000,self.update)
1045 def configure(self,**options):
1046 if options.has_key('message'):
1047 self.mess.configure(text=options['message'])
1048 if options.has_key('barre'):
1049 if options['barre'] == 'oui' :
1050 self.progress.frame.pack(in_=self.frame,side='top')
1051 elif options['barre'] == 'non' :
1052 self.progress.frame.pack_forget()
1053 self.master.update_idletasks()
1056 self.frame.destroy()
1057 self.master.update()
1059 def update(self,event=None):
1060 """ Permet de faire avancer la barre de progression """
1063 bar.value = bar.value+self.increment
1065 self.master.after(100,self.update)
1069 def configure_barre(self,nb):
1070 """ Calcule l'incrément de progression de la barre en fonction
1071 du nombre d'opérations à effectuer afin que le compteur
1072 soit à 100% à la fin des opérations"""
1073 self.increment = 100./nb
1074 self.progress.update()
1076 class Ask_Format_Fichier :
1078 Cette classe permet de créer une fenêtre Toplevel dans laquelle
1079 on propose le choix du format de fichier de commandes à ouvrir
1081 def __init__(self,appli):
1082 self.fenetre = Toplevel()
1083 self.fenetre.configure(width = 250,height=150)
1084 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
1085 self.fenetre.title("Choix du format du fichier de commandes")
1086 # définition des frames
1087 self.frame_texte = Frame(self.fenetre)
1088 self.frame_radioboutons = Frame(self.fenetre)
1089 self.frame_bouton_ok = Frame(self.fenetre)
1090 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
1091 self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
1092 self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
1093 # définition de la zone texte et du scrollbar
1094 zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
1095 zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
1096 # définition des radioboutons
1097 Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
1098 variable=appli.format_fichier,value='Aster').pack(anchor='n')
1099 Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
1100 variable=appli.format_fichier,value='Python').pack(anchor='n')
1101 # création du bouton OK
1102 Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
1103 # centrage de la fenêtre
1104 centerwindow(self.fenetre)
1107 self.fenetre.destroy()
1109 class BARRE_K2000(Toplevel):
1110 def __init__(self,master=None,text = ""):
1111 Toplevel.__init__(self,master,relief='groove')
1112 self.master.iconify()
1113 self.geometry("250x100+0+0")
1114 self.protocol("WM_DELETE_WINDOW",self.quit)
1115 # frame principale dans self (= Toplevel)
1116 self.frame = Frame(self)
1117 self.frame.place(relwidth=1,relheight=1)
1118 # frame contenant le texte à afficher
1119 self.frame_text = Frame(self.frame)
1120 self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
1121 # frame contenant le canvas de la barre
1122 self.frame_canv = Frame(self.frame)
1123 self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
1124 # canvas dans lequel sera affichée la barre K2000
1125 self.canvas = Canvas(self.frame_canv)
1126 self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
1127 # on affiche le texte et la barre
1128 self.build_text(text)
1130 #self.overrideredirect(1)
1131 # on active la barre ...
1132 self.master.after(1000,self.launch)
1133 # on centre la fenêtre
1137 def build_text(self,text):
1139 Affichage de text dans frame_text
1141 self.texte_var = StringVar()
1142 self.texte_var.set(text)
1143 Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
1145 def build_batons(self):
1147 Construit la suite de bâtons dans le canvas
1153 for i in range(0,40):
1154 id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
1155 self.l_batons.append(id)
1159 Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
1163 self.master.deiconify()
1165 if self.sens == 'D':
1166 self.black = self.black+1
1167 l_bat = self.l_batons[0:self.black+1]
1169 elif self.sens == 'G':
1170 self.black = self.black-1
1171 l_bat = self.l_batons[self.black:]
1175 if num_color < 10 : color = 'black'
1176 elif num_color > 90 : color = 'white'
1177 else: color = 'gray'+`num_color`
1178 self.canvas.itemconfigure(bat,fill=color)
1180 if self.black == len(self.l_batons) :
1182 if self.black == 0 and self.sens == 'G':self.sens = 'D'
1183 self.after(80,self.launch)
1185 def update_text(self,new_text):
1187 Remplace le texte affiché par new_text
1189 self.texte_var.set(new_text)
1194 class ListeChoixParGroupes(ListeChoix) :
1196 Cette classe est utilisée pour afficher une liste de commandes classées par
1197 groupes. L'utilisateur peut réaliser des actions de selection
1198 qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
1200 liste_commandes = (("<Enter>",self.selectCmd),
1201 ("<Leave>",self.deselectCmd),
1202 ("<Double-Button-1>",self.defCmd))
1203 Il s'agit d'une liste de doublets dont le premier element est un evenement et le
1204 deuxieme un callback a appeler sur l'evenement en question.
1207 def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
1208 active ='oui',filtre='non',titre='',optionReturn=None,fonte_titre=fontes.standard_gras_souligne):
1209 self.parent = parent
1211 self.liste_groupes = liste_groupes
1212 self.dict_groupes = dict_groupes
1214 self.selection = None
1215 self.liste_commandes = liste_commandes
1216 self.liste_marques = liste_marques
1217 self.arg_selected=''
1218 self.active = active
1220 self.filtre = filtre
1221 self.optionReturn = optionReturn
1222 self.fonte_titre=fonte_titre
1225 def affiche_liste(self):
1226 """ Affiche la liste dans la fenêtre"""
1229 self.MCbox.config(state=NORMAL)
1230 self.MCbox.delete(1.0,END)
1231 for grp in self.liste_groupes:
1232 # On itère sur les groupes
1233 if grp == "CACHE":continue
1234 liste_commandes=self.dict_groupes[grp]
1235 text="GROUPE<<<<<<<< "+grp+" "
1236 text=text+">"*max(0,30-len(text))
1237 label = Label(self.MCbox,
1239 fg = 'black',bg = 'gray95',justify = 'left')
1240 # On stocke la relation entre le nom de la commande et le label
1241 self.dico_labels[grp]=label
1242 liste_labels.append(label)
1243 self.MCbox.window_create(END,
1246 self.MCbox.insert(END,'\n')
1247 for cmd in liste_commandes:
1248 label = Label(self.MCbox,
1250 fg = 'black',bg = 'gray95',justify = 'left')
1251 # On stocke la relation entre le nom de la commande et le label
1252 self.dico_labels[cmd]=label
1253 self.dico_mots[label]=cmd
1254 self.MCbox.window_create(END,
1257 self.MCbox.insert(END,'\n')
1259 def null(*tp,**args): return
1261 if self.active == 'oui':
1262 # Traitement par defaut des evenements
1263 label.bind("<Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.selectitem(x,l,c))
1264 label.bind("<Leave>",lambda e,s=self,c=null,x=cmd,l=label: s.deselectitem(l,x,c))
1265 label.bind("<Double-Button-1>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1266 label.bind("<Return>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1267 label.bind("<KP_Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1268 label.bind("<Key-Right>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1269 label.bind("<Key-Down>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1270 label.bind("<Key-Left>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1271 label.bind("<Key-Up>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1273 # Si des callbacks sont definis on les utilise
1274 for event,callback in self.liste_commandes:
1275 if event == "<Enter>":
1276 label.bind("<Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.selectitem(x,l,c))
1277 elif event == "<Leave>":
1278 label.bind("<Leave>",lambda e,s=self,c=callback,x=cmd,l=label: s.deselectitem(l,x,c))
1279 elif event == "<Double-Button-1>":
1280 label.bind("<Double-Button-1>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1281 elif event == "<Return>":
1282 label.bind("<Return>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1283 elif event == "<KP_Enter>":
1284 label.bind("<KP_Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1285 elif event == "<Key-Right>":
1286 label.bind("<Key-Right>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1287 elif event == "<Key-Down>":
1288 label.bind("<Key-Down>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1289 elif event == "<Key-Left>":
1290 label.bind("<Key-Left>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1291 elif event == "<Key-Up>":
1292 label.bind("<Key-Up>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1294 label.bind(event,lambda e,s=self,c=callback,x=cmd,l=label: c())
1296 for marque in self.liste_marques:
1298 self.markitem(liste_labels[marque])
1302 self.MCbox.config(state=DISABLED)
1303 self.selection = None
1305 for event,callback in self.liste_commandes:
1306 if event == "<Enter>":
1307 self.selection=None,None,callback
1310 def selectPrevItem(self,mot,label,callback,group,cmd):
1311 g=self.liste_groupes.index(group)
1312 liste_commandes=self.dict_groupes[group]
1313 c=liste_commandes.index(cmd)
1315 co=liste_commandes[c-1]
1317 # debut de liste. On passe au groupe precedent
1319 gr=self.liste_groupes[g-1]
1320 co=self.dict_groupes[gr][-1]
1322 # debut des groupes. On ne fait rien
1324 # On a trouve l'item precedent
1325 labelsuivant=self.dico_labels[co]
1326 index = self.MCbox.index(labelsuivant)
1327 self.MCbox.see(index)
1328 self.selectthis(co,labelsuivant,self.selection[2],)
1331 def selectNextItem(self,mot,label,callback,group,cmd):
1332 g=self.liste_groupes.index(group)
1333 liste_commandes=self.dict_groupes[group]
1334 c=liste_commandes.index(cmd)
1336 co=liste_commandes[c+1]
1338 # fin de liste. On passe au groupe suivant
1340 gr=self.liste_groupes[g+1]
1341 co=self.dict_groupes[gr][0]
1343 # fin des groupes. On ne fait rien
1345 # On a trouve l'item suivant
1346 labelsuivant=self.dico_labels[co]
1347 index = self.MCbox.index(labelsuivant)
1348 self.MCbox.see(index)
1349 self.selectthis(co,labelsuivant,self.selection[2],)
1352 def entry_changed(self,event=None):
1354 Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1355 de l'entry et frappe <Return>
1357 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1359 filtre = self.entry.get()+"*"
1360 FILTRE = string.upper(filtre)
1362 # On cherche d'abord dans les noms de groupe
1363 # puis dans les noms de commande groupe par groupe
1365 for grp in self.liste_groupes:
1366 if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1367 cmd=self.dict_groupes[grp][0]
1368 label=self.dico_labels[cmd]
1369 index = self.MCbox.index(label)
1370 self.MCbox.see(index)
1371 self.selectitem(cmd,label,self.selection[2])
1372 # On a trouve un groupe on arrete la recherche
1375 for grp in self.liste_groupes:
1376 for cmd in self.dict_groupes[grp] :
1377 if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1378 label=self.dico_labels[cmd]
1379 index = self.MCbox.index(label)
1380 self.MCbox.see(index)
1381 self.selectitem(cmd,label,self.selection[2])
1382 # On a trouve une commande on arrete la recherche
1385 if __name__ == "__main__":
1387 f=FenetreDeParametre(root,None,None,"\n".join(["coucouxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=2"]*15))
1388 #f=FenetreYesNo(None,titre="Le titre",texte="\n".join(["Le textexxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]*35),yes="Yes",no="No")