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

QxOrm Discussion :

Des relations "à la main" (sans le code de QxEE, mais avec son aide)


Sujet :

QxOrm

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Paysan
    Inscrit en
    Juin 2015
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2015
    Messages : 45
    Par défaut Des relations "à la main" (sans le code de QxEE, mais avec son aide)
    Bonjour,

    Comme dit dans mon trait précédent, j'ai une application qui tourne très bien, mais dans laquelle,
    pour commencer, je n'ai pas exprimé les relations (dans mes objets, la relation à un autre objet
    est un "long IdXXX" de l'IdObj -clé primaire- dans l'autre table, et apparait donc comme un nombre
    dans les colonnes de l'interface utilisateur -et les "model/view", ...-)

    Je suis en train de rajouter les relations dans ce code, car, finalement, je trouve que Qxee me génère
    beaucoup trop de types (avec des nos parfois) pour ma petite application (et peut-être ma petite tête).
    Par exemple (on verra plus bas) un type de pointeur vers le même objet oParam est defini pour chaque relation.
    Je ne sais pas si il est possible d'arriver au bout, mais je me suis inspiré de ce que génère Qxee, en
    regroupant les types identiques (simplifiant ??), en en mettant peut-être trop (par crainte aveugle
    de "verifyColumns" et de son assert(false) ), peut-être parfois pas assez, mais j'obtiens une
    compilation et par contre une erreur à l'éxécution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [QxOrm] qx::QxDataMemberX<T> id (primary key) already defined 'IdObj'
    Faut-il que les clés primaire dans des tables différentes aient des noms différents ?
    (les miens s'appelent tous "IdObj")
    Je n'active pour l'instant que les relations entre deux objets oStIntOb et oParam.
    Lorsque je n'ai modifié que oStIntOb, j'ai eu un chargement correct des oParam, mais une erreur sur les oStIntOb:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Démarrage de /home/cs/Bureau/AteliersLogiciels/CaChaBanPer/build-CaChaBanPer-Desktop_Qt_5_3_GCC_32bit-Debug/CaChaBanPer...
    [QxOrm] qx::QxSqlDatabase : create new database connection in thread '0xb1651740' with key '{7d592a7f-f3c0-49ec-8902-d482abd7212a}'
    [QxOrm] sql query (73 ms) : SELECT oParam.IdObj AS oParam_IdObj_0, oParam.TypeParam AS oParam_TypeParam_0, oParam.Libelle AS oParam_Libelle_0, oParam.Abrege AS oParam_Abrege_0 FROM oParam WHERE TypeParam=1
    [QxOrm] sql query (1 ms) : SELECT oParam.IdObj AS oParam_IdObj_0, oParam.TypeParam AS oParam_TypeParam_0, oParam.Libelle AS oParam_Libelle_0, oParam.Abrege AS oParam_Abrege_0 FROM oParam WHERE TypeParam=2
    [QxOrm] sql query (0 ms) : SELECT oParam.IdObj AS oParam_IdObj_0, oParam.TypeParam AS oParam_TypeParam_0, oParam.Libelle AS oParam_Libelle_0, oParam.Abrege AS oParam_Abrege_0 FROM oParam WHERE TypeParam=3
    [QxOrm] sql query (1 ms) : SELECT oCulture.IdObj AS oCulture_IdObj_0, oCulture.Abrege AS oCulture_Abrege_0, oCulture.dtDebut AS oCulture_dtDebut_0, oCulture.dtFinPrevue AS oCulture_dtFinPrevue_0, oCulture.NbUeK_Rang AS oCulture_NbUeK_Rang_0, oCulture.Sem_Plant_Rang AS oCulture_Sem_Plant_Rang_0, oCulture.idUniteSem_Plant AS oCulture_idUniteSem_Plant_0, oCulture.Prod_Rang AS oCulture_Prod_Rang_0, oCulture.idUniteProd AS oCulture_idUniteProd_0, oCulture.Libelle AS oCulture_Libelle_0 FROM oCulture WHERE KType=1
    [QxOrm] sql query (2 ms) : SELECT oCulture.IdObj AS oCulture_IdObj_0, oCulture.Attr AS oCulture_Attr_0, oCulture.KType AS oCulture_KType_0, oCulture.Abrege AS oCulture_Abrege_0, oCulture.dtDebut AS oCulture_dtDebut_0, oCulture.dtFinPrevue AS oCulture_dtFinPrevue_0, oCulture.NbUeK_Rang AS oCulture_NbUeK_Rang_0, oCulture.Sem_Plant_Rang AS oCulture_Sem_Plant_Rang_0, oCulture.idUniteSem_Plant AS oCulture_idUniteSem_Plant_0, oCulture.Prod_Rang AS oCulture_Prod_Rang_0, oCulture.idUniteProd AS oCulture_idUniteProd_0, oCulture.IdSchema AS oCulture_IdSchema_0, oCulture.IdBP AS oCulture_IdBP_0, oCulture.NoUeK AS oCulture_NoUeK_0, oCulture.NbRang AS oCulture_NbRang_0, oCulture.dtFinEffective AS oCulture_dtFinEffective_0, oCulture.Libelle AS oCulture_Libelle_0 FROM oCulture WHERE KType=2
    ASSERT: "false" in file ../../Libs/QxOrm/include/QxDao/QxSqlQueryBuilder.h, line 228
    Le programme s'est terminé subitement.
    /home/cs/Bureau/AteliersLogiciels/CaChaBanPer/build-CaChaBanPer-Desktop_Qt_5_3_GCC_32bit-Debug/CaChaBanPer a planté
    Ce n'était pas malin de ma part de modifier un côté de la relation (oStIntOb) et pas l'autre (oParam) !!
    J' ai modifié le deuxième, je compile, et j'obtiens à l'éxécution (sur le chargement des oParam):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Démarrage de /home/cs/Bureau/AteliersLogiciels/CaChaBanPer/build-CaChaBanPer-Desktop_Qt_5_3_GCC_32bit-Debug/CaChaBanPer...
    [QxOrm] qx::QxSqlDatabase : create new database connection in thread '0xb161c740' with key '{4602dea7-1a58-4399-a162-30d8615d1db0}'
    [QxOrm] qx::QxDataMemberX<T> id (primary key) already defined 'IdObj'
    ASSERT: "false" in file ../../Libs/QxOrm/include/QxDataMember/../../inl/QxDataMember/QxDataMemberX.inl, line 113
    Le programme s'est terminé subitement.
    /home/cs/Bureau/AteliersLogiciels/CaChaBanPer/build-CaChaBanPer-Desktop_Qt_5_3_GCC_32bit-Debug/CaChaBanPer a planté
    Le code de oparam.h est:
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
     
    #ifndef OPARAM_H
    #define OPARAM_H
     
    #include "ostintob.h"
     
    class oParam
    {
        QX_REGISTER_FRIEND_CLASS(oParam);
    protected:
        long m_IdObj; // dans TGENCCBP
        long m_Attr;  // dans TGENCCBP
        int m_TypeParam;
        QString m_Libelle;
        QString m_Abrege;
        //list_of_oStIntOb m_oStIntOb_use;
        list_of_oStIntOb m_StType;
        list_of_oStIntOb m_StClasse;
        list_of_oStIntOb m_UnitDate_Delai;
        list_of_oStIntOb m_UnitDuree;
        list_of_oStIntOb m_UnitValeur;
        //type_list_of_oCulture m_list_of_oCulture;
        //type_list_of_oCulture_1 m_list_of_oCulture_1;
        //bool m_Modif;
        //QString GetCaption(); // override;
        //void SetType(int aType){m_TypeParam=aType;}
        //void SetLibelle(QString aLibelle){m_Libelle=aLibelle;}
        //void SetAbrege(QString aAbrege){m_Abrege=aAbrege;}
    public:
        oParam():m_IdObj(0){;}
        oParam(const long & id): m_IdObj(id), m_TypeParam(0) { ; }
        oParam(int aType, QString aAbrege, QString aLibelle): m_IdObj(0)
              {m_TypeParam=aType; m_Libelle=aLibelle; m_Abrege=aAbrege;}
        virtual ~oParam(){;}
     
        list_of_oStIntOb getlist_of_oStIntOb_StType() const { return m_StType; }
        list_of_oStIntOb & list_of_oStIntOb_StType() { return m_StType; }
        const list_of_oStIntOb & list_of_oStIntOb_StType() const { return m_StType; }
        list_of_oStIntOb getlist_of_oStIntOb_StClasse() const { return m_StClasse; }
        list_of_oStIntOb & list_of_oStIntOb_StClasse() { return m_StClasse; }
        const list_of_oStIntOb & list_of_oStIntOb_StClasse() const { return m_StClasse; }
        list_of_oStIntOb getlist_of_oStIntOb_UnitDate_Delai() const { return m_UnitDate_Delai; }
        list_of_oStIntOb & list_of_oStIntOb_UnitDate_Delai() { return m_UnitDate_Delai; }
        const list_of_oStIntOb & list_of_oStIntOb_UnitDate_Delai() const { return m_UnitDate_Delai; }
        list_of_oStIntOb getlist_of_oStIntOb_UnitDuree() const { return m_UnitDuree; }
        list_of_oStIntOb & list_of_oStIntOb_UnitDuree() { return m_UnitDuree; }
        const list_of_oStIntOb & list_of_oStIntOb_UnitDuree() const { return m_UnitDuree; }
        list_of_oStIntOb getlist_of_oStIntOb_UnitValeur() const { return m_UnitValeur; }
        list_of_oStIntOb & list_of_oStIntOb_UnitValeur() { return m_UnitValeur; }
        const list_of_oStIntOb & list_of_oStIntOb_UnitValeur() const { return m_UnitValeur; }
        //type_list_of_oCulture getlist_of_oCulture() const;
        //type_list_of_oCulture & list_of_oCulture();
        //const type_list_of_oCulture & list_of_oCulture() const;
        //type_list_of_oCulture_1 getlist_of_oCulture_1() const;
        //type_list_of_oCulture_1 & list_of_oCulture_1();
        //const type_list_of_oCulture_1 & list_of_oCulture_1() const;
     
        list_of_oStIntOb getlist_of_oStIntOb_StType(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        list_of_oStIntOb & list_of_oStIntOb_StType(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        list_of_oStIntOb getlist_of_oStIntOb_StClasse(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        list_of_oStIntOb & list_of_oStIntOb_StClasse(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        list_of_oStIntOb getlist_of_oStIntOb_UnitDate_Delai(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        list_of_oStIntOb & list_of_oStIntOb_UnitDate_Delai(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        list_of_oStIntOb getlist_of_oStIntOb_UnitDuree(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        list_of_oStIntOb & list_of_oStIntOb_UnitDuree(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        list_of_oStIntOb getlist_of_oStIntOb_UnitValeur(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        list_of_oStIntOb & list_of_oStIntOb_UnitValeur(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        //type_list_of_oCulture getlist_of_oCulture(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        //type_list_of_oCulture & list_of_oCulture(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        //type_list_of_oCulture_1 getlist_of_oCulture_1(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
        //type_list_of_oCulture_1 & list_of_oCulture_1(bool bLoadFromDatabase, const QString & sAppendRelations = QString(), QSqlDatabase * pDatabase = NULL, QSqlError * pDaoError = NULL);
     
        static QString relation_list_of_oStIntOb_StType() { return "list_of_oStIntOb_StType"; }
        static QString relation_list_of_oStIntOb_StClasse() { return "list_of_oStIntOb_StClasse"; }
        static QString relation_list_of_oStIntOb_UnitDate_Delai() { return "list_of_oStIntOb_UnitDate_Delai"; }
        static QString relation_list_of_oStIntOb_UnitDuree() { return "list_of_oStIntOb_UnitDuree"; }
        static QString relation_list_of_oStIntOb_UnitValeur() { return "list_of_oStIntOb_UnitValeur"; }
        //static QString relation_list_of_oCulture() { return "list_of_oCulture"; }
        //static QString relation_list_of_oCulture_1() { return "list_of_oCulture_1"; }
        static QString column_IdObj() { return "IdObj"; }
        static QString column_TypeParam() { return "TypeParam"; }
        static QString column_Libelle() { return "Libelle"; }
        static QString column_Abrege() { return "Abrege"; }
        static QString table_name() { return "oParam"; }
     
    //    Q_PROPERTY(long IdObj READ m_IdObj )
    //    Q_PROPERTY(long TypeParam READ m_TypeParam WRITE SetType )   //(int aType)) WRITE à virer -afaire-
    //    Q_PROPERTY(QString Libelle READ m_Libelle WRITE SetLibelle ) //(QString aLibelle))
    //    Q_PROPERTY(QString Abrege READ m_Abrege WRITE SetAbrege )    //(QString aAbrege))
    //    Q_PROPERTY(QString Caption READ GetCaption )
    //    QSqlError Enreg();
    //    QSqlError Lire();
    };
     
    typedef boost::shared_ptr<oParam> oparam_ptr;
    typedef qx::QxCollection<long,oParam> list_of_oParam;
    typedef boost::shared_ptr<list_of_oParam> list_of_oParam_ptr;
    typedef std::vector<oparam_ptr> oparam_lst;
     
    QX_REGISTER_HPP_MY_TEST_EXE(oParam,qx::trait::no_base_class_defined,1);
     
    const int ParamType_Unites       =1;
    const int ParamType_Classes      =2; // Préparations, Semis/Plantations, Végétation, Récoltes
    const int ParamType_StIntOb      =3; // Stades-St, Interventions-Int, Observations-Ob
     
    #endif // OPARAM_H
    On y voit que le même type "list_of_oStIntOb" est utilisé pour les 5 utilisations de oParam dans oStIntOb;
    en fait comme mes relations "fonctionnelles" (vues par l'utilisateur) sont toujours des n-1, je n'aurais
    même pas besoin de ces relations, seulement une liste comme écrite en commentaire juste au dessus pour
    savoir si un paramètre (une définition d'unité de mesure par exemple) est utilisé quelque part.
    (sans avoir même besoin de savoir où; un lstUse.count=0 en quelque sorte)

    Le code de oparam.cpp est:
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
     
    #include "precompiled.h"   // Precompiled-header with '#include <QxOrm.h>' and '#include "export.h"'
    #include "oparam.h"
    #include <QxMemLeak.h>     // Automatic memory leak detection
    //#include <QtSql/qsql.h>
     
    #include "ostintob.h"
    //#include "oculture.h"
     
    QX_REGISTER_CPP_MY_TEST_EXE(oParam)   // This macro is necessary to register any class in QxOrm context
     
    namespace qx
    {
    template <> void register_class(QxClass<oParam> & t)
    {
    /*
    t.id(& oParam::m_IdObj, "IdObj");             // Register 'oParam::m_IdObj' <=> primary key IdObj
    t.data(& oParam::m_TypeParam, "TypeParam");
    t.data(& oParam::m_Libelle, "Libelle");
    t.data(& oParam::m_Abrege, "Abrege");
    */
    /*
    qx::IxDataMember * pData = NULL; Q_UNUSED(pData);
    qx::IxSqlRelation * pRelation = NULL; Q_UNUSED(pRelation);
    qx::IxFunction * pFct = NULL; Q_UNUSED(pFct);
    qx::IxValidator * pValidator = NULL; Q_UNUSED(pValidator);
    */
    t.setName("oParam"); //t.setPropertyBag("QX_EE_GENERATED_BY_SQLITE_IMPORT_PLUGIN", "1");
     
    t.id(& oParam::m_IdObj, "IdObj", 0); //pData->setPropertyBag("QX_EE_GENERATED_BY_SQLITE_IMPORT_PLUGIN", "1");
    t.id(& oParam::m_Attr, "Attr", 0);
     
    t.data(& oParam::m_TypeParam, "TypeParam", 0, true, true); //pData->setPropertyBag("QX_EE_GENERATED_BY_SQLITE_IMPORT_PLUGIN", "1");
    t.data(& oParam::m_Libelle, "Libelle", 0, true, true); //pData->setPropertyBag("QX_EE_GENERATED_BY_SQLITE_IMPORT_PLUGIN", "1");
    t.data(& oParam::m_Abrege, "Abrege", 0, true, true); //pData->setPropertyBag("QX_EE_GENERATED_BY_SQLITE_IMPORT_PLUGIN", "1");
     
    t.relationOneToMany(& oParam::m_StType, "list_of_oStIntOb_StType", "StType", 0);          // IdObj dans oStIntOb:StType
    t.relationOneToMany(& oParam::m_StClasse, "list_of_oStIntOb_StClasse", "StClasse", 0);    // IdObj dans oStIntOb:StClasse
    t.relationOneToMany(& oParam::m_UnitDate_Delai, "list_of_oStIntOb_UniteDate_Delai", "UniteDate_Delai", 0);
    t.relationOneToMany(& oParam::m_UnitDuree, "list_of_oStIntOb_UniteDuree", "UniteDuree", 0);
    t.relationOneToMany(& oParam::m_UnitValeur, "list_of_oStIntOb_UniteValeur", "UniteValeur", 0);
    //pRelation = t.relationOneToMany(& oParam::m_list_of_oCulture, "list_of_oCulture", "idUniteSem_Plant", 0);
    //pRelation = t.relationOneToMany(& oParam::m_list_of_oCulture_1, "list_of_oCulture_1", "idUniteProd", 0);
     
    qx::QxValidatorX<oParam> * pAllValidator = t.getAllValidator(); Q_UNUSED(pAllValidator);
    }
    }//namespace qx
     
    list_of_oStIntOb oParam::getlist_of_oStIntOb_StType(bool bLoadFromDatabase, const QString & sAppendRelations /* = QString() */, QSqlDatabase * pDatabase /* = NULL */, QSqlError * pDaoError /* = NULL */)
    {
       if (pDaoError) { (* pDaoError) = QSqlError(); }
       if (! bLoadFromDatabase) { return getlist_of_oStIntOb_StType(); }
       QString sRelation = "list_of_oStIntOb_StType";
       if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
       else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
       oParam tmp;
       tmp.m_IdObj = this->m_IdObj;
       QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, tmp, pDatabase);
       if (! daoError.isValid()) { this->m_StType = tmp.m_StType; }
       if (pDaoError) { (* pDaoError) = daoError; }
       return m_StType;
    }
     
    list_of_oStIntOb & oParam::list_of_oStIntOb_StType(bool bLoadFromDatabase, const QString & sAppendRelations /* = QString() */, QSqlDatabase * pDatabase /* = NULL */, QSqlError * pDaoError /* = NULL */)
    {
       if (pDaoError) { (* pDaoError) = QSqlError(); }
       if (! bLoadFromDatabase) { return list_of_oStIntOb_StType(); }
       QString sRelation = "list_of_oStIntOb_StType";
       if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
       else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
       oParam tmp;
       tmp.m_IdObj = this->m_IdObj;
       QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, tmp, pDatabase);
       if (! daoError.isValid()) { this->m_StType = tmp.m_StType; }
       if (pDaoError) { (* pDaoError) = daoError; }
       return m_StType;
    }
     
    list_of_oStIntOb oParam::getlist_of_oStIntOb_StClasse(bool bLoadFromDatabase, const QString & sAppendRelations /* = QString() */, QSqlDatabase * pDatabase /* = NULL */, QSqlError * pDaoError /* = NULL */)
    {
       if (pDaoError) { (* pDaoError) = QSqlError(); }
       if (! bLoadFromDatabase) { return getlist_of_oStIntOb_StClasse(); }
       QString sRelation = "list_of_oStIntOb_StClasse";
       if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
       else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
       oParam tmp;
       tmp.m_IdObj = this->m_IdObj;
       QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, tmp, pDatabase);
       if (! daoError.isValid()) { this->m_StClasse = tmp.m_StClasse; }
       if (pDaoError) { (* pDaoError) = daoError; }
       return m_StClasse;
    }
     
    list_of_oStIntOb & oParam::list_of_oStIntOb_StClasse(bool bLoadFromDatabase, const QString & sAppendRelations /* = QString() */, QSqlDatabase * pDatabase /* = NULL */, QSqlError * pDaoError /* = NULL */)
    {
       if (pDaoError) { (* pDaoError) = QSqlError(); }
       if (! bLoadFromDatabase) { return list_of_oStIntOb_StClasse(); }
       QString sRelation = "list_of_oStIntOb_StClasse";
       if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
       else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
       oParam tmp;
       tmp.m_IdObj = this->m_IdObj;
       QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, tmp, pDatabase);
       if (! daoError.isValid()) { this->m_StClasse = tmp.m_StClasse; }
       if (pDaoError) { (* pDaoError) = daoError; }
       return m_StClasse;
    }
     
    list_of_oStIntOb oParam::getlist_of_oStIntOb_UnitDate_Delai(bool bLoadFromDatabase, const QString & sAppendRelations /* = QString() */, QSqlDatabase * pDatabase /* = NULL */, QSqlError * pDaoError /* = NULL */)
    {
       if (pDaoError) { (* pDaoError) = QSqlError(); }
       if (! bLoadFromDatabase) { return getlist_of_oStIntOb_UnitDate_Delai(); }
       QString sRelation = "list_of_oStIntOb_UnitDate_Delai";
       if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
       else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
       oParam tmp;
       tmp.m_IdObj = this->m_IdObj;
       QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, tmp, pDatabase);
       if (! daoError.isValid()) { this->m_UnitDate_Delai = tmp.m_UnitDate_Delai; }
       if (pDaoError) { (* pDaoError) = daoError; }
       return m_UnitDate_Delai;
    }
     
    list_of_oStIntOb & oParam::list_of_oStIntOb_UnitDate_Delai(bool bLoadFromDatabase, const QString & sAppendRelations /* = QString() */, QSqlDatabase * pDatabase /* = NULL */, QSqlError * pDaoError /* = NULL */)
    {
       if (pDaoError) { (* pDaoError) = QSqlError(); }
       if (! bLoadFromDatabase) { return list_of_oStIntOb_UnitDate_Delai(); }
       QString sRelation = "list_of_oStIntOb_UnitDate_Delai";
       if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
       else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
       oParam tmp;
       tmp.m_IdObj = this->m_IdObj;
       QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, tmp, pDatabase);
       if (! daoError.isValid()) { this->m_UnitDate_Delai = tmp.m_UnitDate_Delai; }
       if (pDaoError) { (* pDaoError) = daoError; }
       return m_UnitDate_Delai;
    }
     
    list_of_oStIntOb oParam::getlist_of_oStIntOb_UnitDuree(bool bLoadFromDatabase, const QString & sAppendRelations /* = QString() */, QSqlDatabase * pDatabase /* = NULL */, QSqlError * pDaoError /* = NULL */)
    {
       if (pDaoError) { (* pDaoError) = QSqlError(); }
       if (! bLoadFromDatabase) { return getlist_of_oStIntOb_UnitDuree(); }
       QString sRelation = "list_of_oStIntOb_UnitDuree";
       if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
       else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
       oParam tmp;
       tmp.m_IdObj = this->m_IdObj;
       QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, tmp, pDatabase);
       if (! daoError.isValid()) { this->m_UnitDuree = tmp.m_UnitDuree; }
       if (pDaoError) { (* pDaoError) = daoError; }
       return m_UnitDuree;
    }
     
    list_of_oStIntOb & oParam::list_of_oStIntOb_UnitDuree(bool bLoadFromDatabase, const QString & sAppendRelations /* = QString() */, QSqlDatabase * pDatabase /* = NULL */, QSqlError * pDaoError /* = NULL */)
    {
       if (pDaoError) { (* pDaoError) = QSqlError(); }
       if (! bLoadFromDatabase) { return list_of_oStIntOb_UnitDuree(); }
       QString sRelation = "list_of_oStIntOb_UnitDuree";
       if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
       else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
       oParam tmp;
       tmp.m_IdObj = this->m_IdObj;
       QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, tmp, pDatabase);
       if (! daoError.isValid()) { this->m_UnitDuree = tmp.m_UnitDuree; }
       if (pDaoError) { (* pDaoError) = daoError; }
       return m_UnitDuree;
    }
     
    list_of_oStIntOb oParam::getlist_of_oStIntOb_UnitValeur(bool bLoadFromDatabase, const QString & sAppendRelations /* = QString() */, QSqlDatabase * pDatabase /* = NULL */, QSqlError * pDaoError /* = NULL */)
    {
       if (pDaoError) { (* pDaoError) = QSqlError(); }
       if (! bLoadFromDatabase) { return getlist_of_oStIntOb_UnitValeur(); }
       QString sRelation = "list_of_oStIntOb_UnitValeur";
       if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
       else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
       oParam tmp;
       tmp.m_IdObj = this->m_IdObj;
       QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, tmp, pDatabase);
       if (! daoError.isValid()) { this->m_UnitValeur = tmp.m_UnitValeur; }
       if (pDaoError) { (* pDaoError) = daoError; }
       return m_UnitValeur;
    }
     
    list_of_oStIntOb & oParam::list_of_oStIntOb_UnitValeur(bool bLoadFromDatabase, const QString & sAppendRelations /* = QString() */, QSqlDatabase * pDatabase /* = NULL */, QSqlError * pDaoError /* = NULL */)
    {
       if (pDaoError) { (* pDaoError) = QSqlError(); }
       if (! bLoadFromDatabase) { return list_of_oStIntOb_UnitValeur(); }
       QString sRelation = "list_of_oStIntOb_UnitValeur";
       if (! sAppendRelations.isEmpty() && ! sAppendRelations.startsWith("->") && ! sAppendRelations.startsWith(">>")) { sRelation += "->" + sAppendRelations; }
       else if (! sAppendRelations.isEmpty()) { sRelation += sAppendRelations; }
       oParam tmp;
       tmp.m_IdObj = this->m_IdObj;
       QSqlError daoError = qx::dao::fetch_by_id_with_relation(sRelation, tmp, pDatabase);
       if (! daoError.isValid()) { this->m_UnitValeur = tmp.m_UnitValeur; }
       if (pDaoError) { (* pDaoError) = daoError; }
       return m_UnitValeur;
    }
    Je me demande si mes "simplifications" ne sont pas des "complications pour arriver au bout"; si tout cela est possible ...
    Pour l'immédiat, j'aimerai bien savoir ce qui peut générer cette erreur dans QxDataMemberX,
    et qu'est-ce qu'il faut (au minimum) pour satisfaire "verifyColumns" ?

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    482
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 482
    Par défaut


    Dans la méthode qx::register_class<T>, tu as utilisé 2 fois t.id :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    t.id(& oParam::m_IdObj, "IdObj", 0); //pData->setPropertyBag("QX_EE_GENERATED_BY_SQLITE_IMPORT_PLUGIN", "1");
    t.id(& oParam::m_Attr, "Attr", 0);
    Je pense que c'est ça qui génère ton assert.

    Si tu as besoin de définir une clé primaire sur plusieurs colonnes, tu as la réponse ici : http://www.qxorm.com/qxorm_fr/faq.html#faq_101
    Le site de la bibliothèque QxOrm : bibliothèque C++ de gestion de données (Mapping Objet Relationnel ou ORM) basée sur les frameworks Qt et boost.
    QxEntityEditor : éditeur graphique pour la bibliothèque QxOrm (application multi-plateforme pour gérer graphiquement le modèle d'entités).

    Tutoriel : installer un environnement de développement avec QxOrm sous Windows.
    Tutoriel qxBlog : gestion de blogs en C++/Qt.
    Tutoriel qxClientServer : création d'un serveur d'applications en C++/Qt.

  3. #3
    Membre confirmé
    Homme Profil pro
    Paysan
    Inscrit en
    Juin 2015
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2015
    Messages : 45
    Par défaut
    Citation Envoyé par QxOrm Voir le message
    Dans la méthode qx::register_class<T>, tu as utilisé 2 fois t.id :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    t.id(& oParam::m_IdObj, "IdObj", 0); //pData->setPropertyBag("QX_EE_GENERATED_BY_SQLITE_IMPORT_PLUGIN", "1");
    t.id(& oParam::m_Attr, "Attr", 0);
    Je pense que c'est ça qui génère ton assert.
    Bon sang; que je suis bête; je te dis pas le nombre de fois que j'ai relu ce bout de code ...

    Si tu as besoin de définir une clé primaire sur plusieurs colonnes, tu as la réponse ici : http://www.qxorm.com/qxorm_fr/faq.html#faq_101
    Non, non, merci ... du moins pas aujourd'hui (je l'ai vu au début en cherchant comment démarrer)

    Donc le assert dans QxDataMemberX a disparu (est résolu) et retour au assert de verifyColums (ligne 228)
    J'obtiens: (pour les lectures des oParam qui ne plantent pas mais qui ne se font pas, je vais chercher; par contre,
    je serais heureux de savoir ce qu'il faut (au minimum) pour satisfaire "verifyColumns" ? Déja, plein de merci!)
    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
     
    Démarrage de /home/cs/Bureau/AteliersLogiciels/CaChaBanPer/build-CaChaBanPer-Desktop_Qt_5_3_GCC_32bit-Debug/CaChaBanPer...
    [QxOrm] qx::QxSqlDatabase : create new database connection in thread '0xb1671740' with key '{74f21bd0-f94d-4300-88f1-4e5d7c556f58}'
    [QxOrm] execute sql query failed : SELECT oParam.IdObj AS oParam_IdObj_0, oParam.Attr AS oParam_Attr_0, oParam.TypeParam AS oParam_TypeParam_0, oParam.Libelle AS oParam_Libelle_0, oParam.Abrege AS oParam_Abrege_0 FROM oParam WHERE TypeParam=1
    Unable to fetch row
    No query
    err: ParamUnites
    [QxOrm] execute sql query failed : SELECT oParam.IdObj AS oParam_IdObj_0, oParam.Attr AS oParam_Attr_0, oParam.TypeParam AS oParam_TypeParam_0, oParam.Libelle AS oParam_Libelle_0, oParam.Abrege AS oParam_Abrege_0 FROM oParam WHERE TypeParam=2
    Unable to fetch row
    No query
    err: ParamClasses
    [QxOrm] execute sql query failed : SELECT oParam.IdObj AS oParam_IdObj_0, oParam.Attr AS oParam_Attr_0, oParam.TypeParam AS oParam_TypeParam_0, oParam.Libelle AS oParam_Libelle_0, oParam.Abrege AS oParam_Abrege_0 FROM oParam WHERE TypeParam=3
    Unable to fetch row
    No query
    err: ParamStIntOb
    [QxOrm] sql query (2 ms) : SELECT oCulture.IdObj AS oCulture_IdObj_0, oCulture.Abrege AS oCulture_Abrege_0, oCulture.dtDebut AS oCulture_dtDebut_0, oCulture.dtFinPrevue AS oCulture_dtFinPrevue_0, oCulture.NbUeK_Rang AS oCulture_NbUeK_Rang_0, oCulture.Sem_Plant_Rang AS oCulture_Sem_Plant_Rang_0, oCulture.idUniteSem_Plant AS oCulture_idUniteSem_Plant_0, oCulture.Prod_Rang AS oCulture_Prod_Rang_0, oCulture.idUniteProd AS oCulture_idUniteProd_0, oCulture.Libelle AS oCulture_Libelle_0 FROM oCulture WHERE KType=1
    [QxOrm] sql query (1 ms) : SELECT oCulture.IdObj AS oCulture_IdObj_0, oCulture.Attr AS oCulture_Attr_0, oCulture.KType AS oCulture_KType_0, oCulture.Abrege AS oCulture_Abrege_0, oCulture.dtDebut AS oCulture_dtDebut_0, oCulture.dtFinPrevue AS oCulture_dtFinPrevue_0, oCulture.NbUeK_Rang AS oCulture_NbUeK_Rang_0, oCulture.Sem_Plant_Rang AS oCulture_Sem_Plant_Rang_0, oCulture.idUniteSem_Plant AS oCulture_idUniteSem_Plant_0, oCulture.Prod_Rang AS oCulture_Prod_Rang_0, oCulture.idUniteProd AS oCulture_idUniteProd_0, oCulture.IdSchema AS oCulture_IdSchema_0, oCulture.IdBP AS oCulture_IdBP_0, oCulture.NoUeK AS oCulture_NoUeK_0, oCulture.NbRang AS oCulture_NbRang_0, oCulture.dtFinEffective AS oCulture_dtFinEffective_0, oCulture.Libelle AS oCulture_Libelle_0 FROM oCulture WHERE KType=2
    ASSERT: "false" in file ../../Libs/QxOrm/include/QxDao/QxSqlQueryBuilder.h, line 228
    Le programme s'est terminé subitement.
    /home/cs/Bureau/AteliersLogiciels/CaChaBanPer/build-CaChaBanPer-Desktop_Qt_5_3_GCC_32bit-Debug/CaChaBanPer a planté

  4. #4
    Membre Expert

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    482
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 482
    Par défaut
    verifyColumns est une méthode utilisée uniquement en mode debug (en mode release, l'implémentation de la méthode est vide, donc elle ne fait rien).

    Elle vérifie que les colonnes renvoyées par le SGBD ont bien un champ C++ associé.
    Si pas de champ C++ associé ==> assert !

    En regardant le code de cette fonction, il faudrait ajouter des traces pour avoir plus de détails sur ce qui ne va pas (quelle colonne est en erreur, pour telle classe C++) : j'ajouterai cette trace dans le prochaine version.

    Avec ton éditeur (Qt Creator ? Autre chose ?) : est-ce que tu arrives à récupérer cette assert ?
    Par exemple avec MSVC++ c'est très simple de remonter dans la pile d'appel pour obtenir les valeurs des différentes variables.

    D'après tes logs, l'assert semble se déclencher sur la table oCulture : peux-tu stp fournir le code source de cette classe ?

    je trouve que Qxee me génère beaucoup trop de types
    QxEntityEditor génère des typedef : mais au final ça reste le même type dans ton cas.
    Du coup, je ne comprends pas pourquoi tu essayes de modifier les classes générées par QxEntityEditor : est-ce que ton assert se produit également si tu gardes le code généré par QxEntityEditor ?
    Le site de la bibliothèque QxOrm : bibliothèque C++ de gestion de données (Mapping Objet Relationnel ou ORM) basée sur les frameworks Qt et boost.
    QxEntityEditor : éditeur graphique pour la bibliothèque QxOrm (application multi-plateforme pour gérer graphiquement le modèle d'entités).

    Tutoriel : installer un environnement de développement avec QxOrm sous Windows.
    Tutoriel qxBlog : gestion de blogs en C++/Qt.
    Tutoriel qxClientServer : création d'un serveur d'applications en C++/Qt.

  5. #5
    Membre confirmé
    Homme Profil pro
    Paysan
    Inscrit en
    Juin 2015
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2015
    Messages : 45
    Par défaut
    Citation Envoyé par QxOrm Voir le message
    verifyColumns est une méthode utilisée uniquement en mode debug (en mode release, l'implémentation de la méthode est vide, donc elle ne fait rien).
    C'est ce que j'ai vu dans le code; je suis en mode debug et soucieux de comprendre.

    Elle vérifie que les colonnes renvoyées par le SGBD ont bien un champ C++ associé.
    Si pas de champ C++ associé ==> assert !
    Ok; ça parait simple; je sais à priori où chercher.

    En regardant le code de cette fonction, il faudrait ajouter des traces pour avoir plus de détails sur ce qui ne va pas (quelle colonne est en erreur, pour telle classe C++) : j'ajouterai cette trace dans le prochaine version.
    Je l'ai tracée sous Qt. Mais je n'ai pas pris assez de notes. Je refais cela et je reviens.
    De mémoire, il boucle dans la fonction où verifyColumns est appelé (ligne 228) par les if récurrents
    et je reconnais la liste de champs qu'il remplit ... puis cela finit mal ... par le assert ...
    Avec ton éditeur (Qt Creator ? Autre chose ?) : est-ce que tu arrives à récupérer cette assert ?
    Par exemple avec MSVC++ c'est très simple de remonter dans la pile d'appel pour obtenir les valeurs des différentes variables.
    Qt
    D'après tes logs, l'assert semble se déclencher sur la table oCulture : peux-tu stp fournir le code source de cette classe ?
    Non; c'est après la lecture des oCulture au début de la lecture des oStIntOb (je mettrais cette classe en code)
    QxEntityEditor génère des typedef : mais au final ça reste le même type dans ton cas.
    Du coup, je ne comprends pas pourquoi tu essayes de modifier les classes générées par QxEntityEditor : est-ce que ton assert se produit également si tu gardes le code généré par QxEntityEditor ?
    Oui. J'ai bien pensé que ce serait intéressant d'avoir ce test. C'est ce que j'avais commencé avec BaseAgri. Mais je m'y suis perdu.
    Il faudrait que je recommence un test sans model/view (avec l'export C++ de base)
    Je me pose une autre question qui pèse sur mes choix: Est-ce que je réussirai à faire des "Delegate" en dialogue avec les qx::IxModel
    que j'utilise ? Je dois mettre des combos pour choisir l'unité dans des colonnes des Qtableview.
    Je cerne tout cela en clair et je reviens ... demain probablement.

  6. #6
    Membre Expert

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    482
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 482
    Par défaut
    Fichier QxSqlQueryBuilder.h du package QxOrm, remplace la méthode verifyColumns() avec ce code (ce code fera partie de la prochaine version de QxOrm pour ajouter des infos avant déclenchement de l'assert), puis fait un rebuild sur ton projet :
    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
    #ifndef _QX_MODE_RELEASE
       inline bool verifyColumns(const QStringList & columns) const
       {
          if (! m_pDataMemberX) { return false; }
          for (int i = 0; i < columns.count(); i++)
          {
             if (! m_pDataMemberX->exist_WithDaoStrategy(columns.at(i)))
             {
                QString sColumn = columns.at(i);
                qDebug("[QxOrm] Error in qx::QxSqlQueryBuilder<T>::verifyColumns() : column '%s' not found in table '%s'", qPrintable(sColumn), qPrintable(m_sTableName));
                return false;
             }
          }
          return true;
       }
    #else // _QX_MODE_RELEASE
       inline bool verifyColumns(const QStringList & columns) const
       { Q_UNUSED(columns); return true; }
    #endif // _QX_MODE_RELEASE
    Je pense que le soucis est peut-être quand tu définis les colonnes de ton modèle avec la méthode : qx::IxModel::setListOfColumns().

    Il faudrait que je recommence un test sans model/view
    Peut-être oui, avec model/view, tu t'attaques directement à une partie pas simple à appréhender.
    Tu pourrais par exemple dans un 1er temps utiliser les méthodes du namespace qx::dao pour récupérer les données, puis pour vérifier tes données, utiliser la méthode qx::dump() qui affiche un flux XML de ton instance.

    Je me pose une autre question qui pèse sur mes choix: Est-ce que je réussirai à faire des "Delegate" en dialogue avec les qx::IxModel que j'utilise ?
    A priori oui, tes modèles basés sur qx::IxModel sont des QAbstractItemModel : donc on est bien sur du standard Qt.
    Concernant les relations, le code généré par QxEntityEditor et le module QxModelView sont basés sur le notion de modèles imbriqués : en gros tu as un modèle parent, puis une liste de modèles enfants.
    Tu as un excellent tutoriel disponible ici pour expliquer cette notion de "nested models" : http://christophe-dumez.developpez.c...les-imbriques/
    Comme tu pourras le voir dans ce tuto, ça permet une intégration simple avec QML, mais c'est utilisable aussi avec les classiques QtWidgets.
    Le site de la bibliothèque QxOrm : bibliothèque C++ de gestion de données (Mapping Objet Relationnel ou ORM) basée sur les frameworks Qt et boost.
    QxEntityEditor : éditeur graphique pour la bibliothèque QxOrm (application multi-plateforme pour gérer graphiquement le modèle d'entités).

    Tutoriel : installer un environnement de développement avec QxOrm sous Windows.
    Tutoriel qxBlog : gestion de blogs en C++/Qt.
    Tutoriel qxClientServer : création d'un serveur d'applications en C++/Qt.

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

Discussions similaires

  1. VIDEO sans image mais avec son
    Par funckfot dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 07/06/2007, 11h38
  2. Peut-on importer des relations (sans les tables)
    Par clemasson dans le forum Access
    Réponses: 2
    Dernier message: 10/12/2006, 15h39

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