Bonjour,

J'utilise QT 6.4 et en particulier sa classe QSettings qui offre une gestion d'un fichier de configuration assez simple.
Mais je trouve un peu dommage, à chaque fois que je souhaite accéder à une variable, de devoir faire la chose suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
 
QSetting _preferences;
 
// Pour lire une préférence
_preferences.beginGroup("MonGroupeDePreferences");
     bool b = _preferences.value("UneCle").toBool(); // value() retourne un QVariant qu'il faut typer chaque préférence, du type :
_preferences.endGroup();
 
// Pour écrire une préférence :
_preferences.beginGroup("MonGroupeDePreferences");
     _preferences.setValue("UneCle",bool value);
_preferences.endGroup();
C'est certainement beaucoup mieux que rien, mais à la longue ça agace un peu.

J'ai donc pensé à encapsuler un QSetting par une classe contenant des get/set pour chaque préférence, plus quelques fonctions de maintenance. Mais je me retrouve avec une collection de fonctions dupliquant énormément de code. Par exemple, voici un get :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
bool MyPrefs::getModeDemo(){
    bool b = false;
    _preferences.beginGroup(grpApp);
    QStringList keys = _preferences.childKeys();
    if (keys.contains(modeDemoKey)){
        b = _preferences.value(modeDemoKey).toBool();
    }else{
        _preferences.setValue(modeDemoKey,modeDemoVal);
        b = modeDemoVal;
    }
    _preferences.endGroup();
    return b;
}
De base, pour accéder à une préférence, il faut le nom de sa clé et son type. J'ai alors pensé à créer une classe template pour stocker chaque préférence :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
template<class T>
class OnePref {
public:
    OnePref()                   = delete;
    OnePref(OnePref &t)         = delete;
    OnePref operator=(OnePref)  = delete;
 
    OnePref(QSettings * prefs, QString grp, QString cle, T valDefaut)  {
        set_prefs_obj(prefs);
        _groupe = grp;
        _cle = cle;
        _valeur_defaut = valDefaut;
    }
    ~OnePref(){};
 
    T get_valeur() {
        QVariant v = get_value_as_QVar();
        if (v.canConvert<T>(v)) return v.value<T>();
        else v.clear();
    }
};
L'idée est ensuite de stocker toutes les préférences comme des pointeur vers ces objets patron dans une Map dont la clé est celle de la préférence. Je sais, ça duplique la clé de la préférence, mais je crois que c'est rapide...
Mais le compilateur n'est logiquement pas ok : les pointeurs ne pointent pas vers un même type.

D'où l'idée ensuite de créer une classe virtuelle de laquelle hérite les objets préférence, puis de placer un pointeur vers cette classe virtuelle dans la Map.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class AbstractPref {
public:
    AbstractPref():__preferences(nullptr){};
    virtual ~AbstractPref(){};
    void set_prefs_obj(QSettings * p) { if (p) __preferences = p; }
 
    QString     get_groupe()        const { return _groupe;       }
    QString     get_cle()           const { return _cle;          }
    QSettings * get_pref_obj()      const { return __preferences; }
    QVariant    get_value_as_QVar()             const;
    void        set_value_as_QVar(QVariant &v)  const;
 
    QSettings * __preferences;
    QString     _groupe;
    QString     _cle;
    QVariant    _valeur_defaut;
};
 
class OnePref  : public AbstractPref { /*..*/ };
 
class MyNewPrefs {
public:   MyNewPrefs();
    ~MyNewPrefs();
 
    void ajouter_preferences(AbstractPref * p) { _all_prefs[p->get_cle()] = p; }
 
private:
    void set_prefs();
    QSettings                   _preferences;
    QMap<QString,AbstractPref*> _all_prefs;
};
Ça fonctionne. Sauf que pour accéder à une préférence il va me falloir transtyper _all_prefs["UneCle"] (ligne 30) qui renvoi un AbstractPref*, ce qui n'est pas dans l'esprit de ce que je souhaite faire.

Typiquement, j'aimerais pouvoir faire :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
bool b = _all_prefs["UneCleBool"].value();
J'ai relu mon Stroustrup sur l'héritage et les classes patrons, sans avancer vraiment.

J'envisage d'ajouter dans la classe virtuelle une variable par type utilisé et un indice vers le type à utiliser...

Est-ce que c'est possible ce genre de chose ?

Sylvain