Première application GNOME en C avec Anjuta et Glade

Introduction

Anjuta est un environnement intégré de développement en C ou en C++. Ce guide est cohérent avec la version 1.2.4a. Anjuta est couplé avec Glade (version 2.12.1 à l'heure où ces lignes sont écrites), qui est un programme simple d'emploi pour construire l'interface utilisateur graphique fenêtrée (pour GTK+ et GNOME) associée au programme construit sous Anjuta.
Ce guide est l'œuvre d'un débutant en la matière, qui a une certaine expérience de développement mais découvre totalement à la fois les langages C/C++ et les applications Anjuta et Glade. Il s'appuie beaucoup sur le guide de Micah Carrick (en anglais, et dont son auteur signale que ce n'est pas son guide le plus récent) et le complète sur un ou deux points qui ont quand même bloqué quelques heures l'auteur de la présente page... Disons-le : c'est moins facile que freepascal sous Lazarus car, d'une part, les concepts mis en œuvre sont moins simples et, d'autre part, il faut davantage intervenir à la main dans le code engendré... Trève de considérations oiseuses, au boulot...

L'utilisation de ce guide suppose que les applications Anjuta et GNOME sont installées, ainsi que les paquets GETTEXT, qui sont nécessaires à l'internationalisation (y compris les paquets de développement).
Par ailleurs, les scripts mis en œuvre par Anjuta utilisent des outils de configuration et de génération automatiques (autotools), notamment automake. La version 1.4 de ce dernier installée par défaut par Ubuntu "Dapper Drake" engendrent, lors de l'exécution des scripts, des erreurs relatives aux outils d'internationalisation (GETTEXT). Même si l'on ne met pas ceux-ci en jeu, la constitution d'un paquet distribuable pour transférer l'application sur un autre ordinateur échoue. Il faut donc installer une version plus récente d'automake : la version 1.9 convient. En cas de besoin, voir la description de l'installation.

But visé

Selon une tradition bien établie, la première application sera un programme minimal "Bonjour le Monde" dont la fenêtre principale va être la suivante :

Choisir l'option "Nouveau" du menu "Fichier" provoquera l'affichage de la nouvelle fenêtre suivante :


tandis que choisr l'option "Quitter" du même menu fermera l'application.

Création du projet, une manière simple

Il y a plusieurs façons de procéder, celle décrite ci-dessous convient à un projet simple pour débuter.

Au lancement d'Anjuta, par défaut, s'ouvre un assistant qui offre plusieurs choix. Cet assistant est très utile pour la création de nouveaux projets car il permet d'obtenir tous les éléments du "squelette" du projet.

