=> attention ce script n'est probablement pas exempt de bug... je n'ai pas détecté de problème majeurs mais l'utilisation à vos risques et périls évidemment ) d'autant que ça fait une quinzaine d'année que je n'ai pas touché une ligne de code donc... c'est largement perfectible
gramps\plugins\tool\AddSosaAttrib.gpr.py
Code: Alles auswählen
#
#
"""Add/Remove a SOSA Attribute to people"""
register(TOOL,
id = 'AddSosaAttrib',
name = _("Add/Remove Sosa Attribute Tool"),
description = _("Add or remove Sosa as an attribute from people"),
version = '0.0.0',
gramps_target_version = "5.1",
status = STABLE,
fname = 'AddSosaAttrib.py',
authors = ["LV"],
authors_email = ["[email protected]"],
category = TOOL_DBPROC,
toolclass = 'AddSosa',
optionclass = 'AddSosaOptions',
tool_modes = [TOOL_MODE_GUI],
)
Code: Alles auswählen
#
#
"""Add sosa number in a tag on people"""
# -------------------------------------------------
#
# GRAMPS modules
#
# -------------------------------------------------
from gramps.gui.plug import MenuToolOptions, PluginWindows
from gramps.gen.plug.menu import FilterOption, TextOption, PersonOption, BooleanOption, NumberOption
from gramps.gen.db import DbTxn
from gramps.gui.dialog import OkDialog, WarningDialog
from gramps.gen.filters import CustomFilters, GenericFilterFactory, rules
from gramps.gen.lib import ChildRefType
from gramps.gen.lib import Tag, Attribute
#------------------------------------------------------------------------
# Internationalisation
#------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
try:
_trans = glocale.get_addon_translator(__file__)
except ValueError:
_trans = glocale.translation
_ = _trans.gettext
#------------------------------------------------------------------------
#
# AddSosaOptions
#
#------------------------------------------------------------------------
class AddSosaOptions(MenuToolOptions):
"""
Defines options and provides handling interface.
"""
def __init__(self, name, person_id=None, dbstate=None):
self.db = dbstate.get_database()
MenuToolOptions.__init__(self, name, person_id, dbstate)
# def get_subject(self):
# """ Return a string that describes the subject of the report. """
# gid = self.__pid.get_value()
# person = self.__db.get_person_from_gramps_id(gid)
# return _nd.display(person)
def add_menu_options(self, menu):
"""
Add options to the menu for the ancestor report.
"""
category_name = _("Tool Options")
# Add or remove tags menu option
self.add_remove = FilterOption(_("Add/Remove"), 0)
self.add_remove.set_help(_("Add or remove Sosa attributes from objects."))
self.add_remove.set_items([(0, _("Add Sosa Attributes")), (1, _("Remove Sosa Attributes"))])
menu.add_option(category_name, "add_remove", self.add_remove)
self.__pid = PersonOption(_("Center Person"))
self.__pid.set_help(_("The center person for applying sosa (sosa=1 person)"))
menu.add_option(category_name, "pid", self.__pid)
maxgen = NumberOption(_("Generations"), 50, 1, 100)
maxgen.set_help(
_("The number of generations to apply sosa"))
menu.add_option(category_name, "maxgen", maxgen)
self.__filter_options(menu)
def __filter_options(self, menu):
"""Menu Options for filter option tab."""
self.filter_dict = {}
# get all filter rules, used for generic filters
all_persons = rules.person.Everyone([])
# create a list used for menu filter option creation later
lst = [(_("Person Filter"), 'Person', _("Persons"), all_persons)]
for entry in lst:
# create a filter option for each category e.g. person, events
# filter option is a combination of custom filters and
# a generic filter for all objects of one category
filter_name = FilterOption(entry[0], 0)
menu.add_option(_("Filter options"),
entry[1].lower(),
filter_name)
self.filter_dict[entry[1]] = filter_name
# custom filter:
filter_list = CustomFilters.get_filters(entry[1])
# generic filter:
GenericFilter = GenericFilterFactory(entry[1])
all_filter = GenericFilter()
all_filter.set_name(_("All %s") % (entry[2]))
all_filter.add_rule(entry[3])
# only add the generic filter if it isn't already in the menu
all_filter_in_list = False
for fltr in filter_list:
if fltr.get_name() == all_filter.get_name():
all_filter_in_list = True
if not all_filter_in_list:
filter_list.insert(0, all_filter)
# add the list of custom and generic filters
# to the filter option
self.filter_dict[entry[1]].set_filters(filter_list)
# ----------------------------------------------------------------------------
#
# Tool Class
#
# ----------------------------------------------------------------------------
class AddSosa(PluginWindows.ToolManagedWindowBatch):
"""Add Sosa Tag Tool."""
def get_title(self):
"""Window title."""
return _("Add/Remove Sosa Attribute Tool")
def initial_frame(self):
"""Category tab title."""
return _("Options")
def run(self):
"""Run function of Remove attribute Tool."""
self.db = self.dbstate.get_database()
self.remove = bool(self.__opt_by_name('add_remove').get_value())
self.__menu_opt_handling('person')
def __opt_by_name(self, opt_name):
"""Get an option by its name."""
return self.options.menu.get_option_by_name(opt_name)
def __menu_opt_handling(self, category):
"""General menu option handling."""
self.map = {}
iter_ = list(self.db.method('iter_%s_handles', category)())
if iter_ == []:
txt = _("No %s objects were found in database." % category)
WarningDialog(_("WARNING"), txt, parent=self.window)
return # stop the tool
filter_opt = self.__opt_by_name(category)
filter_ = filter_opt.get_filter()
objects = filter_.apply(self.dbstate.db, iter_)
self.max_generations = self.__opt_by_name('maxgen').get_value()
self.__addsosa_from(objects, category)
def SosaLoop(self, person_handle, index, generation=1):
"""
Recursive function to walk back all parents of the current person.
When max_generations are hit, we stop the traversal.
"""
# check for end of the current recursion level. This happens
# if the person handle is None, or if the max_generations is hit
if not person_handle or generation > self.max_generations:
return
# store the person in the map based off their index number
# which is passed to the routine.
self.map[index] = person_handle
# retrieve the Person instance from the database from the
# passed person_handle and find the parents from the list.
# Since this report is for natural parents (birth parents),
# we have to handle that parents may not
person = self.db.get_person_from_handle(person_handle)
if person is None:
return
father_handle = None
mother_handle = None
for family_handle in person.get_parent_family_handle_list():
family = self.db.get_family_from_handle(family_handle)
# filter the child_ref_list to find the reference that matches
# the passed person. There should be exactly one, but there is
# nothing that prevents the same child in the list multiple times.
ref = [ c for c in family.get_child_ref_list()
if c.get_reference_handle() == person_handle]
if ref:
# If the father_handle is not defined and the relationship is
# BIRTH, then we have found the birth father. Same applies to
# the birth mother. If for some reason, the we have multiple
# people defined as the birth parents, we will select based on
# priority in the list
if not father_handle and \
ref[0].get_father_relation() == ChildRefType.BIRTH:
father_handle = family.get_father_handle()
if not mother_handle and \
ref[0].get_mother_relation() == ChildRefType.BIRTH:
mother_handle = family.get_mother_handle()
# Recursively call the function. It is okay if the handle is None,
# since routine handles a handle of None
self.SosaLoop(father_handle, index*2, generation+1)
self.SosaLoop(mother_handle, (index*2)+1, generation+1)
def __addsosa_from(self, objects, category):
"""Add (or remove) sosa as a tag to persons"""
counter = [0, 0]
num = len(objects)
name = _("Add/Remove Sosa Tag Tool")
pid = self.__opt_by_name('pid').get_value()
self.center_person = self.db.get_person_from_gramps_id(pid)
#build an array with all sosa ancestr, with corresponding sosa number
self.SosaLoop(self.center_person.get_handle(), 1)
with DbTxn(name, self.db, batch=True) as self.trans:
self.db.disable_signals()
self.progress.set_pass(_('Process tags...'), num)
#loop on collected individuals to assign or remove sosa attributes
for key in sorted(self.map):
person = self.db.get_person_from_handle(self.map[key])
SosaValue = '#%09d' % key
if self.remove:
for attr in person.get_attribute_list():
if attr.get_type() == 'SOSA':
person.remove_attribute(attr)
# Update global attribute list:
self.db.individual_attributes.update([str(attr.type)])
break
self.db.method("commit_%s", category)(person, self.trans)
elif not self.remove:
if person is None:
continue
attr = Attribute()
attr.set_type('SOSA')
attr.set_value(SosaValue)
person.add_attribute(attr)
# Update global attribute list:
if attr.type.is_custom() and str(attr.type):
self.db.individual_attributes.update([str(attr.type)])
self.db.method("commit_%s", category)(person, self.trans)
self.db.enable_signals()
self.db.request_rebuild()