Move the module qdoc files from qtdoc and split up doc/src.
[profile/ivi/qtbase.git] / doc / src / widgets / addressbook-fr.qdoc
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the documentation of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:FDL$
10 ** GNU Free Documentation License
11 ** Alternatively, this file may be used under the terms of the GNU Free
12 ** Documentation License version 1.3 as published by the Free Software
13 ** Foundation and appearing in the file included in the packaging of
14 ** this file.
15 **
16 ** Other Usage
17 ** Alternatively, this file may be used in accordance with the terms
18 ** and conditions contained in a signed written agreement between you
19 ** and Nokia.
20 **
21 **
22 **
23 **
24 ** $QT_END_LICENSE$
25 **
26 ****************************************************************************/
27
28 /*!
29     \page tutorials-addressbook-fr.html
30
31     \title Tutoriel "Carnet d'adresses"
32     \brief Une introduction à la programation d'interface graphique montrant comment construire une application simple avec Qt.
33
34     Ce tutoriel est une introduction à la programmation de GUI (interface utilisateur)
35     à l'aide des outils fournis par la plateforme multiplate-forme Qt.
36
37     \image addressbook-tutorial-screenshot.png
38
39     Ce tutoriel va nous amener à découvrir quelques technologies fondamentales fournies 
40     par Qt, tel que:
41
42     \list
43     \o Les Widgets et leur mise en page à l'aide des layouts
44     \o Les signaux et slots
45     \o Les structures de données de collections
46     \o Les entrées/sorties
47     \endlist
48
49     Si c'est votre premier contact avec Qt, lisez \l{How to Learn Qt}{Comment apprendre Qt}
50     si ce n'est déjà fait.
51
52     Le code source du tutoriel est distribué avec Qt dans le dossier \c examples/tutorials/addressbook
53
54     Les chapitres du tutoriel:
55
56     \list 1
57     \o \l{tutorials/addressbook-fr/part1}{Conception de l'interface utilisateur}
58     \o \l{tutorials/addressbook-fr/part2}{Ajouter des adresses}
59     \o \l{tutorials/addressbook-fr/part3}{Navigation entre les éléments}
60     \o \l{tutorials/addressbook-fr/part4}{éditer et supprimer des adresses}
61     \o \l{tutorials/addressbook-fr/part5}{Ajout d'une fonction de recherche}
62     \o \l{tutorials/addressbook-fr/part6}{Sauvegarde et chargement}
63     \o \l{tutorials/addressbook-fr/part7}{Fonctionnalités avancées}
64     \endlist
65
66     La petite application que nous développerons ici ne possède pas tous les éléments
67     des interfaces dernier cri, elle va nous permettre d'utiliser les techniques de base
68     utilisées dans les applications plus complexes.
69
70     Lorsque vous aurez terminé ce tutoriel, nous vous recommandons de poursuivre avec l'exemple
71     "\l{mainwindows/application}{Application}", qui présente une interface simple utilisant
72     les menus et barres d'outils, la barre d'état, etc.
73
74 */
75
76 /*!
77     \page tutorials-addressbook-fr-part1.html
78
79     \example tutorials/addressbook-fr/part1
80     \title Carnet d'adresses 1 - Conception de l'interface utilisateur
81
82     La première partie de ce tutoriel traite de la conception d'une interface graphique
83     (GUI) basique, que l'on utilisera pour l'application Carnet d'adresses.
84
85     La première étape dans la création d'applications graphiques est la conception de
86     l'interface utilisateur. Dans ce chapitre, nous verrons comment créer les labels
87     et champs de saisie nécessaires à l'implementation d'un carnet d'adresses de base.
88     Le résultat attendu est illustré par la capture d'écran ci-dessous.
89
90     \image addressbook-tutorial-part1-screenshot.png
91
92     Nous allons avoir besoin de deux objets QLabel, \c nameLabel et \c addressLabel,
93     ainsi que deux champs de saisie: un objet QLineEdit, \c nameLine, et un objet
94     QTextEdit, \c addressText, afin de permettre à l'utilisateur d'entrer le nom d'un
95     contact et son adresse. Les widgets utilisés ainsi que leur placement sont visibles ci-dessous.
96
97     \image addressbook-tutorial-part1-labeled-screenshot.png
98
99     Trois fichiers sont nécessaires à l'implémentation de ce carnet d'adresses:
100
101     \list
102         \o \c{addressbook.h} - le fichier de définition (header) pour la classe \c AddressBook,
103         \o \c{addressbook.cpp} - le fichier source, qui comprend l'implémentation de la classe
104             \c AddressBook
105         \o \c{main.cpp} - le fichier qui contient la méthode \c main() , et
106         une instance de la classe \c AddressBook.
107     \endlist
108
109     \section1 Programmation en Qt - héritage
110
111
112     Lorsque l'on écrit des programmes avec Qt, on a généralement recours à
113     l'héritage depuis des objets Qt, afin d'y ajouter des fonctionnalités.
114     C'est l'un des concepts fondamentaux de la création de widgets personnalisés
115     ou de collections de widgets. Utiliser l'héritage afin de compléter
116     ou modifier le comportement d'un widget présente les avantages suivants:
117
118     \list
119     \o La possibilité d'implémenter des méthodes virtuelles et des méthodes 
120     virtuelles pures pour obtenir exactement ce que l'on souhaite, avec la possibilité
121     d'utiliser l'implémentation de la classe mère si besoin est.
122     \o Cela permet l'encapsulation partielle de l'interface utilisateur dans une classe,
123     afin que les autres parties de l'application n'aient pas à se soucier de chacun des
124     widgets qui forment l'interface utilisateur.
125     \o La classe fille peut être utilisée pour créer de nombreux widgets personnalisés
126     dans une même application ou bibliothèque, et le code de la classe fille peut être
127     réutilisé dans d'autres projets
128     \endlist
129
130     Comme Qt ne fournit pas de widget standard pour un carnet d'adresses, nous 
131     partirons d'une classe de widget Qt standard et y ajouterons des fonctionnalités.
132     La classe \c AddressBook crée dans ce tutoriel peut être réutilisée si on a besoin d'un
133     widget carnet d'adresses basique.
134
135
136     \section1 La classe AddressBook
137
138     Le fichier \l{tutorials/addressbook-fr/part1/addressbook.h}{\c addressbook.h} permet de
139     définir la classe \c AddressBook.
140
141     On commence par définir \c AddressBook comme une classe fille de QWidget et déclarer
142     un constructeur. On utilise également la macro Q_OBJECT pour indiquer que la classe
143     exploite les fonctionnalités de signaux et slots offertes par Qt ainsi que
144     l'internationalisation, bien que nous ne les utilisions pas à ce stade.
145
146     \snippet tutorials/addressbook-fr/part1/addressbook.h class definition
147
148     La classe contient les déclarations de \c nameLine et \c addressText,
149     les instances privées de QLineEdit et QTextEdit mentionnées précédemment.
150     Vous verrez, dans les chapitres à venir que les informations contenues
151     dans \c nameLine et \c addressText sont nécessaires à de nombreuses méthodes
152     du carnet d'adresses.
153
154     Il n'est pas nécessaire de déclarer les objets QLabel que nous allons utiliser 
155     puisque nous n'aurons pas besoin d'y faire référence après leur création.
156     La façon dont Qt gère la parenté des objets est traitée dans la section suivante.
157
158     La macro Q_OBJECT implémente des fonctionnalités parmi les plus avancées de Qt.
159     Pour le moment, il est bon de voir la macro Q_OBJECT comme un raccourci nous 
160     permettant d'utiliser les méthodes \l{QObject::}{tr()} et \l{QObject::}{connect()}.
161
162     Nous en avons maintenant terminé avec le fichier \c addressbook.h et allons
163     passer à l'implémentation du fichier \c addressbook.cpp.
164
165     \section1 Implémentation de la classe AddressBook
166
167     Le constructeur de la classe \c{AddressBook} prend en paramètre un QWidget, \e parent.
168     Par convention, on passe ce paramètre au constructeur de la classe mère.
169     Ce concept de parenté, où un parent peut avoir un ou plusieurs enfants, est utile
170     pour regrouper les Widgets avec Qt. Par exemple, si vous détruisez le parent,
171     tous ses enfants seront détruits égalament.
172
173
174     \snippet tutorials/addressbook/part1/addressbook.cpp constructor and input fields
175
176     à l'intérieur de ce constructeur, on déclare et instancie deux objets locaux
177     QLabel, \c nameLabel et \c addressLabel, de même on instancie \c nameLine et
178     \c addressText. La méthode \l{QObject::tr()}{tr()} renvoie une version traduite
179     de la chaîne de caractères, si elle existe; dans le cas contraire, elle renvoie
180     la chaîne elle même. On peut voir cette méthode comme un marqueur \tt{<insérer
181     la traduction ici>}, permettant de repérer les objets QString à considérer
182     pour traduire une application. Vous remarquerez, dans les chapitres à venir
183     comme dans les \l{Qt Examples}{exemples Qt}, qu'elle est utilisée chaque fois
184     que l'on utilise une chaîne susceptible d'être traduite.
185
186     Lorsque l'on programme avec Qt, il est utile de savoir comment fonctionnent les
187     agencements ou layouts. Qt fournit trois classes principales de layouts pour
188     contrôler le placement des widgets: QHBoxLayout, QVBoxLayout et QGridLayout.
189
190     \image addressbook-tutorial-part1-labeled-layout.png
191
192     On utilise un QGridLayout pour positionner nos labels et champs de saisie de manière
193     structurée. QGridLayout divise l'espace disponible en une grille, et place les
194     widgets dans les cellules que l'on spécifie par les numéros de ligne et de colonne.
195     Le diagramme ci-dessus présente les cellules et la position des widgets, et cette
196     organisation est obtenue à l'aide du code suivant:
197
198     \snippet tutorials/addressbook/part1/addressbook.cpp layout
199
200     On remarque que le label \c AddressLabel est positionné en utilisant Qt::AlignTop
201     comme argument optionnel. Ceci est destiné à assurer qu'il ne sera pas centré
202     verticalement dans la cellule (1,0). Pour un aperçu rapide des layouts de Qt,
203     consultez la section \l{Layout Management}.
204
205     Afin d'installer l'objet layout dans un widget, il faut appeler la méthode
206     \l{QWidget::setLayout()}{setLayout()} du widget en question:
207
208     \snippet tutorials/addressbook/part1/addressbook.cpp setting the layout
209
210     Enfin, on initialise le titre du widget à "Simple Address Book"
211
212     \section1 Exécution de l'application
213
214     Un fichier séparé, \c main.cpp, est utilisé pour la méthode \c main(). Dans cette
215     fonction, on crée une instance de QApplication, \c app. QApplication se charge de
216     des ressources communes à l'ensemble de l'application, tel que les polices de
217     caractères et le curseur par défaut, ainsi que de l'exécution de la boucle d'évènements.
218     De ce fait, il y a toujours un objet QApplication dans toute application graphique en Qt.
219
220     \snippet tutorials/addressbook/part1/main.cpp main function
221
222     On construit un nouveau widget \c AddressBook sur la pile et on invoque
223     sa méthode \l{QWidget::show()}{show()} pour l'afficher.
224     Cependant, le widget ne sera pas visible tant que la boucle d'évènements
225     n'aura pas été lancée. On démarre la boucle d'évènements en appelant la
226     méthode \l{QApplication::}{exec()} de l'application; le résultat renvoyé
227     par cette méthode est lui même utilisé comme valeur de retour pour la méthode
228     \c main().
229     On comprend maintenant pourquoi \c AddressBook a été créé sur la pile: à la fin
230     du programme, l'objet sort du scope de la fonction \c main() et tous ses widgets enfants
231     sont supprimés, assurant ainsi qu'il n'y aura pas de fuites de mémoire.
232 */
233
234 /*!
235     \page tutorials-addressbook-fr-part2.html
236
237     \example tutorials/addressbook-fr/part2
238     \title Carnet d'adresses 2 - Ajouter des adresses
239
240     La prochaine étape pour créer notre carnet d'adresses est d'ajouter un soupçon
241     d'interactivité.
242
243     \image addressbook-tutorial-part2-add-contact.png
244
245     Nous allons fournir un bouton que l'utilisateur peut
246     cliquer pour ajouter un nouveau contact. Une structure de données est aussi
247     nécessaire afin de pouvoir stocker les contacts en mémoire.
248
249     \section1 Définition de la classe AddressBook
250
251     Maintenant que nous avons mis en place les labels et les champs de saisie,
252     nous ajoutons les boutons pour compléter le processus d'ajout d'un contact.
253     Cela veut dire que notre fichier \c addressbook.h a maintenant trois
254     objets QPushButton et trois slots publics correspondant.
255
256     \snippet tutorials/addressbook/part2/addressbook.h slots
257
258     Un slot est une méthode qui répond à un signal. Nous allons
259     voir ce concept en détail lorsque nous implémenterons la classe \c{AddressBook}.
260     Pour une explication détaillée du concept de signal et slot, vous pouvez
261     vous référer au document \l{Signals and Slots}.
262
263     Les trois objets QPushButton \c addButton, \c submitButton et \c cancelButton
264     sont maintenant inclus dans la déclaration des variables privées, avec
265     \c nameLine et \c addressText du chapitre précédent.
266
267     \snippet tutorials/addressbook/part2/addressbook.h pushbutton declaration
268
269     Nous avons besoin d'un conteneur pour stocker les contacts du carnet
270     d'adresses, de façon à pouvoir les énumérer et les afficher.
271     Un objet QMap, \c contacts, est utilisé pour ça, car il permet de stocker
272     des paires clé-valeur: le nom du contact est la \e{clé} et l'adresse du contact
273     est la \e{valeur}.
274
275     \snippet tutorials/addressbook/part2/addressbook.h remaining private variables
276
277     Nous déclarons aussi deux objects QString privés: \c oldName et \c oldAddress.
278     Ces objets sont nécessaires pour conserver le nom et l'adresse du dernier contact
279     affiché avant que l'utilisateur ne clique sur le bouton "Add". Grâce à ces variables
280     si l'utilisateur clique sur "Cancel", il est possible de revenir
281     à l'affichage du dernier contact.
282
283     \section1 Implémentation de la classe AddressBook
284
285     Dans le constructeur de \c AddressBook, \c nameLine et
286     \c addressText sont mis en mode lecture seule, de façon à autoriser l'affichage
287     mais pas la modification du contact courant.
288
289     \dots
290     \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 1
291     \dots
292     \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 2
293
294     Ensuite, nous instancions les boutons \c addButton, \c submitButton, et
295     \c cancelButton.
296
297     \snippet tutorials/addressbook/part2/addressbook.cpp pushbutton declaration
298
299     Le bouton \c addButton est affiché en invoquant la méthode \l{QPushButton::show()}
300     {show()}, tandis que \c submitButton et \c cancelButton sont cachés en invoquant
301     \l{QPushButton::hide()}{hide()}. Ces deux boutons ne seront affichés que lorsque 
302     l'utilisateur cliquera sur "Add", et ceci est géré par la méthode \c addContact()
303     décrite plus loin.
304
305     \snippet tutorials/addressbook/part2/addressbook.cpp connecting signals and slots
306
307     Nous connectons le signal \l{QPushButton::clicked()}{clicked()} de chaque bouton 
308     au slot qui gèrera l'action.
309     L'image ci-dessous illustre ceci:
310
311     \image addressbook-tutorial-part2-signals-and-slots.png
312
313     Ensuite, nous arrangeons proprement les boutons sur la droite du widget
314     AddressBook, et nous utilisons un QVBoxLayout pour les aligner verticalement.
315
316     \snippet tutorials/addressbook/part2/addressbook.cpp vertical layout
317
318     La methode \l{QBoxLayout::addStretch()}{addStretch()} est utilisée pour
319     assurer que les boutons ne sont pas répartis uniformément, mais regroupés
320     dans la partie supperieure du widget. La figure ci-dessous montre la différence
321     si \l{QBoxLayout::addStretch()}{addStretch()} est utilisé ou pas.
322
323     \image addressbook-tutorial-part2-stretch-effects.png
324
325     Ensuite nous ajoutons \c buttonLayout1 à \c mainLayout, en utilisant
326     \l{QGridLayout::addLayout()}{addLayout()}. Ceci nous permet d'imbriquer les
327     mises en page puisque \c buttonLayout1 est maintenant un enfant de \c mainLayout.
328
329     \snippet tutorials/addressbook/part2/addressbook.cpp grid layout
330
331     Les coordonnées du layout global ressemblent maintenant à ça:
332
333     \image addressbook-tutorial-part2-labeled-layout.png
334
335     Dans la méthode \c addContact(), nous stockons les détails du dernier
336     contact affiché dans \c oldName et \c oldAddress. Ensuite, nous
337     vidons ces champs de saisie et nous désactivons le mode
338     lecture seule. Le focus est placé sur \c nameLine et on affiche
339     \c submitButton et \c cancelButton.
340
341     \snippet tutorials/addressbook/part2/addressbook.cpp addContact
342
343     La méthode \c submitContact() peut être divisée en trois parties:
344
345     \list 1
346     \o Nous extrayons les détails du contact depuis \c nameLine et \c addressText
347     et les stockons dans des objets QString. Nous les validons pour s'assurer
348     que l'utilisateur n'a pas cliqué sur "Add" avec des champs de saisie
349     vides; sinon un message est affiché avec QMessageBox pour rappeller à
350     l'utilisateur que les deux champs doivent être complétés.
351
352     \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1
353
354     \o Ensuite, nous vérifions si le contact existe déjà. Si aucun contacts
355     existant n'entre en conflit avec le nouveau, nous l'ajoutons à
356     \c contacts et nous affichons un QMessageBox pour informer l'utilisateur
357     que le contact a été ajouté.
358
359     \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part2
360
361     Si le contact existe déjà, nous affichons un QMessageBox pour informer
362     l'utilisateur du problème.
363     Notre objet \c contacts est basé sur des paires clé-valeur formés par
364     le nom et l'adresse, nous voulons nous assurer que la \e clé est unique.
365
366     \o Une fois que les deux vérifications précédentes ont été traitées,
367     nous restaurons les boutons à leur état normal à l'aide du code
368     suivant:
369
370     \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part3
371
372     \endlist
373
374     La capture d'écran ci-dessous montre l'affichage fournit par un objet
375     QMessageBox, utilisé ici pour afficher un message d'information
376     à l'utilisateur:
377
378     \image addressbook-tutorial-part2-add-successful.png
379
380     La méthode \c cancel() restaure les détails du dernier contact, active
381     \c addButton, et cache \c submitButton et \c cancelButton.
382
383     \snippet tutorials/addressbook/part2/addressbook.cpp cancel
384
385     L'idée générale pour augmenter la flexibilité lors de l'ajout d'un 
386     contact est de donner la possiblité de cliquer sur "Add" 
387     ou "Cancel" à n'importe quel moment.
388     L'organigramme ci-dessous reprend l'ensemble des interactions dévelopées
389     jusqu'ici:
390
391     \image addressbook-tutorial-part2-add-flowchart.png
392 */
393
394 /*!
395     \page tutorials-addressbook-fr-part3.html
396
397     \example tutorials/addressbook-fr/part3
398     \title Carnet d'adresses 3 - Navigation entre les éléments
399
400     L'application "Carnet d'adresses" est maintenant à moitié terminée. Il
401     nous faut maintenant ajouter quelques fonctions pour naviguer entre
402     les contacts. Avant de commencer, il faut se décider sur le type de structure de
403     données le plus approprié pour stocker les contacts.
404
405     Dans le chapitre 2, nous avons utilisé un QMap utilisant des paires clé-valeur,
406     avec le nom du contact comme \e clé, et l'adresse du contact comme \e valeur.
407     Cela fonctionnait bien jusqu'ici, mais pour ajouter la navigation entre les
408     entrées, quelques améliorations sont nécessaires.
409
410     Nous améliorerons le QMap en le faisant ressembler à une structure de données
411     similaire à une liste liée, où tous les éléments sont connectés, y compris
412     le premier et le dernier élément. La figure ci-dessous illustre cette structure
413     de donnée.
414
415     \image addressbook-tutorial-part3-linkedlist.png
416
417     \section1 Définition de la classe AddressBook
418
419     Pour ajouter les fonctions de navigation au carnet d'adresses, nous avons
420     besoin de deux slots supplémentaires dans notre classe \c AddressBook:
421     \c next() et \c previous(). Ceux-ci sont ajoutés au fichier addressbook.h:
422
423     \snippet tutorials/addressbook/part3/addressbook.h navigation functions
424
425     Nous avons aussi besoin de deux nouveaux objets QPushButton, nous ajoutons
426     donc les variables privées \c nextButton et \c previousButton.
427
428     \snippet tutorials/addressbook/part3/addressbook.h navigation pushbuttons
429
430     \section1 Implémentation de la classe AddressBook
431
432     A l'intérieur du constructeur de \c AddressBook, dans \c addressbook.cpp, nous
433     instancions \c nextButton et \c previousButton et nous les désactivons
434     par défaut. Nous faisons ceci car la navigation ne doit être activée
435     que lorsqu'il y a plus d'un contact dans le carnet d'adresses.
436
437     \snippet tutorials/addressbook/part3/addressbook.cpp navigation pushbuttons
438
439     Nous connectons alors ces boutons à leur slots respectifs:
440
441     \snippet tutorials/addressbook/part3/addressbook.cpp connecting navigation signals
442
443     L'image ci-dessous montre l'interface utilisateur que nous allons créer.
444     Remarquez que cela ressemble de plus en plus à l'interface du programme
445     complet.
446
447     \image addressbook-tutorial-part3-screenshot.png
448
449     Nous suivons les conventions pour les fonctions \c next() et \c previous()
450     en plaçant \c nextButton à droite et \c previousButton à gauche. Pour
451     faire cette mise en page intuitive, nous utilisons un QHBoxLayout pour
452     placer les widgets côte à côte:
453
454     \snippet tutorials/addressbook/part3/addressbook.cpp navigation layout
455
456     L'objet QHBoxLayout, \c buttonLayout2, est ensuite ajouté à \c mainLayout.
457
458     \snippet tutorials/addressbook/part3/addressbook.cpp adding navigation layout
459
460     La figure ci-dessous montre les systèmes de coordonnées pour les widgets du
461     \c mainLayout.
462     \image addressbook-tutorial-part3-labeled-layout.png
463
464     Dans notre méthode \c addContact(), nous avons desactivé ces boutons 
465     pour être sûr que l'utilisateur n'utilise pas la navigation lors de 
466     l'ajout d'un contact.
467
468     \snippet tutorials/addressbook/part3/addressbook.cpp disabling navigation
469
470     Dans notre méthode \c submitContact(), nous activons les boutons de
471     navigation, \c nextButton et \c previousButton, en fonction de la
472     taille de \c contacts. Commen mentionné plus tôt, la navigation n'est 
473     activée que si il y a plus d'un contact dans le carnet d'adresses.
474     Les lignes suivantes montrent comment faire cela:
475
476     \snippet tutorials/addressbook/part3/addressbook.cpp enabling navigation
477
478     Nous incluons aussi ces lignes de code dans le bouton \c cancel().
479
480     Souvenez vous que nous voulons émuler une liste-liée ciruculaire à
481     l'aide de l'objet QMap, \c contacts. Pour faire cela, nous obtenons un itérateur 
482     sur \c contact dans la méthode \c next(), et ensuite:
483
484     \list
485         \o Si l'itérateur n'est pas à la fin de \c contacts, nous l'incrémentons
486         \o Si l'itérateur est à la fin de \c contacts, nous changeons sa position
487         jusqu'au début de \c contacts. Cela donne l'illusion que notre QMap 
488         fonctionne comme une liste circulaire.
489     \endlist
490
491     \snippet tutorials/addressbook/part3/addressbook.cpp next() function
492
493     Une fois que nous avons itéré jusqu'à l'objet recherché dans \c contacts,
494     nous affichons son contenu sur \c nameLine et \c addressText.
495
496     De la même façon, pour la méthode \c previous(), nous obtenons un 
497     itérateur sur \c contacts et ensuite:
498
499     \list
500         \o Si l'itérateur est à la fin de \c contacts, on réinitialise
501            l'affichage et on retourne.
502         \o Si l'itérateur est au début de \c contacts, on change sa 
503            position jusqu'à la fin
504         \o Ensuite, on décrémente l'itérateur
505     \endlist
506
507     \snippet tutorials/addressbook/part3/addressbook.cpp previous() function
508
509     à nouveau, nous affichons le contenu de l'objet courant dans \c contacts.
510
511 */
512
513 /*!
514
515     \page tutorials-addressbook-fr-part4.html
516
517     \example tutorials/addressbook-fr/part4
518     \title Carnet d'Adresses 4 - éditer et supprimer des adresses
519
520
521     Dans ce chapitre, nous verrons comment modifier les données des contacts
522     contenus dans l'application carnet d'adresses.
523
524
525     \image addressbook-tutorial-screenshot.png
526
527     Nous avons maintenant un carnet d'adresses qui ne se contente pas de
528     lister des contacts de façon ordonnée, mais permet également la 
529     navigation. Il serait pratique d'inclure des fonctions telles qu'éditer et
530     supprimer, afin que les détails associés à un contact puissent être
531     modifiés lorsque c'est nécessaire. Cependant, cela requiert une légère
532     modification, sous la forme d'énumérations. Au chapitre précédent, nous avions deux
533     modes: \c {AddingMode} et \c {NavigationMode}, mais ils n'étaient pas
534     définis en tant qu'énumérations. Au lieu de ça, on activait et désactivait les
535     boutons correspondants manuellement, au prix de multiples redondances dans
536     le code.
537
538     Dans ce chapitre, on définit l'énumération \c Mode avec trois valeurs possibles.
539
540     \list
541         \o \c{NavigationMode},
542         \o \c{AddingMode}, et
543         \o \c{EditingMode}.
544     \endlist
545
546     \section1 Définition de la classe AddressBook
547
548     Le fichier \c addressbook.h est mis a jour pour contenir l'énumération \c Mode :
549
550     \snippet tutorials/addressbook/part4/addressbook.h Mode enum
551
552     On ajoute également deux nouveaux slots, \c editContact() et
553     \c removeContact(), à notre liste de slots publics.
554
555     \snippet tutorials/addressbook/part4/addressbook.h edit and remove slots
556
557     Afin de basculer d'un mode à l'autre, on introduit la méthode
558     \c updateInterface() pour contrôller l'activation et la désactivation de
559     tous les objets QPushButton. On ajoute également deux nouveaux boutons,
560     \c editButton et \c removeButton, pour les fonctions d'édition
561     et de suppression mentionnées plus haut.
562
563     \snippet tutorials/addressbook/part4/addressbook.h updateInterface() declaration
564     \dots
565     \snippet tutorials/addressbook/part4/addressbook.h buttons declaration
566     \dots
567     \snippet tutorials/addressbook/part4/addressbook.h mode declaration
568
569     Enfin, on déclare \c currentMode pour garder une trace du mode 
570     actuellement utilisé.
571
572     \section1 Implémentation de la classe AddressBook
573
574     Il nous faut maintenant implémenter les fonctionnalités de changement de
575     mode de l'application carnet d'adresses. Les boutons \c editButton et
576     \c removeButton sont instanciés et désactivés par défaut, puisque le
577     carnet d'adresses démarre sans aucun contact en mémoire.
578
579     \snippet tutorials/addressbook/part4/addressbook.cpp edit and remove buttons
580
581     Ces boutons sont ensuite connectés à leurs slots respectifs,
582     \c editContact() et \c removeContact(), avant d'être ajoutés à
583     \c buttonLayout1.
584
585     \snippet tutorials/addressbook/part4/addressbook.cpp connecting edit and remove
586     \dots
587     \snippet tutorials/addressbook/part4/addressbook.cpp adding edit and remove to the layout
588
589     La methode \c editContact() place les anciens détails du contact dans
590     \c oldName et \c oldAddress, avant de basculer vers le mode
591     \c EditingMode. Dans ce mode, les boutons \c submitButton et
592     \c cancelButton sont tous deux activés, l'utilisateur peut par conséquent
593     modifier les détails du contact et cliquer sur l'un de ces deux boutons
594     par la suite.
595
596     \snippet tutorials/addressbook/part4/addressbook.cpp editContact() function
597
598     La méthode \c submitContact() a été divisée en deux avec un bloc
599     \c{if-else}. On teste \c currentMode pour voir si le mode courant est
600     \c AddingMode. Si c'est le cas, on procède à l'ajout.
601
602     \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function beginning
603     \dots
604     \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part1
605
606     Sinon, on s'assure que \c currentMode est en \c EditingMode. Si c'est le
607     cas, on compare \c oldName et \c name. Si le nom a changé, on supprime
608     l'ancien contact de \c contacts et on insère le contact mis a jour.
609
610     \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part2
611
612     Si seule l'adresse a changé (i.e. \c oldAddress n'est pas identique à
613     \c address), on met à jour l'adresse du contact. Enfin on règle
614     \c currentMode à \c NavigationMode. C'est une étape importante puisque
615     c'est cela qui réactive tous les boutons désactivés.
616
617     Afin de retirer un contact du carnet d'adresses, on implémente la méthode
618     \c removeContact(). Cette méthode vérifie que le contact est présent dans
619     \c contacts.
620
621     \snippet tutorials/addressbook/part4/addressbook.cpp removeContact() function
622
623     Si c'est le cas, on affiche une boîte de dialogue QMessageBox, demandant
624     confirmation de la suppression à l'utilisateur. Une fois la confirmation
625     effectuée, on appelle \c previous(), afin de s'assurer que l'interface
626     utilisateur affiche une autre entrée, et on supprime le contact en
627     utilisant le méthode \l{QMap::remove()}{remove()} de \l{QMap}. Dans un
628     souci pratique, on informe l'utilisateur de la suppression par le biais
629     d'une autre QMessageBox. Les deux boîtes de dialogue utilisées dans cette
630     méthode sont représentées ci-dessous.
631
632     \image addressbook-tutorial-part4-remove.png
633
634     \section2 Mise à jour de l'Interface utilisateur
635
636     On a évoqué plus haut la méthode \c updateInterface() comme moyen
637     d'activer et de désactiver les différents boutons de l'interface en
638     fonction du mode. Cette méthode met à jour le mode courant selon
639     l'argument \c mode qui lui est passé, en l'assignant à \c currentMode,
640     avant de tester sa valeur.
641
642     Chacun des boutons est ensuite activé ou désactivé, en fonction du mode.
643     Le code source pour les cas \c AddingMode et \c EditingMode est visible 
644     ci-dessous:
645
646     \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 1
647
648     Dans le cas de \c NavigationMode, en revanche, des tests conditionnels
649     sont passés en paramètre de QPushButton::setEnabled(). Ceci permet de
650     s'assurer que les boutons \c editButton et \c removeButton ne sont activés
651     que s'il existe au moins un contact dans le carnet d'adresses;
652     \c nextButton et \c previousButton ne sont activés que lorsqu'il existe
653     plus d'un contact dans le carnet d'adresses.
654
655     \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 2
656
657     En effectuant les opérations de réglage du mode et de mise à jour de
658     l'interface utilisateur au sein de la même méthode, on est à l'abri de
659     l'éventualité où l'interface utilisateur se "désynchronise" de l'état
660     interne de l'application.
661
662 */
663
664 /*!
665     \page tutorials-addressbook-fr-part5.html
666
667     \example tutorials/addressbook-fr/part5
668     \title Carnet d'adresse 5 - Ajout d'une fonction de recherche
669
670     Dans ce chapitre, nous allons voir les possibilités pour rechercher
671     des contacts dans le carnet d'adresse.
672
673     \image addressbook-tutorial-part5-screenshot.png
674
675     Plus nous ajoutons des contacts dans l'application, plus
676     il devient difficile de naviguer avec les boutons \e Next et \e Previous.
677     Dans ce cas, une fonction de recherche serait plus efficace pour rechercher
678     les contacts.
679     La capture d'écran ci-dessus montre le bouton de recherche \e Find et sa position
680     dans le paneau de bouton.
681
682     Lorsque l'utilisateur clique sur le bouton \e Find, il est courant d'afficher
683     une boîte de dialogue qui demande à l'utilisateur d'entrer un nom de contact.
684     Qt fournit la classe QDialog, que nous sous-classons dans ce chapitre pour
685     implémenter la class \c FindDialog.
686
687     \section1 Définition de la classe FindDialog
688
689     \image addressbook-tutorial-part5-finddialog.png
690
691     Pour sous-classer QDialog, nous commençons par inclure le header de
692     QDialog dans le fichier \c finddialog.h. De plus, nous déclarons les
693     classes QLineEdit et QPushButton car nous utilisons ces widgets dans
694     notre classe dialogue.
695
696     Tout comme dans la classe \c AddressBook, la classe \c FindDialog utilise
697     la macro Q_OBJECT et son constructeur est défini de façon à accepter
698     un QWidget parent, même si cette boîte de dialogue sera affichée dans une
699     fenêtre séparée.
700
701     \snippet tutorials/addressbook/part5/finddialog.h FindDialog header
702
703     Nous définissons la méthode publique \c getFindText() pour être utilisée
704     par les classes qui instancient \c FindDialog, ce qui leur permet d'obtenir
705     le texte entré par l'utilisateur. Un slot public, \c findClicked(), est
706     défini pour prendre en charge le texte lorsque l'utilisateur clique sur
707     le bouton \gui Find.
708
709     Finalement, nous définissons les variables privées \c findButton,
710     \c lineEdit et \c findText, qui correspondent respectivement au bouton
711     \gui Find, au champ de texte dans lequel l'utilisateur tape le texte
712     à rechercher, et à une variable interne stockant le texte pour une
713     utilisation ultérieure.
714
715     \section1 Implémentation de la classe FindDialog
716
717     Dans le constructeur de \c FindDialog, nous instancions les objets des
718     variables privées \c lineEdit, \c findButton et \c findText. Nous utilisons ensuite
719     un QHBoxLayout pour positionner les widgets.
720
721     \snippet tutorials/addressbook/part5/finddialog.cpp constructor
722
723     Nous mettons en place la mise en page et le titre de la fenêtre, et
724     nous connectons les signaux aux slots. Remarquez que le signal
725     \l{QPushButton::clicked()}{clicked()} de \c{findButton} est connecté
726     à \c findClicked() et \l{QDialog::accept()}{accept()}. Le slot
727     \l{QDialog::accept()}{accept()} fourni par le QDialog ferme
728     la boîte de dialogue et lui donne le code de retour \l{QDialog::}{Accepted}.
729     Nous utilisons cette fonction pour aider la méthode \c findContact() de la classe
730     \c{AddressBook} à savoir si l'objet \c FindDialog a été fermé. Ceci sera
731     expliqué plus loin lorsque nous verrons la méthode \c findContact().
732
733     \image addressbook-tutorial-part5-signals-and-slots.png
734
735     Dans \c findClicked(), nous validons le champ de texte pour nous
736     assurer que l'utilisateur n'a pas cliqué sur le bouton \gui Find sans
737     avoir entré un nom de contact. Ensuite, nous stockons le texte du champ
738     d'entrée \c lineEdit dans \c findText. Et finalement nous vidons le
739     contenu de \c lineEdit et cachons la boîte de dialogue.
740
741     \snippet tutorials/addressbook/part5/finddialog.cpp findClicked() function
742
743     La variable \c findText a un accesseur publique associé: \c getFindText().
744     Étant donné que nous ne modifions \c findText directement que dans le
745     constructeur et la méthode \c findClicked(), nous ne créons pas
746     de manipulateurs associé à \c getFindText().
747     Puisque \c getFindText() est publique, les classes instanciant et
748     utilisant \c FindDialog peuvent toujours accéder à la chaîne de
749     caractères que l'utilisateur a entré et accepté.
750
751     \snippet tutorials/addressbook/part5/finddialog.cpp getFindText() function
752
753     \section1 Définition de la classe AddressBook
754
755     Pour utiliser \c FindDialog depuis la classe \c AddressBook, nous
756     incluons \c finddialog.h dans le fichier \c addressbook.h.
757
758     \snippet tutorials/addressbook/part5/addressbook.h include finddialog's header
759
760     Jusqu'ici, toutes les fonctionnalités du carnet d'adresses ont un
761     QPushButton et un slot correspondant. De la même façon, pour la
762     fonctionnalité \gui Find, nous avons \c findButton et \c findContact().
763
764     Le \c findButton est déclaré comme une variable privée et la
765     méthode \c findContact() est déclarée comme un slot public.
766
767     \snippet tutorials/addressbook/part5/addressbook.h findContact() declaration
768     \dots
769     \snippet tutorials/addressbook/part5/addressbook.h findButton declaration
770
771     Finalement, nous déclarons la variable privée \c dialog que nous allons
772     utiliser pour accéder à une instance de \c FindDialog.
773
774     \snippet tutorials/addressbook/part5/addressbook.h FindDialog declaration
775
776     Une fois que nous avons instancié la boîte de dialogue, nous voulons l'utiliser
777     plus qu'une fois. Utiliser une variable privée nous permet d'y référer
778     à plus d'un endroit dans la classe.
779
780     \section1 Implémentation de la classe AddressBook
781
782     Dans le constructeur de \c AddressBook, nous instancions nos objets privés,
783     \c findbutton et \c findDialog:
784
785     \snippet tutorials/addressbook/part5/addressbook.cpp instantiating findButton
786     \dots
787     \snippet tutorials/addressbook/part5/addressbook.cpp instantiating FindDialog
788
789     Ensuite, nous connectons le signal \l{QPushButton::clicked()}{clicked()} de
790     \c{findButton} à \c findContact().
791
792     \snippet tutorials/addressbook/part5/addressbook.cpp signals and slots for find
793
794     Maintenant, tout ce qui manque est le code de notre méthode \c findContact():
795
796     \snippet tutorials/addressbook/part5/addressbook.cpp findContact() function
797
798     Nous commençons par afficher l'instance de \c FindDialog, \c dialog.
799     L'utilisateur peut alors entrer le nom du contact à rechercher. Lorsque
800     l'utilisateur clique sur le bouton \c findButton, la boîte de dialogue est
801     masquée et le code de retour devient QDialog::Accepted. Ce code de retour
802     vient remplir la condition du premier if.
803
804     Ensuite, nous extrayons le texte que nous utiliserons pour la recherche,
805     il s'agit ici de \c contactName obtenu à l'aide de la méthode \c getFindText()
806     de \c FindDialog. Si le contact existe dans le carnet d'adresse, nous
807     l'affichons directement. Sinon, nous affichons le QMessageBox suivant pour
808     indiquer que la recherche à échouée.
809
810     \image addressbook-tutorial-part5-notfound.png
811 */
812
813 /*!
814     \page tutorials-addressbook-part6.html
815
816     \example tutorials/addressbook-fr/part6
817     \title Carnet d'Adresses 6 - Sauvegarde et chargement
818
819     Ce chapitre couvre les fonctionnalités de gestion des fichiers de Qt que
820     l'on utilise pour écrire les procédures de sauvegarde et chargement pour
821     l'application carnet d'adresses.
822
823     \image addressbook-tutorial-part6-screenshot.png
824
825     Bien que la navigation et la recherche de contacts soient des
826     fonctionnalités importantes, notre carnet d'adresses ne sera pleinement
827     utilisable qu'une fois que l'on pourra sauvegarder les contacts existants
828     et les charger à nouveau par la suite.
829     Qt fournit de nombreuses classes pour gérer les \l{Input/Output and
830     Networking}{entrées et sorties}, mais nous avons choisi de nous contenter d'une
831     combinaison de deux classes simples à utiliser ensemble: QFile et QDataStream.
832
833     Un objet QFile représente un fichier sur le disque qui peut être lu, et
834     dans lequel on peut écrire. QFile est une classe fille de la classe plus
835     générique QIODevice, qui peut représenter différents types de
836     périphériques.
837
838     Un objet QDataStream est utilisé pour sérialiser des données binaires
839     dans le but de les passer à un QIODevice pour les récupérer dans le
840     futur. Pour lire ou écrire dans un QIODevice, il suffit d'ouvrir le
841     flux, avec le périphérique approprié en paramètre, et d'y lire ou
842     écrire.
843
844     \section1 Définition de la classe AddressBook
845
846     On déclare deux slots publics, \c saveToFile() et \c loadFromFile(), 
847     ainsi que deux objets QPushButton, \c loadButton et \c saveButton.
848
849     \snippet tutorials/addressbook/part6/addressbook.h save and load functions declaration
850     \dots
851     \snippet tutorials/addressbook/part6/addressbook.h save and load buttons declaration
852
853     \section1 Implémentation de la classe AddressBook
854
855     Dans notre constructeur, on instancie \c loadButton et \c saveButton.
856     Idéalement, l'interface serait plus conviviale avec des boutons
857     affichant "Load contacts from a file" et "Save contacts to a file". Mais
858     compte tenu de la dimension des autres boutons, on initialise les labels
859     des boutons à \gui{Load...} et \gui{Save...}. Heureusement, Qt offre une
860     façon simple d'ajouter des info-bulles avec
861     \l{QWidget::setToolTip()}{setToolTip()}, et nous l'exploitons de la façon
862     suivante pour nos boutons:
863
864     \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 1
865     \dots
866     \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 2
867
868     Bien qu'on ne cite pas le code correspondant ici, nous ajoutons ces deux boutons au
869     layout de droite, \c button1Layout, comme pour les fonctionnalités précédentes, et 
870     nous connectons leurs signaux
871     \l{QPushButton::clicked()}{clicked()} à leurs slots respectifs.
872
873     Pour la sauvegarde, on commence par récupérer le nom de fichier 
874     \c fileName, en utilisant QFileDialog::getSaveFileName(). C'est une
875     méthode pratique fournie par QFileDialog, qui ouvre une boîte de
876     dialogue modale et permet à l'utilisateur d'entrer un nom de fichier ou
877     de choisir un fichier \c{.abk} existant. Les fichiers \c{.abk}
878     correspondent à l'extension choisie pour la sauvegarde des contacts de
879     notre carnet d'adresses.
880
881     \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part1
882
883     La boîte de dialogue affichée est visible sur la capture d'écran ci-
884     dessous.
885
886     \image addressbook-tutorial-part6-save.png
887
888     Si \c fileName n'est pas vide, on crée un objet QFile, \c file, à partir
889     de \c fileName. QFile fonctionne avec QDataStream puisqu'il dérive de
890     QIODevice.
891
892     Ensuite, on essaie d'ouvrir le fichier en écriture, ce qui correspond au
893     mode \l{QIODevice::}{WriteOnly}. Si cela échoue, on en informe
894     l'utilisateur avec une QMessageBox.
895
896     \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part2
897
898     Dans le cas contraire, on instancie un objet QDataStream, \c out, afin
899     d'écrire dans le fichier ouvert. QDataStream nécessite que la même
900     version de flux soit utilisée pour la lecture et l'écriture. On s'assure
901     que c'est le cas en spécifiant explicitement d'utiliser la
902     \l{QDataStream::Qt_4_5}{version introduite avec Qt 4.5} avant de
903     sérialiser les données vers le fichier \c file.
904
905     \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part3
906
907     Pour le chargement, on récupère également \c fileName en utilisant
908     QFileDialog::getOpenFileName(). Cette méthode est l'homologue de
909     QFileDialog::getSaveFileName() et affiche également une boîte de
910     dialogue modale permettant à l'utilisateur d'entrer un nom de fichier ou
911     de selectionner un fichier \c{.abk} existant, afin de le charger dans le
912     carnet d'adresses.
913
914     \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part1
915
916     Sous Windows, par exemple, cette méthode affiche une boîte de dialogue
917     native pour la sélection de fichier, comme illustré sur la capture
918     d'écran suivante:
919
920     \image addressbook-tutorial-part6-load.png
921
922     Si \c fileName n'est pas vide, on utilise une fois de plus un objet
923     QFile, \c file, et on tente de l'ouvrir en lecture, avec le mode
924     \l{QIODevice::}{ReadOnly}. De même que précédemment dans notre
925     implémentation de \c saveToFile(), si cette tentative s'avère
926     infructueuse, on en informe l'utilisateur par le biais d'une
927     QMessageBox.
928
929     \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part2
930
931     Dans le cas contraire, on instancie un objet QDataStream, \c in, en
932     spécifiant la version à utiliser comme précédemment, et on lit les
933     informations sérialisées vers la structure de données \c contacts. Notez
934     qu'on purge \c contacts avant d'y mettre les informations lues afin de
935     simplifier le processus de lecture de fichier. Une façon plus avancée de
936     procéder serait de lire les contacts dans un objet QMap temporaire, et
937     de copier uniquement les contacts n'existant pas encore dans
938     \c contacts.
939
940     \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part3
941
942     Pour afficher les contacts lus depuis le fichier, on doit d'abord
943     valider les données obtenues afin de s'assurer que le fichier lu
944     contient effectivement des entrées de carnet d'adresses. Si c'est le
945     cas, on affiche le premier contact; sinon on informe l'utilisateur du
946     problème par une QMessageBox. Enfin, on met à jour l'interface afin
947     d'activer et de désactiver les boutons de façon appropriée.
948 */
949
950 /*!
951     \page tutorials-addressbook-fr-part7.html
952
953     \example tutorials/addressbook-fr/part7
954     \title Carnet d'adresse 7 - Fonctionnalités avancées
955
956     Ce chapitre couvre quelques fonctionnalités additionnelles qui
957     feront de notre carnet d'adresses une application plus pratique
958     pour une utilisation quotidienne.
959
960     \image addressbook-tutorial-part7-screenshot.png
961
962     Bien que notre application carnet d'adresses soit utile en tant que telle,
963     il serait pratique de pouvoir échanger les contacts avec d'autres applications.
964     Le format vCard est un un format de fichier populaire pour échanger
965     ce type de données.
966     Dans ce chapitre, nous étendrons notre carnet d'adresses pour permettre
967     d'exporter des contacts dans des fichiers vCard \c{.vcf}.
968
969     \section1 Définition de la classe AddressBook
970
971     Nous ajoutons un objet QPushButton, \c exportButton, et un slot
972     public correspondant, \c exportAsVCard(), à notre classe \c AddressBook 
973     dans le fichier \c addressbook.h.
974
975     \snippet tutorials/addressbook/part7/addressbook.h exportAsVCard() declaration
976     \dots
977     \snippet tutorials/addressbook/part7/addressbook.h exportButton declaration
978
979     \section1 Implémentation de la classe AddressBook
980
981     Dans le constructeur de \c AddressBook, nous connectons le signal
982     \l{QPushButton::clicked()}{clicked()} de \c{exportButton} au slot
983     \c exportAsVCard().
984     Nous ajoutons aussi ce bouton à \c buttonLayout1, le layout responsable
985     du groupe de boutons sur la droite.
986
987     Dans la méthode \c exportAsVCard(), nous commençons par extraire le
988     nom du contact dans \n name. Nous déclarons \c firstname, \c lastName et
989     \c nameList.
990     Ensuite, nous cherchons la position du premier espace blanc de \c name.
991     Si il y a un espace, nous séparons le nom du contact en \c firstName et
992     \c lastName. Finalement, nous remplaçons l'espace par un underscore ("_").
993     Si il n'y a pas d'espace, nous supposons que le contact ne comprend que
994     le prénom.
995
996     \snippet tutorials/addressbook/part7/addressbook.cpp export function part1
997
998     Comme pour la méthode \c saveToFile(), nous ouvrons une boîte de dialogue
999     pour donner la possibilité à l'utilisateur de choisir un emplacement pour
1000     le fichier. Avec le nom de fichier choisi, nous créons une instance de QFile
1001     pour y écrire.
1002
1003     Nous essayons d'ouvrir le fichier en mode \l{QIODevice::}{WriteOnly}. Si
1004     cela échoue, nous affichons un QMessageBox pour informer l'utilisateur
1005     à propos de l'origine du problème et nous quittons la méthode. Sinon, nous passons le
1006     fichier comme paramètre pour créer un objet QTextStream, \c out. De la même façon que
1007     QDataStream, la classe QTextStream fournit les fonctionnalités pour 
1008     lire et écrire des fichiers de texte. Grâce à celà, le fichier \c{.vcf}
1009     généré pourra être ouvert et édité à l'aide d'un simple éditeur de texte.
1010
1011     \snippet tutorials/addressbook/part7/addressbook.cpp export function part2
1012
1013     Nous écrivons ensuite un fichier vCard avec la balise \c{BEGIN:VCARD},
1014     suivit par \c{VERSION:2.1}.
1015     Le nom d'un contact est écrit à l'aide de la balise \c{N:}. Pour la balise
1016     \c{FN:}, qui remplit le titre du contact, nous devons vérifier si le contact
1017     à un nom de famille défini ou non. Si oui, nous utilions les détails de
1018     \c nameList pour remplir le champ, dans le cas contraire on écrit uniquement le contenu
1019     de \c firstName.
1020  
1021     \snippet tutorials/addressbook/part7/addressbook.cpp export function part3
1022
1023     Nous continuons en écrivant l'adresse du contact. Les points-virgules
1024     dans l'adresse sont échappés à l'aide de "\\", les retours de ligne sont
1025     remplacés par des points-virgules, et les vigules sont remplacées par des espaces.
1026     Finalement nous écrivons les balises  \c{ADR;HOME:;} suivies par l'adresse
1027     et la balise \c{END:VCARD}.
1028
1029     \snippet tutorials/addressbook/part7/addressbook.cpp export function part4
1030
1031     À la fin de la méthode, un QMessageBox est affiché pour informer l'utilisateur
1032     que la vCard a été exportée avec succès. 
1033
1034     \e{vCard est une marque déposée de \l{http://www.imc.org}
1035     {Internet Mail Consortium}}.
1036 */