Mis à jour le jeudi 10 janvier 2013
  • Facile
Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Introduction du cours

Parfois, dans vos programmes Qt, vous avez peut-être déjà eu besoin de garder en mémoire certaines informations souvent liées à la configuration.

Par exemple :

  • la taille et la position de la fenêtre ;

  • les options du programme ;

  • le thème ;

  • etc.

Évidemment, pour se "souvenir" de ces données au prochain lancement du programme, il faut les stocker définitivement sur le disque dur, sous forme de fichier. Qt propose pour ça la classe QFile.
Problème : des options sont souvent des informations simples, qui se résument généralement par "cette donnée vaut cette valeur, cette option est activée, etc.".
Utiliser un fichier pour faire cela, c'est un peu exagéré.

Il y a une autre contrainte avec un fichier : comment différencier chaque option ?

Je sais, on fait une ligne par donnée, et hop c'est dans la poche ! :D

Non, car cette méthode ne serait pas très souple : en effet, il y aurait un ordre précis, ce serait dur à maintenir et à modifier.

La meilleure solution, c'est d'utiliser la classe QSettings, qui a été spécialement créée (que de "e" dans un même mot... :p ) pour enregistrer des options !

Comment ça marche ?

Un peu de théorie est nécessaire pour commencer, sinon il va être impossible d'expliquer comment manipuler les données.

La structure d'un fichier d'options

Quand on sauvegarde des options avec QSettings, on va en fait écrire une série de données qui vont chacune contenir une information (cette information doit pouvoir varier, sinon il n'y a pas d'intérêt de la garder en mémoire :lol: ).

Comme tout programmeur qui se respecte, vous allez devoir utiliser du vocabulaire précis :

  • chaque donnée est appelée une clé : c'est le nom de l'information, qui permet de la différencier des autres ;

  • l'information que porte chaque clé est la valeur.

Un fichier d'options peut donc être représenté de cette façon :

Image utilisateur

Figurez-vous que, comme dans un OS, on peut également structurer les informations en les regroupant dans des dossiers : on parle alors de sous-clé ; c'est une clé un peu spéciale, elle n'a pas de valeur, elle contient juste d'autres clés, exactement comme un dossier contient des fichiers.

Le même schéma que le précédent mais avec les sous-clés en plus :

Image utilisateur

Les différentes techniques de stockage

QSettings propose 3 formats pour le fichier d'options.

  • Le format natif : ce format n'en est pas vraiment un, du fait qu'il dépend de votre OS. C'est le plus simple à utiliser puisque QSettings va gérer la création du fichier. ;)

  • Le format INI : le fichier a l'extension .ini, format de base des options de configuration.

  • Un format invalide : ce dernier produit un format personnalisé, mais il est trop compliqué pour nous y intéresser dans ce tutoriel (il faut par exemple définir ses propres fonctions de lecture et écriture :-° ).

Le format natif

Les options vont être stockées vraiment différemment selon les OS. Voici un petit tableau représentatif :

OS

Format

Unix

Les options sont écrites dans un fichier texte, avec l'extension .conf.

Mac OS X

