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
31 from tkFileDialog import *
32 from tkMessageBox import showinfo,askyesno,showerror,askretrycancel
36 from utils import save_in_file
37 from centerwindow import centerwindow
39 from Noyau.N_utils import repr_float
40 from Accas import AsException
42 # Surcharge de la fonction askyesno qui retourne un resultat errone en Python 2.3 avec Tk 8.4
43 # et Tkinter.wantobject==1
45 def askyesno(title=None, message=None, **options):
46 "Ask a question; return true if the answer is yes"
47 s = tkMessageBox._show(title, message, tkMessageBox.QUESTION, tkMessageBox.YESNO, **options)
48 if s == tkMessageBox.YES:return 1
49 if s == tkMessageBox.NO:return 0
55 """ Cette classe permet de créer une fenêtre Toplevel dans laquelle
56 on peut afficher un texte et qui permet de le sauver"""
57 def __init__(self,appli,titre="",texte=""):
59 self.fenetre = Toplevel()
60 self.fenetre.withdraw()
61 self.fenetre.configure(width = 800,height=500)
62 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
63 self.fenetre.title("Visualisation du "+titre)
64 self.texte = string.replace(texte,'\r\n','\n')
66 fonte=fontes.standardcourier10
67 # définition des frames
68 self.frame_texte = Frame(self.fenetre)
69 self.frame_boutons = Frame(self.fenetre)
70 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.9)
71 self.frame_boutons.place(relheight=0.1,relx=0,rely=0.9,relwidth=1.)
72 # définition de la zone texte et du scrollbar
73 self.zone_texte = Text(self.frame_texte,font=fonte)
74 self.zone_texte.bind("<Key-Prior>", self.page_up)
75 self.zone_texte.bind("<Key-Next>", self.page_down)
76 self.zone_texte.bind("<Key-Up>", self.unit_up)
77 self.zone_texte.bind("<Key-Down>", self.unit_down)
78 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
79 #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
80 self.scroll_v.pack(side='right',fill ='y')
81 #self.scroll_h.pack(side='bottom',fill ='x')
82 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
83 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
84 # définition des boutons
85 self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
86 self.but_save = Button(self.frame_boutons,text = "sauver",command = self.save)
87 self.but_quit.place(relx=0.4,rely=0.5,anchor='center')
88 self.but_save.place(relx=0.6,rely=0.5,anchor='center')
90 self.affiche_texte(self.texte)
91 centerwindow(self.fenetre)
92 self.fenetre.deiconify()
94 def page_up(self,event):
95 event.widget.yview_scroll(-1, "page")
96 def page_down(self,event):
97 event.widget.yview_scroll(1, "page")
98 def unit_up(self,event):
99 event.widget.yview_scroll(-1, "unit")
100 def unit_down(self,event):
101 event.widget.yview_scroll(1, "unit")
104 self.fenetre.grab_set()
105 self.zone_texte.focus_set()
106 self.fenetre.wait_window(self.fenetre)
109 self.fenetre.destroy()
111 def efface_scroll(self):
112 """ Efface le scroll lorsqu'il n'est pas nécessaire : ne marche pas"""
113 self.scroll_v.pack_forget()
114 #self.scroll_h.pack_forget()
116 def affiche_texte(self,texte):
117 """ Affiche le texte dans la fenêtre """
119 self.zone_texte.insert(END,texte)
121 self.fenetre.update_idletasks()
122 x0,y0,x1,y1 = self.zone_texte.bbox(END)
123 if (y1-y0) < 300 : self.efface_scroll()
128 """ Permet de sauvegarder le texte dans un fichier dont on a demandé le nom
130 file = asksaveasfilename(defaultextension = '.comm',
131 #initialdir = self.appli.CONFIGURATION.rep_user,
132 initialdir = self.appli.CONFIGURATION.initialdir,
133 title="Sauvegarde du "+self.titre)
135 if not save_in_file(file,self.texte,None) :
136 showerror("Sauvegarde impossible",
137 "Impossible de sauvegarder le texte dans le fichier spécifié\n"+
138 "Vérifiez les droits d'écriture")
140 showinfo("Sauvegarde effectuée","Sauvegarde effectuée dans le fichier %s" %file)
144 self.fenetre.destroy()
148 class FenetreYesNo(Fenetre):
149 def __init__(self,appli,titre="",texte="",yes="Yes",no="No"):
151 self.fenetre = Toplevel()
152 self.fenetre.configure(width = 800,height=500)
153 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
154 self.fenetre.title(titre)
155 self.texte = string.replace(texte,'\r\n','\n')
157 fonte=fontes.standardcourier10
158 # définition des frames
159 self.frame_texte = Frame(self.fenetre)
160 self.frame_boutons = Frame(self.fenetre)
161 self.frame_boutons.place(relx=0,rely=0, relwidth=1.,relheight=0.1)
162 self.frame_texte.place( relx=0,rely=0.1, relwidth=1, relheight=0.9)
163 # définition de la zone texte et du scrollbar
164 self.zone_texte = Text(self.frame_texte,font=fonte)
165 self.zone_texte.bind("<Key-Prior>", self.page_up)
166 self.zone_texte.bind("<Key-Next>", self.page_down)
167 self.zone_texte.bind("<Key-Up>", self.unit_up)
168 self.zone_texte.bind("<Key-Down>", self.unit_down)
169 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
170 #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
171 self.scroll_v.pack(side='right',fill ='y')
172 #self.scroll_h.pack(side='bottom',fill ='x')
173 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
174 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
175 # définition des boutons
176 self.but_yes = Button(self.frame_boutons,text = yes,command=self.yes)
177 self.but_no = Button(self.frame_boutons,text = no,command = self.no)
178 self.but_yes.place(relx=0.4,rely=0.5,anchor='center')
179 self.but_no.place(relx=0.6,rely=0.5,anchor='center')
181 self.affiche_texte(self.texte)
182 centerwindow(self.fenetre)
192 class FenetreDeSelection(Fenetre):
193 """ Classe dérivée de Fenêtre permettant la récupération d'une zone de texte sélectionnée.
194 Cette classe est utilisée pour affecter une liste de valeurs à un mot-clé.
196 def __init__(self,panel,item,appli,titre="",texte="",cardinal=1):
197 Fenetre.__init__(self,appli,titre=titre,texte=texte)
198 self.frame_boutons.place_forget()
199 self.frame_texte.place_forget()
200 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.8)
201 self.frame_boutons.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
203 self.cardinal=cardinal
204 self.fenetre.configure(width = 320,height=400)
205 centerwindow(self.fenetre)
208 self.fenetre.title(titre)
209 self.but_save.configure(text="Ajouter",command=self.traite_selection)
210 # séparateur par défaut
211 self.separateur = ';'
212 # création de la zone de saisie du séparateur
213 l_separateurs_autorises = self.get_separateurs_autorises()
214 self.choix_sep = Pmw.ComboBox(self.frame_boutons,
215 label_text = "Séparateur :",
218 selectioncommand = self.choose_separateur,
219 scrolledlist_items = l_separateurs_autorises)
220 self.choix_sep.component('entry').configure(width=6)
221 self.choix_sep.place(relx=0.01,rely=0.5,anchor='w')
222 self.choix_sep.selectitem(self.separateur)
224 self.but_quit.place_forget()
225 self.but_save.place_forget()
226 self.but_all = Button(self.frame_boutons,text = "Tout Sélectionner", command=self.tout)
227 self.but_save.place(relx=0.6,rely=0.6,anchor='center')
228 self.but_quit.place(relx=0.8,rely=0.6,anchor='center')
229 self.but_all.place(relx=0.7,rely=0.2,anchor='center')
230 self.choose_separateur('espace')
233 def get_separateurs_autorises(self):
235 Retourne la liste des séparateurs autorisés
237 return ['espace',';',',']
239 def choose_separateur(self,nom_sep):
241 Affecte à self.separateur le caractère séparateur correspondant à nom_sep
243 if nom_sep == 'espace' :
244 self.separateur = ' '
246 self.separateur = nom_sep
250 texte=self.texte.splitlines()
252 for mot in string.split(l,self.separateur):
253 if mot != '' and mot != ' ' and mot != self.separateur :
255 self.traite_selection(liste)
257 def traite_selection(self,liste=None):
258 """ Cette méthode effectue tous les traitements nécessaires pour vérifier
259 et affecter la liste de valeurs à l'objet réprésenté par self.item
261 # Récupère la liste des chaines de caractères de la zone sélectionnée
264 message,liste = self.recupere_liste()
265 if self.test_probleme(message,"Sélectionnez des données") == 0:
267 # Vérifie que le nombre de données est dans les limites attendues
268 message = self.verif_liste(liste)
269 if self.test_probleme(message,"Vérifiez le nombre de données") == 0:
271 # Crée une liste de valeurs du type attendu
272 message,liste_valeurs = self.creation_liste_valeurs(liste)
273 if self.test_probleme(message,"Vérifiez le type des données") == 0:
275 # Vérifie que chaque valeur est dans le domaine exigé
276 message = self.verif_valeurs(liste_valeurs)
277 if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:
279 # Ajoute les valeurs dans la liste de valeurs du mot-clé
280 if self.cardinal != 1 :
284 if (len(liste_valeurs)%nb != 0):
285 message="La cardinalité n'est pas correcte"
286 self.test_probleme(message,"On attend des tuples")
288 for i in range(len(liste_valeurs)/nb) :
290 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1])
292 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1], liste_valeurs[i*nb+2])
294 print "probleme : prevenir la maintenance Eficas"
297 liste_valeurs=l_valeurs
298 self.ajouter_valeurs(liste_valeurs)
299 self.appli.affiche_infos("Liste de valeurs acceptée")
301 def test_probleme(self, message, message_eficas):
302 """ Cette méthode affiche un message d'erreur si message != ''
303 et retourne 0, sinon retourne 1 sans rien afficher.
306 showinfo("Problème",message)
307 self.fenetre.tkraise()
308 self.appli.affiche_infos(message_eficas)
313 def recupere_liste(self):
314 """ Cette méthode récupère le texte de la zone sélectionnée, construit et
315 retourne une liste avec les chaines qui se trouvent entre les séparateurs.
316 S'il n'y a pas de données selectionnées, elle retourne un message d'erreur
321 selection=self.fenetre.selection_get()
323 message = "Pas de donnée sélectionnée"
325 # les retours chariots doivent être interprétés comme des séparateurs
326 selection = string.replace(selection,'\n',self.separateur)
327 # on splitte la sélection suivant le caractère séparateur
328 liste_chaines = string.split(selection,self.separateur)
330 for chaine in liste_chaines:
331 chaine = string.strip(chaine)
332 if chaine != '' : l_chaines.append(chaine)
333 return message,l_chaines
335 def verif_liste(self, liste):
336 """ Cette méthode effectue des tests sur le nombre d'éléments de la liste
337 et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur
341 # nombre d'éléments sélectionnés
342 nombre_elements = len(liste)
343 # nombre d'éléments déja dans la liste du panel
344 nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())
345 multiplicite = self.item.GetMultiplicite()
346 if (nombre_elements % multiplicite) != 0:
347 message = "Vous devez sélectionner "+str(multiplicite)+" * n données"
349 nombre_valeurs = nombre_elements / multiplicite
350 cardinalite = self.item.GetMinMax()
351 if nombre_valeurs < cardinalite[0]:
352 message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"
354 if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):
355 message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"
360 def creation_liste_valeurs(self, liste):
361 """ Cette méthode crée et retourne une liste de valeurs du type attendu
362 par le mot-clé. La liste de valeurs est créée à partir de la liste
363 de chaines de caractères transmise.
365 type_attendu = self.item.GetType()[0]
366 if type_attendu == 'R':
367 return self.convertir(liste, f_conversion= float)
368 elif type_attendu == 'I':
369 return self.convertir(liste, f_conversion= int)
370 elif type_attendu == 'TXM':
371 return self.convertir(liste)
373 message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"
376 def convertir(self, liste, f_conversion=None):
377 """ Cette méthode essaie de convertir les éléments de la liste avec la
378 fonction f_conversion si elle existe, et retourne la liste des
379 éléments dans le type voulu en cas de succès, sinon retourne None.
386 liste_valeurs.append(f_conversion(chaine))
388 message = "Impossible de convertir "+chaine+" dans le type attendu"
391 liste_valeurs.append(chaine)
392 return message,liste_valeurs
394 def verif_valeurs(self, liste_valeurs):
395 """ Cette méthode teste tous les éléments de la liste, et retourne 1 si chaque
396 élément est dans le domaine voulu.
399 for valeur in liste_valeurs:
400 test = self.item.IsInIntervalle(valeur)
402 intervalle = str(self.item.GetIntervalle()[0])+","+str(self.item.GetIntervalle()[1])
403 message = "La valeur "+str(valeur)+" n'est pas dans l'intervalle ["+intervalle+"]"
407 def ajouter_valeurs(self, liste_valeurs):
408 """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""
409 liste = self.panel.Liste_valeurs.get_liste()
410 liste.extend(liste_valeurs)
411 self.panel.Liste_valeurs.put_liste(liste)
413 class FenetreDeParametre(Fenetre) :
414 def __init__(self,parent,item,appli,texte):
417 self.fenetre = Toplevel()
418 self.fenetre.configure(width = 250,height=100)
419 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
420 self.fenetre.title("Parametres")
421 self.titre = "Parametres"
422 self.texte = string.replace(texte,'\r\n','\n')
423 fonte=fontes.standardcourier10
425 # définition des frames
426 self.frame_texte = Frame(self.fenetre)
427 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.7)
428 # définition de la zone texte et du scrollbar
429 self.zone_texte = Text(self.frame_texte,font=fonte)
430 self.zone_texte.bind("<Key-Prior>", self.page_up)
431 self.zone_texte.bind("<Key-Next>", self.page_down)
432 self.zone_texte.bind("<Key-Up>", self.unit_up)
433 self.zone_texte.bind("<Key-Down>", self.unit_down)
434 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
435 self.scroll_v.pack(side='right',fill ='y')
436 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
437 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
439 self.affiche_texte(self.texte)
440 self.zone_texte.config(state="disabled")
442 # définition des boutons
443 self.frame_boutons = Frame(self.fenetre)
444 self.frame_boutons.place(relheight=0.3,relx=0,rely=0.65,relwidth=1.)
445 self.label1 = Label(self.frame_boutons,text="surligner la")
446 self.label2 = Label(self.frame_boutons,text="ligne entière")
447 self.label1.place(relx=0.1,rely=0)
448 self.label2.place(relx=0.1,rely=0.5)
449 self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
450 self.but_save = Button(self.frame_boutons,text = "Choisir",command = self.Choisir)
451 self.but_save.place(relx=0.6,rely=0,relheight=1)
452 self.but_quit.place(relx=0.8,rely=0,relheight=1)
457 selection=self.zone_texte.selection_get()
459 showerror("Pas de donnée sélectionnée",
460 "Selectionner un parametre")
462 for param in selection.splitlines():
463 nomparam=param[0:param.find("=")-1]
465 l_param=l_param+nomparam+','
466 self.parent.entry.delete(0,Tkinter.END)
467 self.parent.entry.insert(0,l_param[0:-1])
468 self.parent.valid_valeur()
473 Cette classe permet de créer une boîte Dialog dans laquelle
474 on affiche un formulaire à remplir par l'utilisateur
476 def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
477 if items in ((),[]) : return
481 self.fen_pere = fen_pere
482 self.obj_pere = obj_pere
484 self.command = commande
488 self.init_validateurs()
491 self.init_items_formulaire()
492 self.fenetre.activate(geometry='centerscreenalways')
494 def init_validateurs(self):
496 Crée le dictionnaire des validateurs des objets reconnus par le formulaire
498 self.d_validateurs = {}
499 self.d_validateurs['rep'] = self.repvalidator
500 self.d_validateurs['file'] = self.filevalidator
501 self.d_validateurs['cata']= self.catavalidator
503 def init_fenetre(self):
505 Crée la fenêtre Dialog
507 if self.mode == 'query':
508 buttons=('Valider','Annuler')
509 defaultbutton = 'Valider'
510 elif self.mode == 'display':
512 buttons=(self.command[0],'OK')
517 self.fenetre = Pmw.Dialog(self.fen_pere,
519 defaultbutton = defaultbutton,
521 command = self.execute)
522 self.fenetre.withdraw()
524 def init_texte(self):
526 Crée le label qui affiche le texte à l'intérieur du panneau
528 fonte=fontes.standard
529 fr_texte = Frame(self.fenetre.interior(),height=60)
530 fr_texte.pack(side='top',fill='x',expand=1)
531 Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
533 def init_items_formulaire(self):
535 Crée et affiche les items dans la boîte de dialogue
539 self.item_widgets = {}
541 for item in self.items:
542 if len(item[0])>length_maxi : length_maxi = len(item[0])
543 window = self.fenetre.interior()
544 for item in self.items :
545 label,nature,nom_var,defaut = item
546 # création de la frame
547 fr_item = Frame(window,height=40,width=700)
548 fr_item.pack(side='top',fill='x',expand=1)
550 Label(fr_item,text = label).place(relx=0.05,rely=0.4)
551 if nature in ('rep','file','cata'):
552 # création de l'entry
553 e_item = Entry(fr_item)
554 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
555 self.widgets.append(e_item)
556 self.item_widgets[item] = e_item
557 if defaut : e_item.insert(0,str(defaut))
558 elif nature == 'YesNo':
559 # création de la StringVar
561 setattr(self,'item_'+nom_var,var)
563 # création du radiobouton
564 rb1 = Radiobutton(fr_item,text='OUI',variable=var,value='OUI')
565 rb2 = Radiobutton(fr_item,text='NON',variable=var,value='NON')
566 rb1.place(relx=0.65,rely=0.5,anchor='center')
567 rb2.place(relx=0.80,rely=0.5,anchor='center')
568 self.widgets.append((rb1,rb2))
569 self.item_widgets[item] = var
570 # détermination de la méthode à appliquer sur les boutons
571 if self.mode == 'query':
572 function = self.active
573 elif self.mode == 'display':
574 function = self.inactive
577 # on applique la méthode sur les boutons (activation ou désactivation)
578 for widget in self.widgets :
579 if type(widget) == types.TupleType:
581 apply(function,(widg,),{})
583 apply(function,(widget,),{})
585 def active(self,widget):
587 Active le widget passé en argument
589 widget.configure(state='normal',bg='white')
591 def inactive(self,widget):
593 Inactive le widget passé en argument
595 if not isinstance(widget,Radiobutton) :
596 widget.configure(state='disabled',bg='gray95')
598 widget.configure(state='disabled')
600 # --------------------------------------------------------------------------------
601 # Validateurs des noms de répertoire, de fichiers et de catalogues
602 # -------------------------------------------------------------------------------
604 def repvalidator(self,text):
606 Teste si text peut faire référence à un répertoire ou non
607 Retourne 1 si valide, 0 sinon
609 return os.path.isdir(text),'Répertoire introuvable : %s' %text
611 def filevalidator(self,text):
613 Teste si text peut faire référence à un fichier ou non
614 Retourne 1 si valide, 0 sinon
616 return os.path.isfile(text),'Fichier introuvable : %s' %text
618 def catavalidator(self,text):
620 Teste si text est un chemin d'accès valide à un catalogue
621 Retourne 1 si valide, 0 sinon
623 return os.path.isfile(text),"Catalogue introuvable : %s" %text
625 # --------------------------------------------------------------------------------
626 # Méthodes callbacks des boutons et de fin
627 # --------------------------------------------------------------------------------
629 def execute(self,txt):
631 Cette commande est activée à chaque clic sur un bouton.
632 Redirige l'action sur la bonne méthode en fonction du bouton activé
636 elif txt in ('OK','Annuler'):
638 elif txt == 'Modifier':
639 self.resultat = apply(self.command[1],(),{})
640 self.fenetre.destroy()
642 print "Nom de bouton inconnu"
647 Commande qui termine le panneau et sauvegarde les nouvelles options
648 dans l'objet resultat (dictionnaire)
651 for item,widget in self.item_widgets.items():
654 valeur = widget.get()
655 if self.d_validateurs.has_key(type_var):
656 test = self.d_validateurs[type_var](valeur)
658 # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
659 # sans tuer la fenêtre bien sûr
660 widget.selection_range(0,END)
662 dico[nom_var] = valeur
663 self.fenetre.destroy()
667 self.fenetre.destroy()
671 """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
672 en passant les commandes à lancer suivant différents bindings """
673 def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre='',optionReturn=None, fonte_titre=fontes.standard_gras_souligne):
678 self.selection = None
679 self.liste_commandes = liste_commandes
680 self.liste_marques = liste_marques
685 self.optionReturn = optionReturn
686 self.fonte_titre=fonte_titre
690 self.make_label_titre()
691 self.make_entry_filtre()
694 self.entry.component('entry').focus()
698 def make_label_titre(self):
699 """ Crée le label correspondant au titre """
700 if self.titre == '' : return
701 self.label = Label(self.page,
703 font = self.fonte_titre)
704 self.label.pack(side='top',pady=2)
706 def make_entry_filtre(self):
707 """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
708 if self.filtre != 'oui' : return
709 self.entry = Pmw.EntryField(self.page,labelpos='w',
710 label_text="Filtre :",
711 command=self.entry_changed)
712 self.entry.pack(side='top',pady=2)
714 def make_text_box(self):
715 """ Crée la fenêtre texte dans laquelle sera affichée la liste """
716 self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
717 self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
718 self.MCscroll.pack(side='right',fill ='y',pady=2)
719 self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
720 self.MCbox.configure(yscrollcommand=self.MCscroll.set)
723 def affiche_liste(self):
724 """ Affiche la liste dans la fenêtre"""
726 self.MCbox.config(state=NORMAL)
727 self.MCbox.delete(1.0,END)
728 for objet in self.liste :
729 if type(objet) == types.InstanceType:
734 elif type(objet) in (types.StringType,types.IntType):
736 elif type(objet) == types.FloatType :
737 mot = self.parent.get_valeur_texte(objet)
740 elif type(objet) == types.TupleType :
748 valtexte = self.parent.get_valeur_texte(val)
756 label = Label(self.MCbox,
758 fg = 'black',bg = 'gray95',justify = 'left')
759 self.dico_labels[mot]=label
760 liste_labels.append(label)
761 self.MCbox.window_create(END,
764 self.MCbox.insert(END,'\n')
765 if self.optionReturn != None :
766 label.bind("<Return>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
767 label.bind("<KP_Enter>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
768 label.bind("<Key-Right>",lambda e,s=self,x=objet,l=label : s.selectNextItem(x,l))
769 label.bind("<Key-Left>" ,lambda e,s=self,x=objet,l=label : s.selectPrevItem(x,l))
770 if self.active == 'oui':
771 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))
772 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))
773 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))
775 for marque in self.liste_marques:
777 self.markitem(liste_labels[marque])
781 self.MCbox.config(state=DISABLED)
782 self.selection = None
784 def clear_marque(self):
786 self.dico_labels[self.arg_selected].configure(bg='gray95',fg='black')
787 self.arg_selected = ''
791 def surligne(self,marque):
793 self.highlightitem(self.dico_labels[marque])
794 self.arg_selected = marque
798 def chooseitemsurligne(self,mot,label,commande):
799 """ Active la méthode de choix passée en argument"""
801 mot=self.arg_selected
803 except AsException,e:
805 showerror(raison.split('\n')[0],raison)
807 def chooseitem(self,mot,label,commande):
808 """ Active la méthode de choix passée en argument"""
811 except AsException,e:
813 showerror(raison.split('\n')[0],raison)
815 def selectNextItem(self,mot,label):
817 index=self.liste.index(mot)
819 if indexsuivant > len(self.liste) -1:
821 motsuivant=self.liste[indexsuivant]
822 labelsuivant=self.dico_labels[motsuivant]
824 if self.selection != None :
825 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
826 self.selection = (mot,label,self.selection[2])
827 index = self.MCbox.index(labelsuivant)
828 self.MCbox.see(index)
829 self.highlightitem(labelsuivant)
830 self.arg_selected=motsuivant
831 labelsuivant.focus_set()
832 # PN il faut faire quelque chose pour être dans la fenetre
836 def selectPrevItem(self,mot,label):
838 index=self.liste.index(mot)
840 motprec=self.liste[indexprec]
841 labelprec=self.dico_labels[motprec]
843 if self.selection != None :
844 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
845 self.selection = (mot,label,self.selection[2])
846 index = self.MCbox.index(labelprec)
847 self.MCbox.see(index)
848 self.highlightitem(labelprec)
849 self.arg_selected=motprec
850 labelprec.focus_set()
851 # PN il faut faire quelque chose pour être dans la fenetre
856 def selectitem(self,mot,label,commande) :
857 """ Met l'item sélectionné (représenté par son label) en surbrillance
858 et lance la commande associée au double-clic"""
860 if self.selection != None :
861 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
862 self.highlightitem(label)
863 self.selection = (mot,label,commande)
864 self.arg_selected = mot
867 def highlightitem(self,label) :
868 """ Met l'item représenté par son label en surbrillance """
870 label.configure(bg='#00008b',fg='white')
872 def markitem(self,label):
873 """ Met l'item (représenté par son label) en rouge """
874 label.configure(bg='gray95',fg='red')
876 def deselectitem(self,label,mot='',commande=None) :
877 """ Remet l'item (représenté par son label) en noir"""
878 label.configure(bg='gray95',fg='black')
879 self.arg_selected = ''
880 if commande != None : commande(mot)
882 def cherche_selected_item(self):
883 index=self.MCbox.index(self.selection[1])
884 lign,col=map(int,string.split(index,'.'))
887 def remove_selected_item(self):
888 index=self.MCbox.index(self.selection[1])
889 lign,col=map(int,string.split(index,'.'))
890 del self.liste[lign-1]
893 def entry_changed(self,event=None):
894 """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
895 de l'entry et frappe <Return>"""
896 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
897 filtre = self.entry.get()+"*"
898 FILTRE = string.upper(filtre)
899 for arg in self.liste :
900 if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
901 self.highlightitem(self.dico_labels[arg])
902 index = self.MCbox.index(self.dico_labels[arg])
903 self.MCbox.see(index)
904 self.arg_selected = arg
905 self.dico_labels[self.arg_selected].focus_set()
909 #self.dico_labels[self.arg_selected].focus_set()
913 def get_liste_BAK(self):
917 # PN attention à la gestion des paramétres
918 # cela retourne H = 1 , et ni H, ni 1
920 # print val.__class__.__name__
923 for val in self.liste:
931 def put_liste(self,liste):
936 """ Cette classe permet d'afficher au lancement d'EFICAS le message
937 d'attente et la barre de progression"""
938 def __init__(self,master,message,barre ='oui'):
939 from Tools.foztools.foztools import Slider
940 fonte=fontes.standard12_gras
942 self.frame = Frame(self.master)
943 self.frame.pack(expand=1,fill='both')
944 self.mess = Label(self.frame,text=message,justify='center',
945 bd=2,relief='groove',font=fonte)
946 self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
947 self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
948 fillColor='#00008b',width=200,height=30,
949 background='white',labelColor='red')
951 self.progress.frame.pack(in_=self.frame,side='top')
954 self.progress.frame.after(1000,self.update)
956 def configure(self,**options):
957 if options.has_key('message'):
958 self.mess.configure(text=options['message'])
959 if options.has_key('barre'):
960 if options['barre'] == 'oui' :
961 self.progress.frame.pack(in_=self.frame,side='top')
962 elif options['barre'] == 'non' :
963 self.progress.frame.pack_forget()
964 self.master.update_idletasks()
970 def update(self,event=None):
971 """ Permet de faire avancer la barre de progression """
974 bar.value = bar.value+self.increment
976 self.master.after(100,self.update)
980 def configure_barre(self,nb):
981 """ Calcule l'incrément de progression de la barre en fonction
982 du nombre d'opérations à effectuer afin que le compteur
983 soit à 100% à la fin des opérations"""
984 self.increment = 100./nb
985 self.progress.update()
987 class Ask_Format_Fichier :
989 Cette classe permet de créer une fenêtre Toplevel dans laquelle
990 on propose le choix du format de fichier de commandes à ouvrir
992 def __init__(self,appli):
993 self.fenetre = Toplevel()
994 self.fenetre.configure(width = 250,height=150)
995 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
996 self.fenetre.title("Choix du format du fichier de commandes")
997 # définition des frames
998 self.frame_texte = Frame(self.fenetre)
999 self.frame_radioboutons = Frame(self.fenetre)
1000 self.frame_bouton_ok = Frame(self.fenetre)
1001 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
1002 self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
1003 self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
1004 # définition de la zone texte et du scrollbar
1005 zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
1006 zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
1007 # définition des radioboutons
1008 Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
1009 variable=appli.format_fichier,value='Aster').pack(anchor='n')
1010 Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
1011 variable=appli.format_fichier,value='Python').pack(anchor='n')
1012 # création du bouton OK
1013 Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
1014 # centrage de la fenêtre
1015 centerwindow(self.fenetre)
1018 self.fenetre.destroy()
1020 class BARRE_K2000(Toplevel):
1021 def __init__(self,master=None,text = ""):
1022 Toplevel.__init__(self,master,relief='groove')
1023 self.master.iconify()
1024 self.geometry("250x100+0+0")
1025 self.protocol("WM_DELETE_WINDOW",self.quit)
1026 # frame principale dans self (= Toplevel)
1027 self.frame = Frame(self)
1028 self.frame.place(relwidth=1,relheight=1)
1029 # frame contenant le texte à afficher
1030 self.frame_text = Frame(self.frame)
1031 self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
1032 # frame contenant le canvas de la barre
1033 self.frame_canv = Frame(self.frame)
1034 self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
1035 # canvas dans lequel sera affichée la barre K2000
1036 self.canvas = Canvas(self.frame_canv)
1037 self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
1038 # on affiche le texte et la barre
1039 self.build_text(text)
1041 #self.overrideredirect(1)
1042 # on active la barre ...
1043 self.master.after(1000,self.launch)
1044 # on centre la fenêtre
1048 def build_text(self,text):
1050 Affichage de text dans frame_text
1052 self.texte_var = StringVar()
1053 self.texte_var.set(text)
1054 Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
1056 def build_batons(self):
1058 Construit la suite de bâtons dans le canvas
1064 for i in range(0,40):
1065 id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
1066 self.l_batons.append(id)
1070 Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
1074 self.master.deiconify()
1076 if self.sens == 'D':
1077 self.black = self.black+1
1078 l_bat = self.l_batons[0:self.black+1]
1080 elif self.sens == 'G':
1081 self.black = self.black-1
1082 l_bat = self.l_batons[self.black:]
1086 if num_color < 10 : color = 'black'
1087 elif num_color > 90 : color = 'white'
1088 else: color = 'gray'+`num_color`
1089 self.canvas.itemconfigure(bat,fill=color)
1091 if self.black == len(self.l_batons) :
1093 if self.black == 0 and self.sens == 'G':self.sens = 'D'
1094 self.after(80,self.launch)
1096 def update_text(self,new_text):
1098 Remplace le texte affiché par new_text
1100 self.texte_var.set(new_text)
1105 class ListeChoixParGroupes(ListeChoix) :
1107 Cette classe est utilisée pour afficher une liste de commandes classées par
1108 groupes. L'utilisateur peut réaliser des actions de selection
1109 qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
1111 liste_commandes = (("<Enter>",self.selectCmd),
1112 ("<Leave>",self.deselectCmd),
1113 ("<Double-Button-1>",self.defCmd))
1114 Il s'agit d'une liste de doublets dont le premier element est un evenement et le
1115 deuxieme un callback a appeler sur l'evenement en question.
1118 def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
1119 active ='oui',filtre='non',titre='',optionReturn=None):
1120 self.parent = parent
1122 self.liste_groupes = liste_groupes
1123 self.dict_groupes = dict_groupes
1125 self.selection = None
1126 self.liste_commandes = liste_commandes
1127 self.liste_marques = liste_marques
1128 self.arg_selected=''
1129 self.active = active
1131 self.filtre = filtre
1132 self.optionReturn = optionReturn
1135 def affiche_liste(self):
1136 """ Affiche la liste dans la fenêtre"""
1138 self.MCbox.config(state=NORMAL)
1139 self.MCbox.delete(1.0,END)
1140 for grp in self.liste_groupes:
1141 # On itère sur les groupes
1142 if grp == "CACHE":continue
1143 liste_commandes=self.dict_groupes[grp]
1144 text="GROUPE<<<<<<<< "+grp+" "
1145 text=text+">"*max(0,30-len(text))
1146 label = Label(self.MCbox,
1148 fg = 'black',bg = 'gray95',justify = 'left')
1149 # On stocke la relation entre le nom de la commande et le label
1150 self.dico_labels[grp]=label
1151 liste_labels.append(label)
1152 self.MCbox.window_create(END,
1155 self.MCbox.insert(END,'\n')
1156 for cmd in liste_commandes:
1157 label = Label(self.MCbox,
1159 fg = 'black',bg = 'gray95',justify = 'left')
1160 # On stocke la relation entre le nom de la commande et le label
1161 self.dico_labels[cmd]=label
1162 self.MCbox.window_create(END,
1165 self.MCbox.insert(END,'\n')
1167 def null(*tp,**args): return
1169 if self.active == 'oui':
1170 # Traitement par defaut des evenements
1171 label.bind("<Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.selectitem(x,l,c))
1172 label.bind("<Leave>",lambda e,s=self,c=null,x=cmd,l=label: s.deselectitem(l,x,c))
1173 label.bind("<Double-Button-1>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1174 label.bind("<Return>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1175 label.bind("<KP_Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1176 label.bind("<Key-Right>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1177 label.bind("<Key-Down>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1178 label.bind("<Key-Left>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1179 label.bind("<Key-Up>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1181 # Si des callbacks sont definis on les utilise
1182 for event,callback in self.liste_commandes:
1183 if event == "<Enter>":
1184 label.bind("<Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.selectitem(x,l,c))
1185 elif event == "<Leave>":
1186 label.bind("<Leave>",lambda e,s=self,c=callback,x=cmd,l=label: s.deselectitem(l,x,c))
1187 elif event == "<Double-Button-1>":
1188 label.bind("<Double-Button-1>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1189 elif event == "<Return>":
1190 label.bind("<Return>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1191 elif event == "<KP_Enter>":
1192 label.bind("<KP_Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1193 elif event == "<Key-Right>":
1194 label.bind("<Key-Right>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1195 elif event == "<Key-Down>":
1196 label.bind("<Key-Down>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1197 elif event == "<Key-Left>":
1198 label.bind("<Key-Left>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1199 elif event == "<Key-Up>":
1200 label.bind("<Key-Up>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1202 label.bind(event,lambda e,s=self,c=callback,x=cmd,l=label: c())
1204 for marque in self.liste_marques:
1206 self.markitem(liste_labels[marque])
1210 self.MCbox.config(state=DISABLED)
1211 self.selection = None
1213 def selectPrevItem(self,mot,label,callback,group,cmd):
1214 g=self.liste_groupes.index(group)
1215 liste_commandes=self.dict_groupes[group]
1216 c=liste_commandes.index(cmd)
1218 co=liste_commandes[c-1]
1220 # debut de liste. On passe au groupe precedent
1222 gr=self.liste_groupes[g-1]
1223 co=self.dict_groupes[gr][-1]
1225 # debut des groupes. On ne fait rien
1228 # On a trouve l'item precedent
1230 labelsuivant=self.dico_labels[co]
1231 if self.selection != None :
1232 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
1233 self.selection = (co,labelsuivant,self.selection[2])
1234 index = self.MCbox.index(labelsuivant)
1235 self.MCbox.see(index)
1236 self.arg_selected=co
1237 self.highlightitem(labelsuivant)
1238 labelsuivant.focus_set()
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
1257 labelsuivant=self.dico_labels[co]
1258 if self.selection != None :
1259 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
1260 self.selection = (co,labelsuivant,self.selection[2])
1261 index = self.MCbox.index(labelsuivant)
1262 self.MCbox.see(index)
1263 self.arg_selected=co
1264 self.highlightitem(labelsuivant)
1265 labelsuivant.focus_set()
1268 def entry_changed(self,event=None):
1270 Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1271 de l'entry et frappe <Return>
1273 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1275 filtre = self.entry.get()+"*"
1276 FILTRE = string.upper(filtre)
1278 # On cherche d'abord dans les noms de groupe
1279 # puis dans les noms de commande groupe par groupe
1281 for grp in self.liste_groupes:
1282 if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1283 self.highlightitem(self.dico_labels[grp])
1284 index = self.MCbox.index(self.dico_labels[grp])
1285 self.MCbox.see(index)
1286 # On ne selectionne pas le groupe
1287 #self.arg_selected = grp
1288 self.dico_labels[grp].focus_set()
1289 # On a trouve un groupe on arrete la recherche
1292 for grp in self.liste_groupes:
1293 for cmd in self.dict_groupes[grp] :
1294 if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1295 self.highlightitem(self.dico_labels[cmd])
1296 index = self.MCbox.index(self.dico_labels[cmd])
1297 self.MCbox.see(index)
1298 self.arg_selected = cmd
1299 self.dico_labels[self.arg_selected].focus_set()
1300 # On a trouve une commande on arrete la recherche