Difference between revisions of "Develop an Add-on Rule"

From Gramps
Jump to: navigation, search
m
m
 
(11 intermediate revisions by the same user not shown)
Line 2: Line 2:
 
{{Languages|Develop_an_Add-on_Rule}}
 
{{Languages|Develop_an_Add-on_Rule}}
 
-->
 
-->
{{man warn|1=🚧 Work In Progress|2=This wikipage is a cloned outline from a template. It is being roughed in.
+
{{stub}}
  
Since you are reading '''''this paragraph''''', then the WikiContributor has not progressed to the point of trimming out the excess template material. That means the wikipage is probably not ready for collaborative editing yet. Multiple people editing ''now'' might unintentionally overwrite their work. Please post your suggestion on the '''Discussion''' page instead of directly editing the content.}}
+
Custom [[Gramps_Glossary#filter|Filters]] are built upon Query [[Gramps_Glossary#rule|Rules]]. Sometimes a filter rule has not been provided to search the part of the Tree desired. Or the existing Rules can not be combined to isolate the desired part of the Tree. If those particular branches and leaves must be repeatedly isolated, building a query rule might be the next logical step.
  
Custom Filters are built upon Query Rules. Sometimes a filter rule has not been provided to search the part of the Tree desired. Or the existing Rules can not be combined to isolate the desired part of the Tree. If those particular must be repeatedly isolated, building a query rule might be the next logical step.
+
Query Rules abstract the underlying complexity of the query and provides a higher-level, simpler interface for users to define search criteria without needing to understand the intricate details of the actual database query language.  
== placeholder ==
+
 
 +
 
 +
== coding style guide (placeholder) ==
 
In various rules that allow a Person ID to be selected as a parameter value, both [[Gramps_{{man version}}_Wiki_Manual_-_Filters|built-in rules]] & [[Rule_expansions|add-on rules]] use inconsistent placeholders:
 
In various rules that allow a Person ID to be selected as a parameter value, both [[Gramps_{{man version}}_Wiki_Manual_-_Filters|built-in rules]] & [[Rule_expansions|add-on rules]] use inconsistent placeholders:
  
Line 28: Line 30:
  
 
== Converting a query to an add-on Filter Rule ==
 
== Converting a query to an add-on Filter Rule ==
 +
=== Sample Gramps Plug-in Registration file ===
 +
[https://github.com/gramps-project/addons-source/blob/master/FilterRules/hasrolerule.gpr.py <code>hasrolerule.gpr.py</code>]
 +
 +
<pre>#
 +
# GPR (Gramps plug-in Registration) of a Python module
 +
#    for Gramps - a GTK+/GNOME based genealogy program
 +
#
 +
# Copyright (C) 2018  Paul Culley
 +
#
 +
# 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.
 +
#
 +
# This program is distributed in the hope that it will be useful,
 +
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 +
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +
# GNU General Public License for more details.
 +
#
 +
# You should have received a copy of the GNU General Public License
 +
# along with this program; if not, write to the Free Software
 +
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 +
#
 +
"""
 +
Filter rule to match an Event Role with a particular value.
 +
"""
 +
 +
register(RULE,
 +
        id='HasPersonEventRole',
 +
        name=_("People with events with a selected role"),
 +
        description=_("Matches people with an event with a selected role"),
 +
        version='0.0.14',
 +
        authors=["Paul Culley"],
 +
        authors_email=["[email protected]"],
 +
        gramps_target_version='5.1',
 +
        status=STABLE,
 +
        fname="hasrolerule.py",
 +
        ruleclass='HasPersonEventRole',  # must be rule class name
 +
        namespace='Person',  # one of the primary object classes
 +
        )
 +
 +
register(RULE,
 +
        id='HasFamilyEventRole',
 +
        name=_("Families with events with a selected role"),
 +
        description=_("Matches families with an event with a selected role"),
 +
        version='0.0.14',
 +
        authors=["Paul Culley"],
 +
        authors_email=["[email protected]"],
 +
        gramps_target_version='5.1',
 +
        status=STABLE,
 +
        fname="hasrolerule.py",
 +
        ruleclass='HasFamilyEventRole',  # must be rule class name
 +
        namespace='Family',  # one of the primary object classes
 +
        )
 +
</pre>
 +
 +
=== Sample Gramps Plug-in source file ===
 +
[https://github.com/gramps-project/addons-source/blob/master/FilterRules/hasrolerule.py <code>hasrolerule.py</code>]
 +
 +
''Filenames'' or <code>Filenames</code>
 +
 +
<pre>#
 +
 +
# plug-in Python module
 +
#    for Gramps - a GTK+/GNOME based genealogy program
 +
#
 +
# Copyright (C) 2018  Paul Culley
 +
#
 +
# 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.
 +
#
 +
# This program is distributed in the hope that it will be useful,
 +
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 +
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +
# GNU General Public License for more details.
 +
#
 +
# You should have received a copy of the GNU General Public License
 +
# along with this program; if not, write to the Free Software
 +
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 +
#
 +
 +
"""
 +
Filter rule to match persons with a particular event.
 +
"""
 +
# -------------------------------------------------------------------------
 +
#
 +
# Standard Python modules
 +
#
 +
# -------------------------------------------------------------------------
  
 +
# -------------------------------------------------------------------------
 +
#
 +
# Gramps modules
 +
#
 +
# -------------------------------------------------------------------------
 +
from gramps.gen.lib.eventroletype import EventRoleType
 +
from gramps.gui.editors.filtereditor import MySelect, MyBoolean
 +
from gramps.gen.filters.rules import Rule
 +
from gramps.gen.const import GRAMPS_LOCALE as glocale
 +
try:
 +
    _trans = glocale.get_addon_translator(__file__)
 +
except ValueError:
 +
    _trans = glocale.translation
 +
_ = _trans.gettext
 +
 +
 +
class Roletype(MySelect):
 +
    """ Provide a Role type selector """
 +
    def __init__(self, db):
 +
        MySelect.__init__(self, EventRoleType, db.get_event_roles())
 +
 +
 +
class NoMatch(MyBoolean):
 +
    """ Provide a negation switch """
 +
    def __init__(self, db):
 +
        MyBoolean.__init__(self, _("Does NOT match with selected Role"))
 +
        self.set_tooltip_text(_("Finds the items that don't have event Roles "
 +
                                "of the selected type."))
 +
# -------------------------------------------------------------------------
 +
#
 +
# HasEvent
 +
#
 +
# -------------------------------------------------------------------------
 +
 +
 +
class HasPersonEventRole(Rule):
 +
    """Rule that checks for a person with a selected event role"""
 +
 +
    labels = [(_('Role'), Roletype),
 +
              (_('Inverse'), NoMatch)]
 +
    name = _('People with events with the <role>')
 +
    description = _("Matches people with an event with a selected role")
 +
    category = _('Event filters')
 +
 +
    def apply(self, dbase, person):
 +
        if not self.list[0]:
 +
            return False
 +
        for event_ref in person.get_event_ref_list():
 +
            if not event_ref:
 +
                continue
 +
            if self.list[1] == '1':
 +
                if event_ref.role.xml_str() != self.list[0]:
 +
                    return True
 +
            else:
 +
                if event_ref.role.xml_str() == self.list[0]:
 +
                    return True
 +
        return False
 +
 +
 +
class HasFamilyEventRole(Rule):
 +
    """Rule that checks for a family with a selected event role"""
 +
 +
    labels = [(_('Role'), Roletype),
 +
              (_('Inverse'), NoMatch)]
 +
    name = _('Families with events with the <role>')
 +
    description = _("Matches families with an event with a selected role")
 +
    category = _('Event filters')
 +
 +
    def apply(self, dbase, family):
 +
        if not self.list[0]:
 +
            return False
 +
        for event_ref in family.get_event_ref_list():
 +
            if not event_ref:
 +
                continue
 +
            if self.list[1] == '1':
 +
                if event_ref.role.xml_str() != self.list[0]:
 +
                    return True
 +
            else:
 +
                if event_ref.role.xml_str() == self.list[0]:
 +
                    return True
 +
        return False
 +
</pre>
  
 
== Publishing a new Filter Rule ==
 
== Publishing a new Filter Rule ==
Line 35: Line 210:
 
== See also ==
 
== See also ==
 
* Developer documentation
 
* Developer documentation
 +
** [https://gramps-project.org/docs/index.html Gramps core code docs]
 
** [[Gramps_Data_Model|Gramps Data Model]]
 
** [[Gramps_Data_Model|Gramps Data Model]]
 
** [[Addons_development|Addons development]]
 
** [[Addons_development|Addons development]]
Line 40: Line 216:
 
** [[Getting_started_with_Gramps_development|Getting started with Gramps development]]
 
** [[Getting_started_with_Gramps_development|Getting started with Gramps development]]
 
** [https://github.com/gramps-project/gramps/tree/master/gramps/gen/filters/rules Built-in rule definitions]
 
** [https://github.com/gramps-project/gramps/tree/master/gramps/gen/filters/rules Built-in rule definitions]
 +
** [https://github.com/gramps-project/addons-source/tree/master/FilterRules FilterRules add-on rule definitions]
 +
** [https://github.com/gramps-project/addons-source/tree/master/FilterRules2 FilterRules2 add-on rule definitions]
 +
 
*[[Gramps_Glossary#filter|Filter]] Gramps Glossary definition
 
*[[Gramps_Glossary#filter|Filter]] Gramps Glossary definition
 
+
*based on the [https://discourse.gramps-project.org/ Gramps-users Gramps Discourse forum] archived threads:
*based on the [https://sourceforge.net/p/gramps/mailman/gramps-users/ Gramps Discourse forum] archived threads:
+
** [https://gramps.discourse.group/t/tree-vivisection-experiments-with-the-isotammi-supertool/1621 Tree vivisection experiments with the Isotammi SuperTool]
 +
** [https://www.geneanet.org/forum/viewtopic.php?p=2032470#p2032470 Je kife le SuperTool!] (French: I love the SuperTool! on Geneanet)
 +
** [https://gramps.discourse.group/t/a-little-answer-to-geps-015-using-supertool/1771 A little answer to GEPS 015 (Repository Research Support) using Supertool]
 +
** [https://gramps.discourse.group/t/how-is-the-relationships-view-so-responsive/2802 How is the Relationships view so responsive?]
  
 
<!--
 
<!--
*based on the [https://discourse.gramps-project.org/ Gramps-users] archived threads:
+
*based on the [https://sourceforge.net/p/gramps/mailman/gramps-users/ Gramps Users maillist] archived threads:
 
:[https://sourceforge.net/p/gramps/mailman/message/36617953/ The Group As name override]  
 
:[https://sourceforge.net/p/gramps/mailman/message/36617953/ The Group As name override]  
 
:[https://sourceforge.net/p/gramps/mailman/search/?q=%22unify+similar+surmanes+%3F%3F%22&mail_list=all unify similar surmanes &#91;sic&#93; thread]
 
:[https://sourceforge.net/p/gramps/mailman/search/?q=%22unify+similar+surmanes+%3F%3F%22&mail_list=all unify similar surmanes &#91;sic&#93; thread]
 
:[https://sourceforge.net/p/gramps/mailman/search/?q=%22Group+As+name%22 threads with "Group As name"]
 
:[https://sourceforge.net/p/gramps/mailman/search/?q=%22Group+As+name%22 threads with "Group As name"]
 
-->
 
-->
 
 
* In [https://gramps-project.org/bugs/view_all_bug_page.php in MantisBT] bug reporter for Gramps
 
* In [https://gramps-project.org/bugs/view_all_bug_page.php in MantisBT] bug reporter for Gramps
** Feature Requests for add-on custom filter Rules. (Filter for "filter, rule")  
+
** Feature Requests: search for add-on custom filter Rules. (Filter for "filter, rule")  
 
** {{bug|0011689}}: [GrampsAIO-5.1.2-new_libs_win64] Active and Default Person filter rules
 
** {{bug|0011689}}: [GrampsAIO-5.1.2-new_libs_win64] Active and Default Person filter rules
  
 
{{DEFAULTSORT:How do I...new category location|noreplace}}
 
{{DEFAULTSORT:How do I...new category location|noreplace}}
[[Category:Tutorial]]
+
[[Category:Tutorials]]
 
[[Category:WikiContributors]]
 
[[Category:WikiContributors]]
[[Category:How do I...]]
+
[[Category:Developers/Tutorials]]
  
 
<!--
 
<!--
Line 194: Line 375:
 
{{man note|Example Note |Notes text.}}
 
{{man note|Example Note |Notes text.}}
 
{{man warn|1=WarningTitle/Heading |2=warning text }}</onlyinclude>
 
{{man warn|1=WarningTitle/Heading |2=warning text }}</onlyinclude>
 
 
-->
 
-->

Latest revision as of 00:48, 1 December 2023

Gramps-notes.png

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


Custom Filters are built upon Query Rules. Sometimes a filter rule has not been provided to search the part of the Tree desired. Or the existing Rules can not be combined to isolate the desired part of the Tree. If those particular branches and leaves must be repeatedly isolated, building a query rule might be the next logical step.

Query Rules abstract the underlying complexity of the query and provides a higher-level, simpler interface for users to define search criteria without needing to understand the intricate details of the actual database query language.


coding style guide (placeholder)

In various rules that allow a Person ID to be selected as a parameter value, both built-in rules & add-on rules use inconsistent placeholders:

  • <Id>
  • <id>
  • <person>

It would be better if they were harmonized.

I suspect any variant of <ID> would ambiguous because sometimes these rules (while needing a Person Gramps ID) are in different category custom rules.

What should the standard nomenclature be for the rule names, descriptions & documentation?

Using add-ons to design and test flight Filter Rule

Designing and optimizing a quality query can be challenging. Even a slow rough-cut query is acceptable for a single-use. But clean and fast code is vital to a frequently used add-on Filter Rule.

There are some power tool add-ons to help when designing queries, testing them and optimize their runtimes.

Particularly, using SuperTool design a rough query, the Query Gramplet to experiment with optimizations, the Generic custom rules to commit the query to a something usable with Custom Filters, and FilterParams to tune is one way to use add-ons in concert.

Converting a query to an add-on Filter Rule

Sample Gramps Plug-in Registration file

hasrolerule.gpr.py

#
# GPR (Gramps plug-in Registration) of a Python module
#    for Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2018  Paul Culley
#
# 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
"""
Filter rule to match an Event Role with a particular value.
"""

register(RULE,
         id='HasPersonEventRole',
         name=_("People with events with a selected role"),
         description=_("Matches people with an event with a selected role"),
         version='0.0.14',
         authors=["Paul Culley"],
         authors_email=["[email protected]"],
         gramps_target_version='5.1',
         status=STABLE,
         fname="hasrolerule.py",
         ruleclass='HasPersonEventRole',  # must be rule class name
         namespace='Person',  # one of the primary object classes
         )

register(RULE,
         id='HasFamilyEventRole',
         name=_("Families with events with a selected role"),
         description=_("Matches families with an event with a selected role"),
         version='0.0.14',
         authors=["Paul Culley"],
         authors_email=["[email protected]"],
         gramps_target_version='5.1',
         status=STABLE,
         fname="hasrolerule.py",
         ruleclass='HasFamilyEventRole',  # must be rule class name
         namespace='Family',  # one of the primary object classes
         )

Sample Gramps Plug-in source file

hasrolerule.py

Filenames or Filenames

# 
#  
# plug-in Python module
#    for Gramps - a GTK+/GNOME based genealogy program
# 
# Copyright (C) 2018  Paul Culley
# 
# 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.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# 

"""
Filter rule to match persons with a particular event.
"""
# -------------------------------------------------------------------------
# 
# Standard Python modules
# 
# -------------------------------------------------------------------------

# -------------------------------------------------------------------------
# 
# Gramps modules
# 
# -------------------------------------------------------------------------
from gramps.gen.lib.eventroletype import EventRoleType
from gramps.gui.editors.filtereditor import MySelect, MyBoolean
from gramps.gen.filters.rules import Rule
from gramps.gen.const import GRAMPS_LOCALE as glocale
try:
    _trans = glocale.get_addon_translator(__file__)
except ValueError:
    _trans = glocale.translation
_ = _trans.gettext


class Roletype(MySelect):
    """ Provide a Role type selector """
    def __init__(self, db):
        MySelect.__init__(self, EventRoleType, db.get_event_roles())


class NoMatch(MyBoolean):
    """ Provide a negation switch """
    def __init__(self, db):
        MyBoolean.__init__(self, _("Does NOT match with selected Role"))
        self.set_tooltip_text(_("Finds the items that don't have event Roles "
                                "of the selected type."))
# -------------------------------------------------------------------------
# 
# HasEvent
# 
# -------------------------------------------------------------------------


class HasPersonEventRole(Rule):
    """Rule that checks for a person with a selected event role"""

    labels = [(_('Role'), Roletype),
              (_('Inverse'), NoMatch)]
    name = _('People with events with the <role>')
    description = _("Matches people with an event with a selected role")
    category = _('Event filters')

    def apply(self, dbase, person):
        if not self.list[0]:
            return False
        for event_ref in person.get_event_ref_list():
            if not event_ref:
                continue
            if self.list[1] == '1':
                if event_ref.role.xml_str() != self.list[0]:
                    return True
            else:
                if event_ref.role.xml_str() == self.list[0]:
                    return True
        return False


class HasFamilyEventRole(Rule):
    """Rule that checks for a family with a selected event role"""

    labels = [(_('Role'), Roletype),
              (_('Inverse'), NoMatch)]
    name = _('Families with events with the <role>')
    description = _("Matches families with an event with a selected role")
    category = _('Event filters')

    def apply(self, dbase, family):
        if not self.list[0]:
            return False
        for event_ref in family.get_event_ref_list():
            if not event_ref:
                continue
            if self.list[1] == '1':
                if event_ref.role.xml_str() != self.list[0]:
                    return True
            else:
                if event_ref.role.xml_str() == self.list[0]:
                    return True
        return False

Publishing a new Filter Rule

Update the Rule Expansions wiki page

See also

  • In in MantisBT bug reporter for Gramps
    • Feature Requests: search for add-on custom filter Rules. (Filter for "filter, rule")
    • 0011689: [GrampsAIO-5.1.2-new_libs_win64] Active and Default Person filter rules