IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Qt Discussion :

Accéder à un get/set d'une classe à partir d'une autre


Sujet :

Qt

  1. #1
    Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Janvier 2016
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 54
    Points : 64
    Points
    64
    Par défaut Accéder à un get/set d'une classe à partir d'une autre
    Bonjour à tous,

    Je suis conscient que cette question a été posé des milliers de fois déjà mais rien ne semble s'adapter à mon cas (ou du moins "ça marche pô !").

    Je commence dans Qt et je tatonne un peu mais j'ai pu créer, à l'aide d'une bibliothèque, une interface qui permet de lire des informations sur une carte.

    Cette interface se découpe en deux parties :
    A gauche, le choix du lecteur
    A droite, l'affichage des informations contenus dans la carte

    Aussi, j'ai divisé (peut-être à tort) ces deux différentes parties en deux classes.

    Seulement j'arrive au problème suivant :
    Pour définir les attributs de "droite", il me faut ceux de "gauche".
    Et j'ai tellement essayé de choses différentes que j'en ai le cerveau retourné, j'arrive plus à raisonner de façon logique.

    J'aurais donc besoin d'éclaircissements et notamment sur ceci :
    1) Y'a pas moyen de créer une instance de gauche dans le main ou je ne sais où de façon à pouvoir le récupérer n'importe où sans se prendre la tête ? Comme créer un objet reader et le garder d'un bout à l'autre du programme.

    2) Sinon, comment j'accède à ses fameux get/set ? J'ai essayé des trucs en static, en bidouillant tout ce que je pouvais avec les signaux/slots dans le QML, en créant une autre classe, en mettant en public tout ce que je pouvais trouver mais pas moyen de me débrouiller avec ce système à la *** disons le.
    On m'a parlé de créer une instance de la classe gauche dans la classe droite mais... je vois pas où, ni ce que cette instance va "contenir".

    3)J'aurais du faire tout dans la même classe, au risque d'obtenir un "gauche.cpp" très long et brouillon ?

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    En fait, tu as mélangé la donnée et sa présentation à l'utilisateur.

    Ton programme dispose d'une classe de lecteur de cartes, qui te permet d'obtenir une référence vers la carte qu'il a actuellement (et aussi de te dire s'il a une carte disponible).
    Il dispose ensuite d'une liste de lecteurs.
    Enfin, il doit y avoir quelque part un iterateur/pointeur/bidule qui donne accès au lecteur actif de cette liste.

    Partant de là, il y a une interface graphique qui te permet dans sa partie gauche de modifier cet itérateur.
    Le code qui gère cette partie gauche doit avoir accès à la liste et à l'itérateur. Uniquement.
    Le code de la partie droite, lui, n'à accès qu'à la carte située dans le lecteur actif. Il a donc normalement accès qu'au pointé/déréférencé/bidulisé de l'itérateur. Idéalement, un pointeur/une référence sur le lecteur.

    C'est le principe de séparation modèle (la carte), vue (gauche et droite) et controleur (je ne sais pas trop où, je ne suis pas assez spécialiste).
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Janvier 2016
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 54
    Points : 64
    Points
    64
    Par défaut
    Bonjour à toi et merci beaucoup de venir éclairer ma lanterne.

    Dans la théorie, je comprend plus ou moins ce que tu veux dire mais dans le cas concret de mon programme, j'avoue avoir du mal à comprendre et à relier tout ça avec ce que j'ai fait.

    J'arrive sans aucun soucis à retrouver cette liste de lecteurs en fonction d'un "objet" readerConfiguration" qui va me permettre de récupérer une liste des lecteurs actifs sur le système. Je l'affiche dans une combobox.
    On a donc la liste (présentation à l'utilisateur) qui est récupérée à partir de l'objet "readerConfig" (donnée) que je déclare (non pas par choix) directement dans la fonction.

    Mais je ne vois pas où je peut stocker ces deux différentes parties. Car pour détecter une carte, il me faut l'accès au lecteur. Et pour avoir accès à ce lecteur, il me faut le readerConfig.

    Je réalise en fait que j'ai créé des classes sans vraiment savoir comment les utiliser et en les "remplissant" de tout un tas de choses sans même savoir si c'était pertinent afin de pouvoir communiquer avec la partie QML.

    Ce que tu me conseilles de faire, si j'ai bien compris (et rien n'est moins sûr), c'est d'avoir une architecture en 3 parties avec :
    1) La partie modèle : des classes d'objet pour contenir la donnée c'est à dire une classe ReaderConfiguration, Carte, etc...
    2) La partie vue : le QML et tout ça
    3) La partie controleur : Les classes qui relient le QML au C++

    J'ai l'impression d'avoir raconté tout un tas de conneries mais je vois vraiment pas la logique dans la façon d'architecturer son programme avec Qt.
    Le point d'entrée du programme est le main.cpp mais, contrairement à n'importe quoi que j'ai pu utiliser auparavant, ce main.cpp n'est pas la "base" du programme et ça bouleverse complètement ma vision de la programmation en générale qui jusqu'ici s'avérait plutôt simpliste.

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par Sillimon Voir le message
    J'arrive sans aucun soucis à retrouver cette liste de lecteurs en fonction d'un "objet" readerConfiguration" qui va me permettre de récupérer une liste des lecteurs actifs sur le système. Je l'affiche dans une combobox.
    On a donc la liste (présentation à l'utilisateur) qui est récupérée à partir de l'objet "readerConfig" (donnée) que je déclare (non pas par choix) directement dans la fonction.

    Mais je ne vois pas où je peut stocker ces deux différentes parties. Car pour détecter une carte, il me faut l'accès au lecteur. Et pour avoir accès à ce lecteur, il me faut le readerConfig.
    Mais tu mélanges, de nouveau, la partie vue et la partie métier...

    Tout ce qui ressemble de près ou de loin à un widget (comme un combobox), c'est un élément de la vue. C'est très bien de remplir un combobox, pour permettre à l'utilisateur de voir quels lecteurs sont accessibles. Mais ce n'est pas suffisant: il faut que ton application puisse accéder de manière effective à chacun de ces lecteurs!

    Et, pour ce faire, il faut en "dresser la liste" (et surtout garder cette liste) de telle manière à ce qu'elle soit "accessible par le reste de l'application". De cette manière, tu pourras "assez facilement" faire le lien entre le lecteur qui est sélectionné dans le combobox et ... le lecteur "physique" qui correspond.

    L'idée est simple: tu doit séparer la vue des données métiers, ce qui se traduira au niveau de ta classe par un code ressemblant sans doute à quelque chose comme
    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
    class TaClasseDeGauche : public QWidget{
        Q_OBJECT
    public:
        /* la fonction qui utilise readerConfig */
        void dresserLaListeDesLecteurs();
        Carte /* const */& carteSelectionnee(){
            assert(lecteurSelectionne != nullptr && "veuillez selectionner le lecteur de carte");
            return lecteurSelectionne->fileMoiLaCarteQueTuContiens();
        }
    private SLOTS:
        void changeSelectionLecteur(int index);
    private:
        /* cette fonction veillera à retirer tous les éléments connus du combobox */
        void retirerTousLecteurDuCombobox();
        QComboBox * lecteurVue; // le combobox qui sera affiché
        std::vector<Lecteur /* * ??*/> lesLecteurs; //la liste des "lecteurs physiques"
        /* par facilité: */
        Lecteur * lecteurSelectionne; //celui qui est sélectionné dans le combobox
    }
    De cette manière, ta fonction "dresserLaListeDesLecteurs" pourra remplir le combobox et la liste des "lecteurs physiques" en même temps, sous une forme qui pourrait prendre une forme proche de
    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
    void TaClasseDeGauche :: dresserLaListeDesLecteurs(){
        /* on vide la liste pour éviter les doublons */
        listeLecteurs.clear();
        /* pareil pour le combobox */
        retirerTousLecteurDuCombobox();
        readerConfig config;
        for(auto * lecteurCourent =config.begin(); lecteurCourent != config.end(); ++lecteurCourent){
            /* on ajoute dans le combobox l'information qui nous intéresse au sujet du lecteur courent */
            lecteurVue->addItem(lecteurCourent ->lInformationQuiVabien());
            /* on ajoute le lecteur courant à la liste des lecteurs connus */
           lesLecteurs.push_back(lecteurCourent);
        }
        /* on nettoie les sélections connues */
        lecteurVue->setSelectedIndex(-1);
        lecteurSelectionne=nullptr;
    }
    (bon, tu aurais peut-être intérêt à voir si tu ne peux pas te contenter de dresser la liste des lecteurs puis à créer une instance de QAbstractItemModel que tu donnerait à "manger" à ton combobox... mais la solution présentée ici pourra fonctionner )

    De cette manière, lorsque ton autre classe -- celle qui se trouve à droite, si j'ai bien compris -- voudra accéder aux informations de la carte contenue par le lecteur sélectionné au niveau du combobox de gauche, il lui "suffira" il lui suffira de faire appel à la fonction "carteSelectionnee", et le tour sera joué

    Je réalise en fait que j'ai créé des classes sans vraiment savoir comment les utiliser et en les "remplissant" de tout un tas de choses sans même savoir si c'était pertinent afin de pouvoir communiquer avec la partie QML.
    Ah, ca, c'est pas bien!!!

    Tu ne peux pas apporter de solution correcte à un besoin si tu ignores tout de ce besoin! Il faut donc toujours réfléchir ne serait-ce qu'un tout petit peu à ce qu'il nous faut et à ce dont on dispose, ne serait-ce que pour savoir... comment fournir ce dont l'utilisateur a besoin

    Ce que tu me conseilles de faire, si j'ai bien compris (et rien n'est moins sûr), c'est d'avoir une architecture en 3 parties avec :
    1) La partie modèle : des classes d'objet pour contenir la donnée c'est à dire une classe ReaderConfiguration, Carte, etc...
    2) La partie vue : le QML et tout ça
    3) La partie controleur : Les classes qui relient le QML au C++
    Oui, à ceci près que (1) représente "toutes les données que tu manipule" ...

    J'ai expliqué le MVC il n'y a pas si longtemps... La problématique était tout autre, mais je n'y ai pas dit que des conneries
    J'ai l'impression d'avoir raconté tout un tas de conneries mais je vois vraiment pas la logique dans la façon d'architecturer son programme avec Qt.
    Le point d'entrée du programme est le main.cpp mais, contrairement à n'importe quoi que j'ai pu utiliser auparavant, ce main.cpp n'est pas la "base" du programme et ça bouleverse complètement ma vision de la programmation en générale qui jusqu'ici s'avérait plutôt simpliste.
    Le fait est que tu es trop obnubilé par le fait de "créer un programme Qt".

    Ce qu'il faut faire, c'est prendre les choses "par le bon bout" et, surtout, dans un ordre logique. Car, ce qui est important dans cette phrase ( "créer un programme Qt"), ce n'est pas le dernier terme "Qt", mais le troisième: "programme". Car un programme, quel qu'il soit, n'est jamais qu'un ensemble d'instructions qui permettent de manipuler des données. Ce qui nous amène au coeur du problème: pour qu'un programme soit en mesure de manipuler des données, il faut:
    1. que l'on soit en mesure de représenter les données en mémoire, et
    2. que l'on puisse édicter des règles simples pour s'assurer que les données seront manipulées correctement.

    Mais, tant que l'on n'arrivera pas à obtenir le (1), on n'arrivera à rien avec le (2).

    Or, on se rend compte qu'il y a "un petit nombre" de données "relativement simples" qui seront utilisées de manière systématique. Dans le cas présent, il s'agit de "l'ensemble des informations que l'on peut obtenir de d'une carte". On va donc commencer par créer un type de donnée qui regroupera toutes ces informations. Un bon vieux POD pourrait faire l'affaire, et prendre une forme ressemblant à quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct CardInfo{
        Type1 data1; // choisi correctement les noms et le type de ces données, bien sur
        Type2 data2;
        /* ... */
        TypeN dataN;
        /* !!!! Choisis uniquement les types parmi ceux dont on dispose avec C++ et la bibliothèque standard !!! */
    },
    (comme je ne sais pas s'il s'agit de carte d'identité, de crédit ou de quoi que ce soit d'autre, je n'ai fait aucune hypothèse quant aux informations que nous trouverons dedans )

    Une telle structure devrait nous donner "tout ce qu'il faut" pour nous permettre de représenter la notion de "carte" en mémoire. A priori, on n'aura utilisé que des types primitifs et -- éventuellement -- des fonctionnalités fournies par la bibliothèque standard (comme std::string, par exemple).

    Une fois que l'on peut représenter cette notion de "carte" en mémoire, le besoin suivant est de représenter "l'appareil" qui permet d'extraire les données d'une carte ("physique"). Nous ne lui demanderons -- dans un premier temps -- pas grand chose. Si bien que nous nous attendrons à ce qu'il puisse nous fournir trois services:
    1. nous fournir son "identifiant unique" (afin de pouvoir faire la différence entre lui et son voisin)
    2. nous dire s'il y a une carte qui est insérée dedans ou non et
    3. nous fournir les informations contenues par la carte "physique" sous la forme de notre structure CardInfo.
    (par la suite, il se peut que tu veuilles rajouter des services, permettant, par exemple, de modifier certaines informations sur la carte physique. Mais ca, ce sera après, quand ces deux services fonctionneront... D'autant plus qu'il y aura surement un aspect de sécurité à prendre en compte )

    On va donc créer une classe qui représente le lecteur de cartes. Il pourrait prendre une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class CardReader{
    public:
        Type /*const &*/ id() const; // A toi de choisir le type qui te convient le mieux ;)
        /* une fonction pour savoir si une carte est insérée dans le lecteur de cartes */
        bool hasCardInserted() const;
        CardInfo const & readCard() const;
    private:
        /* tout ce qui permettra au CardReader de fournir les deux services publics */
    };
    NOTA: tu n'as pas encore besoin d'interface graphique ici... Si tu veux t'assurer que nos deux types de données fonctionne, et que le lecteur de cartes ne lira pas "Adrian" alors qu'il aurait du lire "Andre", tu peux créer une fonction [/c]void printInfo(CardInfo const &)[/c] qui affichera toutes les informations sur la "sortie standard" (std::cout)

    Ensuite, d'après ce que j'ai compris, tu te trouve confronté au fait que plusieurs lecteurs de cartes peuvent être accessibles. Tu devras donc créer une autre classe -- que j'appellerais personnellement ReaderHolder et non readerConfig -- qui s'occupera de maintenir en mémoire la liste à jour des lecteurs de cartes qui sont branchés.

    L'un dans l'autre, on souhaite disposer d'un peu plus de services au travers cette classe, car on souhaite sans doute:
    1. pouvoir "enregistrer" un "nouveau" lecteur de carte lorsqu'on le branche
    2. pouvoir "désenregistrer" un lecteur de carte que l'on débranche
    3. pouvoir tester tous les lecteurs de cartes "connus" (pour s'assurer qu'ils sont branché et / ou qu'il fonctionnent)
    4. pouvoir accéder à l'ensemble des lecteurs de cartes connus.
    5. (éventuellement) "déseneregistrer" tous les lecteurs connus

    Cela nous donnera donc une classe qui pourrait ressembler à quelque chose comme
    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
    class ReaderHolder{
        /* un alias de type (privé ) qui nous facilitera le travail */
        using Collection_t = std::vector<CardReader>;
    public:
        void add(/* paramètre permettant de créer un nouveau CardReader */);
        void remove(/* identifiant unique du CardReader qu'il faut supprimer */);
        /* un alias de type qui facilitera le travail pour les fonctions d'accès */
        using const_iterator = typename Collection_t::const_iterator;
        /* Comme pour toute collection qui se repsecte, les fonctions begin et end */
        const_iterator begin() const{
            return readers_.begin();
        }
        const_iterator end() const{
            return readers_.end();
        }
        /* tester tous les lecteurs connus */
        void checkAllReaders();
        /* vider la liste des lecteurs */
        void clear(){
            readers_.clear();
        }
    private:
        /* voici sur quoi tous les services seront basés pour
         * maintenir la liste des lecteurs 
         */
        Collection_t readers_;
    };
    Oups... Je viens de me rendre compte que mon approche ne va pas vraiment avec le fait de créer ton readerConfig directement dans ta fonction...

    Je suis cependant persuadé que mon approche est meilleure. Mais bon, nous n'en sommes pas encore pas encore au point de travailler sur l'IHM. Nous discuterons de cela plus tard

    NOTA: encore une fois, tu peux utiliser les fonctionnalités fournies par la bibliothèque standard pour générer un affichage qui te permettra de vérifier le bon fonctionnement du tout. Un petit programme prenant la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int main(){
         ReaderHolder holder;
         /* utilise holder.add(/* ... */) pour rajouter les lecteurs qui sont connectés */
         for(auto const & reader : holder){
             std::cout<<"le lecteur "<<reader.id()<<" ";
             if(reader.hasCardInserted(){
                 std::cout<<"contient la carte avec le informations suivantes :\n";
                 printInfo(reader.readCard());
            }else{
                std::cout<<"ne contient aucune carte insérée \n";
            }
         }
         return 0;
    }
    Ce n'est qu'une fois que tu en sera arrivé là que tu pourras commencer à t'inquiéter du fait de créer un programme Qt... Car, comme je l'ai fait remarquer à plusieurs occasions, il n'y avait absolument aucune raison d'utiliser Qt pour obtenir le résultat auquel nous sommes arrivés jusqu'ici. N'oublie pas que, tout ce que l'on a fait jusqu'à présent, c'est travailler sur les données métier

    En effet, tu veux utiliser Qt pour une raison en particulier : pour pouvoir fournir une "Zolie interface graphique" à l'utilisateur. Me trompes-je

    Mais cette "zolie interface graphique", elle rentre dans le domaine de la vue; de la représentation des données telles qu'elle est fournie aux utilisateurs de l'application.

    Et tu devrais faire les choses exactement dans le même ordre. Car la première chose que tu veux sans doute pouvoir montrer à l'utilisateur, c'est la représentation des informations contenues dans une carte. Tu vas donc sans doute commencer par créer un widget qui te permettra de le faire

    La deuxième chose que tu voudras sans doute faire, c'est afficher la liste de l'ensemble des lecteurs de carte dans lesquels une carte est introduite. Mais, comme je l'ai dit plus haut, ne faire que l'afficher ne suffira pas

    Par la suite, tu voudras peut-être permettre à l'utilisateur d'interagir avec les données qui sont affichées. Certaines de ces interactions ne feront qu'ouvrir d'autres vues, d'autres devront faire appel à des délégués, car elles auront pour objectif de modifier certaines informations sur les cartes physiques
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Janvier 2016
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 54
    Points : 64
    Points
    64
    Par défaut
    Woah ! Ca fait beaucoup de boulot mais c'est très détaillé !
    Merci beaucoup, c'est très clair et tu ne t'es pas arrêté à mon seul problème !
    Je vais travailler dans ce sens et essayer d'appliquer tes conseils !

    Un gros merci !

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    De rien, c'est la "force de l'expérience"... Ne t'en fais pas, en t’entraînant avec acharnement, tu y arriveras toi aussi tôt ou tard . Mais on ne peut pas tout savoir quand on débute
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. accéder à variable privée d'une classe à partir d'une autre classe
    Par restapa dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 05/08/2010, 08h56
  2. Réponses: 3
    Dernier message: 29/03/2010, 17h01
  3. Accèder les objets d'une form à partir d'une classe
    Par xyron_x dans le forum Windows Forms
    Réponses: 2
    Dernier message: 05/04/2007, 14h49
  4. Réponses: 2
    Dernier message: 29/03/2007, 14h08
  5. Accéder à des objets d'une Form à partir d'une classe
    Par kinouseb dans le forum Windows Forms
    Réponses: 4
    Dernier message: 23/01/2007, 18h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo