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

GTK+ avec C & C++ Discussion :

Logiciel de Facturation VERGIFAC ( C, GTK2, Cairo, SQLITE)


Sujet :

GTK+ avec C & C++

  1. #1
    Futur Membre du Club
    Homme Profil pro
    sans
    Inscrit en
    Novembre 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Novembre 2011
    Messages : 10
    Points : 9
    Points
    9
    Par défaut Logiciel de Facturation VERGIFAC ( C, GTK2, Cairo, SQLITE)
    Développé en C, GTK2, cairo et sqlite.

    J'ai beaucoup utilisé ce forum pour le mettre au point,
    c'est pourquoi je pense que le SOURCE peut
    intéresser quelques programmeurs.

    Téléchargements, copies d'écrans, manuel ,
    accès au SOURCE (github) à cette page:
    http://www.pouillyfuisse-delorme.com/mdcpt/cc.html

    versions Linux (32 et 64 bits) et Windows

  2. #2
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Bonjour.

    Content pour toi que tu ais pu finaliser ton projet.

    Je ne comprends rien à la comptabilité et ne suis donc pas naturellement intéressé par ton application. Cependant mon côté informaticien me pousse à être curieux. J'ai donc cloné ton projet pour voir un peu ton code source. J'aime bien voir comment d'autres écrivent du code source. Ça me donne souvent de nouvelles idées .

    Je me permets ici de te faire quelques remarques. Elles peuvent être constructives pour te permettre peut être d'améliorer un peu ton soft.

    Tout d'abord, ton projet compile sans problème et s'exécute normalement. Pour information je suis sous Debian amd64 testing. C'est déjà bien . Cependant j'obtiens quelques warnings à la compilation. Je te les livre en pâture :
    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
    src/editfast.c: In function ‘interp’:
    src/editfast.c:303:2: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
      if (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.add1);
      ^~
    src/editfast.c:303:30: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.add1);
                                  ^~~~~~~~~
    src/editfast.c:306:2: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
      if (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.add2);
      ^~
    src/editfast.c:306:30: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.add2);
                                  ^~~~~~~~~
    src/editfast.c:309:2: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
      if (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.add3);
      ^~
    src/editfast.c:309:30: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.add3);
                                  ^~~~~~~~~
    src/editfast.c:312:2: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
      if (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.pays);
      ^~
    src/editfast.c:312:30: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.pays);
                                  ^~~~~~~~~
    src/editfast.c:315:2: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
      if (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.codpos);
      ^~
    src/editfast.c:315:30: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.codpos);
                                  ^~~~~~~~~
    src/editfast.c:318:2: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
      if (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.add4);
      ^~
    src/editfast.c:318:30: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.add4);
                                  ^~~~~~~~~
    src/editfast.c:321:2: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
      if (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.datfac);
      ^~
    src/editfast.c:321:30: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.datfac);
                                  ^~~~~~~~~
    src/editfast.c:324:2: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
      if (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.numfac);
      ^~
    src/editfast.c:324:30: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif (param0() ==-1) return;  cairotext(); cairo_show_text(cr,senf.numfac);
                                  ^~~~~~~~~
    echo fic%.o; gcc -o src/saifaccod.o -Wall `pkg-config --cflags gtk+-2.0 sqlite3` -I ./util/ -c `pkg-config --libs --cflags gtk+-2.0 sqlite3`  src/saifaccod.c 
    fic%.o
    echo fic%.o; gcc -o src/saifac.o -Wall `pkg-config --cflags gtk+-2.0 sqlite3` -I ./util/ -c `pkg-config --libs --cflags gtk+-2.0 sqlite3`  src/saifac.c 
    fic%.o
    src/saifac.c: In function ‘init_sfac’:
    src/saifac.c:780:1: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
     if ( ligfac != NULL) free(ligfac); ligfac=NULL;
     ^~
    src/saifac.c:780:36: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif ( ligfac != NULL) free(ligfac); ligfac=NULL;
                                        ^~~~~~
    src/saifac.c:781:1: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
     if ( ligfac_wgt != NULL) free(ligfac_wgt); ligfac_wgt=NULL;
     ^~
    src/saifac.c:781:44: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif ( ligfac_wgt != NULL) free(ligfac_wgt); ligfac_wgt=NULL;
                                                ^~~~~~~~~~
    src/saifac.c: In function ‘sfac_quit’:
    src/saifac.c:855:1: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
     if ( ligfac != NULL) free(ligfac); ligfac=NULL;
     ^~
    src/saifac.c:855:36: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif ( ligfac != NULL) free(ligfac); ligfac=NULL;
                                        ^~~~~~
    src/saifac.c:856:1: warning: thisif’ clause does not guard... [-Wmisleading-indentation]
     if ( ligfac_wgt != NULL) free(ligfac_wgt); ligfac_wgt=NULL;
     ^~
    src/saifac.c:856:44: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘ifif ( ligfac_wgt != NULL) free(ligfac_wgt); ligfac_wgt=NULL;
                                                ^~~~~~~~~~
    src/saifac.c: In function ‘cod_tax’:
    src/saifac.c:720:22: warning: ‘%s’ directive writing up to 49 bytes into a region of size 40 [-Wformat-overflow=]
          sprintf(libtax,"%s %#0.1f %%", ligcod[j].lib, vtax);
                          ^~
    src/saifac.c:720:6: note: ‘sprintf’ output between 7 and 365 bytes into a destination of size 40
          sprintf(libtax,"%s %#0.1f %%", ligcod[j].lib, vtax);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    src/saifac.c:733:22: warning: ‘%s’ directive writing up to 49 bytes into a region of size 40 [-Wformat-overflow=]
          sprintf(libtax,"%s %#0.1f %%  %s", ligcod[j].lib, vtax,zt);
                          ^~
    src/saifac.c:733:6: note: ‘sprintf’ output 9 or more bytes (assuming 58) into a destination of size 40
          sprintf(libtax,"%s %#0.1f %%  %s", ligcod[j].lib, vtax,zt);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Ensuite je suis un peu gêné par ton Makefile. Il n'est pas possible de faire un "make clean". Je n'ai pas tenté un "make install" mais est-ce possible ? Lancer l'exécutable juste après un make est déroutant, du moins pour moi. As-tu construis ce Makefile ou t'es-tu aidé d'un outil particulier ?

    Côté utilisation une première remarque. La fenêtre principale permet de choisir "un dossier". Ceci pose un problème. Pour moi un dossier est un répertoire. Pour toi il semblerait que ce soit à prendre dans un sens plus généraliste. En cliquant dessus on ouvre une fenêtre qui ne demande de choisir un dossier mais un fichier .db. Il faudrait renommer le bouton ainsi que la fenêtre de choix en "Ouvrir une base de données" ou "Ouvrir un fichier de comptabilité (.db)" par exemple. À toi de voir...

    La fenêtre "Paramètres divers" a un petit problème d'espace pour les écritures. Voila une capture d'écran, c'est plus simple pour comprendre :
    Nom : parametres.png
