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)
140 class FenetreYesNo(Fenetre):
141 def __init__(self,appli,titre="",texte="",yes="Yes",no="No"):
143 self.fenetre = Toplevel()
144 self.fenetre.configure(width = 800,height=500)
145 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
146 self.fenetre.title(titre)
147 self.texte = string.replace(texte,'\r\n','\n')
149 fonte=fontes.standardcourier10
150 # définition des frames
151 self.frame_texte = Frame(self.fenetre)
152 self.frame_boutons = Frame(self.fenetre)
153 self.frame_boutons.place(relx=0,rely=0, relwidth=1.,relheight=0.1)
154 self.frame_texte.place( relx=0,rely=0.1, relwidth=1, relheight=0.9)
155 # définition de la zone texte et du scrollbar
156 self.zone_texte = Text(self.frame_texte,font=fonte)
157 self.zone_texte.bind("<Key-Prior>", self.page_up)
158 self.zone_texte.bind("<Key-Next>", self.page_down)
159 self.zone_texte.bind("<Key-Up>", self.unit_up)
160 self.zone_texte.bind("<Key-Down>", self.unit_down)
161 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
162 #self.scroll_h = Scrollbar (self.frame_texte,command = self.zone_texte.xview)
163 self.scroll_v.pack(side='right',fill ='y')
164 #self.scroll_h.pack(side='bottom',fill ='x')
165 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
166 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
167 # définition des boutons
168 self.but_yes = Button(self.frame_boutons,text = yes,command=self.yes)
169 self.but_no = Button(self.frame_boutons,text = no,command = self.no)
170 self.but_yes.place(relx=0.4,rely=0.5,anchor='center')
171 self.but_no.place(relx=0.6,rely=0.5,anchor='center')
173 self.affiche_texte(self.texte)
174 centerwindow(self.fenetre)
184 class FenetreDeSelection(Fenetre):
185 """ Classe dérivée de Fenêtre permettant la récupération d'une zone de texte sélectionnée.
186 Cette classe est utilisée pour affecter une liste de valeurs à un mot-clé.
188 def __init__(self,panel,item,appli,titre="",texte="",cardinal=1):
189 Fenetre.__init__(self,appli,titre=titre,texte=texte)
190 self.cardinal=cardinal
191 self.fenetre.configure(width = 320,height=400)
192 centerwindow(self.fenetre)
195 self.fenetre.title(titre)
196 self.but_save.configure(text="Ajouter",command=self.traite_selection)
197 # séparateur par défaut
198 self.separateur = ";"
199 # création de la zone de saisie du séparateur
200 l_separateurs_autorises = self.get_separateurs_autorises()
201 self.choix_sep = Pmw.ComboBox(self.frame_boutons,
202 label_text = "Séparateur :",
205 selectioncommand = self.choose_separateur,
206 scrolledlist_items = l_separateurs_autorises)
207 self.choix_sep.component('entry').configure(width=6)
208 self.choix_sep.place(relx=0.01,rely=0.5,anchor='w')
209 self.choix_sep.selectitem(self.separateur)
211 self.but_quit.place_forget()
212 self.but_save.place_forget()
213 self.but_save.place(relx=0.6,rely=0.5,anchor='center')
214 self.but_quit.place(relx=0.8,rely=0.5,anchor='center')
216 def get_separateurs_autorises(self):
218 Retourne la liste des séparateurs autorisés
220 return ['espace',';',',']
222 def choose_separateur(self,nom_sep):
224 Affecte à self.separateur le caractère séparateur correspondant à nom_sep
226 if nom_sep == 'espace' :
227 self.separateur = ' '
229 self.separateur = nom_sep
231 def traite_selection(self):
232 """ Cette méthode effectue tous les traitements nécessaires pour vérifier
233 et affecter la liste de valeurs à l'objet réprésenté par self.item
235 # Récupère la liste des chaines de caractères de la zone sélectionnée
236 message,liste = self.recupere_liste()
237 if self.test_probleme(message,"Sélectionnez des données") == 0:
239 # Vérifie que le nombre de données est dans les limites attendues
240 message = self.verif_liste(liste)
241 if self.test_probleme(message,"Vérifiez le nombre de données") == 0:
243 # Crée une liste de valeurs du type attendu
244 message,liste_valeurs = self.creation_liste_valeurs(liste)
245 if self.test_probleme(message,"Vérifiez le type des données") == 0:
247 # Vérifie que chaque valeur est dans le domaine exigé
248 message = self.verif_valeurs(liste_valeurs)
249 if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:
251 # Ajoute les valeurs dans la liste de valeurs du mot-clé
252 if self.cardinal != 1 :
256 if (len(liste_valeurs)%nb != 0):
257 message="La cardinalité n'est pas correcte"
258 self.test_probleme(message,"On attend des tuples")
260 for i in range(len(liste_valeurs)/nb) :
262 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1])
264 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1], liste_valeurs[i*nb+2])
266 print "probleme : prevenir la maintenance Eficas"
269 liste_valeurs=l_valeurs
270 self.ajouter_valeurs(liste_valeurs)
271 self.appli.affiche_infos("Liste de valeurs acceptée")
273 def test_probleme(self, message, message_eficas):
274 """ Cette méthode affiche un message d'erreur si message != ''
275 et retourne 0, sinon retourne 1 sans rien afficher.
278 showinfo("Problème",message)
279 self.fenetre.tkraise()
280 self.appli.affiche_infos(message_eficas)
285 def recupere_liste(self):
286 """ Cette méthode récupère le texte de la zone sélectionnée, construit et
287 retourne une liste avec les chaines qui se trouvent entre les séparateurs.
288 S'il n'y a pas de données selectionnées, elle retourne un message d'erreur
293 selection=self.fenetre.selection_get()
295 message = "Pas de donnée sélectionnée"
297 # les retours chariots doivent être interprétés comme des séparateurs
298 selection = string.replace(selection,'\n',self.separateur)
299 # on splitte la sélection suivant le caractère séparateur
300 liste_chaines = string.split(selection,self.separateur)
302 for chaine in liste_chaines:
303 chaine = string.strip(chaine)
304 if chaine != '' : l_chaines.append(chaine)
305 return message,l_chaines
307 def verif_liste(self, liste):
308 """ Cette méthode effectue des tests sur le nombre d'éléments de la liste
309 et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur
313 # nombre d'éléments sélectionnés
314 nombre_elements = len(liste)
315 # nombre d'éléments déja dans la liste du panel
316 nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())
317 multiplicite = self.item.GetMultiplicite()
318 if (nombre_elements % multiplicite) != 0:
319 message = "Vous devez sélectionner "+str(multiplicite)+" * n données"
321 nombre_valeurs = nombre_elements / multiplicite
322 cardinalite = self.item.GetMinMax()
323 if nombre_valeurs < cardinalite[0]:
324 message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"
326 if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):
327 message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"
332 def creation_liste_valeurs(self, liste):
333 """ Cette méthode crée et retourne une liste de valeurs du type attendu
334 par le mot-clé. La liste de valeurs est créée à partir de la liste
335 de chaines de caractères transmise.
337 type_attendu = self.item.GetType()[0]
338 if type_attendu == 'R':
339 return self.convertir(liste, f_conversion= float)
340 elif type_attendu == 'I':
341 return self.convertir(liste, f_conversion= int)
342 elif type_attendu == 'TXM':
343 return self.convertir(liste)
345 message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"
348 def convertir(self, liste, f_conversion=None):
349 """ Cette méthode essaie de convertir les éléments de la liste avec la
350 fonction f_conversion si elle existe, et retourne la liste des
351 éléments dans le type voulu en cas de succès, sinon retourne None.
358 liste_valeurs.append(f_conversion(chaine))
360 message = "Impossible de convertir "+chaine+" dans le type attendu"
363 liste_valeurs.append(chaine)
364 return message,liste_valeurs
366 def verif_valeurs(self, liste_valeurs):
367 """ Cette méthode teste tous les éléments de la liste, et retourne 1 si chaque
368 élément est dans le domaine voulu.
371 for valeur in liste_valeurs:
372 test = self.item.IsInIntervalle(valeur)
374 intervalle = str(self.item.GetIntervalle()[0])+","+str(self.item.GetIntervalle()[1])
375 message = "La valeur "+str(valeur)+" n'est pas dans l'intervalle ["+intervalle+"]"
379 def ajouter_valeurs(self, liste_valeurs):
380 """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""
381 liste = self.panel.Liste_valeurs.get_liste()
382 liste.extend(liste_valeurs)
383 self.panel.Liste_valeurs.put_liste(liste)
387 Cette classe permet de créer une boîte Dialog dans laquelle
388 on affiche un formulaire à remplir par l'utilisateur
390 def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
391 if items in ((),[]) : return
395 self.fen_pere = fen_pere
396 self.obj_pere = obj_pere
398 self.command = commande
402 self.init_validateurs()
405 self.init_items_formulaire()
406 self.fenetre.activate(geometry='centerscreenalways')
408 def init_validateurs(self):
410 Crée le dictionnaire des validateurs des objets reconnus par le formulaire
412 self.d_validateurs = {}
413 self.d_validateurs['rep'] = self.repvalidator
414 self.d_validateurs['file'] = self.filevalidator
415 self.d_validateurs['cata']= self.catavalidator
417 def init_fenetre(self):
419 Crée la fenêtre Dialog
421 if self.mode == 'query':
422 buttons=('Valider','Annuler')
423 defaultbutton = 'Valider'
424 elif self.mode == 'display':
426 buttons=(self.command[0],'OK')
431 self.fenetre = Pmw.Dialog(self.fen_pere,
433 defaultbutton = defaultbutton,
435 command = self.execute)
436 self.fenetre.withdraw()
438 def init_texte(self):
440 Crée le label qui affiche le texte à l'intérieur du panneau
442 fonte=fontes.standard
443 fr_texte = Frame(self.fenetre.interior(),height=60)
444 fr_texte.pack(side='top',fill='x',expand=1)
445 Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
447 def init_items_formulaire(self):
449 Crée et affiche les items dans la boîte de dialogue
453 self.item_widgets = {}
455 for item in self.items:
456 if len(item[0])>length_maxi : length_maxi = len(item[0])
457 window = self.fenetre.interior()
458 for item in self.items :
459 label,nature,nom_var,defaut = item
460 # création de la frame
461 fr_item = Frame(window,height=40,width=700)
462 fr_item.pack(side='top',fill='x',expand=1)
464 Label(fr_item,text = label).place(relx=0.05,rely=0.4)
465 if nature in ('rep','file','cata'):
466 # création de l'entry
467 e_item = Entry(fr_item)
468 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
469 self.widgets.append(e_item)
470 self.item_widgets[item] = e_item
471 if defaut : e_item.insert(0,str(defaut))
472 elif nature == 'YesNo':
473 # création de la StringVar
475 setattr(self,'item_'+nom_var,var)
477 # création du radiobouton
478 rb1 = Radiobutton(fr_item,text='OUI',variable=var,value='OUI')
479 rb2 = Radiobutton(fr_item,text='NON',variable=var,value='NON')
480 rb1.place(relx=0.65,rely=0.5,anchor='center')
481 rb2.place(relx=0.80,rely=0.5,anchor='center')
482 self.widgets.append((rb1,rb2))
483 self.item_widgets[item] = var
484 # détermination de la méthode à appliquer sur les boutons
485 if self.mode == 'query':
486 function = self.active
487 elif self.mode == 'display':
488 function = self.inactive
491 # on applique la méthode sur les boutons (activation ou désactivation)
492 for widget in self.widgets :
493 if type(widget) == types.TupleType:
495 apply(function,(widg,),{})
497 apply(function,(widget,),{})
499 def active(self,widget):
501 Active le widget passé en argument
503 widget.configure(state='normal',bg='white')
505 def inactive(self,widget):
507 Inactive le widget passé en argument
509 if not isinstance(widget,Radiobutton) :
510 widget.configure(state='disabled',bg='gray95')
512 widget.configure(state='disabled')
514 # --------------------------------------------------------------------------------
515 # Validateurs des noms de répertoire, de fichiers et de catalogues
516 # -------------------------------------------------------------------------------
518 def repvalidator(self,text):
520 Teste si text peut faire référence à un répertoire ou non
521 Retourne 1 si valide, 0 sinon
523 return os.path.isdir(text),'Répertoire introuvable : %s' %text
525 def filevalidator(self,text):
527 Teste si text peut faire référence à un fichier ou non
528 Retourne 1 si valide, 0 sinon
530 return os.path.isfile(text),'Fichier introuvable : %s' %text
532 def catavalidator(self,text):
534 Teste si text est un chemin d'accès valide à un catalogue
535 Retourne 1 si valide, 0 sinon
537 return os.path.isfile(text),"Catalogue introuvable : %s" %text
539 # --------------------------------------------------------------------------------
540 # Méthodes callbacks des boutons et de fin
541 # --------------------------------------------------------------------------------
543 def execute(self,txt):
545 Cette commande est activée à chaque clic sur un bouton.
546 Redirige l'action sur la bonne méthode en fonction du bouton activé
550 elif txt in ('OK','Annuler'):
552 elif txt == 'Modifier':
553 self.resultat = apply(self.command[1],(),{})
554 self.fenetre.destroy()
556 print "Nom de bouton inconnu"
561 Commande qui termine le panneau et sauvegarde les nouvelles options
562 dans l'objet resultat (dictionnaire)
565 for item,widget in self.item_widgets.items():
568 valeur = widget.get()
569 if self.d_validateurs.has_key(type_var):
570 test = self.d_validateurs[type_var](valeur)
572 # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
573 # sans tuer la fenêtre bien sûr
574 widget.selection_range(0,END)
576 dico[nom_var] = valeur
577 self.fenetre.destroy()
581 self.fenetre.destroy()
585 """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
586 en passant les commandes à lancer suivant différents bindings """
587 def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre=''):
592 self.selection = None
593 self.liste_commandes = liste_commandes
594 self.liste_marques = liste_marques
602 self.make_label_titre()
603 self.make_entry_filtre()
606 self.entry.component('entry').focus()
610 def make_label_titre(self):
611 """ Crée le label correspondant au titre """
612 if self.titre == '' : return
613 fonte_titre = fontes.standard_gras_souligne
614 self.label = Label(self.page,
617 self.label.pack(side='top',pady=2)
619 def make_entry_filtre(self):
620 """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
621 if self.filtre != 'oui' : return
622 self.entry = Pmw.EntryField(self.page,labelpos='w',
623 label_text="Filtre :",
624 command=self.entry_changed)
625 self.entry.pack(side='top',pady=2)
627 def make_text_box(self):
628 """ Crée la fenêtre texte dans laquelle sera affichée la liste """
629 self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
630 self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
631 self.MCscroll.pack(side='right',fill ='y',pady=2)
632 self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
633 self.MCbox.configure(yscrollcommand=self.MCscroll.set)
635 def affiche_liste(self):
636 """ Affiche la liste dans la fenêtre"""
638 self.MCbox.config(state=NORMAL)
639 self.MCbox.delete(1.0,END)
640 for objet in self.liste :
641 if type(objet) == types.InstanceType:
646 elif type(objet) in (types.StringType,types.IntType):
648 elif type(objet) == types.FloatType :
649 #mot = repr_float(objet)
651 elif type(objet) == types.TupleType :
663 label = Label(self.MCbox,
665 fg = 'black',bg = 'gray95',justify = 'left')
666 self.dico_labels[mot]=label
667 liste_labels.append(label)
668 self.MCbox.window_create(END,
671 self.MCbox.insert(END,'\n')
672 if self.active == 'oui':
673 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))
674 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))
675 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))
677 for marque in self.liste_marques:
679 self.markitem(liste_labels[marque])
683 self.MCbox.config(state=DISABLED)
684 self.selection = None
686 def chooseitem(self,mot,label,commande):
687 """ Active la méthode de choix passée en argument"""
690 except AsException,e:
692 showerror(raison.split('\n')[0],raison)
694 def selectitem(self,mot,label,commande) :
695 """ Met l'item sélectionné (représenté par son label) en surbrillance
696 et lance la commande associée au double-clic"""
697 if self.selection != None :
698 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
699 self.highlightitem(label)
700 self.selection = (mot,label,commande)
701 self.arg_selected = mot
704 def highlightitem(self,label) :
705 """ Met l'item représenté par son label en surbrillance """
706 label.configure(bg='#00008b',fg='white')
708 def markitem(self,label):
709 """ Met l'item (représenté par son label) en rouge """
710 label.configure(bg='gray95',fg='red')
712 def deselectitem(self,label,mot='',commande=None) :
713 """ Remet l'item (représenté par son label) en noir"""
714 label.configure(bg='gray95',fg='black')
715 self.arg_selected = ''
716 if commande != None : commande(mot)
718 def cherche_selected_item(self):
719 index=self.MCbox.index(self.selection[1])
720 lign,col=map(int,string.split(index,'.'))
723 def remove_selected_item(self):
724 index=self.MCbox.index(self.selection[1])
725 lign,col=map(int,string.split(index,'.'))
726 del self.liste[lign-1]
729 def entry_changed(self,event=None):
730 """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
731 de l'entry et frappe <Return>"""
732 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
733 filtre = self.entry.get()+"*"
734 FILTRE = string.upper(filtre)
735 for arg in self.liste :
736 if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
737 self.highlightitem(self.dico_labels[arg])
738 index = self.MCbox.index(self.dico_labels[arg])
739 self.MCbox.see(index)
740 self.arg_selected = arg
743 def get_liste_old(self):
746 # PN attention à la gestion des paramétres
747 # cela retourne H = 1 , et ni H, ni 1
749 # print val.__class__.__name__
752 for val in self.liste:
760 def put_liste(self,liste):
765 """ Cette classe permet d'afficher au lancement d'EFICAS le message
766 d'attente et la barre de progression"""
767 def __init__(self,master,message,barre ='oui'):
768 from Tools.foztools.foztools import Slider
769 fonte=fontes.standard12_gras
771 self.frame = Frame(self.master)
772 self.frame.pack(expand=1,fill='both')
773 self.mess = Label(self.frame,text=message,justify='center',
774 bd=2,relief='groove',font=fonte)
775 self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
776 self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
777 fillColor='#00008b',width=200,height=30,
778 background='white',labelColor='red')
780 self.progress.frame.pack(in_=self.frame,side='top')
783 self.progress.frame.after(1000,self.update)
785 def configure(self,**options):
786 if options.has_key('message'):
787 self.mess.configure(text=options['message'])
788 if options.has_key('barre'):
789 if options['barre'] == 'oui' :
790 self.progress.frame.pack(in_=self.frame,side='top')
791 elif options['barre'] == 'non' :
792 self.progress.frame.pack_forget()
793 self.master.update_idletasks()
799 def update(self,event=None):
800 """ Permet de faire avancer la barre de progression """
803 bar.value = bar.value+self.increment
805 self.master.after(100,self.update)
809 def configure_barre(self,nb):
810 """ Calcule l'incrément de progression de la barre en fonction
811 du nombre d'opérations à effectuer afin que le compteur
812 soit à 100% à la fin des opérations"""
813 self.increment = 100./nb
814 self.progress.update()
816 class Ask_Format_Fichier :
818 Cette classe permet de créer une fenêtre Toplevel dans laquelle
819 on propose le choix du format de fichier de commandes à ouvrir
821 def __init__(self,appli):
822 self.fenetre = Toplevel()
823 self.fenetre.configure(width = 250,height=150)
824 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
825 self.fenetre.title("Choix du format du fichier de commandes")
826 # définition des frames
827 self.frame_texte = Frame(self.fenetre)
828 self.frame_radioboutons = Frame(self.fenetre)
829 self.frame_bouton_ok = Frame(self.fenetre)
830 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
831 self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
832 self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
833 # définition de la zone texte et du scrollbar
834 zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
835 zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
836 # définition des radioboutons
837 Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
838 variable=appli.format_fichier,value='Aster').pack(anchor='n')
839 Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
840 variable=appli.format_fichier,value='Python').pack(anchor='n')
841 # création du bouton OK
842 Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
843 # centrage de la fenêtre
844 centerwindow(self.fenetre)
847 self.fenetre.destroy()
849 class BARRE_K2000(Toplevel):
850 def __init__(self,master=None,text = ""):
851 Toplevel.__init__(self,master,relief='groove')
852 self.master.iconify()
853 self.geometry("250x100+0+0")
854 self.protocol("WM_DELETE_WINDOW",self.quit)
855 # frame principale dans self (= Toplevel)
856 self.frame = Frame(self)
857 self.frame.place(relwidth=1,relheight=1)
858 # frame contenant le texte à afficher
859 self.frame_text = Frame(self.frame)
860 self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
861 # frame contenant le canvas de la barre
862 self.frame_canv = Frame(self.frame)
863 self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
864 # canvas dans lequel sera affichée la barre K2000
865 self.canvas = Canvas(self.frame_canv)
866 self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
867 # on affiche le texte et la barre
868 self.build_text(text)
870 #self.overrideredirect(1)
871 # on active la barre ...
872 self.master.after(1000,self.launch)
873 # on centre la fenêtre
877 def build_text(self,text):
879 Affichage de text dans frame_text
881 self.texte_var = StringVar()
882 self.texte_var.set(text)
883 Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
885 def build_batons(self):
887 Construit la suite de bâtons dans le canvas
893 for i in range(0,40):
894 id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
895 self.l_batons.append(id)
899 Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
903 self.master.deiconify()
906 self.black = self.black+1
907 l_bat = self.l_batons[0:self.black+1]
909 elif self.sens == 'G':
910 self.black = self.black-1
911 l_bat = self.l_batons[self.black:]
915 if num_color < 10 : color = 'black'
916 elif num_color > 90 : color = 'white'
917 else: color = 'gray'+`num_color`
918 self.canvas.itemconfigure(bat,fill=color)
920 if self.black == len(self.l_batons) :
922 if self.black == 0 and self.sens == 'G':self.sens = 'D'
923 self.after(80,self.launch)
925 def update_text(self,new_text):
927 Remplace le texte affiché par new_text
929 self.texte_var.set(new_text)
934 class ListeChoixParGroupes(ListeChoix) :
936 Cette classe est utilisée pour afficher une liste de commandes classées par
937 groupes. L'utilisateur peut réaliser des actions de selection
938 qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
940 def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
941 active ='oui',filtre='non',titre=''):
944 self.liste_groupes = liste_groupes
945 self.dict_groupes = dict_groupes
947 self.selection = None
948 self.liste_commandes = liste_commandes
949 self.liste_marques = liste_marques
956 def affiche_liste(self):
957 """ Affiche la liste dans la fenêtre"""
959 self.MCbox.config(state=NORMAL)
960 self.MCbox.delete(1.0,END)
961 for grp in self.liste_groupes:
962 # On itère sur les groupes
963 if grp == "CACHE":continue
964 liste_commandes=self.dict_groupes[grp]
965 text="GROUPE<<<<<<<< "+grp+" "
966 text=text+">"*max(0,30-len(text))
967 label = Label(self.MCbox,
969 fg = 'black',bg = 'gray95',justify = 'left')
970 # On stocke la relation entre le nom de la commande et le label
971 self.dico_labels[grp]=label
972 liste_labels.append(label)
973 self.MCbox.window_create(END,
976 self.MCbox.insert(END,'\n')
977 for cmd in liste_commandes:
978 label = Label(self.MCbox,
980 fg = 'black',bg = 'gray95',justify = 'left')
981 # On stocke la relation entre le nom de la commande et le label
982 self.dico_labels[cmd]=label
983 self.MCbox.window_create(END,
986 self.MCbox.insert(END,'\n')
987 if self.active == 'oui':
988 label.bind(self.liste_commandes[0][0],
989 lambda e,s=self,c=self.liste_commandes[0][1],x=cmd,l=label : s.selectitem(x,l,c))
990 label.bind(self.liste_commandes[1][0],
991 lambda e,s=self,c=self.liste_commandes[1][1],x=cmd,l=label : s.deselectitem(l,x,c))
992 label.bind(self.liste_commandes[2][0],
993 lambda e,s=self,c=self.liste_commandes[2][1],x=cmd,l=label : s.chooseitem(x,l,c))
995 for marque in self.liste_marques:
997 self.markitem(liste_labels[marque])
1001 self.MCbox.config(state=DISABLED)
1002 self.selection = None
1004 def entry_changed(self,event=None):
1006 Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1007 de l'entry et frappe <Return>
1009 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1010 filtre = self.entry.get()+"*"
1011 FILTRE = string.upper(filtre)
1013 # On cherche d'abord dans les noms de groupe
1014 # puis dans les noms de commande groupe par groupe
1016 for grp in self.liste_groupes:
1017 if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1018 index = self.MCbox.index(self.dico_labels[grp])
1019 self.MCbox.see(index)
1020 # On ne selectionne pas le groupe
1021 #self.arg_selected = grp
1022 # On a trouve un groupe on arrete la recherche
1025 for grp in self.liste_groupes:
1026 for cmd in self.dict_groupes[grp] :
1027 if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1028 self.highlightitem(self.dico_labels[cmd])
1029 index = self.MCbox.index(self.dico_labels[cmd])
1030 self.MCbox.see(index)
1031 self.arg_selected = cmd
1032 # On a trouve une commande on arrete la recherche