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.configure(width = 800,height=500)
61 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
62 self.fenetre.title("Visualisation du "+titre)
63 self.texte = string.replace(texte,'\r\n','\n')
65 fonte=fontes.standardcourier10
66 # définition des frames
67 self.frame_texte = Frame(self.fenetre)
68 self.frame_boutons = Frame(self.fenetre)
69 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.9)
70 self.frame_boutons.place(relheight=0.1,relx=0,rely=0.9,relwidth=1.)
71 # définition de la zone texte et du scrollbar
72 self.zone_texte = Text(self.frame_texte,font=fonte)
73 self.zone_texte.bind("<Key-Prior>", self.page_up)
74 self.zone_texte.bind("<Key-Next>", self.page_down)
75 self.zone_texte.bind("<Key-Up>", self.unit_up)
76 self.zone_texte.bind("<Key-Down>", self.unit_down)
77 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
78 #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
79 self.scroll_v.pack(side='right',fill ='y')
80 #self.scroll_h.pack(side='bottom',fill ='x')
81 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
82 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
83 # définition des boutons
84 self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
85 self.but_save = Button(self.frame_boutons,text = "sauver",command = self.save)
86 self.but_quit.place(relx=0.4,rely=0.5,anchor='center')
87 self.but_save.place(relx=0.6,rely=0.5,anchor='center')
89 self.affiche_texte(self.texte)
90 centerwindow(self.fenetre)
92 def page_up(self,event):
93 event.widget.yview_scroll(-1, "page")
94 def page_down(self,event):
95 event.widget.yview_scroll(1, "page")
96 def unit_up(self,event):
97 event.widget.yview_scroll(-1, "unit")
98 def unit_down(self,event):
99 event.widget.yview_scroll(1, "unit")
102 self.fenetre.grab_set()
103 self.zone_texte.focus_set()
104 self.fenetre.wait_window(self.fenetre)
107 self.fenetre.destroy()
109 def efface_scroll(self):
110 """ Efface le scroll lorsqu'il n'est pas nécessaire : ne marche pas"""
111 self.scroll_v.pack_forget()
112 #self.scroll_h.pack_forget()
114 def affiche_texte(self,texte):
115 """ Affiche le texte dans la fenêtre """
117 self.zone_texte.insert(END,texte)
119 self.fenetre.update_idletasks()
120 x0,y0,x1,y1 = self.zone_texte.bbox(END)
121 if (y1-y0) < 300 : self.efface_scroll()
126 """ Permet de sauvegarder le texte dans un fichier dont on a demandé le nom
128 file = asksaveasfilename(defaultextension = '.comm',
129 #initialdir = self.appli.CONFIGURATION.rep_user,
130 initialdir = self.appli.CONFIGURATION.initialdir,
131 title="Sauvegarde du "+self.titre)
133 if not save_in_file(file,self.texte) :
134 showerror("Sauvegarde impossible",
135 "Impossible de sauvegarder le texte dans le fichier spécifié\n"+
136 "Vérifiez les droits d'écriture")
138 showinfo("Sauvegarde effectuée","Sauvegarde effectuée dans le fichier %s" %file)
142 self.fenetre.destroy()
146 class FenetreYesNo(Fenetre):
147 def __init__(self,appli,titre="",texte="",yes="Yes",no="No"):
149 self.fenetre = Toplevel()
150 self.fenetre.configure(width = 800,height=500)
151 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
152 self.fenetre.title(titre)
153 self.texte = string.replace(texte,'\r\n','\n')
155 fonte=fontes.standardcourier10
156 # définition des frames
157 self.frame_texte = Frame(self.fenetre)
158 self.frame_boutons = Frame(self.fenetre)
159 self.frame_boutons.place(relx=0,rely=0, relwidth=1.,relheight=0.1)
160 self.frame_texte.place( relx=0,rely=0.1, relwidth=1, relheight=0.9)
161 # définition de la zone texte et du scrollbar
162 self.zone_texte = Text(self.frame_texte,font=fonte)
163 self.zone_texte.bind("<Key-Prior>", self.page_up)
164 self.zone_texte.bind("<Key-Next>", self.page_down)
165 self.zone_texte.bind("<Key-Up>", self.unit_up)
166 self.zone_texte.bind("<Key-Down>", self.unit_down)
167 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
168 #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
169 self.scroll_v.pack(side='right',fill ='y')
170 #self.scroll_h.pack(side='bottom',fill ='x')
171 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
172 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
173 # définition des boutons
174 self.but_yes = Button(self.frame_boutons,text = yes,command=self.yes)
175 self.but_no = Button(self.frame_boutons,text = no,command = self.no)
176 self.but_yes.place(relx=0.4,rely=0.5,anchor='center')
177 self.but_no.place(relx=0.6,rely=0.5,anchor='center')
179 self.affiche_texte(self.texte)
180 centerwindow(self.fenetre)
190 class FenetreDeSelection(Fenetre):
191 """ Classe dérivée de Fenêtre permettant la récupération d'une zone de texte sélectionnée.
192 Cette classe est utilisée pour affecter une liste de valeurs à un mot-clé.
194 def __init__(self,panel,item,appli,titre="",texte="",cardinal=1):
195 Fenetre.__init__(self,appli,titre=titre,texte=texte)
196 self.frame_boutons.place_forget()
197 self.frame_texte.place_forget()
198 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.8)
199 self.frame_boutons.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
201 self.cardinal=cardinal
202 self.fenetre.configure(width = 320,height=400)
203 centerwindow(self.fenetre)
206 self.fenetre.title(titre)
207 self.but_save.configure(text="Ajouter",command=self.traite_selection)
208 # séparateur par défaut
209 self.separateur = ';'
210 # création de la zone de saisie du séparateur
211 l_separateurs_autorises = self.get_separateurs_autorises()
212 self.choix_sep = Pmw.ComboBox(self.frame_boutons,
213 label_text = "Séparateur :",
216 selectioncommand = self.choose_separateur,
217 scrolledlist_items = l_separateurs_autorises)
218 self.choix_sep.component('entry').configure(width=6)
219 self.choix_sep.place(relx=0.01,rely=0.5,anchor='w')
220 self.choix_sep.selectitem(self.separateur)
222 self.but_quit.place_forget()
223 self.but_save.place_forget()
224 self.but_all = Button(self.frame_boutons,text = "Tout Sélectionner", command=self.tout)
225 self.but_save.place(relx=0.6,rely=0.6,anchor='center')
226 self.but_quit.place(relx=0.8,rely=0.6,anchor='center')
227 self.but_all.place(relx=0.7,rely=0.2,anchor='center')
228 self.choose_separateur('espace')
231 def get_separateurs_autorises(self):
233 Retourne la liste des séparateurs autorisés
235 return ['espace',';',',']
237 def choose_separateur(self,nom_sep):
239 Affecte à self.separateur le caractère séparateur correspondant à nom_sep
241 if nom_sep == 'espace' :
242 self.separateur = ' '
244 self.separateur = nom_sep
248 texte=self.texte.splitlines()
250 for mot in string.split(l,self.separateur):
251 if mot != '' and mot != ' ' and mot != self.separateur :
253 self.traite_selection(liste)
255 def traite_selection(self,liste=None):
256 """ Cette méthode effectue tous les traitements nécessaires pour vérifier
257 et affecter la liste de valeurs à l'objet réprésenté par self.item
259 # Récupère la liste des chaines de caractères de la zone sélectionnée
262 message,liste = self.recupere_liste()
263 if self.test_probleme(message,"Sélectionnez des données") == 0:
265 # Vérifie que le nombre de données est dans les limites attendues
266 message = self.verif_liste(liste)
267 if self.test_probleme(message,"Vérifiez le nombre de données") == 0:
269 # Crée une liste de valeurs du type attendu
270 message,liste_valeurs = self.creation_liste_valeurs(liste)
271 if self.test_probleme(message,"Vérifiez le type des données") == 0:
273 # Vérifie que chaque valeur est dans le domaine exigé
274 message = self.verif_valeurs(liste_valeurs)
275 if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:
277 # Ajoute les valeurs dans la liste de valeurs du mot-clé
278 if self.cardinal != 1 :
282 if (len(liste_valeurs)%nb != 0):
283 message="La cardinalité n'est pas correcte"
284 self.test_probleme(message,"On attend des tuples")
286 for i in range(len(liste_valeurs)/nb) :
288 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1])
290 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1], liste_valeurs[i*nb+2])
292 print "probleme : prevenir la maintenance Eficas"
295 liste_valeurs=l_valeurs
296 self.ajouter_valeurs(liste_valeurs)
297 self.appli.affiche_infos("Liste de valeurs acceptée")
299 def test_probleme(self, message, message_eficas):
300 """ Cette méthode affiche un message d'erreur si message != ''
301 et retourne 0, sinon retourne 1 sans rien afficher.
304 showinfo("Problème",message)
305 self.fenetre.tkraise()
306 self.appli.affiche_infos(message_eficas)
311 def recupere_liste(self):
312 """ Cette méthode récupère le texte de la zone sélectionnée, construit et
313 retourne une liste avec les chaines qui se trouvent entre les séparateurs.
314 S'il n'y a pas de données selectionnées, elle retourne un message d'erreur
319 selection=self.fenetre.selection_get()
321 message = "Pas de donnée sélectionnée"
323 # les retours chariots doivent être interprétés comme des séparateurs
324 selection = string.replace(selection,'\n',self.separateur)
325 # on splitte la sélection suivant le caractère séparateur
326 liste_chaines = string.split(selection,self.separateur)
328 for chaine in liste_chaines:
329 chaine = string.strip(chaine)
330 if chaine != '' : l_chaines.append(chaine)
331 return message,l_chaines
333 def verif_liste(self, liste):
334 """ Cette méthode effectue des tests sur le nombre d'éléments de la liste
335 et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur
339 # nombre d'éléments sélectionnés
340 nombre_elements = len(liste)
341 # nombre d'éléments déja dans la liste du panel
342 nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())
343 multiplicite = self.item.GetMultiplicite()
344 if (nombre_elements % multiplicite) != 0:
345 message = "Vous devez sélectionner "+str(multiplicite)+" * n données"
347 nombre_valeurs = nombre_elements / multiplicite
348 cardinalite = self.item.GetMinMax()
349 if nombre_valeurs < cardinalite[0]:
350 message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"
352 if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):
353 message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"
358 def creation_liste_valeurs(self, liste):
359 """ Cette méthode crée et retourne une liste de valeurs du type attendu
360 par le mot-clé. La liste de valeurs est créée à partir de la liste
361 de chaines de caractères transmise.
363 type_attendu = self.item.GetType()[0]
364 if type_attendu == 'R':
365 return self.convertir(liste, f_conversion= float)
366 elif type_attendu == 'I':
367 return self.convertir(liste, f_conversion= int)
368 elif type_attendu == 'TXM':
369 return self.convertir(liste)
371 message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"
374 def convertir(self, liste, f_conversion=None):
375 """ Cette méthode essaie de convertir les éléments de la liste avec la
376 fonction f_conversion si elle existe, et retourne la liste des
377 éléments dans le type voulu en cas de succès, sinon retourne None.
384 liste_valeurs.append(f_conversion(chaine))
386 message = "Impossible de convertir "+chaine+" dans le type attendu"
389 liste_valeurs.append(chaine)
390 return message,liste_valeurs
392 def verif_valeurs(self, liste_valeurs):
393 """ Cette méthode teste tous les éléments de la liste, et retourne 1 si chaque
394 élément est dans le domaine voulu.
397 for valeur in liste_valeurs:
398 test = self.item.IsInIntervalle(valeur)
400 intervalle = str(self.item.GetIntervalle()[0])+","+str(self.item.GetIntervalle()[1])
401 message = "La valeur "+str(valeur)+" n'est pas dans l'intervalle ["+intervalle+"]"
405 def ajouter_valeurs(self, liste_valeurs):
406 """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""
407 liste = self.panel.Liste_valeurs.get_liste()
408 liste.extend(liste_valeurs)
409 self.panel.Liste_valeurs.put_liste(liste)
411 class FenetreDeParametre(Fenetre) :
412 def __init__(self,parent,item,appli,texte):
415 self.fenetre = Toplevel()
416 self.fenetre.configure(width = 250,height=100)
417 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
418 self.fenetre.title("Parametres")
419 self.titre = "Parametres"
420 self.texte = string.replace(texte,'\r\n','\n')
421 fonte=fontes.standardcourier10
423 # définition des frames
424 self.frame_texte = Frame(self.fenetre)
425 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.7)
426 # définition de la zone texte et du scrollbar
427 self.zone_texte = Text(self.frame_texte,font=fonte)
428 self.zone_texte.bind("<Key-Prior>", self.page_up)
429 self.zone_texte.bind("<Key-Next>", self.page_down)
430 self.zone_texte.bind("<Key-Up>", self.unit_up)
431 self.zone_texte.bind("<Key-Down>", self.unit_down)
432 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
433 self.scroll_v.pack(side='right',fill ='y')
434 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
435 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
437 self.affiche_texte(self.texte)
438 self.zone_texte.config(state="disabled")
440 # définition des boutons
441 self.frame_boutons = Frame(self.fenetre)
442 self.frame_boutons.place(relheight=0.3,relx=0,rely=0.65,relwidth=1.)
443 self.label1 = Label(self.frame_boutons,text="surligner la")
444 self.label2 = Label(self.frame_boutons,text="ligne entière")
445 self.label1.place(relx=0.1,rely=0)
446 self.label2.place(relx=0.1,rely=0.5)
447 self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
448 self.but_save = Button(self.frame_boutons,text = "Choisir",command = self.Choisir)
449 self.but_save.place(relx=0.6,rely=0,relheight=1)
450 self.but_quit.place(relx=0.8,rely=0,relheight=1)
455 selection=self.zone_texte.selection_get()
457 showerror("Pas de donnée sélectionnée",
458 "Selectionner un parametre")
460 for param in selection.splitlines():
461 nomparam=param[0:param.find("=")-1]
463 l_param=l_param+nomparam+','
464 self.parent.entry.delete(0,Tkinter.END)
465 self.parent.entry.insert(0,l_param[0:-1])
466 self.parent.valid_valeur()
471 Cette classe permet de créer une boîte Dialog dans laquelle
472 on affiche un formulaire à remplir par l'utilisateur
474 def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
475 if items in ((),[]) : return
479 self.fen_pere = fen_pere
480 self.obj_pere = obj_pere
482 self.command = commande
486 self.init_validateurs()
489 self.init_items_formulaire()
490 self.fenetre.activate(geometry='centerscreenalways')
492 def init_validateurs(self):
494 Crée le dictionnaire des validateurs des objets reconnus par le formulaire
496 self.d_validateurs = {}
497 self.d_validateurs['rep'] = self.repvalidator
498 self.d_validateurs['file'] = self.filevalidator
499 self.d_validateurs['cata']= self.catavalidator
501 def init_fenetre(self):
503 Crée la fenêtre Dialog
505 if self.mode == 'query':
506 buttons=('Valider','Annuler')
507 defaultbutton = 'Valider'
508 elif self.mode == 'display':
510 buttons=(self.command[0],'OK')
515 self.fenetre = Pmw.Dialog(self.fen_pere,
517 defaultbutton = defaultbutton,
519 command = self.execute)
520 self.fenetre.withdraw()
522 def init_texte(self):
524 Crée le label qui affiche le texte à l'intérieur du panneau
526 fonte=fontes.standard
527 fr_texte = Frame(self.fenetre.interior(),height=60)
528 fr_texte.pack(side='top',fill='x',expand=1)
529 Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
531 def init_items_formulaire(self):
533 Crée et affiche les items dans la boîte de dialogue
537 self.item_widgets = {}
539 for item in self.items:
540 if len(item[0])>length_maxi : length_maxi = len(item[0])
541 window = self.fenetre.interior()
542 for item in self.items :
543 label,nature,nom_var,defaut = item
544 # création de la frame
545 fr_item = Frame(window,height=40,width=700)
546 fr_item.pack(side='top',fill='x',expand=1)
548 Label(fr_item,text = label).place(relx=0.05,rely=0.4)
549 if nature in ('rep','file','cata'):
550 # création de l'entry
551 e_item = Entry(fr_item)
552 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
553 self.widgets.append(e_item)
554 self.item_widgets[item] = e_item
555 if defaut : e_item.insert(0,str(defaut))
556 elif nature == 'YesNo':
557 # création de la StringVar
559 setattr(self,'item_'+nom_var,var)
561 # création du radiobouton
562 rb1 = Radiobutton(fr_item,text='OUI',variable=var,value='OUI')
563 rb2 = Radiobutton(fr_item,text='NON',variable=var,value='NON')
564 rb1.place(relx=0.65,rely=0.5,anchor='center')
565 rb2.place(relx=0.80,rely=0.5,anchor='center')
566 self.widgets.append((rb1,rb2))
567 self.item_widgets[item] = var
568 # détermination de la méthode à appliquer sur les boutons
569 if self.mode == 'query':
570 function = self.active
571 elif self.mode == 'display':
572 function = self.inactive
575 # on applique la méthode sur les boutons (activation ou désactivation)
576 for widget in self.widgets :
577 if type(widget) == types.TupleType:
579 apply(function,(widg,),{})
581 apply(function,(widget,),{})
583 def active(self,widget):
585 Active le widget passé en argument
587 widget.configure(state='normal',bg='white')
589 def inactive(self,widget):
591 Inactive le widget passé en argument
593 if not isinstance(widget,Radiobutton) :
594 widget.configure(state='disabled',bg='gray95')
596 widget.configure(state='disabled')
598 # --------------------------------------------------------------------------------
599 # Validateurs des noms de répertoire, de fichiers et de catalogues
600 # -------------------------------------------------------------------------------
602 def repvalidator(self,text):
604 Teste si text peut faire référence à un répertoire ou non
605 Retourne 1 si valide, 0 sinon
607 return os.path.isdir(text),'Répertoire introuvable : %s' %text
609 def filevalidator(self,text):
611 Teste si text peut faire référence à un fichier ou non
612 Retourne 1 si valide, 0 sinon
614 return os.path.isfile(text),'Fichier introuvable : %s' %text
616 def catavalidator(self,text):
618 Teste si text est un chemin d'accès valide à un catalogue
619 Retourne 1 si valide, 0 sinon
621 return os.path.isfile(text),"Catalogue introuvable : %s" %text
623 # --------------------------------------------------------------------------------
624 # Méthodes callbacks des boutons et de fin
625 # --------------------------------------------------------------------------------
627 def execute(self,txt):
629 Cette commande est activée à chaque clic sur un bouton.
630 Redirige l'action sur la bonne méthode en fonction du bouton activé
634 elif txt in ('OK','Annuler'):
636 elif txt == 'Modifier':
637 self.resultat = apply(self.command[1],(),{})
638 self.fenetre.destroy()
640 print "Nom de bouton inconnu"
645 Commande qui termine le panneau et sauvegarde les nouvelles options
646 dans l'objet resultat (dictionnaire)
649 for item,widget in self.item_widgets.items():
652 valeur = widget.get()
653 if self.d_validateurs.has_key(type_var):
654 test = self.d_validateurs[type_var](valeur)
656 # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
657 # sans tuer la fenêtre bien sûr
658 widget.selection_range(0,END)
660 dico[nom_var] = valeur
661 self.fenetre.destroy()
665 self.fenetre.destroy()
669 """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
670 en passant les commandes à lancer suivant différents bindings """
671 def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre='',optionReturn=None):
676 self.selection = None
677 self.liste_commandes = liste_commandes
678 self.liste_marques = liste_marques
683 self.optionReturn = optionReturn
687 self.make_label_titre()
688 self.make_entry_filtre()
691 self.entry.component('entry').focus()
695 def make_label_titre(self):
696 """ Crée le label correspondant au titre """
697 if self.titre == '' : return
698 fonte_titre = fontes.standard_gras_souligne
699 self.label = Label(self.page,
702 self.label.pack(side='top',pady=2)
704 def make_entry_filtre(self):
705 """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
706 if self.filtre != 'oui' : return
707 self.entry = Pmw.EntryField(self.page,labelpos='w',
708 label_text="Filtre :",
709 command=self.entry_changed)
710 self.entry.pack(side='top',pady=2)
712 def make_text_box(self):
713 """ Crée la fenêtre texte dans laquelle sera affichée la liste """
714 self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
715 self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
716 self.MCscroll.pack(side='right',fill ='y',pady=2)
717 self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
718 self.MCbox.configure(yscrollcommand=self.MCscroll.set)
721 def affiche_liste(self):
722 """ Affiche la liste dans la fenêtre"""
724 self.MCbox.config(state=NORMAL)
725 self.MCbox.delete(1.0,END)
726 for objet in self.liste :
727 if type(objet) == types.InstanceType:
732 elif type(objet) in (types.StringType,types.IntType):
734 elif type(objet) == types.FloatType :
735 mot = self.parent.get_valeur_texte(objet)
738 elif type(objet) == types.TupleType :
746 valtexte = self.parent.get_valeur_texte(val)
754 label = Label(self.MCbox,
756 fg = 'black',bg = 'gray95',justify = 'left')
757 self.dico_labels[mot]=label
758 liste_labels.append(label)
759 self.MCbox.window_create(END,
762 self.MCbox.insert(END,'\n')
763 if self.optionReturn != None :
764 label.bind("<Return>",lambda e,s=self,c=self.liste_commandes[2][1],x=objet,l=label : s.chooseitemsurligne(x,l,c))
765 label.bind("<Key-Right>",lambda e,s=self,x=objet,l=label : s.selectNextItem(x,l))
766 if self.active == 'oui':
767 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))
768 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))
769 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))
771 for marque in self.liste_marques:
773 self.markitem(liste_labels[marque])
777 self.MCbox.config(state=DISABLED)
778 self.selection = None
780 def clear_marque(self):
782 self.dico_labels[self.arg_selected].configure(bg='gray95',fg='black')
783 self.arg_selected = ''
787 def surligne(self,marque):
789 self.highlightitem(self.dico_labels[marque])
790 self.arg_selected = marque
794 def chooseitemsurligne(self,mot,label,commande):
795 """ Active la méthode de choix passée en argument"""
797 mot=self.arg_selected
799 except AsException,e:
801 showerror(raison.split('\n')[0],raison)
803 def chooseitem(self,mot,label,commande):
804 """ Active la méthode de choix passée en argument"""
807 except AsException,e:
809 showerror(raison.split('\n')[0],raison)
811 def selectNextItem(self,mot,label):
813 index=self.liste.index(mot)
815 motsuivant=self.liste[indexsuivant]
816 labelsuivant=self.dico_labels[motsuivant]
818 if self.selection != None :
819 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
820 self.selection = (mot,label,self.selection[2])
821 self.highlightitem(labelsuivant)
822 self.arg_selected=motsuivant
823 labelsuivant.focus_set()
824 # PN il faut faire quelque chose pour être dans la fenetre
829 def selectitem(self,mot,label,commande) :
830 """ Met l'item sélectionné (représenté par son label) en surbrillance
831 et lance la commande associée au double-clic"""
833 if self.selection != None :
834 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
835 self.highlightitem(label)
836 self.selection = (mot,label,commande)
837 self.arg_selected = mot
840 def highlightitem(self,label) :
841 """ Met l'item représenté par son label en surbrillance """
842 label.configure(bg='#00008b',fg='white')
844 def markitem(self,label):
845 """ Met l'item (représenté par son label) en rouge """
846 label.configure(bg='gray95',fg='red')
848 def deselectitem(self,label,mot='',commande=None) :
849 """ Remet l'item (représenté par son label) en noir"""
850 label.configure(bg='gray95',fg='black')
851 self.arg_selected = ''
852 if commande != None : commande(mot)
854 def cherche_selected_item(self):
855 index=self.MCbox.index(self.selection[1])
856 lign,col=map(int,string.split(index,'.'))
859 def remove_selected_item(self):
860 index=self.MCbox.index(self.selection[1])
861 lign,col=map(int,string.split(index,'.'))
862 del self.liste[lign-1]
865 def entry_changed(self,event=None):
866 """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
867 de l'entry et frappe <Return>"""
868 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
869 filtre = self.entry.get()+"*"
870 FILTRE = string.upper(filtre)
871 for arg in self.liste :
872 if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
873 self.highlightitem(self.dico_labels[arg])
874 index = self.MCbox.index(self.dico_labels[arg])
875 self.MCbox.see(index)
876 self.arg_selected = arg
877 self.dico_labels[self.arg_selected].focus_set()
881 #self.dico_labels[self.arg_selected].focus_set()
885 def get_liste_BAK(self):
888 # PN attention à la gestion des paramétres
889 # cela retourne H = 1 , et ni H, ni 1
891 # print val.__class__.__name__
894 for val in self.liste:
902 def put_liste(self,liste):
907 """ Cette classe permet d'afficher au lancement d'EFICAS le message
908 d'attente et la barre de progression"""
909 def __init__(self,master,message,barre ='oui'):
910 from Tools.foztools.foztools import Slider
911 fonte=fontes.standard12_gras
913 self.frame = Frame(self.master)
914 self.frame.pack(expand=1,fill='both')
915 self.mess = Label(self.frame,text=message,justify='center',
916 bd=2,relief='groove',font=fonte)
917 self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
918 self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
919 fillColor='#00008b',width=200,height=30,
920 background='white',labelColor='red')
922 self.progress.frame.pack(in_=self.frame,side='top')
925 self.progress.frame.after(1000,self.update)
927 def configure(self,**options):
928 if options.has_key('message'):
929 self.mess.configure(text=options['message'])
930 if options.has_key('barre'):
931 if options['barre'] == 'oui' :
932 self.progress.frame.pack(in_=self.frame,side='top')
933 elif options['barre'] == 'non' :
934 self.progress.frame.pack_forget()
935 self.master.update_idletasks()
941 def update(self,event=None):
942 """ Permet de faire avancer la barre de progression """
945 bar.value = bar.value+self.increment
947 self.master.after(100,self.update)
951 def configure_barre(self,nb):
952 """ Calcule l'incrément de progression de la barre en fonction
953 du nombre d'opérations à effectuer afin que le compteur
954 soit à 100% à la fin des opérations"""
955 self.increment = 100./nb
956 self.progress.update()
958 class Ask_Format_Fichier :
960 Cette classe permet de créer une fenêtre Toplevel dans laquelle
961 on propose le choix du format de fichier de commandes à ouvrir
963 def __init__(self,appli):
964 self.fenetre = Toplevel()
965 self.fenetre.configure(width = 250,height=150)
966 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
967 self.fenetre.title("Choix du format du fichier de commandes")
968 # définition des frames
969 self.frame_texte = Frame(self.fenetre)
970 self.frame_radioboutons = Frame(self.fenetre)
971 self.frame_bouton_ok = Frame(self.fenetre)
972 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
973 self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
974 self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
975 # définition de la zone texte et du scrollbar
976 zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
977 zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
978 # définition des radioboutons
979 Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
980 variable=appli.format_fichier,value='Aster').pack(anchor='n')
981 Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
982 variable=appli.format_fichier,value='Python').pack(anchor='n')
983 # création du bouton OK
984 Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
985 # centrage de la fenêtre
986 centerwindow(self.fenetre)
989 self.fenetre.destroy()
991 class BARRE_K2000(Toplevel):
992 def __init__(self,master=None,text = ""):
993 Toplevel.__init__(self,master,relief='groove')
994 self.master.iconify()
995 self.geometry("250x100+0+0")
996 self.protocol("WM_DELETE_WINDOW",self.quit)
997 # frame principale dans self (= Toplevel)
998 self.frame = Frame(self)
999 self.frame.place(relwidth=1,relheight=1)
1000 # frame contenant le texte à afficher
1001 self.frame_text = Frame(self.frame)
1002 self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
1003 # frame contenant le canvas de la barre
1004 self.frame_canv = Frame(self.frame)
1005 self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
1006 # canvas dans lequel sera affichée la barre K2000
1007 self.canvas = Canvas(self.frame_canv)
1008 self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
1009 # on affiche le texte et la barre
1010 self.build_text(text)
1012 #self.overrideredirect(1)
1013 # on active la barre ...
1014 self.master.after(1000,self.launch)
1015 # on centre la fenêtre
1019 def build_text(self,text):
1021 Affichage de text dans frame_text
1023 self.texte_var = StringVar()
1024 self.texte_var.set(text)
1025 Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
1027 def build_batons(self):
1029 Construit la suite de bâtons dans le canvas
1035 for i in range(0,40):
1036 id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
1037 self.l_batons.append(id)
1041 Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
1045 self.master.deiconify()
1047 if self.sens == 'D':
1048 self.black = self.black+1
1049 l_bat = self.l_batons[0:self.black+1]
1051 elif self.sens == 'G':
1052 self.black = self.black-1
1053 l_bat = self.l_batons[self.black:]
1057 if num_color < 10 : color = 'black'
1058 elif num_color > 90 : color = 'white'
1059 else: color = 'gray'+`num_color`
1060 self.canvas.itemconfigure(bat,fill=color)
1062 if self.black == len(self.l_batons) :
1064 if self.black == 0 and self.sens == 'G':self.sens = 'D'
1065 self.after(80,self.launch)
1067 def update_text(self,new_text):
1069 Remplace le texte affiché par new_text
1071 self.texte_var.set(new_text)
1076 class ListeChoixParGroupes(ListeChoix) :
1078 Cette classe est utilisée pour afficher une liste de commandes classées par
1079 groupes. L'utilisateur peut réaliser des actions de selection
1080 qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
1082 liste_commandes = (("<Enter>",self.selectCmd),
1083 ("<Leave>",self.deselectCmd),
1084 ("<Double-Button-1>",self.defCmd))
1085 Il s'agit d'une liste de doublets dont le premier element est un evenement et le
1086 deuxieme un callback a appeler sur l'evenement en question.
1089 def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
1090 active ='oui',filtre='non',titre='',optionReturn=None):
1091 self.parent = parent
1093 self.liste_groupes = liste_groupes
1094 self.dict_groupes = dict_groupes
1096 self.selection = None
1097 self.liste_commandes = liste_commandes
1098 self.liste_marques = liste_marques
1099 self.arg_selected=''
1100 self.active = active
1102 self.filtre = filtre
1103 self.optionReturn = optionReturn
1106 def affiche_liste(self):
1107 """ Affiche la liste dans la fenêtre"""
1109 self.MCbox.config(state=NORMAL)
1110 self.MCbox.delete(1.0,END)
1111 for grp in self.liste_groupes:
1112 # On itère sur les groupes
1113 if grp == "CACHE":continue
1114 liste_commandes=self.dict_groupes[grp]
1115 text="GROUPE<<<<<<<< "+grp+" "
1116 text=text+">"*max(0,30-len(text))
1117 label = Label(self.MCbox,
1119 fg = 'black',bg = 'gray95',justify = 'left')
1120 # On stocke la relation entre le nom de la commande et le label
1121 self.dico_labels[grp]=label
1122 liste_labels.append(label)
1123 self.MCbox.window_create(END,
1126 self.MCbox.insert(END,'\n')
1127 for cmd in liste_commandes:
1128 label = Label(self.MCbox,
1130 fg = 'black',bg = 'gray95',justify = 'left')
1131 # On stocke la relation entre le nom de la commande et le label
1132 self.dico_labels[cmd]=label
1133 self.MCbox.window_create(END,
1136 self.MCbox.insert(END,'\n')
1138 def null(*tp,**args): return
1140 if self.active == 'oui':
1141 # Traitement par defaut des evenements
1142 label.bind("<Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.selectitem(x,l,c))
1143 label.bind("<Leave>",lambda e,s=self,c=null,x=cmd,l=label: s.deselectitem(l,x,c))
1144 label.bind("<Double-Button-1>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1145 label.bind("<Return>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1146 label.bind("<Key-Right>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1147 label.bind("<Key-Down>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1148 label.bind("<Key-Left>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1149 label.bind("<Key-Up>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1151 # Si des callbacks sont definis on les utilise
1152 for event,callback in self.liste_commandes:
1153 if event == "<Enter>":
1154 label.bind("<Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.selectitem(x,l,c))
1155 elif event == "<Leave>":
1156 label.bind("<Leave>",lambda e,s=self,c=callback,x=cmd,l=label: s.deselectitem(l,x,c))
1157 elif event == "<Double-Button-1>":
1158 label.bind("<Double-Button-1>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1159 elif event == "<Return>":
1160 label.bind("<Return>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1161 elif event == "<Key-Right>":
1162 label.bind("<Key-Right>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1163 elif event == "<Key-Down>":
1164 label.bind("<Key-Down>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1165 elif event == "<Key-Left>":
1166 label.bind("<Key-Left>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1167 elif event == "<Key-Up>":
1168 label.bind("<Key-Up>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1170 label.bind(event,lambda e,s=self,c=callback,x=cmd,l=label: c())
1172 for marque in self.liste_marques:
1174 self.markitem(liste_labels[marque])
1178 self.MCbox.config(state=DISABLED)
1179 self.selection = None
1181 def selectPrevItem(self,mot,label,callback,group,cmd):
1182 g=self.liste_groupes.index(group)
1183 liste_commandes=self.dict_groupes[group]
1184 c=liste_commandes.index(cmd)
1186 co=liste_commandes[c-1]
1188 # debut de liste. On passe au groupe precedent
1190 gr=self.liste_groupes[g-1]
1191 co=self.dict_groupes[gr][-1]
1193 # debut des groupes. On ne fait rien
1196 # On a trouve l'item precedent
1198 labelsuivant=self.dico_labels[co]
1199 if self.selection != None :
1200 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
1201 self.selection = (co,labelsuivant,self.selection[2])
1202 index = self.MCbox.index(labelsuivant)
1203 self.MCbox.see(index)
1204 self.arg_selected=co
1205 self.highlightitem(labelsuivant)
1206 labelsuivant.focus_set()
1209 def selectNextItem(self,mot,label,callback,group,cmd):
1210 g=self.liste_groupes.index(group)
1211 liste_commandes=self.dict_groupes[group]
1212 c=liste_commandes.index(cmd)
1214 co=liste_commandes[c+1]
1216 # fin de liste. On passe au groupe suivant
1218 gr=self.liste_groupes[g+1]
1219 co=self.dict_groupes[gr][0]
1221 # fin des groupes. On ne fait rien
1223 # On a trouve l'item suivant
1225 labelsuivant=self.dico_labels[co]
1226 if self.selection != None :
1227 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
1228 self.selection = (co,labelsuivant,self.selection[2])
1229 index = self.MCbox.index(labelsuivant)
1230 self.MCbox.see(index)
1231 self.arg_selected=co
1232 self.highlightitem(labelsuivant)
1233 labelsuivant.focus_set()
1236 def entry_changed(self,event=None):
1238 Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1239 de l'entry et frappe <Return>
1241 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1243 filtre = self.entry.get()+"*"
1244 FILTRE = string.upper(filtre)
1246 # On cherche d'abord dans les noms de groupe
1247 # puis dans les noms de commande groupe par groupe
1249 for grp in self.liste_groupes:
1250 if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1251 self.highlightitem(self.dico_labels[grp])
1252 index = self.MCbox.index(self.dico_labels[grp])
1253 self.MCbox.see(index)
1254 # On ne selectionne pas le groupe
1255 #self.arg_selected = grp
1256 self.dico_labels[grp].focus_set()
1257 # On a trouve un groupe on arrete la recherche
1260 for grp in self.liste_groupes:
1261 for cmd in self.dict_groupes[grp] :
1262 if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1263 self.highlightitem(self.dico_labels[cmd])
1264 index = self.MCbox.index(self.dico_labels[cmd])
1265 self.MCbox.see(index)
1266 self.arg_selected = cmd
1267 self.dico_labels[self.arg_selected].focus_set()
1268 # On a trouve une commande on arrete la recherche