Salome HOME
configuration du langage
[samples/hello.git] / doc / dev_guide.html
1 <?xml version="1.0" encoding="utf-8" ?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6 <meta name="generator" content="Docutils 0.3.0: http://docutils.sourceforge.net/" />
7 <title>Guide pour le développement d'un module SALOME 2 en C++</title>
8 <link rel="stylesheet" href="default.css" type="text/css" />
9 </head>
10 <body>
11 <div class="document" id="guide-pour-le-d-veloppement-d-un-module-salome-2-en-c">
12 <h1 class="title">Guide pour le développement d'un module SALOME 2 en C++</h1>
13 <table class="docinfo" frame="void" rules="none">
14 <col class="docinfo-name" />
15 <col class="docinfo-content" />
16 <tbody valign="top">
17 <tr class="field"><th class="docinfo-name">Auteur:</th><td class="field-body">Crouzet N.</td>
18 </tr>
19 </tbody>
20 </table>
21 <div class="contents topic" id="contents">
22 <p class="topic-title"><a name="contents">Contents</a></p>
23 <ul class="auto-toc simple">
24 <li><a class="reference" href="#pr-sentation" id="id1" name="id1">1   Présentation</a></li>
25 <li><a class="reference" href="#les-tapes-de-construction-du-module-exemple" id="id2" name="id2">2   Les étapes de construction du module exemple</a></li>
26 <li><a class="reference" href="#cr-ation-de-l-arborescence-du-module" id="id3" name="id3">3   Création de l'arborescence du module</a></li>
27 <li><a class="reference" href="#interface-idl" id="id4" name="id4">4   Interface idl</a></li>
28 <li><a class="reference" href="#impl-mentation-c" id="id5" name="id5">5   Implémentation C++</a><ul class="auto-toc">
29 <li><a class="reference" href="#les-sources" id="id6" name="id6">5.1   Les sources</a></li>
30 <li><a class="reference" href="#makefile" id="id7" name="id7">5.2   Makefile</a></li>
31 </ul>
32 </li>
33 <li><a class="reference" href="#pilotage-du-composant-depuis-python-mode-tui" id="id8" name="id8">6   Pilotage du composant depuis Python (mode TUI)</a></li>
34 <li><a class="reference" href="#interface-graphique" id="id9" name="id9">7   Interface graphique</a><ul class="auto-toc">
35 <li><a class="reference" href="#introduction" id="id10" name="id10">7.1   Introduction</a></li>
36 <li><a class="reference" href="#choix-des-widgets" id="id11" name="id11">7.2   Choix des widgets</a><ul class="auto-toc">
37 <li><a class="reference" href="#description-xml" id="id12" name="id12">7.2.1   Description xml</a></li>
38 <li><a class="reference" href="#convention" id="id13" name="id13">7.2.2   Convention</a></li>
39 </ul>
40 </li>
41 <li><a class="reference" href="#impl-mentation-de-l-ihm" id="id14" name="id14">7.3   Implémentation de l'IHM</a><ul class="auto-toc">
42 <li><a class="reference" href="#gestion-des-v-nements" id="id15" name="id15">7.3.1   Gestion des évènements</a></li>
43 <li><a class="reference" href="#classes-disponibles" id="id16" name="id16">7.3.2   Classes disponibles</a></li>
44 <li><a class="reference" href="#gestion-du-multi-linguisme" id="id17" name="id17">7.3.3   Gestion du multi-linguisme</a></li>
45 </ul>
46 </li>
47 </ul>
48 </li>
49 <li><a class="reference" href="#r-gles-syntaxiques-de-nommage" id="id18" name="id18">8   Règles syntaxiques de nommage</a></li>
50 </ul>
51 </div>
52 <div class="section" id="pr-sentation">
53 <h1><a class="toc-backref" href="#id1" name="pr-sentation">1   Présentation</a></h1>
54 <p>Ce document a pour objectif de décrire les différentes étapes
55 du développement d'un module SALOME 2 en C++.
56 Il fait suite au document &quot;Guide pour le développement d'un module SALOME 2 en
57 Python&quot;, qui documente de module PYHELLO, et en reprend la démarche :
58 construction pas à pas d'un module HELLO.
59 Comme de nombreux points ne sont pas repris, il est recommendé de lire ce
60 document préalablement.</p>
61 </div>
62 <div class="section" id="les-tapes-de-construction-du-module-exemple">
63 <h1><a class="toc-backref" href="#id2" name="les-tapes-de-construction-du-module-exemple">2   Les étapes de construction du module exemple</a></h1>
64 <p>Le composant choisi pour illustrer le processus de construction en C++
65 est le même que celui choisi pour illustrer la construction du module python :
66 il implémentera donc la même interface idl Corba.
67 Il sera complété par un GUI graphique écrit en Qt.</p>
68 <p>Les différentes étapes du développement seront les suivantes :</p>
69 <blockquote>
70 <ul class="simple">
71 <li>créer une arborescence de module</li>
72 <li>créer un composant SALOME 2 chargeable par un container C++</li>
73 <li>configurer le module pour que le composant soit connu de SALOME</li>
74 <li>ajouter un GUI graphique</li>
75 <li>rendre le composant utilisable dans le superviseur</li>
76 </ul>
77 </blockquote>
78 </div>
79 <div class="section" id="cr-ation-de-l-arborescence-du-module">
80 <h1><a class="toc-backref" href="#id3" name="cr-ation-de-l-arborescence-du-module">3   Création de l'arborescence du module</a></h1>
81 <p>Dans un premier temps, on se contentera de mettre dans le module exemple un composant
82 SALOME écrit en C++ qui sera chargeable par un container C++.
83 Il suffit donc d'une interface idl et d'une implantation C++ du composant.
84 Pour mettre en oeuvre ceci dans un module SALOME 2, il nous faut reproduire l'arborescence de
85 fichier standard suivante:</p>
86 <pre class="literal-block">
87 + HELLO1_SRC
88   + build_configure
89   + configure.in.base
90   + Makefile.in
91   + adm_local
92     + unix
93       + make_commence.in
94       + make_omniorb.in
95       + config_files
96   + bin
97     + VERSION
98     + runAppli.in
99     + runSalome.py
100   + idl
101     + Makefile.in
102     + HELLO_Gen.idl
103   + src
104     + Makefile.in
105     + HELLO
106       + Makefile.in
107       + HELLO.cxx 
108       + HELLO.hxx 
109   + doc
110 </pre>
111 <p>Pour cela, on recopie l'arborescence de PYHELLO, et on modifie où nécessaire
112 PYHELLO en HELLO:</p>
113 <pre class="literal-block">
114 cp -r PYHELLO1_SRC HELLO1_SRC
115 cd HELLO1_SRC
116 mv idl/PYHELLO_Gen.idl idl/HELLO_Gen.idl
117 mv src/PYHELLO src/HELLO
118 </pre>
119 </div>
120 <div class="section" id="interface-idl">
121 <h1><a class="toc-backref" href="#id4" name="interface-idl">4   Interface idl</a></h1>
122 <p>Dans le répertoire idl, nous modifions le fichier idl HELLO_Gen.idl : le
123 module défini est renommé HELLO_ORB, et l'interface en HELLO_Gen.
124 Le service rendu reste le même : à partir d'une chaine de caractères
125 fournie comme unique argument, retour d'une chaine de caractères obtenue
126 par concaténation de &quot;Hello, &quot; et de la chaine d'entrée.
127 Ce service est spécifié par la fonction makeBanner.</p>
128 <p>Un utilitaire de documentation basé sur doxygen a été mis en place pour
129 compiler une documentation des services corba à partir de commentaires se
130 trouvant dans les fichiers idl. Nous rajouter donc à notre idl quelques
131 commentaires, en respectant le formalisme doxygen.
132 Un commentaire doxygen commence par &quot;/<em>!&quot; et se finit pas &quot;</em>/&quot;.
133 Pour structurer un minimum les pages générées, on les regroupes par module ou
134 sujet. Dans notre exemple, nous utilisons la directive:</p>
135 <pre class="literal-block">
136 \ingroup EXAMPLES 
137 </pre>
138 <p>spécifiant que la documentation générée fait partie du groupe EXAMPLES.
139 (pour plus d'information sur doxygen, consulter le site www.doxygen.org).</p>
140 <p>Pour finir, nous mettons à jour le Makefile avec le nouveau nom de composant:</p>
141 <pre class="literal-block">
142 IDL_FILES = HELLO_Gen.idl
143 </pre>
144 </div>
145 <div class="section" id="impl-mentation-c">
146 <h1><a class="toc-backref" href="#id5" name="impl-mentation-c">5   Implémentation C++</a></h1>
147 <div class="section" id="les-sources">
148 <h2><a class="toc-backref" href="#id6" name="les-sources">5.1   Les sources</a></h2>
149 <p>L'implémentation C++ de notre module CORBA HELLO (interface idl HELLO_Gen) est faite dans le répertoire
150 /src/HELLO:</p>
151 <pre class="literal-block">
152 HELLO.hxx
153 HELLO.cxx
154 </pre>
155 <p>Au début du header de notre module (HELLO.hxx), les inclusions suivantes sont
156 nécessaires:</p>
157 <pre class="literal-block">
158 #include &lt;SALOMEconfig.h&gt;
159 #include CORBA_SERVER_HEADER(HELLO_Gen)
160 #include &quot;SALOME_Component_i.hxx&quot;
161 </pre>
162 <p>Le fichier SALOMEconfig.h contient un certain nombre de définitions utiles
163 pour assurer l'indépendance du code par rapport à la version de CORBA
164 utilisée. SALOME_Component_i.hxx contient l'interface de la classe
165 d'implémentation C++ du composant de base Salome (idl Engines::Component).
166 Enfin, la macro CORBA_SERVER_HEADER assure l'indépendance des noms de fichiers
167 d'inclusion par rapport à l'implémentation de l'ORB CORBA.</p>
168 <p>Après cela, nous définissons une classe d'implémentation, nommée HELLO, dérivant de
169 POA_HELLO_ORB::HELLO_Gen (classe abstraite générée automatiquement par CORBA lors de la
170 compilation de l'idl) et de Engines_Component_i (car l'interface idl HELLO_Gen
171 dérive de Engines::Component comme tout composant Salome2). Cette classe
172 contient un constructeur dont les arguments sont imposés par CORBA, un
173 destructeur virtuel, et une méthode makeBanner fournissant le service souhaité:</p>
174 <pre class="literal-block">
175 class HELLO:
176   public POA_HELLO_ORB::HELLO_Gen,
177   public Engines_Component_i
178 {
179 public:
180     HELLO(CORBA::ORB_ptr orb,
181             PortableServer::POA_ptr poa,
182             PortableServer::ObjectId * contId,
183             const char *instanceName,
184             const char *interfaceName);
185     virtual ~HELLO();
186     char* makeBanner(const char* name);
187 };
188 </pre>
189 <p>La fonction makeBanner prend comme argument et renvoit un char*, projection C++ du type CORBA/IDL
190 string. 
191 La documentation complète du mapping c++ de l'IDL est fournie par l'OMG sur
192 son site internet : <a class="reference" href="http://www.omg.org/cgi-bin/doc?ptc/00-01-02">http://www.omg.org/cgi-bin/doc?ptc/00-01-02</a>.</p>
193 <p>Enfin, nous fournissons l'interface (normalisé) de la fonction HELLOEngine_factory, qui
194 sera appelée par le &quot;FactoryServer C++&quot; pour charger le composant HELLO:</p>
195 <pre class="literal-block">
196 extern &quot;C&quot;
197     PortableServer::ObjectId * HELLOEngine_factory(
198             CORBA::ORB_ptr orb,
199             PortableServer::POA_ptr poa,
200             PortableServer::ObjectId * contId,
201             const char *instanceName,
202             const char *interfaceName);
203 </pre>
204 <p>Dans le fichier source (HELLO.cxx) se trouvent les définitions 
205 du constructeur et de la fonction d'instanciation
206 HELLOEngine_factory (toutes deux normalisées!), et de makeBanner:</p>
207 <pre class="literal-block">
208 char* HELLO::makeBanner(const char* name)
209 {
210     string banner=&quot;Hello, &quot;;
211     banner+=name;
212     return CORBA::string_dup(banner.c_str());
213 }
214 </pre>
215 <p>Dans cette fonction, l'emploi de string_dup (fonction déclarée dans le
216 namespace CORBA) n'est pas obligatoire (on aurait pu utiliser l'opérateur new),
217 mais conseillé car ces fonctions permettent aux ORB d'utiliser des mécanismes
218 spéciaux de gestion de la mémoire sans avoir à redéfinir les opérateurs new
219 globaux.</p>
220 </div>
221 <div class="section" id="makefile">
222 <h2><a class="toc-backref" href="#id7" name="makefile">5.2   Makefile</a></h2>
223 <p>Dans le makefile, il faut définir certaines cibles:</p>
224 <pre class="literal-block">
225 VPATH=.:&#64;srcdir&#64;:&#64;top_srcdir&#64;/idl
226 LIB = libHELLOEngine.la
227 LIB_SRC = HELLO.cxx
228 LIB_SERVER_IDL = HELLO_Gen.idl
229 LIB_CLIENT_IDL = SALOME_Component.idl SALOME_Exception.idl Logger.idl
230 CPPFLAGS += -I${KERNEL_ROOT_DIR}/include/salome
231 LDFLAGS+= -lSalomeContainer -lOpUtil -L${KERNEL_ROOT_DIR}/lib/salome
232 </pre>
233 <p>Passons en revue chacune de ces cibles.
234 - LIB contient le nom <em>normalisé</em> (lib&lt;Nom_Module&gt;Engine.la) le nom de la
235 librairie, LIB_SRC définit le nom des fichiers sources, et VPATH les
236 repertoire où l'on peut les trouver.
237 - LIB_SERVER_IDL contient le nom des fichiers idl implémentés par le module.
238 - LIB_CLIENT_IDL contient le nom des idl où sont définis les services CORBA
239 utilisés par le module. HELLO utilise Logger.idl via les macros &quot;MESSAGE&quot;,
240 SALOME_Component.idl et SALOME_Exception.idl via l'héritage de HELLO_ORB::
241 - Il faut ajouter à CPPFLAGS le chemin pour les fichiers includes utilisés
242 (SALOMEconfig.h, SALOME_Component_i.hxx et utilities.h se trouvent dans
243 ${KERNEL_ROOT_DIR}/include/salome)::
244 - La classe HELLO utilise les librairies lib (pour Engines_Component_i) et
245 libOptUtil (pour PortableServer et Salome_Exception). On indique donc le nom
246 de ces librairies et leur chemin dans LDFLAGS.
247 D'autres librairies sont souvent utiles, par exemple libsalomeDS si on
248 implémente la persistence, ou libSalomeNS si on utilise le naming service.</p>
249 </div>
250 </div>
251 <div class="section" id="pilotage-du-composant-depuis-python-mode-tui">
252 <h1><a class="toc-backref" href="#id8" name="pilotage-du-composant-depuis-python-mode-tui">6   Pilotage du composant depuis Python (mode TUI)</a></h1>
253 <p>Lors de la compilation du module, la cible lib du Makefile dans /idl a
254 provoqué la génération d'un stub python (souche côté client générée à partir
255 de l'idl et offrant une interface dans le langage client - ici python.
256 Concrètement, un module python HELLO_ORB contenant une classe
257 _objref_HELLO_Gen sont créés, permettant de faire appel aux services de notre
258 module C++ depuis python. Mettons ceci en application. Pour cela, nous lançons
259 Salome en mode TUI:</p>
260 <pre class="literal-block">
261 cd $HELLO_ROOT_DIR/bin/salome
262 python -i runSalome.py --modules=HELLO --xterm --logger --containers=cpp,python --killall
263 </pre>
264 <p>Depuis la fenêtre python, nous importons le module LifeCycle, et utilisons ses
265 services pour charger notre composant Dans la conteneur C++ FactoryServer:</p>
266 <pre class="literal-block">
267 &gt;&gt;&gt; import LifeCycleCORBA
268 &gt;&gt;&gt; lcc = LifeCycleCORBA.LifeCycleCORBA(clt.orb)
269 &gt;&gt;&gt; import HELLO_ORB
270 &gt;&gt;&gt; hello = lcc.FindOrLoadComponent(&quot;FactoryServer&quot;, &quot;HELLO&quot;)
271 </pre>
272 <p>L'import de HELLO_ORB est nécessaire avant l'appel de FindOrLoadComponent,
273 pour permettre de retourner un objet typé (opération de &quot;narrowing&quot;). Sinon,
274 l'objet retourné est générique de type Engines::Component. Vérifions que notre
275 objet hello est correctement typé, et appelons le service makeBanner:</p>
276 <pre class="literal-block">
277 &gt;&gt;&gt; print hello
278 &lt;HELLO_ORB._objref_HELLO_Gen instance at 0x8274e94&gt;
279 &gt;&gt;&gt; mybanner=hello.makeBanner(&quot;Nicolas&quot;)
280 &gt;&gt;&gt; print mybanner
281 Hello, Nicolas
282 </pre>
283 <p>Les commandes précédentes ont été regroupées dans la fonction test du script
284 /bin/runSalome.py.</p>
285 </div>
286 <div class="section" id="interface-graphique">
287 <h1><a class="toc-backref" href="#id9" name="interface-graphique">7   Interface graphique</a></h1>
288 <div class="section" id="introduction">
289 <h2><a class="toc-backref" href="#id10" name="introduction">7.1   Introduction</a></h2>
290 <p>Pour aller plus loin dans l'intégration de notre module, nous allons ajouter
291 une interface graphique (développée en Qt), s'intégrant dans l'interface
292 applicative de Salome (IAPP).
293 On ne détaillera pas ici le fonctionnement de l'IAPP de Salome, mais pour
294 résumer, l'IAPP gère une boucle d'évènements (clics souris, clavier, etc), et
295 redirige après traitement ces évènements vers le module actif (le principe est
296 qu'à un instant donné, <em>un</em> module est actif. Lorsqu'un module est activé, son
297 IHM est chargée dynamiquement).
298 Le programmeur de la GUI d'un module a donc à charge de définir les méthodes
299 permettant de traiter correctement les évènements transmis. Parmi ces
300 méthodes, citons les principales : OnGUIEvent(), OnMousePress(), OnMouseMove(),
301 OnKeyPress(), DefinePopup(), CustomPopup().</p>
302 </div>
303 <div class="section" id="choix-des-widgets">
304 <h2><a class="toc-backref" href="#id11" name="choix-des-widgets">7.2   Choix des widgets</a></h2>
305 <div class="section" id="description-xml">
306 <h3><a class="toc-backref" href="#id12" name="description-xml">7.2.1   Description xml</a></h3>
307 <p>La description des items de notre module se fait dans le fichier XML
308 /ressources/HELLO_en.xml. Ce fichier est utilisé par l'IAPP pour charger
309 dynamiquement l'IHM du module quand celle-ci est activée.
310 Le principe est de définir par des balises les menus et boutons souhaités, et
311 d'y associer des ID, qui seront récupérés par les fonctions gérant les
312 évènemements IHM. Plusieures possibilités sont offertes:</p>
313 <ul>
314 <li><p class="first">ajout d'items à des menus déjà existant, auquel cas il faut reprendre les
315 balises du menu pré-existant, et y ajouter les nouveaux items. Dans
316 l'exemple qui suis, on ajoute le Menu <strong>Hello</strong> et l'item <strong>MyNewItem</strong> au
317 menu File, dont l'ID vaut 1:</p>
318 <pre class="literal-block">
319 &lt;menu-item label-id=&quot;File&quot; item-id=&quot;1&quot; pos-id=&quot;&quot;&gt;
320      &lt;submenu label-id=&quot;Hello&quot; item-id=&quot;19&quot; pos-id=&quot;8&quot;&gt;
321         &lt;popup-item item-id=&quot;190&quot; pos-id=&quot;&quot; label-id=&quot;MyNewItem&quot; icon-id=&quot;&quot; tooltip-id=&quot;&quot; accel-id=&quot;&quot; toggle-id=&quot;&quot; execute-action=&quot;&quot;/&gt;
322       &lt;/submenu&gt;
323       &lt;endsubmenu /&gt;
324 &lt;/menu-item&gt;
325 </pre>
326 </li>
327 <li><p class="first">Création de nouveaux menus. Pour le module HELLO, nous ajoutons un menu
328 HELLO, avec un unique item de label &quot;Get banner&quot;:</p>
329 <pre class="literal-block">
330 &lt;menubar&gt;
331  &lt;menu-item label-id=&quot;HELLO&quot; item-id=&quot;90&quot; pos-id=&quot;3&quot;&gt;
332   &lt;popup-item item-id=&quot;901&quot; label-id=&quot;Get banner&quot; icon-id=&quot;&quot; tooltip-id=&quot;Get HELLO banner&quot; accel-id=&quot;&quot; toggle-id=&quot;&quot; execute-action=&quot;&quot;/&gt;
333  &lt;/menu-item&gt;
334 &lt;/menubar&gt;
335 </pre>
336 </li>
337 <li><p class="first">Ajout d'un bouton dans la barre à boutons. Dans l'exemple suivant, nous
338 créons un deuxième point d'entrée pour notre action &quot;Get banner&quot;, sous forme
339 d'un bouton associé au même ID &quot;901&quot;. L'icône est spécifiée par la le champ
340 icon-id, qui doit être un fichier graphique 20x20 pixels au format png:</p>
341 <pre class="literal-block">
342 &lt;toolbar label-id=&quot;HELLO&quot;&gt;
343  &lt;toolbutton-item item-id=&quot;901&quot; label-id=&quot;Get banner&quot; icon-id=&quot;ExecHELLO.png&quot;
344 tooltip-id=&quot;Get HELLO banner&quot; accel-id=&quot;&quot; toggle-id=&quot;&quot; execute-action=&quot;&quot;/&gt;
345 &lt;/toolbar&gt;
346 </pre>
347 </li>
348 </ul>
349 </div>
350 <div class="section" id="convention">
351 <h3><a class="toc-backref" href="#id13" name="convention">7.2.2   Convention</a></h3>
352 <p>A chaque menu ou item est associé un ID. Les numéros entre 1 et 40 sont
353 réservés à l'IAPP. Les numéros d'ID suivent une certaine règle, quoique
354 celle-ci ne soit pas obligatoire. Au menu &quot;HELLO&quot; est associé l'ID 90. Son
355 unique item &quot;Get banner&quot; a l'ID 901. Un deuxième item aurait l'ID 902, et un
356 sous item l'ID 9021.</p>
357 </div>
358 </div>
359 <div class="section" id="impl-mentation-de-l-ihm">
360 <h2><a class="toc-backref" href="#id14" name="impl-mentation-de-l-ihm">7.3   Implémentation de l'IHM</a></h2>
361 <p>L'implémentation C++ de l'IHM est faite dans le répertoire /src/HELLOGUI.
362 Le header HELLOGUI.h déclare de la classe HELLOGUI, et
363 contient des directives Qt (Q_OBJECT). De ce fait, il doit être processé par
364 le compilateur moc (Qt Meta Model Compiler). Pour cette raison, l'extension du
365 fichier est .h et dans le Makefile nous ajoutons la cible:</p>
366 <pre class="literal-block">
367 LIB_MOC = HELLOGUI.h
368 </pre>
369 <p>Le fichier source HELLO.cxx contient la définition des fonctions membres, et
370 le Makefile permet de construire une librairie libHELLOGUI (le nom est
371 normalisé poour permettre le chargement dynamique : lib&lt;NomModule&gt;GUI.</p>
372 <div class="section" id="gestion-des-v-nements">
373 <h3><a class="toc-backref" href="#id15" name="gestion-des-v-nements">7.3.1   Gestion des évènements</a></h3>
374 <p>Pour l'IHM d'HELLO, nous définissons la fonction HELLOGUI::OnGUIEvent, qui
375 sera appelé à chaque évènement. Cette fonction contient essentiellement une
376 structure switch permettant de traiter l'ID reçu en argument:</p>
377 <pre class="literal-block">
378 switch (theCommandID)
379   {
380   case 901:
381     // Traitement de &quot;Get banner&quot;
382     ...
383   case 190:
384     // Traitement de &quot;MyNewItem&quot;
385     ...
386   }
387 </pre>
388 <p>Le traitement standard consiste à récupérer des données d'entrée (ici, le
389 prénom via une fenêtre de dialogue QInputDialog::getText), à récupérer une
390 poignée sur le composant CORBA interfacé afin d'appeler le service souhaité
391 (ici, getBanner), et d'afficher le résultat obtenu ().</p>
392 </div>
393 <div class="section" id="classes-disponibles">
394 <h3><a class="toc-backref" href="#id16" name="classes-disponibles">7.3.2   Classes disponibles</a></h3>
395 <p>Pour les dialogues avec l'utilisateur, il est possible d'utiliser n'importe
396 quelle classe fournie par Qt (<a class="reference" href="http://doc.trolltech.com/3.2/classes.html">http://doc.trolltech.com/3.2/classes.html</a>). 
397 Cependant, lorque c'eset possible, il est préférable d'utiliser les fonctions
398 QAD (Qt Application Desktop), définies dans KERNEL_SRC/src/SALOMEGUI, qui
399 encapsulent les fonctions Qt correspondantes et gèrent mieux les
400 communications avec l'IAPP. Ainsi, dans HELLOGUI, nous utilisons la classe
401 QAD_MessageBox en lieu et place de la classe Qt QMessageBox.</p>
402 </div>
403 <div class="section" id="gestion-du-multi-linguisme">
404 <h3><a class="toc-backref" href="#id17" name="gestion-du-multi-linguisme">7.3.3   Gestion du multi-linguisme</a></h3>
405 <p>Qt fournit un outil d'aide au support du multi-linguisme. Celui-ci est
406 repris dans salome. Le principe est simple : toutes les chaînes de caractères
407 utilisées pour les labels des menus et les dialogues avec l'utilisateur 
408 sont encapsulés dans des appels à la fonction Qt tr() (pour translate), qui
409 prend en argument un nom de label. Par exemple, pour demander à l'utilisateur
410 de rentrer un prénom, nous utilisons la fonction getText, où les deux premiers
411 arguments sont des labels encapsulés par tr():</p>
412 <pre class="literal-block">
413 myName = QInputDialog::getText( tr(&quot;QUE_HELLO_LABEL&quot;), tr(&quot;QUE_HELLO_NAME&quot;),
414                                 QLineEdit::Normal, QString::null, &amp;ok);
415 </pre>
416 <p>Le nom des label est préfixé à titre indicatif par trois lettres et un underscore. Les codes
417 suivants sont utilisés:</p>
418 <pre class="literal-block">
419 - MEN_ : label menu
420 - BUT_ : label bouton
421 - TOT_ : aide tooltip
422 - ERR_ : message d'erreur
423 - WRN_ : message d'alerte
424 - INF_ : message d'information
425 - QUE_ : question
426 - PRP_ : prompt dans la barre des status
427 </pre>
428 <p>La traduction des labels encapsulés par tr() est faite pour différents
429 langages cibles (par exemple français et anglais) dans des fichiers nommés &quot;&lt;nom_module&gt;_msg_&lt;langage&gt;.po&quot;. 
430 &lt;langage&gt; correspond au code du langage, on a choisi <strong>en</strong> pour l'anglais et
431 <strong>fr</strong> pour le français. Ce fichier doit contenir pour chaque clé sa
432 traduction, par exemple:</p>
433 <pre class="literal-block">
434 msgid &quot;HELLOGUI::INF_HELLO_BANNER&quot;
435 msgstr &quot;HELLO Information&quot;
436 </pre>
437 <p>Le squelette de ce fichier peut être généré par l'utilitaire Qt findtr:</p>
438 <pre class="literal-block">
439 findtr HELLOGUI.cxx &gt; HELLO_msg_en.po
440 </pre>
441 <p>puis éditer le fichier HELLO_msg_en.po pour remplir les traductions.
442 Ces fichiers sont ensuite compilés par l'utilitaire <strong>msg2qm</strong> pour générer
443 des binaires <em>.qm</em>. Pour cela, il faut remplir la cible LIB_MOC dans le
444 Makefile:</p>
445 <pre class="literal-block">
446 PO_FILES =  HELLO_msg_en.po HELLO_msg_fr.po
447 </pre>
448 <p>Pour l'utilisateur final, le choix du langage se fait au niveau de chaque
449 module dans le fichier ressources/config, en utilisant la commande:</p>
450 <pre class="literal-block">
451 langage=&lt;langage&gt;
452 </pre>
453 </div>
454 </div>
455 </div>
456 <div class="section" id="r-gles-syntaxiques-de-nommage">
457 <h1><a class="toc-backref" href="#id18" name="r-gles-syntaxiques-de-nommage">8   Règles syntaxiques de nommage</a></h1>
458 <p>Dans ce qui précède, nous avons utilisé un certain nombre de règles de
459 nommage. Le présent chapitre se propose de faire le point sur ces règles.
460 Celles-ci ne sont pas toutes obligatoires, mais simplifient la compréhension
461 si on les suit!</p>
462 <table class="table" frame="border" rules="all">
463 <colgroup>
464 <col width="21%" />
465 <col width="20%" />
466 <col width="17%" />
467 <col width="42%" />
468 </colgroup>
469 <thead valign="bottom">
470 <tr><th>Règle</th>
471 <th>Formalisme</th>
472 <th>Exemple HELLO</th>
473 <th>Commentaire</th>
474 </tr>
475 </thead>
476 <tbody valign="top">
477 <tr><td>Nom du module</td>
478 <td>&lt;Module&gt;</td>
479 <td>HELLO</td>
480 <td>C'est le nom qui figure dans le
481 catalogue des modules</td>
482 </tr>
483 <tr><td>Base CVS</td>
484 <td>&lt;Module&gt;</td>
485 <td>EXAMPLES</td>
486 <td>Si la base cvs contient plusieurs
487 modules, on prend un autre nom</td>
488 </tr>
489 <tr><td>Repertoire source</td>
490 <td>&lt;Module&gt;_SRC</td>
491 <td>HELLO1_SRC</td>
492 <td>L'indice 1 est utilisé car on prévoit
493 plusieurs version du module</td>
494 </tr>
495 <tr><td>Fichier idl</td>
496 <td>&lt;Module&gt;_Gen.idl</td>
497 <td>HELLO_Gen.idl</td>
498 <td>&nbsp;</td>
499 </tr>
500 <tr><td>Nom du module
501 CORBA</td>
502 <td>&lt;Module&gt;_ORB</td>
503 <td>HELLO_ORB</td>
504 <td>On évite d'utiliser le nom du module
505 (conflits)</td>
506 </tr>
507 <tr><td>Nom de
508 l'interface CORBA</td>
509 <td>&lt;Module&gt;_Gen</td>
510 <td>HELLO_Gen</td>
511 <td>La compilation de l'idl génère une
512 classe abstraite
513 POA_&lt;Module&gt;_ORB::&lt;Module&gt;_Gen</td>
514 </tr>
515 <tr><td>fichier source</td>
516 <td>&lt;Module&gt;.cxx</td>
517 <td>HELLO.cxx</td>
518 <td>Dans le répertoire /src/&lt;Module&gt;</td>
519 </tr>
520 <tr><td>Classe
521 d'implémentation</td>
522 <td>&lt;Module&gt;</td>
523 <td>HELLO</td>
524 <td>Cette classe hérite de
525 POA_HELLO_ORB::HELLO_Gen</td>
526 </tr>
527 <tr><td>Fonction
528 d'instanciation</td>
529 <td>&lt;Module&gt;_
530 Engine_factory</td>
531 <td>HELLO_Engine
532 factory</td>
533 <td>Cette fonction est appelée par
534 le FactoryServer de Salome</td>
535 </tr>
536 <tr><td>Catalogue des
537 modules</td>
538 <td>&lt;Module&gt;Catalog
539 .xml</td>
540 <td>HELLOCatalog
541 .xml</td>
542 <td>Dans /ressources</td>
543 </tr>
544 <tr><td>Nom de la
545 librairie C++</td>
546 <td>lib&lt;Module&gt;Engine</td>
547 <td>libHELLOEngine</td>
548 <td>Dans le répertoire /src/&lt;Module&gt;</td>
549 </tr>
550 <tr><td>Librairie C++
551 de l'IHM</td>
552 <td>lib&lt;Module&gt;GUI</td>
553 <td>libHELLOGUI</td>
554 <td>Dans le répertoire /src/&lt;Module&gt;GUI</td>
555 </tr>
556 <tr><td>Variable
557 d'environnement</td>
558 <td>&lt;Module&gt;_ROOT_DIR</td>
559 <td>HELLO_ROOT_DIR</td>
560 <td>&nbsp;</td>
561 </tr>
562 <tr><td><p class="last">...</p>
563 </td>
564 <td><p class="last">...</p>
565 </td>
566 <td><p class="last">...</p>
567 </td>
568 <td><p class="last">...</p>
569 </td>
570 </tr>
571 </tbody>
572 </table>
573 </div>
574 </div>
575 </body>
576 </html>