Les options sont stockées dans le dossier des préférences système
(d'après la doc : "the CFPreferences API"), dans des fichiers spéciaux .plist.

Windows

Ici, pas de fichiers, on utilise directement le registre système
(rassurez-vous, si vous utilisez bien QSettings, il n'y aucun risque de dommage ^^ ).

Le format INI

Comme je l'ai dit précédemment, ce format force la création d'un fichier .ini, quel que soit l'OS utilisé.

On peut alors définir un chemin différent du chemin par défaut (qui n'est pas très accessible :p ), et c'est plus facile pour une éventuelle maintenance.

Maintenant que tout est clair, nous allons pouvoir commencer les choses sérieusement ! :pirate:

Créer un fichier d'options

Avant de commencer, créez un nouveau projet.
Comme on ne va pas créer de fenêtre (du moins pas dans cette partie), vous aurez seulement besoin du main.cpp :

#include <QApplication>
#include <QWidget>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QWidget widget;
    widget.show();

    return app.exec();
}

Nous allons créer un nouveau fichier d'options en créant un nouvel objet QSettings.
Voici le constructeur :

QSettings::QSettings ( const QString &amp; organization, const QString &amp; application = QString(), QObject * parent = 0 )

Le dernier argument (l'objet parent) est un QObject (vous pouvez mettre n'importe quelle classe de Qt) qui se chargera de libérer votre objet de la mémoire en cas d'allocation dynamique. Vu que ce n'est pas le cas ici, nous allons seulement remplir les deux premiers : organization et application, qui sont le nom de votre équipe et le nom de votre programme.

Mais qu'est-ce qu'on en a à faire du nom de notre équipe et de notre programme ? o_O Ça n'aurait pas été mieux de dire le chemin ou le nom du fichier ?

La raison vient du fait que nous allons utiliser le format natif pour notre fichier d'options (rappelez-vous, celui qui dépend de votre OS). Vous ne pouviez pas le savoir, puisqu'on ne l'a pas précisé dans le constructeur, car c'est le format par défaut.
Comme on utilise un chemin de stockage totalement différent selon les OS, l'emplacement du fichier ne peut être précisé. Le fichier sera créé dans le répertoire des configurations de votre OS.

Du coup, pour le différencier des autres, QSettings va le placer dans un sous-répertoire : un dossier portant le nom de votre programme, qui est lui-même contenu dans un dossier portant le nom de votre équipe.

C'est un peu compliqué, donc rien ne vaut un schéma pour expliquer :

Image utilisateur

Le constructeur

Si tout est clair, nous allons tester le constructeur. Nous allons choisir "sdz" comme nom d'équipe et "MonProgramme" comme nom de programme. Reprenez le main et ajoutez-y ces lignes :

#include <QApplication>
#include <QWidget>
#include <QSettings>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QWidget widget;
    widget.show();

    QSettings settings("sdz", "MonProgramme");

    return app.exec();
}

Compilez et lancez le programme : rien ne se passe (à part la fenêtre vide).
En fait, le programme vient de créer votre fichier, sans que vous ne vous en rendiez compte. Suivez ce tableau pour le retrouver :

OS

Emplacement

Unix

$HOME/.config/sdz/MonProgramme.conf
où $HOME est le répertoire de votre home

Mac OS X

$HOME/Library/Preferences/com.sdz.MonProgramme.plist
où $HOME est le répertoire de votre home

Windows

HKEY_CURRENT_USER\Software\sdz\MonProgramme
qui est un répertoire du registre système

Le cas de Windows

Euh, moi je suis sous Windows :euh: ... Et je n'ai pas tout compris à ton chemin bizarre et ton "registre système"...

Le registre système est en quelque sorte un immense fichier d'options qui contient absolument toute la configuration de votre ordinateur. Y sont stockés :

  • les options des programmes ;

  • les infos du panneau de configuration ;

  • les différents périphériques installés ;

  • mais aussi, comme son nom l'indique, des informations sur le système auxquelles il ne faut pas toucher si vous tenez à la santé de votre OS. :D

Étant structuré comme nos fichiers d'options, il contient beaucoup de sous-clés, que l'on considère comme des répertoires. Le chemin si bizarre que je vous ai donné plus haut est donc la liste des sous-clés à suivre pour accéder à votre programme.

Oui mais comment j'y accède moi au registre ? L'explorateur ne trouve pas le dossier HKEY_CURRENT_USER ! :colere2:

Il va falloir utiliser un logiciel spécial intégré à Windows, qui s'appelle regedit (pour REGistry EDITor, l'éditeur du registre). Celui-ci affiche, sous forme d'arborescence, la liste de toutes les clés et sous-clés qui ont été inscrites dans le registre (celles des autres programmes mais aussi celles du système). Il permet même d'éditer manuellement les valeurs de ces clés, mais ne faites cela que si vous êtes absolument sûrs de ce que vous faites (vous pourriez perdre des données importantes ou même foutre en l'air votre système :waw: ).

Pour ouvrir ce logiciel (il est bien caché), faites "Exécuter" dans le menu Démarrer, et tapez "regedit", sans les guillemets. Si vous avez un message de sécurité, acceptez-le. Voici comment se présente le programme sous Vista :

Image utilisateur

Déplacez-vous dans les sous-clés et allez jusqu'à l'emplacement de votre fichier d'options de vos sous-clés (c'est-à-dire HKEY_CURRENT_USER\Software\sdz\MonProgramme). Vous devriez voir ceci :

Image utilisateur

Conclusion

Vous avez créé votre fichier, mais pour l'instant il ne sert à rien. Il serait peut-être temps d'apprendre à le remplir ! ;)

Ecrire des données

Ecrire des clés

Voici la fonction de la classe QSettings qui permet d'écrire des clés :

void QSettings::setValue ( const QString &amp; key, const QVariant &amp; value )

Cette méthode prend donc deux arguments : le nom de la clé et sa valeur.

Gné c'est quoi cet argument o_O QVariant value... Et si je veux mettre un int ?

En fait, QVariant est une classe Qt, qui permet de stocker n'importe quel type de variable ou d'objet. En regardant la doc, on se rend compte que cette classe peut représenter un grand nombre de classes Qt (la liste complète...).

L'intérêt de cette classe réside dans le fait que l'on peut créer des fonctions qui acceptent tous les types de Qt, comme c'est le cas dans la méthode setValue ; la fonction se charge alors de convertir la QVariant passée en argument dans le type originel.

De plus, comble du bonheur, vous n'êtes pas obligés de créer un objet QVariant pour utiliser setValue : indiquez seulement votre objet ou variable, Qt se charge de le transformer en QVariant. Plus simple tu meurs. :D

Je teste, tu testes, il teste...

Essayons cette fonction avec le fichier d'options que l'on a créé tout à l'heure. Ici, je vais appeler ma clé "test" et elle aura pour valeur "true" (un booléen) :

#include <QApplication>
#include <QWidget>
#include <QSettings>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QWidget widget;
    widget.show();

    QSettings settings("sdz", "MonProgramme");
    settings.setValue("test", true);

    return app.exec();
}

Compilez et exécutez le code (vous verrez toujours la fenêtre vide). Normalement, la clé a dû être écrite (ou alors votre ordi ne marche pas :p ). Voici ce que vous devriez avoir dans votre fichier d'options :

Image utilisateur

Et dans le regedit :

Image utilisateur

Vous pouvez remarquer la clé appelée "(par défaut)" ;
c'est une fonction spécifique à Windows, cette clé sert à attribuer une valeur à la sous-clé actuelle
(si vous l'utilisez, votre programme ne sera pas portable !)

Y'a un truc qui m'asticote depuis tout à l'heure...
Et si je veux enregistrer un objet qui n'est pas dans la liste de la QVariant ?

Heureusement, les développeurs ont tout prévu : quand le deuxième argument ne peut être stocké dans la QVariant, il est automatiquement converti pour qu'il puisse être stocké. Vous pouvez donc écrire n'importe quel objet, même d'une classe que vous avez créée ! :p

Ecrire des sous-clés

Et voici la fonction qui permet d'écrire des sous-clés...

void QSettings::setValue ( const QString &amp; key, const QVariant &amp; value )

Eh, mais c'est la même que pour les clés ! :waw:

Ben oui. Et c'est normal.
En effet, on ne crée pas de sous-clés directement ; elles vont être ajoutées automatiquement en écrivant des clés stockées dans ces sous-clés.

Comment ? Cela va se passer dans le premier argument de la fonction. Je vous avais dit qu'il représentait le nom de la clé, eh bien... je vous ai menti. :honte:
On indique en réalité le chemin de la clé. Oui oui, comme pour un fichier, avec les slashes ! Comme tout à l'heure nous n'avions pas besoin de structurer notre fichier avec des sous-clés, il était inutile d'en créer.

Mais toutes les explications au monde ne vaudront jamais un bon exemple. Ici, je vais créer une clé "nom" avec pour valeur "granarc" et une clé "age" avec pour valeur "13" (eh oui je suis jeune ^^ ) ; elles seront toutes les deux stockées dans la sous-clé "Identite".

#include <QApplication>
#include <QWidget>
#include <QSettings>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QWidget widget;
    widget.show();

    QSettings settings("sdz", "MonProgramme");
    settings.setValue("Identite/nom", "granarc");
    settings.setValue("Identite/age", 13);

    return app.exec();
}

