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.65,relwidth=1.)
424 self.label1 = Label(self.frame_boutons,text="surligner la")
425 self.label2 = Label(self.frame_boutons,text="ligne entière")
426 self.label1.place(relx=0.1,rely=0)
427 self.label2.place(relx=0.1,rely=0.5)
428 self.but_quit = Button(self.frame_boutons,text = "Fermer",command=self.quit)
429 self.but_save = Button(self.frame_boutons,text = "Choisir",command = self.Choisir)
430 self.but_save.place(relx=0.6,rely=0,relheight=1)
431 self.but_quit.place(relx=0.8,rely=0,relheight=1)
436 selection=self.zone_texte.selection_get()
438 showerror("Pas de donnée sélectionnée",
439 "Selectionner un parametre")
441 for param in selection.splitlines():
442 nomparam=param[0:param.find("=")-1]
444 l_param=l_param+nomparam+','
445 self.parent.entry.delete(0,Tkinter.END)
446 self.parent.entry.insert(0,l_param[0:-1])
447 self.parent.valid_valeur()
452 Cette classe permet de créer une boîte Dialog dans laquelle
453 on affiche un formulaire à remplir par l'utilisateur
455 def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
456 if items in ((),[]) : return
460 self.fen_pere = fen_pere
461 self.obj_pere = obj_pere
463 self.command = commande
467 self.init_validateurs()
470 self.init_items_formulaire()
471 self.fenetre.activate(geometry='centerscreenalways')
473 def init_validateurs(self):
475 Crée le dictionnaire des validateurs des objets reconnus par le formulaire
477 self.d_validateurs = {}
478 self.d_validateurs['rep'] = self.repvalidator
479 self.d_validateurs['file'] = self.filevalidator
480 self.d_validateurs['cata']= self.catavalidator
482 def init_fenetre(self):
484 Crée la fenêtre Dialog
486 if self.mode == 'query':
487 buttons=('Valider','Annuler')
488 defaultbutton = 'Valider'
489 elif self.mode == 'display':
491 buttons=(self.command[0],'OK')
496 self.fenetre = Pmw.Dialog(self.fen_pere,
498 defaultbutton = defaultbutton,
500 command = self.execute)
501 self.fenetre.withdraw()
503 def init_texte(self):
505 Crée le label qui affiche le texte à l'intérieur du panneau
507 fonte=fontes.standard
508 fr_texte = Frame(self.fenetre.interior(),height=60)
509 fr_texte.pack(side='top',fill='x',expand=1)
510 Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
512 def init_items_formulaire(self):
514 Crée et affiche les items dans la boîte de dialogue
518 self.item_widgets = {}
520 for item in self.items:
521 if len(item[0])>length_maxi : length_maxi = len(item[0])
522 window = self.fenetre.interior()
523 for item in self.items :
524 label,nature,nom_var,defaut = item
525 # création de la frame
526 fr_item = Frame(window,height=40,width=700)
527 fr_item.pack(side='top',fill='x',expand=1)
529 Label(fr_item,text = label).place(relx=0.05,rely=0.4)
530 if nature in ('rep','file','cata'):
531 # création de l'entry
532 e_item = Entry(fr_item)
533 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
534 self.widgets.append(e_item)
535 self.item_widgets[item] = e_item
536 if defaut : e_item.insert(0,str(defaut))
537 elif nature == 'YesNo':
538 # création de la StringVar
540 setattr(self,'item_'+nom_var,var)
542 # création du radiobouton
543 rb1 = Radiobutton(fr_item,text='OUI',variable=var,value='OUI')
544 rb2 = Radiobutton(fr_item,text='NON',variable=var,value='NON')
545 rb1.place(relx=0.65,rely=0.5,anchor='center')
546 rb2.place(relx=0.80,rely=0.5,anchor='center')
547 self.widgets.append((rb1,rb2))
548 self.item_widgets[item] = var
549 # détermination de la méthode à appliquer sur les boutons
550 if self.mode == 'query':
551 function = self.active
552 elif self.mode == 'display':
553 function = self.inactive
556 # on applique la méthode sur les boutons (activation ou désactivation)
557 for widget in self.widgets :
558 if type(widget) == types.TupleType:
560 apply(function,(widg,),{})
562 apply(function,(widget,),{})
564 def active(self,widget):
566 Active le widget passé en argument
568 widget.configure(state='normal',bg='white')
570 def inactive(self,widget):
572 Inactive le widget passé en argument
574 if not isinstance(widget,Radiobutton) :
575 widget.configure(state='disabled',bg='gray95')
577 widget.configure(state='disabled')
579 # --------------------------------------------------------------------------------
580 # Validateurs des noms de répertoire, de fichiers et de catalogues
581 # -------------------------------------------------------------------------------
583 def repvalidator(self,text):
585 Teste si text peut faire référence à un répertoire ou non
586 Retourne 1 si valide, 0 sinon
588 return os.path.isdir(text),'Répertoire introuvable : %s' %text
590 def filevalidator(self,text):
592 Teste si text peut faire référence à un fichier ou non
593 Retourne 1 si valide, 0 sinon
595 return os.path.isfile(text),'Fichier introuvable : %s' %text
597 def catavalidator(self,text):
599 Teste si text est un chemin d'accès valide à un catalogue
600 Retourne 1 si valide, 0 sinon
602 return os.path.isfile(text),"Catalogue introuvable : %s" %text
604 # --------------------------------------------------------------------------------
605 # Méthodes callbacks des boutons et de fin
606 # --------------------------------------------------------------------------------
608 def execute(self,txt):
610 Cette commande est activée à chaque clic sur un bouton.
611 Redirige l'action sur la bonne méthode en fonction du bouton activé
615 elif txt in ('OK','Annuler'):
617 elif txt == 'Modifier':
618 self.resultat = apply(self.command[1],(),{})
619 self.fenetre.destroy()
621 print "Nom de bouton inconnu"
626 Commande qui termine le panneau et sauvegarde les nouvelles options
627 dans l'objet resultat (dictionnaire)
630 for item,widget in self.item_widgets.items():
633 valeur = widget.get()
634 if self.d_validateurs.has_key(type_var):
635 test = self.d_validateurs[type_var](valeur)
637 # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
638 # sans tuer la fenêtre bien sûr
639 widget.selection_range(0,END)
641 dico[nom_var] = valeur
642 self.fenetre.destroy()
646 self.fenetre.destroy()
650 """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
651 en passant les commandes à lancer suivant différents bindings """
652 def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre=''):
657 self.selection = None
658 self.liste_commandes = liste_commandes
659 self.liste_marques = liste_marques
667 self.make_label_titre()
668 self.make_entry_filtre()
671 self.entry.component('entry').focus()
675 def make_label_titre(self):
676 """ Crée le label correspondant au titre """
677 if self.titre == '' : return
678 fonte_titre = fontes.standard_gras_souligne
679 self.label = Label(self.page,
682 self.label.pack(side='top',pady=2)
684 def make_entry_filtre(self):
685 """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
686 if self.filtre != 'oui' : return
687 self.entry = Pmw.EntryField(self.page,labelpos='w',
688 label_text="Filtre :",
689 command=self.entry_changed)
690 self.entry.pack(side='top',pady=2)
692 def make_text_box(self):
693 """ Crée la fenêtre texte dans laquelle sera affichée la liste """
694 self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
695 self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
696 self.MCscroll.pack(side='right',fill ='y',pady=2)
697 self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
698 self.MCbox.configure(yscrollcommand=self.MCscroll.set)
700 def affiche_liste(self):
701 """ Affiche la liste dans la fenêtre"""
703 self.MCbox.config(state=NORMAL)
704 self.MCbox.delete(1.0,END)
705 for objet in self.liste :
706 if type(objet) == types.InstanceType:
711 elif type(objet) in (types.StringType,types.IntType):
713 elif type(objet) == types.FloatType :
714 #mot = repr_float(objet)
716 elif type(objet) == types.TupleType :
728 label = Label(self.MCbox,
730 fg = 'black',bg = 'gray95',justify = 'left')
731 self.dico_labels[mot]=label
732 liste_labels.append(label)
733 self.MCbox.window_create(END,
736 self.MCbox.insert(END,'\n')
737 if self.active == 'oui':
738 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))
739 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))
740 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))
742 for marque in self.liste_marques:
744 self.markitem(liste_labels[marque])
748 self.MCbox.config(state=DISABLED)
749 self.selection = None
751 def clear_marque(self):
753 self.dico_labels[self.arg_selected].configure(bg='gray95',fg='black')
754 self.arg_selected = ''
758 def surligne(self,marque):
760 self.highlightitem(self.dico_labels[marque])
761 self.arg_selected = marque
765 def chooseitem(self,mot,label,commande):
766 """ Active la méthode de choix passée en argument"""
769 except AsException,e:
771 showerror(raison.split('\n')[0],raison)
773 def selectitem(self,mot,label,commande) :
774 """ Met l'item sélectionné (représenté par son label) en surbrillance
775 et lance la commande associée au double-clic"""
777 if self.selection != None :
778 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
779 self.highlightitem(label)
780 self.selection = (mot,label,commande)
781 self.arg_selected = mot
784 def highlightitem(self,label) :
785 """ Met l'item représenté par son label en surbrillance """
786 label.configure(bg='#00008b',fg='white')
788 def markitem(self,label):
789 """ Met l'item (représenté par son label) en rouge """
790 label.configure(bg='gray95',fg='red')
792 def deselectitem(self,label,mot='',commande=None) :
793 """ Remet l'item (représenté par son label) en noir"""
794 label.configure(bg='gray95',fg='black')
795 self.arg_selected = ''
796 if commande != None : commande(mot)
798 def cherche_selected_item(self):
799 index=self.MCbox.index(self.selection[1])
800 lign,col=map(int,string.split(index,'.'))
803 def remove_selected_item(self):
804 index=self.MCbox.index(self.selection[1])
805 lign,col=map(int,string.split(index,'.'))
806 del self.liste[lign-1]
809 def entry_changed(self,event=None):
810 """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
811 de l'entry et frappe <Return>"""
812 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
813 filtre = self.entry.get()+"*"
814 FILTRE = string.upper(filtre)
815 for arg in self.liste :
816 if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
817 self.highlightitem(self.dico_labels[arg])
818 index = self.MCbox.index(self.dico_labels[arg])
819 self.MCbox.see(index)
820 self.arg_selected = arg
823 def get_liste_old(self):
826 # PN attention à la gestion des paramétres
827 # cela retourne H = 1 , et ni H, ni 1
829 # print val.__class__.__name__
832 for val in self.liste:
840 def put_liste(self,liste):
845 """ Cette classe permet d'afficher au lancement d'EFICAS le message
846 d'attente et la barre de progression"""
847 def __init__(self,master,message,barre ='oui'):
848 from Tools.foztools.foztools import Slider
849 fonte=fontes.standard12_gras
851 self.frame = Frame(self.master)
852 self.frame.pack(expand=1,fill='both')
853 self.mess = Label(self.frame,text=message,justify='center',
854 bd=2,relief='groove',font=fonte)
855 self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
856 self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
857 fillColor='#00008b',width=200,height=30,
858 background='white',labelColor='red')
860 self.progress.frame.pack(in_=self.frame,side='top')
863 self.progress.frame.after(1000,self.update)
865 def configure(self,**options):
866 if options.has_key('message'):
867 self.mess.configure(text=options['message'])
868 if options.has_key('barre'):
869 if options['barre'] == 'oui' :
870 self.progress.frame.pack(in_=self.frame,side='top')
871 elif options['barre'] == 'non' :
872 self.progress.frame.pack_forget()
873 self.master.update_idletasks()
879 def update(self,event=None):
880 """ Permet de faire avancer la barre de progression """
883 bar.value = bar.value+self.increment
885 self.master.after(100,self.update)
889 def configure_barre(self,nb):
890 """ Calcule l'incrément de progression de la barre en fonction
891 du nombre d'opérations à effectuer afin que le compteur
892 soit à 100% à la fin des opérations"""
893 self.increment = 100./nb
894 self.progress.update()
896 class Ask_Format_Fichier :
898 Cette classe permet de créer une fenêtre Toplevel dans laquelle
899 on propose le choix du format de fichier de commandes à ouvrir
901 def __init__(self,appli):
902 self.fenetre = Toplevel()
903 self.fenetre.configure(width = 250,height=150)
904 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
905 self.fenetre.title("Choix du format du fichier de commandes")
906 # définition des frames
907 self.frame_texte = Frame(self.fenetre)
908 self.frame_radioboutons = Frame(self.fenetre)
909 self.frame_bouton_ok = Frame(self.fenetre)
910 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
911 self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
912 self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
913 # définition de la zone texte et du scrollbar
914 zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
915 zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
916 # définition des radioboutons
917 Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
918 variable=appli.format_fichier,value='Aster').pack(anchor='n')
919 Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
920 variable=appli.format_fichier,value='Python').pack(anchor='n')
921 # création du bouton OK
922 Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
923 # centrage de la fenêtre
924 centerwindow(self.fenetre)
927 self.fenetre.destroy()
929 class BARRE_K2000(Toplevel):
930 def __init__(self,master=None,text = ""):
931 Toplevel.__init__(self,master,relief='groove')
932 self.master.iconify()
933 self.geometry("250x100+0+0")
934 self.protocol("WM_DELETE_WINDOW",self.quit)
935 # frame principale dans self (= Toplevel)
936 self.frame = Frame(self)
937 self.frame.place(relwidth=1,relheight=1)
938 # frame contenant le texte à afficher
939 self.frame_text = Frame(self.frame)
940 self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
941 # frame contenant le canvas de la barre
942 self.frame_canv = Frame(self.frame)
943 self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
944 # canvas dans lequel sera affichée la barre K2000
945 self.canvas = Canvas(self.frame_canv)
946 self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
947 # on affiche le texte et la barre
948 self.build_text(text)
950 #self.overrideredirect(1)
951 # on active la barre ...
952 self.master.after(1000,self.launch)
953 # on centre la fenêtre
957 def build_text(self,text):
959 Affichage de text dans frame_text
961 self.texte_var = StringVar()
962 self.texte_var.set(text)
963 Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
965 def build_batons(self):
967 Construit la suite de bâtons dans le canvas
973 for i in range(0,40):
974 id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
975 self.l_batons.append(id)
979 Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
983 self.master.deiconify()
986 self.black = self.black+1
987 l_bat = self.l_batons[0:self.black+1]
989 elif self.sens == 'G':
990 self.black = self.black-1
991 l_bat = self.l_batons[self.black:]
995 if num_color < 10 : color = 'black'
996 elif num_color > 90 : color = 'white'
997 else: color = 'gray'+`num_color`
998 self.canvas.itemconfigure(bat,fill=color)
1000 if self.black == len(self.l_batons) :
1002 if self.black == 0 and self.sens == 'G':self.sens = 'D'
1003 self.after(80,self.launch)
1005 def update_text(self,new_text):
1007 Remplace le texte affiché par new_text
1009 self.texte_var.set(new_text)
1014 class ListeChoixParGroupes(ListeChoix) :
1016 Cette classe est utilisée pour afficher une liste de commandes classées par
1017 groupes. L'utilisateur peut réaliser des actions de selection
1018 qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
1020 def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
1021 active ='oui',filtre='non',titre=''):
1022 self.parent = parent
1024 self.liste_groupes = liste_groupes
1025 self.dict_groupes = dict_groupes
1027 self.selection = None
1028 self.liste_commandes = liste_commandes
1029 self.liste_marques = liste_marques
1030 self.arg_selected=''
1031 self.active = active
1033 self.filtre = filtre
1036 def affiche_liste(self):
1037 """ Affiche la liste dans la fenêtre"""
1039 self.MCbox.config(state=NORMAL)
1040 self.MCbox.delete(1.0,END)
1041 for grp in self.liste_groupes:
1042 # On itère sur les groupes
1043 if grp == "CACHE":continue
1044 liste_commandes=self.dict_groupes[grp]
1045 text="GROUPE<<<<<<<< "+grp+" "
1046 text=text+">"*max(0,30-len(text))
1047 label = Label(self.MCbox,
1049 fg = 'black',bg = 'gray95',justify = 'left')
1050 # On stocke la relation entre le nom de la commande et le label
1051 self.dico_labels[grp]=label
1052 liste_labels.append(label)
1053 self.MCbox.window_create(END,
1056 self.MCbox.insert(END,'\n')
1057 for cmd in liste_commandes:
1058 label = Label(self.MCbox,
1060 fg = 'black',bg = 'gray95',justify = 'left')
1061 # On stocke la relation entre le nom de la commande et le label
1062 self.dico_labels[cmd]=label
1063 self.MCbox.window_create(END,
1066 self.MCbox.insert(END,'\n')
1067 if self.active == 'oui':
1068 label.bind(self.liste_commandes[0][0],
1069 lambda e,s=self,c=self.liste_commandes[0][1],x=cmd,l=label : s.selectitem(x,l,c))
1070 label.bind(self.liste_commandes[1][0],
1071 lambda e,s=self,c=self.liste_commandes[1][1],x=cmd,l=label : s.deselectitem(l,x,c))
1072 label.bind(self.liste_commandes[2][0],
1073 lambda e,s=self,c=self.liste_commandes[2][1],x=cmd,l=label : s.chooseitem(x,l,c))
1075 for marque in self.liste_marques:
1077 self.markitem(liste_labels[marque])
1081 self.MCbox.config(state=DISABLED)
1082 self.selection = None
1084 def entry_changed(self,event=None):
1086 Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1087 de l'entry et frappe <Return>
1089 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1090 filtre = self.entry.get()+"*"
1091 FILTRE = string.upper(filtre)
1093 # On cherche d'abord dans les noms de groupe
1094 # puis dans les noms de commande groupe par groupe
1096 for grp in self.liste_groupes:
1097 if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1098 index = self.MCbox.index(self.dico_labels[grp])
1099 self.MCbox.see(index)
1100 # On ne selectionne pas le groupe
1101 #self.arg_selected = grp
1102 # On a trouve un groupe on arrete la recherche
1105 for grp in self.liste_groupes:
1106 for cmd in self.dict_groupes[grp] :
1107 if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1108 self.highlightitem(self.dico_labels[cmd])
1109 index = self.MCbox.index(self.dico_labels[cmd])
1110 self.MCbox.see(index)
1111 self.arg_selected = cmd
1112 # On a trouve une commande on arrete la recherche