Difference between revisions of "Écrire un rapport"

From Gramps
Jump to: navigation, search
m (report.gpr.py)
(38 intermediate revisions by one other user not shown)
Line 1: Line 1:
 
{{languages|Report-writing tutorial}}
 
{{languages|Report-writing tutorial}}
{{cleanup}}
+
{{stub}}
  
 
== Introduction ==
 
== Introduction ==
  
  
Ce tutoriel décrit les bases d'écriture d'un simple rapport utilisant l'infrastructure de GRAMPS. il couvre les processus de gestion d'options, la construction d'un document et de création de rapport.
+
Ce tutoriel décrit les bases pour l'écriture d'un simple rapport utilisant l'infrastructure de GRAMPS. Il couvre les processus de gestion d'options, la construction d'un document et de création d'un rapport.
  
Les objectifs de ce rapport est de créer une base de données de rapport de synthèse. Il comportera les informations suivantes dans le rapport:
+
Les objectifs de ce rapport est de créer un rapport de synthèse. Il comportera les informations suivantes :
  
 
     * Le nombre de personnes dans la base de données
 
     * Le nombre de personnes dans la base de données
Line 14: Line 14:
 
     * Le prénom le plus commun.
 
     * Le prénom le plus commun.
  
À partir de la version 3.2, également un  [[Simple Access API|accès simple]] aux [http://www.gramps-project.org/docs/ API] de base de données est disponible, accompagnée de [[Quick Reports|Rapports rapides]], [[Gramplets]] and [[Addons_Development|Addons]].
+
À partir de la version 3.2, sont également disponibles : un  [[Simple Access API|accès simple]] aux [http://www.gramps-project.org/docs/ API] de base de données, accompagné de [[Quick Reports|Rapports rapides]], [[Gramplets]] et [[Addons_Development|Addons]].
 
 
  
 
== Aperçu ==
 
== Aperçu ==
  
  
Avant d'entrer dans les détails, il est utile de noter que le rapport devrait comporter trois éléments fondamentaux. Comme expliqué sur la page [[Addons_Development|Addons]], les éléments sont dans deux fichiers différents : le fichier code source (càd : report.py) et le fichier d'enregistrement du greffon Gramps (càd : report.gpr.py).
+
Avant d'entrer dans les détails, il est utile de noter que le rapport doit comporter trois éléments fondamentaux. Comme expliqué sur la page [[Addons_Development|Addons]], les éléments sont dans deux fichiers différents : le fichier code source (càd : report.py) et le fichier d'enregistrement du greffon Gramps (càd : report.gpr.py).
  
 
===report.py===  
 
===report.py===  
  
 
;Rapport de classe
 
;Rapport de classe
    C'est ce code qui prend les données de la base de données GRAMPS et organise dans la structure du document.
+
C'est ce code qui contient les données de la base de données GRAMPS et les structure dans le document.
Cette structure peut ensuite être imprimée, visualisée, ou écrite dans un fichier dans une variété de formats.
+
 
Cette classe utilise l'interface [http://www.gramps-project.org/docs/ docgen] à l'écart résumé le format de sortie de détails.
+
Cette structure peut ensuite être imprimée, visualisée, ou écrite dans une variété de formats.
 +
 
 +
Cette classe utilise l'interface [http://www.gramps-project.org/docs/ docgen], fournissant les détails pour le format de sortie.
 +
 
 
;Options de la classe
 
;Options de la classe
    C'est le code qui fournit les moyens nécessaires pour obtenir des options pour le rapport
+
C'est le code qui fournit les moyens nécessaires à l'obtention des options pour le rapport, utilisant une variété de mécanismes disponibles.
en utilisant une variété de mécanismes disponibles.
 
  
 
===report.gpr.py===
 
===report.gpr.py===
  
 
;Déclaration d'enregistrement
 
;Déclaration d'enregistrement
    Ceci initialise le report par un simple appel de <tt>register()</tt> dans le module.
+
Ceci initialise le report par un simple appel de <tt>register()</tt> dans le module.
  
Il est trivial, mais sans elle votre rapport ne sera pas disponible dans GRAMPS, même si il est par ailleurs parfaitement écrit.
+
Il est trivial, mais sans ceci votre rapport ne sera pas disponible dans GRAMPS, même si il est par ailleurs parfaitement écrit.
  
 
Un rapport peut être généré potentiellement comme un rapport unique, comme un item de livre GRAMPS, et comme un rapport en ligne de commande. L'enregistrement détermine quels sont les modes activés pour un rapport donné. Le rapport classe ne nécessite aucune connaissance du mode. La classe d'options est là pour fournir des options d'interface pour tous les modes disponibles.
 
Un rapport peut être généré potentiellement comme un rapport unique, comme un item de livre GRAMPS, et comme un rapport en ligne de commande. L'enregistrement détermine quels sont les modes activés pour un rapport donné. Le rapport classe ne nécessite aucune connaissance du mode. La classe d'options est là pour fournir des options d'interface pour tous les modes disponibles.
  
== Document d'interface ==
+
== L'interface du document==
 
 
  
GRAMPS résumé les tentatives de sortie hors format de document le rapport. Par codage à la [http://www.gramps-project.org/docs/ docgen] classe, le rapport peut générer sa production dans le format désiré par l'utilisateur final. Le document transmis au rapport (<tt>self.doc</tt>) pourrait représenter une page HTML, OpenDocument, PDF ou dans les autres formats supportés par l'utilisateur. Le rapport n'a pas à se préoccuper des détails du format de sortie, puisque tous les détails sont pris en charge par l'objet document.
+
GRAMPS essaye d'ignorer la sortie du document quel que soit le rapport. En codant la classe [http://www.gramps-project.org/docs/ docgen], le rapport peut générer le document selon le format désiré par l'utilisateur final. Le document transmis au rapport (<tt>self.doc</tt>) peut être une page HTML, OpenDocument, PDF ou d'autres formats supportés par l'utilisateur. Le rapport n'a pas à se préoccuper des détails du format de sortie, puisque tous les détails sont pris en charge par l'objet document.
  
Un document est composé de paragraphes, des tableaux, des graphiques et d'objets. Les tableaux et les graphiques des objets ne seront pas couvertes dans ce tutoriel.
+
Un document est composé de paragraphes, des tableaux, des graphiques et d'objets. Les tableaux et les graphiques des objets ne seront pas développés dans ce tutoriel.
  
Le rapport définit une série de paragraphe et styles, ainsi que leur application par défaut. L'utilisateur peut l'emporter sur la définition de chaque modèle, qui permet à l'utilisateur de personnaliser le rapport. Chaque style de paragraphe doit être nommé spécifiquement, à prévenir les collisions lors de l'impression dans un format livre. Il est recommandé à chaque préfixe style de paragraphe avec un code à trois lettres uniques au rapport.
+
Le rapport définit une série de paragraphe et styles, ainsi que leur application par défaut. L'utilisateur peut passer outre la définition de chaque modèle, lui permettant de personnaliser le rapport. Chaque style de paragraphe doit être nommé spécifiquement, pour prévenir les collisions lors de l'impression dans un format livre. Il est recommandé de préfixer chaque style de paragraphe avec un code à trois lettres uniques au rapport.
  
Paragraphe et styles sont définis dans le <tt>make_default_style()</tt> la fonction de la classe d'options. Les points sont regroupés en un <tt>StyleSheet</tt>, que le <tt>make_default_style()</tt> définit. Pour l'exemple de rapport (<tt>DbSummary</tt>), les styles de paragraphe sont définies comme suit:
+
Paragraphe et styles sont définis dans <tt>make_default_style()</tt> : la fonction de la classe d'options. Les paragraphes sont regroupés dans <tt>StyleSheet</tt>, qui est défini dans <tt>make_default_style()</tt>. Pour l'exemple du rapport (<tt>DbSummary</tt>), les styles de paragraphe sont définies comme suit:
 
<pre>
 
<pre>
 
     def make_default_style(self, default_style):
 
     def make_default_style(self, default_style):
Line 87: Line 87:
  
  
=== Rapport de classe ===
+
=== La classe du rapport ===
  
L'utilisateur du rapport de classe doit hériter de la classe Rapport contenues dans le rapport du module. Le constructeur devrait prendre trois arguments (à part la classe exemple lui-même, le plus souvent signalés par un "moi" nom):
+
La classe du rapport doit hériter des contenus du rapport. Le développeur doit définir deux arguments (hors de la classe elle-même, le plus souvent signalés par un 'self'):
  
     * GRAMPS instance de base de données
+
     * La base de données GRAMPS
     * Personne objet
+
     * Classe options
    * Options de la classe exemple
 
  
Le premier est la base de données pour travailler. La deuxième est la personne sur laquelle le rapport est centré. Le troisième est l'instance de la classe d'options définies dans le même rapport, voir la section suivante. Voici un exemple d'un rapport de définition de classe:
+
Le premier est la base de données de travail. La deuxième est l'instance de la classe d'options définie dans le même rapport, voir la section suivante. Voici l'exemple d'une définition de classe pour un rapport:
 
<pre>
 
<pre>
 
   from ReportBase import Report, ReportUtils, ReportOptions
 
   from ReportBase import Report, ReportUtils, ReportOptions
Line 103: Line 102:
 
           Report.__init__(self,database,person,options_class)
 
           Report.__init__(self,database,person,options_class)
 
</pre>
 
</pre>
Le rapport classe le constructeur va initialiser plusieurs variables pour l'utilisateur basé sur les valeurs passées. Il s'agit de:
+
La classe du rapport va initialiser plusieurs variables pour l'utilisateur, basées sur les valeurs définies. Il s'agit de :
; self.doc: Le document ouvert exemple prêt pour la sortie. Il s'agit du type [http://www.gramps-project.org/docs/ docgen], et elle est '''pas''' un fichier normal objet.
+
 
; self.database: Le [http://www.gramps-project.org/docs/gen/gen_lib.html#module-gen.lib GrampsDbBase] objet de base de données
+
; self.doc : le document ouvert, prêt pour la sortie. Du type [http://www.gramps-project.org/docs/ docgen], ceci n'est '''pas''' un fichier objet normal.
; self.options_class: Le [http://www.gramps-project.org/devdoc/api/2.2/private/ReportBase._ReportOptions.ReportOptions-class.html ReportOptions] classe passées au rapport
+
; self.database : l'objet [http://www.gramps-project.org/docs/gen/gen_lib.html#module-gen.lib GrampsDbBase] de base de données.
Tout le reste du rapport classe les besoins afin de produire le rapport devrait être obtenu auprès de la <tt>options_class</tt>. Par exemple, vous pouvez avoir besoin d'inclure le code supplémentaires dans le rapport construction de la classe d'obtenir les options que vous avez définies pour le rapport.
+
; self.options_class : la classe [http://www.gramps-project.org/devdoc/api/2.2/private/ReportBase._ReportOptions.ReportOptions-class.html ReportOptions].
  
Rapport de la classe '''doit''' fournir <tt>write_report()</tt>. Cette méthode devrait copier le rapport contenu dans le document déjà ouvert.
+
Tout le reste du rapport devant définir les besoins afin de produire le rapport sera obtenu auprès de la classe <tt>options_class</tt>. Par exemple, vous pouvez avoir besoin d'inclure du code supplémentaires dans la construction de la classe afin d'obtenir les options que vous avez définies pour le rapport.
 +
 
 +
La classe du rapport '''doit''' fournir <tt>write_report()</tt>. Cette méthode doit copier le contenu du rapport dans le document déjà ouvert.
 
<pre>
 
<pre>
 
       def write_report(self):
 
       def write_report(self):
Line 116: Line 117:
 
           self.doc.end_paragraph()
 
           self.doc.end_paragraph()
 
</pre>
 
</pre>
Le reste du rapport est quasiment classe donnée au rapport écrivain. Selon les objectifs et la portée du rapport, il ya un montant de code en cause. Lorsque l'utilisateur génère le rapport dans n'importe quel mode, la construction de la classe va être exécuté, et ensuite la méthode <tt>write_report()</tt> sera appelée. Donc, si vous avez écrit que la méthode de cotation belle chose vraiment importante, assurez-vous qu'il est finalement appelée depuis <tt>write_report()</tt>. Sinon personne ne la verrez que si en regardant le code.
+
Le reste de la classe est plus l'affaire du développeur. Selon les objectifs et la portée du rapport, il y a une taille du code. Lorsque l'utilisateur génère le rapport dans n'importe quel mode, la construction de la classe va être exécutée, puis la méthode <tt>write_report()</tt> sera appelée. Donc, si vous avez écrit quelque chose de vraiment important, assurez-vous que ceci est appelée depuis <tt>write_report()</tt>. Sinon personne ne le verra, à part en regardant dans le code.
  
=== Options de la classe ===
+
=== La classe Options ===
  
    * Options de la classe devrait découler de [http://www.gramps-project.org/docs/ ReportOptions] classe.  
+
* La classe Options doit dériver de la classe [http://www.gramps-project.org/docs/ ReportOptions]. En général dans un simple rapport, la classe <tt>MenuReportOptions</tt> en est dérivée. <tt>MenuReportOptions</tt> va fournir l'essentiel de la gestion du widget de bas niveau.
 
 
Souvent dans un simple rapport la classe <tt>MenuReportOptions</tt> en est dérivée. <tt>MenuReportOptions</tt> va fournir l'essentiel de la gestion du widget de bas niveau.
 
  
 
====Utilisation de ReportOptions====
 
====Utilisation de ReportOptions====
Line 131: Line 130:
 
           ReportOptions.__init__(self,name,person_id)
 
           ReportOptions.__init__(self,name,person_id)
 
</pre>
 
</pre>
Il devrait fixer de nouvelles options qui sont spécifiques aux fins du présent rapport, par des raisons de la <tt>set_new_options()</tt> qui définit <tt>options_dict</tt> et <tt>options_help</tt> dictionnaires:
+
Elle doit fixer les nouvelles options spécifiques au rapport, avec <tt>set_new_options()</tt> qui définit les dictionnaires <tt>options_dict</tt> et <tt>options_help</tt>:
 
<pre>
 
<pre>
 
       def set_new_options(self):
 
       def set_new_options(self):
Line 147: Line 146:
 
         }
 
         }
 
</pre>
 
</pre>
* Il devrait également permettre à la "semi-common" les options qui sont utilisées dans le présent rapport, par des raisons de la <tt>enable_options</tt> qui définit <tt>enable_dict</tt> dictionnaire. Les semi-commons sont les options que GRAMPS connaît, mais qui ne sont pas nécessairement présentes dans tous les rapports:
+
* Elle doit également permettre les options "semi-common" utilisées dans le rapport, en passant par la méthode <tt>enable_options</tt> qui définit le dictionnaire <tt>enable_dict</tt>. Les semi-commons sont les options connues par GRAMPS, mais qui ne sont pas nécessairement présentes dans tous les rapports:
 
<pre>
 
<pre>
 
       def enable_options(self):
 
       def enable_options(self):
Line 155: Line 154:
 
           }
 
           }
 
</pre>
 
</pre>
Tous les options sont déjà prises en charge par la base de GRAMPS.
+
Toutes les options sont déjà prises en charge par le coeur de GRAMPS.
* Pour tout mettre en place de nouvelles options dans la classe d'options, il doit être défini widgets pour fournir les moyens de changer ces options par le biais du dialogue. En outre, il faut définir des méthodes pour extraire les valeurs de ces options dans le widgets et de les mettre ainsi dans la classe variable dictionnaire:
+
 
 +
* Pour mettre en place de nouvelles options dans la classe d'options, on doit définir des widgets d'interface, fournissant les moyens de changer ces options par le biais du dialogue. En outre, il faut définir des méthodes pour extraire les valeurs de ces options dans le widgets et de les mettre ainsi dans le dictionnaire de classe variable :
 
<pre>
 
<pre>
 
       def add_user_options(self,dialog):
 
       def add_user_options(self,dialog):
Line 186: Line 186:
 
</pre>
 
</pre>
 
 
* Enfin, les définitions par défaut pour l'utilisateur réglable paragraphe style doit être défini ici, pour former un 'défaut' feuille de style:
+
* Enfin, les définitions par défaut réglables par l'utilisateur. Le paragraphe et le style doivent être définis ici, formant une feuille de style par 'défaut' :
 
<pre>
 
<pre>
 
       def make_default_style(self,default_style):
 
       def make_default_style(self,default_style):
Line 197: Line 197:
 
           default_style.add_style("ABC-Name",p)
 
           default_style.add_style("ABC-Name",p)
 
</pre>
 
</pre>
 +
 +
====Utilisation de MenuReportOptions====
 +
 +
<tt>MenuReportOptions</tt> peut être utilisé à la place de <tt>ReportOptions</tt>, fournissant à l'utilisateur une interface standard pour le rapport. Au lieu de passer par des options, vous générez un menu parmi une ou plusieurs classes disponibles dans <tt>gen.plug.menu</tt>. Elles sont initialisées dans la fonction <tt>add_menu_options</tt> (qui est une fonction requise quand vous héritez depuis <tt>MenuReportOptions</tt>). Par exemple:
 +
 +
<pre>
 +
    def add_menu_options(self, menu):
 +
        """
 +
        Add options to the menu for this report.
 +
        """
 +
        category_name = _("Report Options")
 +
        what_types = BooleanListOption(_('Select From:'))
 +
        what_types.add_button(_('People'), True)
 +
        what_types.add_button(_('Families'), False)
 +
        what_types.add_button(_('Places'), False)
 +
        what_types.add_button(_('Events'), False)
 +
        menu.add_option(category_name, "what_types", what_types)
 +
</pre>
 +
 +
Dans cet exemple un objet <tt>BooleanListOption</tt> est créé qui fournit à l'utilisateur un groupe de case à cocher, créées par <tt>add_button</tt>. Enfin l'objet est ajouté au menu avec <tt>menu.add_option()</tt>. Le nom de la catégorie est utilisé pour générer des tabulations dans le dialogue du rapport.
 +
 +
Puis pour accéder aux valeurs sélectionnées une fois que l'utilisateur utilise le rapport, vous appelez l'objet menu depuis la fonction <tt>__init__</tt> du rapport.  Par exemple, pour accéder à "what_types" sélectionné depuis le menu ci-dessus, vous ajouterez le code suivant :
 +
 +
<pre>
 +
class ExampleReport(Report):
 +
 +
    def __init__(self, database, options_class):
 +
 +
        Report.__init__(self, database, options_class)
 +
 +
menu_option = options_class.menu.get_option_by_name('what_types')
 +
        self.what_types = menu_option.get_selected()
 +
</pre>
 +
 +
Dans cet exemple, la classe option est rapportée par la fonction <tt>get_option_by_name()</tt>.  La chaîne doit correspondre au nom qui vous avez saisi comme second argument dans <tt>menu.add_option()</tt> lorsque que vous avez créé le menu. Enfin une liste des items sélectionnés est rapportée avec <tt>get_selected()</tt> et stockée comme faisant partie d'une classe pour une utilisation future.
  
 
== Implémentation ==
 
== Implémentation ==
=== Définition de la classe Rapport Options ===
+
=== Définition de la classe Options du rapport ===
  
Dans cet exemple, aucune des options spéciales sont requises. Cela rend la classe d'options très simple. Tout ce qui est nécessaire pour définir les styles par défaut.
+
Dans cet exemple, aucune option particulière n'est requise. Cela rend la classe d'options très simple. Tout ce qui est nécessaire pour définir les styles par défaut.
 
<pre>
 
<pre>
 
class DbSummaryOptions(ReportOptions):
 
class DbSummaryOptions(ReportOptions):
Line 214: Line 249:
 
         # 18 point, bold Sans Serif font with a paragraph that is centered
 
         # 18 point, bold Sans Serif font with a paragraph that is centered
  
         font = BaseDoc.FontStyle()
+
         font = docgen.FontStyle()
 
         font.set_size(18)
 
         font.set_size(18)
         font.set_type_face(BaseDoc.FONT_SANS_SERIF)
+
         font.set_type_face(docgen.FONT_SANS_SERIF)
 
         font.set_bold(True)
 
         font.set_bold(True)
  
         para = BaseDoc.ParagraphStyle()
+
         para = docgen.ParagraphStyle()
 
         para.set_header_level(1)
 
         para.set_header_level(1)
         para.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
+
         para.set_alignment(docgen.PARA_ALIGN_CENTER)
 
         para.set_font(font)
 
         para.set_font(font)
 
         para.set_description(_('The style used for the title of the page.'))
 
         para.set_description(_('The style used for the title of the page.'))
Line 230: Line 265:
 
         # 12 point, Serif font.
 
         # 12 point, Serif font.
  
         font = BaseDoc.FontStyle()
+
         font = docgen.FontStyle()
 
         font.set_size(12)
 
         font.set_size(12)
         font.set_type_face(BaseDoc.FONT_SERIF)
+
         font.set_type_face(docgen.FONT_SERIF)
  
         para = BaseDoc.ParagraphStyle()
+
         para = docgen.ParagraphStyle()
 
         para.set_font(font)
 
         para.set_font(font)
 
         para.set_description(_('The style used for normal text'))
 
         para.set_description(_('The style used for normal text'))
Line 240: Line 275:
 
         default_style.add_style('DBS-Normal',para)
 
         default_style.add_style('DBS-Normal',para)
 
</pre>
 
</pre>
=== Définir le rapport de classe ===
 
  
La mise en place effective de la <tt>DbSummary</tt> rapport est assez simple. Pas de travail supplémentaire doit être fait pour initialiser la classe, de sorte que les parents <tt>__init__</tt> routine est appelée.
+
=== Définir la classe du rapport ===
  
Tout le travail se fait dans le <tt>write_report()</tt>. Cette fonction utilise un <tt>GrampsCursor</tt> à itérer à travers la carte de la <tt>Person</tt> qui rassemble les objets et de simples statistiques.
+
La mise en place effective du rapport <tt>DbSummary</tt> est assez simple. Pas de travail supplémentaire pour initialiser la classe, de sorte que la routine parent <tt>__init__</tt> est appelée.
  
La seule chose de toute complication la détermination de la plupart des communes patronyme. Un dictionnaire Python est utilisé pour stocker le nombre de fois que chaque nom est utilisé. Chaque fois qu'un nom est rencontré, la valeur dans le dictionnaire est incrémenté. Les résultats sont ensuite chargés dans une liste et classés, ce qui nous permet de trouver le nom le plus courant en regardant la dernière inscription dans la liste.
+
Tout le travail se fait dans <tt>write_report()</tt>. Cette fonction utilise <tt>GrampsCursor</tt> pour itérer à travers les <tt>objects</tt>, rassemblant les objets tels de simples statistiques.
 +
 
 +
La seule chose un peu plus compliqué étant la détermination des patronymes les plus courants. Un dictionnaire Python est utilisé pour stocker le nombre de fois que chaque nom est utilisé. Chaque fois qu'un nom est rencontré, la valeur dans le dictionnaire est incrémentée. Les résultats sont ensuite chargés dans une liste et classés, ce qui nous permet de trouver le nom le plus courant en regardant la dernière inscription dans la liste.
 
<pre>
 
<pre>
 
class DbSummaryReport(Report):
 
class DbSummaryReport(Report):
Line 313: Line 349:
 
         self.doc.end_paragraph()
 
         self.doc.end_paragraph()
 
</pre>
 
</pre>
 +
 
=== L'enregistrement du rapport ===
 
=== L'enregistrement du rapport ===
  
 
* L'enregistrement est défini dans un fichier ''nom.gpr.py''.
 
* L'enregistrement est défini dans un fichier ''nom.gpr.py''.
* L'enregistrement devrait définir nom interne du rapport (de préférence, seule chaîne avec des caractères spéciaux, utilisable pour rendre l'identification de la ligne de commande et dans les options de stockage, ainsi que pour former le nom du fichier sain pour stocker ses propres modèles). Il devrait aussi définir la catégorie de rapport (texte / graphiques / Code), traduit nom (celui de l'affichage dans les menus), et les modes de transport qui doit être activé pour le rapport (autonome, le carnet de point, de ligne de commande). Enfin, les deux options de rapport classe et la classe devrait être passé à l'enregistrement. Voici par exemple la déclaration d'enregistrement:
+
* L'enregistrement doit définir un nom interne pour le rapport (de préférence, une seule chaîne sans caractères spéciaux, utilisable pour l'identification en ligne de commande et dans les options de stockage, ainsi que pour fournir un nom de fichier nécessaire au stockage de ses propres modèles). On doit aussi définir :
Finalement, les classes ''options'' et ''report'' doivent passer par l'enregistrement.  
+
 
 +
** la catégorie du rapport (texte / graphiques / Code)
 +
** le nom pour la traduction (celui de l'affichage dans les menus)
 +
** les modes qui doivent être activés pour le rapport (autonome, livre, ligne de commande).
 +
 
 +
* Si le rapport a besoin d'une personne active pour fonctionner, alors <tt>require_active</tt> doit être défini comme ''True''.
 +
* Enfin, les classes ''options'' et ''report'' doivent être passées par l'enregistrement.  
 +
 
 
Voici un exemple d'enregistrement :
 
Voici un exemple d'enregistrement :
 
<pre>
 
<pre>
  plg = newplugin()
+
register(REPORT,
  plg.id    = 'un identifiant unique'
+
id    = 'un identifiant unique'
  plg.name  = _("Nom du plugin")
+
name  = _("Nom du plugin")
  plg.description =  _("Produces a ...")
+
description =  _("Produces a ...")
  plg.version = '1.0'
+
version = '1.0'
  plg.gramps_target_version = '3.2'
+
gramps_target_version = '3.2'
  plg.status = STABLE
+
status = STABLE
  plg.fname = 'filename.py'
+
fname = 'filename.py'
  plg.ptype = REPORT
+
authors = ["John Doe"]
  plg.authors = [""]
+
authors_email = ["jdoe@example.com"]
  plg.authors_email = ["@"]
+
category = CATEGORY_TEXT
  plg.category = CATEGORY_TEXT
+
require_active = False
  plg.reportclass = 'DbSummaryReport'
+
reportclass = 'DbSummaryReport'
  plg.optionclass = 'DbSummaryOptions'
+
optionclass = 'DbSummaryOptions'
  plg.report_modes = [REPORT_MODE_GUI, REPORT_MODE_CLI]
+
report_modes = [REPORT_MODE_GUI, REPORT_MODE_CLI]
 
</pre>
 
</pre>
Deux chaînes définissent le rapport de classe et d'options classe.  
+
Deux chaînes définissent la classe du rapport et la classe d'options.  
L'argument <tt>report_modes</tt> argument est fixé à la somme de bits sage (le <tt>OU</tt>) de chacun des trois modes possibles: GUI (autonome rapport produit d'GRAMPS cours d'exécution dans une fenêtre), BKI (Livre en question), et CLI (interface de ligne de commande). Cela signifie que le rapport sera disponible dans les trois modes. Le reste devrait être d'explication.
+
L'argument <tt>report_modes</tt> est défini pour être une somme de bits (le <tt>OR</tt> statement) parmi les modes disponibles : GUI (rapport autonome produit depuis GRAMPS dans une fenêtre), BKI (article du livre), et CLI (interface de la ligne de commande). Cela signifie que le rapport sera disponible dans les trois modes.
 
 
Un exemplaire complet du rapport peut être [[media:DbSummary.zip|téléchargé (1.66 KB)]] pour les essais et l'expérimentation.
 
 
 
  
[[Category:Fr:Documentation]]
+
[[Category:Fr:Documentation|R]]

Revision as of 08:26, 5 January 2017

Gramps-notes.png

This article's content is incomplete or a placeholder stub.
Please update or expand this section.


Introduction

Ce tutoriel décrit les bases pour l'écriture d'un simple rapport utilisant l'infrastructure de GRAMPS. Il couvre les processus de gestion d'options, la construction d'un document et de création d'un rapport.

Les objectifs de ce rapport est de créer un rapport de synthèse. Il comportera les informations suivantes :

    * Le nombre de personnes dans la base de données
    * Le nombre de garçons et de filles
    * Le nombre de noms de famille uniques.
    * Le prénom le plus commun.

À partir de la version 3.2, sont également disponibles : un accès simple aux API de base de données, accompagné de Rapports rapides, Gramplets et Addons.

Aperçu

Avant d'entrer dans les détails, il est utile de noter que le rapport doit comporter trois éléments fondamentaux. Comme expliqué sur la page Addons, les éléments sont dans deux fichiers différents : le fichier code source (càd : report.py) et le fichier d'enregistrement du greffon Gramps (càd : report.gpr.py).

report.py

Rapport de classe

C'est ce code qui contient les données de la base de données GRAMPS et les structure dans le document.

Cette structure peut ensuite être imprimée, visualisée, ou écrite dans une variété de formats.

Cette classe utilise l'interface docgen, fournissant les détails pour le format de sortie.

Options de la classe

C'est le code qui fournit les moyens nécessaires à l'obtention des options pour le rapport, utilisant une variété de mécanismes disponibles.

report.gpr.py

Déclaration d'enregistrement

Ceci initialise le report par un simple appel de register() dans le module.

Il est trivial, mais sans ceci votre rapport ne sera pas disponible dans GRAMPS, même si il est par ailleurs parfaitement écrit.

Un rapport peut être généré potentiellement comme un rapport unique, comme un item de livre GRAMPS, et comme un rapport en ligne de commande. L'enregistrement détermine quels sont les modes activés pour un rapport donné. Le rapport classe ne nécessite aucune connaissance du mode. La classe d'options est là pour fournir des options d'interface pour tous les modes disponibles.

L'interface du document

GRAMPS essaye d'ignorer la sortie du document quel que soit le rapport. En codant la classe docgen, le rapport peut générer le document selon le format désiré par l'utilisateur final. Le document transmis au rapport (self.doc) peut être une page HTML, OpenDocument, PDF ou d'autres formats supportés par l'utilisateur. Le rapport n'a pas à se préoccuper des détails du format de sortie, puisque tous les détails sont pris en charge par l'objet document.

Un document est composé de paragraphes, des tableaux, des graphiques et d'objets. Les tableaux et les graphiques des objets ne seront pas développés dans ce tutoriel.

Le rapport définit une série de paragraphe et styles, ainsi que leur application par défaut. L'utilisateur peut passer outre la définition de chaque modèle, lui permettant de personnaliser le rapport. Chaque style de paragraphe doit être nommé spécifiquement, pour prévenir les collisions lors de l'impression dans un format livre. Il est recommandé de préfixer chaque style de paragraphe avec un code à trois lettres uniques au rapport.

Paragraphe et styles sont définis dans make_default_style() : la fonction de la classe d'options. Les paragraphes sont regroupés dans StyleSheet, qui est défini dans make_default_style(). Pour l'exemple du rapport (DbSummary), les styles de paragraphe sont définies comme suit:

    def make_default_style(self, default_style):

        # Define the title paragraph, named 'DBS-Title', which uses a
        # 18 point, bold Sans Serif font with a paragraph that is centered

        font = docgen.FontStyle()
        font.set_size(18)
        font.set_type_face(docgen.FONT_SANS_SERIF)
        font.set_bold(True)

        para = docgen.ParagraphStyle()
        para.set_header_level(1)
        para.set_alignment(docgen.PARA_ALIGN_CENTER)
        para.set_font(font)
        para.set_description(_('The style used for the title of the page.'))

        default_style.add_style('DBS-Title',para)

        # Define the normal paragraph, named 'DBS-Normal', which uses a
        # 12 point, Serif font.

        font = docgen.FontStyle()
        font.set_size(12)
        font.set_type_face(docgen.FONT_SERIF)

        para = docgen.ParagraphStyle()
        para.set_font(font)
        para.set_description(_('The style used for normal text'))

        default_style.add_style('DBS-Normal',para)

Définir les classes

La classe du rapport

La classe du rapport doit hériter des contenus du rapport. Le développeur doit définir deux arguments (hors de la classe elle-même, le plus souvent signalés par un 'self'):

    * La base de données GRAMPS
    * Classe options

Le premier est la base de données de travail. La deuxième est l'instance de la classe d'options définie dans le même rapport, voir la section suivante. Voici l'exemple d'une définition de classe pour un rapport:

  from ReportBase import Report, ReportUtils, ReportOptions

  class ReportClassName(Report):
      def __init__(self,database,person,options_class):
          Report.__init__(self,database,person,options_class)

La classe du rapport va initialiser plusieurs variables pour l'utilisateur, basées sur les valeurs définies. Il s'agit de :

self.doc 
le document ouvert, prêt pour la sortie. Du type docgen, ceci n'est pas un fichier objet normal.
self.database 
l'objet GrampsDbBase de base de données.
self.options_class 
la classe ReportOptions.

Tout le reste du rapport devant définir les besoins afin de produire le rapport sera obtenu auprès de la classe options_class. Par exemple, vous pouvez avoir besoin d'inclure du code supplémentaires dans la construction de la classe afin d'obtenir les options que vous avez définies pour le rapport.

La classe du rapport doit fournir write_report(). Cette méthode doit copier le contenu du rapport dans le document déjà ouvert.

      def write_report(self):
          self.doc.start_paragraph("ABC-Title")
          self.doc.write_text(_("Some text"))
          self.doc.end_paragraph()

Le reste de la classe est plus l'affaire du développeur. Selon les objectifs et la portée du rapport, il y a une taille du code. Lorsque l'utilisateur génère le rapport dans n'importe quel mode, la construction de la classe va être exécutée, puis la méthode write_report() sera appelée. Donc, si vous avez écrit quelque chose de vraiment important, assurez-vous que ceci est appelée depuis write_report(). Sinon personne ne le verra, à part en regardant dans le code.

La classe Options

  • La classe Options doit dériver de la classe ReportOptions. En général dans un simple rapport, la classe MenuReportOptions en est dérivée. MenuReportOptions va fournir l'essentiel de la gestion du widget de bas niveau.

Utilisation de ReportOptions

  class OptionsClassName(ReportOptions):
      def __init__(self,name,person_id=None):
          ReportOptions.__init__(self,name,person_id)

Elle doit fixer les nouvelles options spécifiques au rapport, avec set_new_options() qui définit les dictionnaires options_dict et options_help:

      def set_new_options(self):
          # Options specific for this report
          self.options_dict = {
              'my_fist_option'    : 0,
              'my_second_option'  : '',
          }
          self.options_help = {
              'my_fist_option'    : ("=num","Number of something",
                                     [ "First value", "Second value" ],
                                     True),
              'my_second_option'  : ("=str","Some necessary string for the report",
                                     "Whatever String You Wish"),
        }
  • Elle doit également permettre les options "semi-common" utilisées dans le rapport, en passant par la méthode enable_options qui définit le dictionnaire enable_dict. Les semi-commons sont les options connues par GRAMPS, mais qui ne sont pas nécessairement présentes dans tous les rapports:
      def enable_options(self):
          # Semi-common options that should be enabled for this report
          self.enable_dict = {
              'filter'    : 0,
          }

Toutes les options sont déjà prises en charge par le coeur de GRAMPS.

  • Pour mettre en place de nouvelles options dans la classe d'options, on doit définir des widgets d'interface, fournissant les moyens de changer ces options par le biais du dialogue. En outre, il faut définir des méthodes pour extraire les valeurs de ces options dans le widgets et de les mettre ainsi dans le dictionnaire de classe variable :
      def add_user_options(self,dialog):
          option_menu = gtk.OptionMenu()
          self.the_menu = gtk.Menu()

          for item_index in range(10):
              item = _("Item numer %d") % item_index
              menuitem = gtk.MenuItem(item)
              menuitem.show()
              self.the_menu.append(menuitem)

          option_menu.set_menu(self.the_menu)
          option_menu.set_history(self.options_dict['my_first_option'])

          dialog.add_option(_('My first option'),option_menu)

          self.the_string_entry = gtk.Entry()
          if self.options_dict['my_second_option']:
              self.the_string_entry.set_text(self.options_dict['my_second_option'])
          else:
              self.the_string_entry.set_text(_("Empty string"))
          self.the_string_entry.show()
          dialog.add_option(_('My second option'),self.the_string_entry)

      def parse_user_options(self,dialog):
          self.options_dict['my_second_option'] = unicode(self.the_string_entry.get_text())
          self.options_dict['my_first_option'] = self.the_menu.get_history()
  • Enfin, les définitions par défaut réglables par l'utilisateur. Le paragraphe et le style doivent être définis ici, formant une feuille de style par 'défaut' :
      def make_default_style(self,default_style):
          f = docgen.FontStyle()
          f.set_size(10)
          f.set_type_face(docgen.FONT_SANS_SERIF)
          p = docgen.ParagraphStyle()
          p.set_font(f)
          p.set_description(_("The style used for the person's name."))
          default_style.add_style("ABC-Name",p)

Utilisation de MenuReportOptions

MenuReportOptions peut être utilisé à la place de ReportOptions, fournissant à l'utilisateur une interface standard pour le rapport. Au lieu de passer par des options, vous générez un menu parmi une ou plusieurs classes disponibles dans gen.plug.menu. Elles sont initialisées dans la fonction add_menu_options (qui est une fonction requise quand vous héritez depuis MenuReportOptions). Par exemple:

    def add_menu_options(self, menu):
        """
        Add options to the menu for this report.
        """
        category_name = _("Report Options")
        what_types = BooleanListOption(_('Select From:'))
        what_types.add_button(_('People'), True)
        what_types.add_button(_('Families'), False)
        what_types.add_button(_('Places'), False)
        what_types.add_button(_('Events'), False)
        menu.add_option(category_name, "what_types", what_types)

Dans cet exemple un objet BooleanListOption est créé qui fournit à l'utilisateur un groupe de case à cocher, créées par add_button. Enfin l'objet est ajouté au menu avec menu.add_option(). Le nom de la catégorie est utilisé pour générer des tabulations dans le dialogue du rapport.

Puis pour accéder aux valeurs sélectionnées une fois que l'utilisateur utilise le rapport, vous appelez l'objet menu depuis la fonction __init__ du rapport. Par exemple, pour accéder à "what_types" sélectionné depuis le menu ci-dessus, vous ajouterez le code suivant :

class ExampleReport(Report):

    def __init__(self, database, options_class):

        Report.__init__(self, database, options_class)

	menu_option = options_class.menu.get_option_by_name('what_types')
        self.what_types = menu_option.get_selected()

Dans cet exemple, la classe option est rapportée par la fonction get_option_by_name(). La chaîne doit correspondre au nom qui vous avez saisi comme second argument dans menu.add_option() lorsque que vous avez créé le menu. Enfin une liste des items sélectionnés est rapportée avec get_selected() et stockée comme faisant partie d'une classe pour une utilisation future.

Implémentation

Définition de la classe Options du rapport

Dans cet exemple, aucune option particulière n'est requise. Cela rend la classe d'options très simple. Tout ce qui est nécessaire pour définir les styles par défaut.

class DbSummaryOptions(ReportOptions):

    def __init__(self, name, person_id=None):

        ReportOptions.__init__(self, name, person_id)

    def make_default_style(self, default_style):

        # Define the title paragraph, named 'DBS-Title', which uses a
        # 18 point, bold Sans Serif font with a paragraph that is centered

        font = docgen.FontStyle()
        font.set_size(18)
        font.set_type_face(docgen.FONT_SANS_SERIF)
        font.set_bold(True)

        para = docgen.ParagraphStyle()
        para.set_header_level(1)
        para.set_alignment(docgen.PARA_ALIGN_CENTER)
        para.set_font(font)
        para.set_description(_('The style used for the title of the page.'))

        default_style.add_style('DBS-Title',para)

        # Define the normal paragraph, named 'DBS-Normal', which uses a
        # 12 point, Serif font.

        font = docgen.FontStyle()
        font.set_size(12)
        font.set_type_face(docgen.FONT_SERIF)

        para = docgen.ParagraphStyle()
        para.set_font(font)
        para.set_description(_('The style used for normal text'))

        default_style.add_style('DBS-Normal',para)

Définir la classe du rapport

La mise en place effective du rapport DbSummary est assez simple. Pas de travail supplémentaire pour initialiser la classe, de sorte que la routine parent __init__ est appelée.

Tout le travail se fait dans write_report(). Cette fonction utilise GrampsCursor pour itérer à travers les objects, rassemblant les objets tels de simples statistiques.

La seule chose un peu plus compliqué étant la détermination des patronymes les plus courants. Un dictionnaire Python est utilisé pour stocker le nombre de fois que chaque nom est utilisé. Chaque fois qu'un nom est rencontré, la valeur dans le dictionnaire est incrémentée. Les résultats sont ensuite chargés dans une liste et classés, ce qui nous permet de trouver le nom le plus courant en regardant la dernière inscription dans la liste.

class DbSummaryReport(Report):

    def __init__(self, database, person, options_class):

        Report.__init__(self, database, person, options_class)

    def write_report(self):

        cursor = self.database.get_person_cursor()

        data = cursor.first()

        males = 0
        females = 0
        total = 0
        surname_map = {}
        while data:
            person = RelLib.Person()
            person.unserialize(data[1])

            if person.get_gender() == RelLib.Person.MALE:
                males += 1
            if person.get_gender() == RelLib.Person.FEMALE:
                females += 1
            total += 1

            surname = person.get_primary_name().get_surname()

            if surname_map.has_key(surname):
                surname_map[surname] += 1
            else:
                surname_map[surname] = 1

            data = cursor.next()
        cursor.close()

        slist = []
        for key in surname_map.keys():
            slist.append((surname_map[key],key))
        slist.sort()

        self.doc.start_paragraph("DBS-Title")
        self.doc.write_text(_("Database Summary"))
        self.doc.end_paragraph()

        self.doc.start_paragraph('DBS-Normal')
        self.doc.write_text(_('Number of males : %d') % males)
        self.doc.end_paragraph()

        self.doc.start_paragraph('DBS-Normal')
        self.doc.write_text(_('Number of females : %d') % females)
        self.doc.end_paragraph()

        self.doc.start_paragraph('DBS-Normal')
        self.doc.write_text(_('Total people : %d') % total)
        self.doc.end_paragraph()

        self.doc.start_paragraph('DBS-Normal')
        self.doc.write_text(_('Number of unique surnames : %d') % len(slist))
        self.doc.end_paragraph()

        self.doc.start_paragraph('DBS-Normal')
        self.doc.write_text(_('Most common surname : %s') % (slist[-1][1]))
        self.doc.end_paragraph()

L'enregistrement du rapport

  • L'enregistrement est défini dans un fichier nom.gpr.py.
  • L'enregistrement doit définir un nom interne pour le rapport (de préférence, une seule chaîne sans caractères spéciaux, utilisable pour l'identification en ligne de commande et dans les options de stockage, ainsi que pour fournir un nom de fichier nécessaire au stockage de ses propres modèles). On doit aussi définir :
    • la catégorie du rapport (texte / graphiques / Code)
    • le nom pour la traduction (celui de l'affichage dans les menus)
    • les modes qui doivent être activés pour le rapport (autonome, livre, ligne de commande).
  • Si le rapport a besoin d'une personne active pour fonctionner, alors require_active doit être défini comme True.
  • Enfin, les classes options et report doivent être passées par l'enregistrement.

Voici un exemple d'enregistrement :

register(REPORT,
id    = 'un identifiant unique'
name  = _("Nom du plugin")
description =  _("Produces a ...")
version = '1.0'
gramps_target_version = '3.2'
status = STABLE
fname = 'filename.py'
authors = ["John Doe"]
authors_email = ["[email protected]"]
category = CATEGORY_TEXT
require_active = False
reportclass = 'DbSummaryReport'
optionclass = 'DbSummaryOptions'
report_modes = [REPORT_MODE_GUI, REPORT_MODE_CLI]

Deux chaînes définissent la classe du rapport et la classe d'options. L'argument report_modes est défini pour être une somme de bits (le OR statement) parmi les modes disponibles : GUI (rapport autonome produit depuis GRAMPS dans une fenêtre), BKI (article du livre), et CLI (interface de la ligne de commande). Cela signifie que le rapport sera disponible dans les trois modes.