Et le résultat dans le fichier d'options :

Image utilisateur

Et dans le regedit :

Image utilisateur

On remarque que dans le fichier, la sous-clé est indiquée par son nom entre crochets [] (si c'est une sous-sous-clé elle sera indiquée par son chemin, par exemple Famille/pere=Patrick pour la clé "Identite/Famille/pere"), et dans le regedit, elle est indiquée par un nouveau dossier dans l'arborescence.

Exercice : écrivez le code qui produirait le fichier suivant :

vivant=true
reel=true

[Identite]
nom=granarc
age=13
Famille/Freres/frere1=Remi
Famille/Soeurs/soeur1=Pauline
Famille/Soeurs/soeur2=Laura
orphelin=false
Famille/mere=Josiane
Famille/pere=Patrick

[Coordonnees]
ville=Martigues
Maison/rue=rue des Lilas
Maison/numero=27
codePostal=13500

Compléments

Voici encore trois choses qui pourraient vous être utiles.

Éditer une clé

Pour cela, c'est très simple, si vous utilisez setValue sur une clé déjà existante, la valeur de cette clé est remplacée par celle que vous demandez.

Supprimer une clé

Utilisez la fonction remove :

void QSettings::remove ( const QString &amp; key )

Vous n'avez qu'à indiquer le nom (ou le chemin) de la clé à supprimer.

Se déplacer dans les sous-clés

Si vous avez beaucoup de sous-clés, c'est un peu gavant de réécrire le chemin entier de chaque clé ; si vous avez fait l'exercice proposé au-dessus, vous avez dû le remarquer.
Heureusement, il existe une fonction qui permet de se déplacer dans une sous-clé, qui dit au QSettings : "Attention, les clés qui vont être écrites maintenant se trouvent dans telle sous-clé".

Il suffit pour cela d'utiliser la méthode beginGroup qui prend en seul paramètre le nom de la sous-clé dans laquelle aller. Vous pouvez utiliser maintenant setValue pour écrire vos données ; quand vous avez fini, appelez la méthode endGroup (ne prend aucun argument), cela vous fera revenir à la racine de votre fichier d'options.

Exemple:

#include <QApplication>
#include <QWidget>
#include <QSettings>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QWidget widget;
    widget.show();

    QSettings settings("sdz", "MonProgramme");
    settings.beginGroup("Identite");
    settings.setValue("nom", "granarc");
    settings.setValue("age", 13);
    settings.endGroup();

    return app.exec();
}

Ce code donnera la même chose que notre exemple précédent :

Image utilisateur

Vous avez désormais toutes les cartes en main pour garder en mémoire absolument toute la configuration de votre programme. Cependant, il vous manque une chose essentielle : savoir lire ces informations !

Lire des données

Pour lire des clés, on utilise la méthode value :

QVariant QSettings::value ( const QString &amp; key, const QVariant &amp; defaultValue = QVariant() ) const

Le premier argument est le nom de la clé à lire ; comme pour setValue, vous pouvez indiquer les sous-clés ou utiliser beginGroup et endGroup.
Le second argument est la valeur par défaut que renverra la fonction si la clé n'est pas trouvée. Encore une fois, inutile de créer un objet QVariant, la fonction se charge de convertir automatiquement l'argument qu'on lui passe.

Utilisation simple

Il est temps de tester cette fonction. Reprenez l'exemple de tout à l'heure ; nous allons afficher dans un bouton la valeur de la clé "nom" contenue dans la sous-clé "Identite" :

