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) :
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):
678 self.selection = None
679 self.liste_commandes = liste_commandes
680 self.liste_marques = liste_marques
685 self.optionReturn = optionReturn
689 self.make_label_titre()
690 self.make_entry_filtre()
693 self.entry.component('entry').focus()
697 def make_label_titre(self):
698 """ Crée le label correspondant au titre """
699 if self.titre == '' : return
700 fonte_titre = fontes.standard_gras_souligne
701 self.label = Label(self.page,
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("<Key-Right>",lambda e,s=self,x=objet,l=label : s.selectNextItem(x,l))
768 if self.active == 'oui':
769 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))
770 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))
771 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))
773 for marque in self.liste_marques:
775 self.markitem(liste_labels[marque])
779 self.MCbox.config(state=DISABLED)
780 self.selection = None
782 def clear_marque(self):
784 self.dico_labels[self.arg_selected].configure(bg='gray95',fg='black')
785 self.arg_selected = ''
789 def surligne(self,marque):
791 self.highlightitem(self.dico_labels[marque])
792 self.arg_selected = marque
796 def chooseitemsurligne(self,mot,label,commande):
797 """ Active la méthode de choix passée en argument"""
799 mot=self.arg_selected
801 except AsException,e:
803 showerror(raison.split('\n')[0],raison)
805 def chooseitem(self,mot,label,commande):
806 """ Active la méthode de choix passée en argument"""
809 except AsException,e:
811 showerror(raison.split('\n')[0],raison)
813 def selectNextItem(self,mot,label):
815 index=self.liste.index(mot)
817 motsuivant=self.liste[indexsuivant]
818 labelsuivant=self.dico_labels[motsuivant]
820 if self.selection != None :
821 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
822 self.selection = (mot,label,self.selection[2])
823 index = self.MCbox.index(labelsuivant)
824 self.MCbox.see(index)
825 self.highlightitem(labelsuivant)
826 self.arg_selected=motsuivant
827 labelsuivant.focus_set()
828 # PN il faut faire quelque chose pour être dans la fenetre
833 def selectitem(self,mot,label,commande) :
834 """ Met l'item sélectionné (représenté par son label) en surbrillance
835 et lance la commande associée au double-clic"""
837 if self.selection != None :
838 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
839 self.highlightitem(label)
840 self.selection = (mot,label,commande)
841 self.arg_selected = mot
844 def highlightitem(self,label) :
845 """ Met l'item représenté par son label en surbrillance """
846 label.configure(bg='#00008b',fg='white')
848 def markitem(self,label):
849 """ Met l'item (représenté par son label) en rouge """
850 label.configure(bg='gray95',fg='red')
852 def deselectitem(self,label,mot='',commande=None) :
853 """ Remet l'item (représenté par son label) en noir"""
854 label.configure(bg='gray95',fg='black')
855 self.arg_selected = ''
856 if commande != None : commande(mot)
858 def cherche_selected_item(self):
859 index=self.MCbox.index(self.selection[1])
860 lign,col=map(int,string.split(index,'.'))
863 def remove_selected_item(self):
864 index=self.MCbox.index(self.selection[1])
865 lign,col=map(int,string.split(index,'.'))
866 del self.liste[lign-1]
869 def entry_changed(self,event=None):
870 """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
871 de l'entry et frappe <Return>"""
872 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
873 filtre = self.entry.get()+"*"
874 FILTRE = string.upper(filtre)
875 for arg in self.liste :
876 if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
877 self.highlightitem(self.dico_labels[arg])
878 index = self.MCbox.index(self.dico_labels[arg])
879 self.MCbox.see(index)
880 self.arg_selected = arg
881 self.dico_labels[self.arg_selected].focus_set()
885 #self.dico_labels[self.arg_selected].focus_set()
889 def get_liste_BAK(self):
893 # PN attention à la gestion des paramétres
894 # cela retourne H = 1 , et ni H, ni 1
896 # print val.__class__.__name__
899 for val in self.liste:
907 def put_liste(self,liste):
912 """ Cette classe permet d'afficher au lancement d'EFICAS le message
913 d'attente et la barre de progression"""
914 def __init__(self,master,message,barre ='oui'):
915 from Tools.foztools.foztools import Slider
916 fonte=fontes.standard12_gras
918 self.frame = Frame(self.master)
919 self.frame.pack(expand=1,fill='both')
920 self.mess = Label(self.frame,text=message,justify='center',
921 bd=2,relief='groove',font=fonte)
922 self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
923 self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
924 fillColor='#00008b',width=200,height=30,
925 background='white',labelColor='red')
927 self.progress.frame.pack(in_=self.frame,side='top')
930 self.progress.frame.after(1000,self.update)
932 def configure(self,**options):
933 if options.has_key('message'):
934 self.mess.configure(text=options['message'])
935 if options.has_key('barre'):
936 if options['barre'] == 'oui' :
937 self.progress.frame.pack(in_=self.frame,side='top')
938 elif options['barre'] == 'non' :
939 self.progress.frame.pack_forget()
940 self.master.update_idletasks()
946 def update(self,event=None):
947 """ Permet de faire avancer la barre de progression """
950 bar.value = bar.value+self.increment
952 self.master.after(100,self.update)
956 def configure_barre(self,nb):
957 """ Calcule l'incrément de progression de la barre en fonction
958 du nombre d'opérations à effectuer afin que le compteur
959 soit à 100% à la fin des opérations"""
960 self.increment = 100./nb
961 self.progress.update()
963 class Ask_Format_Fichier :
965 Cette classe permet de créer une fenêtre Toplevel dans laquelle
966 on propose le choix du format de fichier de commandes à ouvrir
968 def __init__(self,appli):
969 self.fenetre = Toplevel()
970 self.fenetre.configure(width = 250,height=150)
971 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
972 self.fenetre.title("Choix du format du fichier de commandes")
973 # définition des frames
974 self.frame_texte = Frame(self.fenetre)
975 self.frame_radioboutons = Frame(self.fenetre)
976 self.frame_bouton_ok = Frame(self.fenetre)
977 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
978 self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
979 self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
980 # définition de la zone texte et du scrollbar
981 zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
982 zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
983 # définition des radioboutons
984 Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
985 variable=appli.format_fichier,value='Aster').pack(anchor='n')
986 Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
987 variable=appli.format_fichier,value='Python').pack(anchor='n')
988 # création du bouton OK
989 Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
990 # centrage de la fenêtre
991 centerwindow(self.fenetre)
994 self.fenetre.destroy()
996 class BARRE_K2000(Toplevel):
997 def __init__(self,master=None,text = ""):
998 Toplevel.__init__(self,master,relief='groove')
999 self.master.iconify()
1000 self.geometry("250x100+0+0")
1001 self.protocol("WM_DELETE_WINDOW",self.quit)
1002 # frame principale dans self (= Toplevel)
1003 self.frame = Frame(self)
1004 self.frame.place(relwidth=1,relheight=1)
1005 # frame contenant le texte à afficher
1006 self.frame_text = Frame(self.frame)
1007 self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
1008 # frame contenant le canvas de la barre
1009 self.frame_canv = Frame(self.frame)
1010 self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
1011 # canvas dans lequel sera affichée la barre K2000
1012 self.canvas = Canvas(self.frame_canv)
1013 self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
1014 # on affiche le texte et la barre
1015 self.build_text(text)
1017 #self.overrideredirect(1)
1018 # on active la barre ...
1019 self.master.after(1000,self.launch)
1020 # on centre la fenêtre
1024 def build_text(self,text):
1026 Affichage de text dans frame_text
1028 self.texte_var = StringVar()
1029 self.texte_var.set(text)
1030 Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
1032 def build_batons(self):
1034 Construit la suite de bâtons dans le canvas
1040 for i in range(0,40):
1041 id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
1042 self.l_batons.append(id)
1046 Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
1050 self.master.deiconify()
1052 if self.sens == 'D':
1053 self.black = self.black+1
1054 l_bat = self.l_batons[0:self.black+1]
1056 elif self.sens == 'G':
1057 self.black = self.black-1
1058 l_bat = self.l_batons[self.black:]
1062 if num_color < 10 : color = 'black'
1063 elif num_color > 90 : color = 'white'
1064 else: color = 'gray'+`num_color`
1065 self.canvas.itemconfigure(bat,fill=color)
1067 if self.black == len(self.l_batons) :
1069 if self.black == 0 and self.sens == 'G':self.sens = 'D'
1070 self.after(80,self.launch)
1072 def update_text(self,new_text):
1074 Remplace le texte affiché par new_text
1076 self.texte_var.set(new_text)
1081 class ListeChoixParGroupes(ListeChoix) :
1083 Cette classe est utilisée pour afficher une liste de commandes classées par
1084 groupes. L'utilisateur peut réaliser des actions de selection
1085 qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
1087 liste_commandes = (("<Enter>",self.selectCmd),
1088 ("<Leave>",self.deselectCmd),
1089 ("<Double-Button-1>",self.defCmd))
1090 Il s'agit d'une liste de doublets dont le premier element est un evenement et le
1091 deuxieme un callback a appeler sur l'evenement en question.
1094 def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
1095 active ='oui',filtre='non',titre='',optionReturn=None):
1096 self.parent = parent
1098 self.liste_groupes = liste_groupes
1099 self.dict_groupes = dict_groupes
1101 self.selection = None
1102 self.liste_commandes = liste_commandes
1103 self.liste_marques = liste_marques
1104 self.arg_selected=''
1105 self.active = active
1107 self.filtre = filtre
1108 self.optionReturn = optionReturn
1111 def affiche_liste(self):
1112 """ Affiche la liste dans la fenêtre"""
1114 self.MCbox.config(state=NORMAL)
1115 self.MCbox.delete(1.0,END)
1116 for grp in self.liste_groupes:
1117 # On itère sur les groupes
1118 if grp == "CACHE":continue
1119 liste_commandes=self.dict_groupes[grp]
1120 text="GROUPE<<<<<<<< "+grp+" "
1121 text=text+">"*max(0,30-len(text))
1122 label = Label(self.MCbox,
1124 fg = 'black',bg = 'gray95',justify = 'left')
1125 # On stocke la relation entre le nom de la commande et le label
1126 self.dico_labels[grp]=label
1127 liste_labels.append(label)
1128 self.MCbox.window_create(END,
1131 self.MCbox.insert(END,'\n')
1132 for cmd in liste_commandes:
1133 label = Label(self.MCbox,
1135 fg = 'black',bg = 'gray95',justify = 'left')
1136 # On stocke la relation entre le nom de la commande et le label
1137 self.dico_labels[cmd]=label
1138 self.MCbox.window_create(END,
1141 self.MCbox.insert(END,'\n')
1143 def null(*tp,**args): return
1145 if self.active == 'oui':
1146 # Traitement par defaut des evenements
1147 label.bind("<Enter>",lambda e,s=self,c=null,x=cmd,l=label: s.selectitem(x,l,c))
1148 label.bind("<Leave>",lambda e,s=self,c=null,x=cmd,l=label: s.deselectitem(l,x,c))
1149 label.bind("<Double-Button-1>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1150 label.bind("<Return>",lambda e,s=self,c=null,x=cmd,l=label: s.chooseitem(x,l,c))
1151 label.bind("<Key-Right>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1152 label.bind("<Key-Down>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectNextItem(x,l,c,gr,x))
1153 label.bind("<Key-Left>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1154 label.bind("<Key-Up>",lambda e,s=self,c=null,x=cmd,l=label,gr=grp: s.selectPrevItem(x,l,c,gr,x))
1156 # Si des callbacks sont definis on les utilise
1157 for event,callback in self.liste_commandes:
1158 if event == "<Enter>":
1159 label.bind("<Enter>",lambda e,s=self,c=callback,x=cmd,l=label: s.selectitem(x,l,c))
1160 elif event == "<Leave>":
1161 label.bind("<Leave>",lambda e,s=self,c=callback,x=cmd,l=label: s.deselectitem(l,x,c))
1162 elif event == "<Double-Button-1>":
1163 label.bind("<Double-Button-1>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1164 elif event == "<Return>":
1165 label.bind("<Return>",lambda e,s=self,c=callback,x=cmd,l=label: s.chooseitem(x,l,c))
1166 elif event == "<Key-Right>":
1167 label.bind("<Key-Right>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1168 elif event == "<Key-Down>":
1169 label.bind("<Key-Down>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectNextItem(x,l,c,gr,x))
1170 elif event == "<Key-Left>":
1171 label.bind("<Key-Left>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1172 elif event == "<Key-Up>":
1173 label.bind("<Key-Up>",lambda e,s=self,c=callback,x=cmd,l=label,gr=grp:s.selectPrevItem(x,l,c,gr,x))
1175 label.bind(event,lambda e,s=self,c=callback,x=cmd,l=label: c())
1177 for marque in self.liste_marques:
1179 self.markitem(liste_labels[marque])
1183 self.MCbox.config(state=DISABLED)
1184 self.selection = None
1186 def selectPrevItem(self,mot,label,callback,group,cmd):
1187 g=self.liste_groupes.index(group)
1188 liste_commandes=self.dict_groupes[group]
1189 c=liste_commandes.index(cmd)
1191 co=liste_commandes[c-1]
1193 # debut de liste. On passe au groupe precedent
1195 gr=self.liste_groupes[g-1]
1196 co=self.dict_groupes[gr][-1]
1198 # debut des groupes. On ne fait rien
1201 # On a trouve l'item precedent
1203 labelsuivant=self.dico_labels[co]
1204 if self.selection != None :
1205 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
1206 self.selection = (co,labelsuivant,self.selection[2])
1207 index = self.MCbox.index(labelsuivant)
1208 self.MCbox.see(index)
1209 self.arg_selected=co
1210 self.highlightitem(labelsuivant)
1211 labelsuivant.focus_set()
1214 def selectNextItem(self,mot,label,callback,group,cmd):
1215 g=self.liste_groupes.index(group)
1216 liste_commandes=self.dict_groupes[group]
1217 c=liste_commandes.index(cmd)
1219 co=liste_commandes[c+1]
1221 # fin de liste. On passe au groupe suivant
1223 gr=self.liste_groupes[g+1]
1224 co=self.dict_groupes[gr][0]
1226 # fin des groupes. On ne fait rien
1228 # On a trouve l'item suivant
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 entry_changed(self,event=None):
1243 Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1244 de l'entry et frappe <Return>
1246 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1248 filtre = self.entry.get()+"*"
1249 FILTRE = string.upper(filtre)
1251 # On cherche d'abord dans les noms de groupe
1252 # puis dans les noms de commande groupe par groupe
1254 for grp in self.liste_groupes:
1255 if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1256 self.highlightitem(self.dico_labels[grp])
1257 index = self.MCbox.index(self.dico_labels[grp])
1258 self.MCbox.see(index)
1259 # On ne selectionne pas le groupe
1260 #self.arg_selected = grp
1261 self.dico_labels[grp].focus_set()
1262 # On a trouve un groupe on arrete la recherche
1265 for grp in self.liste_groupes:
1266 for cmd in self.dict_groupes[grp] :
1267 if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1268 self.highlightitem(self.dico_labels[cmd])
1269 index = self.MCbox.index(self.dico_labels[cmd])
1270 self.MCbox.see(index)
1271 self.arg_selected = cmd
1272 self.dico_labels[self.arg_selected].focus_set()
1273 # On a trouve une commande on arrete la recherche