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