#include <QApplication>
#include <QPushButton>
#include <QSettings>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QPushButton bouton;
    bouton.show();

    QSettings settings("sdz", "MonProgramme");
    bouton.setText(settings.value("Identite/nom"));

    return app.exec();
}

Compilez et vous devriez obtenir... une belle erreur ! :D

Que nous dit le compilateur ?

main.cpp:13: error: no matching function for call to 'QPushButton::setText(QVariant)'

Mais oui, c'est normal ! Regardez le prototype de value : la fonction renvoie une QVariant, car elle ne sait pas de quel type sont les données récupérées ; comme la méthode setText attend une QString, forcément, ça plante !

Il y a un moyen simple de contourner le problème : en regardant la doc de QVariant, on voit qu'il y a toute une série de fonctions commençant par "to", qui reconvertissent la QVariant dans son type d'origine.
Ici, nous voulons une QString, donc nous allons appliquer la méthode toString à la QVariant que l'on nous renvoie :

#include <QApplication>
#include <QPushButton>
#include <QSettings>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QPushButton bouton;
    bouton.show();

    QSettings settings("sdz", "MonProgramme");
    bouton.setText(settings.value("Identite/nom").toString());

    return app.exec();
}

Et voilà le travail :D :

Image utilisateur

La valeur par défaut

Souvenez-vous : il y avait un deuxième argument, celui de la valeur par défaut. Si la clé est introuvable (pas encore créée par exemple), la fonction va renvoyer une QVariant contenant cette valeur.

Essayez d'obtenir une clé inexistante ("prenom" par exemple) avec comme valeur par défaut "jacques" (ce n'est pas mon prénom si vous voulez savoir ^^ ) :

#include <QApplication>
#include <QPushButton>
#include <QSettings>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QPushButton bouton;
    bouton.show();

    QSettings settings("sdz", "MonProgramme");

    // J'ai un peu réorganisé le code pour être plus clair
    QString prenom = settings.value("Identite/prenom", "jacques").toString();
    bouton.setText(prenom);

    return app.exec();
}

Et le résultat :

Image utilisateur

Remarquez que si, dans ce même code, vous ne précisez pas de valeur par défaut, la méthode renverra une QVariant vide.

J'ai une dernière petite question. Pour la méthode setValue, tu nous a dit que si on utilisait un objet qui n'était pas stockable dans une QVariant, la fonction s'occupait de le convertir. Mais là, vu que c'est nous qui devons faire la conversion, comment faisons-nous, hein ? Y'a pas de méthode toColor par exemple !

Dans ce cas, il suffit d'utiliser la fonction valuede la QVariant. C'est une fonction utilisant les templates, vous aurez juste à indiquer entre chevrons <> le type de l'objet à renvoyer. Exemple en supposant que j'aie enregistré une clé "couleur" ayant pour valeur une QColor noire :

#include <QApplication>
#include <QPushButton>
#include <QSettings>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    QPushButton bouton;
    bouton.show();

    QSettings settings("sdz", "MonProgramme");
    QColor couleur = settings.value("couleur").value<QColor>();
    bouton.setPalette(QPalette(couleur));

    return app.exec();
}

Ce qui donne bien un bouton noir :

Image utilisateur

D'autres fonctions de lecture

Voici quelques autres fonctions qui pourraient vous servir un jour :

allKeys()

Cette fonction renvoie une QStringList de toutes les clés contenues dans la sous-clé actuelle ; celles qui sont contenues dans des sous-clés enfants sont sous la forme sous-clé/clé.
Exemple :

settings.setValue("langage", "C++");
settings.setValue("librairie/nom", "Qt");
settings.setValue("librairie/version", 4);

QStringList cles = settings.allKeys();

Retour :

["langage", "librarie/nom", "librairie/version"]

childKeys()

Cette fonction renvoie une QStringList de toutes les clés contenues cette fois directement dans la sous-clé actuelle.
Exemple :

settings.setValue("langage", "C++");
settings.setValue("librairie/nom", "Qt");
settings.setValue("librairie/version", 4);

