Salome HOME
PN vielles macros
[tools/eficas.git] / Installation / install.py
1 # -*- coding: utf-8 -*-
2 SUCCES,ECHEC = 1,0\r
3 OUI,NON = 1,0\r
4 \r
5 ## constantes pour les tests de versions \r
6 \r
7 python_min = 20\r
8 tcl_min = 83\r
9 tk_min  = 83\r
10 pmw_min = 85\r
11 test = 0\r
12 \r
13 try:\r
14     import sys,string,re,types,traceback\r
15     import os,commands\r
16 except Exception,e:\r
17     print "Mauvaise installation de Python"\r
18     print str(e)\r
19 \r
20 REPERTOIRE = os.path.abspath(os.curdir)\r
21 \r
22 def strip_points(chaine):\r
23     """\r
24     Enlève les caractères autres que les chiffres des chaînes\r
25     """\r
26     x=""\r
27     for i in range(len(chaine)):\r
28         try:\r
29             dummy = float(chaine[i])\r
30             x=x+chaine[i]\r
31         except:\r
32             pass\r
33     return x\r
34 \r
35 class Test_Environnement :\r
36     def __init__(self):\r
37         self.l_errors = []\r
38 \r
39     def test_plate_forme(self):\r
40         """\r
41         Teste que la plate-forme est bien supportée\r
42         """\r
43         if os.name not in ('nt','posix'):\r
44             self.l_errors.append("La plate-forme %s n'est pas supportée" %os.name)\r
45             \r
46     def test_version_python(self):\r
47         """\r
48         Test de la version de python\r
49         """\r
50         version = sys.version\r
51         n = string.index(version,"(") - 1\r
52         vpyt = strip_points(version[0:n])[0:2]     ## recupere les 2 premiers caracteres\r
53         if int(vpyt)<python_min :\r
54             self.l_errors.append("La version %s de python n'est plus supportée" %version[0:n])\r
55 \r
56     def test_tcl_tk(self):\r
57         """\r
58         Test des versions de tcl et tk\r
59         """\r
60         try:\r
61             import Tkinter\r
62             vtcl = Tkinter.tkinter.TCL_VERSION\r
63             vtk  = Tkinter.tkinter.TK_VERSION\r
64             # version tcl\r
65             x = strip_points(vtcl)\r
66             if int(x)<tcl_min :\r
67                 self.l_errors.append("La version %s de tcl n'est plus supportée" %vtcl)\r
68             # version tk\r
69             x = strip_points(vtk)\r
70             if int(x)<tk_min :\r
71                 self.l_errors.append("La version %s de tk n'est plus supportée" %vtk)\r
72         except Exception,e:\r
73             self.l_errors.append("Tkinter n'est pas installé")\r
74             print str(e)\r
75 \r
76     def test_Pmw(self):\r
77         """\r
78         Test de la version de Pmw\r
79         """\r
80         try:\r
81             import Pmw\r
82             vpmw = Pmw._version\r
83             x = strip_points(vpmw)\r
84             if int(x)<pmw_min :\r
85                 self.l_errors.append("La version %s de Pmw n'est plus supportée" %vpmw)\r
86         except:\r
87             self.l_errors.append("Pmw n'est pas installé")\r
88 \r
89     def test(self):\r
90         """\r
91         Active les tests de version Python, versions Tcl/Tk et Pmw\r
92         """\r
93         self.test_plate_forme()\r
94         self.test_version_python()\r
95         self.test_tcl_tk()\r
96         self.test_Pmw()\r
97         if not len(self.l_errors):\r
98             print "Environnement Ok"\r
99             return 1\r
100         else :\r
101             print "Il manque des prérequis"\r
102             print "EFICAS ne peut pas être installé"\r
103             print "Erreurs : ",string.join(self.l_errors)\r
104             return 0\r
105 \r
106 class Slider:\r
107     def __init__(self, master=None, orientation="horizontal", min=0, max=100,\r
108                  width=100, height=25, autoLabel="true", appearance="sunken",\r
109                  fillColor="blue", background="black", labelColor="yellow",\r
110                  labelText="", labelFormat="%d%%", value=50, bd=2):\r
111         # preserve various values\r
112         self.master=master\r
113         self.orientation=orientation\r
114         self.min=min\r
115         self.max=max\r
116         self.width=width\r
117         self.height=height\r
118         self.autoLabel=autoLabel\r
119         self.fillColor=fillColor\r
120         self.labelColor=labelColor\r
121         self.background=background\r
122         self.labelText=labelText\r
123         self.labelFormat=labelFormat\r
124         self.value=value\r
125         self.frame=Tkinter.Frame(master, relief=appearance, bd=bd)\r
126         self.canvas=Tkinter.Canvas(self.frame, height=height, width=width, bd=0,\r
127                                    highlightthickness=0, background=background)\r
128         self.scale=self.canvas.create_rectangle(0, 0, width, height,\r
129                                                 fill=fillColor)\r
130         self.label=self.canvas.create_text(self.canvas.winfo_reqwidth() / 2,\r
131                                            height / 2, text=labelText,\r
132                                            anchor="c", fill=labelColor)\r
133         self.update()\r
134         self.canvas.pack(side='top', fill='x', expand='no')\r
135 \r
136     def update(self):\r
137         # Trim the values to be between min and max\r
138         value=self.value\r
139         if value > self.max:\r
140             value = self.max\r
141         if value < self.min:\r
142             value = self.min\r
143         # Preserve the new value\r
144         c=self.canvas\r
145         # Adjust the rectangle\r
146         if self.orientation == "horizontal":\r
147             c.coords(self.scale,0, 0,float(value) / self.max * self.width, self.height)\r
148         else:\r
149             c.coords(self.scale,0, self.height - (float(value) / self.max*self.height),self.width, self.height)\r
150         # Now update the colors\r
151         c.itemconfig(self.scale, fill=self.fillColor)\r
152         c.itemconfig(self.label, fill=self.labelColor)\r
153         # And update the label\r
154         if self.autoLabel=="true":\r
155             c.itemconfig(self.label, text=self.labelFormat % value)\r
156         else:\r
157             c.itemconfig(self.label, text=self.labelFormat % self.labelText)\r
158         c.update_idletasks()\r
159 try :\r
160     import Tkinter\r
161     import Pmw\r
162     from tkMessageBox import showinfo,askyesno,showerror,askretrycancel\r
163 except:\r
164     pass\r
165 \r
166 class SplashScreen(Tkinter.Toplevel):\r
167     """ Provides a splash screen. Usage:\r
168         Subclass and override 'CreateWidgets()'\r
169         In constructor of main window/application call\r
170         - S = SplashScreen(main=self)        (if caller is Toplevel)\r
171         - S = SplashScreen(main=self.master) (if caller is Frame)\r
172         - S.quit()  after you are done creating your widgets etc.\r
173     """\r
174     def __init__(self, master,**args):\r
175         Tkinter.Toplevel.__init__(self, master, relief='groove',borderwidth=5)\r
176         self.protocol("WM_DELETE_WINDOW",lambda x=0: x+x  )       # pour ne pas détruire la fenêtre en pleine copie de fichiers\r
177         self.main = master\r
178         if self.main != None :\r
179             self.main.withdraw()\r
180         self.frame = Tkinter.Frame(self)\r
181         self.frame.pack(expand=1,fill='both')\r
182         self.init(args)\r
183         self.geometry("300x200")\r
184         self.resizable(0,0)\r
185         self.CreateWidgets()\r
186 \r
187     def init(self,args={}):\r
188         self.text = Tkinter.StringVar()\r
189         self.text.set('')\r
190         self.icone = 'Editeur/icons/logo_edf.gif'\r
191         self.barre = 'non'\r
192         if args == {} : return\r
193         if args.has_key('text'):\r
194             self.text.set(args['text'])\r
195         if args.has_key('titre'):\r
196             self.title(args['titre'])\r
197         if args.has_key('code'):\r
198             self.code = args['code']\r
199         else:\r
200             self.code = 'inconnu'\r
201         if self.code == 'ASTER' :\r
202             self.icone = 'Editeur/icons/code_aster.gif'\r
203         \r
204     def CreateWidgets(self):\r
205         fic_image = os.path.join("./", self.icone)\r
206         if os.path.exists(fic_image):\r
207             self.catIcon = Tkinter.PhotoImage(file=os.path.join("./", self.icone))\r
208             Tkinter.Label(self.frame, image=self.catIcon).pack(side=Tkinter.TOP)\r
209         else:\r
210             Tkinter.Label(self.frame, text = "EFICAS pour Code_Aster").pack(side=Tkinter.TOP)\r
211         self.label = Tkinter.Label(self.frame, textvariable=self.text)\r
212         self.label.pack(side=Tkinter.TOP,expand=1,fill='both')\r
213         self.progress = Slider(self.frame,value=0,max=100,orientation='horizontal',\r
214                                fillColor='blue',width=200,height=30,\r
215                                background='white',labelColor='red')\r
216 \r
217     def update_barre(self,event=None):\r
218         """ Permet de faire avancer la barre de progression """\r
219         try:\r
220             self.progress.value = self.progress.value+self.increment\r
221             self.progress.update()\r
222             #self.after(100,self.update_barre)\r
223         except:\r
224             pass\r
225 \r
226     def configure_barre(self):\r
227         """ Calcule l'incrément de progression de la barre en fonction\r
228         du nombre d'opérations à effectuer afin que le compteur\r
229         soit à 100% à la fin des opérations"""\r
230         self.increment = 100./self.ratio\r
231         self.progress.update()\r
232 \r
233     def configure(self,**args):\r
234         if args.has_key('text'):\r
235             self.text.set(args['text'])\r
236         if args.has_key('titre'):\r
237             self.title(args['titre'])\r
238         if args.has_key('barre'):\r
239             old = self.barre\r
240             self.barre = args['barre']\r
241             if self.barre == 'oui' and old == 'non':\r
242                 self.progress.frame.pack(in_=self.frame,side='top')\r
243             elif self.barre == 'non' and old == 'oui':\r
244                 self.progress.frame.pack_forget()\r
245         if args.has_key('ratio'):\r
246             self.ratio = args['ratio']\r
247             self.configure_barre()\r
248         self.update()\r
249         \r
250     def quit(self):\r
251         self.progress = None\r
252         self.withdraw()\r
253         self.main.update()\r
254         self.main.deiconify()\r
255 \r
256 def centerwindow(window,parent = 'avec'):\r
257     if parent =='avec':\r
258         parent = window.winfo_parent()\r
259         if type(parent) == types.StringType:\r
260             try:\r
261                 parent = window._nametowidget(parent)\r
262             except:\r
263                 parent = window\r
264     # Find size of window.\r
265     window.update_idletasks()\r
266     width = window.winfo_width()\r
267     height = window.winfo_height()\r
268     if width == 1 and height == 1:\r
269         # If the window has not yet been displayed, its size is\r
270         # reported as 1x1, so use requested size.\r
271         width = window.winfo_reqwidth()\r
272         height = window.winfo_reqheight()\r
273     # Place in centre of screen:\r
274     if parent =='avec' :\r
275         x = (window.winfo_screenwidth() - width) / 2 - parent.winfo_vrootx()\r
276         y = (window.winfo_screenheight() - height) / 3 - parent.winfo_vrooty()\r
277     else:\r
278         x = (window.winfo_screenwidth() - width) / 2 \r
279         y = (window.winfo_screenheight() - height) / 3\r
280     if x < 0:\r
281         x = 0\r
282     if y < 0:\r
283         y = 0\r
284     window.geometry('+%d+%d' % (x, y))\r
285     \r
286 class config_item:\r
287     """\r
288     Classe utilisée pour représenter chaque option de configuration\r
289     """\r
290     def __init__(self, pere, nom):\r
291         self.nom = nom\r
292         self.pere = pere\r
293         self.entree_value = None\r
294         self.default = None\r
295         self.test = None\r
296         self.pere.register_item(self)\r
297 \r
298     def get_valeur(self):\r
299         return os.path.abspath(self.entree.get())\r
300     \r
301     def set_entree(self,entree):\r
302         self.entree = entree\r
303         self.pere.register_entree(entree)\r
304 \r
305 class Config(Tkinter.Toplevel):\r
306     """\r
307     Classe principale : une instance de Config est utilisée pour\r
308     créer l'interface. Toutes les actions (création de répertoire, copie\r
309     de fichiers ...) sont réalisées par des méthodes de Config ou de ses\r
310     composants\r
311     """\r
312     pat_rep = re.compile(r'^(rep_)([\w_]*)')             # expression réguliere pour reconnaitre les\r
313                                                          # les options qui désignent des répertoires\r
314     def __init__(self, parent):\r
315         self.master = parent\r
316         Tkinter.Toplevel.__init__(self,None)\r
317         parent.withdraw()\r
318         self.title("Installation d'EFICAS")\r
319         self.geometry("500x320+0+0")\r
320         centerwindow(self)\r
321         self.install_running = 0\r
322         #évite que la fenêtre puisse être détruite en pleine copie de fichiers\r
323         self.protocol("WM_DELETE_WINDOW",self.exit  )\r
324         # création des frames\r
325         self.frame_gen = Tkinter.Frame(self,bd=1,relief='groove')\r
326         self.frame_gen.place(relx=0,rely=0,relwidth=1,relheight=0.9 )\r
327         self.frame_but = Tkinter.Frame(self,bd=1,relief='groove')\r
328         self.frame_but.place(relx=0,rely=0.9 ,relheight=0.1 ,relwidth=1)\r
329         # création des items de configuration\r
330         self.make_items_config()\r
331         # remplissage de la frame générale\r
332         self.make_frame_gen()\r
333         # remplissage de la frame boutons\r
334         self.make_frame_but()\r
335         # création boîtes de dialogue\r
336         self.init_complementaire()\r
337         # init système\r
338         self.init_systeme()\r
339         \r
340     def make_items_config(self):\r
341         """\r
342         Création des objets Config_item\r
343         """\r
344         self.items = []\r
345         self.items_a_creer = []\r
346         self.liste_rep_crees = []\r
347         self.entrees = []\r
348         # designation, texte d'invite , option par defaut(unix), option par defaut(windows), flag obligatoire/facultatif\r
349         self.l_tx_items = (('rep_install'   ,\r
350                             "Répertoire d'installation :",\r
351                             '',\r
352                             '',\r
353                             'o'),\r
354                            ('rep_travail'   ,\r
355                             'Répertoire de travail :',\r
356                             'tmp',\r
357                             'tmp',\r
358                             'f'),\r
359                            ('rep_mat'       ,\r
360                             'Répertoire matériaux :',\r
361                             None,\r
362                             None,\r
363                             'f'),\r
364                            ('rep_docaster'  ,\r
365                             "Chemin d'accès à la doc Aster :" ,\r
366                             None,\r
367                             None,\r
368                             'f'\r
369                             ),\r
370                            ('acrobat'       ,\r
371                             'Exécutable Acrobat Reader :',\r
372                             '/usr/bin/acroread',\r
373                             'acrobat.exe',\r
374                             'o')\r
375                            )\r
376 \r
377         for item in self.l_tx_items:\r
378             nom_item = item[0]\r
379             setattr(self,nom_item,config_item(self,nom_item))\r
380 \r
381     def make_frame_gen(self):\r
382         """\r
383         Création des zones de saisie des paramètres généraux\r
384         """\r
385         # Création du label titre de la frame\r
386         self.information = Tkinter.Label(self.frame_gen,text="CONFIGURATION D'EFICAS")\r
387         self.information.pack(side="top",pady=10)\r
388         # création des widgets de saisie des items\r
389         for txt in self.l_tx_items:\r
390             nom_item = txt[0]\r
391             txt_item = txt[1]\r
392             if os.name == 'nt':\r
393                 default_value = txt[3]\r
394             else:\r
395                 default_value = txt[2]\r
396             item = getattr(self,nom_item)\r
397             wdg_item = Pmw.EntryField(self.frame_gen,\r
398                                       labelpos = 'w',\r
399                                       label_text = txt_item,\r
400                                       command = lambda s=self,i=item : s.select_next_entry(i.entree))\r
401             item.default_value = default_value\r
402             item.statut = txt[4]\r
403             item.set_entree(wdg_item)\r
404         # on affiche les entrées\r
405         for entree in self.entrees:\r
406             entree.pack(fill='x', expand=1, padx=10, pady=5)\r
407         Pmw.alignlabels(self.entrees)\r
408         self.entrees[0].focus_set()\r
409         #self.rep_cata_dev.entree.configure(entry_state = 'disabled')\r
410         self.display_defaults()\r
411         \r
412     def make_frame_but(self):\r
413         """\r
414         Création des boutons de commande Installer et Annuler\r
415         """\r
416         self.validButton    = Tkinter.Button(self.frame_but, text = 'Installer', command = self.run_install)\r
417         self.exitButton     = Tkinter.Button(self.frame_but,\r
418                                              text = 'Annuler',\r
419                                              command = lambda s=self : s.exit(annule='oui'))\r
420         self.exitButton.place(relx=0.35,rely=0.5,anchor='center')\r
421         self.validButton.place(relx=0.65,rely=0.5,anchor='center')\r
422 \r
423     def init_complementaire(self):\r
424         """\r
425         Création de widgets complémentaires (boîtes de dialogue ...)\r
426         """\r
427         self.erreur_dialog = Pmw.Dialog(self,\r
428                                         buttons = ('Modifier', 'Annuler'),\r
429                                         defaultbutton = 'Modifier',\r
430                                         title = 'Erreur',\r
431                                         command = self.erreur_exec)\r
432         self.erreur_dialog.withdraw()\r
433         self.fatale_dialog = Pmw.Dialog(self,\r
434                                         buttons = ('Annuler',),\r
435                                         title = 'Fatal',\r
436                                         command = self.fatale_exec)\r
437         self.fatale_dialog.withdraw()\r
438         self.info_dialog = Pmw.Dialog(self,\r
439                                         buttons = ('Ok',),\r
440                                         title = 'Attention')\r
441         self.info_dialog.configure(command=self.info_dialog.withdraw())\r
442         self.info_dialog.withdraw()\r
443         self.attente = SplashScreen(None,code="ASTER")\r
444         self.attente.withdraw()\r
445 \r
446     def init_systeme(self):\r
447         """\r
448         Détermine les commandes à exécuter en fonction de l'OS\r
449         """\r
450         self.d_commandes = {}\r
451         if os.name == 'nt':\r
452             self.d_commandes['decompress'] = "unzip.exe "\r
453             self.d_commandes['copy'] = "copy "\r
454             self.d_commandes['delete'] = "del "\r
455         elif os.name == 'posix':\r
456             self.d_commandes['decompress'] = "gunzip "\r
457             self.d_commandes['copy'] = "cp "\r
458             self.d_commandes['delete'] = "rm "\r
459 \r
460     def run_install(self):\r
461         """\r
462         Lance l'installation proprement dite d'EFICAS\r
463         """\r
464         self.install_running = 1\r
465         self.afficher_splash()\r
466         self.deactivate_entries()           #  Les entrees et les boutons sont desactivees\r
467         self.deactivate_buttons()           #  pendant les operations d'installation\r
468         #self.decompress_archive()\r
469         #if not os.path.exists(os.path.join(REPERTOIRE,'Eficas')):\r
470         #    self.afficher_fatale("Il manque des fichiers d'EFICAS")\r
471         #    self.install_running = 0\r
472         #    return\r
473         self.nb_fichiers = self.compte_fichiers(REPERTOIRE)\r
474         if self.nb_fichiers == 0:\r
475             self.afficher_fatale("Il manque des fichiers d'EFICAS")\r
476             self.install_running = 0\r
477             return\r
478         # essaie de creer les repertoires.\r
479         try:\r
480             if self.make_dirs() == ECHEC :                             \r
481                 self.activate_entries()                               \r
482                 self.activate_buttons()                               \r
483                 self.install_running = 0\r
484                 return\r
485         except:\r
486             self.install_running = 0\r
487             self.afficher_fatale("Impossible de créer certains répertoires")\r
488             \r
489         # affiche la fenêtre avec la barre de progression\r
490         self.afficher_copie_fichiers()          \r
491         # essaie de copier les fichiers d'EFICAS\r
492         try:\r
493             if  self.move_files() == ECHEC:                           \r
494                 self.afficher_echec("Impossible de copier les fichiers d'EFICAS")\r
495                 self.activate_buttons()\r
496                 self.install_running = 0\r
497                 return\r
498         except :\r
499             traceback.print_exc()\r
500             self.install_running = 0\r
501             self.afficher_fatale("Impossible de copier certains fichiers")\r
502 \r
503         #self.rm_temp_dirs()                     # efface les répertoires temporaires\r
504         try:\r
505             self.creer_fic_conf()                   # crée le fichier eficas.conf\r
506         except:\r
507             afficher_info("Impossible de créer le fichier de configuration\n Il est possible de le faire a la main")\r
508 #        self.install_running = 0\r
509         self.afficher_install_terminee()        # A ce stade tout est fait et il ne reste plus qu'à attendre\r
510                                                 # un clic de souris pour sortir\r
511 \r
512     def display_defaults(self):\r
513         """\r
514         Affiche les valeurs par défaut dans les zones de saisie\r
515         """\r
516         # racine indique la racine de l'arborescence\r
517         if os.name == 'nt':\r
518             racine = 'C:\\'\r
519         else:\r
520             racine = os.environ['HOME']\r
521         # remplit les zones de saisie avec les options par défaut\r
522         for item in self.items:\r
523             if item.default_value == None : continue\r
524             item.default_value = os.path.join(racine,item.default_value)\r
525             item.entree.insert(0,item.default_value)\r
526 \r
527     def register_item(self,item):\r
528         """\r
529         Enregistre l'item dans la liste des items et éventuellement\r
530         dans la liste des items à créer (répertoires)\r
531         """\r
532         self.items.append(item)\r
533         if self.pat_rep.match(item.nom) :\r
534             self.items_a_creer.append(item)\r
535 \r
536     def register_entree(self,entree):\r
537         """\r
538         Enregistre la zone de saisie dans la liste des zones\r
539         """\r
540         self.entrees.append(entree)\r
541 \r
542     def select_next_entry(self,entree):\r
543         """\r
544         Place le focus dans l'entry suivant celle passée en argument\r
545         """\r
546         index = self.entrees.index(entree)+1\r
547         if index != len(self.entrees):\r
548             self.entrees[index].component('entry').focus()\r
549 \r
550     def activate_entries(self):\r
551         """\r
552         Active les entrées. Les zones de saisie deviennent éditables.\r
553         """\r
554         for item in self.entrees:\r
555             item.configure(entry_state='normal')\r
556 \r
557     def deactivate_entries(self):\r
558         """\r
559         Désactive les entrées. Les zones ne sont plus éditables.\r
560         """\r
561         for item in self.entrees:                                #  Les entrees sont desactivees\r
562             item.configure(entry_state='disabled')               #  pendant les operations d'installation\r
563 \r
564     def activate_buttons(self):\r
565         """\r
566         active les boutons valider et annuler\r
567         """\r
568         self.validButton.configure(state = 'normal')\r
569         self.exitButton.configure(state = 'normal')\r
570 \r
571     def deactivate_buttons(self):\r
572         """\r
573         désactive des boutons valider de annuler\r
574         """\r
575         self.validButton.configure(state = 'disabled')\r
576         self.exitButton.configure(state = 'disabled')\r
577 \r
578     def erreur_exec(self, result):\r
579         """\r
580         Callback exécuté lorsque l'utilisateur clique sur un des boutons\r
581         Modifier/Annuler de la fenêtre de dialogue qui lui présente les erreurs\r
582         """\r
583         self.erreur_dialog.deactivate(result)\r
584         self.removedir()\r
585         if result == 'Annuler':\r
586             self.install_running = 0\r
587             self.exit(annule='non')\r
588 \r
589     def fatale_exec(self, result):\r
590         """\r
591         Callback exécuté lorsque l'utilisateur clique sur le bouton\r
592         Quitter de la fenêtre de dialogue qui lui présente les erreurs fatales\r
593         Seule solution : sortir de l'installation\r
594         """\r
595         self.fatale_dialog.deactivate(result)\r
596         self.install_running = 0\r
597         self.exit(annule='oui')\r
598         \r
599     def test_confirmation(self,flag,nom):\r
600         """\r
601         Callback activé par le clic sur bouton fenêtre demandant confirmation\r
602         avant création répertoire facultatif\r
603         """\r
604         if flag == 'NON':\r
605             self.confirmation.destroy()\r
606             self.TEST_confirmation_avant_creation = NON\r
607             return \r
608         else :\r
609             self.confirmation.destroy()\r
610             self.TEST_confirmation_avant_creation = OUI            \r
611             \r
612     def afficher_fatale(self, message):\r
613         """\r
614         Affiche les erreurs fatales\r
615         """\r
616         self.attente.withdraw()\r
617         w = Tkinter.Label(self.fatale_dialog.interior(),text = message, pady = 5)\r
618         w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)\r
619         self.fatale_dialog.configure(deactivatecommand = w.destroy)\r
620         self.fatale_dialog.activate()\r
621 \r
622     def afficher_echec(self, message):\r
623         """\r
624         Affiche un message d'erreur\r
625         Par construction, dès que l'on passe par cette méthode, on sort de l'installation\r
626         en passant le flag install_running à 0\r
627         """\r
628         self.attente.withdraw()\r
629         w = Tkinter.Label(self.erreur_dialog.interior(),text = message, pady = 5)\r
630         w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)\r
631         self.erreur_dialog.configure(deactivatecommand = w.destroy)\r
632         self.erreur_dialog.activate()\r
633 \r
634     def confirmation_avant_creation(self,repertoire):\r
635         """\r
636         Affiche une boite de dialogue pour confirmer la création\r
637         d'un répertoire facultatif.\r
638         """\r
639         self.attente.withdraw()\r
640         self.confirmation = Pmw.Dialog(self,\r
641                                        buttons = ('OUI', 'NON'),\r
642                                        defaultbutton = 'OUI',\r
643                                        title = "Répertoire inexistant",\r
644                                        command = lambda f,s=self,r=repertoire : s.test_confirmation(f,r))\r
645         self.confirmation.withdraw()\r
646         Tkinter.Label(self.confirmation.interior(),\r
647                       text="Le répertoire %s n'existe pas \n Voulez-vous le créer ?" %repertoire).pack(side='top')\r
648         self.confirmation.activate(geometry='centerscreenalways')\r
649         return self.TEST_confirmation_avant_creation\r
650   \r
651     def afficher_splash(self):\r
652         """\r
653         Afficher la boite de message \r
654         """\r
655         self.attente.deiconify()\r
656         self.attente.tkraise()\r
657         centerwindow(self.attente)\r
658         self.attente.configure(titre="Installation d'EFICAS",\r
659                                text="Vérification intégrité sources Eficas",\r
660                                barre="non")\r
661         \r
662     def afficher_info(self,message):\r
663         """\r
664         Afficher une boite de warning\r
665         """\r
666         w = Tkinter.Label(self.info_dialog.interior(),text = message, pady = 5)\r
667         w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)\r
668         self.info_dialog.configure(deactivatecommand = w.destroy)\r
669         self.info_dialog.activate()\r
670         \r
671     def afficher_copie_fichiers(self):\r
672         """\r
673         Afficher la boite de message avec la barre de progression\r
674         """\r
675         self.attente.deiconify()\r
676         self.attente.tkraise()\r
677         self.attente.configure(titre="Installation d'EFICAS",\r
678                                text="copie des fichiers",\r
679                                barre="oui")\r
680         self.attente.ratio = self.nb_fichiers\r
681         self.attente.configure_barre()\r
682 \r
683     def afficher_install_terminee(self):\r
684         """\r
685         Afficher le message Installation terminée\r
686         """\r
687         self.withdraw()\r
688         self.attente.configure(titre="Installation d'EFICAS",\r
689                                text="Installation terminée",\r
690                                barre="non")\r
691         self.exitButton.place_forget()\r
692         self.validButton.place_forget()\r
693         self.validButton = Tkinter.Button(self.attente.frame,\r
694                                           text = 'Quitter',\r
695                                           command = self.exit)\r
696         self.validButton.pack(side='top',pady=5)\r
697         self.install_running = 0\r
698 \r
699     def decompress_archive(self) :\r
700         """\r
701         Décompresse l'archive d'EFICAS dans un répertoire temporaire (.)\r
702         """\r
703         print "decompress_archive"\r
704         #try:\r
705         commande = os.path.join(REPERTOIRE,self.d_commandes['decompress'])\r
706         fichier = os.path.join(REPERTOIRE,"eficas.zip")\r
707         print 'commande =',commande\r
708         print 'fichier =',fichier\r
709         os.execv(commande,("eficas.zip",))\r
710         #except:\r
711         #    self.affiche_echec("Erreur dans la décompression")\r
712 \r
713     def normaliser_chemin(self, nom):\r
714         """\r
715         Retourne le chemin d'accès complet à nom\r
716         """\r
717         return os.path.abspath(os.path.expanduser(nom))\r
718 \r
719     def discriminer_noms(self):\r
720         """\r
721         Emet un message d'alerte si des zones de saisie ne sont pas remplies\r
722         ou si des noms de répertoires à créer sont identiques.\r
723         """\r
724         liste_noms = []\r
725         for item in self.items_a_creer:\r
726             nom = item.entree.get()\r
727             if nom == self.rep_install.entree.get():        # il faut ajouter 'Eficas' au chemin du repertoire\r
728                 nom = os.path.join(nom,"Eficas")            # d'installation\r
729             liste_noms.append(nom)\r
730 \r
731         test = SUCCES\r
732         for item in self.items_a_creer:\r
733             nom = item.entree.get()\r
734             if len(nom) == 0 :\r
735                 test = ECHEC\r
736                 message = "attention : certains répertoires n'ont pas de nom"\r
737                 self.afficher_echec(message)\r
738             item.entree.component('entry').focus()\r
739             break\r
740 \r
741         if test == ECHEC :\r
742             return test\r
743 \r
744         for item in self.items_a_creer:\r
745             nom = item.entree.get()\r
746             if liste_noms.count(nom) >1 :\r
747                 test = ECHEC\r
748                 message = "attention : certains répertoires ont le même nom"\r
749                 self.afficher_echec(message)\r
750             item.entree.component('entry').focus()\r
751             break\r
752 \r
753         return test\r
754 \r
755     def compte_fichiers(self,path):\r
756         """\r
757         Dénombre les fichiers présents dans le répertoire Eficas (et ses sous-répertoires)\r
758         """\r
759         nb = 0\r
760         l_fic = os.listdir(path)\r
761         l_rep = []\r
762         for fic in l_fic :\r
763             if os.path.isdir(os.path.join(path,fic)):\r
764                 l_rep.append(fic)\r
765             else:\r
766                 nb = nb+1\r
767         for rep in l_rep :\r
768             nb = nb + self.compte_fichiers(os.path.join(path,rep))\r
769         return nb\r
770 \r
771     def creer_fic_conf(self):\r
772         """\r
773         Crée le fichier editeur.ini a partir des données saisies\r
774         par l'administrateur.\r
775         """\r
776         fichier_conf = os.path.join(self.normaliser_chemin(self.rep_install.get_valeur()),"Eficas/Aster/editeur.ini")\r
777         f = open(fichier_conf,'w')\r
778         f.write("path_doc        =    "+'"'+self.normaliser_chemin(self.rep_docaster.get_valeur())+'"\n')\r
779         f.write("exec_acrobat    =    "+'"'+self.normaliser_chemin(self.acrobat.get_valeur())+'"\n')\r
780         f.write('isdeveloppeur   =    "NON"\n')\r
781         f.write("rep_travail     =    "+'"'+self.normaliser_chemin(self.rep_travail.get_valeur())+'"\n')\r
782         f.write("rep_cata        =    "+'"'+os.path.join(self.normaliser_chemin(self.rep_install.get_valeur()),"Eficas/Aster/Cata/")+'"\n') # attention au dernier slash\r
783         f.write("rep_mat         =    "+'"'+self.normaliser_chemin(self.rep_mat.get_valeur())+'"\n')\r
784         cata = """catalogues = (('ASTER','v6',rep_cata + 'cata_STA6.py','python','defaut'),)\n"""\r
785         f.write(cata)\r
786         f.close()\r
787         \r
788 \r
789     def move_files(self):\r
790         """\r
791         Déplace les fichiers Eficas du répertoire temporaire vers\r
792         leur répertoire de destination\r
793         """\r
794         # création du répertoire Eficas\r
795         rep_eficas = os.path.join(self.rep_install.get_valeur(),'Eficas')\r
796         self.copy_rep(REPERTOIRE,rep_eficas)\r
797 \r
798     def copy_rep(self,rep_dep,rep_arr):\r
799         """\r
800         Copie le répertoire path_dep et ses sous-répertoires dans path_arr\r
801         """\r
802         l_fichiers = os.listdir(rep_dep)\r
803         if not os.path.exists(rep_arr) :\r
804             # création du répertoire d'arrivée quand il n'existe pas \r
805             self.mkdirs(rep_arr)\r
806         for fic in l_fichiers :\r
807             nom_complet_dep = os.path.join(rep_dep,fic)\r
808             nom_complet_arr = os.path.join(rep_arr,fic)\r
809             if os.path.isfile(nom_complet_dep):\r
810                 commande_copie = self.d_commandes['copy']+nom_complet_dep+' '+nom_complet_arr\r
811                 commande_delete= self.d_commandes['delete']+nom_complet_dep\r
812                 try:\r
813                     os.system(commande_copie)\r
814                     #os.system(commande_delete)\r
815                     self.attente.update_barre()\r
816                 except Exception,e:\r
817                     pass\r
818             elif os.path.isdir(nom_complet_dep):\r
819                 self.copy_rep(nom_complet_dep,nom_complet_arr)\r
820 \r
821     def rm_temp_dirs(self):\r
822         """\r
823         Détruit le répertoire temporaire de l'archive d'Eficas\r
824         """\r
825         rep_arch = os.path.join(REPERTOIRE,'Eficas')\r
826         self.rm_r(rep_arch)\r
827 \r
828     def make_dirs(self):\r
829         """\r
830         Crée les répertoires d'accueil des fichiers d'EFICAS\r
831         """\r
832         # création des répertoires dont l'utilisateur a donné le nom\r
833         if self.discriminer_noms() == ECHEC:\r
834             return ECHEC\r
835         for item in self.items_a_creer:\r
836             if not item.entree.get():\r
837                 continue\r
838             nom = item.get_valeur()\r
839             if nom == self.normaliser_chemin(self.rep_install.entree.get()):        # il faut ajouter 'Eficas' au chemin du repertoire\r
840                 nom = os.path.join(nom,"Eficas")            # d'installation\r
841             item.test = self.essai_creer(nom,item.statut)\r
842             if item.test == ECHEC :\r
843                 item.entree.component('entry').focus()\r
844                 return ECHEC\r
845         return SUCCES\r
846 \r
847     def essai_creer(self, nom, statut):\r
848         """\r
849         Essaie de créer le répertoire nom s'il n'existe pas déjà.\r
850         Si statut == 'f' et si le fichier n'existe pas, demande\r
851         confirmation avant création\r
852         """\r
853         repertoire = self.normaliser_chemin(nom)                # repertoire = chemin absolu de nom\r
854         if os.path.exists(repertoire):\r
855             if statut == 'o' :\r
856                 self.afficher_echec("Un fichier ou répertoire de nom "+ repertoire+ " existe déjà !\n"+\r
857                                 "L'installation ne peut continuer")\r
858                 return ECHEC\r
859             else:\r
860                 return SUCCES\r
861 \r
862         if statut == 'f' :\r
863             # on demande confirmation de création à l'utilisateur\r
864             test = self.confirmation_avant_creation(repertoire)\r
865             if test == NON:\r
866                 return SUCCES\r
867 \r
868         try:\r
869             test = self.mkdirs(repertoire)\r
870             return SUCCES\r
871         except Exception,e:\r
872             message = "La création de "+repertoire+" a échoué :\n %s \n Vérifiez vos droits d'écriture"  %str(e)  # message d'erreur\r
873             self.afficher_echec(message)\r
874             return ECHEC\r
875 \r
876     def mkdirs(self,rep):\r
877         """\r
878         Création récursive des répertoires d'installation.\r
879         Les noms des répertoires crées sont stockés dans\r
880         une liste dont se sert la méthode removedir pour\r
881         restaurer l'environnement initial en cas d'annulation.\r
882         """\r
883         if rep==os.path.dirname(rep):\r
884             return SUCCES\r
885 \r
886         if os.path.exists(os.path.dirname(rep)):\r
887             os.mkdir(rep)\r
888             self.liste_rep_crees.append(rep)\r
889             return SUCCES\r
890         else:\r
891             test = self.mkdirs(os.path.dirname(rep))\r
892             if test == SUCCES:\r
893                 os.mkdir(rep)\r
894                 self.liste_rep_crees.append(rep)\r
895                 return SUCCES\r
896             else:\r
897                 return ECHEC\r
898 \r
899     def rm_r(self,path):\r
900         """\r
901         Detruit récursivement path\r
902         """\r
903         if not os.path.exists(path):\r
904             return\r
905         try:\r
906             if len(os.listdir(path))!=0:\r
907                 for entree in os.listdir(path):\r
908                     entree = os.path.join(path,entree)\r
909                     self.rm_r(entree)\r
910             os.rmdir(path)\r
911         except Exception,e:\r
912             self.afficher_info("Impossible de détruire le répertoire : "+path+"\n"+"\n"+str(e)+"\n L'installation continue néanmoins")\r
913 \r
914     def removedir(self):\r
915         """\r
916         Destruction des répertoires déja crées (en cas d'annulation)\r
917         """\r
918         for rep in self.liste_rep_crees:\r
919             self.rm_r(rep)\r
920         self.liste_rep_crees = []\r
921 \r
922     def exit(self,annule='non'):\r
923         """\r
924         Tente de sortir de l'application.\r
925         Echoue si installation en cours\r
926         """\r
927         if self.install_running :\r
928             # l'installation est en cours --> on interdit la sortie\r
929             self.afficher_info("Impossible de quitter tant que l'installation est en cours\n Veuillez patienter")\r
930         else:\r
931             if annule == 'oui' : self.removedir()\r
932             self.master.quit()\r
933 \r
934 if __name__ == '__main__':\r
935     test = Test_Environnement().test()\r
936     if not test :\r
937         # environnement incomplet --> on sort de la procédure d'installation\r
938         sys.exit()\r
939     else:\r
940         import Tkinter\r
941         import Pmw\r
942         root = Tkinter.Tk()\r
943         Pmw.initialise(root)\r
944         try:\r
945             principal = Config(root)\r
946             root.mainloop()\r
947         except Exception,e:\r
948             print "Erreur non prévue rencontrée : ",str(e)\r
949             print "Veuillez prévenir la maintenance"\r
950             sys.exit()\r