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 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=""):
60 self.fenetre = Toplevel()
61 self.fenetre.withdraw()
62 self.fenetre.configure(width = 800,height=500)
63 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
64 self.fenetre.title("Visualisation du "+titre)
65 self.texte = string.replace(texte,'\r\n','\n')
67 fonte=fontes.standardcourier10
68 # définition des frames
69 self.frame_texte = Frame(self.fenetre)
70 self.frame_boutons = Frame(self.fenetre)
71 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.9)
72 self.frame_boutons.place(relheight=0.1,relx=0,rely=0.9,relwidth=1.)
73 # définition de la zone texte et du scrollbar
74 self.zone_texte = Text(self.frame_texte,font=fonte)
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,default='active')
87 self.but_save = Button(self.frame_boutons,text = "sauver",command = self.save)
88 self.but_quit.place(relx=0.4,rely=0.5,anchor='center')
89 self.but_save.place(relx=0.6,rely=0.5,anchor='center')
91 self.affiche_texte(self.texte)
92 self.zone_texte.config(state=DISABLED)
93 centerwindow(self.fenetre)
94 self.fenetre.deiconify()
96 def page_up(self,event):
97 event.widget.yview_scroll(-1, "page")
98 def page_down(self,event):
99 event.widget.yview_scroll(1, "page")
100 def unit_up(self,event):
101 event.widget.yview_scroll(-1, "unit")
102 def unit_down(self,event):
103 event.widget.yview_scroll(1, "unit")
106 self.fenetre.grab_set()
107 self.zone_texte.focus_set()
108 self.fenetre.wait_window(self.fenetre)
111 self.fenetre.destroy()
113 def efface_scroll(self):
114 """ Efface le scroll lorsqu'il n'est pas nécessaire : ne marche pas"""
115 self.scroll_v.pack_forget()
116 #self.scroll_h.pack_forget()
118 def affiche_texte(self,texte):
119 """ Affiche le texte dans la fenêtre """
121 self.zone_texte.insert(END,texte)
123 self.fenetre.update_idletasks()
124 x0,y0,x1,y1 = self.zone_texte.bbox(END)
125 if (y1-y0) < 300 : self.efface_scroll()
130 """ Permet de sauvegarder le texte dans un fichier dont on a demandé le nom
132 file = asksaveasfilename(defaultextension = '.comm',
133 #initialdir = self.appli.CONFIGURATION.rep_user,
134 initialdir = self.appli.CONFIGURATION.initialdir,
135 title="Sauvegarde du "+self.titre)
137 if not save_in_file(file,self.texte,None) :
138 showerror("Sauvegarde impossible",
139 "Impossible de sauvegarder le texte dans le fichier spécifié\n"+
140 "Vérifiez les droits d'écriture")
142 showinfo("Sauvegarde effectuée","Sauvegarde effectuée dans le fichier %s" %file)
146 self.fenetre.destroy()
150 class FenetreYesNo(Fenetre):
151 def __init__(self,appli,titre="",texte="",yes="Yes",no="No"):
153 self.fenetre = Toplevel()
154 self.fenetre.configure(width = 800,height=500)
155 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
156 self.fenetre.title(titre)
157 self.texte = string.replace(texte,'\r\n','\n')
159 fonte=fontes.standardcourier10
160 # définition des frames
161 self.frame_texte = Frame(self.fenetre)
162 self.frame_boutons = Frame(self.fenetre)
163 self.frame_boutons.place(relx=0,rely=0, relwidth=1.,relheight=0.1)
164 self.frame_texte.place( relx=0,rely=0.1, relwidth=1, relheight=0.9)
165 # définition de la zone texte et du scrollbar
166 self.zone_texte = Text(self.frame_texte,font=fonte)
167 self.zone_texte.bind("<Key-Prior>", self.page_up)
168 self.zone_texte.bind("<Key-Next>", self.page_down)
169 self.zone_texte.bind("<Key-Up>", self.unit_up)
170 self.zone_texte.bind("<Key-Down>", self.unit_down)
171 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
172 #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
173 self.scroll_v.pack(side='right',fill ='y')
174 #self.scroll_h.pack(side='bottom',fill ='x')
175 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
176 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
177 # définition des boutons
178 self.but_yes = Button(self.frame_boutons,text = yes,command=self.yes)
179 self.but_no = Button(self.frame_boutons,text = no,command = self.no)
180 self.but_yes.place(relx=0.4,rely=0.5,anchor='center')
181 self.but_no.place(relx=0.6,rely=0.5,anchor='center')
183 self.affiche_texte(self.texte)
184 centerwindow(self.fenetre)
194 class FenetreDeSelection(Fenetre):
195 """ Classe dérivée de Fenêtre permettant la récupération d'une zone de texte sélectionnée.
196 Cette classe est utilisée pour affecter une liste de valeurs à un mot-clé.
198 def __init__(self,panel,item,appli,titre="",texte="",cardinal=1):
199 Fenetre.__init__(self,appli,titre=titre,texte=texte)
200 self.frame_boutons.place_forget()
201 self.frame_texte.place_forget()
202 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.8)
203 self.frame_boutons.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
205 self.cardinal=cardinal
206 self.fenetre.configure(width = 320,height=400)
207 centerwindow(self.fenetre)
210 self.fenetre.title(titre)
211 self.but_save.configure(text="Ajouter",command=self.traite_selection)
212 # séparateur par défaut
213 self.separateur = ';'
214 # création de la zone de saisie du séparateur
215 l_separateurs_autorises = self.get_separateurs_autorises()
216 self.choix_sep = Pmw.ComboBox(self.frame_boutons,
217 label_text = "Séparateur :",
220 selectioncommand = self.choose_separateur,
221 scrolledlist_items = l_separateurs_autorises)
222 self.choix_sep.component('entry').configure(width=6)
223 self.choix_sep.place(relx=0.01,rely=0.5,anchor='w')
224 self.choix_sep.selectitem(self.separateur)
226 self.but_quit.place_forget()
227 self.but_save.place_forget()
228 self.but_all = Button(self.frame_boutons,text = "Tout Sélectionner", command=self.tout)
229 self.but_save.place(relx=0.6,rely=0.6,anchor='center')
230 self.but_quit.place(relx=0.8,rely=0.6,anchor='center')
231 self.but_all.place(relx=0.7,rely=0.2,anchor='center')
232 self.choose_separateur('espace')
235 def get_separateurs_autorises(self):
237 Retourne la liste des séparateurs autorisés
239 return ['espace',';',',']
241 def choose_separateur(self,nom_sep):
243 Affecte à self.separateur le caractère séparateur correspondant à nom_sep
245 if nom_sep == 'espace' :
246 self.separateur = ' '
248 self.separateur = nom_sep
252 texte=self.texte.splitlines()
254 for mot in string.split(l,self.separateur):
255 if mot != '' and mot != ' ' and mot != self.separateur :
257 self.traite_selection(liste)
259 def traite_selection(self,liste=None):
260 """ Cette méthode effectue tous les traitements nécessaires pour vérifier
261 et affecter la liste de valeurs à l'objet réprésenté par self.item
263 # Récupère la liste des chaines de caractères de la zone sélectionnée
266 message,liste = self.recupere_liste()
267 if self.test_probleme(message,"Sélectionnez des données") == 0:
269 # Vérifie que le nombre de données est dans les limites attendues
270 message = self.verif_liste(liste)
271 if self.test_probleme(message,"Vérifiez le nombre de données") == 0:
273 # Crée une liste de valeurs du type attendu
274 message,liste_valeurs = self.creation_liste_valeurs(liste)
275 if self.test_probleme(message,"Vérifiez le type des données") == 0:
277 # Vérifie que chaque valeur est dans le domaine exigé
278 message = self.verif_valeurs(liste_valeurs)
279 if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:
281 # Ajoute les valeurs dans la liste de valeurs du mot-clé
282 if self.cardinal != 1 :
286 if (len(liste_valeurs)%nb != 0):
287 message="La cardinalité n'est pas correcte"
288 self.test_probleme(message,"On attend des tuples")
290 for i in range(len(liste_valeurs)/nb) :
292 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1])
294 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1], liste_valeurs[i*nb+2])
296 print "probleme : prevenir la maintenance Eficas"
299 liste_valeurs=l_valeurs
300 self.ajouter_valeurs(liste_valeurs)
301 self.appli.affiche_infos("Liste de valeurs acceptée")
303 def test_probleme(self, message, message_eficas):
304 """ Cette méthode affiche un message d'erreur si message != ''
305 et retourne 0, sinon retourne 1 sans rien afficher.
308 showinfo("Problème",message)
309 self.fenetre.tkraise()
310 self.appli.affiche_infos(message_eficas)
315 def recupere_liste(self):
316 """ Cette méthode récupère le texte de la zone sélectionnée, construit et
317 retourne une liste avec les chaines qui se trouvent entre les séparateurs.
318 S'il n'y a pas de données selectionnées, elle retourne un message d'erreur
323 selection=self.fenetre.selection_get()
325 message = "Pas de donnée sélectionnée"
327 # les retours chariots doivent être interprétés comme des séparateurs
328 selection = string.replace(selection,'\n',self.separateur)
329 # on splitte la sélection suivant le caractère séparateur
330 liste_chaines = string.split(selection,self.separateur)
332 for chaine in liste_chaines:
333 chaine = string.strip(chaine)
334 if chaine != '' : l_chaines.append(chaine)
335 return message,l_chaines
337 def verif_liste(self, liste):
338 """ Cette méthode effectue des tests sur le nombre d'éléments de la liste
339 et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur
343 # nombre d'éléments sélectionnés
344 nombre_elements = len(liste)
345 # nombre d'éléments déja dans la liste du panel
346 nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())
347 multiplicite = self.item.GetMultiplicite()
348 if (nombre_elements % multiplicite) != 0:
349 message = "Vous devez sélectionner "+str(multiplicite)+" * n données"
351 nombre_valeurs = nombre_elements / multiplicite
352 cardinalite = self.item.GetMinMax()
353 if nombre_valeurs < cardinalite[0]:
354 message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"
356 if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):
357 message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"
362 def creation_liste_valeurs(self, liste):
363 """ Cette méthode crée et retourne une liste de valeurs du type attendu
364 par le mot-clé. La liste de valeurs est créée à partir de la liste
365 de chaines de caractères transmise.
367 type_attendu = self.item.GetType()[0]
368 if type_attendu == 'R':
369 return self.convertir(liste, f_conversion= float)
370 elif type_attendu == 'I':
371 return self.convertir(liste, f_conversion= int)
372 elif type_attendu == 'TXM':
373 return self.convertir(liste)
375 message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"
378 def convertir(self, liste, f_conversion=None):
379 """ Cette méthode essaie de convertir les éléments de la liste avec la
380 fonction f_conversion si elle existe, et retourne la liste des
381 éléments dans le type voulu en cas de succès, sinon retourne None.
388 liste_valeurs.append(f_conversion(chaine))
390 message = "Impossible de convertir "+chaine+" dans le type attendu"
393 liste_valeurs.append(chaine)
394 return message,liste_valeurs
396 def verif_valeurs(self, liste_valeurs):
397 """ Cette méthode teste tous les éléments de la liste, et retourne 1 si chaque
398 élément est dans le domaine voulu.
401 for valeur in liste_valeurs:
402 test = self.item.IsInIntervalle(valeur)
404 intervalle = str(self.item.GetIntervalle()[0])+","+str(self.item.GetIntervalle()[1])
405 message = "La valeur "+str(valeur)+" n'est pas dans l'intervalle ["+intervalle+"]"
409 def ajouter_valeurs(self, liste_valeurs):
410 """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""
411 liste = self.panel.Liste_valeurs.get_liste()
412 liste.extend(liste_valeurs)
413 self.panel.Liste_valeurs.put_liste(liste)
415 class FenetreDeParametre(Fenetre) :
416 def __init__(self,parent,item,appli,texte):
419 self.fenetre = Toplevel()
420 self.fenetre.configure(width = 250,height=100)
421 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
422 self.fenetre.title("Parametres")
423 self.titre = "Parametres"
424 self.texte = string.replace(texte,'\r\n','\n')
425 fonte=fontes.standardcourier10
427 # définition des frames
428 self.frame_texte = Frame(self.fenetre)
429 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.7)
430 # définition de la zone texte et du scrollbar
431 self.zone_texte = Text(self.frame_texte,font=fonte)
432 self.zone_texte.bind("<Key-Prior>", self.page_up)
433 self.zone_texte.bind("<Key-Next>", self.page_down)
434 self.zone_texte.bind("<Key-Up>", self.unit_up)
435 self.zone_texte.bind("<Key-Down>", self.unit_down)
436 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
437 self.scroll_v.pack(side='right',fill ='y')
438 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
439 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
441 self.affiche_texte(self.texte)
442 self.zone_texte.config(state="disabled")
444 # définition des boutons
445 self.frame_boutons = Frame(self.fenetre)
446 self.frame_boutons.place(relheight=0.3,relx=0,rely=0.65,relwidth=1.)
447 self.label1 = Label(self.frame_boutons,text="surligner la")
448 self.label2 = Label(self.frame_boutons,text="ligne entière")
449 self.label1.place(relx=0.1,rely=0)
450 self.label2.place(relx=0.1,rely=0.5)
451 self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
452 self.but_save = Button(self.frame_boutons,text = "Choisir",command = self.Choisir)
453 self.but_save.place(relx=0.6,rely=0,relheight=1)
454 self.but_quit.place(relx=0.8,rely=0,relheight=1)
459 selection=self.zone_texte.selection_get()
461 showerror("Pas de donnée sélectionnée",
462 "Selectionner un parametre")
464 for param in selection.splitlines():
465 nomparam=param[0:param.find("=")-1]
467 l_param=l_param+nomparam+','
468 self.parent.entry.delete(0,Tkinter.END)
469 self.parent.entry.insert(0,l_param[0:-1])
470 self.parent.valid_valeur()
475 Cette classe permet de créer une boîte Dialog dans laquelle
476 on affiche un formulaire à remplir par l'utilisateur
478 def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
479 if items in ((),[]) : return
483 self.fen_pere = fen_pere
484 self.obj_pere = obj_pere
486 self.command = commande
490 self.init_validateurs()
493 self.init_items_formulaire()
494 self.fenetre.activate(geometry='centerscreenalways')
496 def init_validateurs(self):
498 Crée le dictionnaire des validateurs des objets reconnus par le formulaire
500 self.d_validateurs = {}
501 self.d_validateurs['rep'] = self.repvalidator
502 self.d_validateurs['file'] = self.filevalidator
503 self.d_validateurs['cata']= self.catavalidator
505 def init_fenetre(self):
507 Crée la fenêtre Dialog
509 if self.mode == 'query':
510 buttons=('Valider','Annuler')
511 defaultbutton = 'Valider'
512 elif self.mode == 'display':
514 buttons=(self.command[0],'OK')
519 self.fenetre = Pmw.Dialog(self.fen_pere,
521 defaultbutton = defaultbutton,
523 command = self.execute)
524 self.fenetre.withdraw()
526 def init_texte(self):
528 Crée le label qui affiche le texte à l'intérieur du panneau
530 fonte=fontes.standard
531 fr_texte = Frame(self.fenetre.interior(),height=60)
532 fr_texte.pack(side='top',fill='x',expand=1)
533 Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
535 def init_items_formulaire(self):
537 Crée et affiche les items dans la boîte de dialogue
541 self.item_widgets = {}
543 for item in self.items:
544 if len(item[0])>length_maxi : length_maxi = len(item[0])
545 window = self.fenetre.interior()
546 for item in self.items :
548 label,nature,nom_var,defaut = item
552 label,nature,nom_var,defaut,chaine,chaine2 = item
553 # création de la frame
554 fr_item = Frame(window,height=40,width=700)
555 fr_item.pack(side='top',fill='x',expand=1)
557 Label(fr_item,text = label).place(relx=0.05,rely=0.4)
558 if nature in ('rep','file','cata'):
559 # création de l'entry
560 e_item = Entry(fr_item)
561 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
562 self.widgets.append(e_item)
563 self.item_widgets[item] = e_item
564 if defaut : e_item.insert(0,str(defaut))
565 elif nature == 'YesNo':
566 # création de la StringVar
568 setattr(self,'item_'+nom_var,var)
570 # création du radiobouton
571 rb1 = Radiobutton(fr_item,text=chaine,variable=var,value='OUI')
572 rb2 = Radiobutton(fr_item,text=chaine2,variable=var,value='NON')
573 rb1.place(relx=0.65,rely=0.5,anchor='center')
574 rb2.place(relx=0.80,rely=0.5,anchor='center')
575 self.widgets.append((rb1,rb2))
576 self.item_widgets[item] = var
577 # détermination de la méthode à appliquer sur les boutons
578 if self.mode == 'query':
579 function = self.active
580 elif self.mode == 'display':
581 function = self.inactive
584 # on applique la méthode sur les boutons (activation ou désactivation)
585 for widget in self.widgets :
586 if type(widget) == types.TupleType:
588 apply(function,(widg,),{})
590 apply(function,(widget,),{})
592 def active(self,widget):
594 Active le widget passé en argument
596 widget.configure(state='normal',bg='white')
598 def inactive(self,widget):
600 Inactive le widget passé en argument
602 if not isinstance(widget,Radiobutton) :
603 widget.configure(state='disabled',bg='gray95')
605 widget.configure(state='disabled')
607 # --------------------------------------------------------------------------------
608 # Validateurs des noms de répertoire, de fichiers et de catalogues
609 # -------------------------------------------------------------------------------
611 def repvalidator(self,text):
613 Teste si text peut faire référence à un répertoire ou non
614 Retourne 1 si valide, 0 sinon
616 return os.path.isdir(text),'Répertoire introuvable : %s' %text
618 def filevalidator(self,text):
620 Teste si text peut faire référence à un fichier ou non
621 Retourne 1 si valide, 0 sinon
623 return os.path.isfile(text),'Fichier introuvable : %s' %text
625 def catavalidator(self,text):
627 Teste si text est un chemin d'accès valide à un catalogue
628 Retourne 1 si valide, 0 sinon
630 return os.path.isfile(text),"Catalogue introuvable : %s" %text
632 # --------------------------------------------------------------------------------
633 # Méthodes callbacks des boutons et de fin
634 # --------------------------------------------------------------------------------
636 def execute(self,txt):
638 Cette commande est activée à chaque clic sur un bouton.
639 Redirige l'action sur la bonne méthode en fonction du bouton activé
643 elif txt in ('OK','Annuler'):
645 elif txt == 'Modifier':
646 self.resultat = apply(self.command[1],(),{})
647 self.fenetre.destroy()
649 print "Nom de bouton inconnu"
654 Commande qui termine le panneau et sauvegarde les nouvelles options
655 dans l'objet resultat (dictionnaire)
658 for item,widget in self.item_widgets.items():
661 valeur = widget.get()
662 if self.d_validateurs.has_key(type_var):
663 test = self.d_validateurs[type_var](valeur)
665 # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
666 # sans tuer la fenêtre bien sûr
667 widget.selection_range(0,END)
669 dico[nom_var] = valeur
670 self.fenetre.destroy()
674 self.fenetre.destroy()
678 """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
679 en passant les commandes à lancer suivant différents bindings """
680 def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre='',
681 optionReturn=None, fonte_titre=fontes.standard_gras_souligne):
686 self.selection = None
687 self.liste_commandes = liste_commandes
688 self.liste_marques = liste_marques
693 self.optionReturn = optionReturn
694 self.fonte_titre=fonte_titre
698 self.make_label_titre()
699 self.make_entry_filtre()
702 self.entry.component('entry').focus()
706 def make_label_titre(self):
707 """ Crée le label correspondant au titre """
708 if self.titre == '' : return
709 self.label = Label(self.page,
711 font = self.fonte_titre)
712 self.label.pack(side='top',pady=2)
714 def make_entry_filtre(self):
715 """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
716 if self.filtre != 'oui' : return
717 self.entry = Pmw.EntryField(self.page,labelpos='w',
718 label_text="Filtre :",
719 command=self.entry_changed)
720 self.entry.pack(side='top',pady=2)
722 def make_text_box(self):
723 """ Crée la fenêtre texte dans laquelle sera affichée la liste """
724 self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
725 self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
726 self.MCscroll.pack(side='right',fill ='y',pady=2)
727 self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
728 self.MCbox.configure(yscrollcommand=self.MCscroll.set)
731 def affiche_liste(self):
732 """ Affiche la liste dans la fenêtre"""
734 self.MCbox.config(state=NORMAL)
735 self.MCbox.delete(1.0,END)
736 for objet in self.liste :
737 if type(objet) == types.InstanceType:
742 elif type(objet) in (types.StringType,types.IntType):
744 elif type(objet) == types.FloatType :
745 mot = self.parent.get_valeur_texte(objet)
748 elif type(objet) == types.TupleType :
756 valtexte = self.parent.get_valeur_texte(val)
764 label = Label(self.MCbox,
766 fg = 'black',bg = 'gray95',justify = 'left')
767 self.dico_labels[mot]=label
768 liste_labels.append(label)
769 self.MCbox.window_create(END,
772 self.MCbox.insert(END,'\n')
773 if self.optionReturn != None :
774 label.bind("<Return>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
775 label.bind("<KP_Enter>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
776 label.bind("<Key-Right>",lambda e,s=self,x=objet,l=label : s.selectNextItem(x,l))
777 label.bind("<Key-Down>",lambda e, s=self,x=objet,l=label : s.selectNextItem(x,l))
778 label.bind("<Key-Left>" ,lambda e,s=self,x=objet,l=label : s.selectPrevItem(x,l))
779 label.bind("<Key-Up>" ,lambda e,s=self,x=objet,l=label : s.selectPrevItem(x,l))
780 if self.active == 'oui':
781 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))
782 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))
783 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))
785 for marque in self.liste_marques:
787 self.markitem(liste_labels[marque])
791 self.MCbox.config(state=DISABLED)
792 self.selection = None
794 for event,callback in self.liste_commandes:
795 if event == "<Enter>":
796 self.selection=None,None,callback
799 def clear_marque(self):
801 self.dico_labels[self.arg_selected].configure(bg='gray95',fg='black')
802 self.arg_selected = ''
806 def surligne(self,marque):
808 self.highlightitem(self.dico_labels[marque])
809 self.arg_selected = marque
813 def chooseitemsurligne(self,mot,label,commande):
814 """ Active la méthode de choix passée en argument"""
816 mot=self.arg_selected
818 except AsException,e:
820 showerror(raison.split('\n')[0],raison)
822 def chooseitem(self,mot,label,commande):
823 """ Active la méthode de choix passée en argument"""
826 except AsException,e:
828 showerror(raison.split('\n')[0],raison)
830 def selectNextItem(self,mot,label):
831 index=self.liste.index(mot)
833 if indexsuivant > len(self.liste) -1:
835 motsuivant=self.liste[indexsuivant]
836 labelsuivant=self.dico_labels[motsuivant]
837 index = self.MCbox.index(labelsuivant)
838 self.MCbox.see(index)
839 self.selectthis(motsuivant,labelsuivant,self.selection[2],)
842 def selectPrevItem(self,mot,label):
843 index=self.liste.index(mot)
845 motprec=self.liste[indexprec]
846 labelprec=self.dico_labels[motprec]
847 index = self.MCbox.index(labelprec)
848 self.MCbox.see(index)
849 self.selectthis(motprec,labelprec,self.selection[2],)
852 def selectthis(self,mot,label,commande) :
854 if self.selection != None :
855 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
856 self.highlightitem(label)
857 self.selection = (mot,label,commande)
858 self.arg_selected = mot
859 if commande : commande(mot)
861 def selectitem(self,mot,label,commande) :
862 """ Met l'item sélectionné (représenté par son label) en surbrillance
863 et lance la commande associée au double-clic"""
867 self.selectthis(mot,label,commande)
869 def highlightitem(self,label) :
870 """ Met l'item représenté par son label en surbrillance """
872 label.configure(bg='#00008b',fg='white')
874 def markitem(self,label):
875 """ Met l'item (représenté par son label) en rouge """
876 label.configure(bg='gray95',fg='red')
878 def deselectitem(self,label,mot='',commande=None) :
879 """ Remet l'item (représenté par son label) en noir"""
880 if label:label.configure(bg='gray95',fg='black')
881 self.arg_selected = ''
882 if commande and mot : commande(mot)
884 def cherche_selected_item(self):
885 index=self.MCbox.index(self.selection[1])
886 lign,col=map(int,string.split(index,'.'))
889 def remove_selected_item(self):
891 index=self.MCbox.index(self.selection[1])
893 index=self.MCbox.index(self.dico_labels[self.arg_selected] )
894 lign,col=map(int,string.split(index,'.'))
895 del self.liste[lign-1]
898 def entry_changed(self,event=None):
899 """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
900 de l'entry et frappe <Return>"""
901 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
902 filtre = self.entry.get()+"*"
903 FILTRE = string.upper(filtre)
904 for arg in self.liste :
905 if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
906 label=self.dico_labels[arg]
907 index = self.MCbox.index(label)
908 self.MCbox.see(index)
909 self.selectitem(arg,label,self.selection[2])
913 #self.dico_labels[self.arg_selected].focus_set()
918 # PN attention à la gestion des paramétres
919 # cela retourne H = 1 , et ni H, ni 1
921 # print val.__class__.__name__
924 for val in self.liste:
932 def put_liste(self,liste):
937 """ Cette classe permet d'afficher au lancement d'EFICAS le message
938 d'attente et la barre de progression"""
939 def __init__(self,master,message,barre ='oui'):
940 from Tools.foztools.foztools import Slider
941 fonte=fontes.standard12_gras
943 self.frame = Frame(self.master)
944 self.frame.pack(expand=1,fill='both')
945 self.mess = Label(self.frame,text=message,justify='center',
946 bd=2,relief='groove',font=fonte)
947 self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
948 self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
949 fillColor='#00008b',width=200,height=30,
950 background='white',labelColor='red')
952 self.progress.frame.pack(in_=self.frame,side='top')
955 self.progress.frame.after(1000,self.update)
957 def configure(self,**options):
958 if options.has_key('message'):
959 self.mess.configure(text=options['message'])
960 if options.has_key('barre'):
961 if options['barre'] == 'oui' :
962 self.progress.frame.pack(in_=self.frame,side='top')
963 elif options['barre'] == 'non' :
964 self.progress.frame.pack_forget()
965 self.master.update_idletasks()
971 def update(self,event=None):
972 """ Permet de faire avancer la barre de progression """
975 bar.value = bar.value+self.increment
977 self.master.after(100,self.update)
981 def configure_barre(self,nb):
982 """ Calcule l'incrément de progression de la barre en fonction
983 du nombre d'opérations à effectuer afin que le compteur
984 soit à 100% à la fin des opérations"""
985 self.increment = 100./nb
986 self.progress.update()
988 class Ask_Format_Fichier :
990 Cette classe permet de créer une fenêtre Toplevel dans laquelle
991 on propose le choix du format de fichier de commandes à ouvrir
993 def __init__(self,appli):
994 self.fenetre = Toplevel()
995 self.fenetre.configure(width = 250,height=150)
996 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
997 self.fenetre.title("Choix du format du fichier de commandes")
998 # définition des frames
999 self.frame_texte = Frame(self.fenetre)
1000 self.frame_radioboutons = Frame(self.fenetre)
1001 self.frame_bouton_ok = Frame(self.fenetre)
1002 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
1003 self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
1004 self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
1005 # définition de la zone texte et du scrollbar
1006 zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
1007 zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
1008 # définition des radioboutons
1009 Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
1010 variable=appli.format_fichier,value='Aster').pack(anchor='n')
1011 Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
1012 variable=appli.format_fichier,value='Python').pack(anchor='n')
1013 # création du bouton OK
1014 Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
1015 # centrage de la fenêtre
1016 centerwindow(self.fenetre)
1019 self.fenetre.destroy()
1021 class BARRE_K2000(Toplevel):
1022 def __init__(self,master=None,text = ""):
1023 Toplevel.__init__(self,master,relief='groove')
1024 self.master.iconify()
1025 self.geometry("250x100+0+0")
1026 self.protocol("WM_DELETE_WINDOW",self.quit)
1027 # frame principale dans self (= Toplevel)
1028 self.frame = Frame(self)
1029 self.frame.place(relwidth=1,relheight=1)
1030 # frame contenant le texte à afficher
1031 self.frame_text = Frame(self.frame)
1032 self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
1033 # frame contenant le canvas de la barre
1034 self.frame_canv = Frame(self.frame)
1035 self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
1036 # canvas dans lequel sera affichée la barre K2000
1037 self.canvas = Canvas(self.frame_canv)
1038 self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
1039 # on affiche le texte et la barre
1040 self.build_text(text)
1042 #self.overrideredirect(1)
1043 # on active la barre ...
1044 self.master.after(1000,self.launch)
1045 # on centre la fenêtre
1049 def build_text(self,text):
1051 Affichage de text dans frame_text
1053 self.texte_var = StringVar()
1054 self.texte_var.set(text)
1055 Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
1057 def build_batons(self):
1059 Construit la suite de bâtons dans le canvas
1065 for i in range(0,40):
1066 id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
1067 self.l_batons.append(id)
1071 Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
1075 self.master.deiconify()
1077 if self.sens == 'D':
1078 self.black = self.black+1
1079 l_bat = self.l_batons[0:self.black+1]
1081 elif self.sens == 'G':
1082 self.black = self.black-1
1083 l_bat = self.l_batons[self.black:]
1087 if num_color < 10 : color = 'black'
1088 elif num_color > 90 : color = 'white'
1089 else: color = 'gray'+`num_color`
1090 self.canvas.itemconfigure(bat,fill=color)
1092 if self.black == len(self.l_batons) :
1094 if self.black == 0 and self.sens == 'G':self.sens = 'D'
1095 self.after(80,self.launch)
1097 def update_text(self,new_text):
1099 Remplace le texte affiché par new_text
1101 self.texte_var.set(new_text)
1106 class ListeChoixParGroupes(ListeChoix) :
1108 Cette classe est utilisée pour afficher une liste de commandes classées par
1109 groupes. L'utilisateur peut réaliser des actions de selection
1110 qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
1112 liste_commandes = (("<Enter>",self.selectCmd),
1113 ("<Leave>",self.deselectCmd),
1114 ("<Double-Button-1>",self.defCmd))
1115 Il s'agit d'une liste de doublets dont le premier element est un evenement et le
1116 deuxieme un callback a appeler sur l'evenement en question.
1119 def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
1120 active ='oui',filtre='non',titre='',optionReturn=None,fonte_titre=fontes.standard_gras_souligne):
1121 self.parent = parent
1123 self.liste_groupes = liste_groupes
1124 self.dict_groupes = dict_groupes
1126 self.selection = None
1127 self.liste_commandes = liste_commandes
1128 self.liste_marques = liste_marques
1129 self.arg_selected=''
1130 self.active = active
1132 self.filtre = filtre
1133 self.optionReturn = optionReturn
1134 self.fonte_titre=fonte_titre
1137 def affiche_liste(self):
1138 """ Affiche la liste dans la fenêtre"""
1140 self.MCbox.config(state=NORMAL)
1141 self.MCbox.delete(1.0,END)
1142 for grp in self.liste_groupes:
1143 # On itère sur les groupes
1144 if grp == "CACHE":continue
1145 liste_commandes=self.dict_groupes[grp]
1146 text="GROUPE<<<<<<<< "+grp+" "
1147 text=text+">"*max(0,30-len(text))
1148 label = Label(self.MCbox,
1150 fg = 'black',bg = 'gray95',justify = 'left')
1151 # On stocke la relation entre le nom de la commande et le label
1152 self.dico_labels[grp]=label
1153 liste_labels.append(label)
1154 self.MCbox.window_create(END,
1157 self.MCbox.insert(END,'\n')
1158 for cmd in liste_commandes:
1159 label = Label(self.MCbox,
1161 fg = 'black',bg = 'gray95',justify = 'left')
1162 # On stocke la relation entre le nom de la commande et le label
1163 self.dico_labels[cmd]=label
1164 self.MCbox.window_create(END,
1167 self.MCbox.insert(END,'\n')
1169 def null(*tp,**args): return
1171 if self.active == 'oui':
1172 # Traitement par defaut des evenements
1173 label.bind("<Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.selectitem(x,l,c))
1174 label.bind("<Leave>",lambda e,s=self,c=null,x=cmd,l=label: s.deselectitem(l,x,c))
1175 label.bind("<Double-Button-1>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1176 label.bind("<Return>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1177 label.bind("<KP_Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1178 label.bind("<Key-Right>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1179 label.bind("<Key-Down>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1180 label.bind("<Key-Left>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1181 label.bind("<Key-Up>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1183 # Si des callbacks sont definis on les utilise
1184 for event,callback in self.liste_commandes:
1185 if event == "<Enter>":
1186 label.bind("<Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.selectitem(x,l,c))
1187 elif event == "<Leave>":
1188 label.bind("<Leave>",lambda e,s=self,c=callback,x=cmd,l=label: s.deselectitem(l,x,c))
1189 elif event == "<Double-Button-1>":
1190 label.bind("<Double-Button-1>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1191 elif event == "<Return>":
1192 label.bind("<Return>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1193 elif event == "<KP_Enter>":
1194 label.bind("<KP_Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1195 elif event == "<Key-Right>":
1196 label.bind("<Key-Right>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1197 elif event == "<Key-Down>":
1198 label.bind("<Key-Down>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1199 elif event == "<Key-Left>":
1200 label.bind("<Key-Left>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1201 elif event == "<Key-Up>":
1202 label.bind("<Key-Up>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1204 label.bind(event,lambda e,s=self,c=callback,x=cmd,l=label: c())
1206 for marque in self.liste_marques:
1208 self.markitem(liste_labels[marque])
1212 self.MCbox.config(state=DISABLED)
1213 self.selection = None
1215 for event,callback in self.liste_commandes:
1216 if event == "<Enter>":
1217 self.selection=None,None,callback
1220 def selectPrevItem(self,mot,label,callback,group,cmd):
1221 g=self.liste_groupes.index(group)
1222 liste_commandes=self.dict_groupes[group]
1223 c=liste_commandes.index(cmd)
1225 co=liste_commandes[c-1]
1227 # debut de liste. On passe au groupe precedent
1229 gr=self.liste_groupes[g-1]
1230 co=self.dict_groupes[gr][-1]
1232 # debut des groupes. On ne fait rien
1234 # On a trouve l'item precedent
1235 labelsuivant=self.dico_labels[co]
1236 index = self.MCbox.index(labelsuivant)
1237 self.MCbox.see(index)
1238 self.selectthis(co,labelsuivant,self.selection[2],)
1241 def selectNextItem(self,mot,label,callback,group,cmd):
1242 g=self.liste_groupes.index(group)
1243 liste_commandes=self.dict_groupes[group]
1244 c=liste_commandes.index(cmd)
1246 co=liste_commandes[c+1]
1248 # fin de liste. On passe au groupe suivant
1250 gr=self.liste_groupes[g+1]
1251 co=self.dict_groupes[gr][0]
1253 # fin des groupes. On ne fait rien
1255 # On a trouve l'item suivant
1256 labelsuivant=self.dico_labels[co]
1257 index = self.MCbox.index(labelsuivant)
1258 self.MCbox.see(index)
1259 self.selectthis(co,labelsuivant,self.selection[2],)
1262 def entry_changed(self,event=None):
1264 Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1265 de l'entry et frappe <Return>
1267 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1269 filtre = self.entry.get()+"*"
1270 FILTRE = string.upper(filtre)
1272 # On cherche d'abord dans les noms de groupe
1273 # puis dans les noms de commande groupe par groupe
1275 for grp in self.liste_groupes:
1276 if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1277 cmd=self.dict_groupes[grp][0]
1278 label=self.dico_labels[cmd]
1279 index = self.MCbox.index(label)
1280 self.MCbox.see(index)
1281 self.selectitem(cmd,label,self.selection[2])
1282 # On a trouve un groupe on arrete la recherche
1285 for grp in self.liste_groupes:
1286 for cmd in self.dict_groupes[grp] :
1287 if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1288 label=self.dico_labels[cmd]
1289 index = self.MCbox.index(label)
1290 self.MCbox.see(index)
1291 self.selectitem(cmd,label,self.selection[2])
1292 # On a trouve une commande on arrete la recherche