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.cardinal=cardinal
197 self.fenetre.configure(width = 320,height=400)
198 centerwindow(self.fenetre)
201 self.fenetre.title(titre)
202 self.but_save.configure(text="Ajouter",command=self.traite_selection)
203 # séparateur par défaut
204 self.separateur = ";"
205 # création de la zone de saisie du séparateur
206 l_separateurs_autorises = self.get_separateurs_autorises()
207 self.choix_sep = Pmw.ComboBox(self.frame_boutons,
208 label_text = "Séparateur :",
211 selectioncommand = self.choose_separateur,
212 scrolledlist_items = l_separateurs_autorises)
213 self.choix_sep.component('entry').configure(width=6)
214 self.choix_sep.place(relx=0.01,rely=0.5,anchor='w')
215 self.choix_sep.selectitem(self.separateur)
217 self.but_quit.place_forget()
218 self.but_save.place_forget()
219 self.but_save.place(relx=0.6,rely=0.5,anchor='center')
220 self.but_quit.place(relx=0.8,rely=0.5,anchor='center')
223 def get_separateurs_autorises(self):
225 Retourne la liste des séparateurs autorisés
227 return ['espace',';',',']
229 def choose_separateur(self,nom_sep):
231 Affecte à self.separateur le caractère séparateur correspondant à nom_sep
233 if nom_sep == 'espace' :
234 self.separateur = ' '
236 self.separateur = nom_sep
238 def traite_selection(self):
239 """ Cette méthode effectue tous les traitements nécessaires pour vérifier
240 et affecter la liste de valeurs à l'objet réprésenté par self.item
242 # Récupère la liste des chaines de caractères de la zone sélectionnée
243 message,liste = self.recupere_liste()
244 if self.test_probleme(message,"Sélectionnez des données") == 0:
246 # Vérifie que le nombre de données est dans les limites attendues
247 message = self.verif_liste(liste)
248 if self.test_probleme(message,"Vérifiez le nombre de données") == 0:
250 # Crée une liste de valeurs du type attendu
251 message,liste_valeurs = self.creation_liste_valeurs(liste)
252 if self.test_probleme(message,"Vérifiez le type des données") == 0:
254 # Vérifie que chaque valeur est dans le domaine exigé
255 message = self.verif_valeurs(liste_valeurs)
256 if self.test_probleme(message,"Vérifiez le domaine des valeurs") == 0:
258 # Ajoute les valeurs dans la liste de valeurs du mot-clé
259 if self.cardinal != 1 :
263 if (len(liste_valeurs)%nb != 0):
264 message="La cardinalité n'est pas correcte"
265 self.test_probleme(message,"On attend des tuples")
267 for i in range(len(liste_valeurs)/nb) :
269 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1])
271 t=(liste_valeurs[i*nb], liste_valeurs[i*nb+1], liste_valeurs[i*nb+2])
273 print "probleme : prevenir la maintenance Eficas"
276 liste_valeurs=l_valeurs
277 self.ajouter_valeurs(liste_valeurs)
278 self.appli.affiche_infos("Liste de valeurs acceptée")
280 def test_probleme(self, message, message_eficas):
281 """ Cette méthode affiche un message d'erreur si message != ''
282 et retourne 0, sinon retourne 1 sans rien afficher.
285 showinfo("Problème",message)
286 self.fenetre.tkraise()
287 self.appli.affiche_infos(message_eficas)
292 def recupere_liste(self):
293 """ Cette méthode récupère le texte de la zone sélectionnée, construit et
294 retourne une liste avec les chaines qui se trouvent entre les séparateurs.
295 S'il n'y a pas de données selectionnées, elle retourne un message d'erreur
300 selection=self.fenetre.selection_get()
302 message = "Pas de donnée sélectionnée"
304 # les retours chariots doivent être interprétés comme des séparateurs
305 selection = string.replace(selection,'\n',self.separateur)
306 # on splitte la sélection suivant le caractère séparateur
307 liste_chaines = string.split(selection,self.separateur)
309 for chaine in liste_chaines:
310 chaine = string.strip(chaine)
311 if chaine != '' : l_chaines.append(chaine)
312 return message,l_chaines
314 def verif_liste(self, liste):
315 """ Cette méthode effectue des tests sur le nombre d'éléments de la liste
316 et retourne 1 si la liste est correcte, sinon 0 et le message d'erreur
320 # nombre d'éléments sélectionnés
321 nombre_elements = len(liste)
322 # nombre d'éléments déja dans la liste du panel
323 nombre_in_liste = len(self.panel.Liste_valeurs.get_liste())
324 multiplicite = self.item.GetMultiplicite()
325 if (nombre_elements % multiplicite) != 0:
326 message = "Vous devez sélectionner "+str(multiplicite)+" * n données"
328 nombre_valeurs = nombre_elements / multiplicite
329 cardinalite = self.item.GetMinMax()
330 if nombre_valeurs < cardinalite[0]:
331 message = "Vous devez sélectionner au moins "+str(cardinalite[0])+" valeurs"
333 if cardinalite[1] != "**" and nombre_valeurs > (long(cardinalite[1])-nombre_in_liste):
334 message = "La liste ne peut avoir plus de "+str(cardinalite[1])+" valeurs"
339 def creation_liste_valeurs(self, liste):
340 """ Cette méthode crée et retourne une liste de valeurs du type attendu
341 par le mot-clé. La liste de valeurs est créée à partir de la liste
342 de chaines de caractères transmise.
344 type_attendu = self.item.GetType()[0]
345 if type_attendu == 'R':
346 return self.convertir(liste, f_conversion= float)
347 elif type_attendu == 'I':
348 return self.convertir(liste, f_conversion= int)
349 elif type_attendu == 'TXM':
350 return self.convertir(liste)
352 message = "Seuls les entiers, les réels et les chaines de caractères sont convertis"
355 def convertir(self, liste, f_conversion=None):
356 """ Cette méthode essaie de convertir les éléments de la liste avec la
357 fonction f_conversion si elle existe, et retourne la liste des
358 éléments dans le type voulu en cas de succès, sinon retourne None.
365 liste_valeurs.append(f_conversion(chaine))
367 message = "Impossible de convertir "+chaine+" dans le type attendu"
370 liste_valeurs.append(chaine)
371 return message,liste_valeurs
373 def verif_valeurs(self, liste_valeurs):
374 """ Cette méthode teste tous les éléments de la liste, et retourne 1 si chaque
375 élément est dans le domaine voulu.
378 for valeur in liste_valeurs:
379 test = self.item.IsInIntervalle(valeur)
381 intervalle = str(self.item.GetIntervalle()[0])+","+str(self.item.GetIntervalle()[1])
382 message = "La valeur "+str(valeur)+" n'est pas dans l'intervalle ["+intervalle+"]"
386 def ajouter_valeurs(self, liste_valeurs):
387 """ Cette méthode ajoute les nouvelles valeurs à la liste existante."""
388 liste = self.panel.Liste_valeurs.get_liste()
389 liste.extend(liste_valeurs)
390 self.panel.Liste_valeurs.put_liste(liste)
392 class FenetreDeParametre(Fenetre) :
393 def __init__(self,parent,item,appli,texte):
396 self.fenetre = Toplevel()
397 self.fenetre.configure(width = 250,height=100)
398 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
399 self.fenetre.title("Parametres")
400 self.titre = "Parametres"
401 self.texte = string.replace(texte,'\r\n','\n')
402 fonte=fontes.standardcourier10
404 # définition des frames
405 self.frame_texte = Frame(self.fenetre)
406 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.7)
407 # définition de la zone texte et du scrollbar
408 self.zone_texte = Text(self.frame_texte,font=fonte)
409 self.zone_texte.bind("<Key-Prior>", self.page_up)
410 self.zone_texte.bind("<Key-Next>", self.page_down)
411 self.zone_texte.bind("<Key-Up>", self.unit_up)
412 self.zone_texte.bind("<Key-Down>", self.unit_down)
413 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
414 self.scroll_v.pack(side='right',fill ='y')
415 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
416 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
418 self.affiche_texte(self.texte)
419 self.zone_texte.config(state="disabled")
421 # définition des boutons
422 self.frame_boutons = Frame(self.fenetre)
423 self.frame_boutons.place(relheight=0.3,relx=0,rely=0.7,relwidth=1.)
424 self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
425 self.but_save = Button(self.frame_boutons,text = "Choisir",command = self.Choisir)
426 self.but_save.place(relx=0.6,rely=0,relheight=1)
427 self.but_quit.place(relx=0.8,rely=0,relheight=1)
432 selection=self.zone_texte.selection_get()
434 showerror("Pas de donnée sélectionnée",
435 "Selectionner un parametre")
437 for param in selection.splitlines():
438 nomparam=param[0:param.find("=")-1]
440 l_param=l_param+nomparam+','
441 self.parent.entry.delete(0,Tkinter.END)
442 self.parent.entry.insert(0,l_param[0:-1])
443 self.parent.valid_valeur()
448 Cette classe permet de créer une boîte Dialog dans laquelle
449 on affiche un formulaire à remplir par l'utilisateur
451 def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
452 if items in ((),[]) : return
456 self.fen_pere = fen_pere
457 self.obj_pere = obj_pere
459 self.command = commande
463 self.init_validateurs()
466 self.init_items_formulaire()
467 self.fenetre.activate(geometry='centerscreenalways')
469 def init_validateurs(self):
471 Crée le dictionnaire des validateurs des objets reconnus par le formulaire
473 self.d_validateurs = {}
474 self.d_validateurs['rep'] = self.repvalidator
475 self.d_validateurs['file'] = self.filevalidator
476 self.d_validateurs['cata']= self.catavalidator
478 def init_fenetre(self):
480 Crée la fenêtre Dialog
482 if self.mode == 'query':
483 buttons=('Valider','Annuler')
484 defaultbutton = 'Valider'
485 elif self.mode == 'display':
487 buttons=(self.command[0],'OK')
492 self.fenetre = Pmw.Dialog(self.fen_pere,
494 defaultbutton = defaultbutton,
496 command = self.execute)
497 self.fenetre.withdraw()
499 def init_texte(self):
501 Crée le label qui affiche le texte à l'intérieur du panneau
503 fonte=fontes.standard
504 fr_texte = Frame(self.fenetre.interior(),height=60)
505 fr_texte.pack(side='top',fill='x',expand=1)
506 Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
508 def init_items_formulaire(self):
510 Crée et affiche les items dans la boîte de dialogue
514 self.item_widgets = {}
516 for item in self.items:
517 if len(item[0])>length_maxi : length_maxi = len(item[0])
518 window = self.fenetre.interior()
519 for item in self.items :
520 label,nature,nom_var,defaut = item
521 # création de la frame
522 fr_item = Frame(window,height=40,width=700)
523 fr_item.pack(side='top',fill='x',expand=1)
525 Label(fr_item,text = label).place(relx=0.05,rely=0.4)
526 if nature in ('rep','file','cata'):
527 # création de l'entry
528 e_item = Entry(fr_item)
529 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
530 self.widgets.append(e_item)
531 self.item_widgets[item] = e_item
532 if defaut : e_item.insert(0,str(defaut))
533 elif nature == 'YesNo':
534 # création de la StringVar
536 setattr(self,'item_'+nom_var,var)
538 # création du radiobouton
539 rb1 = Radiobutton(fr_item,text='OUI',variable=var,value='OUI')
540 rb2 = Radiobutton(fr_item,text='NON',variable=var,value='NON')
541 rb1.place(relx=0.65,rely=0.5,anchor='center')
542 rb2.place(relx=0.80,rely=0.5,anchor='center')
543 self.widgets.append((rb1,rb2))
544 self.item_widgets[item] = var
545 # détermination de la méthode à appliquer sur les boutons
546 if self.mode == 'query':
547 function = self.active
548 elif self.mode == 'display':
549 function = self.inactive
552 # on applique la méthode sur les boutons (activation ou désactivation)
553 for widget in self.widgets :
554 if type(widget) == types.TupleType:
556 apply(function,(widg,),{})
558 apply(function,(widget,),{})
560 def active(self,widget):
562 Active le widget passé en argument
564 widget.configure(state='normal',bg='white')
566 def inactive(self,widget):
568 Inactive le widget passé en argument
570 if not isinstance(widget,Radiobutton) :
571 widget.configure(state='disabled',bg='gray95')
573 widget.configure(state='disabled')
575 # --------------------------------------------------------------------------------
576 # Validateurs des noms de répertoire, de fichiers et de catalogues
577 # -------------------------------------------------------------------------------
579 def repvalidator(self,text):
581 Teste si text peut faire référence à un répertoire ou non
582 Retourne 1 si valide, 0 sinon
584 return os.path.isdir(text),'Répertoire introuvable : %s' %text
586 def filevalidator(self,text):
588 Teste si text peut faire référence à un fichier ou non
589 Retourne 1 si valide, 0 sinon
591 return os.path.isfile(text),'Fichier introuvable : %s' %text
593 def catavalidator(self,text):
595 Teste si text est un chemin d'accès valide à un catalogue
596 Retourne 1 si valide, 0 sinon
598 return os.path.isfile(text),"Catalogue introuvable : %s" %text
600 # --------------------------------------------------------------------------------
601 # Méthodes callbacks des boutons et de fin
602 # --------------------------------------------------------------------------------
604 def execute(self,txt):
606 Cette commande est activée à chaque clic sur un bouton.
607 Redirige l'action sur la bonne méthode en fonction du bouton activé
611 elif txt in ('OK','Annuler'):
613 elif txt == 'Modifier':
614 self.resultat = apply(self.command[1],(),{})
615 self.fenetre.destroy()
617 print "Nom de bouton inconnu"
622 Commande qui termine le panneau et sauvegarde les nouvelles options
623 dans l'objet resultat (dictionnaire)
626 for item,widget in self.item_widgets.items():
629 valeur = widget.get()
630 if self.d_validateurs.has_key(type_var):
631 test = self.d_validateurs[type_var](valeur)
633 # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
634 # sans tuer la fenêtre bien sûr
635 widget.selection_range(0,END)
637 dico[nom_var] = valeur
638 self.fenetre.destroy()
642 self.fenetre.destroy()
646 """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
647 en passant les commandes à lancer suivant différents bindings """
648 def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre=''):
653 self.selection = None
654 self.liste_commandes = liste_commandes
655 self.liste_marques = liste_marques
663 self.make_label_titre()
664 self.make_entry_filtre()
667 self.entry.component('entry').focus()
671 def make_label_titre(self):
672 """ Crée le label correspondant au titre """
673 if self.titre == '' : return
674 fonte_titre = fontes.standard_gras_souligne
675 self.label = Label(self.page,
678 self.label.pack(side='top',pady=2)
680 def make_entry_filtre(self):
681 """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
682 if self.filtre != 'oui' : return
683 self.entry = Pmw.EntryField(self.page,labelpos='w',
684 label_text="Filtre :",
685 command=self.entry_changed)
686 self.entry.pack(side='top',pady=2)
688 def make_text_box(self):
689 """ Crée la fenêtre texte dans laquelle sera affichée la liste """
690 self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
691 self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
692 self.MCscroll.pack(side='right',fill ='y',pady=2)
693 self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
694 self.MCbox.configure(yscrollcommand=self.MCscroll.set)
696 def affiche_liste(self):
697 """ Affiche la liste dans la fenêtre"""
699 self.MCbox.config(state=NORMAL)
700 self.MCbox.delete(1.0,END)
701 for objet in self.liste :
702 if type(objet) == types.InstanceType:
707 elif type(objet) in (types.StringType,types.IntType):
709 elif type(objet) == types.FloatType :
710 #mot = repr_float(objet)
712 elif type(objet) == types.TupleType :
724 label = Label(self.MCbox,
726 fg = 'black',bg = 'gray95',justify = 'left')
727 self.dico_labels[mot]=label
728 liste_labels.append(label)
729 self.MCbox.window_create(END,
732 self.MCbox.insert(END,'\n')
733 if self.active == 'oui':
734 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))
735 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))
736 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))
738 for marque in self.liste_marques:
740 self.markitem(liste_labels[marque])
744 self.MCbox.config(state=DISABLED)
745 self.selection = None
747 def chooseitem(self,mot,label,commande):
748 """ Active la méthode de choix passée en argument"""
751 except AsException,e:
753 showerror(raison.split('\n')[0],raison)
755 def selectitem(self,mot,label,commande) :
756 """ Met l'item sélectionné (représenté par son label) en surbrillance
757 et lance la commande associée au double-clic"""
758 if self.selection != None :
759 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
760 self.highlightitem(label)
761 self.selection = (mot,label,commande)
762 self.arg_selected = mot
765 def highlightitem(self,label) :
766 """ Met l'item représenté par son label en surbrillance """
767 label.configure(bg='#00008b',fg='white')
769 def markitem(self,label):
770 """ Met l'item (représenté par son label) en rouge """
771 label.configure(bg='gray95',fg='red')
773 def deselectitem(self,label,mot='',commande=None) :
774 """ Remet l'item (représenté par son label) en noir"""
775 label.configure(bg='gray95',fg='black')
776 self.arg_selected = ''
777 if commande != None : commande(mot)
779 def cherche_selected_item(self):
780 index=self.MCbox.index(self.selection[1])
781 lign,col=map(int,string.split(index,'.'))
784 def remove_selected_item(self):
785 index=self.MCbox.index(self.selection[1])
786 lign,col=map(int,string.split(index,'.'))
787 del self.liste[lign-1]
790 def entry_changed(self,event=None):
791 """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
792 de l'entry et frappe <Return>"""
793 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
794 filtre = self.entry.get()+"*"
795 FILTRE = string.upper(filtre)
796 for arg in self.liste :
797 if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
798 self.highlightitem(self.dico_labels[arg])
799 index = self.MCbox.index(self.dico_labels[arg])
800 self.MCbox.see(index)
801 self.arg_selected = arg
804 def get_liste_old(self):
807 # PN attention à la gestion des paramétres
808 # cela retourne H = 1 , et ni H, ni 1
810 # print val.__class__.__name__
813 for val in self.liste:
821 def put_liste(self,liste):
826 """ Cette classe permet d'afficher au lancement d'EFICAS le message
827 d'attente et la barre de progression"""
828 def __init__(self,master,message,barre ='oui'):
829 from Tools.foztools.foztools import Slider
830 fonte=fontes.standard12_gras
832 self.frame = Frame(self.master)
833 self.frame.pack(expand=1,fill='both')
834 self.mess = Label(self.frame,text=message,justify='center',
835 bd=2,relief='groove',font=fonte)
836 self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
837 self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
838 fillColor='#00008b',width=200,height=30,
839 background='white',labelColor='red')
841 self.progress.frame.pack(in_=self.frame,side='top')
844 self.progress.frame.after(1000,self.update)
846 def configure(self,**options):
847 if options.has_key('message'):
848 self.mess.configure(text=options['message'])
849 if options.has_key('barre'):
850 if options['barre'] == 'oui' :
851 self.progress.frame.pack(in_=self.frame,side='top')
852 elif options['barre'] == 'non' :
853 self.progress.frame.pack_forget()
854 self.master.update_idletasks()
860 def update(self,event=None):
861 """ Permet de faire avancer la barre de progression """
864 bar.value = bar.value+self.increment
866 self.master.after(100,self.update)
870 def configure_barre(self,nb):
871 """ Calcule l'incrément de progression de la barre en fonction
872 du nombre d'opérations à effectuer afin que le compteur
873 soit à 100% à la fin des opérations"""
874 self.increment = 100./nb
875 self.progress.update()
877 class Ask_Format_Fichier :
879 Cette classe permet de créer une fenêtre Toplevel dans laquelle
880 on propose le choix du format de fichier de commandes à ouvrir
882 def __init__(self,appli):
883 self.fenetre = Toplevel()
884 self.fenetre.configure(width = 250,height=150)
885 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
886 self.fenetre.title("Choix du format du fichier de commandes")
887 # définition des frames
888 self.frame_texte = Frame(self.fenetre)
889 self.frame_radioboutons = Frame(self.fenetre)
890 self.frame_bouton_ok = Frame(self.fenetre)
891 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
892 self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
893 self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
894 # définition de la zone texte et du scrollbar
895 zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
896 zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
897 # définition des radioboutons
898 Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
899 variable=appli.format_fichier,value='Aster').pack(anchor='n')
900 Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
901 variable=appli.format_fichier,value='Python').pack(anchor='n')
902 # création du bouton OK
903 Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
904 # centrage de la fenêtre
905 centerwindow(self.fenetre)
908 self.fenetre.destroy()
910 class BARRE_K2000(Toplevel):
911 def __init__(self,master=None,text = ""):
912 Toplevel.__init__(self,master,relief='groove')
913 self.master.iconify()
914 self.geometry("250x100+0+0")
915 self.protocol("WM_DELETE_WINDOW",self.quit)
916 # frame principale dans self (= Toplevel)
917 self.frame = Frame(self)
918 self.frame.place(relwidth=1,relheight=1)
919 # frame contenant le texte à afficher
920 self.frame_text = Frame(self.frame)
921 self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
922 # frame contenant le canvas de la barre
923 self.frame_canv = Frame(self.frame)
924 self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
925 # canvas dans lequel sera affichée la barre K2000
926 self.canvas = Canvas(self.frame_canv)
927 self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
928 # on affiche le texte et la barre
929 self.build_text(text)
931 #self.overrideredirect(1)
932 # on active la barre ...
933 self.master.after(1000,self.launch)
934 # on centre la fenêtre
938 def build_text(self,text):
940 Affichage de text dans frame_text
942 self.texte_var = StringVar()
943 self.texte_var.set(text)
944 Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
946 def build_batons(self):
948 Construit la suite de bâtons dans le canvas
954 for i in range(0,40):
955 id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
956 self.l_batons.append(id)
960 Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
964 self.master.deiconify()
967 self.black = self.black+1
968 l_bat = self.l_batons[0:self.black+1]
970 elif self.sens == 'G':
971 self.black = self.black-1
972 l_bat = self.l_batons[self.black:]
976 if num_color < 10 : color = 'black'
977 elif num_color > 90 : color = 'white'
978 else: color = 'gray'+`num_color`
979 self.canvas.itemconfigure(bat,fill=color)
981 if self.black == len(self.l_batons) :
983 if self.black == 0 and self.sens == 'G':self.sens = 'D'
984 self.after(80,self.launch)
986 def update_text(self,new_text):
988 Remplace le texte affiché par new_text
990 self.texte_var.set(new_text)
995 class ListeChoixParGroupes(ListeChoix) :
997 Cette classe est utilisée pour afficher une liste de commandes classées par
998 groupes. L'utilisateur peut réaliser des actions de selection
999 qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
1001 def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
1002 active ='oui',filtre='non',titre=''):
1003 self.parent = parent
1005 self.liste_groupes = liste_groupes
1006 self.dict_groupes = dict_groupes
1008 self.selection = None
1009 self.liste_commandes = liste_commandes
1010 self.liste_marques = liste_marques
1011 self.arg_selected=''
1012 self.active = active
1014 self.filtre = filtre
1017 def affiche_liste(self):
1018 """ Affiche la liste dans la fenêtre"""
1020 self.MCbox.config(state=NORMAL)
1021 self.MCbox.delete(1.0,END)
1022 for grp in self.liste_groupes:
1023 # On itère sur les groupes
1024 if grp == "CACHE":continue
1025 liste_commandes=self.dict_groupes[grp]
1026 text="GROUPE<<<<<<<< "+grp+" "
1027 text=text+">"*max(0,30-len(text))
1028 label = Label(self.MCbox,
1030 fg = 'black',bg = 'gray95',justify = 'left')
1031 # On stocke la relation entre le nom de la commande et le label
1032 self.dico_labels[grp]=label
1033 liste_labels.append(label)
1034 self.MCbox.window_create(END,
1037 self.MCbox.insert(END,'\n')
1038 for cmd in liste_commandes:
1039 label = Label(self.MCbox,
1041 fg = 'black',bg = 'gray95',justify = 'left')
1042 # On stocke la relation entre le nom de la commande et le label
1043 self.dico_labels[cmd]=label
1044 self.MCbox.window_create(END,
1047 self.MCbox.insert(END,'\n')
1048 if self.active == 'oui':
1049 label.bind(self.liste_commandes[0][0],
1050 lambda e,s=self,c=self.liste_commandes[0][1],x=cmd,l=label : s.selectitem(x,l,c))
1051 label.bind(self.liste_commandes[1][0],
1052 lambda e,s=self,c=self.liste_commandes[1][1],x=cmd,l=label : s.deselectitem(l,x,c))
1053 label.bind(self.liste_commandes[2][0],
1054 lambda e,s=self,c=self.liste_commandes[2][1],x=cmd,l=label : s.chooseitem(x,l,c))
1056 for marque in self.liste_marques:
1058 self.markitem(liste_labels[marque])
1062 self.MCbox.config(state=DISABLED)
1063 self.selection = None
1065 def entry_changed(self,event=None):
1067 Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1068 de l'entry et frappe <Return>
1070 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1071 filtre = self.entry.get()+"*"
1072 FILTRE = string.upper(filtre)
1074 # On cherche d'abord dans les noms de groupe
1075 # puis dans les noms de commande groupe par groupe
1077 for grp in self.liste_groupes:
1078 if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1079 index = self.MCbox.index(self.dico_labels[grp])
1080 self.MCbox.see(index)
1081 # On ne selectionne pas le groupe
1082 #self.arg_selected = grp
1083 # On a trouve un groupe on arrete la recherche
1086 for grp in self.liste_groupes:
1087 for cmd in self.dict_groupes[grp] :
1088 if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1089 self.highlightitem(self.dico_labels[cmd])
1090 index = self.MCbox.index(self.dico_labels[cmd])
1091 self.MCbox.see(index)
1092 self.arg_selected = cmd
1093 # On a trouve une commande on arrete la recherche