% vim: set textwidth=78 autoindent:

%\section{QGIS Coding Standards}
\section{Standards de Codage de QGIS}

% when the revision of a section has been finalized,
% comment out the following line:
% \updatedisclaimer

% The following chapters provide coding information for QGIS Version \CURRENT. 
% This document corresponds almost to a \LaTeX~ conversion of
% the CODING.t2t file coming with the QGIS sources from December, 16th 2008.
Le chapitre suivant fournie des informations de codage pour la version \CURRENT de QGIS.
Ce document correspond quasiment à une conversion en \LaTeX du fichier CODING.txt fournit 
avec les sources de QGIS du 16 décembre 2008.

% These standards should be followed by all QGIS developers. Current information 
% about QGIS Coding Standards are also available from wiki at:
Ces standards doivent être suivis par tous les développeurs de QGIS. Les informations actuelles
sur les standards de codage de QGIS sont également disponibles sur le wiki :

\url{http://wiki.qgis.org/qgiswiki/CodingGuidelines} \\
\url{http://wiki.qgis.org/qgiswiki/CodingStandards} \\
\url{http://wiki.qgis.org/qgiswiki/UsingSubversion} \\
\url{http://wiki.qgis.org/qgiswiki/DebuggingPlugins} \\
\url{http://wiki.qgis.org/qgiswiki/DevelopmentInBranches} \\
\url{http://wiki.qgis.org/qgiswiki/SubmittingPatchesAndSvnAccess} \\

\subsection{Classes}
% \subsubsection{Names}
\subsubsection{Noms}
% Class in QGIS begin with Qgs and are formed using mixed case. 
Les classes dans QGIS débutent avec Qgs et sont formées en utilisant une casse mixte.

\begin{verbatim}
Exemples :
	QgsPoint
	QgsMapCanvas
	QgsRasterLayer
\end{verbatim}

% \subsubsection{Members}
\subsubsection{Membres}
% Class member names begin with a lower case \textit{m} and are formed using mixed case.
Les noms des membres de classe débutent avec un \textit{m} en minuscule et sont formés de casses mixtes.

\begin{verbatim}
	mMapCanvas	
	mCurrentExtent
\end{verbatim}

% All class members should be private.
Tous les membres de classes doivent être privés.

% \textbf{Public class members are STRONGLY discouraged}
\textbf{Les membres publics de classes sont fortement déconseillés.}

% \subsubsection{Accessor Functions}
\subsubsection{Fonctions accesseurs}
% Class member values should be obtained through accesssor functions. The function should be named without a \textit{get} prefix. Accessor functions for the two private members above would be: 
Les membres des classes doivent être obtenus par une fonction accesseurs. La fonction doit être nommée avec un préfixe \textit{get}. les fonctions accesseurs pour deux membres privées doivent être :
\begin{verbatim}
	mapCanvas()
	currentExtent()
\end{verbatim}

% \subsubsection{Functions}
\subsubsection{Fonctions}
% Function names begin with a lowercase letter and are formed using mixed case. The function name should convey something about the purpose of the function.
Les noms de fonction doivent commencer par une lettre en minuscule et sont formés de casse mixte. Le nom de la fonction doit se rapporter à l'objectif de la fonction.

\begin{verbatim}
	updateMapExtent()
	setUserOptions()
\end{verbatim}

% \subsection{Qt Designer}
\subsection{Qt Designer}
% \subsubsection{Generated Classes}
\subsubsection{Classes générées}
% QGIS classes that are generated from Qt Designer (ui) files should have a \textit{Base} suffix. This identifies the class as a generated base class.
Les classes de QGIS qui sont générées à partir des fichiers de Qt Designer (ui) doivent avoir un suffixe \textit{Base}. Cela identifie la classe comme classe de base générée.

\begin{verbatim}
Exemples :
	QgsPluginMangerBase
	QgsUserOptionsBase
\end{verbatim}
% \subsubsection{Dialogs}
\subsubsection{Boîtes de dialogues}
% All dialogs should implement the following:
Toutes les boîtes de dialogue implémentent ce qui suit :
%  * Tooltip help for all toolbar icons and other relevant widgets
 * aide en tootlip pour toutes les icônes de la barre d'outils et autre widgets pertinents ;
%  * WhatsThis help for \textbf{all} widgets on the dialog
  * aide WhatsThis pour \textbf{tous} les widgets sur la boîte de dialogue ;
%  * An optional (though highly recommended) context sensitive \textit{Help} button that directs the user to the appropriate help page by launching their web browser
  * un bouton \textit{Help} fonction du contexte optionnel (bien que fortement recommandé) qui redirige l'utilisateur vers une page d'aide appropriée en lançant leur navigateur web.

% \subsection{C++ Files}
\subsection{Files C++}
% \subsubsection{Names}
\subsubsection{Noms}
% C++ implementation and header files should be have a .cpp and .h extension respectively.
% Filename should be all lowercase and, in the case of classes, match the class name.
Les fichiers d'implémentations C++ et d'en-tête doivent avoir respectivement une extension.cpp et .h. Les noms de fichier doivent être en minuscule et dans le cas des classes, correspondre au nom de la classe.

\begin{verbatim}
Exemple :
	Class QgsFeatureAttribute source files are 
		qgsfeatureattribute.cpp and qgsfeatureattribute.h
\end{verbatim}

% \subsubsection{Standard Header and License}
\subsubsection{En-tête standard et license}
% Each source file should contain a header section patterned after the following example:
Chaque fichier source doit contenir un section d'en-tête sur le modèle de cet exemple :

\begin{verbatim}
/***************************************************************************
    qgsfield.cpp - Describes a field in a layer or table
     --------------------------------------
    Date                 : 01-Jan-2004
    Copyright            : (C) 2004 by Gary E.Sherman
    Email                : sherman at mrcc.com
/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
\end{verbatim}

% \subsubsection{CVS Keyword}
\subsubsection{Mot-clé CVS}
% Each source file should contain the \$Id\$ keyword. This will be expanded by CVS to contain useful information about the file, revision, last committer, and date/time of last checkin.
Chaque fichier source doit contenir le mot-clé \$Id\$. Cela sera remplacé par CVS pour contenir des informations utiles sur le fichier, la révision, le dernier commiteur et la date et l'heure de la dernière récupération. 
% Place the keyword right after the standard header/license that is found at the top of each source file:
Placer le mot-clé directement après la licence/l'en-tête standard qui est trouvé en haut de chaque fichier source :
\begin{verbatim}
	/* $Id$ */
\end{verbatim}

% \subsection{Variable Names}
\subsection{Noms de variables}
% Variable names begin with a lower case letter and are formed using mixed case.
Les noms de variables débutent avec une minuscule et sont formés de casse mixte.
\begin{verbatim}
Exemples :
	mapCanvas
	currentExtent
\end{verbatim}
% \subsection{Enumerated Types}
\subsection{Types d'énumération}
% Enumerated types should be named in CamelCase with a leading capital e.g.:
Les types d'énumération doivent être nommés en CamelCase avec la première lettre en capital, par exemple :
\begin{verbatim}
    enum UnitType
    {
      Meters,
      Feet,
      Degrees,
      UnknownUnit
    } ;
\end{verbatim}

% Do not use generic type names that will conflict with other types. e.g. use "UnkownUnit" rather 
% than "Unknown"
N'utilisez pas de nom de type générique qui entrera en conflit avec d'autres types. Par exemple, utiliser ``UnkownUnit'' plutôt que ``Unknown''.

% \subsection{Global Constants}
\subsection{Constantes globales}
% Global constants should be written in upper case underscore separated e.g.:
Les constantes globales doivent être écrit en majuscule séparée par des symboles soulignement, par exemple :
\begin{verbatim}
const long GEOCRS_ID = 3344;
\end{verbatim}

% \subsection{Editing}
\subsection{Édition}
% Any text editor/IDE can be used to edit QGIS code, providing the following requirements are met.
N'importe quel éditeur/IDE peut être utilisé pour éditer le code de QGIS s'il fournit les besoins suivants :

% \subsubsection{Tabs}
\subsubsection{Tabulations}
% Set your editor to emulate tabs with spaces. Tab spacing should be set to 2 spaces.
Définissez votre éditeur pour simuler les tabulations avec des espaces. L'espace des tabulations doit être de 2 espaces.

% \subsubsection{Indentation}
\subsubsection{Indentation}
% Source code should be indented to improve readability. There is a .indent.pro file in the QGIS src directory that contains the switches to be used when indenting code using the GNU indent program. If you don't use GNU indent, you should emulate these settings.
Le code source doit être indenté pour améliorer la lisibilité. Il y a un fichier .ident.pro dans le répertoire src de QGIS qui contient la correspondance à utiliser pour indenter le code en utilisant le programme GNU indent. Si vous n'utilisez pas ce programme, vous devez simuler ces paramétrages.

% \subsubsection{Braces}
\subsubsection{Accolades}
% Braces should start on the line following the expression:
Les accolades débutent sur la ligne suivant l'expression :

\begin{verbatim}
	if(foo == 1)
	{
	  // faire quelque chose
	  ...
 	}else
	{
	  // faire quelque chose d'autre
	  ...
	}
\end{verbatim}

% \subsection{API Compatibility}
\subsection{Compatibilitie avec l'API}
% From QGIS 1.0 we will provide a stable, backwards compatible API. This will
% provide a stable basis for people to develop against, knowing their code will
% work against any of the 1.x QGIS releases (although recompiling may be
% required).Cleanups to the API should be done in a manner similar to the
% Trolltech developers e.g.
À partir de QGIS 1.0, nous fournissons une API stable et compatible arrière. Ceci fournira une base stable sur laquelle les personnes développeront, en sachant que leur code restera compatible avec les versions 1.x de QGIS (bien qu’une recompilation puisse être nécessaire). Le nettoyage de l'API sera effectué de la même manière que les développeurs de Trolltech, par exemple :

\begin{verbatim}
class Foo 
{
  public:
    /** This method will be deprecated, you are encouraged to use 
      doSomethingBetter() rather.
      @see doSomethingBetter()
     */
    bool doSomething();

    /** Does something a better way.
      @note This method was introduced in QGIS version 1.1
     */
    bool doSomethingBetter();

}
\end{verbatim}

% \subsection{Coding Style}
\subsection{Style de codage}
% Here are described some programming hints and tips that will hopefully reduce errors, development time, and maintenance.
Voici la description de quelques idées et astuces de programmation qui permettra de réduire les erreurs, le temps de développement et de maintenance.

% \subsubsection{Where-ever Possible Generalize Code}
\subsubsection{Généraliser le code quand c'est possible}

% If you are cut-n-pasting code, or otherwise writing the same thing more than once, consider consolidating the code 
% into a single function.
Si vous copiez collé du code ou du moins, recopiez la même portion de code, considérez la généralisation du code en une fonction.

% This will allow changes to be made in one location instead of in multiple places
Cela permettra de modifier en un seul endroit au lieu d'en plusieurs endroits.

\begin{itemize}
% \item help prevent code bloat
\item aide à prévenir l'hypertrophie du code ;
% \item make it more difficult for multiple copies to evolve differences over time, thus making it harder to understand and maintain for others
\item rend plus difficile l'évolution dans le temps de multiple copies de codes et donc complique la compréhension et le maintient pour les autres.
\end{itemize}

% \subsubsection{Prefer Having Constants First in Predicates}
\subsubsection{Préférer les constantes en premier dans les prédicats}
% Prefer to put constants first in predicates. 
Préférez le placement des constants en début dans les prédicats.

\begin{verbatim}
"0 == value" au lieu de "value == 0"
\end{verbatim}

% This will help prevent programmers from accidentally using "=" when they meant to use "==", which can introduce very subtle 
% logic bugs.  The compiler will generate an error if you accidentally use "=" instead of "==" for comparisons since constants 
% inherently cannot be assigned values.
Cela aidera à prévenir les utilisations accidentelles de ``='' au lieu d'utiliser ``=='' qui peut introduire des bugs subtils. Le compilateur rejettera une erreur si vous utilisez accidentellement ``='' au lieu de ``=='' pour la comparaison puisqu'on ne peut pas assigné une valeur aux constantes.

% \subsubsection{Whitespace Can Be Your Friend}
\subsubsection{Les espaces sont vos amis}
% Adding spaces between operators, statements, and functions makes it easier for humans to parse code.
Ajouter des espaces entre les opérateurs, commandes et fonctions permet de faciliter la lecture du code.

% Which is easier to read, this:
Lequel est plus facile à lire, ceci :

\begin{verbatim}
if (!a&&b)
\end{verbatim}

% or this:
ou ceci :

\begin{verbatim}
if ( ! a && b )
\end{verbatim}

% \subsubsection{Add Trailing Identifying Comments}
\subsubsection{Ajouter des commantaires}
% Adding comments at the end of function, struct and class implementations makes it easier to find them later.
Ajouter des commentaires à la fin des fonctions, des implémentations des structures et des classes, il est plus facile de les retrouver plus tard.

% Consider that you're at the bottom of a source file and need to find a very long function -- without these kinds of trailing 
% comments you will have to page up past the body of the function to find its name.  Of course this is ok if you wanted to find 
% the beginning of the function; but what if you were interested at code near its end?  You'd have to page up and then back down 
% again to the desired part.
Considérez que vous êtes au fond d'un fichier source et que vous devez retrouver une fonction très longue - sans ce type de commentaires, vous devrez remonter dans le code pour retrouver son nom. Bien sûr, cela est ok si vous voulez trouver le début de la fonction, mais si vous vous intéressez au code près de la fin ? Vous devriez descendre puis parvenir à nouveau à la partie désirée.

% E.g.,
Par exemple,

\begin{verbatim}
void foo::bar()
{ 
    // ... imaginez beacuoup de code ici
 } // foo::bar()
\end{verbatim}

% \subsubsection{Use Braces Even for Single Line Statements}
\subsubsection{Utiliser des accolades même pour des commandes sur une seule ligne}
% Using braces for code in if/then blocks or similar code structures even for single line statements means that adding another 
% statement is less likely to generate broken code.
En utilisant des accolades pour le code dans les blocs if/then ou des structures similaires, même pour une seule ligne de code signifie que l'ajout d'une autre déclaration est moins susceptible de générer un code cassé.

% Consider:
Considérez :

\begin{verbatim}
  if (foo)
    bar();
 else
    baz();
\end{verbatim}

% Adding code after bar() or baz() without adding enclosing braces would create broken code.  Though most programmers would 
% naturally do that, some may forget to do so in haste.
Ajouter du code après bar() ou baz() sans ajouter d'accolades autour créera un code cassé. Bien que la plupart des programmeurs le feront naturellement, certains pourraient oublier.

% So, prefer this:
Ainsi, préférez ceci :

\begin{verbatim}
 if (foo)
 {
   bar();
 }
 else
 { 
    baz();
 } 
\end{verbatim}

% \subsubsection{Book recommendations}
\subsubsection{Recommendations de livres}

Effective C++ \url{http://www.awprofessional.com/title/0321334876} \\
More Effective C++ \url{http://www.awprofessional.com/bookstore/product.asp?isbn=020163371X&rl=1} \\
Effective STL \url{http://www.awprofessional.com/title/0201749629} \\
Design Patterns \url{http://www.awprofessional.com/title/0201634988}

% You should also really read this article from Qt Quarterly on designing Qt style \url{http://doc.trolltech.com/qq/qq13-apis.html}
Vous devez aussi vraiment lire cette article de la publication trimestrielle de Qt \url{http://doc.trolltech.com/qq/qq13-apis.html}
%%\section{SVN Access}
\section{Accès SVN}
%This page describes how to get started using the QGIS Subversion repository
Cette page explicite la procédure de démarrage exploitant le répertoire QGIS Subversion.
%\subsection{Accessing the Repository}
\subsection{Accéder au répertoire}
%To check out QGIS HEAD:
Pour vérifier le QGIS HEAD :
%\begin{verbatim}
%  svn --username [your user name] co https://svn.qgis.org/repos/qgis/trunk/qgis
%\end{verbatim}
\begin{verbatim}
  svn --username [votre nom d'utilisateur] co https://svn.qgis.org/repos/qgis/trunk/qgis
\end{verbatim}

%\subsection{Anonymous Access}
\subsection{Accès anonyme}

%You can use the following commands to perform an anonymous checkout from the QGIS Subversion repository. 
%Note we recommend checking out the trunk (unless you are a developer or really HAVE to have the latest 
%changes and dont mind lots of crashing!).
Vous pouvez utiliser les commandes suivantes pour fournir un accès anonyme au dossier QGIS Subversion. Notez que nous recommandons de contrôler les troncs (sauf si vous êtes un développeur ou que vous avez vraiment BESOIN d'avoir les dernières modifications et que vous ne craignez pas de nombreux crashs).

%You must have a subversion client installed prior to checking out the code. See the Subversion website 
%for more information. The Links page contains a good selection of SVN clients for various platforms.
Vous devez avoir une sous-version client installée avant de saisir le code. Regardez sur le site internet dédié aux Subversions pour plus d'information. La page des liens contient une sélection de clients SVN pour de nombreuses plateformes.

%To check out a branch
Pour vérifier une branche :

\begin{verbatim}
  svn co https://svn.qgis.org/repos/qgis/branches/<branch name>
\end{verbatim}

%To check out SVN stable trunk:
Pour vérifier le tronc :

\begin{verbatim}
  svn co https://svn.qgis.org/repos/qgis/trunk/qgis qgis_unstable
\end{verbatim}

%/!$\backslash$ \textbf{Note:} If you are behind a proxy server, edit your \~{}/subversion/servers file to specify 
%your proxy settings first!
/!$\backslash$ \textbf{Note :} Si vous êtes derrière un serveur proxy, éditez votre configuration proxy en premier.

%/!$\backslash$ \textbf{Note:} In QGIS we keep our most stable code in trunk. Periodically we will tag a release 
%off trunk, and then continue stabilisation and selective incorporation of new features into trunk.
/!$\backslash$ \textbf{Note :} Dans QGIS, nous conservons notre code le plus stable dans le tronc. Nous mettons à régulièrement une version en dehors du tronc, et ensuite nous continuons à stabiliser et incorporer une sélection de nouvelles fonctionnalités  dans le tronc.

%See the INSTALL file in the source tree for specific instructions on building development versions. 
Veuillez regarder le fichier INSTALL à la racine de l'arbre pour les instructions spécifiques sur la construction et le développement des versions.

%\subsection{QGIS documentation sources}
\subsection{Documentation des sources de QGIS}

%If you're interested in checking out Quantum GIS documentation sources:
Si vous souhaitez étudier la documentation des sources de Quantum GIS :

\begin{verbatim}
  svn co https://svn.qgis.org/repos/qgis_docs/trunk qgis_docs
\end{verbatim}

%You can also take a look at DocumentationWritersCorner for more information.
Vous pouvez de même regarder la section \og{}DocumentationWritersCorner\fg{} pour plus d'information.

\subsection{Documentation}
%The repository is organized as follows:
Le répertoire est organisé comme suit :

\htmladdnormallink{http://wiki.qgis.org/images/repo.png}{http://wiki.qgis.org/images/repo.png}

%See the Subversion book \htmladdnormallink{http://svnbook.red-bean.com}{http://svnbook.red-bean.com} for information on becoming a SVN master.
Veuillez vous reporter au livre des Subversion \htmladdnormallink{http://svnbook.red-bean.com}{http://svnbook.red-bean.com} pour obtenir de plus ample information pour devenir un SVN master.


%\subsection{Development in branches}
\subsection{Développement des branches}

%\subsubsection{Purpose}
\subsubsection{Sujet}

%The complexity of the QGIS source code has increased considerably during the last years. Therefore it is hard 
%to anticipate the side effects that the addition of a feature will have. In the past, the QGIS project had very 
%long release cycles because it was a lot of work to reetablish the stability of the software system after new 
%features were added. To overcome these problems, QGIS switched to a development model where new features are 
%coded in svn branches first and merged to trunk (the main branch) when they are finished and stable. This section 
%describes the procedure for branching and merging in the QGIS project.
Le code de QGIS s'est considérablement complexifié ces dernières années. Ainsi, il est désormais dur d'anticiper les effets de bords que l'addition d'une fonctionnalité peut avoir. Dans le passé, les cycles développement des versions du projet QGIS furent très longs, car d'importants travaux pour ré-établir la stabilité du logiciel furent nécessaires après l'ajout de nouvelles composantes. Pour venir à bout de ces problèmes, QGIS choisit un modelé de développement dans lequel les nouvelles fonctionnalités sont codées dans des branches du SVN et fusionnées dans le tronc (la branche principale) quand elles sont finies et stables. Cette section décrit la procédure allant de la branche à la fusion dans le projet QGIS. 

%\subsubsection{Procedure}
\subsubsection{Procédure}
% * Initial announcement on mailing list
%Before starting, make an announcement on the developer mailing list to see if another developer is 
%already working on the same feature. Also contact the technical advisor of the project steering committee 
%(PSC). If the new feature requires any changes to the QGIS architecture, a request for comment (RFC) is needed. 
 * Annonce initiale dans la liste de discussion
 Avant de commencer, veuillez poster une annonce sur la liste de discussion des développeurs pour voir si un autre développeur n'est pas déjà en train de travailler sur la même fonctionnalité. Veuillez aussi contacter le responsable technique (technical advisor) du comité pilotage du projet (project steering committee --- PSC). Si la nouvelle fonctionnalité demande des changements dans l'architecture QGIS, une requête pour commentaire (request for comment --- RFC) est nécessaire.
 % * Create a branch
%Create a new svn branch for the development of the new feature (see UsingSubversion for the svn syntax). Now 
%you can start developing.
 * Créer une nouvelle branche
Créez une nouvelle branche dans le SVN correspondant à la nouvelle fonctionnalité (voir UsingSubversion pour la syntaxe SVN). Vous pouvez désormais commencer le développement. 
% * Merge from trunk regularly
%It is recommended to merge the changes in trunk to the branch on a regular basis. This makes it easier to merge 
%the branch back to trunk later.
 * Fusionner régulièrement à partir du tronc
Il est recommandé de fusionner périodiquement les changements effectués dans le tronc avec la branche. Ces fusions facilitent la fusion ultérieure de la branche avec le tronc.% * Documentation on wiki
%It is also recommended to document the intended changes and the current status of the work on a wiki page.
 * Documenter sur le wiki
Il est de même conseillé de documenter les changements prévus ainsi que l'état du travail en cours sur une page du wiki.
% * Testing before merging back to trunk
%When you are finished with the new feature and happy with the stability, make an announcement on the developer list. 
%Before merging back, the changes will be tested by developers and users. Binary packages (especially for OsX and Windows) 
%will be generated to also involve non-developers. In trac, a new Component will be opened to file tickets against. 
%Once there are no remaining issues left, the technical advisor of the PSC merges the changes into trunk.
 * Tester avant de fusionner dans la branche principale
Quand vous avez fini le développement de la nouvelle fonctionnalité et satisfait de sa stabilité, veuillez poster une annonce sur la liste de discussion des développeurs. Avant de fusionner avec le tronc, les changements doivent être testés par les développeurs et les utilisateurs. Les versions binaires (surtout pour OsX et Windows) seront générées pour impliquer aussi les non-développeurs. Dans le suivi (le trac), un nouveau composant sera ouvert contre le ticket du fichier. Dès qu'il n'y a plus de question en suspens, le responsable technique du PSC fusionne les changements dans le tronc.

%\subsubsection{Creating a branch}
\subsubsection{Créer une branche}
%We prefer that new feature developments happen out of trunk so that trunk remains in a 
%stable state. To create a branch use the following command:
Nous préférons que le développement d'une nouvelle fonctionnalité se fasse en dehors du tronc, donc que le tronc reste à un état stable. Pour créer une branche, veuillez utiliser les commandes suivantes :
\begin{verbatim}
svn copy https://svn.qgis.org/repos/qgis/trunk/qgis \
https://svn.qgis.org/repos/qgis/branches/qgis_newfeature
svn commit -m "New feature branch"
\end{verbatim}


%\subsubsection{Merge regularly from trunk to branch}
\subsubsection{Fusionner régulièrement le tronc dans la branche}
%When working in a branch you should regularly merge trunk into it so that your branch does not diverge more 
%than necessary. In the top level dir of your branch, first type \texttt{`svn info`} to determine the revision 
%numbers of your branch which will produce output something like this:
Quand vous travaillez dans une branche, vous devez régulièrement fusionner le tronc dans ladite branche afin que votre branche ne diverge pas plus que nécessaire. Dans le répertoire de plus haut niveau de votre branche, veuillez en premier taper \texttt{`svn info`} afin d'obtenir la version de révision de votre branche ce qui doit afficher quelque chose similaire à :

\begin{verbatim}
timlinux@timlinux-desktop:~/dev/cpp/qgis_raster_transparency_branch$ svn info
Caminho: .
URL: https://svn.qgis.org/repos/qgis/branches/raster_transparency_branch
Raiz do Repositorio: https://svn.qgis.org/repos/qgis
UUID do repositorio: c8812cc2-4d05-0410-92ff-de0c093fc19c
Revisao: 6546
Tipo de No: diretorio
Agendado: normal
Autor da Ultima Mudanca: timlinux
Revisao da Ultima Mudanca: 6495
Data da Ultima Mudanca: 2007-02-02 09:29:47 -0200 (Sex, 02 Fev 2007)
Propriedades da Ultima Mudanca: 2007-01-09 11:32:55 -0200 (Ter, 09 Jan 2007)
\end{verbatim}

%The second revision number shows the revision number of the start revision of your branch and the first the 
%current revision. You can do a dry run of the merge like this:
Le second indice de révisions indique la version d'origine de votre branche tandis que le premier vous donne la version en cours. Vous pouvez lancer une simulation de fusion comme suit :

\begin{verbatim}
svn merge --dry-run -r 6495:6546 https://svn.qgis.org/repos/qgis/trunk/qgis
\end{verbatim}

%After you are happy with the changes that will be made do the merge for real like this:
Après être satisfait des changements à effectuer, vous pouvez lancer la véritable fusion comme suit : 
\begin{verbatim}
svn merge -r 6495:6546 https://svn.qgis.org/repos/qgis/trunk/qgis
svn commit -m "Merged upstream changes from trunk to my branch"
\end{verbatim}

%\subsection{Submitting Patches}
%There are a few guidelines that will help you to get your patches into QGIS easily, and help us 
%deal with the patches that are sent to use easily.
\subsection{Soumettre des correctifs}
Il existe quelques aides pouvant vous aider pour avoir aisément vos correctifs dans QGIS, et nous aider à gérer facilement les correctifs envoyés.

%\subsubsection{Patch file naming}
%If the patch is a fix for a specific bug, please name the file with the bug number in it e.g. 
%\textbf{bug777fix.diff}, and attach it to the original bug report in trac (\htmladdnormallink{https://trac.osgeo.org/qgis/}{https://trac.osgeo.org/qgis/}).
\subsubsection{Nommage des fichiers du correctif}
Si le correctif permet de résoudre un bug spécifique, veuillez nommer le fichier en intégrant le numéro du bug, e.g. 
\textbf{bug777fix.diff}, et attacher le fichier au rapport original du bug dans le trac (\htmladdnormallink{https://trac.osgeo.org/qgis/}{https://trac.osgeo.org/qgis/}).

%If the bug is an enhancement or new feature, its usually a good idea to create a ticket in 
%trac (\htmladdnormallink{https://trac.osgeo.org/qgis/}{https://trac.osgeo.org/qgis/}) first and then attach you 
Si le bug est une nouvelle fonctionnalité ou une amélioration, il est classiquement de bon goût de créer en premier lieu un ticket dans le trac (\htmladdnormallink{https://trac.osgeo.org/qgis/}{https://trac.osgeo.org/qgis/}) et ensuite d'attacher votre correctif.

%\subsubsection{Create your patch in the top level QGIS source dir}
%This makes it easier for us to apply the patches since we don't need to navigate to a specific 
%place in the source tree to apply the patch. Also when I receive patches I usually evaluate them 
%using kompare, and having the patch from the top level dir makes this much easier. Below is an 
%example of you you can include multiple changed files into your patch from the top level directory:
\subsubsection{Créer votre correctif dans le dossier de plus haut niveau des sources de QGIS}
%This makes it easier for us to apply the patches since we don't need to navigate to a specific 
%place in the source tree to apply the patch. Also when I receive patches I usually evaluate them 
%using kompare, and having the patch from the top level dir makes this much easier. Below is an 
%example of you you can include multiple changed files into your patch from the top level directory:
Ainsi, il est plus facile pour nous d'appliquer les correctifs puisque nous n'avons pas besoin de nous placer dans des répertoires spécifiques dans l'arbre des sources pour appliquer les correctifs. De plus, quand je reçois des correctifs, j'ai l'habitude de les évaluer en utilisant kompare ; placer le correctif dans le dossier de plus haut niveau facilite grandement cette exploitation. Vous trouverez ci-dessous un exemple vous permettant d'inclure les fichiers du correctif à partir du dossier de plus haut niveau :

\begin{verbatim}
cd qgis
svn diff src/ui/somefile.ui src/app/somefile2.cpp > bug872fix.diff
\end{verbatim}

%\subsubsection{Including non version controlled files in your patch}
%If your improvements include new files that don't yet exist in the repository, you should indicate 
%to svn that they need to be added before generating your patch e.g.
\subsubsection{Inclure une version non controllée des fichiers dans votre correctif}
Si vos corrections contiennent de nouveaux fichiers encore non existants dans le répertoire, vous devez indiquer dans le svn que ces fichiers doivent être ajoutés avant de générer votre correctif, p. ex.

\begin{verbatim}
cd qgis
svn add src/lib/somenewfile.cpp
svn diff > bug7887fix.diff
\end{verbatim}

%\subsubsection{Getting your patch noticed}
%QGIS developers are busy folk. We do scan the incoming patches on bug reports but sometimes we miss things. 
%Don't be offended or alarmed. Try to identify a developer to help you - using the ["Project Organigram"] and 
%contact them asking them if they can look at your patch. If you dont get any response, you can escalate your 
%query to one of the Project Steering Committee members (contact details also available on the ["Project Organigram"]).
\subsubsection{Obtenir une notification de votre correctif}
Les développeurs de QGIS sont très occupés. Nous scannons les correctifs des bugs rapportés arrivant, mais il peut nous arriver d'en oublier. N'en soyez pas offensé ou alarmé. Tentez d'identifier des développeurs pour vous aider, en utilisant le ["Project Organigram"], et contacter les pour leur demander s’ils peuvent regarder votre correctif. Si vous n'obtenez aucune réponse, vous pouvez faire remonter votre requête aux membres du Project Steering Committee dont les contacts sont disponibles sur le ["Project Organigram"].

%\subsubsection{Due Diligence}
%QGIS is licensed under the GPL. You should make every effort to ensure you only submit patches which are 
%unencumbered by conflicting intellectual property rights. Also do not submit code that you are not happy to 
%have made available under the GPL.
\subsubsection{Diligence des droits}
QGIS est sous licence GPL. Vous devez faire tous les efforts nécessaires pour vous assurer que vous soumettez uniquement des correctifs qui ne peuvent être en conflit avec les droits à la propriété intellectuelle. Ainsi, veuillez ne pas soumettre du code pour lequel la disponibilité sous GPL ne vous satisferez pas.

%\subsection{Obtaining SVN Write Access}
%Write access to QGIS source tree is by invitation. Typically when a person submits several (there is no fixed 
%number here) substantial patches that demonstrate basic competance and understanding of C++ and QGIS coding 
%conventions, one of the PSC members or other existing developers can nominate that person to the PSC for granting 
%of write access. The nominator should give a basic promotional paragraph of why they think that person should gain 
%write access. In some cases we will grant write access to non C++ developers e.g. for translators and documentors. 
%In these cases, the person should still have demonstrated ability to submit patches and should ideally have submtted 
%several substantial patches that demonstrate their understanding of modifying the code base without breaking things, etc.
\subsection{Obtenir les droits en écriture sur le SVN}
Les droits en écriture sur les sources de QGIS s'obtiennent sur invitation. Typiquement, quand une personne soumet plusieurs (il n'y a pas de nombre fixé) correctifs substantiels qui démontrent une base de compétence et de compréhension du C++ et des conventions de code dans QGIS, un membre du PSC ou d'autres développeurs peuvent proposer cette personne au PSC pour l'obtention des droits en écriture. La personne présentant le candidat doit fournir une courte présentation motivant le choix de la personne. Dans certains cas, nous donnons les droits d'écriture à des personnes ne développant pas en C++ à l'instar des traducteurs et des documentalistes. Dans ces cas, la personne doit quand même démontrer sa capacité à soumettre des correctifs et doit dans l'idéal avoir soumis des correctifs substantiels démontrant sa compréhension des modifications du code de base sans perturbations.

%\subsubsection{Procedure once you have access}
\subsubsection{Procédure quand vous avez les droits en écriture}
%Checkout the sources:
Vérifiez les sources :

\begin{verbatim}
svn co https://svn.qgis.org/repos/qgis/trunk/qgis qgis
\end{verbatim}

%Build the sources (see INSTALL document for proper detailed instructions)
Compilez les sources (voir le document INSTALL pour les instructions détaillées)

\begin{verbatim}
cd qgis
mkdir build
ccmake ..    (set your preferred options)
make
make install  (maybe you need to do with sudo / root perms)
\end{verbatim}

%Make your edits
Faites vos éditions

\begin{verbatim}
cd ..
\end{verbatim}

%Make your changes in sources. Always check that everything compiles before making any commits.
%Try to be aware of possible breakages your commits may cause for people building on other 
%platforms and with older / newer versions of libraries.
Faites vos corrections dans les sources. Il faut toujours vérifier que tout compile avant de faire quoi que ce soit. Tâchez de vérifier les possibles perturbations que vos modifications peuvent causer aux personnes compilant sur d'autres plateformes ou avec des versions plus anciennes ou récentes des bibliothèques.

%Add files (if you added any new files). The svn status command can be used to quickly see 
%if you have added new files.
Ajoutez les fichiers (si vous avez ajouté de nouveaux fichiers). La commande pour le statut du svn peut être utilisée pour voir rapidement si vous avez ajouté de nouveaux fichiers.

\begin{verbatim}
svn status src/pluguns/grass/modules
\end{verbatim}

%Files listed with ? in front are not in SVN and possibly need to be added by you:
Les fichiers listés avec ? au début ne sont pas dans le SVN et il possible qu'il soit nécessaire qu'ils soient ajoutés par vous :

\begin{verbatim}
svn add src/pluguns/grass/modules/foo.xml
\end{verbatim}

%Commit your changes
Réalisez vos changements

\begin{verbatim}
svn commit src/pluguns/grass/modules/foo.xml
\end{verbatim}

%Your editor (as defined in \$EDITOR environment variable) will appear and you should make a
% comment at the top of the file (above the area that says 'dont change this'. Put a 
%descriptive comment and rather do several small commits if the changes across a number of 
%files are unrelated. Conversely we prefer you to group related changes into a single commit.
Votre éditeur (celui défini dans la variable d'environnement \$EDITOR) apparaitra et vous devrez faire un commentaire en haut du fichier (au-dessus de la zone disant 'dont change this'). Donnez un commentaire descriptif de votre correction et faire aussi des commentaires courts au travers des fichiers non reliés. Nous préférons que vous groupiez vos commentaires relatifs à vos modifications dans un unique commentaire.

%Save and close in your editor. The first time you do this, you should be prompted to 
%put in your username and password. Just use the same ones as your trac account.
Sauvez et fermez votre éditeur. La première fois que vous le faites, vous devez être invité à saisir votre nom d'utilisateur et votre mot de passe. Utilisez les mêmes que ceux de votre compte trac.

% \section{Unit Testing}
% As of November 2007 we require all new features going into trunk to be accompanied with 
% a unit test. Initially we have limited this requirement to qgis\_core, and we will extend 
% this requirement to other parts of the code base once people are familiar with the 
% procedures for unit testing explained in the sections that follow.
\section{Les Tests unitaires}
Depuis novembre 2007, nous exigeons que toutes les nouvelles fonctionnalités à intégrer à la branche principale de développement soient accompagnées d'un test unitaire. Cette exigence était initialement limitée à qgis\_core, nous l'étendrons à d'autres parties du code dès que les gens seront plus familiers avec les procédures décrites dans le reste de cette section.

% \subsection{The QGIS testing framework  - an overview}
% Unit testing is carried out using a combination of QTestLib (the Qt testing library) and 
% CTest (a framework for compiling and running tests as part of the CMake build process). 
% Lets take an overview of the process before I delve into the details:
\subsection{L'environnement de test de QGIS - un aperçu}
Les tests unitaires sont véhiculés par une combinaison de QTestLib (la bibliothèque de test de Qt) et de CTest (un environnement de compilation et d'exécution de tests faisant partie de CMake). 
Prenons un aperçu de ce processus avant de rentrer dans les détails :

% \begin{itemize}
% \item \textbf{There is some code you want to test}, e.g. a class or function. Extreme programming 
%    advocates suggest that the code should not even be written yet when you start 
%    building your tests, and then as you implement your code you can immediately validate 
%    each new functional part you add with your test. In practive you will probably 
%    need to write tests for pre-existing code in QGIS since we are starting with a testing 
%    framework well after much application logic has already been implemented.
% 
% \item \textbf{You create a unit test.} This happens under $<$QGIS Source Dir$>$/tests/src/core 
%    in the case of the core lib. The test is basically a client that creates an instance 
%    of a class and calls some methods on that class. It will check the return from each 
%    method to make sure it matches the expected value. If any one of the calls fails,
%    the unit will fail.
% 
% \item \textbf{You include QtTestLib macros in your test class.} This macro is processed by 
%    the Qt meta object compiler (moc) and expands your test class into a runnable application. 
\begin{itemize}
\item \textbf{Ici se trouve le code à tester}, p. ex. une classe ou une fonction. Les partisans de l'Extreme Programming suggèrent que le code ne devrait pas être écrit avant d'avoir conçu les tests, ainsi vous pouvez valider votre code au fur et  à mesure de son implémentation. Dans la pratique, vous aurez probablement besoin d'écrire des tests pour du code pré-existant dans QGIS du fait que nous avons entrepris cet effort de test bien après avoir réalisé de nombreuses applications logiques.

\item \textbf{Vous créez un test unitaire.} Cela se produit dans $<$QGIS Source Dir$>$/tests/src/core pour le cas d'une bibliothèque principale. Le test est un client basique qui créé une instance d'une classe et appelle quelques méthodes de cette même classe. Il vérifie ce que retourne chaque méthode pour s'assurer que cela correspond bien au résultat attendu. Si l'un de ces appels échoue alors le test échoue également.

\item \textbf{Vous incluez une macro QtTestLib dans votre classe de test.} Cette macro est traitée par le compilateur de méta-objet de Qt (moc) et étend votre classe de test vers une application exécutable.

% \item \textbf{You add a section to the CMakeLists.txt} in your tests directory that will
%    build your test.
% 
% \item \textbf{You ensure you have ENABLE\_TESTING enabled in ccmake / cmakesetup.} This 
%    will ensure your tests actually get compiled when you type make.
% 
% \item \textbf{You optionally add test data to $<$QGIS Source Dir$>$/tests/testdata} if your 
%    test is data driven (e.g. needs to load a shapefile). These test data should be 
%    as small as possible and wherever possible you should use the existing datasets 
%    already there. Your tests should never modify this data in situ, but rather 
%    may a temporary copy somewhere if needed.
% 
% \item \textbf{You compile your sources and install.} Do this using normal make \&\& (sudo) 
%    make install procedure.
% 
% \item \textbf{You run your tests.} This is normally done simply by doing \textbf{make test} 
%  after the make install step, though I will explain other aproaches that offer more 
%  fine grained control over running tests.
% \end{itemize}
\item \textbf{Vous ajoutez une section à CMakeLists.txt} dans votre répertoire de tests qui construira votre test.

\item \textbf{Vous vous assurez d'avoir activé ENABLE\_TESTING dans ccmake / cmakesetup.} Cela permet de garantir que vos tests seront bien compilés lorsque vous taperez make.

\item \textbf{Vous pouvez ajoutez les données du test dans $<$QGIS Source Dir$>$/tests/testdata} si votre test nécessite des données (p. ex. nécessité de charger un shapefile). Ces données doivent être aussi légères que possible et quand c'est possible, réutiliser les données déjà présentes. Vos tests ne doivent jamais modifier les données en place mais plutôt une copie temporaire.

\item \textbf{Vous compilez vos sources et installez.} Faites-le avec une procédure normale de make \&\& (sudo) make install.

\item \textbf{Vous exécutez vos tests.} C'est normalement effectué par \textbf{make test} après l'étape make install, je vous expliquerais d'autres approches qui offrent plus de contrôles sur l'exécution.
\end{itemize}

% Right with that overview in mind, I will delve into a bit of detail. I've already 
% done much of the configuration for you in CMake and other places in the source tree 
% so all you need to do are the easy bits - writing unit tests!
Avec cet aperçu en tête, je vais vous expliquer plus en détail avec une configuration déjà préparée pour CMake et d'autres parties des sources de manière à ce que vous n'ayez qu'à faire les choses les plus simples - écrire des tests unitaires !

% \subsection{Creating a unit test}
% Creating a unit test is easy - typically you will do this by just creating a 
% single .cpp file (not .h file is used) and implement all your test methods as
% public methods that return void. I'll use a simple test class for QgsRasterLayer 
% throughout the section that follows to illustrate. By convention we will name our 
% test with the same name as the class they are testing but prefixed with 'Test'.
% So our test implementation goes in a file called testqgsrasterlayer.cpp and 
% the class itself will be TestQgsRasterLayer. First we add our standard copyright 
% banner:
\subsection{Créer un test unitaire}
Créer un test unitaire est simple - vous allez généralement le faire en créant un seul fichier .cpp (aucun .h n'est utilisé) et implémenter vos méthodes de test en tant que méthodes publiques qui ne retourneront rien. Pour illustrer ce point, je vais utiliser une classe de test pour QgsRasterLayer. Par convention, nous allons appeler ce test avec le même nom que la classe qui va être testé, mais en rajoutant le préfixe 'test'. Notre exemple sera donc un fichier testqgsrasterlayer.cpp et une classe TestQgsRasterLayer. Il faut d'abord rajouter un en-tête précisant la licence et l'auteur :

\newpage

\begin{verbatim}
/***************************************************************************
     testqgsvectorfilewriter.cpp
     --------------------------------------
    Date                 : Frida  Nov 23  2007
    Copyright            : (C) 2007 by Tim Sutton
    Email                : tim@linfiniti.com
 ***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
\end{verbatim}

% Next we use start our includes needed for the tests we plan to run. There is 
% one special include all tests should have:
Ensuite nous allons débuter par les inclusions (includes) nécessaires aux tests que nous voulons faire.Next we use start our includes needed for the tests we plan to run. Il y a une spéciale que tous les tests vont avoir:

\begin{verbatim}
#include <QtTest>
\end{verbatim}

% Beyond that you just continue implementing your class as per normal, pulling 
% in whatever headers you may need:
A par ça, vous pouvez écrire vos classes comme d'habitude, en utilisant n'importe quel en-tête (header) que vous voulez:

\begin{verbatim}
//Qt includes...
#include <QObject>
#include <QString>
#include <QObject>
#include <QApplication>
#include <QFileInfo>
#include <QDir>

//qgis includes...
#include <qgsrasterlayer.h> 
#include <qgsrasterbandstats.h> 
#include <qgsapplication.h>
\end{verbatim}

% Since we are combining both class declaration and implementation in a single 
% file the class declaration comes next. We start with our doxygen documentation. 
% Every test case should be properly documented. We use the doxygen \textbf{ingroup} 
% directive so that all the UnitTests appear as a module in the generated 
% Doxygen documentation. After that comes a short description of the unit test:
Puisque nous combinons la déclaration et l'implémentation de classe dans un unique fichier, la déclaration vient ensuite. On débute avec la documentation doxygen. Chaque test doit être proprement documenté, nous utilisons la directive Doxygen \textbf{ingroup} pour que l'ensemble des tests unitaires (UnitTests) apparaisse comme un module dans la documentation Doxygen générée. C'est suivi d'une courte description du test:

\begin{verbatim}
/** \ingroup UnitTests
 * This is a unit test for the QgsRasterLayer class.
 */
\end{verbatim}

% The class \textbf{must} inherit from QObject and include the Q\_OBJECT macro.
La classe \textbf{doit} hériter de QObject et inclure la macro Q\_OBJECT.

\begin{verbatim}
class TestQgsRasterLayer: public QObject
{
  Q_OBJECT;
\end{verbatim}
% All our test methods are implemented as \textbf{private slots}. The QtTest framework 
% will sequentially call each private slot method in the test class. There are 
% four 'special' methods which if implemented will be called at the start of 
% the unit test (\textbf{initTestCase}), at the end of the unit test (\textbf{cleanupTestCase}). 
% Before each test method is called, the \textbf{init()} method will be called and 
% after each test method is called the \textbf{cleanup()} method is called. These 
% methods are handy in that they allow you to allocate and cleanup resources 
% prior to running each test, and the test unit as a whole.
Toutes nos méthodes sont conçues comme des \textbf{slots privés}. L'environnement QtTest appellera séquentiellement chacun des slots privés de la classe de test. Il y a quatre méthodes 'spéciales' qui si utilisées seront appelées au début de chaque test unitaire (\textbf{initTestCase}),et à leur fin (\textbf{cleanupTestCase}).  Avant que chaque méthode soit appelée, la méthode \textbf{init()} sera appelée et après ce sera la méthode  \textbf{cleanup()}. Ces méthodes sont pratiques, car elles vous permettent d'allouer et de nettoyer les ressources avant d'exécuter chaque test.

\begin{verbatim}
private slots:
    // will be called before the first testfunction is executed.
    void initTestCase();
    // will be called after the last testfunction was executed.
    void cleanupTestCase(){};
    // will be called before each testfunction is executed.
    void init(){};
    // will be called after every testfunction.
    void cleanup();
\end{verbatim}

% Then come your test methods, all of which should take \textbf{no parameters} and 
% should \textbf{return void}. The methods will be called in order of declaration.
% I am implementing two methods here which illustrates to types of testing. In 
% the first case I want to generally test the various parts of the class are 
% working, I can use a \textbf{functional testing} approach. Once again, extreme 
% programmers would advocate writing these tests \textbf{before} implementing the 
% class. Then as you work your way through your class implementation you 
% iteratively run your unit tests. More and more test functions should complete 
% sucessfully as your class implementation work progresses, and when the whole 
% unit test passes, your new class is done and is now complete with a repeatable 
% way to validate it.
Ensuite viennent vos méthodes de test, toutes doivent être \textbf{sans paramètres} et ne \textbf{rien retourner}. Elles sont appelées dans l'ordre de déclaration. Voici deux exemples, dans le premier cas je veux tester si les diverses parties de la classe fonctionnent, je peux utilise une approche de \textbf{test fonctionnel}. Une fois encore, certains sont partisans d'écrire ces tests \textbf{avant} de créer la classe puis de concevoir la classe en exécutant de façon itérative votre test unitaire. De plus en plus de fonctions de test devraient réussir au long de l'écriture de la classe et quand le test entier réussit votre nouvelle classe est complète avec un test réutilisable pour la valider.
% Typically your unit tests would only cover the \textbf{public} API of your 
% class, and normally you do not need to write tests for accessors and mutators.
% If it should happen that an acccessor or mutator is not working as expected 
% you would normally implement a \textbf{regression} test to check for this (see 
% lower down).
Habituellement, votre test unitaire ne devrait couvrir seulement l'API \textbf{publique}, vous ne devriez pas avoir à écrire de tests pour un accessoire ou un mutator. Si l'un d'eux ne fonctionne pas comme prévu, vous devrez créer un test de \textbf{régression} pour le vérifier.

\begin{verbatim}
    //
    // Functional Testing
    //
    
    /** Check if a raster is valid. */
    void isValid();

    // more functional tests here ...
\end{verbatim}

% Next we implement our \textbf{regression tests}. Regression tests should be 
% implemented to replicate the conditions of a particular bug. For example 
% I recently received a report by email that the cell count by rasters was 
% off by 1, throwing off all the statistics for the raster bands. I opened 
% a bug (ticket \#832) and then created a regression test that replicated 
% the bug using a small test dataset (a 10x10 raster). Then I ran the test 
% and ran it, verifying that it did indeed fail (the cell count was 99 
% instead of 100). Then I went to fix the bug and reran the unit test and 
% the regression test passed. I committed the regression test along with 
% the bug fix. Now if anybody breakes this in the source code again in the 
% future, we can immediatly identify that the code has regressed. Better 
% yet before committing any changes in the future, running our tests will 
% ensure our changes dont have unexpected side effects - like breaking 
% existing functionality.
Maintenant nous créons nos \textbf{tests de régression}, ils doivent répliquer les conditions d'un bug particulier . Par exemple, j'ai récemment reçu un rapport de bug par email sur le fait que le compte de cellules d'un raster était décalé de 1, faussant toutes les statistiques pour les bandes de rasters/ J'ai ouvert un rapport de bug (ticket \#832) et créé un test de régression qui répliquait le bug en utilisant un petit raster de 10x10. Puis j'ai exécuté le test à plusieurs reprises, en vérifiant qu'il échouait bien (le compte des cellules était de 99 au lieu de 100). J'ai corrigé ce bug et relancé le test avec succès. J'ai joint ce test à la correction pour s'assurer que si jamais ce bug devait se présenter de nouveau dans le code source nous pourrions l'identifier immédiatement. Encore mieux, en exécutant ce test avant chaque changement nous nous assurons qu'ils n'auront pas d'effets indésirables - comme briser une fonctionnalité existante.

% There is one more benifit to regression tests - they can save you time. 
% If you ever fixed a bug that involved making changes to the source, 
% and then running the application and performing a series of convoluted 
% steps to replicate the issue, it will be immediately apparent that 
% simply implementing your regression test \textbf{before} fixing the bug 
% will let you automate the testing for bug resolution in an efficient 
% manner.
Il y a un autre bénéfice à  ces tests de régression - ils peuvent vous faire gagner du temps. Si vous fixez un bug nécessitant un changement dans les sources puis lancez une série de vérifications complexes dans l'application pour vous assurer de sa résolution, il vous sera vite évident que l'écriture de ce test de régression \textbf{avant} de fixer le bug vous permet d'automatiser le test de manière efficace.

% To implement your regression test, you should follow the naming 
% convention of regression$<$TicketID$>$ for your test functions. If no 
% trac ticket exists for the regression, you should create one first. 
% Using this approach allows the person running a failed regression 
% test easily go and find out more information.
Pour créer votre test de régression, vous pouvez suivre la convention de nommage regression$<$TicketID$>$ pour vos fonctions. Si aucun ticket de suivi n’existe pour cette régression, vous devrez en créer un. Cette approche permet à une personne constatant l'échec d'un test de régression d'obtenir plus d'informations.

\begin{verbatim}
    //
    // Regression Testing
    //
    
    /** This is our second test case...to check if a raster
     reports its dimensions properly. It is a regression test 
     for ticket #832 which was fixed with change r7650. 
     */
    void regression832(); 
  
    // more regression tests go here ...
\end{verbatim}

% Finally in our test class declaration you can declare privately 
% any data members and helper methods your unit test may need. In our 
% case I will declare a QgsRasterLayer * which can be used by any 
% of our test methods. The raster layer will be created in the 
% initTestCase() function which is run before any other tests, and then
% destroyed using cleanupTestCase() which is run after all tests. By 
% declaring helper methods (which may be called by various test 
% functions) privately, you can ensure that they wont be automatically 
% run by the QTest executeable that is created when we compile our test.
Finalement dans notre déclaration de classe de test, vous allez déclarer de manière privée toutes les données chiffrées et les méthodes que votre test pourrait nécessiter. Dans notre cas, je vais déclarer QgsRasterLayer * qui peut être utilisé par chacune des méthodes de test. La couche raster sera créer par la fonction initTestCase() puis détruire par cleanupTestCase(). En déclarant les méthodes assistantes (qui peuvent être utilisé par différentes fonctions de test) de manière privée, vous pouvez vous assurer qu'elles ne seront pas automatiquement lancées par l'exécutable QTest créé quand nous compilons notre test.

\begin{verbatim}
  private:
    // Here we have any data structures that may need to 
    // be used in many test cases.
    QgsRasterLayer * mpLayer;
};

\end{verbatim}

% That ends our class declaration. The implementation is simply 
% inlined in the same file lower down. First our init and cleanup functions:
Cela clôt notre déclaration de classe. Cette implémentation est simplement placée plus bas dans le même fichier. D'abord nos fonctions init et cleanup:

\begin{verbatim}
void TestQgsRasterLayer::initTestCase()
{
  // init QGIS's paths - true means that all path will be inited from prefix
  QString qgisPath = QCoreApplication::applicationDirPath ();
  QgsApplication::setPrefixPath(qgisPath, TRUE);
#ifdef Q_OS_LINUX
  QgsApplication::setPkgDataPath(qgisPath + "/../share/qgis");
#endif
  //create some objects that will be used in all tests...

  std::cout << "Prefix  PATH: " << QgsApplication::prefixPath().toLocal8Bit().data() \
  << std::endl;
  std::cout << "Plugin  PATH: " << QgsApplication::pluginPath().toLocal8Bit().data() \
  << std::endl;
  std::cout << "PkgData PATH: " << QgsApplication::pkgDataPath().toLocal8Bit().data() \
  << std::endl;
  std::cout << "User DB PATH: " << QgsApplication::qgisUserDbFilePath().toLocal8Bit() \
  .data() << std::endl;

  //create a raster layer that will be used in all tests...
  QString myFileName (TEST_DATA_DIR); //defined in CmakeLists.txt
  myFileName = myFileName + QDir::separator() + "tenbytenraster.asc";
  QFileInfo myRasterFileInfo ( myFileName );
  mpLayer = new QgsRasterLayer ( myRasterFileInfo.filePath(),
            myRasterFileInfo.completeBaseName() );
}

void TestQgsRasterLayer::cleanupTestCase()
{
  delete mpLayer;
}

\end{verbatim}

% The above init function illustrates a couple of interesting things.
% 
%  1. I needed to manually set the QGIS application data path so that
%    resources such as srs.db can be found properly.
%  2. Secondly, this is a data driven test so we needed to provide a 
%    way to generically locate the 'tenbytenraster.asc file. This was 
%    achieved by using the compiler define \textbf{TEST\_DATA\_PATH}. The 
%    define is created in the CMakeLists.txt configuration file under 
%    $<$QGIS Source Root$>$/tests/CMakeLists.txt and is available to all 
%    QGIS unit tests. If you need test data for your test, commit it 
%    under $<$QGIS Source Root$>$/tests/testdata. You should only commit 
%    very small datasets here. If your test needs to modify the test 
%    data, it should make a copy of if first.
La fonction init ci-dessus démontre quelques points intéressants:

 1. J'ai eu besoin de mettre manuellement le chemin des données de QGIS pour que les ressources telles que srs.db soient correctement détectées.
 2. Deuxièmement, c'est un test recourant à des données donc nous devons fournir une façon de localiser le fichier tenbytenraster.asc. Cela est fait en définissant via le compilateur \textbf{TEST\_DATA\_PATH}. Cette définition est créé dans le fichier de configuration CMakeLists.txt dans $<$QGIS Source Root$>$/tests/CMakeLists.txt et est disponible pour tous les tests unitaires de QGIS. Si vous avez besoin d'autres fichiers, placez-les dans $<$QGIS Source Root$>$/tests/testdata. Efforcez-vous de réduire leur poids et surtout n'écrivez que sur des copies.

% Qt also provides some other interesting mechanisms for data driven 
% testing, so if you are interested to know more on the topic, consult 
% the Qt documentation.
Qt fourni également des mécanismes utiles pour les tests utilisant des données, si cela vous intéresse consultez la documentation.

% Next lets look at our functional test. The isValid() test simply 
% checks the raster layer was correctly loaded in the initTestCase. 
% QVERIFY is a Qt macro that you can use to evaluate a test condition. 
% There are a few other use macros Qt provide for use in your tests 
% including:
Maintenant, regardons notre test fonctionnel. Le test isValid() vérifie simplement si la couche raster est correctement chargée par initTestCase. QVERIFY est une macro Qt que vous pouvez utiliser pour évaluer une condition de test. Il y a d'autres macros que vous pouvez utiliser:

\begin{verbatim}
QCOMPARE ( actual, expected )
QEXPECT_FAIL ( dataIndex, comment, mode )
QFAIL ( message )
QFETCH ( type, name )
QSKIP ( description, mode )
QTEST ( actual, testElement )
QTEST_APPLESS_MAIN ( TestClass )
QTEST_MAIN ( TestClass )
QTEST_NOOP_MAIN ()
QVERIFY2 ( condition, message )
QVERIFY ( condition )
QWARN ( message ) 
\end{verbatim}

% Some of these macros are useful only when using the Qt framework 
% for data driven testing (see the Qt docs for more detail).
Certaines de ces macros ne sont utiles que si vous utilisez l'environnement Qt pour les tests recourant aux données (voir la documentation de Qt).

\begin{verbatim}
void TestQgsRasterLayer::isValid()
{
  QVERIFY ( mpLayer->isValid() );
}
\end{verbatim}

% Normally your functional tests would cover all the range of 
% functionality of your classes public API where feasible. With our 
% functional tests out the way, we can look at our regression test example.
% 
% Since the issue in bug \#832 is a misreported cell count, writing 
% our test if simply a matter of using QVERIFY to check that the 
% cell count meets the expected value:
Normalement vos tests fonctionnels devraient couvrir l'ensemble des fonctionnalités de vos classes. Ayant vu cela nous pouvons passer à notre exemple de test de régression.

Le problème \#832 est un compte de cellules mal effectué, l'écriture de notre test va simplement consisté à utiliser QVERIFY pour regarder si la valeur calculer est bien la valeur qui était prévue:

\begin{verbatim}
void TestQgsRasterLayer::regression832()
{
   QVERIFY ( mpLayer->getRasterXDim() == 10 );
   QVERIFY ( mpLayer->getRasterYDim() == 10 );
   // regression check for ticket #832
   // note getRasterBandStats call is base 1
   QVERIFY ( mpLayer->getRasterBandStats(1).elementCountInt == 100 );
}
\end{verbatim}

% With all the unit test functions implemented, there one final thing we 
% need to add to our test class:
Avec toutes les fonctions du test crées, il reste encore une chose à ajouter pour finaliser notre classe:

\begin{verbatim}
QTEST_MAIN(TestQgsRasterLayer)
#include "moc_testqgsrasterlayer.cxx"
\end{verbatim}

% The purpose of these two lines is to signal to Qt's moc that his is a 
% QtTest (it will generate a main method that in turn calls each test funtion.
% The last line is the include for the MOC generated sources. You should 
% replace 'testqgsrasterlayer' with the name of your class in lower case.
Le but de ces deux lignes est de signaler au moc de Qt que c'est un QTest (ça génèrera une méthode principale qui appellera chaque fonction du test). La dernière ligne est une inclusion pour les sources générées du MOC. Vous devez remplacer 'testqgsrasterlayer' par le nom de votre classe en caractère minuscule.

% \subsection{Adding your unit test to CMakeLists.txt}
% Adding your unit test to the build system is simply a matter of editing 
% the CMakeLists.txt in the test directory, cloning one of the existing 
% test blocks, and then search and replacing your test class name into it. 
% For example:
\subsection{Ajouter votre test unitaire à CMakeLists.txt}
Ajouter votre test unitaire au système de construction consiste juste à éditer le fichier CMakeLists.txt, copier un des blocs de test existants, puis de remplacer par votre nom de classe. Par exemple:

\begin{verbatim}
#
# QgsRasterLayer test
#
SET(qgis_rasterlayertest_SRCS testqgsrasterlayer.cpp)
SET(qgis_rasterlayertest_MOC_CPPS testqgsrasterlayer.cpp)
QT4_WRAP_CPP(qgis_rasterlayertest_MOC_SRCS ${qgis_rasterlayertest_MOC_CPPS})
ADD_CUSTOM_TARGET(qgis_rasterlayertestmoc ALL DEPENDS ${qgis_rasterlayertest_MOC_SRCS})
ADD_EXECUTABLE(qgis_rasterlayertest ${qgis_rasterlayertest_SRCS})
ADD_DEPENDENCIES(qgis_rasterlayertest qgis_rasterlayertestmoc)
TARGET_LINK_LIBRARIES(qgis_rasterlayertest ${QT_LIBRARIES} qgis_core)
INSTALL(TARGETS qgis_rasterlayertest RUNTIME DESTINATION ${QGIS_BIN_DIR})
ADD_TEST(qgis_rasterlayertest ${QGIS_BIN_DIR}/qgis_rasterlayertest)
\end{verbatim}
% I'll run through these lines briefly to explain what they do, but if 
% you are not interested, just clone the block, search and replace e.g.
Je vais parcourir brièvement ces lignes pour expliquer leur but, mais si cela ne vous intéresse pas, copiez le bloc et faites une recherche et puis un remplacement

\begin{verbatim}
:'<,'>s/rasterlayer/mynewtest/g
\end{verbatim}

% Lets look a little more in detail at the individual lines. First we 
% define the list of sources for our test. Since we have only one source file 
% (following the methodology I described above where class declaration and 
% definition are in the same file) its a simple statement:
Regardons en détail ces lignes. premièrement, nous définissons la liste des sources pour notre test et puisque nous n'avons qu'un fichier source (en ayant suivi la méthodologie décrite précédemment où la déclaration et la définition d'une classe sont dan s le même fichier), c'est une ligne simple:

\begin{verbatim}
SET(qgis_rasterlayertest_SRCS testqgsrasterlayer.cpp)
\end{verbatim}

% Since our test class needs to be run through the Qt meta object compiler (moc) 
% we need to provide a couple of lines to make that happen too:
Notre classe de test requiert d'être lancé via le compilateur méta-objet de Qt (MOC), nous devons fournir un couple de ligne pour le permettre:

\begin{verbatim}
SET(qgis_rasterlayertest_MOC_CPPS testqgsrasterlayer.cpp)
QT4_WRAP_CPP(qgis_rasterlayertest_MOC_SRCS ${qgis_rasterlayertest_MOC_CPPS})
ADD_CUSTOM_TARGET(qgis_rasterlayertestmoc ALL DEPENDS ${qgis_rasterlayertest_MOC_SRCS})
\end{verbatim}

% Next we tell cmake that it must make an executeable from the test class. 
% Remember in the previous section on the last line of the class implementation 
% I included the moc outputs directly into our test class, so that will 
% give it (among other things) a main method so the class can be 
% compiled as an executeable:
Ensuite, nous devons signifier à CMake qu'il doit produire un exécutable à partir de la classe de test. Souvenez-vous que dans la section précédente j'ai inclus à la dernière ligne le résultat du MOC directement dans notre classe, donc cela donnera (entre autres) une méthode principale qui permettra à la classe d'être compilée en tant qu'exécutable :

\begin{verbatim}
ADD_EXECUTABLE(qgis_rasterlayertest ${qgis_rasterlayertest_SRCS})
ADD_DEPENDENCIES(qgis_rasterlayertest qgis_rasterlayertestmoc)
\end{verbatim}

% Next we need to specify any library dependencies. At the moment classes 
% have been implemented with a catch-all QT\_LIBRARIES dependency, but I will 
% be working to replace that with the specific Qt libraries that each class 
% needs only. Of course you also need to link to the relevant qgis 
% libraries as required by your unit test.
A présent, nous allons spécifier les dépendances de bibliothèques. Pour l'instant les classes ont été réalisées avec une dépendance sur toutes les QT\_LIBRARIES, mais je vais réduire ce montant aux bibliothèques réellement utilisées par les classes. Bien entendu vous devez lier les bibliothèques qgis requises par votre test unitaire.

\begin{verbatim}
TARGET_LINK_LIBRARIES(qgis_rasterlayertest ${QT_LIBRARIES} qgis_core)
\end{verbatim}

% Next I tell cmake to the same place as the qgis binaries itself. This 
% is something I plan to remove in the future so that the tests can 
% run directly from inside the source tree.
Il faut maintenant dire à Cmake de se placer dans le même répertoire que les binaires de QGIS. C'est un point que je prévois de supprimer dans le futur pour que les tests puissent être lancés depuis l'arbre des sources.

\begin{verbatim}
INSTALL(TARGETS qgis_rasterlayertest RUNTIME DESTINATION ${QGIS_BIN_DIR})
\end{verbatim}

% Finally here is where the best magic happens - we register the class with 
% ctest. If you recall in the overview I gave in the beginning of this 
% section we are using both QtTest and CTest together. To recap, \textbf{QtTest} adds a 
% main method to your test unit and handles calling your test methods within 
% the class. It also provides some macros like QVERIFY that you can use as 
% to test for failure of the tests using conditions. The output from 
% a QtTest unit test is an executeable which you can run from the command line. 
% However when you have a suite of tests and you want to run each executeable 
% in turn, and better yet integrate running tests into the build process, 
% the \textbf{CTest} is what we use. The next line registers the unit test with 
% CMake / CTest.
Voici le moment magique - nous enregistrons la classe avec ctest. Si vous vous rappelez l'aperçu du début, nous utilisons conjointement QtTest et CTest. Pour récapituler, \textbf{QtTest} ajoute une méthode principale à notre test et gère les appels des méthodes internes à la classe. Il fournit aussi des macros comme QVERIFY pour vérifier les échecs à des conditions pré-établies. Le résultat est un exécutable que vous pouvez lancer depuis la console. Il est important quand vous avez une série de tests que vous voulez effectuer, ou mieux encore, que vous voulez intégrer au processus de compilation, d'utiliser \textbf{CTest}. La ligne suivante enregistre le test unitaire avec CMake / CTest.

\begin{verbatim}
ADD_TEST(qgis_rasterlayertest ${QGIS_BIN_DIR}/qgis_rasterlayertest)
\end{verbatim}

% The last thing I should add is that if your test requires optional 
% parts of the build process (e.g. Postgresql support, GSL libs, GRASS etc.), 
% you should take care to enclose you test block inside a IF () block 
% in the CMakeLists.txt file.
La dernière chose que j'ajouterai est que si votre test requiert des composants optionnels (p. ex. support de PostgreSQL, GRASS, etc.), vous devrez faire attention à circoncire votre bloc de test dans un IF () au sein du fichier CMakeLists.txt.

% \subsection{Building your unit test}
% To build the unit test you need only to make sure that ENABLE\_TESTS=true 
% in the cmake configuration. There are two ways to do this:
\subsection{Compiler votre test unitaire}
Pour construire votre test unitaire, vous devez seulement vous assurer que ENABLE\_TESTS=true dans la configuration de cmake; vous avez deux possibilités pour ce faire:
%  1. Run ccmake .. (cmakesetup .. under windows) and interactively set 
%  the ENABLE\_TESTS flag to ON.
%  1. Add a command line flag to cmake e.g. cmake -DENABLE\_TESTS=true ..
 1. Lancer ccmake .. (cmakesetup .. sous windows) et mettre ENABLE\_TESTS sur ON.
 2. Ajouter une ligne de commande à cmake e.g. cmake -DENABLE\_TESTS=true ..
% Other than that, just build QGIS as per normal and the tests should build too.
À part ça, compilez QGIS comme d'habitude et les tests devraient être compilés également.

% \subsection{Run your tests}
% The simplest way to run the tests is as part of your normal build process:
\subsection{Exécuter vos tests}
La façon la plus simple est de les lancer au court du processus de construction normal:

\begin{verbatim}
make && make install && make test
\end{verbatim}

% The make test command will invoke CTest which will run each test that 
% was registered using the ADD\_TEST CMake directive described above. Typical 
% output from make test will look like this:
La commande make test va invoquer CTest pour exécuter chaque test qui a été enregistré avec la directive CMake ADD\_TEST. Le résultat typique ressemble à ça:

\begin{verbatim}
Running tests...
Start processing tests
Test project /Users/tim/dev/cpp/qgis/build
1/  3 Testing qgis_applicationtest          ***Exception: Other
2/  3 Testing qgis_filewritertest           *** Passed
3/  3 Testing qgis_rasterlayertest          *** Passed

0% tests passed, 3 tests failed out of 3

  The following tests FAILED:
  1 - qgis_applicationtest (OTHER_FAULT)
  Errors while running CTest
  make: *** [test] Error 8
\end{verbatim}

% If a test fails, you can use the ctest command to examine more 
% closely why it failed. User the -R option to specify a regex for 
% which tests you want to run and -V to get verbose output:
Si un test échoue, vous pouvez utiliser la commande ctest pour examiner de plus prêt la raison de l'échec. Utilisez l'option -R pour spécifier un regex pour les tests que vous voulez exécuter et -V pour afficher une sortie verbeuse:

\begin{verbatim}
[build] ctest -R appl -V
Start processing tests
Test project /Users/tim/dev/cpp/qgis/build
Constructing a list of tests
Done constructing a list of tests
Changing directory into /Users/tim/dev/cpp/qgis/build/tests/src/core
1/  3 Testing qgis_applicationtest          
Test command: /Users/tim/dev/cpp/qgis/build/tests/src/core/qgis_applicationtest
********* Start testing of TestQgsApplication *********
  Config: Using QTest library 4.3.0, Qt 4.3.0
PASS   : TestQgsApplication::initTestCase()
  Prefix  PATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/../
  Plugin  PATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//lib/qgis
  PkgData PATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//share/qgis
  User DB PATH: /Users/tim/.qgis/qgis.db
PASS   : TestQgsApplication::getPaths()
  Prefix  PATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/../
  Plugin  PATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//lib/qgis
  PkgData PATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//share/qgis
  User DB PATH: /Users/tim/.qgis/qgis.db
  QDEBUG : TestQgsApplication::checkTheme() Checking if a theme icon exists:
  QDEBUG : TestQgsApplication::checkTheme() 
  /Users/tim/dev/cpp/qgis/build/tests/src/core/.. \
  //share/qgis/themes/default//mIconProjectionDisabled.png
  FAIL!  : TestQgsApplication::checkTheme() '!myPixmap.isNull()' returned FALSE. ()
  Loc: [/Users/tim/dev/cpp/qgis/tests/src/core/testqgsapplication.cpp(59)]
PASS   : TestQgsApplication::cleanupTestCase()
  Totals: 3 passed, 1 failed, 0 skipped
  ********* Finished testing of TestQgsApplication *********
  -- Process completed
  ***Failed

  0% tests passed, 1 tests failed out of 1

  The following tests FAILED:
1 - qgis_applicationtest (Failed)
  Errors while running CTest

\end{verbatim}

% Well that concludes this section on writing unit tests in QGIS. We hope you 
% will get into the habit of writing test to test new functionality and to 
% check for regressions. Some aspects of the test system (in particular the 
% CMakeLists.txt parts) are still being worked on so that the testing framework 
% works in a truly platform way. I will update this document as things progress.
Ceci conclut la section sur les tests unitaires dans QGIS. Nous espérons que vous allez vous habituer à écrire des tests pour éprouver chaque fonctionnalité et repérer les régressions. Certains aspects du système de test sont encore en chantier (notamment la partie sur CMakeLists.txt) pour améliorer l'environnement de test, le document rendra compte de ces mies à jour dans la procédure.

% \section{HIG (Human Interface Guidelines)}
% In order for all graphical user interface elements to appear consistant and 
% to all the user to instinctively use dialogs, it is important that the following 
% guidelines are followed in layout and design of GUIs.
\section{HIG (Guide de l'Interface Humaine)}
Pour avoir une interface graphique dont les divers éléments aient une consistance et que les utilisateurs puissent utiliser de manière instinctive, il est important de respecter les principes énoncés ci-dessous dans le design et la conception de l'interface.

%  \begin{enumerate}
%  \item Group related elements using group boxes:
%    Try to identify elements that can be grouped together and then use 
%    group boxes with a label to identify the topic of that group. 
%    Avoid using group boxes with only a single widget / item inside.
 \begin{enumerate}
 \item Grouper les éléments liés en utilisant des boîtes de groupe:
   Essayez d'identifier les éléments qui peuvent être rassemblés puis utilisez des boîtes munies d'une étiquette visant à déterminer le rôle de ce groupe. Il faut éviter de créer des boîtes avec un seul élément à l'intérieur.
%  \item Capitalise first letter only in labels:
%    Labels (and group box labels) should be written as a phrase with leading capital letter,
%    and all remaing words written with lower case first letters 
 \item Mettre en majuscule la première lettre uniquement dans les étiquettes:
   Les étiquettes (et celles des boîtes) doivent être rédigées avec une phrase dont la première lettre est en majuscule, tous les mots qui suivent doivent être en minuscule.
%  \item Do not end labels for widgets or group boxes with a colon:
%    Adding a colon causes visual noise and does not impart additional meaning,
%    so dont use them. An exception to this rule is when you have two labels 
%    next to each other e.g.: Label1 \htmladdnormallink{Plugin}{Path:} Label2 [/path/to/plugins]
 \item Ne pas terminer les étiquettes avec une colonne:
   L'ajout d'une colonne provoque une nuisance visuelle et ne donne aucune signification supplémentaire. Une exception à cette règle est si vous avez deux étiquettes côte à côte p. ex. : Etiquette1 \htmladdnormallink{Extension}{Chemin:} Etiquette2 [/chemin/vers/extensions]
%  \item Keep harmful actions away from harmless ones:
%    If you have actions for 'delete', 'remove' etc, try to impose adequate 
%    space between the harmful action and innocuous actions so that the users 
%    is less likely to inadvertantly click on the harmful action.
 \item Placer les actions dangereuses à l'écart de celles inoffensives:
   Si vous avez une action pour 'effacer', 'annuler', etc., essayez de conserver un espace entre ces actions et celles moins à risque pour éviter que l'utilisateur clique dessus par mégarde.
%  \item Always use a QButtonBox for 'OK', 'Cancel' etc buttons:
%    Using a button box will ensure that the order of 'OK' and 'Cancel' etc, 
%    buttons is consistent with the operating system / locale / desktop 
%    environment that the user is using.
 \item Toujours utiliser une QButtonBox pour les boutons 'OK', 'Annuler', etc. :
   Cela permet d'avoir un ordre et une apparence des boutons qui soient cohérents avec la plateforme / langue / environnement de bureau de l'utilisateur.
 \end{enumerate}
