Salome HOME
This commit was generated by cvs2git to track changes on a CVS vendor
[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 = 20\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,traceback\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 = 'Editeur/icons/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 = 'Editeur/icons/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                             '',\r
351                             '',\r
352                             'o'),\r
353                            ('rep_travail'   ,\r
354                             'Répertoire de travail :',\r
355                             'tmp',\r
356                             'tmp',\r
357                             'f'),\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(REPERTOIRE)\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             self.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             traceback.print_exc()\r
499             self.install_running = 0\r
500             self.afficher_fatale("Impossible de copier certains fichiers")\r
501 \r
502         #self.rm_temp_dirs()                     # efface les répertoires temporaires\r
503         try:\r
504             self.creer_fic_conf()                   # crée le fichier eficas.conf\r
505         except:\r
506             afficher_info("Impossible de créer le fichier de configuration\n Il est possible de le faire a la main")\r
507 #        self.install_running = 0\r
508         self.afficher_install_terminee()        # A ce stade tout est fait et il ne reste plus qu'à attendre\r
509                                                 # un clic de souris pour sortir\r
510 \r
511     def display_defaults(self):\r
512         """\r
513         Affiche les valeurs par défaut dans les zones de saisie\r
514         """\r
515         # racine indique la racine de l'arborescence\r
516         if os.name == 'nt':\r
517             racine = 'C:\\'\r
518         else:\r
519             racine = os.environ['HOME']\r
520         # remplit les zones de saisie avec les options par défaut\r
521         for item in self.items:\r
522             if item.default_value == None : continue\r
523             item.default_value = os.path.join(racine,item.default_value)\r
524             item.entree.insert(0,item.default_value)\r
525 \r
526     def register_item(self,item):\r
527         """\r
528         Enregistre l'item dans la liste des items et éventuellement\r
529         dans la liste des items à créer (répertoires)\r
530         """\r
531         self.items.append(item)\r
532         if self.pat_rep.match(item.nom) :\r
533             self.items_a_creer.append(item)\r
534 \r
535     def register_entree(self,entree):\r
536         """\r
537         Enregistre la zone de saisie dans la liste des zones\r
538         """\r
539         self.entrees.append(entree)\r
540 \r
541     def select_next_entry(self,entree):\r
542         """\r
543         Place le focus dans l'entry suivant celle passée en argument\r
544         """\r
545         index = self.entrees.index(entree)+1\r
546         if index != len(self.entrees):\r
547             self.entrees[index].component('entry').focus()\r
548 \r
549     def activate_entries(self):\r
550         """\r
551         Active les entrées. Les zones de saisie deviennent éditables.\r
552         """\r
553         for item in self.entrees:\r
554             item.configure(entry_state='normal')\r
555 \r
556     def deactivate_entries(self):\r
557         """\r
558         Désactive les entrées. Les zones ne sont plus éditables.\r
559         """\r
560         for item in self.entrees:                                #  Les entrees sont desactivees\r
561             item.configure(entry_state='disabled')               #  pendant les operations d'installation\r
562 \r
563     def activate_buttons(self):\r
564         """\r
565         active les boutons valider et annuler\r
566         """\r
567         self.validButton.configure(state = 'normal')\r
568         self.exitButton.configure(state = 'normal')\r
569 \r
570     def deactivate_buttons(self):\r
571         """\r
572         désactive des boutons valider de annuler\r
573         """\r
574         self.validButton.configure(state = 'disabled')\r
575         self.exitButton.configure(state = 'disabled')\r
576 \r
577     def erreur_exec(self, result):\r
578         """\r
579         Callback exécuté lorsque l'utilisateur clique sur un des boutons\r
580         Modifier/Annuler de la fenêtre de dialogue qui lui présente les erreurs\r
581         """\r
582         self.erreur_dialog.deactivate(result)\r
583         self.removedir()\r
584         if result == 'Annuler':\r
585             self.install_running = 0\r
586             self.exit(annule='non')\r
587 \r
588     def fatale_exec(self, result):\r
589         """\r
590         Callback exécuté lorsque l'utilisateur clique sur le bouton\r
591         Quitter de la fenêtre de dialogue qui lui présente les erreurs fatales\r
592         Seule solution : sortir de l'installation\r
593         """\r
594         self.fatale_dialog.deactivate(result)\r
595         self.install_running = 0\r
596         self.exit(annule='oui')\r
597         \r
598     def test_confirmation(self,flag,nom):\r
599         """\r
600         Callback activé par le clic sur bouton fenêtre demandant confirmation\r
601         avant création répertoire facultatif\r
602         """\r
603         if flag == 'NON':\r
604             self.confirmation.destroy()\r
605             self.TEST_confirmation_avant_creation = NON\r
606             return \r
607         else :\r
608             self.confirmation.destroy()\r
609             self.TEST_confirmation_avant_creation = OUI            \r
610             \r
611     def afficher_fatale(self, message):\r
612         """\r
613         Affiche les erreurs fatales\r
614         """\r
615         self.attente.withdraw()\r
616         w = Tkinter.Label(self.fatale_dialog.interior(),text = message, pady = 5)\r
617         w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)\r
618         self.fatale_dialog.configure(deactivatecommand = w.destroy)\r
619         self.fatale_dialog.activate()\r
620 \r
621     def afficher_echec(self, message):\r
622         """\r
623         Affiche un message d'erreur\r
624         Par construction, dès que l'on passe par cette méthode, on sort de l'installation\r
625         en passant le flag install_running à 0\r
626         """\r
627         self.attente.withdraw()\r
628         w = Tkinter.Label(self.erreur_dialog.interior(),text = message, pady = 5)\r
629         w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)\r
630         self.erreur_dialog.configure(deactivatecommand = w.destroy)\r
631         self.erreur_dialog.activate()\r
632 \r
633     def confirmation_avant_creation(self,repertoire):\r
634         """\r
635         Affiche une boite de dialogue pour confirmer la création\r
636         d'un répertoire facultatif.\r
637         """\r
638         self.attente.withdraw()\r
639         self.confirmation = Pmw.Dialog(self,\r
640                                        buttons = ('OUI', 'NON'),\r
641                                        defaultbutton = 'OUI',\r
642                                        title = "Répertoire inexistant",\r
643                                        command = lambda f,s=self,r=repertoire : s.test_confirmation(f,r))\r
644         self.confirmation.withdraw()\r
645         Tkinter.Label(self.confirmation.interior(),\r
646                       text="Le répertoire %s n'existe pas \n Voulez-vous le créer ?" %repertoire).pack(side='top')\r
647         self.confirmation.activate(geometry='centerscreenalways')\r
648         return self.TEST_confirmation_avant_creation\r
649   \r
650     def afficher_splash(self):\r
651         """\r
652         Afficher la boite de message \r
653         """\r
654         self.attente.deiconify()\r
655         self.attente.tkraise()\r
656         centerwindow(self.attente)\r
657         self.attente.configure(titre="Installation d'EFICAS",\r
658                                text="Vérification intégrité sources Eficas",\r
659                                barre="non")\r
660         \r
661     def afficher_info(self,message):\r
662         """\r
663         Afficher une boite de warning\r
664         """\r
665         w = Tkinter.Label(self.info_dialog.interior(),text = message, pady = 5)\r
666         w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)\r
667         self.info_dialog.configure(deactivatecommand = w.destroy)\r
668         self.info_dialog.activate()\r
669         \r
670     def afficher_copie_fichiers(self):\r
671         """\r
672         Afficher la boite de message avec la barre de progression\r
673         """\r
674         self.attente.deiconify()\r
675         self.attente.tkraise()\r
676         self.attente.configure(titre="Installation d'EFICAS",\r
677                                text="copie des fichiers",\r
678                                barre="oui")\r
679         self.attente.ratio = self.nb_fichiers\r
680         self.attente.configure_barre()\r
681 \r
682     def afficher_install_terminee(self):\r
683         """\r
684         Afficher le message Installation terminée\r
685         """\r
686         self.withdraw()\r
687         self.attente.configure(titre="Installation d'EFICAS",\r
688                                text="Installation terminée",\r
689                                barre="non")\r
690         self.exitButton.place_forget()\r
691         self.validButton.place_forget()\r
692         self.validButton = Tkinter.Button(self.attente.frame,\r
693                                           text = 'Quitter',\r
694                                           command = self.exit)\r
695         self.validButton.pack(side='top',pady=5)\r
696         self.install_running = 0\r
697 \r
698     def decompress_archive(self) :\r
699         """\r
700         Décompresse l'archive d'EFICAS dans un répertoire temporaire (.)\r
701         """\r
702         print "decompress_archive"\r
703         #try:\r
704         commande = os.path.join(REPERTOIRE,self.d_commandes['decompress'])\r
705         fichier = os.path.join(REPERTOIRE,"eficas.zip")\r
706         print 'commande =',commande\r
707         print 'fichier =',fichier\r
708         os.execv(commande,("eficas.zip",))\r
709         #except:\r
710         #    self.affiche_echec("Erreur dans la décompression")\r
711 \r
712     def normaliser_chemin(self, nom):\r
713         """\r
714         Retourne le chemin d'accès complet à nom\r
715         """\r
716         return os.path.abspath(os.path.expanduser(nom))\r
717 \r
718     def discriminer_noms(self):\r
719         """\r
720         Emet un message d'alerte si des zones de saisie ne sont pas remplies\r
721         ou si des noms de répertoires à créer sont identiques.\r
722         """\r
723         liste_noms = []\r
724         for item in self.items_a_creer:\r
725             nom = item.entree.get()\r
726             if nom == self.rep_install.entree.get():        # il faut ajouter 'Eficas' au chemin du repertoire\r
727                 nom = os.path.join(nom,"Eficas")            # d'installation\r
728             liste_noms.append(nom)\r
729 \r
730         test = SUCCES\r
731         for item in self.items_a_creer:\r
732             nom = item.entree.get()\r
733             if len(nom) == 0 :\r
734                 test = ECHEC\r
735                 message = "attention : certains répertoires n'ont pas de nom"\r
736                 self.afficher_echec(message)\r
737             item.entree.component('entry').focus()\r
738             break\r
739 \r
740         if test == ECHEC :\r
741             return test\r
742 \r
743         for item in self.items_a_creer:\r
744             nom = item.entree.get()\r
745             if liste_noms.count(nom) >1 :\r
746                 test = ECHEC\r
747                 message = "attention : certains répertoires ont le même nom"\r
748                 self.afficher_echec(message)\r
749             item.entree.component('entry').focus()\r
750             break\r
751 \r
752         return test\r
753 \r
754     def compte_fichiers(self,path):\r
755         """\r
756         Dénombre les fichiers présents dans le répertoire Eficas (et ses sous-répertoires)\r
757         """\r
758         nb = 0\r
759         l_fic = os.listdir(path)\r
760         l_rep = []\r
761         for fic in l_fic :\r
762             if os.path.isdir(os.path.join(path,fic)):\r
763                 l_rep.append(fic)\r
764             else:\r
765                 nb = nb+1\r
766         for rep in l_rep :\r
767             nb = nb + self.compte_fichiers(os.path.join(path,rep))\r
768         return nb\r
769 \r
770     def creer_fic_conf(self):\r
771         """\r
772         Crée le fichier editeur.ini a partir des données saisies\r
773         par l'administrateur.\r
774         """\r
775         fichier_conf = os.path.join(self.normaliser_chemin(self.rep_install.get_valeur()),"Eficas/Aster/editeur.ini")\r
776         f = open(fichier_conf,'w')\r
777         f.write("path_doc        =    "+'"'+self.normaliser_chemin(self.rep_docaster.get_valeur())+'"\n')\r
778         f.write("exec_acrobat    =    "+'"'+self.normaliser_chemin(self.acrobat.get_valeur())+'"\n')\r
779         f.write('isdeveloppeur   =    "NON"\n')\r
780         f.write("rep_travail     =    "+'"'+self.normaliser_chemin(self.rep_travail.get_valeur())+'"\n')\r
781         f.write("rep_cata        =    "+'"'+os.path.join(self.normaliser_chemin(self.rep_install.get_valeur()),"Eficas/Aster/Cata/")+'"\n') # attention au dernier slash\r
782         f.write("rep_mat         =    "+'"'+self.normaliser_chemin(self.rep_mat.get_valeur())+'"\n')\r
783         cata = """catalogues = (('ASTER','v6',rep_cata + 'cata_STA6.py','python','defaut'),)\n"""\r
784         f.write(cata)\r
785         f.close()\r
786         \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(REPERTOIRE,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