Affichages : 434
Taille : 19,4 Ko

    Même chose pour la fenêtre "Saisie facture". Le menu déroulant du type de facture est un peu étriqué. La date en dessous a le même problème.
    Nom : saisie_facture.png
Affichages : 593
Taille : 32,9 Ko

    J'arrête ici mon petit descriptif. Encore bravo pour ton projet

  3. #3
    Futur Membre du Club
    Homme Profil pro
    sans
    Inscrit en
    Novembre 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Novembre 2011
    Messages : 10
    Points : 9
    Points
    9
    Par défaut Réponse à Gerald3d
    Bonjour Gerald3d et merci pour ton post.

    Les WARNINGS
    Je n'ai pas tes warning dans toutes mes compils.

    exemple vergifac64 (linux)
    système Linux Mint 18 Cinnamon 64-bit
    gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)

    [-Wmisleading-indentation]
    Le code en question est volontairement concis pour en faciliter la relecture si besoin.
    if ( strcmp( ze,"ad1") == 0) {
    if (param0() ==-1) return; cairotext(); cairo_show_text(cr,senf.add1);
    }

    je pense que le warning disparaîtrait si code écrit comme ça:

    if ( strcmp( ze,"ad1") == 0) {
    if (param0() ==-1) return;
    cairotext();
    cairo_show_text(cr,senf.add1);
    }

    Par contre les warnings sur ces lignes:

    sprintf(libtax,"%s %#0.1f %%", ligcod[j].lib, vtax);
    détectent un problème potentiel que je vais corriger.

    Tous les programmeurs savent qu'un 'problème potentiel' est le fait d'utilisateurs pervers qui se font un malin plaisir de brutaliser un logiciel en activant du code qui n'a pas été testé.

    ______
    makefile
    Je suis pas un champion. Je l'ai bricolé à force d'essais et de copies à droite et à gauche. C'est un makefile pour test.
    Je pense que des outils comme make, bash et d'autres sont de vieux outils modifiés depuis presque 40 ans par des rustines et des rustines sur rustines mériteraient d'être remis à plat en proposant des syntaxes moins tordus.

    ________
    taille police
    Ici c'est le problème de l'aspect des fenêtres variables suivant le thème du bureau, la taille de la police et la taille de l'écran.

    Par exemple, sur mon Mint cinnamon, je ne me suis pas préoccupé du thème et des polices parce que inconsciemment ça me convenait.
    thème = Linux Mint ?
    j'ai police par défaut = 'noto sans regular' taille 9
    test taille 10 c'est encore bon
    taille 11 j'ai le même problème que toi.

    Existe-t-il dans GTK un paramétrage de la taille de la police utilisée dans une application ? et redimensionner les fenêtres en conséquence ?

    J'ai du étudier le problème à un moment ou un autre sans le finalisé complètement.
    Dans le fichier util/genfen.h j'ai un paramètre fixe
    #define DIMC 7 // dimension 1 car a afficher
    qui ajuste la taille des saisies.
    On pourrait le mettre en paramètre variable, mais bonjour la doc.

  4. #4
    Futur Membre du Club
    Homme Profil pro
    sans
    Inscrit en
    Novembre 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Novembre 2011
    Messages : 10
    Points : 9
    Points
    9
    Par défaut Modif dans github
    Rebonjour Gerald3d

    Je viens de recevoir le message de tes modifs dans github.

    Je pédale pas mal dans la choucroute avec github

    Je vais donc tenter de récupérer ton code et le tester.

    Je te tiens au courant.

    Et encore merci pour ton interet à vergifac.

  5. #5
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par pap71 Voir le message
    Rebonjour Gerald3d

    Je viens de recevoir le message de tes modifs dans github.

    Je pédale pas mal dans la choucroute avec github

    Je vais donc tenter de récupérer ton code et le tester.

    Je te tiens au courant.

    Et encore merci pour ton interet à vergifac.
    J'ai trouvé ces deux liens qui pourraient peut-être t'aider pour intégrer la branche optimisations à ton projet local :
    https://borisschapira.com/2016/06/re...r-mr-en-local/
    https://gist.github.com/dzc34/44e3c2248cea08ac510a

  6. #6
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Pendant que j'y suis je regarde depuis un petit moment la fonction formfloat ();. Je suis inquiet . comment fixes-tu la taille du tableau char ss[] qui va recevoir le résultat de la conversion du double ff transmis ?

    Je partirai plutôt sur une fonction de la forme gchar * formfloat (gdouble ff);. Le pointeur renvoyé serait alloué dynamiquement. Ainsi tu pourrais avoir ce genre d'utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    gchar *result = NULL;
     
    result = formfloat (10.31313002);
    ...
    /* utilisation de result */
    ...
    g_free (result);
    result = NULL;
    Et cette méthode pourrait être généralisée dans tout ton code. Cela le rendrait bien plus robuste je pense.

    Ensuite pour ce qui est du cœur de cette fonction je ne comprends pas bien son fonctionnement. Je suis certainement dans l'erreur mais je pense que tu désires enlever le point et les zéros après la virgule si bien sûr le double transmis est en réalité un en entier.
    Si c'est bien ce que tu recherches vérifies simplement si ff est un entier en vérifiant le modulo de ff par 2. Si tel est le cas il te suffit d'utiliser g_strdup_printf(); pour le convertir en gchar* alloué dynamiquement.

  7. #7
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par pap71 Voir le message
    Bonjour Gerald3d et merci pour ton post.

    Les WARNINGS
    Je n'ai pas tes warning dans toutes mes compils.

    exemple vergifac64 (linux)
    système Linux Mint 18 Cinnamon 64-bit
    gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)

    [-Wmisleading-indentation]
    Le code en question est volontairement concis pour en faciliter la relecture si besoin.
    if ( strcmp( ze,"ad1") == 0) {
    if (param0() ==-1) return; cairotext(); cairo_show_text(cr,senf.add1);
    }

    je pense que le warning disparaîtrait si code écrit comme ça:

    if ( strcmp( ze,"ad1") == 0) {
    if (param0() ==-1) return;
    cairotext();
    cairo_show_text(cr,senf.add1);
    }
    Je confirme. Les warnings disparaissent.

    Citation Envoyé par pap71 Voir le message
    Par contre les warnings sur ces lignes:

    sprintf(libtax,"%s %#0.1f %%", ligcod[j].lib, vtax);
    détectent un problème potentiel que je vais corriger.

    Tous les programmeurs savent qu'un 'problème potentiel' est le fait d'utilisateurs pervers qui se font un malin plaisir de brutaliser un logiciel en activant du code qui n'a pas été testé.
    J'ai justement corrigé dans les commits que je t'ai envoyé.

    Citation Envoyé par pap71 Voir le message
    _____
    makefile
    Je suis pas un champion. Je l'ai bricolé à force d'essais et de copies à droite et à gauche. C'est un makefile pour test.
    Je pense que des outils comme make, bash et d'autres sont de vieux outils modifiés depuis presque 40 ans par des rustines et des rustines sur rustines mériteraient d'être remis à plat en proposant des syntaxes moins tordus.
    Je suis bien d'accord. Ce n'est pas très clair. Mais comme on dit, c'est en forgeant qu'on devient forgeron...

    Citation Envoyé par pap71 Voir le message
    ________
    taille police
    Ici c'est le problème de l'aspect des fenêtres variables suivant le thème du bureau, la taille de la police et la taille de l'écran.

    Par exemple, sur mon Mint cinnamon, je ne me suis pas préoccupé du thème et des polices parce que inconsciemment ça me convenait.
    thème = Linux Mint ?
    j'ai police par défaut = 'noto sans regular' taille 9
    test taille 10 c'est encore bon
    taille 11 j'ai le même problème que toi.

    Existe-t-il dans GTK un paramétrage de la taille de la police utilisée dans une application ? et redimensionner les fenêtres en conséquence ?

    J'ai du étudier le problème à un moment ou un autre sans le finalisé complètement.
    Dans le fichier util/genfen.h j'ai un paramètre fixe
    #define DIMC 7 // dimension 1 car a afficher
    qui ajuste la taille des saisies.
    On pourrait le mettre en paramètre variable, mais bonjour la doc.
    Je vais regardé un peu ce petit souci d'affichage voir s'il y a une solution élégante.

  8. #8
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Bonjour,

    Citation Envoyé par pap71 Voir le message
    makefile
    Je suis pas un champion. Je l'ai bricolé à force d'essais et de copies à droite et à gauche. C'est un makefile pour test.
    Je pense que des outils comme make, bash et d'autres sont de vieux outils modifiés depuis presque 40 ans par des rustines et des rustines sur rustines mériteraient d'être remis à plat en proposant des syntaxes moins tordus.
    C'est déjà le cas. Il y a des alternatives:
    • autotools qui existe depuis des lustres mais assez gargantuesque
    • CMake, plus accessible
    • meson, récemment adopté par le projet GTK+ (et GStreamer, et pas mal d'autres)


    J'ai clairement un parti pris pour meson. Il a une syntaxe claire et proche de python, et tu peux faire une application simple en GTK+ en 3 lignes: http://mesonbuild.com/Tutorial.html
    De plus, meson tente de faire par défaut ce qu'on attendrait. Par exemple les warnings du compilateur sont activés par défaut, ce qui évite les erreurs grossières (souvent les débutants oublient ou ne savent pas activer les warnings).
    Voici par exemple gtk3-graph, une petite application qui utilise cairo pour afficher une courbe dans une fenêtre GTK+, et que je construis avec meson.
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

  9. #9
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Je commence à comprendre les petits soucis d'affichage. Tu as tendance à vouloir imposer des tailles pour tes widgets. Malheureusement pour toi ce n'est pas la philosophie de Gtk+. Tu dois libérer tout ce petit monde et le laisser prendre la place dont il a besoin .

    Par exemple dans la fonction void boutsfac(GtkWidget *box); tu imposes la taille au GtkComboBox avec la ligne gtk_widget_set_size_request(cbtypdoc, 100, 25);. Une fois cette ligne mise en commentaire le menu déroulant s'adapte aux textes internes. Ainsi tu n'as pas à te soucier du thème graphique de l'utilisateur final.

    Menu avant modification :Nom : menu_avant.png
Affichages : 515
Taille : 9,4 Ko Menu après fermé :Nom : menu_ferme.png
Affichages : 424
Taille : 10,1 Ko Menu après ouvert :Nom : menu_ouvert.png
Affichages : 484
Taille : 9,8 Ko

  10. #10
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Autre commentaire: je te conseille de lire les Human Interface Guidelines de GNOME (GNOME HIG) qui t'indiquent comment agencer des widgets pour rendre une application plaisante à utiliser. Je pense aussi que ton application gagnerait à avoir plus de fenêtres, mais avec moins de widgets, là c'est assez brouillon. Tu peux utiliser Glade pour concevoir ton interface et GtkBuilder pour la construire dynamiquement au démarrage de ton application.
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

  11. #11
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par liberforce Voir le message
    Autre commentaire: je te conseille de lire les Human Interface Guidelines de GNOME (GNOME HIG) qui t'indiquent comment agencer des widgets pour rendre une application plaisante à utiliser. Je pense aussi que ton application gagnerait à avoir plus de fenêtres, mais avec moins de widgets, là c'est assez brouillon. Tu peux utiliser Glade pour concevoir ton interface et GtkBuilder pour la construire dynamiquement au démarrage de ton application.
    Je n'ai pas osé aller encore sur ce terrain là dans mes premiers commentaires. Cela l'obligerai à revoir de fond en comble une application qu'il vient de finir. Pour ma part ca aurait tendance à me casser le moral . Mais effectivement tu as tout fait raison.

    Je verrais bien un passage à Glade et Gtk3+ pour la future version 2.0 .

  12. #12
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut Accéder à un pointeur d'un widget en tout point d'un programme
    Je profite de la brèche ouverte par liberforce au sujet de Glade. Je me suis dit qu'il serait possible à moindre coût de trouver une solution intermédiaire pour celles et ceux qui désirent construire leur interface par le code source et accéder à tous les widgets en tout point de leur programme sans variables déclarées en global. Cette dernière phrase est un peu longue, j'en conviens . Je vais la disséquer.

    Je reprends ici une partie du code de vergifac pour la création de la fenêtre principale. Tout d'abord quelques pointeurs sont déclarés en static et en dehors de toute fonction (déclaration en global).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    static GtkWidget *boutsfac;
    static GtkWidget *boutsfcli;
    static GtkWidget *boutsprod;
    static GtkWidget *boutliprod;
    static GtkWidget *boutopen;
    static GtkWidget *boutlicli;
    static GtkWidget *labdb;
    Ces pointeurs sont utilisés pour pouvoir dans deux fonctions rendre sensible ou insensible à la souris les widgets associées.
    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
    void deactiv_bmenu()
    {
     gtk_widget_set_sensitive(boutsfac,FALSE);
     gtk_widget_set_sensitive(boutlicli,FALSE);
     gtk_widget_set_sensitive(boutsfcli,FALSE);
     gtk_widget_set_sensitive(boutsprod,FALSE);
     gtk_widget_set_sensitive(boutliprod,FALSE);
     gtk_widget_set_sensitive(cbparam,FALSE);
    }
     
    void activ_bmenu()
    {
     gtk_widget_set_sensitive(boutsfac,TRUE);
     gtk_widget_set_sensitive(boutlicli,TRUE);
     gtk_widget_set_sensitive(boutsfcli,TRUE);
     gtk_widget_set_sensitive(boutsprod,TRUE);
     gtk_widget_set_sensitive(boutliprod,TRUE);
     gtk_widget_set_sensitive(cbparam,TRUE);
    }
    Est aussi déclarer en global le pointeur du widget principal : GtkWidget *winp;.

    Pour le code exemple que je vais détaillé ci-après je vais conserver le pointeur principal winp en global. Il est bien entendu possible et même conseillé de ne pas agir ainsi. Mais je ne voudrais pas trop embrouiller le lecteur .

    L'idée générale serait de se passer tant que faire ce peut des déclarations en global. Comment faire ? Deux solutions sont possibles :

    1. créér une structure dans laquelle on déclare toutes les variables nécessaires. On déclare ensuite une variable de ce type. On initialise tout ce petit monde et on la propage à toutes les fonctions qui en aurait besoin,
    2. le pointeur de la fenêtre principale pointe sur un container. il ne faut pas oublier qu'une IHM est construite sur le principe des poupées russes. Nous pouvons donc récupérer tous les pointeurs de tous les widgets de l'interface depuis le pointeur principal.

    La première solution est très intéressante. Elle permet aux applications de se passer de toute (ou presque) déclaration en global. Il ne faut donc pas l'écarter. Elle devrait être utilisée ne serait-ce que pour déclarer le pointeur principal winp en local.

    La deuxième solution est celle que je vais détailler. La méthode employée ici est une méthode intermédiaire. Je m'explique. Si vous utilisez Glade pour construire vos interfaces, vous passez par un GtkBuilder. Il vous permet d'accéder à tout pointeur de l'interface via le nom que vous lui avez donné. Si maintenant vous avez construit l'interface avec le code source il est aussi possible de faire la même chose mais sans passer par un GtkBuilder, inutilisable en l'état dans cette configuration. Il est nécessaire d'écrire quelques lignes de code que je vais vous livrer ici.

    Accéder à tout widget d'une interface.

    La première chose à savoir est que la plupart des widgets hérite avant tout d'un GtkContainer qui lui-même hérite d'un GtkWidget. Nous pouvons donc les caster en GtkContainer. Pour les autres (GtkButton, GtkLabel etc) ils ne contiennent rien à l'intérieur. Ils seront traités par les fonctions liées au GtkContainer. Cette première notion est fondamentale.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    GtkWidget
         GtkContainer
              GtkBin
              GtkBox
              GtkCList
              GtkFixed
              ...
    La deuxième chose à savoir est que tout GtkWidget a un nom. Quand j'écris un nom, je parle bien d'un texte gchar* qui le décrit. Lorsque vous créez un GtkLabel par exemple son nom par défaut est "GtkLabel". Bon OK ca n'apporte pas grand chose pour l'instant . Ce qui est intéressant c'est qu'on peut modifier ce nom et bien entendu aussi le récupérer via ces deux fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void
    gtk_widget_set_name (GtkWidget *widget,
                         const gchar *name);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const gchar *
    gtk_widget_get_name (GtkWidget *widget);
    Nous avons maintenant la possibilité de trouver un pointeur depuis un texte. Il nous faut aussi avoir la possibilité d'extraire tous les pointeurs de l'interface pour nous permettre de comparer les noms. C'est ici que les fonctions liées aux GtkContainer vont nous sauver :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void
    gtk_container_foreach (GtkContainer *container,
                           GtkCallback callback,
                           gpointer callback_data);
    Cette fonction permet d'envoyer à une fonction callback tous les widgets qui sont inclus dans le container transmis. On peut aussi envoyer à cette même fonction une donnée personnelle que nous utiliserons ici.
    Il est important de comprendre que le callback sera appelé une seule fois si le premier widget de l'interface est un GtkBox par exemple. En effet cette fonction s'arrête à la première "poupée russe" rencontrée. Il faudra créer une boucle pour entrer dans le GtkBox et à nouveau lancer gtk_container_foreach();.

    En résumé.

    • On peut nommer les GtkWidget et ainsi les retrouver grâce aux fonctions gtk_widget_set_name () et gtk_widget_get_name (),
    • on peut extraire tous les widgets d'une interface grâce à la fonction gtk_container_foreach ().


    Je vous livre tout d'abord la fonction callback ainsi que la fonction à appeler pour extraire un pointeur. La fonction callback_find_widget () est déclarée en static puisque exclusivement utiliser par la fonction de recherche get_widget_from_window ().
    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
    static void
    callback_find_widget (GtkWidget *widget, gpointer data)
    {
      /* Création d'une structure interne pour pouvoir récupérer les différents
       * widgets de l'interface mais aussi le résultat de la comparaison des noms.
       */
      typedef struct
      {
        GtkWidget *widget;
        const gchar *name;
        gboolean resultcomp;
        GtkWidget *ptrfind;
      } Sresult;
     
      Sresult *result = (Sresult*)data;
     
      if (g_strcmp0 (gtk_widget_get_name (widget), result->name)==0)
      {
        result->resultcomp = TRUE;
        result->ptrfind = widget;
      }
     
      result->widget = widget;
    }
     
    GtkWidget *
    get_widget_from_window (GtkWidget *winp, const gchar *name)
    {
      /* Retourne NULL si le widget n'est pas valide */
      g_return_val_if_fail (GTK_IS_WIDGET (winp), NULL);
      /* Retourne NULL si name = NULL */
      g_return_val_if_fail (name!=NULL, NULL);
     
      /* Création d'uns structure interne pour pouvoir récupérer les différents
       * widgets de l'interface mais aussi le résultat de la comparaison des noms.
       */
      typedef struct
      {
        GtkWidget *widget;
        const gchar *name;
        gboolean resultcomp;
        GtkWidget *ptrfind;
      } Sresult;
     
      Sresult result;
      GtkWidget *widget = NULL;
     
      /* Initialisation de result */
      result.widget = winp;
      result.name = name;
      result.resultcomp = FALSE;
      widget = winp;
      while (1)
        {
           if (GTK_IS_CONTAINER (widget))
    	gtk_container_foreach (GTK_CONTAINER (widget),(GtkCallback)callback_find_widget, &result);
     
          if (result.resultcomp == TRUE)
    	return result.ptrfind;
          else
    	{
    	  /* Permet de sortir de la boucle lorsque tous les widgets ont été parcourus */
    	  if (widget==result.widget)
    	    break;
    	  else
    	    widget = result.widget;
    	}
        }
     
      return NULL;
    }
    La fonction get_widget_from_window (GtkWidget *winp, const gchar *name); permet donc, depuis le GtkWidget *winp transmis d'extraire le pointeur d'un widget portant le nom name. Cette fonction vous renvoie soit un pointeur valide si la recherche est fructueuse, soit NULL dans le cas contraire ou si winp n'est pas valide ou name est NULL.

    Pour pouvoir l'utiliser il ne reste plus qu'à nommer nos widgets. En reprenant le code exemple, lors de la création on peut écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ...
    boutsfac = gtk_button_new_with_label("Saisie Facture");
    gtk_widget_set_size_request(boutsfac, 120, 25);
    gtk_fixed_put(GTK_FIXED(frawp), boutsfac,20,py);
    gtk_widget_set_name (boutsfac, "boutsfac");
    ...
    Pour pouvoir retrouver le pointeur de ce widget il suffira d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      if (get_widget_from_window (winp, "boutsfac"))
        g_printerr ("widget trouvé\n");
      else
        g_printerr ("widget non trouvé !!!\n");
    Ainsi en reprenant le code exemple du départ avec nos deux fonctions qui désactivent/activent des widgets on peut écrire ceci et se passer des déclarations en global de tous les pointeurs associés :
    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
    /* static GtkWidget *boutsfac; */
    static GtkWidget *boutsfcli;
    static GtkWidget *boutsprod;
    static GtkWidget *boutliprod;
    static GtkWidget *boutopen;
    static GtkWidget *boutlicli;
    static GtkWidget *labdb;
    
    void deactiv_bmenu()
    {
      gtk_widget_set_sensitive(get_widget_from_window (winp, "boutsfac"), FALSE);
      gtk_widget_set_sensitive(boutlicli,FALSE);
      gtk_widget_set_sensitive(boutsfcli,FALSE);
      gtk_widget_set_sensitive(boutsprod,FALSE);
      gtk_widget_set_sensitive(boutliprod,FALSE);
      gtk_widget_set_sensitive(cbparam,FALSE);
    }
    
    void activ_bmenu()
    {
      gtk_widget_set_sensitive(get_widget_from_window (winp, "boutsfac"), TRUE);
      gtk_widget_set_sensitive(boutlicli,TRUE);
      gtk_widget_set_sensitive(boutsfcli,TRUE);
      gtk_widget_set_sensitive(boutsprod,TRUE);
      gtk_widget_set_sensitive(boutliprod,TRUE);
      gtk_widget_set_sensitive(cbparam,TRUE);
    }
    À vos claviers...et vos commentaires.

  13. #13
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Bounjour gerald3d,

    merci pour ton article, qui montre un approche intéressante.
    Cependant je pense que même si cela peut être utile pour un usage ponctuel, il y a trop de limitations pour pouvoir conseiller cela.
    En termes de performances déjà: analyser récursivement tout une hiérarchie de widgets pour en trouver un, ça ne passe pas à l'échelle quand tu as de nombreux widgets.

    Si le but est de se passer des pointeurs vers les widgets en static, alors il faut créer des structures qui contiennent les pointeurs vers ces widgets, et passer ces structures en paramètre à la connexion des signaux (paramètre user_data), ou bien pour les fonctions qu'on écrit soi même, passer la structure en paramètre d'entrée. Il faut vraiment essayer de toujours passer à une fonction tout ce dont elle a besoin pour travailler. Il faut à tout prix éviter lui éviter d'avoir à se débrouiller et à chercher elle même ce dont elle a besoin pour travailler.

    C'est vrai en GTK+, mais aussi dans tout programme car c'est aussi ce qui permet de tester plus facilement un programme: tu lui fournis des "imitations", de objets de test qui te permettent de te tester ton code. C'est ce qu'on appelle de l'injection de dépendances. Si tu fais cela en interne, cela devient difficile de passer juste nécessaire en entrée de ta fonction, tu te retrouves à devoir te baser sur un état qu'il faut recontruire et c'est difficile à faire.

    Bien sûr pour du code, être capable de savoir ce qu'il contient, ses caractéristiques, de manière dynamique, ça peut être utile, mais pour retrouver juste ces widgets, utiliser des pointeurs vers des structures et les passer en paramètre me semble être le premier pas. Le second pas c'est effectivement GtkBuilder + Glade.
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

  14. #14
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par liberforce Voir le message
    Bounjour gerald3d,

    merci pour ton article, qui montre un approche intéressante.
    Cependant je pense que même si cela peut être utile pour un usage ponctuel, il y a trop de limitations pour pouvoir conseiller cela.
    En termes de performances déjà: analyser récursivement tout une hiérarchie de widgets pour en trouver un, ça ne passe pas à l'échelle quand tu as de nombreux widgets.

    Si le but est de se passer des pointeurs vers les widgets en static, alors il faut créer des structures qui contiennent les pointeurs vers ces widgets, et passer ces structures en paramètre à la connexion des signaux (paramètre user_data), ou bien pour les fonctions qu'on écrit soi même, passer la structure en paramètre d'entrée. Il faut vraiment essayer de toujours passer à une fonction tout ce dont elle a besoin pour travailler. Il faut à tout prix éviter lui éviter d'avoir à se débrouiller et à chercher elle même ce dont elle a besoin pour travailler.

    C'est vrai en GTK+, mais aussi dans tout programme car c'est aussi ce qui permet de tester plus facilement un programme: tu lui fournis des "imitations", de objets de test qui te permettent de te tester ton code. C'est ce qu'on appelle de l'injection de dépendances. Si tu fais cela en interne, cela devient difficile de passer juste nécessaire en entrée de ta fonction, tu te retrouves à devoir te baser sur un état qu'il faut recontruire et c'est difficile à faire.

    Bien sûr pour du code, être capable de savoir ce qu'il contient, ses caractéristiques, de manière dynamique, ça peut être utile, mais pour retrouver juste ces widgets, utiliser des pointeurs vers des structures et les passer en paramètre me semble être le premier pas. Le second pas c'est effectivement GtkBuilder + Glade.
    Bonjour Liberforce.

    Loin de moi l'idée d'utiliser cette méthode comme étant la réponse à tous nos problèmes . Je suis tout à fait d'accord avec toi. Il faut passer aux fonctions ce dont elles ont besoin. Elles nous restituent ensuite le fruit de leur travail.
    Ici je me suis plutôt amuser à faire une figure de style. Ca donne une approche du fonctionnement d'encapsulation des widgets et une approche "philosophique" de l'utilisation ultérieure des GtkBuilder. Un pointeur à partir duquel on accède à tous les widgets de l'interface. D'ailleurs, lorsqu'on utilise Glade, il faut propager le pointeur GtkBuilder* à toutes les fonctions qui ont besoin d'accéder à l'interface. Et cela se fait en le transmettant en paramètre.
    J'ai aussi écrit ce code pour pap71. Il y a dans son code beaucoup trop de variables déclarées en globale. Il semblerait que l'utilisation des paramètres dans ses fonctions ne fasse pas encore partie de sa manière d'écrire. Son code est relativement difficile à lire et à déchiffrer par la même occasion, sans parler du déboggage,lorsqu'il y en a besoin.

    Voila c'est juste une petite pierre à l'édifice de la compréhension des systèmes...

  15. #15
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    C'est surtout qu'on m'a demandé si ton article de blog pouvait passer en page d'accueil, donc il me fallait quand même commenter pour laisser une trace qui dit "ne faites pas ça à la maison les enfants"
    Je suis d'accord pour l'aspect pédagogique

    Il y a dans son code beaucoup trop de variables déclarées en globale. Il semblerait que l'utilisation des paramètres dans ses fonctions ne fasse pas encore partie de sa manière d'écrire. Son code est relativement difficile à lire et à déchiffrer par la même occasion, sans parler du déboggage,lorsqu'il y en a besoin.
    Si développeur c'était si facile ce ne serait pas un métier
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

  16. #16
    Futur Membre du Club
    Homme Profil pro
    sans
    Inscrit en
    Novembre 2011
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Novembre 2011
    Messages : 10
    Points : 9
    Points
    9
    Par défaut g_strdup_printf g_strtod formfloat
    modif de sprintf en g_strdup_printf

    Dans le cas où on a un texte de longueur variable (dont codage en utf8)
    et que ce texte n'a pas vocation à être mémorisé dans une donnée de longueur définie (messages à afficher par exemple)
    ou on prend en compte la longueur et agit en conséquence
    la modif est tout à fait justifiée et encore merci.

    fonction formfloat (qui devrait s'appeler formdouble. Les calculs avec double sont moins imprécis qu'avec float).
    Le but de la fonction est d'éditer une variable double
    sprintf(s1,"%f",ff);
    s1 récupère l'édition du double ff avec le formatage standard %f.
    Le résultat a par défaut 6 décimales qq soit la valeur.
    exemple ff=2 résultat s1 = "2.000000"
    la fonction efface les car de fin si ='0' jusqu'à trouver # de '0' ou la marque décimale. si le dernier car est la marque décimale on l'efface.
    exemple ff=2 s1 final = 2 si ff=52.140000 s1 final = 52.14

    J'ai crée cette fonction pour mon prog de FACTURATION VERGIFAC pour la donnée quantité. Si l'utilisateur saisit quant = 5 l'édition retourne 5 et non 5.000000 réstituant en principe ce qu'il a saisi.

    Dans le cas de vergifac la quantité est saisie dans un edit de 10 caractères.
    La longueur maximale de s1 est 1234567890.000000 soit 17 caractères.
    formfloat(char *ss,double ff) retour dans ss.
    tant que ss pointe sur une variable > 17 car je pense ne pas risquer de débordement.
    longueur mini de ss = longueur des entiers estimés + 7 car.

    En revérifiant ma fonction formfloat, j'ai retrouvé une interrogation au sujet de la fonction g_strtod.
    double dd = g_strtod(text,NULL); // convertion texte en double
    concernant la marque décimale.
    Dans mon prog vergifac si la saisie du nombre se fait avec une marque décimale à la mode française (virgule), sur MON système ça marche (bien sur je l'ai testé x fois ).

    Pour en être sur j'ai refait le test avec un prog de test de formfloat et ça ne marche pas !

    g_strtod tient compte des 'local' dans quel cas ?

    formfloat.c test de la fonction

    formfloat.c

  17. #17
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par pap71 Voir le message
    ...
    g_strtod tient compte des 'local' dans quel cas ?
    Effectivement cette fonction peut poser problème. Un manière simple serait de vérifier si le texte comporte une virgule. Si oui tu la remplaces par un point, ou vice et versa...

    Citation Envoyé par pap71 Voir le message
    fonction formfloat (qui devrait s'appeler formdouble. Les calculs avec double sont moins imprécis qu'avec float).
    Le but de la fonction est d'éditer une variable double
    sprintf(s1,"%f",ff);
    s1 récupère l'édition du double ff avec le formatage standard %f.
    Le résultat a par défaut 6 décimales qq soit la valeur.
    ...
    Donc si ff = 2.123456789 tu décides de perdre la précision pour ne garder que ff = 2.123456. Si c'est bien çà tu peux déjà lors de conversion demander de ne conserver que les six chiffres après la virgule : sprintf(s1,"%0.6f",ff);.

    Tu gagnes déjà çà en simplification.

  18. #18
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    En compilant ton programme de test j'ai déjà ce warning :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    main.c:39:8: warning: right-hand operand of comma expression has no effect [-Wunused-value]
     fl = 10,31313002;
    Ce qui est tout à fait normal. Le code source ne connaît que le point. La virgule est un séparateur de champ et non un séparateur décimal.

  19. #19
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 291
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 291
    Points : 4 941
    Points
    4 941
    Billets dans le blog
    5
    Par défaut
    Je me suis encore un peu amusé . J'ai écrit une fonction gchar *formdouble (double ff) qui devrait faire l'affaire :
    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
    gchar *formdouble (double ff)
    {
      /* Pointeur sur une zone mémoire allouée dynamiquement qui contiendra le
       * résultat final. */
      gchar *result = NULL;
     
      /* conversion en gchar* avec 6 chiffres max après la virgule. */
      gchar *tmp = g_strdup_printf ("%0.6f", ff);
     
      /* Pointeur temporaire pour remplacer la virgule par un point au cas où. */
      gchar *find = NULL;
     
      /* on vérifie si la conversion comporte une virgule et non un point. Si oui
       * on change la virgule pour un point. */
      if ((find= g_strstr_len (tmp, -1, ",")))
          *find = '.';
     
      /* Suppression des 0 de fin, voir du point si nécessaire */
      gint length = strlen (tmp)-1; /* pour ne pas lire le terminateur /0 */
      gchar *car = tmp; /* curseur sur la chaîne à scruter */
     
      while (length>=0)
        {
          if (car[length]!='0' && car[length]!='.')
    	break;
          if (car[length]=='.')
    	{
    	  length--; /* Nécessaire pour enlever le '.' */
    	  break;
    	}
     
          length--;
        }
     
      /* length+1 correspond à la longueur finale du résultat. Il suffit de copier
       * les length+1 caractères de tmp et de renvoyer ce résultat. */
      result = g_strndup (tmp, length+1);
     
      /* Suppression de tmp devenu inutile */
      g_free (tmp);
     
      return result;
    }
    Elle renvoie un gchar* alloué. Il faudra donc une fois son utilisation devenue obsolète libérer la mémoire pointée par un g_free();.

    Pour exemple voici ce quelle renvoie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    transmis : 10.313130            result = 10.31313
    transmis : 1245643456.000001    result = 1245643456.000001
    transmis : 12346.102030         result = 12346.10203
    transmis : 12.000000            result = 12
    transmis : 0.000000             result = 0
    Pour l'utiliser dans ton code source voila un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
      gchar *result = NULL;
      gdouble fl = 10.31313002;
     
      for ( i=1; i<10; ++i)	{
        result = formdouble (fl);
        g_print ("i=%d fl=%f s= '%10s'\t %d\n",i,fl,result,(int)strlen(result));
        g_free (result);
        fl /= 5;
      }
    Et le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    i=1 fl=10.313130 s= '  10.31313'	 8
    i=2 fl=2.062626 s= '  2.062626'	 8
    i=3 fl=0.412525 s= '  0.412525'	 8
    i=4 fl=0.082505 s= '  0.082505'	 8
    i=5 fl=0.016501 s= '  0.016501'	 8
    i=6 fl=0.003300 s= '    0.0033'	 6
    i=7 fl=0.000660 s= '   0.00066'	 7
    i=8 fl=0.000132 s= '  0.000132'	 8
    i=9 fl=0.000026 s= '  0.000026'	 8

Discussions similaires

  1. Cherche Logiciel de Facturation Gratuit
    Par stanley dans le forum Autres Logiciels
    Réponses: 4
    Dernier message: 31/05/2016, 22h19
  2. Logiciels de Facturation VERGIFAC et de Comptabilité VERGISC
    Par pap71 dans le forum Autres Logiciels
    Réponses: 0
    Dernier message: 01/11/2013, 08h49
  3. Cherche Logiciel de Facturation
    Par stanley dans le forum Autres Logiciels
    Réponses: 10
    Dernier message: 17/12/2007, 07h22
  4. [INFO]Logiciel de Facturation
    Par stanley dans le forum Autres Logiciels
    Réponses: 1
    Dernier message: 29/09/2007, 15h20
  5. [aide]Conseils logiciel de facturation
    Par diden138 dans le forum Delphi
    Réponses: 14
    Dernier message: 12/01/2007, 10h47

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