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)
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 centerwindow(self.fenetre)
93 self.fenetre.deiconify()
95 def page_up(self,event):
96 event.widget.yview_scroll(-1, "page")
97 def page_down(self,event):
98 event.widget.yview_scroll(1, "page")
99 def unit_up(self,event):
100 event.widget.yview_scroll(-1, "unit")
101 def unit_down(self,event):
102 event.widget.yview_scroll(1, "unit")
105 self.fenetre.grab_set()
106 self.zone_texte.focus_set()
107 self.fenetre.wait_window(self.fenetre)
110 self.fenetre.destroy()
112 def efface_scroll(self):
113 """ Efface le scroll lorsqu'il n'est pas nécessaire : ne marche pas"""
114 self.scroll_v.pack_forget()
115 #self.scroll_h.pack_forget()
117 def affiche_texte(self,texte):
118 """ Affiche le texte dans la fenêtre """
120 self.zone_texte.insert(END,texte)
122 self.fenetre.update_idletasks()
123 x0,y0,x1,y1 = self.zone_texte.bbox(END)
124 if (y1-y0) < 300 : self.efface_scroll()
129 """ Permet de sauvegarder le texte dans un fichier dont on a demandé le nom
131 file = asksaveasfilename(defaultextension = '.comm',
132 #initialdir = self.appli.CONFIGURATION.rep_user,
133 initialdir = self.appli.CONFIGURATION.initialdir,
134 title="Sauvegarde du "+self.titre)
136 if not save_in_file(file,self.texte,None) :
137 showerror("Sauvegarde impossible",
138 "Impossible de sauvegarder le texte dans le fichier spécifié\n"+
139 "Vérifiez les droits d'écriture")
141 showinfo("Sauvegarde effectuée","Sauvegarde effectuée dans le fichier %s" %file)
145 self.fenetre.destroy()
149 class FenetreYesNo(Fenetre):
150 def __init__(self,appli,titre="",texte="",yes="Yes",no="No"):
152 self.fenetre = Toplevel()
153 self.fenetre.configure(width = 800,height=500)
154 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
155 self.fenetre.title(titre)
156 self.texte = string.replace(texte,'\r\n','\n')
158 fonte=fontes.standardcourier10
159 # définition des frames
160 self.frame_texte = Frame(self.fenetre)
161 self.frame_boutons = Frame(self.fenetre)
162 self.frame_boutons.place(relx=0,rely=0, relwidth=1.,relheight=0.1)
163 self.frame_texte.place( relx=0,rely=0.1, relwidth=1, relheight=0.9)
164 # définition de la zone texte et du scrollbar
165 self.zone_texte = Text(self.frame_texte,font=fonte)
166 self.zone_texte.bind("<Key-Prior>", self.page_up)
167 self.zone_texte.bind("<Key-Next>", self.page_down)
168 self.zone_texte.bind("<Key-Up>", self.unit_up)
169 self.zone_texte.bind("<Key-Down>", self.unit_down)
170 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
171 #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
172 self.scroll_v.pack(side='right',fill ='y')
173 #self.scroll_h.pack(side='bottom',fill ='x')
174 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
175 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
176 # définition des boutons
177 self.but_yes = Button(self.frame_boutons,text = yes,command=self.yes)
178 self.but_no = Button(self.frame_boutons,text = no,command = self.no)
179 self.but_yes.place(relx=0.4,rely=0.5,anchor='center')
180 self.but_no.place(relx=0.6,rely=0.5,anchor='center')
182 self.affiche_texte(self.texte)
183 centerwindow(self.fenetre)
193 class FenetreDeSelection(Fenetre):
194 """ Classe dérivée de Fenêtre permettant la récupération d'une zone de texte sélectionnée.
195 Cette classe est utilisée pour affecter une liste de valeurs à un mot-clé.
197 def __init__(self,panel,item,appli,titre="",texte="",cardinal=1):
198 Fenetre.__init__(self,appli,titre=titre,texte=texte)
199 self.frame_boutons.place_forget()
200 self.frame_texte.place_forget()
201 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.8)
202 self.frame_boutons.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
204 self.cardinal=cardinal
205 self.fenetre.configure(width = 320,height=400)
206 centerwindow(self.fenetre)
209 self.fenetre.title(titre)
210 self.but_save.configure(text="Ajouter",command=self.traite_selection)
211 # séparateur par défaut
212 self.separateur = ';'
213 # création de la zone de saisie du séparateur
214 l_separateurs_autorises = self.get_separateurs_autorises()
215 self.choix_sep = Pmw.ComboBox(self.frame_boutons,
216 label_text = "Séparateur :",
219 selectioncommand = self.choose_separateur,
220 scrolledlist_items = l_separateurs_autorises)
221 self.choix_sep.component('entry').configure(width=6)
222 self.choix_sep.place(relx=0.01,rely=0.5,anchor='w')
223 self.choix_sep.selectitem(self.separateur)
225 self.but_quit.place_forget()
226 self.but_save.place_forget()
227 self.but_all = Button(self.frame_boutons,text = "Tout Sélectionner", command=self.tout)
228 self.but_save.place(relx=0.6,rely=0.6,anchor='center')
229 self.but_quit.place(relx=0.8,rely=0.6,anchor='center')
230 self.but_all.place(relx=0.7,rely=0.2,anchor='center')
231 self.choose_separateur('espace')
234 def get_separateurs_autorises(self):
236 Retourne la liste des séparateurs autorisés
238 return ['espace',';',',']
240 def choose_separateur(self,nom_sep):
242 Affecte à self.separateur le caractère séparateur correspondant à nom_sep
244 if nom_sep == 'espace' :
245 self.separateur = ' '
247 self.separateur = nom_sep
251 texte=self.texte.splitlines()
253 for mot in string.split(l,self.separateur):
254 if mot != '' and mot != ' ' and mot != self.separateur :
256 self.traite_selection(liste)
258 def traite_selection(self,liste=None):
259 """ Cette méthode effectue tous les traitements nécessaires pour vérifier
260 et affecter la liste de valeurs à l'objet réprésenté par self.item
262 # Récupère la liste des chaines de caractères de la zone sélectionnée
265 message,liste = self.recupere_liste()
266 if self.test_probleme(message,"Sélectionnez des données") == 0:
268 # Vérifie que le nombre de données est dans les limites attendues
269 message = self.verif_liste(liste)
270 if self.test_probleme(message,"Vérifiez le nombre de données") == 0:
272 # Crée une liste de valeurs du type attendu
273 message,liste_valeurs = self.creation_liste_valeurs(liste)
274 if self.test_probleme(message,"Vérifiez le type des données") == 0:
276 # Vérifie que chaque valeur est dans le domaine exigé
277 message = self.verif_valeurs(liste_valeurs)
278 if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:
280 # Ajoute les valeurs dans la liste de valeurs du mot-clé
281 if self.cardinal != 1 :
285 if (len(liste_valeurs)%nb != 0):
286 message="La cardinalité n'est pas correcte"
287 self.test_probleme(message,"On attend des tuples")
289 for i in range(len(liste_valeurs)/nb) :
291 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1])
293 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1], liste_valeurs[i*nb+2])
295 print "probleme : prevenir la maintenance Eficas"
298 liste_valeurs=l_valeurs
299 self.ajouter_valeurs(liste_valeurs)
300 self.appli.affiche_infos("Liste de valeurs acceptée")
302 def test_probleme(self, message, message_eficas):
303 """ Cette méthode affiche un message d'erreur si message != ''
304 et retourne 0, sinon retourne 1 sans rien afficher.
307 showinfo("Problème",message)
308 self.fenetre.tkraise()
309 self.appli.affiche_infos(message_eficas)
314 def recupere_liste(self):
315 """ Cette méthode récupère le texte de la zone sélectionnée, construit et
316 retourne une liste avec les chaines qui se trouvent entre les séparateurs.
317 S'il n'y a pas de données selectionnées, elle retourne un message d'erreur
322 selection=self.fenetre.selection_get()
324 message = "Pas de donnée sélectionnée"
326 # les retours chariots doivent être interprétés comme des séparateurs
327 selection = string.replace(selection,'\n',self.separateur)
328 # on splitte la sélection suivant le caractère séparateur
329 liste_chaines = string.split(selection,self.separateur)
331 for chaine in liste_chaines:
332 chaine = string.strip(chaine)
333 if chaine != '' : l_chaines.append(chaine)
334 return message,l_chaines
336 def verif_liste(self, liste):
337 """ Cette méthode effectue des tests sur le nombre d'éléments de la liste
338 et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur
342 # nombre d'éléments sélectionnés
343 nombre_elements = len(liste)
344 # nombre d'éléments déja dans la liste du panel
345 nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())
346 multiplicite = self.item.GetMultiplicite()
347 if (nombre_elements % multiplicite) != 0:
348 message = "Vous devez sélectionner "+str(multiplicite)+" * n données"
350 nombre_valeurs = nombre_elements / multiplicite
351 cardinalite = self.item.GetMinMax()
352 if nombre_valeurs < cardinalite[0]:
353 message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"
355 if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):
356 message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"
361 def creation_liste_valeurs(self, liste):
362 """ Cette méthode crée et retourne une liste de valeurs du type attendu
363 par le mot-clé. La liste de valeurs est créée à partir de la liste
364 de chaines de caractères transmise.
366 type_attendu = self.item.GetType()[0]
367 if type_attendu == 'R':
368 return self.convertir(liste, f_conversion= float)
369 elif type_attendu == 'I':
370 return self.convertir(liste, f_conversion= int)
371 elif type_attendu == 'TXM':
372 return self.convertir(liste)
374 message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"
377 def convertir(self, liste, f_conversion=None):
378 """ Cette méthode essaie de convertir les éléments de la liste avec la
379 fonction f_conversion si elle existe, et retourne la liste des
380 éléments dans le type voulu en cas de succès, sinon retourne None.
387 liste_valeurs.append(f_conversion(chaine))
389 message = "Impossible de convertir "+chaine+" dans le type attendu"
392 liste_valeurs.append(chaine)
393 return message,liste_valeurs
395 def verif_valeurs(self, liste_valeurs):
396 """ Cette méthode teste tous les éléments de la liste, et retourne 1 si chaque
397 élément est dans le domaine voulu.
400 for valeur in liste_valeurs:
401 test = self.item.IsInIntervalle(valeur)
403 intervalle = str(self.item.GetIntervalle()[0])+","+str(self.item.GetIntervalle()[1])
404 message = "La valeur "+str(valeur)+" n'est pas dans l'intervalle ["+intervalle+"]"
408 def ajouter_valeurs(self, liste_valeurs):
409 """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""
410 liste = self.panel.Liste_valeurs.get_liste()
411 liste.extend(liste_valeurs)
412 self.panel.Liste_valeurs.put_liste(liste)
414 class FenetreDeParametre(Fenetre) :
415 def __init__(self,parent,item,appli,texte):
418 self.fenetre = Toplevel()
419 self.fenetre.configure(width = 250,height=100)
420 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
421 self.fenetre.title("Parametres")
422 self.titre = "Parametres"
423 self.texte = string.replace(texte,'\r\n','\n')
424 fonte=fontes.standardcourier10
426 # définition des frames
427 self.frame_texte = Frame(self.fenetre)
428 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.7)
429 # définition de la zone texte et du scrollbar
430 self.zone_texte = Text(self.frame_texte,font=fonte)
431 self.zone_texte.bind("<Key-Prior>", self.page_up)
432 self.zone_texte.bind("<Key-Next>", self.page_down)
433 self.zone_texte.bind("<Key-Up>", self.unit_up)
434 self.zone_texte.bind("<Key-Down>", self.unit_down)
435 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
436 self.scroll_v.pack(side='right',fill ='y')
437 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
438 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
440 self.affiche_texte(self.texte)
441 self.zone_texte.config(state="disabled")
443 # définition des boutons
444 self.frame_boutons = Frame(self.fenetre)
445 self.frame_boutons.place(relheight=0.3,relx=0,rely=0.65,relwidth=1.)
446 self.label1 = Label(self.frame_boutons,text="surligner la")
447 self.label2 = Label(self.frame_boutons,text="ligne entière")
448 self.label1.place(relx=0.1,rely=0)
449 self.label2.place(relx=0.1,rely=0.5)
450 self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
451 self.but_save = Button(self.frame_boutons,text = "Choisir",command = self.Choisir)
452 self.but_save.place(relx=0.6,rely=0,relheight=1)
453 self.but_quit.place(relx=0.8,rely=0,relheight=1)
458 selection=self.zone_texte.selection_get()
460 showerror("Pas de donnée sélectionnée",
461 "Selectionner un parametre")
463 for param in selection.splitlines():
464 nomparam=param[0:param.find("=")-1]
466 l_param=l_param+nomparam+','
467 self.parent.entry.delete(0,Tkinter.END)
468 self.parent.entry.insert(0,l_param[0:-1])
469 self.parent.valid_valeur()
474 Cette classe permet de créer une boîte Dialog dans laquelle
475 on affiche un formulaire à remplir par l'utilisateur
477 def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
478 if items in ((),[]) : return
482 self.fen_pere = fen_pere
483 self.obj_pere = obj_pere
485 self.command = commande
489 self.init_validateurs()
492 self.init_items_formulaire()
493 self.fenetre.activate(geometry='centerscreenalways')
495 def init_validateurs(self):
497 Crée le dictionnaire des validateurs des objets reconnus par le formulaire
499 self.d_validateurs = {}
500 self.d_validateurs['rep'] = self.repvalidator
501 self.d_validateurs['file'] = self.filevalidator
502 self.d_validateurs['cata']= self.catavalidator
504 def init_fenetre(self):
506 Crée la fenêtre Dialog
508 if self.mode == 'query':
509 buttons=('Valider','Annuler')
510 defaultbutton = 'Valider'
511 elif self.mode == 'display':
513 buttons=(self.command[0],'OK')
518 self.fenetre = Pmw.Dialog(self.fen_pere,
520 defaultbutton = defaultbutton,
522 command = self.execute)
523 self.fenetre.withdraw()
525 def init_texte(self):
527 Crée le label qui affiche le texte à l'intérieur du panneau
529 fonte=fontes.standard
530 fr_texte = Frame(self.fenetre.interior(),height=60)
531 fr_texte.pack(side='top',fill='x',expand=1)
532 Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
534 def init_items_formulaire(self):
536 Crée et affiche les items dans la boîte de dialogue
540 self.item_widgets = {}
542 for item in self.items:
543 if len(item[0])>length_maxi : length_maxi = len(item[0])
544 window = self.fenetre.interior()
545 for item in self.items :
547 label,nature,nom_var,defaut = item
551 label,nature,nom_var,defaut,chaine,chaine2 = item
552 # création de la frame
553 fr_item = Frame(window,height=40,width=700)
554 fr_item.pack(side='top',fill='x',expand=1)
556 Label(fr_item,text = label).place(relx=0.05,rely=0.4)
557 if nature in ('rep','file','cata'):
558 # création de l'entry
559 e_item = Entry(fr_item)
560 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
561 self.widgets.append(e_item)
562 self.item_widgets[item] = e_item
563 if defaut : e_item.insert(0,str(defaut))
564 elif nature == 'YesNo':
565 # création de la StringVar
567 setattr(self,'item_'+nom_var,var)
569 # création du radiobouton
570 rb1 = Radiobutton(fr_item,text=chaine,variable=var,value='OUI')
571 rb2 = Radiobutton(fr_item,text=chaine2,variable=var,value='NON')
572 rb1.place(relx=0.65,rely=0.5,anchor='center')
573 rb2.place(relx=0.80,rely=0.5,anchor='center')
574 self.widgets.append((rb1,rb2))
575 self.item_widgets[item] = var
576 # détermination de la méthode à appliquer sur les boutons
577 if self.mode == 'query':
578 function = self.active
579 elif self.mode == 'display':
580 function = self.inactive
583 # on applique la méthode sur les boutons (activation ou désactivation)
584 for widget in self.widgets :
585 if type(widget) == types.TupleType:
587 apply(function,(widg,),{})
589 apply(function,(widget,),{})
591 def active(self,widget):
593 Active le widget passé en argument
595 widget.configure(state='normal',bg='white')
597 def inactive(self,widget):
599 Inactive le widget passé en argument
601 if not isinstance(widget,Radiobutton) :
602 widget.configure(state='disabled',bg='gray95')
604 widget.configure(state='disabled')
606 # --------------------------------------------------------------------------------
607 # Validateurs des noms de répertoire, de fichiers et de catalogues
608 # -------------------------------------------------------------------------------
610 def repvalidator(self,text):
612 Teste si text peut faire référence à un répertoire ou non
613 Retourne 1 si valide, 0 sinon
615 return os.path.isdir(text),'Répertoire introuvable : %s' %text
617 def filevalidator(self,text):
619 Teste si text peut faire référence à un fichier ou non
620 Retourne 1 si valide, 0 sinon
622 return os.path.isfile(text),'Fichier introuvable : %s' %text
624 def catavalidator(self,text):
626 Teste si text est un chemin d'accès valide à un catalogue
627 Retourne 1 si valide, 0 sinon
629 return os.path.isfile(text),"Catalogue introuvable : %s" %text
631 # --------------------------------------------------------------------------------
632 # Méthodes callbacks des boutons et de fin
633 # --------------------------------------------------------------------------------
635 def execute(self,txt):
637 Cette commande est activée à chaque clic sur un bouton.
638 Redirige l'action sur la bonne méthode en fonction du bouton activé
642 elif txt in ('OK','Annuler'):
644 elif txt == 'Modifier':
645 self.resultat = apply(self.command[1],(),{})
646 self.fenetre.destroy()
648 print "Nom de bouton inconnu"
653 Commande qui termine le panneau et sauvegarde les nouvelles options
654 dans l'objet resultat (dictionnaire)
657 for item,widget in self.item_widgets.items():
660 valeur = widget.get()
661 if self.d_validateurs.has_key(type_var):
662 test = self.d_validateurs[type_var](valeur)
664 # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
665 # sans tuer la fenêtre bien sûr
666 widget.selection_range(0,END)
668 dico[nom_var] = valeur
669 self.fenetre.destroy()
673 self.fenetre.destroy()
677 """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
678 en passant les commandes à lancer suivant différents bindings """
679 def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre='',
680 optionReturn=None, fonte_titre=fontes.standard_gras_souligne):
685 self.selection = None
686 self.liste_commandes = liste_commandes
687 self.liste_marques = liste_marques
692 self.optionReturn = optionReturn
693 self.fonte_titre=fonte_titre
697 self.make_label_titre()
698 self.make_entry_filtre()
701 self.entry.component('entry').focus()
705 def make_label_titre(self):
706 """ Crée le label correspondant au titre """
707 if self.titre == '' : return
708 self.label = Label(self.page,
710 font = self.fonte_titre)
711 self.label.pack(side='top',pady=2)
713 def make_entry_filtre(self):
714 """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
715 if self.filtre != 'oui' : return
716 self.entry = Pmw.EntryField(self.page,labelpos='w',
717 label_text="Filtre :",
718 command=self.entry_changed)
719 self.entry.pack(side='top',pady=2)
721 def make_text_box(self):
722 """ Crée la fenêtre texte dans laquelle sera affichée la liste """
723 self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
724 self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
725 self.MCscroll.pack(side='right',fill ='y',pady=2)
726 self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
727 self.MCbox.configure(yscrollcommand=self.MCscroll.set)
730 def affiche_liste(self):
731 """ Affiche la liste dans la fenêtre"""
733 self.MCbox.config(state=NORMAL)
734 self.MCbox.delete(1.0,END)
735 for objet in self.liste :
736 if type(objet) == types.InstanceType:
741 elif type(objet) in (types.StringType,types.IntType):
743 elif type(objet) == types.FloatType :
744 mot = self.parent.get_valeur_texte(objet)
747 elif type(objet) == types.TupleType :
755 valtexte = self.parent.get_valeur_texte(val)
763 label = Label(self.MCbox,
765 fg = 'black',bg = 'gray95',justify = 'left')
766 self.dico_labels[mot]=label
767 liste_labels.append(label)
768 self.MCbox.window_create(END,
771 self.MCbox.insert(END,'\n')
772 if self.optionReturn != None :
773 label.bind("<Return>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
774 label.bind("<KP_Enter>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
775 label.bind("<Key-Right>",lambda e,s=self,x=objet,l=label : s.selectNextItem(x,l))
776 label.bind("<Key-Down>",lambda e, s=self,x=objet,l=label : s.selectNextItem(x,l))
777 label.bind("<Key-Left>" ,lambda e,s=self,x=objet,l=label : s.selectPrevItem(x,l))
778 label.bind("<Key-Up>" ,lambda e,s=self,x=objet,l=label : s.selectPrevItem(x,l))
779 if self.active == 'oui':
780 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))
781 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))
782 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))
784 for marque in self.liste_marques:
786 self.markitem(liste_labels[marque])
790 self.MCbox.config(state=DISABLED)
791 self.selection = None
793 for event,callback in self.liste_commandes:
794 if event == "<Enter>":
795 self.selection=None,None,callback
798 def clear_marque(self):
800 self.dico_labels[self.arg_selected].configure(bg='gray95',fg='black')
801 self.arg_selected = ''
805 def surligne(self,marque):
807 self.highlightitem(self.dico_labels[marque])
808 self.arg_selected = marque
812 def chooseitemsurligne(self,mot,label,commande):
813 """ Active la méthode de choix passée en argument"""
815 mot=self.arg_selected
817 except AsException,e:
819 showerror(raison.split('\n')[0],raison)
821 def chooseitem(self,mot,label,commande):
822 """ Active la méthode de choix passée en argument"""
825 except AsException,e:
827 showerror(raison.split('\n')[0],raison)
829 def selectNextItem(self,mot,label):
830 index=self.liste.index(mot)
832 if indexsuivant > len(self.liste) -1:
834 motsuivant=self.liste[indexsuivant]
835 labelsuivant=self.dico_labels[motsuivant]
836 index = self.MCbox.index(labelsuivant)
837 self.MCbox.see(index)
838 self.selectthis(motsuivant,labelsuivant,self.selection[2],)
841 def selectPrevItem(self,mot,label):
842 index=self.liste.index(mot)
844 motprec=self.liste[indexprec]
845 labelprec=self.dico_labels[motprec]
846 index = self.MCbox.index(labelprec)
847 self.MCbox.see(index)
848 self.selectthis(motprec,labelprec,self.selection[2],)
851 def selectthis(self,mot,label,commande) :
853 if self.selection != None :
854 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
855 self.highlightitem(label)
856 self.selection = (mot,label,commande)
857 self.arg_selected = mot
858 if commande : commande(mot)
860 def selectitem(self,mot,label,commande) :
861 """ Met l'item sélectionné (représenté par son label) en surbrillance
862 et lance la commande associée au double-clic"""
866 self.selectthis(mot,label,commande)
868 def highlightitem(self,label) :
869 """ Met l'item représenté par son label en surbrillance """
871 label.configure(bg='#00008b',fg='white')
873 def markitem(self,label):
874 """ Met l'item (représenté par son label) en rouge """
875 label.configure(bg='gray95',fg='red')
877 def deselectitem(self,label,mot='',commande=None) :
878 """ Remet l'item (représenté par son label) en noir"""
879 if label:label.configure(bg='gray95',fg='black')
880 self.arg_selected = ''
881 if commande and mot : commande(mot)
883 def cherche_selected_item(self):
884 index=self.MCbox.index(self.selection[1])
885 lign,col=map(int,string.split(index,'.'))
888 def remove_selected_item(self):
889 index=self.MCbox.index(self.selection[1])
890 lign,col=map(int,string.split(index,'.'))
891 del self.liste[lign-1]
894 def entry_changed(self,event=None):
895 """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
896 de l'entry et frappe <Return>"""
897 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
898 filtre = self.entry.get()+"*"
899 FILTRE = string.upper(filtre)
900 for arg in self.liste :
901 if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
902 label=self.dico_labels[arg]
903 index = self.MCbox.index(label)
904 self.MCbox.see(index)
905 self.selectitem(arg,label,self.selection[2])
909 #self.dico_labels[self.arg_selected].focus_set()
914 # PN attention à la gestion des paramétres
915 # cela retourne H = 1 , et ni H, ni 1
917 # print val.__class__.__name__
920 for val in self.liste:
928 def put_liste(self,liste):
933 """ Cette classe permet d'afficher au lancement d'EFICAS le message
934 d'attente et la barre de progression"""
935 def __init__(self,master,message,barre ='oui'):
936 from Tools.foztools.foztools import Slider
937 fonte=fontes.standard12_gras
939 self.frame = Frame(self.master)
940 self.frame.pack(expand=1,fill='both')
941 self.mess = Label(self.frame,text=message,justify='center',
942 bd=2,relief='groove',font=fonte)
943 self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
944 self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
945 fillColor='#00008b',width=200,height=30,
946 background='white',labelColor='red')
948 self.progress.frame.pack(in_=self.frame,side='top')
951 self.progress.frame.after(1000,self.update)
953 def configure(self,**options):
954 if options.has_key('message'):
955 self.mess.configure(text=options['message'])
956 if options.has_key('barre'):
957 if options['barre'] == 'oui' :
958 self.progress.frame.pack(in_=self.frame,side='top')
959 elif options['barre'] == 'non' :
960 self.progress.frame.pack_forget()
961 self.master.update_idletasks()
967 def update(self,event=None):
968 """ Permet de faire avancer la barre de progression """
971 bar.value = bar.value+self.increment
973 self.master.after(100,self.update)
977 def configure_barre(self,nb):
978 """ Calcule l'incrément de progression de la barre en fonction
979 du nombre d'opérations à effectuer afin que le compteur
980 soit à 100% à la fin des opérations"""
981 self.increment = 100./nb
982 self.progress.update()
984 class Ask_Format_Fichier :
986 Cette classe permet de créer une fenêtre Toplevel dans laquelle
987 on propose le choix du format de fichier de commandes à ouvrir
989 def __init__(self,appli):
990 self.fenetre = Toplevel()
991 self.fenetre.configure(width = 250,height=150)
992 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
993 self.fenetre.title("Choix du format du fichier de commandes")
994 # définition des frames
995 self.frame_texte = Frame(self.fenetre)
996 self.frame_radioboutons = Frame(self.fenetre)
997 self.frame_bouton_ok = Frame(self.fenetre)
998 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
999 self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
1000 self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
1001 # définition de la zone texte et du scrollbar
1002 zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
1003 zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
1004 # définition des radioboutons
1005 Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
1006 variable=appli.format_fichier,value='Aster').pack(anchor='n')
1007 Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
1008 variable=appli.format_fichier,value='Python').pack(anchor='n')
1009 # création du bouton OK
1010 Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
1011 # centrage de la fenêtre
1012 centerwindow(self.fenetre)
1015 self.fenetre.destroy()
1017 class BARRE_K2000(Toplevel):
1018 def __init__(self,master=None,text = ""):
1019 Toplevel.__init__(self,master,relief='groove')
1020 self.master.iconify()
1021 self.geometry("250x100+0+0")
1022 self.protocol("WM_DELETE_WINDOW",self.quit)
1023 # frame principale dans self (= Toplevel)
1024 self.frame = Frame(self)
1025 self.frame.place(relwidth=1,relheight=1)
1026 # frame contenant le texte à afficher
1027 self.frame_text = Frame(self.frame)
1028 self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
1029 # frame contenant le canvas de la barre
1030 self.frame_canv = Frame(self.frame)
1031 self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
1032 # canvas dans lequel sera affichée la barre K2000
1033 self.canvas = Canvas(self.frame_canv)
1034 self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
1035 # on affiche le texte et la barre
1036 self.build_text(text)
1038 #self.overrideredirect(1)
1039 # on active la barre ...
1040 self.master.after(1000,self.launch)
1041 # on centre la fenêtre
1045 def build_text(self,text):
1047 Affichage de text dans frame_text
1049 self.texte_var = StringVar()
1050 self.texte_var.set(text)
1051 Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
1053 def build_batons(self):
1055 Construit la suite de bâtons dans le canvas
1061 for i in range(0,40):
1062 id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
1063 self.l_batons.append(id)
1067 Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
1071 self.master.deiconify()
1073 if self.sens == 'D':
1074 self.black = self.black+1
1075 l_bat = self.l_batons[0:self.black+1]
1077 elif self.sens == 'G':
1078 self.black = self.black-1
1079 l_bat = self.l_batons[self.black:]
1083 if num_color < 10 : color = 'black'
1084 elif num_color > 90 : color = 'white'
1085 else: color = 'gray'+`num_color`
1086 self.canvas.itemconfigure(bat,fill=color)
1088 if self.black == len(self.l_batons) :
1090 if self.black == 0 and self.sens == 'G':self.sens = 'D'
1091 self.after(80,self.launch)
1093 def update_text(self,new_text):
1095 Remplace le texte affiché par new_text
1097 self.texte_var.set(new_text)
1102 class ListeChoixParGroupes(ListeChoix) :
1104 Cette classe est utilisée pour afficher une liste de commandes classées par
1105 groupes. L'utilisateur peut réaliser des actions de selection
1106 qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
1108 liste_commandes = (("<Enter>",self.selectCmd),
1109 ("<Leave>",self.deselectCmd),
1110 ("<Double-Button-1>",self.defCmd))
1111 Il s'agit d'une liste de doublets dont le premier element est un evenement et le
1112 deuxieme un callback a appeler sur l'evenement en question.
1115 def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
1116 active ='oui',filtre='non',titre='',optionReturn=None,fonte_titre=fontes.standard_gras_souligne):
1117 self.parent = parent
1119 self.liste_groupes = liste_groupes
1120 self.dict_groupes = dict_groupes
1122 self.selection = None
1123 self.liste_commandes = liste_commandes
1124 self.liste_marques = liste_marques
1125 self.arg_selected=''
1126 self.active = active
1128 self.filtre = filtre
1129 self.optionReturn = optionReturn
1130 self.fonte_titre=fonte_titre
1133 def affiche_liste(self):
1134 """ Affiche la liste dans la fenêtre"""
1136 self.MCbox.config(state=NORMAL)
1137 self.MCbox.delete(1.0,END)
1138 for grp in self.liste_groupes:
1139 # On itère sur les groupes
1140 if grp == "CACHE":continue
1141 liste_commandes=self.dict_groupes[grp]
1142 text="GROUPE<<<<<<<< "+grp+" "
1143 text=text+">"*max(0,30-len(text))
1144 label = Label(self.MCbox,
1146 fg = 'black',bg = 'gray95',justify = 'left')
1147 # On stocke la relation entre le nom de la commande et le label
1148 self.dico_labels[grp]=label
1149 liste_labels.append(label)
1150 self.MCbox.window_create(END,
1153 self.MCbox.insert(END,'\n')
1154 for cmd in liste_commandes:
1155 label = Label(self.MCbox,
1157 fg = 'black',bg = 'gray95',justify = 'left')
1158 # On stocke la relation entre le nom de la commande et le label
1159 self.dico_labels[cmd]=label
1160 self.MCbox.window_create(END,
1163 self.MCbox.insert(END,'\n')
1165 def null(*tp,**args): return
1167 if self.active == 'oui':
1168 # Traitement par defaut des evenements
1169 label.bind("<Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.selectitem(x,l,c))
1170 label.bind("<Leave>",lambda e,s=self,c=null,x=cmd,l=label: s.deselectitem(l,x,c))
1171 label.bind("<Double-Button-1>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1172 label.bind("<Return>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1173 label.bind("<KP_Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1174 label.bind("<Key-Right>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1175 label.bind("<Key-Down>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1176 label.bind("<Key-Left>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1177 label.bind("<Key-Up>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1179 # Si des callbacks sont definis on les utilise
1180 for event,callback in self.liste_commandes:
1181 if event == "<Enter>":
1182 label.bind("<Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.selectitem(x,l,c))
1183 elif event == "<Leave>":
1184 label.bind("<Leave>",lambda e,s=self,c=callback,x=cmd,l=label: s.deselectitem(l,x,c))
1185 elif event == "<Double-Button-1>":
1186 label.bind("<Double-Button-1>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1187 elif event == "<Return>":
1188 label.bind("<Return>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1189 elif event == "<KP_Enter>":
1190 label.bind("<KP_Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1191 elif event == "<Key-Right>":
1192 label.bind("<Key-Right>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1193 elif event == "<Key-Down>":
1194 label.bind("<Key-Down>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1195 elif event == "<Key-Left>":
1196 label.bind("<Key-Left>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1197 elif event == "<Key-Up>":
1198 label.bind("<Key-Up>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1200 label.bind(event,lambda e,s=self,c=callback,x=cmd,l=label: c())
1202 for marque in self.liste_marques:
1204 self.markitem(liste_labels[marque])
1208 self.MCbox.config(state=DISABLED)
1209 self.selection = None
1211 for event,callback in self.liste_commandes:
1212 if event == "<Enter>":
1213 self.selection=None,None,callback
1216 def selectPrevItem(self,mot,label,callback,group,cmd):
1217 g=self.liste_groupes.index(group)
1218 liste_commandes=self.dict_groupes[group]
1219 c=liste_commandes.index(cmd)
1221 co=liste_commandes[c-1]
1223 # debut de liste. On passe au groupe precedent
1225 gr=self.liste_groupes[g-1]
1226 co=self.dict_groupes[gr][-1]
1228 # debut des groupes. On ne fait rien
1230 # On a trouve l'item precedent
1231 labelsuivant=self.dico_labels[co]
1232 index = self.MCbox.index(labelsuivant)
1233 self.MCbox.see(index)
1234 self.selectthis(co,labelsuivant,self.selection[2],)
1237 def selectNextItem(self,mot,label,callback,group,cmd):
1238 g=self.liste_groupes.index(group)
1239 liste_commandes=self.dict_groupes[group]
1240 c=liste_commandes.index(cmd)
1242 co=liste_commandes[c+1]
1244 # fin de liste. On passe au groupe suivant
1246 gr=self.liste_groupes[g+1]
1247 co=self.dict_groupes[gr][0]
1249 # fin des groupes. On ne fait rien
1251 # On a trouve l'item suivant
1252 labelsuivant=self.dico_labels[co]
1253 index = self.MCbox.index(labelsuivant)
1254 self.MCbox.see(index)
1255 self.selectthis(co,labelsuivant,self.selection[2],)
1258 def entry_changed(self,event=None):
1260 Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1261 de l'entry et frappe <Return>
1263 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1265 filtre = self.entry.get()+"*"
1266 FILTRE = string.upper(filtre)
1268 # On cherche d'abord dans les noms de groupe
1269 # puis dans les noms de commande groupe par groupe
1271 for grp in self.liste_groupes:
1272 if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1273 cmd=self.dict_groupes[grp][0]
1274 label=self.dico_labels[cmd]
1275 index = self.MCbox.index(label)
1276 self.MCbox.see(index)
1277 self.selectitem(cmd,label,self.selection[2])
1278 # On a trouve un groupe on arrete la recherche
1281 for grp in self.liste_groupes:
1282 for cmd in self.dict_groupes[grp] :
1283 if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1284 label=self.dico_labels[cmd]
1285 index = self.MCbox.index(label)
1286 self.MCbox.see(index)
1287 self.selectitem(cmd,label,self.selection[2])
1288 # On a trouve une commande on arrete la recherche