doc/src/tutorials/addressbook-fr.qdoc
branchRCL_3
changeset 7 3f74d0d4af4c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/tutorials/addressbook-fr.qdoc	Thu Apr 08 14:19:33 2010 +0300
@@ -0,0 +1,1066 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+    \page tutorials-addressbook-fr.html
+
+    \startpage {index.html}{Qt Reference Documentation}
+    \contentspage Tutorials
+    \nextpage {tutorials/addressbook-fr/part1}{Chapitre 1}
+
+    \title Tutoriel "Carnet d'adresses"
+    \brief Une introduction à la programation d'interface graphique montrant comment construire une application simple avec Qt.
+
+    Ce tutoriel est une introduction à la programmation de GUI (interface utilisateur)
+    à l'aide des outils fournis par la plateforme multiplate-forme Qt.
+
+    \image addressbook-tutorial-screenshot.png
+
+    Ce tutoriel va nous amener à découvrir quelques technologies fondamentales fournies 
+    par Qt, tel que:
+
+    \list
+    \o Les Widgets et leur mise en page à l'aide des layouts
+    \o Les signaux et slots
+    \o Les structures de données de collections
+    \o Les entrées/sorties
+    \endlist
+
+    Si c'est votre premier contact avec Qt, lisez \l{How to Learn Qt}{Comment apprendre Qt}
+    si ce n'est déjà fait.
+
+    Le code source du tutoriel est distribué avec Qt dans le dossier \c examples/tutorials/addressbook
+
+    Les chapitres du tutoriel:
+
+    \list 1
+    \o \l{tutorials/addressbook-fr/part1}{Conception de l'interface utilisateur}
+    \o \l{tutorials/addressbook-fr/part2}{Ajouter des adresses}
+    \o \l{tutorials/addressbook-fr/part3}{Navigation entre les éléments}
+    \o \l{tutorials/addressbook-fr/part4}{éditer et supprimer des adresses}
+    \o \l{tutorials/addressbook-fr/part5}{Ajout d'une fonction de recherche}
+    \o \l{tutorials/addressbook-fr/part6}{Sauvegarde et chargement}
+    \o \l{tutorials/addressbook-fr/part7}{Fonctionnalités avancées}
+    \endlist
+
+    La petite application que nous développerons ici ne possède pas tous les éléments
+    des interfaces dernier cri, elle va nous permettre d'utiliser les techniques de base
+    utilisées dans les applications plus complexes.
+
+    Lorsque vous aurez terminé ce tutoriel, nous vous recommandons de poursuivre avec l'exemple
+    "\l{mainwindows/application}{Application}", qui présente une interface simple utilisant
+    les menus et barres d'outils, la barre d'état, etc.
+
+*/
+
+/*!
+    \page tutorials-addressbook-fr-part1.html
+    \contentspage {Tutoriel "Carnet d'adresses"}{Sommaire}
+    \nextpage {tutorials/addressbook-fr/part2}{Chapitre 2}
+    \example tutorials/addressbook-fr/part1
+    \title Carnet d'adresses 1 - Conception de l'interface utilisateur
+
+    La première partie de ce tutoriel traite de la conception d'une interface graphique
+    (GUI) basique, que l'on utilisera pour l'application Carnet d'adresses.
+
+    La première étape dans la création d'applications graphiques est la conception de
+    l'interface utilisateur. Dans ce chapitre, nous verrons comment créer les labels
+    et champs de saisie nécessaires à l'implementation d'un carnet d'adresses de base.
+    Le résultat attendu est illustré par la capture d'écran ci-dessous.
+
+    \image addressbook-tutorial-part1-screenshot.png
+
+    Nous allons avoir besoin de deux objets QLabel, \c nameLabel et \c addressLabel,
+    ainsi que deux champs de saisie: un objet QLineEdit, \c nameLine, et un objet
+    QTextEdit, \c addressText, afin de permettre à l'utilisateur d'entrer le nom d'un
+    contact et son adresse. Les widgets utilisés ainsi que leur placement sont visibles ci-dessous.
+
+    \image addressbook-tutorial-part1-labeled-screenshot.png
+
+    Trois fichiers sont nécessaires à l'implémentation de ce carnet d'adresses:
+
+    \list
+        \o \c{addressbook.h} - le fichier de définition (header) pour la classe \c AddressBook,
+        \o \c{addressbook.cpp} - le fichier source, qui comprend l'implémentation de la classe
+            \c AddressBook
+        \o \c{main.cpp} - le fichier qui contient la méthode \c main() , et
+        une instance de la classe \c AddressBook.
+    \endlist
+
+    \section1 Programmation en Qt - héritage
+
+
+    Lorsque l'on écrit des programmes avec Qt, on a généralement recours à
+    l'héritage depuis des objets Qt, afin d'y ajouter des fonctionnalités.
+    C'est l'un des concepts fondamentaux de la création de widgets personnalisés
+    ou de collections de widgets. Utiliser l'héritage afin de compléter
+    ou modifier le comportement d'un widget présente les avantages suivants:
+
+    \list
+    \o La possibilité d'implémenter des méthodes virtuelles et des méthodes 
+    virtuelles pures pour obtenir exactement ce que l'on souhaite, avec la possibilité
+    d'utiliser l'implémentation de la classe mère si besoin est.
+    \o Cela permet l'encapsulation partielle de l'interface utilisateur dans une classe,
+    afin que les autres parties de l'application n'aient pas à se soucier de chacun des
+    widgets qui forment l'interface utilisateur.
+    \o La classe fille peut être utilisée pour créer de nombreux widgets personnalisés
+    dans une même application ou bibliothèque, et le code de la classe fille peut être
+    réutilisé dans d'autres projets
+    \endlist
+
+    Comme Qt ne fournit pas de widget standard pour un carnet d'adresses, nous 
+    partirons d'une classe de widget Qt standard et y ajouterons des fonctionnalités.
+    La classe \c AddressBook crée dans ce tutoriel peut être réutilisée si on a besoin d'un
+    widget carnet d'adresses basique.
+
+
+    \section1 La classe AddressBook
+
+    Le fichier \l{tutorials/addressbook-fr/part1/addressbook.h}{\c addressbook.h} permet de
+    définir la classe \c AddressBook.
+
+    On commence par définir \c AddressBook comme une classe fille de QWidget et déclarer
+    un constructeur. On utilise également la macro Q_OBJECT pour indiquer que la classe
+    exploite les fonctionnalités de signaux et slots offertes par Qt ainsi que
+    l'internationalisation, bien que nous ne les utilisions pas à ce stade.
+
+    \snippet tutorials/addressbook-fr/part1/addressbook.h class definition
+
+    La classe contient les déclarations de \c nameLine et \c addressText,
+    les instances privées de QLineEdit et QTextEdit mentionnées précédemment.
+    Vous verrez, dans les chapitres à venir que les informations contenues
+    dans \c nameLine et \c addressText sont nécessaires à de nombreuses méthodes
+    du carnet d'adresses.
+
+    Il n'est pas nécessaire de déclarer les objets QLabel que nous allons utiliser 
+    puisque nous n'aurons pas besoin d'y faire référence après leur création.
+    La façon dont Qt gère la parenté des objets est traitée dans la section suivante.
+
+    La macro Q_OBJECT implémente des fonctionnalités parmi les plus avancées de Qt.
+    Pour le moment, il est bon de voir la macro Q_OBJECT comme un raccourci nous 
+    permettant d'utiliser les méthodes \l{QObject::}{tr()} et \l{QObject::}{connect()}.
+
+    Nous en avons maintenant terminé avec le fichier \c addressbook.h et allons
+    passer à l'implémentation du fichier \c addressbook.cpp.
+
+    \section1 Implémentation de la classe AddressBook
+
+    Le constructeur de la classe \c{AddressBook} prend en paramètre un QWidget, \e parent.
+    Par convention, on passe ce paramètre au constructeur de la classe mère.
+    Ce concept de parenté, où un parent peut avoir un ou plusieurs enfants, est utile
+    pour regrouper les Widgets avec Qt. Par exemple, si vous détruisez le parent,
+    tous ses enfants seront détruits égalament.
+
+
+    \snippet tutorials/addressbook/part1/addressbook.cpp constructor and input fields
+
+    à l'intérieur de ce constructeur, on déclare et instancie deux objets locaux
+    QLabel, \c nameLabel et \c addressLabel, de même on instancie \c nameLine et
+    \c addressText. La méthode \l{QObject::tr()}{tr()} renvoie une version traduite
+    de la chaîne de caractères, si elle existe; dans le cas contraire, elle renvoie
+    la chaîne elle même. On peut voir cette méthode comme un marqueur \tt{<insérer
+    la traduction ici>}, permettant de repérer les objets QString à considérer
+    pour traduire une application. Vous remarquerez, dans les chapitres à venir
+    comme dans les \l{Qt Examples}{exemples Qt}, qu'elle est utilisée chaque fois
+    que l'on utilise une chaîne susceptible d'être traduite.
+
+    Lorsque l'on programme avec Qt, il est utile de savoir comment fonctionnent les
+    agencements ou layouts. Qt fournit trois classes principales de layouts pour
+    contrôler le placement des widgets: QHBoxLayout, QVBoxLayout et QGridLayout.
+
+    \image addressbook-tutorial-part1-labeled-layout.png
+
+    On utilise un QGridLayout pour positionner nos labels et champs de saisie de manière
+    structurée. QGridLayout divise l'espace disponible en une grille, et place les
+    widgets dans les cellules que l'on spécifie par les numéros de ligne et de colonne.
+    Le diagramme ci-dessus présente les cellules et la position des widgets, et cette
+    organisation est obtenue à l'aide du code suivant:
+
+    \snippet tutorials/addressbook/part1/addressbook.cpp layout
+
+    On remarque que le label \c AddressLabel est positionné en utilisant Qt::AlignTop
+    comme argument optionnel. Ceci est destiné à assurer qu'il ne sera pas centré
+    verticalement dans la cellule (1,0). Pour un aperçu rapide des layouts de Qt,
+    consultez la section \l{Layout Management}.
+
+    Afin d'installer l'objet layout dans un widget, il faut appeler la méthode
+    \l{QWidget::setLayout()}{setLayout()} du widget en question:
+
+    \snippet tutorials/addressbook/part1/addressbook.cpp setting the layout
+
+    Enfin, on initialise le titre du widget à "Simple Address Book"
+
+    \section1 Exécution de l'application
+
+    Un fichier séparé, \c main.cpp, est utilisé pour la méthode \c main(). Dans cette
+    fonction, on crée une instance de QApplication, \c app. QApplication se charge de
+    des ressources communes à l'ensemble de l'application, tel que les polices de
+    caractères et le curseur par défaut, ainsi que de l'exécution de la boucle d'évènements.
+    De ce fait, il y a toujours un objet QApplication dans toute application graphique en Qt.
+
+    \snippet tutorials/addressbook/part1/main.cpp main function
+
+    On construit un nouveau widget \c AddressBook sur la pile et on invoque
+    sa méthode \l{QWidget::show()}{show()} pour l'afficher.
+    Cependant, le widget ne sera pas visible tant que la boucle d'évènements
+    n'aura pas été lancée. On démarre la boucle d'évènements en appelant la
+    méthode \l{QApplication::}{exec()} de l'application; le résultat renvoyé
+    par cette méthode est lui même utilisé comme valeur de retour pour la méthode
+    \c main().
+    On comprend maintenant pourquoi \c AddressBook a été créé sur la pile: à la fin
+    du programme, l'objet sort du scope de la fonction \c main() et tous ses widgets enfants
+    sont supprimés, assurant ainsi qu'il n'y aura pas de fuites de mémoire.
+*/
+
+/*!
+    \page tutorials-addressbook-fr-part2.html
+    \previouspage {tutorials/addressbook-fr/part1}{Chapitre 1}
+    \contentspage {Tutoriel "Carnet d'adresses"}{Sommaire}
+    \nextpage {tutorials/addressbook-fr/part3}{Chapitre 3}
+    \example tutorials/addressbook-fr/part2
+    \title Carnet d'adresses 2 - Ajouter des adresses
+
+    La prochaine étape pour créer notre carnet d'adresses est d'ajouter un soupçon
+    d'interactivité.
+
+    \image addressbook-tutorial-part2-add-contact.png
+
+    Nous allons fournir un bouton que l'utilisateur peut
+    cliquer pour ajouter un nouveau contact. Une structure de données est aussi
+    nécessaire afin de pouvoir stocker les contacts en mémoire.
+
+    \section1 Définition de la classe AddressBook
+
+    Maintenant que nous avons mis en place les labels et les champs de saisie,
+    nous ajoutons les boutons pour compléter le processus d'ajout d'un contact.
+    Cela veut dire que notre fichier \c addressbook.h a maintenant trois
+    objets QPushButton et trois slots publics correspondant.
+
+    \snippet tutorials/addressbook/part2/addressbook.h slots
+
+    Un slot est une méthode qui répond à un signal. Nous allons
+    voir ce concept en détail lorsque nous implémenterons la classe \c{AddressBook}.
+    Pour une explication détaillée du concept de signal et slot, vous pouvez
+    vous référer au document \l{Signals and Slots}.
+
+    Les trois objets QPushButton \c addButton, \c submitButton et \c cancelButton
+    sont maintenant inclus dans la déclaration des variables privées, avec
+    \c nameLine et \c addressText du chapitre précédent.
+
+    \snippet tutorials/addressbook/part2/addressbook.h pushbutton declaration
+
+    Nous avons besoin d'un conteneur pour stocker les contacts du carnet
+    d'adresses, de façon à pouvoir les énumérer et les afficher.
+    Un objet QMap, \c contacts, est utilisé pour ça, car il permet de stocker
+    des paires clé-valeur: le nom du contact est la \e{clé} et l'adresse du contact
+    est la \e{valeur}.
+
+    \snippet tutorials/addressbook/part2/addressbook.h remaining private variables
+
+    Nous déclarons aussi deux objects QString privés: \c oldName et \c oldAddress.
+    Ces objets sont nécessaires pour conserver le nom et l'adresse du dernier contact
+    affiché avant que l'utilisateur ne clique sur le bouton "Add". Grâce à ces variables
+    si l'utilisateur clique sur "Cancel", il est possible de revenir
+    à l'affichage du dernier contact.
+
+    \section1 Implémentation de la classe AddressBook
+
+    Dans le constructeur de \c AddressBook, \c nameLine et
+    \c addressText sont mis en mode lecture seule, de façon à autoriser l'affichage
+    mais pas la modification du contact courant.
+
+    \dots
+    \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 1
+    \dots
+    \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 2
+
+    Ensuite, nous instancions les boutons \c addButton, \c submitButton, et
+    \c cancelButton.
+
+    \snippet tutorials/addressbook/part2/addressbook.cpp pushbutton declaration
+
+    Le bouton \c addButton est affiché en invoquant la méthode \l{QPushButton::show()}
+    {show()}, tandis que \c submitButton et \c cancelButton sont cachés en invoquant
+    \l{QPushButton::hide()}{hide()}. Ces deux boutons ne seront affichés que lorsque 
+    l'utilisateur cliquera sur "Add", et ceci est géré par la méthode \c addContact()
+    décrite plus loin.
+
+    \snippet tutorials/addressbook/part2/addressbook.cpp connecting signals and slots
+
+    Nous connectons le signal \l{QPushButton::clicked()}{clicked()} de chaque bouton 
+    au slot qui gèrera l'action.
+    L'image ci-dessous illustre ceci:
+
+    \image addressbook-tutorial-part2-signals-and-slots.png
+
+    Ensuite, nous arrangeons proprement les boutons sur la droite du widget
+    AddressBook, et nous utilisons un QVBoxLayout pour les aligner verticalement.
+
+    \snippet tutorials/addressbook/part2/addressbook.cpp vertical layout
+
+    La methode \l{QBoxLayout::addStretch()}{addStretch()} est utilisée pour
+    assurer que les boutons ne sont pas répartis uniformément, mais regroupés
+    dans la partie supperieure du widget. La figure ci-dessous montre la différence
+    si \l{QBoxLayout::addStretch()}{addStretch()} est utilisé ou pas.
+
+    \image addressbook-tutorial-part2-stretch-effects.png
+
+    Ensuite nous ajoutons \c buttonLayout1 à \c mainLayout, en utilisant
+    \l{QGridLayout::addLayout()}{addLayout()}. Ceci nous permet d'imbriquer les
+    mises en page puisque \c buttonLayout1 est maintenant un enfant de \c mainLayout.
+
+    \snippet tutorials/addressbook/part2/addressbook.cpp grid layout
+
+    Les coordonnées du layout global ressemblent maintenant à ça:
+
+    \image addressbook-tutorial-part2-labeled-layout.png
+
+    Dans la méthode \c addContact(), nous stockons les détails du dernier
+    contact affiché dans \c oldName et \c oldAddress. Ensuite, nous
+    vidons ces champs de saisie et nous désactivons le mode
+    lecture seule. Le focus est placé sur \c nameLine et on affiche
+    \c submitButton et \c cancelButton.
+
+    \snippet tutorials/addressbook/part2/addressbook.cpp addContact
+
+    La méthode \c submitContact() peut être divisée en trois parties:
+
+    \list 1
+    \o Nous extrayons les détails du contact depuis \c nameLine et \c addressText
+    et les stockons dans des objets QString. Nous les validons pour s'assurer
+    que l'utilisateur n'a pas cliqué sur "Add" avec des champs de saisie
+    vides; sinon un message est affiché avec QMessageBox pour rappeller à
+    l'utilisateur que les deux champs doivent être complétés.
+
+    \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1
+
+    \o Ensuite, nous vérifions si le contact existe déjà. Si aucun contacts
+    existant n'entre en conflit avec le nouveau, nous l'ajoutons à
+    \c contacts et nous affichons un QMessageBox pour informer l'utilisateur
+    que le contact a été ajouté.
+
+    \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part2
+
+    Si le contact existe déjà, nous affichons un QMessageBox pour informer
+    l'utilisateur du problème.
+    Notre objet \c contacts est basé sur des paires clé-valeur formés par
+    le nom et l'adresse, nous voulons nous assurer que la \e clé est unique.
+
+    \o Une fois que les deux vérifications précédentes ont été traitées,
+    nous restaurons les boutons à leur état normal à l'aide du code
+    suivant:
+
+    \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part3
+
+    \endlist
+
+    La capture d'écran ci-dessous montre l'affichage fournit par un objet
+    QMessageBox, utilisé ici pour afficher un message d'information
+    à l'utilisateur:
+
+    \image addressbook-tutorial-part2-add-successful.png
+
+    La méthode \c cancel() restaure les détails du dernier contact, active
+    \c addButton, et cache \c submitButton et \c cancelButton.
+
+    \snippet tutorials/addressbook/part2/addressbook.cpp cancel
+
+    L'idée générale pour augmenter la flexibilité lors de l'ajout d'un 
+    contact est de donner la possiblité de cliquer sur "Add" 
+    ou "Cancel" à n'importe quel moment.
+    L'organigramme ci-dessous reprend l'ensemble des interactions dévelopées
+    jusqu'ici:
+
+    \image addressbook-tutorial-part2-add-flowchart.png
+*/
+
+/*!
+    \page tutorials-addressbook-fr-part3.html
+    \previouspage {tutorials/addressbook-fr/part2}{Chapitre 2}
+    \contentspage {Tutoriel "Carnet d'adresses"}{Sommaire}
+    \nextpage {tutorials/addressbook-fr/part4}{Chapitre 4}
+    \example tutorials/addressbook-fr/part3
+    \title Carnet d'adresses 3 - Navigation entre les éléments
+
+    L'application "Carnet d'adresses" est maintenant à moitié terminée. Il
+    nous faut maintenant ajouter quelques fonctions pour naviguer entre
+    les contacts. Avant de commencer, il faut se décider sur le type de structure de
+    données le plus approprié pour stocker les contacts.
+
+    Dans le chapitre 2, nous avons utilisé un QMap utilisant des paires clé-valeur,
+    avec le nom du contact comme \e clé, et l'adresse du contact comme \e valeur.
+    Cela fonctionnait bien jusqu'ici, mais pour ajouter la navigation entre les
+    entrées, quelques améliorations sont nécessaires.
+
+    Nous améliorerons le QMap en le faisant ressembler à une structure de données
+    similaire à une liste liée, où tous les éléments sont connectés, y compris
+    le premier et le dernier élément. La figure ci-dessous illustre cette structure
+    de donnée.
+
+    \image addressbook-tutorial-part3-linkedlist.png
+
+    \section1 Définition de la classe AddressBook
+
+    Pour ajouter les fonctions de navigation au carnet d'adresses, nous avons
+    besoin de deux slots supplémentaires dans notre classe \c AddressBook:
+    \c next() et \c previous(). Ceux-ci sont ajoutés au fichier addressbook.h:
+
+    \snippet tutorials/addressbook/part3/addressbook.h navigation functions
+
+    Nous avons aussi besoin de deux nouveaux objets QPushButton, nous ajoutons
+    donc les variables privées \c nextButton et \c previousButton.
+
+    \snippet tutorials/addressbook/part3/addressbook.h navigation pushbuttons
+
+    \section1 Implémentation de la classe AddressBook
+
+    A l'intérieur du constructeur de \c AddressBook, dans \c addressbook.cpp, nous
+    instancions \c nextButton et \c previousButton et nous les désactivons
+    par défaut. Nous faisons ceci car la navigation ne doit être activée
+    que lorsqu'il y a plus d'un contact dans le carnet d'adresses.
+
+    \snippet tutorials/addressbook/part3/addressbook.cpp navigation pushbuttons
+
+    Nous connectons alors ces boutons à leur slots respectifs:
+
+    \snippet tutorials/addressbook/part3/addressbook.cpp connecting navigation signals
+
+    L'image ci-dessous montre l'interface utilisateur que nous allons créer.
+    Remarquez que cela ressemble de plus en plus à l'interface du programme
+    complet.
+
+    \image addressbook-tutorial-part3-screenshot.png
+
+    Nous suivons les conventions pour les fonctions \c next() et \c previous()
+    en plaçant \c nextButton à droite et \c previousButton à gauche. Pour
+    faire cette mise en page intuitive, nous utilisons un QHBoxLayout pour
+    placer les widgets côte à côte:
+
+    \snippet tutorials/addressbook/part3/addressbook.cpp navigation layout
+
+    L'objet QHBoxLayout, \c buttonLayout2, est ensuite ajouté à \c mainLayout.
+
+    \snippet tutorials/addressbook/part3/addressbook.cpp adding navigation layout
+
+    La figure ci-dessous montre les systèmes de coordonnées pour les widgets du
+    \c mainLayout.
+    \image addressbook-tutorial-part3-labeled-layout.png
+
+    Dans notre méthode \c addContact(), nous avons desactivé ces boutons 
+    pour être sûr que l'utilisateur n'utilise pas la navigation lors de 
+    l'ajout d'un contact.
+
+    \snippet tutorials/addressbook/part3/addressbook.cpp disabling navigation
+
+    Dans notre méthode \c submitContact(), nous activons les boutons de
+    navigation, \c nextButton et \c previousButton, en fonction de la
+    taille de \c contacts. Commen mentionné plus tôt, la navigation n'est 
+    activée que si il y a plus d'un contact dans le carnet d'adresses.
+    Les lignes suivantes montrent comment faire cela:
+
+    \snippet tutorials/addressbook/part3/addressbook.cpp enabling navigation
+
+    Nous incluons aussi ces lignes de code dans le bouton \c cancel().
+
+    Souvenez vous que nous voulons émuler une liste-liée ciruculaire à
+    l'aide de l'objet QMap, \c contacts. Pour faire cela, nous obtenons un itérateur 
+    sur \c contact dans la méthode \c next(), et ensuite:
+
+    \list
+        \o Si l'itérateur n'est pas à la fin de \c contacts, nous l'incrémentons
+        \o Si l'itérateur est à la fin de \c contacts, nous changeons sa position
+        jusqu'au début de \c contacts. Cela donne l'illusion que notre QMap 
+        fonctionne comme une liste circulaire.
+    \endlist
+
+    \snippet tutorials/addressbook/part3/addressbook.cpp next() function
+
+    Une fois que nous avons itéré jusqu'à l'objet recherché dans \c contacts,
+    nous affichons son contenu sur \c nameLine et \c addressText.
+
+    De la même façon, pour la méthode \c previous(), nous obtenons un 
+    itérateur sur \c contacts et ensuite:
+
+    \list
+        \o Si l'itérateur est à la fin de \c contacts, on réinitialise
+           l'affichage et on retourne.
+        \o Si l'itérateur est au début de \c contacts, on change sa 
+           position jusqu'à la fin
+        \o Ensuite, on décrémente l'itérateur
+    \endlist
+
+    \snippet tutorials/addressbook/part3/addressbook.cpp previous() function
+
+    à nouveau, nous affichons le contenu de l'objet courant dans \c contacts.
+
+*/
+
+/*!
+
+    \page tutorials-addressbook-fr-part4.html
+    \previouspage {tutorials/addressbook-fr/part3}{Chapitre 3}
+    \contentspage {Tutoriel "Carnet d'adresses"}{Sommaire}
+    \nextpage {tutorials/addressbook-fr/part5}{Chapitre 5}
+    \example tutorials/addressbook-fr/part4
+    \title Carnet d'Adresses 4 - éditer et supprimer des adresses
+
+
+    Dans ce chapitre, nous verrons comment modifier les données des contacts
+    contenus dans l'application carnet d'adresses.
+
+
+    \image addressbook-tutorial-screenshot.png
+
+    Nous avons maintenant un carnet d'adresses qui ne se contente pas de
+    lister des contacts de façon ordonnée, mais permet également la 
+    navigation. Il serait pratique d'inclure des fonctions telles qu'éditer et
+    supprimer, afin que les détails associés à un contact puissent être
+    modifiés lorsque c'est nécessaire. Cependant, cela requiert une légère
+    modification, sous la forme d'énumérations. Au chapitre précédent, nous avions deux
+    modes: \c {AddingMode} et \c {NavigationMode}, mais ils n'étaient pas
+    définis en tant qu'énumérations. Au lieu de ça, on activait et désactivait les
+    boutons correspondants manuellement, au prix de multiples redondances dans
+    le code.
+
+    Dans ce chapitre, on définit l'énumération \c Mode avec trois valeurs possibles.
+
+    \list
+        \o \c{NavigationMode},
+        \o \c{AddingMode}, et
+        \o \c{EditingMode}.
+    \endlist
+
+    \section1 Définition de la classe AddressBook
+
+    Le fichier \c addressbook.h est mis a jour pour contenir l'énumération \c Mode :
+
+    \snippet tutorials/addressbook/part4/addressbook.h Mode enum
+
+    On ajoute également deux nouveaux slots, \c editContact() et
+    \c removeContact(), à notre liste de slots publics.
+
+    \snippet tutorials/addressbook/part4/addressbook.h edit and remove slots
+
+    Afin de basculer d'un mode à l'autre, on introduit la méthode
+    \c updateInterface() pour contrôller l'activation et la désactivation de
+    tous les objets QPushButton. On ajoute également deux nouveaux boutons,
+    \c editButton et \c removeButton, pour les fonctions d'édition
+    et de suppression mentionnées plus haut.
+
+    \snippet tutorials/addressbook/part4/addressbook.h updateInterface() declaration
+    \dots
+    \snippet tutorials/addressbook/part4/addressbook.h buttons declaration
+    \dots
+    \snippet tutorials/addressbook/part4/addressbook.h mode declaration
+
+    Enfin, on déclare \c currentMode pour garder une trace du mode 
+    actuellement utilisé.
+
+    \section1 Implémentation de la classe AddressBook
+
+    Il nous faut maintenant implémenter les fonctionnalités de changement de
+    mode de l'application carnet d'adresses. Les boutons \c editButton et
+    \c removeButton sont instanciés et désactivés par défaut, puisque le
+    carnet d'adresses démarre sans aucun contact en mémoire.
+
+    \snippet tutorials/addressbook/part4/addressbook.cpp edit and remove buttons
+
+    Ces boutons sont ensuite connectés à leurs slots respectifs,
+    \c editContact() et \c removeContact(), avant d'être ajoutés à
+    \c buttonLayout1.
+
+    \snippet tutorials/addressbook/part4/addressbook.cpp connecting edit and remove
+    \dots
+    \snippet tutorials/addressbook/part4/addressbook.cpp adding edit and remove to the layout
+
+    La methode \c editContact() place les anciens détails du contact dans
+    \c oldName et \c oldAddress, avant de basculer vers le mode
+    \c EditingMode. Dans ce mode, les boutons \c submitButton et
+    \c cancelButton sont tous deux activés, l'utilisateur peut par conséquent
+    modifier les détails du contact et cliquer sur l'un de ces deux boutons
+    par la suite.
+
+    \snippet tutorials/addressbook/part4/addressbook.cpp editContact() function
+
+    La méthode \c submitContact() a été divisée en deux avec un bloc
+    \c{if-else}. On teste \c currentMode pour voir si le mode courant est
+    \c AddingMode. Si c'est le cas, on procède à l'ajout.
+
+    \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function beginning
+    \dots
+    \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part1
+
+    Sinon, on s'assure que \c currentMode est en \c EditingMode. Si c'est le
+    cas, on compare \c oldName et \c name. Si le nom a changé, on supprime
+    l'ancien contact de \c contacts et on insère le contact mis a jour.
+
+    \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part2
+
+    Si seule l'adresse a changé (i.e. \c oldAddress n'est pas identique à
+    \c address), on met à jour l'adresse du contact. Enfin on règle
+    \c currentMode à \c NavigationMode. C'est une étape importante puisque
+    c'est cela qui réactive tous les boutons désactivés.
+
+    Afin de retirer un contact du carnet d'adresses, on implémente la méthode
+    \c removeContact(). Cette méthode vérifie que le contact est présent dans
+    \c contacts.
+
+    \snippet tutorials/addressbook/part4/addressbook.cpp removeContact() function
+
+    Si c'est le cas, on affiche une boîte de dialogue QMessageBox, demandant
+    confirmation de la suppression à l'utilisateur. Une fois la confirmation
+    effectuée, on appelle \c previous(), afin de s'assurer que l'interface
+    utilisateur affiche une autre entrée, et on supprime le contact en
+    utilisant le méthode \l{QMap::remove()}{remove()} de \l{QMap}. Dans un
+    souci pratique, on informe l'utilisateur de la suppression par le biais
+    d'une autre QMessageBox. Les deux boîtes de dialogue utilisées dans cette
+    méthode sont représentées ci-dessous.
+
+    \image addressbook-tutorial-part4-remove.png
+
+    \section2 Mise à jour de l'Interface utilisateur
+
+    On a évoqué plus haut la méthode \c updateInterface() comme moyen
+    d'activer et de désactiver les différents boutons de l'interface en
+    fonction du mode. Cette méthode met à jour le mode courant selon
+    l'argument \c mode qui lui est passé, en l'assignant à \c currentMode,
+    avant de tester sa valeur.
+
+    Chacun des boutons est ensuite activé ou désactivé, en fonction du mode.
+    Le code source pour les cas \c AddingMode et \c EditingMode est visible 
+    ci-dessous:
+
+    \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 1
+
+    Dans le cas de \c NavigationMode, en revanche, des tests conditionnels
+    sont passés en paramètre de QPushButton::setEnabled(). Ceci permet de
+    s'assurer que les boutons \c editButton et \c removeButton ne sont activés
+    que s'il existe au moins un contact dans le carnet d'adresses;
+    \c nextButton et \c previousButton ne sont activés que lorsqu'il existe
+    plus d'un contact dans le carnet d'adresses.
+
+    \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 2
+
+    En effectuant les opérations de réglage du mode et de mise à jour de
+    l'interface utilisateur au sein de la même méthode, on est à l'abri de
+    l'éventualité où l'interface utilisateur se "désynchronise" de l'état
+    interne de l'application.
+
+*/
+
+/*!
+    \page tutorials-addressbook-fr-part5.html
+    \previouspage {tutorials/addressbook-fr/part4}{Chapitre 4}
+    \contentspage {Tutoriel "Carnet d'adresses"}{Sommaire}
+    \nextpage {tutorials/addressbook-fr/part6}{Chapitre 6}
+    \example tutorials/addressbook-fr/part5
+    \title Carnet d'adresse 5 - Ajout d'une fonction de recherche
+
+    Dans ce chapitre, nous allons voir les possibilités pour rechercher
+    des contacts dans le carnet d'adresse.
+
+    \image addressbook-tutorial-part5-screenshot.png
+
+    Plus nous ajoutons des contacts dans l'application, plus
+    il devient difficile de naviguer avec les boutons \e Next et \e Previous.
+    Dans ce cas, une fonction de recherche serait plus efficace pour rechercher
+    les contacts.
+    La capture d'écran ci-dessus montre le bouton de recherche \e Find et sa position
+    dans le paneau de bouton.
+
+    Lorsque l'utilisateur clique sur le bouton \e Find, il est courant d'afficher
+    une boîte de dialogue qui demande à l'utilisateur d'entrer un nom de contact.
+    Qt fournit la classe QDialog, que nous sous-classons dans ce chapitre pour
+    implémenter la class \c FindDialog.
+
+    \section1 Définition de la classe FindDialog
+
+    \image addressbook-tutorial-part5-finddialog.png
+
+    Pour sous-classer QDialog, nous commençons par inclure le header de
+    QDialog dans le fichier \c finddialog.h. De plus, nous déclarons les
+    classes QLineEdit et QPushButton car nous utilisons ces widgets dans
+    notre classe dialogue.
+
+    Tout comme dans la classe \c AddressBook, la classe \c FindDialog utilise
+    la macro Q_OBJECT et son constructeur est défini de façon à accepter
+    un QWidget parent, même si cette boîte de dialogue sera affichée dans une
+    fenêtre séparée.
+
+    \snippet tutorials/addressbook/part5/finddialog.h FindDialog header
+
+    Nous définissons la méthode publique \c getFindText() pour être utilisée
+    par les classes qui instancient \c FindDialog, ce qui leur permet d'obtenir
+    le texte entré par l'utilisateur. Un slot public, \c findClicked(), est
+    défini pour prendre en charge le texte lorsque l'utilisateur clique sur
+    le bouton \gui Find.
+
+    Finalement, nous définissons les variables privées \c findButton,
+    \c lineEdit et \c findText, qui correspondent respectivement au bouton
+    \gui Find, au champ de texte dans lequel l'utilisateur tape le texte
+    à rechercher, et à une variable interne stockant le texte pour une
+    utilisation ultérieure.
+
+    \section1 Implémentation de la classe FindDialog
+
+    Dans le constructeur de \c FindDialog, nous instancions les objets des
+    variables privées \c lineEdit, \c findButton et \c findText. Nous utilisons ensuite
+    un QHBoxLayout pour positionner les widgets.
+
+    \snippet tutorials/addressbook/part5/finddialog.cpp constructor
+
+    Nous mettons en place la mise en page et le titre de la fenêtre, et
+    nous connectons les signaux aux slots. Remarquez que le signal
+    \l{QPushButton::clicked()}{clicked()} de \c{findButton} est connecté
+    à \c findClicked() et \l{QDialog::accept()}{accept()}. Le slot
+    \l{QDialog::accept()}{accept()} fourni par le QDialog ferme
+    la boîte de dialogue et lui donne le code de retour \l{QDialog::}{Accepted}.
+    Nous utilisons cette fonction pour aider la méthode \c findContact() de la classe
+    \c{AddressBook} à savoir si l'objet \c FindDialog a été fermé. Ceci sera
+    expliqué plus loin lorsque nous verrons la méthode \c findContact().
+
+    \image addressbook-tutorial-part5-signals-and-slots.png
+
+    Dans \c findClicked(), nous validons le champ de texte pour nous
+    assurer que l'utilisateur n'a pas cliqué sur le bouton \gui Find sans
+    avoir entré un nom de contact. Ensuite, nous stockons le texte du champ
+    d'entrée \c lineEdit dans \c findText. Et finalement nous vidons le
+    contenu de \c lineEdit et cachons la boîte de dialogue.
+
+    \snippet tutorials/addressbook/part5/finddialog.cpp findClicked() function
+
+    La variable \c findText a un accesseur publique associé: \c getFindText().
+    Étant donné que nous ne modifions \c findText directement que dans le
+    constructeur et la méthode \c findClicked(), nous ne créons pas
+    de manipulateurs associé à \c getFindText().
+    Puisque \c getFindText() est publique, les classes instanciant et
+    utilisant \c FindDialog peuvent toujours accéder à la chaîne de
+    caractères que l'utilisateur a entré et accepté.
+
+    \snippet tutorials/addressbook/part5/finddialog.cpp getFindText() function
+
+    \section1 Définition de la classe AddressBook
+
+    Pour utiliser \c FindDialog depuis la classe \c AddressBook, nous
+    incluons \c finddialog.h dans le fichier \c addressbook.h.
+
+    \snippet tutorials/addressbook/part5/addressbook.h include finddialog's header
+
+    Jusqu'ici, toutes les fonctionnalités du carnet d'adresses ont un
+    QPushButton et un slot correspondant. De la même façon, pour la
+    fonctionnalité \gui Find, nous avons \c findButton et \c findContact().
+
+    Le \c findButton est déclaré comme une variable privée et la
+    méthode \c findContact() est déclarée comme un slot public.
+
+    \snippet tutorials/addressbook/part5/addressbook.h findContact() declaration
+    \dots
+    \snippet tutorials/addressbook/part5/addressbook.h findButton declaration
+
+    Finalement, nous déclarons la variable privée \c dialog que nous allons
+    utiliser pour accéder à une instance de \c FindDialog.
+
+    \snippet tutorials/addressbook/part5/addressbook.h FindDialog declaration
+
+    Une fois que nous avons instancié la boîte de dialogue, nous voulons l'utiliser
+    plus qu'une fois. Utiliser une variable privée nous permet d'y référer
+    à plus d'un endroit dans la classe.
+
+    \section1 Implémentation de la classe AddressBook
+
+    Dans le constructeur de \c AddressBook, nous instancions nos objets privés,
+    \c findbutton et \c findDialog:
+
+    \snippet tutorials/addressbook/part5/addressbook.cpp instantiating findButton
+    \dots
+    \snippet tutorials/addressbook/part5/addressbook.cpp instantiating FindDialog
+
+    Ensuite, nous connectons le signal \l{QPushButton::clicked()}{clicked()} de
+    \c{findButton} à \c findContact().
+
+    \snippet tutorials/addressbook/part5/addressbook.cpp signals and slots for find
+
+    Maintenant, tout ce qui manque est le code de notre méthode \c findContact():
+
+    \snippet tutorials/addressbook/part5/addressbook.cpp findContact() function
+
+    Nous commençons par afficher l'instance de \c FindDialog, \c dialog.
+    L'utilisateur peut alors entrer le nom du contact à rechercher. Lorsque
+    l'utilisateur clique sur le bouton \c findButton, la boîte de dialogue est
+    masquée et le code de retour devient QDialog::Accepted. Ce code de retour
+    vient remplir la condition du premier if.
+
+    Ensuite, nous extrayons le texte que nous utiliserons pour la recherche,
+    il s'agit ici de \c contactName obtenu à l'aide de la méthode \c getFindText()
+    de \c FindDialog. Si le contact existe dans le carnet d'adresse, nous
+    l'affichons directement. Sinon, nous affichons le QMessageBox suivant pour
+    indiquer que la recherche à échouée.
+
+    \image addressbook-tutorial-part5-notfound.png
+*/
+
+/*!
+    \page tutorials-addressbook-part6.html
+    \previouspage {tutorials/addressbook-fr/part5}{Chapitre 5}
+    \contentspage {Tutoriel "Carnet d'adresses"}{Sommaire}
+    \nextpage {tutorials/addressbook-fr/part7}{Chapitre 7}
+    \example tutorials/addressbook-fr/part6
+    \title Carnet d'Adresses 6 - Sauvegarde et chargement
+
+    Ce chapitre couvre les fonctionnalités de gestion des fichiers de Qt que
+    l'on utilise pour écrire les procédures de sauvegarde et chargement pour
+    l'application carnet d'adresses.
+
+    \image addressbook-tutorial-part6-screenshot.png
+
+    Bien que la navigation et la recherche de contacts soient des
+    fonctionnalités importantes, notre carnet d'adresses ne sera pleinement
+    utilisable qu'une fois que l'on pourra sauvegarder les contacts existants
+    et les charger à nouveau par la suite.
+    Qt fournit de nombreuses classes pour gérer les \l{Input/Output and
+    Networking}{entrées et sorties}, mais nous avons choisi de nous contenter d'une
+    combinaison de deux classes simples à utiliser ensemble: QFile et QDataStream.
+
+    Un objet QFile représente un fichier sur le disque qui peut être lu, et
+    dans lequel on peut écrire. QFile est une classe fille de la classe plus
+    générique QIODevice, qui peut représenter différents types de
+    périphériques.
+
+    Un objet QDataStream est utilisé pour sérialiser des données binaires
+    dans le but de les passer à un QIODevice pour les récupérer dans le
+    futur. Pour lire ou écrire dans un QIODevice, il suffit d'ouvrir le
+    flux, avec le périphérique approprié en paramètre, et d'y lire ou
+    écrire.
+
+    \section1 Définition de la classe AddressBook
+
+    On déclare deux slots publics, \c saveToFile() et \c loadFromFile(), 
+    ainsi que deux objets QPushButton, \c loadButton et \c saveButton.
+
+    \snippet tutorials/addressbook/part6/addressbook.h save and load functions declaration
+    \dots
+    \snippet tutorials/addressbook/part6/addressbook.h save and load buttons declaration
+
+    \section1 Implémentation de la classe AddressBook
+
+    Dans notre constructeur, on instancie \c loadButton et \c saveButton.
+    Idéalement, l'interface serait plus conviviale avec des boutons
+    affichant "Load contacts from a file" et "Save contacts to a file". Mais
+    compte tenu de la dimension des autres boutons, on initialise les labels
+    des boutons à \gui{Load...} et \gui{Save...}. Heureusement, Qt offre une
+    façon simple d'ajouter des info-bulles avec
+    \l{QWidget::setToolTip()}{setToolTip()}, et nous l'exploitons de la façon
+    suivante pour nos boutons:
+
+    \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 1
+    \dots
+    \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 2
+
+    Bien qu'on ne cite pas le code correspondant ici, nous ajoutons ces deux boutons au
+    layout de droite, \c button1Layout, comme pour les fonctionnalités précédentes, et 
+    nous connectons leurs signaux
+    \l{QPushButton::clicked()}{clicked()} à leurs slots respectifs.
+
+    Pour la sauvegarde, on commence par récupérer le nom de fichier 
+    \c fileName, en utilisant QFileDialog::getSaveFileName(). C'est une
+    méthode pratique fournie par QFileDialog, qui ouvre une boîte de
+    dialogue modale et permet à l'utilisateur d'entrer un nom de fichier ou
+    de choisir un fichier \c{.abk} existant. Les fichiers \c{.abk}
+    correspondent à l'extension choisie pour la sauvegarde des contacts de
+    notre carnet d'adresses.
+
+    \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part1
+
+    La boîte de dialogue affichée est visible sur la capture d'écran ci-
+    dessous.
+
+    \image addressbook-tutorial-part6-save.png
+
+    Si \c fileName n'est pas vide, on crée un objet QFile, \c file, à partir
+    de \c fileName. QFile fonctionne avec QDataStream puisqu'il dérive de
+    QIODevice.
+
+    Ensuite, on essaie d'ouvrir le fichier en écriture, ce qui correspond au
+    mode \l{QIODevice::}{WriteOnly}. Si cela échoue, on en informe
+    l'utilisateur avec une QMessageBox.
+
+    \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part2
+
+    Dans le cas contraire, on instancie un objet QDataStream, \c out, afin
+    d'écrire dans le fichier ouvert. QDataStream nécessite que la même
+    version de flux soit utilisée pour la lecture et l'écriture. On s'assure
+    que c'est le cas en spécifiant explicitement d'utiliser la
+    \l{QDataStream::Qt_4_5}{version introduite avec Qt 4.5} avant de
+    sérialiser les données vers le fichier \c file.
+
+    \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part3
+
+    Pour le chargement, on récupère également \c fileName en utilisant
+    QFileDialog::getOpenFileName(). Cette méthode est l'homologue de
+    QFileDialog::getSaveFileName() et affiche également une boîte de
+    dialogue modale permettant à l'utilisateur d'entrer un nom de fichier ou
+    de selectionner un fichier \c{.abk} existant, afin de le charger dans le
+    carnet d'adresses.
+
+    \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part1
+
+    Sous Windows, par exemple, cette méthode affiche une boîte de dialogue
+    native pour la sélection de fichier, comme illustré sur la capture
+    d'écran suivante:
+
+    \image addressbook-tutorial-part6-load.png
+
+    Si \c fileName n'est pas vide, on utilise une fois de plus un objet
+    QFile, \c file, et on tente de l'ouvrir en lecture, avec le mode
+    \l{QIODevice::}{ReadOnly}. De même que précédemment dans notre
+    implémentation de \c saveToFile(), si cette tentative s'avère
+    infructueuse, on en informe l'utilisateur par le biais d'une
+    QMessageBox.
+
+    \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part2
+
+    Dans le cas contraire, on instancie un objet QDataStream, \c in, en
+    spécifiant la version à utiliser comme précédemment, et on lit les
+    informations sérialisées vers la structure de données \c contacts. Notez
+    qu'on purge \c contacts avant d'y mettre les informations lues afin de
+    simplifier le processus de lecture de fichier. Une façon plus avancée de
+    procéder serait de lire les contacts dans un objet QMap temporaire, et
+    de copier uniquement les contacts n'existant pas encore dans
+    \c contacts.
+
+    \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part3
+
+    Pour afficher les contacts lus depuis le fichier, on doit d'abord
+    valider les données obtenues afin de s'assurer que le fichier lu
+    contient effectivement des entrées de carnet d'adresses. Si c'est le
+    cas, on affiche le premier contact; sinon on informe l'utilisateur du
+    problème par une QMessageBox. Enfin, on met à jour l'interface afin
+    d'activer et de désactiver les boutons de façon appropriée.
+*/
+
+/*!
+    \page tutorials-addressbook-fr-part7.html
+    \previouspage {tutorials/addressbook-fr/part6}{Chapitre 6}
+    \contentspage {Tutoriel "Carnet d'adresses"}{Sommaire}
+    \example tutorials/addressbook-fr/part7
+    \title Carnet d'adresse 7 - Fonctionnalités avancées
+
+    Ce chapitre couvre quelques fonctionnalités additionnelles qui
+    feront de notre carnet d'adresses une application plus pratique
+    pour une utilisation quotidienne.
+
+    \image addressbook-tutorial-part7-screenshot.png
+
+    Bien que notre application carnet d'adresses soit utile en tant que telle,
+    il serait pratique de pouvoir échanger les contacts avec d'autres applications.
+    Le format vCard est un un format de fichier populaire pour échanger
+    ce type de données.
+    Dans ce chapitre, nous étendrons notre carnet d'adresses pour permettre
+    d'exporter des contacts dans des fichiers vCard \c{.vcf}.
+
+    \section1 Définition de la classe AddressBook
+
+    Nous ajoutons un objet QPushButton, \c exportButton, et un slot
+    public correspondant, \c exportAsVCard(), à notre classe \c AddressBook 
+    dans le fichier \c addressbook.h.
+
+    \snippet tutorials/addressbook/part7/addressbook.h exportAsVCard() declaration
+    \dots
+    \snippet tutorials/addressbook/part7/addressbook.h exportButton declaration
+
+    \section1 Implémentation de la classe AddressBook
+
+    Dans le constructeur de \c AddressBook, nous connectons le signal
+    \l{QPushButton::clicked()}{clicked()} de \c{exportButton} au slot
+    \c exportAsVCard().
+    Nous ajoutons aussi ce bouton à \c buttonLayout1, le layout responsable
+    du groupe de boutons sur la droite.
+
+    Dans la méthode \c exportAsVCard(), nous commençons par extraire le
+    nom du contact dans \n name. Nous déclarons \c firstname, \c lastName et
+    \c nameList.
+    Ensuite, nous cherchons la position du premier espace blanc de \c name.
+    Si il y a un espace, nous séparons le nom du contact en \c firstName et
+    \c lastName. Finalement, nous remplaçons l'espace par un underscore ("_").
+    Si il n'y a pas d'espace, nous supposons que le contact ne comprend que
+    le prénom.
+
+    \snippet tutorials/addressbook/part7/addressbook.cpp export function part1
+
+    Comme pour la méthode \c saveToFile(), nous ouvrons une boîte de dialogue
+    pour donner la possibilité à l'utilisateur de choisir un emplacement pour
+    le fichier. Avec le nom de fichier choisi, nous créons une instance de QFile
+    pour y écrire.
+
+    Nous essayons d'ouvrir le fichier en mode \l{QIODevice::}{WriteOnly}. Si
+    cela échoue, nous affichons un QMessageBox pour informer l'utilisateur
+    à propos de l'origine du problème et nous quittons la méthode. Sinon, nous passons le
+    fichier comme paramètre pour créer un objet QTextStream, \c out. De la même façon que
+    QDataStream, la classe QTextStream fournit les fonctionnalités pour 
+    lire et écrire des fichiers de texte. Grâce à celà, le fichier \c{.vcf}
+    généré pourra être ouvert et édité à l'aide d'un simple éditeur de texte.
+
+    \snippet tutorials/addressbook/part7/addressbook.cpp export function part2
+
+    Nous écrivons ensuite un fichier vCard avec la balise \c{BEGIN:VCARD},
+    suivit par \c{VERSION:2.1}.
+    Le nom d'un contact est écrit à l'aide de la balise \c{N:}. Pour la balise
+    \c{FN:}, qui remplit le titre du contact, nous devons vérifier si le contact
+    à un nom de famille défini ou non. Si oui, nous utilions les détails de
+    \c nameList pour remplir le champ, dans le cas contraire on écrit uniquement le contenu
+    de \c firstName.
+ 
+    \snippet tutorials/addressbook/part7/addressbook.cpp export function part3
+
+    Nous continuons en écrivant l'adresse du contact. Les points-virgules
+    dans l'adresse sont échappés à l'aide de "\\", les retours de ligne sont
+    remplacés par des points-virgules, et les vigules sont remplacées par des espaces.
+    Finalement nous écrivons les balises  \c{ADR;HOME:;} suivies par l'adresse
+    et la balise \c{END:VCARD}.
+
+    \snippet tutorials/addressbook/part7/addressbook.cpp export function part4
+
+    À la fin de la méthode, un QMessageBox est affiché pour informer l'utilisateur
+    que la vCard a été exportée avec succès. 
+
+    \e{vCard est une marque déposée de \l{http://www.imc.org}
+    {Internet Mail Consortium}}.
+*/