Dans la première fenêtre de l'assistant, cliquer sur le bouton "Assistant de création d'application".
Dans la deuxième, il n'y a rien à faire, cliquer sur le bouton "Avancer".
Dans la suivante faire un simple clic pour sélectionner l'icone "Projet GNOME 2.0" puis cliquer sur le bouton "Avancer".
Dans la quatrième, il faut faire un peu d'écriture : donner le nom du projet (par défaut, l'assistant recopie le même nom dans le champ cible (la cible est le produit d'Anjunta, dans notre cas, l'exécutable)), le numéro de version, le nom de l'auteur. Dans la même fenêtre, choisir le langage utilisé (ici C) et le type de cible (dans notre cas: cible d'exécution, ce qui signifie que Anjuta va produire un exécutable). Puis cliquer sur Avancer.
Dans la suivante, donner une petite description. Puis cliquer sur Avancer.
Dans la sixième, pour ce projet, il est inutile de garder le copyright GNU. Ne conserver la case "Support de gettext" que si l'on sait manier l'internationalisation. Pour ce premier projet, il suffira de conserver seulement la dernière case cochée (génération du code en utilisant glade, pour se faciliter la construction du code associé à l'interface graphique). Puis cliquer sur Avancer.
Enfin, dans la dernière étape, vérifier la récapitulation des informations et les confirmer en cliquant sur "Appliquer"

Anjuta prend une minute pour faire la construction du projet. Ce faisant,il affiche une longue liste de messages pendant la génération du projet, avec quelques avertissements mais pas d'erreur fatale, et conclut à la réussite. Bien.

A la fin de cet exercice, on se retrouve avec, dans le dossier "Projects", un nouveau dossier de 2,4 Mo contenant une ribambelle ésotérique de fichiers (acconfig.h, config.h, bonjour.desktop, install-sh, NEWS, acinclude.m4, config.h.in, bonjour.desktop.in, libtool, aclocal.m4, config.log, bonjour.glade, ltmain.sh, README, AUTHORS, config.status, bonjour.gladep, Makefile, setup-gettext, autogen.sh, config.sub, bonjour.prj, Makefile.am, configure, bonjour.prj.bak, Makefile.in, stamp-h, ChangeLog, configure.in, bonjour.pws, missing, stamp-h.in, config.guess, COPYING, INSTALL, mkinstalldirs, TODO) et trois sous-dossiers (po, src, autom4te.cache).
Pour le moment, le sous-dossier src nous intéresse particulièrement. On y trouve les fichiers du programme proprement dits (callbacks.c, interface.c, main.c, Makefile.am, support.c, callbacks.h, interface.h, Makefile, Makefile.in, support.h). Il contient notamment le programme principal main.c et le fichier callbacks.c qui contiendra le code attaché aux actions de l'utilisateur sur les contrôles de la fenêtre du programme. Après la compilation, on y trouvera aussi l'exécutable. Il est temps de passer à la programmation de l'application.

Conception de la fenêtre d'interface

A ce stade, on est dans Anjuta, avec une fenêtre presque vide :

.

On lance Glade depuis Anjuta, en prenant l'option "Editer l'IHM" du menu "Projet". Cela ouvre Glade qui affiche plusieurs fenêtres : la principale "Glade", ainsi que "propriétés", "palette" et "hiérarchie des composants". Le bureau commence à être encombré ! En déplaçant Anjunta sur un autre bureau, voici ce que donne Glade au lancement :
.

Si la fenêtre "Hiérarchie des composants graphiques" n'est se montre pas, aller dans la fenêtre principale de Glade, Menu Affichage, et sélectionner l'option correspondante.

Dans la fenêtre Glade, faire un double clic sur le composant window1, cela ouvre une fenêtre encore vierge.
Dans la palette, sélectionner l'outil "boîte verticale" et cliquer dans la fenêtre vierge ; dans le dialogue qui s'ouvre, spécifier "2" au lieu de "3" et valider. Cela divise verticalement la fenêtre en deux parties, comme montré ci-dessous :

.

Dans la palette, sélectionner l'outil "Barre de menu" et cliquer dans la partie supérieure de la fenêtre. Celle-se réduit alors à une barre de menu ! En dessous subsiste le reste de l'espace vierge.
Juste pour le décor, dans la palette sélectionner l'outil "Etiquette" et cliquer dans l'espace vide ; celui-ci se remplit d'un panneau blanc contenant simplement "label1".

L'interface est complète, il reste à en personnaliser l'aspect esthétique dans Glade, comme exposé juste après, d'une part, et, d'autre part, à écrire dans Anjuta les éléments de code connectés aux composants graphiques, ce qui fait l'objet du chapitre suivant.

Pour la personnalisation, il est commode de se servir de la fenêtre "hiérarchie des composants" qui présente tous les composants graphiques sous la forme d'une arborescence ; il est possible la "déplier" plus ou moins en simple-cliquant sur le triangle placé devant chaque composant.


Dans les opérations ci-dessous, "sélectionner tel composant" signifie "simple-cliquer sur tel composant dans la fenêtre 'hiérachie des composants graphiques'" ; ceci a pour effet de le mettre en couleurs inversées.
Pour le cas présent, appliquer les étapes suivantes :

Programmation

Pour la programmation, dans Anjuta, dans le panneau "Projet" à gauche, déplier le dossier "source - src" et faire un double-clic sur le fichier callbacks.c pour l'ouvrir dans l'éditeur.
Dans l'éditeur, rechercher la fonction "on_quitter1_activate" (ou "on_quit1_activate"), initialement vide, et la compléter pour lui donner la forme suivante :

void
on_quitter1_activate     (GtkMenuItem *menuitem,
                                         gpointer user_data)
{
gtk_main_quit();
}

Ceci permet d'accrocher à l'option "Quitter" du menu "Fichier" la fonction qui fait quitter le programme principal.

On va maintenant connecter une action à l'option "Nouveau" du même menu. Toujours dans callbacks.c, rechercher la fonction "on_nouveau1_activate" (ou "on_new1_activate").
Elle est initialement vide. La compléter pour lui donner la forme :

void
on_nouveau1_activate     (GtkMenuItem *menuitem,
                                         gpointer user_data)
{
GtkWidget *msgbox = gnome_app_new("Choix de Nouveau", NULL);
gnome_app_message (GNOME_APP(msgbox), "Bonjour, vous avez choisi Nouveau!");
}

La première ligne ajoutée entre les accolades crée une nouvelle fenêtre (msgbox), et la deuxième ligne y inscrit un message.
On y est presque. Seulement, pour que callbacks.c puisse ouvrir une nouvelle fenêtre, il faut d'abord l'initialiser dans le programme principal.
Dans le panneau de gauche de Anjuta, double cliquer sur main.c et entrer dedans dans la fenêtre de l'éditeur. Il s'avère que les deux modifications suivantes ne sont pas toujours nécessaires, les lignes voulues étant déjà présentes. Donc, le cas échéant :

Modification 1 - Début

Après la ligne

gtk_init (&argc, &argv);

Ajouter les deux lignes suivantes :

// Ci-dessous, ligne ajoutee pour les besoins de callbacks.c
gnome_program_init(PACKAGE, VERSION, LIBGNOMEUI_MODULE, argc, argv, NULL) ;

La première ligne n'est qu'un commentaire au contenu indifférent. La seconde initialise l'application pour permettre la création d'une nouvelle fenêtre par callbacks.c.

Modification 1 - Fin

Modification 2 - Début

Pour que cette fonction puisse fonctionner, il faut inclure un élément supplémentaire dans le programme. Toujours dans main.c, remplacer la ligne

#include <gtk/gtk.h>

par la ligne

#include <gnome.h>

car cette deuxième ligne permet d'avoir accès aux fonctionnalités de GNOME et implique l'inclusion de l'en-tête de gtk initialement inscrite dans le fichier.
Et il faut également procéder au même remplacement de ligne dans callbacks.c pour que la fonction gnome_app_new soit reconnue.

Modification 2 - Fin

Cette fois, c'est fini.

Bien sûr, l'application exécutable est disponible dans le dossier src cité plus haut, d'où elle peut être exécutée en double-cliquant dessus, sans passer par Anjuta. Voilà, c'est terminé ... réussite ;-).

Distribution

Pour transférer le programme sur un autre ordinateur, il ne reste plus qu'a choisir "Projet/Préparer la distribution".
Encore une suite de messages de la part d'Anjuta... Les opérations produisent un fichier comprimé (tar.gz) contenant les éléments nécessaires à l'installation du programme sur une autre machine.

Compléments et commentaires

Le code

En cas de besoin, voici le contenu de main.c et de callbacks.c.

Les arguments de la fonction gnome_app_new

La fonction gnome_app_new, qui est utilisée dans callbacks.c pour créer une nouvelle fenêtre, demande deux arguments : le premier est le nom de l'application associée (une chaîne de caractères qui la caractérise de façon unique) et le second est un titre pour la fenêtre. Cependant, dans l'emploi qui en est fait ici, l'utilisateur pourra constater que les deux chaînes n'ont guère d'influence.

GETTEXT

La seule erreur mise en évidence en rouge dans les messages de construction initiale, lorsque l'on emploie la version 1.4 d'automake, est celle relative à GETTEXT :

Makefile.am:6: AM_GNU_GETTEXT in `configure.in' but `intl' not in SUBDIRS

Cette erreur disparaît avec automake 1.9. Ce dernier est toutefois un peu plus exigeant sur la syntaxe, ce qui provoque quelques avertissements, heureusement sans gravité.

GETTEXT est une fonction GNU qui permet d'écrire des programmes multilingues. Lors de l'écriture du programme, le développeur prend des dispositions pour que l'interface de son logiciel s'adapte à la langue locale, pour peu qu'un traducteur ait élaboré le fichier de traduction idoine. Tout ceci est expliqué dans cet article de Wikipedia.

Autres erreurs non fatales à la construction

Le premier avertissement est le suivant :

Please add the files
codeset.m4 gettext.m4 glibc21.m4 iconv.m4 isc-posix.m4 lcmessage.m4 progtest.m4
from the /usr/share/aclocal directory to your autoconf macro directory or directly to your aclocal.m4 file.
You will also need config.guess and config.sub, which you can get from ftp://ftp.gnu.org/pub/gnu/config/.

Vérification faite, les fichiers cités sur la deuxième ligne sont sur la machine depuis bien longtemps avant l'installation de Anjuta . La recherche de "autoconf" montre qu'il y a un exécutable ("script shell") de ce nom là dans usr/bin/ mais qu'il n'y a qu'un dossier de ce nom (en fait deux, l'un contenu dans l'autre) (usr/share/autoconf/autoconf). Le dossier intérieur contient effectivement des macros, dont l'une qui s'appelle "autoconf.m4". On peut donc supposer que l'avertissement signifie qu'il faut placer les fichiers désignés (ou peut-être seulement un lien vers eux) dans ce dossier.
Par ailleurs, aclocal.m4 est un long fichier de code (dans le dossier du projet) et ceci ne donne pas trop envie de le modifier pour venir y coller le contenu des autres fichiers de macro. La première solution semble préférable... Ce point reste à approfondir.

Les fichiers config.guess et config.sub évoqués par la deuxième partie du message contiennent des informations permettant à Anjuta d'adapter l'application aux diverses architectures informatiques susceptibles d'être rencontrées. Ces fichiers sont régulièrement mis à jour. Pour améliorer la portabilité des applications, il est donc avantageux de s'assurer que l'on dispose des dernières versions téléchargées sur le site indiqué.

Quant aux messages disant qu'on peut faire mieux en utilisant des méthodes plus modernes, on est content de le savoir ; cela donne une marge de progrès... ;-).