Avez-vous tous réussi ?
Si ce n'est pas le cas, relisez les deux chapitres précédents et demandez de l'aide sur le forum avant de consulter la correction.
Nous allons regarder pas à pas
mon code ; il est très certain que nos codes soient différents.
Pour commencer, j'importe les modules :
Code : Python1
2
3
4
5 | # -*- coding:Utf-8 -*-
import pygtk
pygtk.require("2.0")
import gtk
import os
|
Deuxièmement, je crée la classe DocumentOuvert() :
Code : Python1
2
3
4
5
6 | class DocumentOuvert():
"Objet qui contient des informations sur un fichier ouvert"
def __init__(self):
self.chemin = ''
self.aSauvegarder = False
self.zoneTexteDocument = None
|
Je n'ai toujours pas de commentaire à faire ; ceci est expliqué plus haut.
Avant de continuer, je vais vous donner mon fichier glade :
Code : XML 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 | <?xml version="1.0"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="fenetre">
<property name="visible">True</property>
<property name="title" translatable="yes">Éditeur de texte en PyGtk</property>
<property name="icon">editeurDeTexteIco.png</property>
<accel-groups>
<group name="accelgroup1"/>
</accel-groups>
<signal name="destroy" handler="quitter"/>
<signal name="delete_event" handler="detruireFen"/>
<child>
<object class="GtkVBox" id="boiteV">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkMenuBar" id="barreMenu">
<property name="visible">True</property>
<child>
<object class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Fichier</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu1">
<property name="visible">True</property>
<child>
<object class="GtkImageMenuItem" id="nouveau">
<property name="label">gtk-new</property>
<property name="visible">True</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<property name="accel_group">accelgroup1</property>
<signal name="activate" handler="nouveau"/>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="ouvrir">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<property name="accel_group">accelgroup1</property>
<signal name="activate" handler="ouvrirFichierDialogue"/>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="enregistrer">
<property name="label">gtk-save</property>
<property name="visible">True</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<property name="accel_group">accelgroup1</property>
<signal name="activate" handler="enregistrer"/>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="enregistrerSous">
<property name="label">gtk-save-as</property>
<property name="visible">True</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<property name="accel_group">accelgroup1</property>
<signal name="activate" handler="enregistrerSous"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="fermer">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<property name="accel_group">accelgroup1</property>
<signal name="activate" handler="fermer"/>
</object>
</child>
<child>
<object class="GtkImageMenuItem" id="quitter">
<property name="label">gtk-quit</property>
<property name="visible">True</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<property name="accel_group">accelgroup1</property>
<signal name="activate" handler="quitter"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="label" translatable="yes">Aid_e</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu3">
<property name="visible">True</property>
<child>
<object class="GtkImageMenuItem" id="aPropos">
<property name="label">gtk-about</property>
<property name="visible">True</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<property name="accel_group">accelgroup1</property>
<signal name="activate" handler="aPropos"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkToolbar" id="barreOutils">
<property name="visible">True</property>
<child>
<object class="GtkToolButton" id="nouveau1">
<property name="visible">True</property>
<property name="label" translatable="yes">Nouveau</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-new</property>
<signal name="clicked" handler="nouveau"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="toolbutton1">
<property name="visible">True</property>
<property name="label" translatable="yes">Ouvrir</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-open</property>
<signal name="clicked" handler="ouvrirFichierDialogue"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="toolbutton2">
<property name="visible">True</property>
<property name="label" translatable="yes">Enregistrer</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-save</property>
<signal name="clicked" handler="enregistrer"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="toolbutton3">
<property name="visible">True</property>
<property name="label" translatable="yes">Enregistrer sous...</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-save-as</property>
<signal name="clicked" handler="enregistrerSous"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkSeparatorToolItem" id="separateur">
<property name="visible">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="toolbutton5">
<property name="visible">True</property>
<property name="label" translatable="yes">À propos</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-about</property>
<signal name="clicked" handler="aPropos"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="fermer1">
<property name="visible">True</property>
<property name="label" translatable="yes">Fermer</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-close</property>
<signal name="clicked" handler="fermer"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton" id="toolbutton4">
<property name="visible">True</property>
<property name="label" translatable="yes">Quitter</property>
<property name="use_underline">True</property>
<property name="stock_id">gtk-quit</property>
<signal name="clicked" handler="quitter"/>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="barresDefilement">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkAccelGroup" id="accelgroup1"/>
</interface>
|
Ensuite, on crée la fenêtre principale à partir du fichier glade :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | class PyGtkApp:
def __init__(self):
#Création de la fenêtre principale à partie d'un fichier glade
interface = gtk.Builder()
interface.add_from_file('fenetre.glade')
self.fenetre = interface.get_object("fenetre")
self.barresDefilement = interface.get_object('barresDefilement')
interface.connect_signals(self)
self.fenetre.maximize()
self.documents = [] #Liste des documents ouverts
self.documentActif = None #Le document actif (objet DocumentOuvert())
[...]
PyGtkApp()
gtk.main()
|
Tout ceci est du déjà vu : on crée la fenêtre, on connecte les signaux, on met les barres de défilement dans une variable pour réutiliser le widget et on crée deux attributs. Après les autres fonctions que j'ai passés pour l'instant, on appelle la classe principale et on commence la boucle principale.
Voyons chacune des méthodes de la classe principale :
Code : Python1
2
3
4
5
6
7
8 | def detruireFen(self, widget, evenement):
"Lorsque la fenêtre est détruite"
if self.documentActif != None:
if not self.fermer(None) == False:
return False #Si le document est bien fermé, on peut fermer la fenêtre
else:
return False #Si aucun document n'est actif, on peut aussi la fermer
return True #Sinon, on la laisse ouverte
|
Cette méthode est appelée lorsque l'utilisateur clique sur le x ou ferme la fenêtre d'une autre façon (par exemple, Alt-F4). Si aucun document n'est actif, on revoie False, donc le signal 'destroy' est émit. Ce signal est également émit si un document est ouvert mais qu'il se ferme ensuite. Sinon, on renvoie True pour laisser la fenêtre ouverte, donc ne pas émettre le signal 'destroy'.
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | def aPropos(self, widget):
"Dialogue À propos"
pixbuf = gtk.gdk.pixbuf_new_from_file("editeurDeTexteIco.png")
aPropos = gtk.AboutDialog()
aPropos.set_icon_from_file("editeurDeTexteIco.png")
aPropos.set_name("Éditeur de texte")
aPropos.set_version("1.0")
aPropos.set_copyright("Copyright © 2009, tous droits réservés")
aPropos.set_comments(aPropos.get_name() + " " + aPropos.get_version() +" est un éditeur de texte basique.")
aPropos.set_license("Copyright © 2009 antoyo\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along\nwith this program; if not, write to the Free Software Foundation, Inc.,\n51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.")
auteurs = ["Antoyo"]
aPropos.set_authors(auteurs)
aPropos.set_logo(pixbuf)
reponse = aPropos.run()
aPropos.destroy()
|
Revoyez le chapitre
Les widgets (Partie 2), sous-partie
D'autres boîtes de dialogue pour savoir ce que fait chacune des méthodes.
Notez également que j'ai mis la licence GNU GPL ; regardez
ce tutoriel pour faire de votre programme un logiciel libre.
Voici enfin la fonction de fermeture d'un fichier :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 | def fermer(self, widget):
"Fermeture d'un fichier" #Dans cette fonction, si le retour est False, cela indique qu'il n'y a pas eu de fermeture
if self.documentActif != None: #S'il y a un document actif
if self.documentActif.aSauvegarder: #Si il est modifié
#On crée un boîte de dialogue pour demander à l'utilisateur s'il veut enregistrer les modifications ou non ou bien annuler la fermeture
fermetureDialogue = gtk.Dialog("Enregistrer", self.fenetre, 0, (gtk.STOCK_YES, gtk.RESPONSE_YES, gtk.STOCK_NO, gtk.RESPONSE_NO, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
etiquette = gtk.Label('Voulez-vous enregistrer les modifications ?')
boiteH = gtk.HBox()
fermetureDialogue.vbox.pack_start(boiteH, False)
stock = gtk.image_new_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG)
boiteH.pack_start(stock, False)
boiteH.pack_start(etiquette, False)
fermetureDialogue.show_all()
reponse = fermetureDialogue.run()
if reponse == gtk.RESPONSE_YES:
if self.enregistrer(None):
#Si l'utilisateur appuie sur Oui et qu'il enregistre le document, on peut le fermer
self.documentActif.zoneTexteDocument.destroy()
self.documents.remove(self.documentActif)
self.documentActif = None
else:
#S'il ne l'enregistre pas, on ferme la boîte de dialogue
fermetureDialogue.destroy()
return False
self.fenetre.set_title('Éditeur de texte en PyGtk') #On remet le titre à la fenêtre
elif reponse == gtk.RESPONSE_NO:
#S'il appuie sur Non, on ferme le document sans enregistrer
self.documentActif.zoneTexteDocument.destroy()
self.documents.remove(self.documentActif)
self.documentActif = None
self.fenetre.set_title('Éditeur de texte en PyGtk')
elif reponse == gtk.RESPONSE_CANCEL:
#S'il appuie sur Annuler, on fermer seulement la boîte de dialogue
fermetureDialogue.destroy()
return False
fermetureDialogue.destroy()
else:
self.documentActif.zoneTexteDocument.destroy()
self.documents.remove(self.documentActif)
self.documentActif = None
self.fenetre.set_title('Éditeur de texte en PyGtk')
else:
self.afficherAvertissement("Il n'y a aucun document ouvert.")
|
Voyons-le bloc par bloc. Premièrement :
Code : Python1
2
3
4 | if self.documentActif != None: #S'il y a un document actif
[...]
else:
self.afficherAvertissement("Il n'y a aucun document ouvert.")
|
Au début, on vérifie si un document est ouvert ; si ce n'est pas le cas, on affiche un avertissement pour l'indiquer à l'utilisateur (il faut prévoir tous les cas en programmation ;
on ne sait jamais si un ****** essayera de fermer un fichier alors qu'aucun n'est ouvert.)
Ensuite, nous voyons ceci :
Code : Python1
2
3
4
5
6
7 | if self.documentActif.aSauvegarder: #Si il est modifié
[...]
else:
self.documentActif.zoneTexteDocument.destroy()
self.documents.remove(self.documentActif)
self.documentActif = None
self.fenetre.set_title('Éditeur de texte en PyGtk')
|
Donc, si un fichier est ouvert, on vérifie s'il est modifié ; si ce n'est pas le cas, on détruit la zone de texte, on enlève le document actif de la liste des documents et on change le titre de la fenêtre.
Après, il y a :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13 | #On crée un boîte de dialogue pour demander à l'utilisateur s'il veut enregistrer les modifications ou non ou bien annuler la fermeture
fermetureDialogue = gtk.Dialog("Enregistrer", self.fenetre, 0, (gtk.STOCK_YES, gtk.RESPONSE_YES, gtk.STOCK_NO, gtk.RESPONSE_NO, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
etiquette = gtk.Label('Voulez-vous enregistrer les modifications ?')
boiteH = gtk.HBox()
fermetureDialogue.vbox.pack_start(boiteH, False)
stock = gtk.image_new_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG)
boiteH.pack_start(stock, False)
boiteH.pack_start(etiquette, False)
fermetureDialogue.show_all()
reponse = fermetureDialogue.run()
|
S'il est modifié, on affiche une boîte de dialogue personnalisée pour demander gentiment à l'utilisateur ce qu'il veut faire avec le fichier ouvert (l'enregistrer, ne pas l'enregistrer ou annuler la fermeture).
Puis, vient cela :
Code : Python1
2
3
4
5
6
7
8 | if reponse == gtk.RESPONSE_YES:
[...]
elif reponse == gtk.RESPONSE_NO:
[...]
elif reponse == gtk.RESPONSE_CANCEL:
#S'il appuie sur Annuler, on fermer seulement la boîte de dialogue
fermetureDialogue.destroy()
return False
|
Si l'utilisateur appuie sur Annuler, on détruit la boîte de dialogue sans autre action et on retourne False pour indiquer qu'aucun enregistrement n'a été effectué.
Revenons à ceci :
Code : Python1
2
3
4
5
6
7 | elif reponse == gtk.RESPONSE_NO:
#S'il appuie sur Non, on ferme le document sans enregistrer
self.documentActif.zoneTexteDocument.destroy()
self.documents.remove(self.documentActif)
self.documentActif = None
self.fenetre.set_title('Éditeur de texte en PyGtk')
|
S'il appuie sur Non, on détruit le fichier de la même manière que s'il n'aurait pas été à sauvegarder.
Et enfin :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12 | if reponse == gtk.RESPONSE_YES:
if self.enregistrer(None):
#Si l'utilisateur appuie sur Oui et qu'il enregistre le document, on peut le fermer
self.documentActif.zoneTexteDocument.destroy()
self.documents.remove(self.documentActif)
self.documentActif = None
else:
#S'il ne l'enregistre pas, on ferme la boîte de dialogue
fermetureDialogue.destroy()
return False
self.fenetre.set_title('Éditeur de texte en PyGtk') #On remet le titre à la fenêtre
|
Par contre, s'il appuie sur Oui, on fait quelque chose de plus intéressant ! On appelle la méthode
self.enregistrer() (voir plus bas) et si l'utilisateur a changé d'avis (s'il a appuyé sur Annuler), ben on ferme la boîte de dialogue. S'il a choisi le nom du fichier (méthode
self.enregistrer()), on ferme le document ; la méthode
self.enregistrer() faisant le travail d'enregistrer le fichier.
Le retour de cette méthode est très important : il permet de dire aux méthodes qui l'appelle si le fichier a été fermé, donc si elles peuvent continuer à faire ce qu'elles doivent faire.
Puis, voyons la méthode
self.nouveau() :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | def nouveau(self, widget):
"Création d'un nouveau document"
if self.documentActif == None: #On le crée seulement s'il n'y en a pas déjà un d'ouvert
#Création d'un objet DocumentOuvert() sans chemin
nouveau = DocumentOuvert()
nouveau.chemin = ''
nouveau.ASauvegarder = False
#Le chemin vaut '' et il n'est pas à sauvegarder
self.documents.append(nouveau) #On l'ajoute à la liste
self.documentActif = nouveau #Et c'est le document actif
nouveau.zoneTexteDocument = gtk.TextView() #On crée une nouvelle zone de texte
tampon = nouveau.zoneTexteDocument.get_buffer()
tampon.connect("changed", self.fichierModifie) #On récupère le tampon pour savoir quand il est modifié
self.barresDefilement.add(nouveau.zoneTexteDocument)
nouveau.zoneTexteDocument.show()
self.definirTitre()
else:
self.afficherAvertissement("Il y a déjà un document ouvert.")
|
Si un document est déjà ouvert, on avertie l'utilisateur que c'est le cas. Sinon, on crée un objet
DocumentOuvert(), en spécifiant que son chemin est '' et qu'il n'est pas à enregistrer. On l'ajoute à la liste des documents et le nouveau document devient le document actif. On crée un nouvelle zone de texte et on récupère son buffer. On le connecte au signal 'changed' (rappelez-vous, celui qui est émit lorsque le contenu d'un buffer est changé), on l'ajoute dans des barres de défilement et on l'affiche.
La méthode self.fichierModifie est très simple :
Code : Python1
2
3
4 | def fichierModifie(self, widget):
#Si un fichier est modifié, on change son status et le titre de la fenêtre
self.documentActif.aSauvegarder = True
self.definirTitre()
|
Elle est appelé lorsque le signal 'changed' est émit. Dans cette méthode, on change l'attribut aSauvegarder du document actif pour True et on change le titre de la fenêtre (cela ajoute la petite étoile signifiant que le fichier a été modifié).
Voyons maintenant la méthode
self.definirTitre() :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12 | def definirTitre(self):
titre = ''
if self.documentActif.chemin != '':
#Si un document est ouvert, on affiche son nom
titre = os.path.basename(self.documentActif.chemin)
else:
#Si c'est un nouveau document, on affiche 'Nouveau document'
titre = 'Nouveau document'
if self.documentActif.aSauvegarder:
#S'il est modifié, on ajoute une étoile
titre = '*' + titre
self.fenetre.set_title(titre)
|
Si le fichier ouvert existe sur l'ordinateur, le titre devient le nom de ce fichier, sinon, on l'appelle 'Nouveau document'. S'il est modifié, on ajoute une étoile. Finalement, on change le titre de la fenêtre.
Voilà maintenant une méthode très importante dans un éditeur de texte, la méthode
self.enregistrer() :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 | def enregistrer(self, widget):
#Retourne False si l'utilisateur n'effectue pas la sauvegarde, sinon retourne True
if self.documentActif != None:
if self.documentActif.aSauvegarder:
if self.documentActif.chemin == '':
#Si un document est ouvert, modifié et n'existe pas dans l'ordinateur, on affiche la boîte de dialogue Enregistrer sous
sauvegarderFichierDialogue = gtk.FileChooserDialog("Enregistrer sous...", self.fenetre, gtk.FILE_CHOOSER_ACTION_SAVE, ((gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)))
sauvegarderFichierDialogue.set_do_overwrite_confirmation(True)
reponse = sauvegarderFichierDialogue.run()
if reponse == gtk.RESPONSE_OK:
nomFichier = sauvegarderFichierDialogue.get_filename()
self.documentActif.chemin = nomFichier
sauvegarderFichierDialogue.destroy()
elif reponse == gtk.RESPONSE_CANCEL:
sauvegarderFichierDialogue.destroy()
return False
if self.documentActif.chemin != '':
fichier = open(self.documentActif.chemin, 'w') #On ouvre le fichier
#On obtient le texte de la zone de texte
tampon = self.documentActif.zoneTexteDocument.get_buffer()
debut = tampon.get_start_iter()
fin = tampon.get_end_iter()
texte = tampon.get_text(debut, fin, True)
#On enregistre le fichier
fichier.write(texte)
fichier.close()
#Il n'est plus à sauvegarder, donc on change le titre (plus d'étoile)
self.documentActif.aSauvegarder = False
self.definirTitre()
return True
else:
if self.fenetre.get_title() == 'Nouveau document':
#Si le document n'est pas modifié, mais que c'est un nouveau document, on peut l'enregistrer
self.documentActif.aSauvegarder = True
if not self.enregistrer(None):
#Si l'utilisateur ne le sauvegarde pas
self.documentActif.aSauvegarder = False
self.definirTitre()
else:
self.afficherAvertissement("Il n'y a aucun document ouvert.")
|
Voyons cette méthode bloc par bloc ; ce sera plus facile à expliquer.
Code : Python1
2
3
4 | if self.documentActif != None:
[...]
else:
self.afficherAvertissement("Il n'y a aucun document ouvert.")
|
Premièrement, il faut qu'un document soit ouvert, sinon, on affiche un avertissement.
Voici le code qui suit :
Code : Python1
2
3
4
5
6
7
8
9 | if self.documentActif.aSauvegarder:
[...]
else:
if self.fenetre.get_title() == 'Nouveau document':
#Si le document n'est pas modifié, mais que c'est un nouveau document, on peut l'enregistrer
self.documentActif.aSauvegarder = True
if not self.enregistrer(None):
#Si l'utilisateur ne le sauvegarde pas
self.documentActif.aSauvegarder = False
|
Deuxièmement, si le fichier n'est pas modifié, on vérifie si c'est un nouveau document ; si c'est le cas, on indique qu'il est à sauvegarder et on appelle cette même méthode. S'il a changé d'avis et ne veut pas enregistrer, on remet l'attribut
aSauvegarder à False (pour qu'il n'y ait pas d'étoile dans le titre ; j'en ai eu des problèmes avec cette fichue étoile

).
La suite est :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13 | if self.documentActif.chemin == '':
#Si un document est ouvert, modifié et n'existe pas dans l'ordinateur, on affiche la boîte de dialogue Enregistrer sous
sauvegarderFichierDialogue = gtk.FileChooserDialog("Enregistrer sous...", self.fenetre, gtk.FILE_CHOOSER_ACTION_SAVE, ((gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)))
sauvegarderFichierDialogue.set_do_overwrite_confirmation(True)
reponse = sauvegarderFichierDialogue.run()
if reponse == gtk.RESPONSE_OK:
nomFichier = sauvegarderFichierDialogue.get_filename()
self.documentActif.chemin = nomFichier
sauvegarderFichierDialogue.destroy()
elif reponse == gtk.RESPONSE_CANCEL:
sauvegarderFichierDialogue.destroy()
return False
|
Après, on vérifie que le fichier existe sur le disque dur ; si ce n'est pas le cas, on affiche une boîte de dialogue dans laquelle on demande à l'utilisateur le nom du fichier à enregistrer. N'oubliez pas d'appeler la méthode
sauvegarderFichierDialogue.set_do_overwrite_confirmation(True) (au début, je l'avais oublié celle-là ; j'avais donc recréé cette méthode, mais ça fonctionnait

)
Ici, on n'enregistre pas tout de suite le fichier, on indique seulement son chemin.
Et enfin :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | if self.documentActif.chemin != '':
fichier = open(self.documentActif.chemin, 'w') #On ouvre le fichier
#On obtient le texte de la zone de texte
tampon = self.documentActif.zoneTexteDocument.get_buffer()
debut = tampon.get_start_iter()
fin = tampon.get_end_iter()
texte = tampon.get_text(debut, fin, True)
#On enregistre le fichier
fichier.write(texte)
fichier.close()
#Il n'est plus à sauvegarder, donc on change le titre (plus d'étoile)
self.documentActif.aSauvegarder = False
self.definirTitre()
return True
|
C'est dans cette condition-là qu'on enregistre : d'abord, on ouvre le fichier, ensuite, on récupère le contenu du gtk.TextView(), on écrit dans le fichier, on change l'attribut aSauvegarder et le titre (pour enlever l'étoile).
Il ne reste pas beaucoup de méthode, allez courage

(je commence à avoir mal au doigt, vous savez

)
Voici la méthode self.enregistrerSous() :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | def enregistrerSous(self, widget):
if self.documentActif != None: #Si un document est ouvert
#On enregistre des informations temporaires au cas où l'utilisateur annulerait la sauvegarde
cheminTemp = self.documentActif.chemin
aSauvegarderTemp = self.documentActif.aSauvegarder
#On change le chemin pour '' et aSauvegarde pour True pour que l'enregistrement se fasse dans un autre fichier (enregistrer sous)
self.documentActif.chemin = ''
self.documentActif.aSauvegarder = True
if not self.enregistrer(widget): #Si l'utilisateur annule l'enregistrement, on remet les informations d'avant
self.documentActif.chemin = cheminTemp
self.documentActif.aSauvegarder = aSauvegarderTemp
self.definirTitre() #et on remet le titre (parce qu'on le change après l'enregistrement)
else:
self.afficherAvertissement("Il n'y a aucun document ouvert.")
|
Si aucun document n'est ouvert, on affiche un avertissement !
Sinon, on enregistre les attributs du document dans des variables temporaires, car on doit les changer pour appeler la méthode self.enregistrer(). En effet, si le chemin vaut '' et que aSauvegarder, True, cette méthode affiche la boîte de dialogue 'Enregistrer sous...'.
Par contre, si aucun enregistrement n'est effectué, on remet leur valeur initiale au attributs changés. On le sait grâce à ce que retourne la méthode self.enregistrer().
Voilà maintenant la méthode self.quitter() :
Code : Python1
2
3
4
5
6
7
8 | def quitter(self, widget, evenement = None):
if self.documentActif != None:
if not self.fermer(None) == False:
#Si un document est ouvert, mais qu'il est fermé après, on quitter
gtk.main_quit()
else:
#Si aucun document est ouvert, on quitte
gtk.main_quit()
|
Elle est appelée non seulement lorsque l'utilisateur clique sur le menu Quitter, ou le bouton Quitter sur la barre d'outils, mais aussi si la méthode
self.detruireFen() revoie False (dans le cas où le fichier s'est fermé).
Si un document est ouvert, on essaie de le fermer, si ça fontionne, on quitte. Si aucun document n'est ouvert, on quitte aussi.
Pourquoi as-tu écrit "if not self.fermer(None) == False:" au lieu de "if self.fermer(None):", ça aurait été moins long, non ?
J'ai écrit "if not self.fermer(None) == False:" parce que la fonction ne renvoie pas True, j'aurais pu changé cela, en effet.
Voici la méthode
self.ouvrirFichier() :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | def ouvrirFichier(self, nomFichier):
#Cette méthode ressemble à la méthode self.nouveau()
#Création d'un objet DocumentOuvert() avec chemin
nouveau = DocumentOuvert()
nouveau.chemin = nomFichier
nouveau.ASauvegarder = False
self.documents.append(nouveau)
self.documentActif = nouveau
nouveau.zoneTexteDocument = gtk.TextView()
nouveau.zoneTexteDocument.show()
self.barresDefilement.add(nouveau.zoneTexteDocument)
tampon = nouveau.zoneTexteDocument.get_buffer()
fichier = open(nomFichier, 'r')
texteListe = fichier.readlines()
texte = ''.join(texteListe)
fichier.close()
#Comme on doit changer le texte pour celui du fichier, il faut bien faire attention à connecter le signal 'changed' APRÈS de l'avoir changer pour pas que l'attribut aSauvegarder devienne True
tampon.set_text(texte)
tampon.connect("changed", self.fichierModifie)
self.definirTitre()
|
Elle ressemble beaucoup à la méthode
self.nouveau(). Les seules différences sont que le document a un chemin et que la zone de texte a du texte.
Cette méthode est appelée par une autre,
self.ouvrirFichierDialogue :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | def ouvrirFichierDialogue(self, widget):
continuer = False
if self.documentActif != None:
if not self.fermer(None) == False:
#Si le document ouvert se ferme, on peut ouvrir la boîte de dialogue
continuer = True
else:
#Si aucun document est ouvert, on peut ouvrir la boîte de dialogue
continuer = True
if continuer:
ouvrirFichierDialogue = gtk.FileChooserDialog("Ouverture de fichiers", self.fenetre, gtk.FILE_CHOOSER_ACTION_OPEN, ((gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)))
reponse = ouvrirFichierDialogue.run()
if reponse == gtk.RESPONSE_OK:
nomFichier = ouvrirFichierDialogue.get_filename()
#On essaie d'ouvrir le fichier pour savoir s'il existe
try:
fichier = open(nomFichier)
except:
#Dans le cas où l'utilisateur aurait taper le nom du fichier et que celui-ci n'existerait pas, on affiche une erreur
self.afficherErreur('Le fichier <b>' + os.path.basename(nomFichier) + '</b> n\'existe pas.', True)
else:
#S'il existe, on l'ouvre
fichier.close()
self.ouvrirFichier(nomFichier)
ouvrirFichierDialogue.destroy()
|
Si aucun document n'est ouvert, on passe à la suite, sinon, il faut l'enregistrer. Si l'enregistrement s'effectue correctement, on continue aussi.
Si l'utilisateur ouvre un fichier, on vérifie qu'il existe bien (avec les exceptions), s'il n'existe pas, on affiche une erreur.
Voici les dernières méthodes, dont une inutilisée qui pourra servir plus tard :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 | def afficherInformation(self, texte, use_markup = False):
"Affiche une information (non utilisée)"
if use_markup:
#Si use_markup vaut True, on insère le texte avec set_markup()
infoDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK)
infoDialogue.set_markup(texte)
else:
infoDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, texte)
infoDialogue.set_title("Information")
infoDialogue.run()
infoDialogue.destroy()
def afficherAvertissement(self, texte, use_markup = False):
"Affiche un avertissement"
if use_markup:
avertissementDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK)
avertissementDialogue.set_markup(texte)
else:
avertissementDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, texte)
avertissementDialogue.set_title("Avertissement")
avertissementDialogue.run()
avertissementDialogue.destroy()
def afficherErreur(self, texte, use_markup = False):
"Affiche une erreur"
if use_markup:
erreurDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK)
erreurDialogue.set_markup(texte)
else:
erreurDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, texte)
erreurDialogue.set_title("Erreur")
erreurDialogue.run()
erreurDialogue.destroy()
erreurDialogue.destroy()
|
La seule chose de différent par rapport à d'habitude, c'est que si le paramètre
use_markup vaut True, on affiche le texte avec la méthode
set_markup().
Voici le code complet (je le donne, car il y a un problème avec les tabulations) :
Code : Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298 | # -*- coding:Utf-8 -*-
import pygtk
pygtk.require("2.0")
import gtk
import os
class DocumentOuvert():
"Objet qui contient des informations sur un fichier ouvert"
def __init__(self):
self.chemin = ''
self.aSauvegarder = False
self.zoneTexteDocument = None
class PyGtkApp:
def __init__(self):
#Création de la fenêtre principale à partie d'un fichier glade
interface = gtk.Builder()
interface.add_from_file('fenetre.glade')
self.fenetre = interface.get_object("fenetre")
self.barresDefilement = interface.get_object('barresDefilement')
interface.connect_signals(self)
self.fenetre.maximize()
self.documents = [] #Liste des documents ouverts
self.documentActif = None #Le document actif (objet DocumentOuvert())
def detruireFen(self, widget, evenement):
"Lorsque la fenêtre est détruite"
if self.documentActif != None:
if not self.fermer(None) == False:
return False #Si le document est bien fermé, on peut fermer la fenêtre
else:
return False #Si aucun document n'est actif, on peut aussi la fermer
return True #Sinon, on la laisse ouverte
def aPropos(self, widget):
"Dialogue À propos"
pixbuf = gtk.gdk.pixbuf_new_from_file("editeurDeTexteIco.png")
aPropos = gtk.AboutDialog()
aPropos.set_icon_from_file("editeurDeTexteIco.png")
aPropos.set_name("Éditeur de texte")
aPropos.set_version("1.0")
aPropos.set_copyright("Copyright © 2009, tous droits réservés")
aPropos.set_comments(aPropos.get_name() + " " + aPropos.get_version() +" est un éditeur de texte basique.")
aPropos.set_license("Copyright © 2009 antoyo\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License along\nwith this program; if not, write to the Free Software Foundation, Inc.,\n51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.")
auteurs = ["Antoyo"]
aPropos.set_authors(auteurs)
aPropos.set_logo(pixbuf)
reponse = aPropos.run()
aPropos.destroy()
def fermer(self, widget):
"Fermeture d'un fichier" #Dans cette fonction, si le retour est False, cela indique qu'il n'y a pas eu de fermeture
if self.documentActif != None: #S'il y a un document actif
if self.documentActif.aSauvegarder: #Si il est modifié
#On crée un boîte de dialogue pour demander à l'utilisateur s'il veut enregistrer les modifications ou non ou bien annuler la fermeture
fermetureDialogue = gtk.Dialog("Enregistrer", self.fenetre, 0, (gtk.STOCK_YES, gtk.RESPONSE_YES, gtk.STOCK_NO, gtk.RESPONSE_NO, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
etiquette = gtk.Label('Voulez-vous enregistrer les modifications ?')
boiteH = gtk.HBox()
fermetureDialogue.vbox.pack_start(boiteH, False)
stock = gtk.image_new_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG)
boiteH.pack_start(stock, False)
boiteH.pack_start(etiquette, False)
fermetureDialogue.show_all()
reponse = fermetureDialogue.run()
if reponse == gtk.RESPONSE_YES:
if self.enregistrer(None):
#Si l'utilisateur appuie sur Oui et qu'il enregistre le document, on peut le fermer
self.documentActif.zoneTexteDocument.destroy()
self.documents.remove(self.documentActif)
self.documentActif = None
else:
#S'il ne l'enregistre pas, on ferme la boîte de dialogue
fermetureDialogue.destroy()
return False
self.fenetre.set_title('Éditeur de texte en PyGtk') #On remet le titre à la fenêtre
elif reponse == gtk.RESPONSE_NO:
#S'il appuie sur Non, on ferme le document sans enregistrer
self.documentActif.zoneTexteDocument.destroy()
self.documents.remove(self.documentActif)
self.documentActif = None
self.fenetre.set_title('Éditeur de texte en PyGtk')
elif reponse == gtk.RESPONSE_CANCEL:
#S'il appuie sur Annuler, on fermer seulement la boîte de dialogue
fermetureDialogue.destroy()
return False
fermetureDialogue.destroy()
else:
self.documentActif.zoneTexteDocument.destroy()
self.documents.remove(self.documentActif)
self.documentActif = None
self.fenetre.set_title('Éditeur de texte en PyGtk')
else:
self.afficherAvertissement("Il n'y a aucun document ouvert.")
def nouveau(self, widget):
"Création d'un nouveau document"
if self.documentActif == None: #On le crée seulement s'il n'y en a pas déjà un d'ouvert
#Création d'un objet DocumentOuvert() sans chemin
nouveau = DocumentOuvert()
nouveau.chemin = ''
nouveau.ASauvegarder = False
#Le chemin vaut '' et il n'est pas à sauvegarder
self.documents.append(nouveau) #On l'ajoute à la liste
self.documentActif = nouveau #Et c'est le document actif
nouveau.zoneTexteDocument = gtk.TextView() #On crée une nouvelle zone de texte
tampon = nouveau.zoneTexteDocument.get_buffer()
tampon.connect("changed", self.fichierModifie) #On récupère le tampon pour savoir quand il est modifié
self.barresDefilement.add(nouveau.zoneTexteDocument)
nouveau.zoneTexteDocument.show()
self.definirTitre()
else:
self.afficherAvertissement("Il y a déjà un document ouvert.")
def fichierModifie(self, widget):
#Si un fichier est modifié, on change son status et le titre de la fenêtre
self.documentActif.aSauvegarder = True
self.definirTitre()
def definirTitre(self):
titre = ''
if self.documentActif.chemin != '':
#Si un document est ouvert, on affiche son nom
titre = os.path.basename(self.documentActif.chemin)
else:
#Si c'est un nouveau document, on affiche 'Nouveau document'
titre = 'Nouveau document'
if self.documentActif.aSauvegarder:
#S'il est modifié, on ajoute une étoile
titre = '*' + titre
self.fenetre.set_title(titre)
def enregistrer(self, widget):
#Retourne False si l'utilisateur n'effectue pas la sauvegarde, sinon retourne True
if self.documentActif != None:
if self.documentActif.aSauvegarder:
if self.documentActif.chemin == '':
#Si un document est ouvert, modifié et n'existe pas dans l'ordinateur, on affiche la boîte de dialogue Enregistrer sous
sauvegarderFichierDialogue = gtk.FileChooserDialog("Enregistrer sous...", self.fenetre, gtk.FILE_CHOOSER_ACTION_SAVE, ((gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)))
sauvegarderFichierDialogue.set_do_overwrite_confirmation(True)
reponse = sauvegarderFichierDialogue.run()
if reponse == gtk.RESPONSE_OK:
nomFichier = sauvegarderFichierDialogue.get_filename()
self.documentActif.chemin = nomFichier
sauvegarderFichierDialogue.destroy()
elif reponse == gtk.RESPONSE_CANCEL:
sauvegarderFichierDialogue.destroy()
return False
if self.documentActif.chemin != '':
fichier = open(self.documentActif.chemin, 'w') #On ouvre le fichier
#On obtient le texte de la zone de texte
tampon = self.documentActif.zoneTexteDocument.get_buffer()
debut = tampon.get_start_iter()
fin = tampon.get_end_iter()
texte = tampon.get_text(debut, fin, True)
#On enregistre le fichier
fichier.write(texte)
fichier.close()
#Il n'est plus à sauvegarder, donc on change le titre (plus d'étoile)
self.documentActif.aSauvegarder = False
self.definirTitre()
return True
else:
if self.fenetre.get_title() == 'Nouveau document':
#Si le document n'est pas modifié, mais que c'est un nouveau document, on peut l'enregistrer
self.documentActif.aSauvegarder = True
if not self.enregistrer(None):
#Si l'utilisateur ne le sauvegarde pas
self.documentActif.aSauvegarder = False
self.definirTitre()
else:
self.afficherAvertissement("Il n'y a aucun document ouvert.")
def enregistrerSous(self, widget):
if self.documentActif != None: #Si un document est ouvert
#On enregistre des informations temporaires au cas où l'utilisateur annulerait la sauvegarde
cheminTemp = self.documentActif.chemin
aSauvegarderTemp = self.documentActif.aSauvegarder
#On change le chemin pour '' et aSauvegarde pour True pour que l'enregistrement se fasse dans un autre fichier (enregistrer sous)
self.documentActif.chemin = ''
self.documentActif.aSauvegarder = True
if not self.enregistrer(widget): #Si l'utilisateur annule l'enregistrement, on remet les informations d'avant
self.documentActif.chemin = cheminTemp
self.documentActif.aSauvegarder = aSauvegarderTemp
self.definirTitre() #et on remet le titre (parce qu'on le change après l'enregistrement)
else:
self.afficherAvertissement("Il n'y a aucun document ouvert.")
def quitter(self, widget, evenement = None):
if self.documentActif != None:
if not self.fermer(None) == False:
#Si un document est ouvert, mais qu'il est fermé après, on quitter
gtk.main_quit()
else:
#Si aucun document est ouvert, on quitte
gtk.main_quit()
def ouvrirFichier(self, nomFichier):
#Cette méthode ressemble à la méthode self.nouveau()
#Création d'un objet DocumentOuvert() avec chemin
nouveau = DocumentOuvert()
nouveau.chemin = nomFichier
nouveau.ASauvegarder = False
self.documents.append(nouveau)
self.documentActif = nouveau
nouveau.zoneTexteDocument = gtk.TextView()
nouveau.zoneTexteDocument.show()
self.barresDefilement.add(nouveau.zoneTexteDocument)
tampon = nouveau.zoneTexteDocument.get_buffer()
fichier = open(nomFichier, 'r')
texteListe = fichier.readlines()
texte = ''.join(texteListe)
fichier.close()
#Comme on doit changer le texte pour celui du fichier, il faut bien faire attention à connecter le signal 'changed' APRÈS de l'avoir changer pour pas que l'attribut aSauvegarder devienne True
tampon.set_text(texte)
tampon.connect("changed", self.fichierModifie)
self.definirTitre()
def ouvrirFichierDialogue(self, widget):
continuer = False
if self.documentActif != None:
if not self.fermer(None) == False:
#Si le document ouvert se ferme, on peut ouvrir la boîte de dialogue
continuer = True
else:
#Si aucun document est ouvert, on peut ouvrir la boîte de dialogue
continuer = True
if continuer:
ouvrirFichierDialogue = gtk.FileChooserDialog("Ouverture de fichiers", self.fenetre, gtk.FILE_CHOOSER_ACTION_OPEN, ((gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)))
reponse = ouvrirFichierDialogue.run()
if reponse == gtk.RESPONSE_OK:
nomFichier = ouvrirFichierDialogue.get_filename()
#On essaie d'ouvrir le fichier pour savoir s'il existe
try:
fichier = open(nomFichier)
except:
#Dans le cas où l'utilisateur aurait taper le nom du fichier et que celui-ci n'existerait pas, on affiche une erreur
self.afficherErreur('Le fichier <b>' + os.path.basename(nomFichier) + '</b> n\'existe pas.', True)
else:
#S'il existe, on l'ouvre
fichier.close()
self.ouvrirFichier(nomFichier)
ouvrirFichierDialogue.destroy()
def afficherInformation(self, texte, use_markup = False):
"Affiche une information (non utilisée)"
if use_markup:
#Si use_markup vaut True, on insère le texte avec set_markup()
infoDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK)
infoDialogue.set_markup(texte)
else:
infoDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, texte)
infoDialogue.set_title("Information")
infoDialogue.run()
infoDialogue.destroy()
def afficherAvertissement(self, texte, use_markup = False):
"Affiche un avertissement"
if use_markup:
avertissementDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK)
avertissementDialogue.set_markup(texte)
else:
avertissementDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, texte)
avertissementDialogue.set_title("Avertissement")
avertissementDialogue.run()
avertissementDialogue.destroy()
def afficherErreur(self, texte, use_markup = False):
"Affiche une erreur"
if use_markup:
erreurDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK)
erreurDialogue.set_markup(texte)
else:
erreurDialogue = gtk.MessageDialog(self.fenetre, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, texte)
erreurDialogue.set_title("Erreur")
erreurDialogue.run()
erreurDialogue.destroy()
erreurDialogue.destroy()
PyGtkApp()
gtk.main()
|
Voilà, vous savez maintenant comment faire un éditeur de texte assez simple. Après le chapitre 8, vous pourrez le terminer pour qu'il ait un panneau, des onglets et l'impression des fichiers.