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.9)
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.zone_texte.bind("<Double-Button-3>", self.OnButton3doubleclick)
414 self.scroll_v = Scrollbar (self.frame_texte,command = self.zone_texte.yview)
415 self.scroll_v.pack(side='right',fill ='y')
416 self.zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
417 self.zone_texte.configure(yscrollcommand=self.scroll_v.set)
419 self.affiche_texte(self.texte)
420 self.zone_texte.config(state="disabled")
422 def OnButton3doubleclick(self,event):
424 selection=self.zone_texte.selection_get()
426 showerror("Pas de donnée sélectionnée",
427 "Selectionner un parametre")
429 for param in selection.splitlines():
430 nomparam=param[0:param.find("=")-1]
432 l_param=l_param+nomparam+','
433 self.parent.entry.delete(0,Tkinter.END)
434 self.parent.entry.insert(0,l_param[0:-1])
435 self.parent.valid_valeur()
440 Cette classe permet de créer une boîte Dialog dans laquelle
441 on affiche un formulaire à remplir par l'utilisateur
443 def __init__(self,fen_pere,obj_pere=None,titre="",texte="",items=(),mode='query',commande=None):
444 if items in ((),[]) : return
448 self.fen_pere = fen_pere
449 self.obj_pere = obj_pere
451 self.command = commande
455 self.init_validateurs()
458 self.init_items_formulaire()
459 self.fenetre.activate(geometry='centerscreenalways')
461 def init_validateurs(self):
463 Crée le dictionnaire des validateurs des objets reconnus par le formulaire
465 self.d_validateurs = {}
466 self.d_validateurs['rep'] = self.repvalidator
467 self.d_validateurs['file'] = self.filevalidator
468 self.d_validateurs['cata']= self.catavalidator
470 def init_fenetre(self):
472 Crée la fenêtre Dialog
474 if self.mode == 'query':
475 buttons=('Valider','Annuler')
476 defaultbutton = 'Valider'
477 elif self.mode == 'display':
479 buttons=(self.command[0],'OK')
484 self.fenetre = Pmw.Dialog(self.fen_pere,
486 defaultbutton = defaultbutton,
488 command = self.execute)
489 self.fenetre.withdraw()
491 def init_texte(self):
493 Crée le label qui affiche le texte à l'intérieur du panneau
495 fonte=fontes.standard
496 fr_texte = Frame(self.fenetre.interior(),height=60)
497 fr_texte.pack(side='top',fill='x',expand=1)
498 Label(fr_texte,text = self.texte, font=fonte).place(relx=0.5,rely=0.5,anchor='center')
500 def init_items_formulaire(self):
502 Crée et affiche les items dans la boîte de dialogue
506 self.item_widgets = {}
508 for item in self.items:
509 if len(item[0])>length_maxi : length_maxi = len(item[0])
510 window = self.fenetre.interior()
511 for item in self.items :
512 label,nature,nom_var,defaut = item
513 # création de la frame
514 fr_item = Frame(window,height=40,width=700)
515 fr_item.pack(side='top',fill='x',expand=1)
517 Label(fr_item,text = label).place(relx=0.05,rely=0.4)
518 if nature in ('rep','file','cata'):
519 # création de l'entry
520 e_item = Entry(fr_item)
521 e_item.place(relx=0.5,rely=0.4,relwidth=0.45)
522 self.widgets.append(e_item)
523 self.item_widgets[item] = e_item
524 if defaut : e_item.insert(0,str(defaut))
525 elif nature == 'YesNo':
526 # création de la StringVar
528 setattr(self,'item_'+nom_var,var)
530 # création du radiobouton
531 rb1 = Radiobutton(fr_item,text='OUI',variable=var,value='OUI')
532 rb2 = Radiobutton(fr_item,text='NON',variable=var,value='NON')
533 rb1.place(relx=0.65,rely=0.5,anchor='center')
534 rb2.place(relx=0.80,rely=0.5,anchor='center')
535 self.widgets.append((rb1,rb2))
536 self.item_widgets[item] = var
537 # détermination de la méthode à appliquer sur les boutons
538 if self.mode == 'query':
539 function = self.active
540 elif self.mode == 'display':
541 function = self.inactive
544 # on applique la méthode sur les boutons (activation ou désactivation)
545 for widget in self.widgets :
546 if type(widget) == types.TupleType:
548 apply(function,(widg,),{})
550 apply(function,(widget,),{})
552 def active(self,widget):
554 Active le widget passé en argument
556 widget.configure(state='normal',bg='white')
558 def inactive(self,widget):
560 Inactive le widget passé en argument
562 if not isinstance(widget,Radiobutton) :
563 widget.configure(state='disabled',bg='gray95')
565 widget.configure(state='disabled')
567 # --------------------------------------------------------------------------------
568 # Validateurs des noms de répertoire, de fichiers et de catalogues
569 # -------------------------------------------------------------------------------
571 def repvalidator(self,text):
573 Teste si text peut faire référence à un répertoire ou non
574 Retourne 1 si valide, 0 sinon
576 return os.path.isdir(text),'Répertoire introuvable : %s' %text
578 def filevalidator(self,text):
580 Teste si text peut faire référence à un fichier ou non
581 Retourne 1 si valide, 0 sinon
583 return os.path.isfile(text),'Fichier introuvable : %s' %text
585 def catavalidator(self,text):
587 Teste si text est un chemin d'accès valide à un catalogue
588 Retourne 1 si valide, 0 sinon
590 return os.path.isfile(text),"Catalogue introuvable : %s" %text
592 # --------------------------------------------------------------------------------
593 # Méthodes callbacks des boutons et de fin
594 # --------------------------------------------------------------------------------
596 def execute(self,txt):
598 Cette commande est activée à chaque clic sur un bouton.
599 Redirige l'action sur la bonne méthode en fonction du bouton activé
603 elif txt in ('OK','Annuler'):
605 elif txt == 'Modifier':
606 self.resultat = apply(self.command[1],(),{})
607 self.fenetre.destroy()
609 print "Nom de bouton inconnu"
614 Commande qui termine le panneau et sauvegarde les nouvelles options
615 dans l'objet resultat (dictionnaire)
618 for item,widget in self.item_widgets.items():
621 valeur = widget.get()
622 if self.d_validateurs.has_key(type_var):
623 test = self.d_validateurs[type_var](valeur)
625 # une entrée n'est pas valide --> on la met en surbrillance et on quitte la méthode
626 # sans tuer la fenêtre bien sûr
627 widget.selection_range(0,END)
629 dico[nom_var] = valeur
630 self.fenetre.destroy()
634 self.fenetre.destroy()
638 """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre
639 en passant les commandes à lancer suivant différents bindings """
640 def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre=''):
645 self.selection = None
646 self.liste_commandes = liste_commandes
647 self.liste_marques = liste_marques
655 self.make_label_titre()
656 self.make_entry_filtre()
659 self.entry.component('entry').focus()
663 def make_label_titre(self):
664 """ Crée le label correspondant au titre """
665 if self.titre == '' : return
666 fonte_titre = fontes.standard_gras_souligne
667 self.label = Label(self.page,
670 self.label.pack(side='top',pady=2)
672 def make_entry_filtre(self):
673 """ Crée l'entry permettant à l'utilisateur d'entrer un filtre de sélection dans la liste """
674 if self.filtre != 'oui' : return
675 self.entry = Pmw.EntryField(self.page,labelpos='w',
676 label_text="Filtre :",
677 command=self.entry_changed)
678 self.entry.pack(side='top',pady=2)
680 def make_text_box(self):
681 """ Crée la fenêtre texte dans laquelle sera affichée la liste """
682 self.MCbox = Text (self.page,relief='sunken',bg='gray95',bd=2)
683 self.MCscroll = Scrollbar (self.page,command = self.MCbox.yview)
684 self.MCscroll.pack(side='right',fill ='y',pady=2)
685 self.MCbox.pack(fill='y',expand=1,padx=2,pady=2)
686 self.MCbox.configure(yscrollcommand=self.MCscroll.set)
688 def affiche_liste(self):
689 """ Affiche la liste dans la fenêtre"""
691 self.MCbox.config(state=NORMAL)
692 self.MCbox.delete(1.0,END)
693 for objet in self.liste :
694 if type(objet) == types.InstanceType:
699 elif type(objet) in (types.StringType,types.IntType):
701 elif type(objet) == types.FloatType :
702 #mot = repr_float(objet)
704 elif type(objet) == types.TupleType :
716 label = Label(self.MCbox,
718 fg = 'black',bg = 'gray95',justify = 'left')
719 self.dico_labels[mot]=label
720 liste_labels.append(label)
721 self.MCbox.window_create(END,
724 self.MCbox.insert(END,'\n')
725 if self.active == 'oui':
726 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))
727 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))
728 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))
730 for marque in self.liste_marques:
732 self.markitem(liste_labels[marque])
736 self.MCbox.config(state=DISABLED)
737 self.selection = None
739 def chooseitem(self,mot,label,commande):
740 """ Active la méthode de choix passée en argument"""
743 except AsException,e:
745 showerror(raison.split('\n')[0],raison)
747 def selectitem(self,mot,label,commande) :
748 """ Met l'item sélectionné (représenté par son label) en surbrillance
749 et lance la commande associée au double-clic"""
750 if self.selection != None :
751 self.deselectitem(self.selection[1],self.selection[0],self.selection[2],)
752 self.highlightitem(label)
753 self.selection = (mot,label,commande)
754 self.arg_selected = mot
757 def highlightitem(self,label) :
758 """ Met l'item représenté par son label en surbrillance """
759 label.configure(bg='#00008b',fg='white')
761 def markitem(self,label):
762 """ Met l'item (représenté par son label) en rouge """
763 label.configure(bg='gray95',fg='red')
765 def deselectitem(self,label,mot='',commande=None) :
766 """ Remet l'item (représenté par son label) en noir"""
767 label.configure(bg='gray95',fg='black')
768 self.arg_selected = ''
769 if commande != None : commande(mot)
771 def cherche_selected_item(self):
772 index=self.MCbox.index(self.selection[1])
773 lign,col=map(int,string.split(index,'.'))
776 def remove_selected_item(self):
777 index=self.MCbox.index(self.selection[1])
778 lign,col=map(int,string.split(index,'.'))
779 del self.liste[lign-1]
782 def entry_changed(self,event=None):
783 """ Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
784 de l'entry et frappe <Return>"""
785 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
786 filtre = self.entry.get()+"*"
787 FILTRE = string.upper(filtre)
788 for arg in self.liste :
789 if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) :
790 self.highlightitem(self.dico_labels[arg])
791 index = self.MCbox.index(self.dico_labels[arg])
792 self.MCbox.see(index)
793 self.arg_selected = arg
796 def get_liste_old(self):
799 # PN attention à la gestion des paramétres
800 # cela retourne H = 1 , et ni H, ni 1
802 # print val.__class__.__name__
805 for val in self.liste:
813 def put_liste(self,liste):
818 """ Cette classe permet d'afficher au lancement d'EFICAS le message
819 d'attente et la barre de progression"""
820 def __init__(self,master,message,barre ='oui'):
821 from Tools.foztools.foztools import Slider
822 fonte=fontes.standard12_gras
824 self.frame = Frame(self.master)
825 self.frame.pack(expand=1,fill='both')
826 self.mess = Label(self.frame,text=message,justify='center',
827 bd=2,relief='groove',font=fonte)
828 self.mess.pack(in_ = self.frame,side='top',expand=1,fill='both')
829 self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',
830 fillColor='#00008b',width=200,height=30,
831 background='white',labelColor='red')
833 self.progress.frame.pack(in_=self.frame,side='top')
836 self.progress.frame.after(1000,self.update)
838 def configure(self,**options):
839 if options.has_key('message'):
840 self.mess.configure(text=options['message'])
841 if options.has_key('barre'):
842 if options['barre'] == 'oui' :
843 self.progress.frame.pack(in_=self.frame,side='top')
844 elif options['barre'] == 'non' :
845 self.progress.frame.pack_forget()
846 self.master.update_idletasks()
852 def update(self,event=None):
853 """ Permet de faire avancer la barre de progression """
856 bar.value = bar.value+self.increment
858 self.master.after(100,self.update)
862 def configure_barre(self,nb):
863 """ Calcule l'incrément de progression de la barre en fonction
864 du nombre d'opérations à effectuer afin que le compteur
865 soit à 100% à la fin des opérations"""
866 self.increment = 100./nb
867 self.progress.update()
869 class Ask_Format_Fichier :
871 Cette classe permet de créer une fenêtre Toplevel dans laquelle
872 on propose le choix du format de fichier de commandes à ouvrir
874 def __init__(self,appli):
875 self.fenetre = Toplevel()
876 self.fenetre.configure(width = 250,height=150)
877 self.fenetre.protocol("WM_DELETE_WINDOW", self.quit)
878 self.fenetre.title("Choix du format du fichier de commandes")
879 # définition des frames
880 self.frame_texte = Frame(self.fenetre)
881 self.frame_radioboutons = Frame(self.fenetre)
882 self.frame_bouton_ok = Frame(self.fenetre)
883 self.frame_texte.place(relx=0,rely=0,relwidth=1,relheight=0.3)
884 self.frame_radioboutons.place(relheight=0.5,relx=0,rely=0.3,relwidth=1.)
885 self.frame_bouton_ok.place(relheight=0.2,relx=0,rely=0.8,relwidth=1.)
886 # définition de la zone texte et du scrollbar
887 zone_texte = Label(self.frame_texte,text = "Format du fichier à ouvrir :")
888 zone_texte.pack(side='top',fill='both',expand=1,padx=5,pady=10)
889 # définition des radioboutons
890 Radiobutton(self.frame_radioboutons,text='Format Aster (Code_Aster --> v5)',
891 variable=appli.format_fichier,value='Aster').pack(anchor='n')
892 Radiobutton(self.frame_radioboutons,text='Format Python (Code_Aster v6-->)',
893 variable=appli.format_fichier,value='Python').pack(anchor='n')
894 # création du bouton OK
895 Button(self.frame_bouton_ok,text='OK',command=self.quit).pack(anchor='n')
896 # centrage de la fenêtre
897 centerwindow(self.fenetre)
900 self.fenetre.destroy()
902 class BARRE_K2000(Toplevel):
903 def __init__(self,master=None,text = ""):
904 Toplevel.__init__(self,master,relief='groove')
905 self.master.iconify()
906 self.geometry("250x100+0+0")
907 self.protocol("WM_DELETE_WINDOW",self.quit)
908 # frame principale dans self (= Toplevel)
909 self.frame = Frame(self)
910 self.frame.place(relwidth=1,relheight=1)
911 # frame contenant le texte à afficher
912 self.frame_text = Frame(self.frame)
913 self.frame_text.place(relwidth=1,relheight=0.75,rely=0)
914 # frame contenant le canvas de la barre
915 self.frame_canv = Frame(self.frame)
916 self.frame_canv.place(relwidth=1,relheight=0.25,rely=0.75)
917 # canvas dans lequel sera affichée la barre K2000
918 self.canvas = Canvas(self.frame_canv)
919 self.canvas.place(relx=0.5,rely=0.5,relheight=0.8,relwidth=0.8,anchor='center')
920 # on affiche le texte et la barre
921 self.build_text(text)
923 #self.overrideredirect(1)
924 # on active la barre ...
925 self.master.after(1000,self.launch)
926 # on centre la fenêtre
930 def build_text(self,text):
932 Affichage de text dans frame_text
934 self.texte_var = StringVar()
935 self.texte_var.set(text)
936 Label(self.frame_text,textvariable=self.texte_var).place(relx=0.5,rely=0.5,anchor='center')
938 def build_batons(self):
940 Construit la suite de bâtons dans le canvas
946 for i in range(0,40):
947 id = self.canvas.create_rectangle(i*5,0,(i+1)*5,20,fill='gray90',outline='')
948 self.l_batons.append(id)
952 Active la barre K2000 en affichant les bâtons avec des couleurs en dégradé
956 self.master.deiconify()
959 self.black = self.black+1
960 l_bat = self.l_batons[0:self.black+1]
962 elif self.sens == 'G':
963 self.black = self.black-1
964 l_bat = self.l_batons[self.black:]
968 if num_color < 10 : color = 'black'
969 elif num_color > 90 : color = 'white'
970 else: color = 'gray'+`num_color`
971 self.canvas.itemconfigure(bat,fill=color)
973 if self.black == len(self.l_batons) :
975 if self.black == 0 and self.sens == 'G':self.sens = 'D'
976 self.after(80,self.launch)
978 def update_text(self,new_text):
980 Remplace le texte affiché par new_text
982 self.texte_var.set(new_text)
987 class ListeChoixParGroupes(ListeChoix) :
989 Cette classe est utilisée pour afficher une liste de commandes classées par
990 groupes. L'utilisateur peut réaliser des actions de selection
991 qui déclenchent des actions spécifiées par les bindings contenus dans liste_commandes
993 def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[],
994 active ='oui',filtre='non',titre=''):
997 self.liste_groupes = liste_groupes
998 self.dict_groupes = dict_groupes
1000 self.selection = None
1001 self.liste_commandes = liste_commandes
1002 self.liste_marques = liste_marques
1003 self.arg_selected=''
1004 self.active = active
1006 self.filtre = filtre
1009 def affiche_liste(self):
1010 """ Affiche la liste dans la fenêtre"""
1012 self.MCbox.config(state=NORMAL)
1013 self.MCbox.delete(1.0,END)
1014 for grp in self.liste_groupes:
1015 # On itère sur les groupes
1016 if grp == "CACHE":continue
1017 liste_commandes=self.dict_groupes[grp]
1018 text="GROUPE<<<<<<<< "+grp+" "
1019 text=text+">"*max(0,30-len(text))
1020 label = Label(self.MCbox,
1022 fg = 'black',bg = 'gray95',justify = 'left')
1023 # On stocke la relation entre le nom de la commande et le label
1024 self.dico_labels[grp]=label
1025 liste_labels.append(label)
1026 self.MCbox.window_create(END,
1029 self.MCbox.insert(END,'\n')
1030 for cmd in liste_commandes:
1031 label = Label(self.MCbox,
1033 fg = 'black',bg = 'gray95',justify = 'left')
1034 # On stocke la relation entre le nom de la commande et le label
1035 self.dico_labels[cmd]=label
1036 self.MCbox.window_create(END,
1039 self.MCbox.insert(END,'\n')
1040 if self.active == 'oui':
1041 label.bind(self.liste_commandes[0][0],
1042 lambda e,s=self,c=self.liste_commandes[0][1],x=cmd,l=label : s.selectitem(x,l,c))
1043 label.bind(self.liste_commandes[1][0],
1044 lambda e,s=self,c=self.liste_commandes[1][1],x=cmd,l=label : s.deselectitem(l,x,c))
1045 label.bind(self.liste_commandes[2][0],
1046 lambda e,s=self,c=self.liste_commandes[2][1],x=cmd,l=label : s.chooseitem(x,l,c))
1048 for marque in self.liste_marques:
1050 self.markitem(liste_labels[marque])
1054 self.MCbox.config(state=DISABLED)
1055 self.selection = None
1057 def entry_changed(self,event=None):
1059 Cette méthode est invoquée chaque fois que l'utilisateur modifie le contenu
1060 de l'entry et frappe <Return>
1062 if self.arg_selected != '' : self.deselectitem(self.dico_labels[self.arg_selected])
1063 filtre = self.entry.get()+"*"
1064 FILTRE = string.upper(filtre)
1066 # On cherche d'abord dans les noms de groupe
1067 # puis dans les noms de commande groupe par groupe
1069 for grp in self.liste_groupes:
1070 if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) :
1071 index = self.MCbox.index(self.dico_labels[grp])
1072 self.MCbox.see(index)
1073 # On ne selectionne pas le groupe
1074 #self.arg_selected = grp
1075 # On a trouve un groupe on arrete la recherche
1078 for grp in self.liste_groupes:
1079 for cmd in self.dict_groupes[grp] :
1080 if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) :
1081 self.highlightitem(self.dico_labels[cmd])
1082 index = self.MCbox.index(self.dico_labels[cmd])
1083 self.MCbox.see(index)
1084 self.arg_selected = cmd
1085 # On a trouve une commande on arrete la recherche