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