QStringList cles = settings.childKeys();

Retour :

["langage"]

childGroups()

Cette fonction renvoie une QStringList de toutes les sous-clés contenues directement dans la sous-clé actuelle.
Exemple :

settings.setValue("langage", "C++");
settings.setValue("librairie/nom", "Qt");
settings.setValue("librairie/version", 4);

QStringList cles = settings.childGroups();

Retour :

["librarie"]

contains(QString key)

Cette fonction prend en argument le nom d'une clé et renvoie un booléen indiquant si la clé existe ou non.
Exemple :

settings.setValue("langage", "C++");
settings.setValue("librairie/nom", "Qt");
settings.setValue("librairie/version", 4);

bool existe = settings.contains("auteur");

Retour :

false

Annexes

Créer un fichier INI

Pour l'instant, notre fichier d'options était sous le format natif, et donc son type et son emplacement changeaient radicalement selon les OS. Peut-être que, pour des raisons de goûts ou de besoins, vous préférerez qu'il soit forcément stocké sous forme de fichier INI. Le gros avantage c'est que vous pourrez alors spécifier votre propre emplacement pour le fichier.

Pour créer un fichier d'options en précisant le chemin du fichier et non le nom du programme et l'équipe, nous allons utiliser ce constructeur :

QSettings::QSettings ( const QString &amp; fileName, Format format, QObject * parent = 0 )
  • L'argument filename est le nom du fichier (avec éventuellement son emplacement relatif ou absolu).

  • L'argument format sert à indiquer le format du fichier d'options. Les valeurs possibles sont celles de l'énumération Format (expliqué au début du tuto).

  • Le dernier argument (parent) sert à la même chose que dans notre ancien constructeur ; si vous ne vous en souvenez plus, retournez voir en dessous du constructeur de la partie "Créer un fichier d'options". Retenez en tout cas qu'il n'est utile que si votre objet QSettings est créé avec new (ce n'est pas le cas ici ;) ).

Et un exemple, un ! :D

QSettings settings("../mesoptions.ini", QSettings::IniFormat);
/*...*/

Après avoir lancé le programme, vous verrez apparaître un fichier "mesoptions.ini" dans le répertoire parent de votre exécutable.

Et pour la lecture / écriture ?

Eh bien figurez-vous que le constructeur est la seule chose qui change ! C'est ça la puissance de QSettings : les fonctions sont toujours les mêmes, elles s'adapteront juste au type de fichier.

QSettings en pratique

Durant tout ce tutoriel, je vous ai parlé du fonctionnement des QSettings ; cette sous-partie traitera elle de l'utilisation concrète de QSettings dans un programme.

L'écriture des données

En général, on sauvegarde la configuration du programme au moment où l'on quitte. Si vous avez un menu avec une action "Quitter", c'est très simple : connectez le signal triggered() de cette action à un slot personnalisé quitter() par exemple, où vous écrirez les clés puis appellerez le slot quit() pour fermer le programme.

Le problème, c'est que l'utilisateur peut très bien quitter en cliquant sur la croix, et là, votre enregistrement tombe à l'eau.

Alors comment on fait pour détecter si l'utilisateur clique sur la croix ?

Vous le savez, Qt détecte les événements sous forme de signaux (connectés à des slots), mais peut également détecter des événements plus généraux comme l'appui d'une touche ou un mouvement de la souris. Pour réagir avec ces événements "généraux", on n'utilise pas les signaux : Qt appelle à chaque événement une fonction qui est chargée de le traiter. Ces fonctions prennent en paramètre une des classes qui héritent de QEvent, qui représentent chacune un événement bien spécifique. L'intérêt d'avoir une classe pour chaque événement, c'est qu'elles contiennent des informations propres à l'événement. Quelques exemples de ces fonctions :

  • keyPressEvent ( QKeyEvent * event) : appelée quand on appuie sur une touche du clavier ;

  • mouseMoveEvent ( QMouseEvent * event) : appelée quand on bouge la souris ;

  • resizeEvent ( QResizeEvent * event) : appelée quand la fenêtre est redimensionnée ;

  • etc.

La fonction qui est appelée lors de la fermeture de la fenêtre est closeEvent( QCloseEvent * event). Il suffit de modifier cette fonction pour pouvoir enregistrer nos options.

Comment ça "modifier la fonction" ? Ça veut dire que je dois modifier le code source ?! o_O

Non, heureusement, nous allons donc utiliser une technique spéciale du C++ : le masquage de méthodes. Derrière ce nom complexe se cache en fait quelque chose de très simple. Si jamais une classe hérite d'une autre et qu'elles ont toutes les deux une méthode en commun, c'est la méthode de la classe fille qui est utilisée. En gros, vous pouvez modifier les méthodes d'une classe mère en les "recopiant" : on parle de ré-implémentation.

Donc, pour modifier la fonction closeEvent de la classe QWidget, nous devons :

  • hériter de QWidget : bon, là, rien à faire, votre fenêtre hérite forcément de cette classe ; ;)

  • réécrire la fonction closeEvent : c'est là que nous intervenons. :D

Ajoutez donc une fonction void closeEvent ( QCloseEvent * event ) à votre classe dans la portée protected :

#include <QWidget>

class MaClasse : QWidget // Peut hériter de n'importe quelle classe fille de QWidget
{
    public:
        MaClasse();
        /* Vos méthodes */

    private:
        /* Vos attributs */

    protected:
        void closeEvent(QCloseEvent *event);
};

Il ne vous reste plus qu'à ré-implémenter cette fonction pour y sauvegarder les options :

/* ...Tout plein de code
pour votre programme... */

void MaClasse::closeEvent(QCloseEvent *event)
{
    QSettings settings("LoremIpsum Team", "zSuperProgramme");
    // Écrivez ce que vous avez à écrire
    event->accept();
}

/* ...Encore du code
qui ne regarde que vous... */

La lecture

Bien, vos options sont sauvegardées, il faut maintenant les lire. Bon, c'est d'un coup moins compliqué, il suffit juste de lire les clés au début du programme (dans le constructeur ^^ ) ; la lecture peut éventuellement être faite dans une fonction à part pour plus de clarté.

Cependant, un problème (qui n'en est pas vraiment un) se pose : comment accéder ensuite aux données à l'intérieur du programme ? Cela serait évidemment une très mauvaise idée de réouvrir le fichier et de récupérer les données à chaque fois que l'on en a besoin.

Je sais, on n'a qu'à stocker le fichier QSettings dans un attribut ! :D

C'est déjà mieux, mais on gaspillerait encore du temps à lire les données à chaque fois. Non, la meilleure solution, c'est de stocker une bonne fois pour toutes dans des attributs :) . Pour mieux structurer le code et éviter les confusions, on mettra un préfixe spécial à ces attributs, "opt" par exemple.

Un exemple de programme :

Citation

#include <QPushButton>

class Fenetre : QPushButton
{
    public:
        Fenetre();
        void chargerOptions();

    private:
        int opt_largeur;
        int opt_hauteur;
        QColor opt_couleur;
};
#include "Fenetre.h"

Fenetre::Fenetre() : QPushButton()
{
    chargerOptions();
    resize(opt_largeur, opt_hauteur);
    setPalette(QPalette(couleur));
}

void Fenetre::chargerOptions()
{
    QSettings settings("sdz", "programme");

    opt_largeur = settings.value("largeur", 300).toInt();
    opt_hauteur = settings.value("hauteur", 250).toInt();
    opt_couleur = settings.value("couleur", QColor(Qt::white)).value<QColor>();
}

Et voilà, c'est fini pour les annexes ! :)

Avouez que maintenant, il vous est beaucoup plus facile de sauvegarder les options de votre programme, et encore plus facile de les lire.

J'espère que ce tuto vous aura servi. Si vous avez une remarque ou un problème, vous pouvez m'envoyer un MP, et n'hésitez pas à laisser un commentaire. ;)

Enjoy programming !

Exemple de certificat de réussite
Exemple de certificat de réussite