diff --git a/gramps/gen/filters/_genericfilter.py b/gramps/gen/filters/_genericfilter.py index 02dcfd2b82b..10e73822207 100644 --- a/gramps/gen/filters/_genericfilter.py +++ b/gramps/gen/filters/_genericfilter.py @@ -24,6 +24,9 @@ Package providing filtering framework for Gramps. """ +import logging +import time + # ------------------------------------------------------------------------ # # Gramps imports @@ -41,8 +44,10 @@ from ..lib.tag import Tag from ..lib.serialize import from_dict from ..const import GRAMPS_LOCALE as glocale +from .rules import Rule _ = glocale.translation.gettext +LOG = logging.getLogger(".filter.optimize") # ------------------------------------------------------------------------- @@ -53,7 +58,8 @@ class GenericFilter: """Filter class that consists of several rules.""" - logical_functions = ["or", "and", "xor", "one"] + logical_functions = ["and", "or", "one"] + table = "person" def __init__(self, source=None): if source: @@ -71,11 +77,11 @@ def __init__(self, source=None): self.logical_op = "and" self.invert = False - def match(self, handle, db): + def match(self, data, db): """ Return True or False depending on whether the handle matches the filter. """ - if self.apply(db, [handle]): + if self.apply_to_one(db, data): return True else: return False @@ -89,10 +95,7 @@ def set_logical_op(self, val): if val in GenericFilter.logical_functions: self.logical_op = val else: - self.logical_op = "and" - - def get_logical_op(self): - return self.logical_op + raise Exception("invalid operator: %r" % val) def set_invert(self, val): self.invert = bool(val) @@ -139,99 +142,194 @@ def find_from_handle(self, db, handle): def get_number(self, db): return db.get_number_of_people() - def check_func(self, db, id_list, task, user=None, tupleind=None, tree=False): + def walk_filters(self, filter, parent_invert, result): + """ + Walk all of the filters/rules and get + rules with maps + """ + current_invert = parent_invert if not filter.invert else not parent_invert + LOG.debug( + "walking, filter: %s, invert=%s, parent_invert=%s", + filter, + filter.invert, + parent_invert, + ) + rules = [] + for item in filter.flist: + if hasattr(item, "find_filter"): + rule_filter = item.find_filter() + if rule_filter is not None: + self.walk_filters( + rule_filter, + current_invert, + result, + ) + elif hasattr(item, "map"): + rules.append(item.map) + if rules: + LOG.debug( + "filter %s: parent_invert=%s, invert=%s, op=%s, number of maps=%s", + filter, + parent_invert, + filter.invert, + filter.logical_op, + len(rules), + ) + result.append( + ( + current_invert, + filter.logical_op, + rules, + ) + ) + + def apply_logical_op_to_all( + self, db, id_list, apply_logical_op, user=None, tupleind=None, tree=False + ): final_list = [] - if user: - user.begin_progress(_("Filter"), _("Applying ..."), self.get_number(db)) + + def intersection(sets): + if sets: + result = sets[0] + for s in sets[1:]: + result = result.intersection(s) + return result + else: + return set() + + def union(sets): + if sets: + result = sets[0] + for s in sets[1:]: + result = result.union(s) + return result + else: + return set() + + # ------------------------------------------------------ + # Optimiziation + # ------------------------------------------------------ + all_maps = [] + self.walk_filters(self, False, all_maps) + LOG.debug("number of maps to consider: %s", len(all_maps)) + handles_in = None + handles_out = set() + # Get all positive non-inverted maps + for inverted, logical_op, maps in all_maps: + if logical_op == "and" and not inverted: + LOG.debug("optimizer positive match!") + if handles_in is None: + handles_in = intersection(maps) + else: + handles_in = intersection([handles_in] + maps) + + # Get all inverted maps: + for inverted, logical_op, maps in all_maps: + if logical_op == "and" and inverted: + LOG.debug("optimizer inverted match!") + handles_out = union([handles_out] + maps) + + if handles_in is not None: + handles_in = handles_in - handles_out + + # ------------------------------------------------------ + LOG.debug("optimizer handles_in: %s", len(handles_in) if handles_in else 0) if id_list is None: - with self.get_tree_cursor(db) if tree else self.get_cursor(db) as cursor: - for handle, data in cursor: - person = from_dict(data) + if handles_in is not None: + if user: + user.begin_progress(_("Filter"), _("Applying ..."), len(handles)) + + # Use these rather than going through entire database + for handle in handles_in: if user: user.step_progress() - if task(db, person) != self.invert: - final_list.append(handle) + + if handle is None: + continue + + json_data = self.get_raw_data(db, handle) + + if apply_logical_op(db, json_data, self.flist) != self.invert: + final_list.append(json_data["handle"]) + + else: + with ( + self.get_tree_cursor(db) if tree else self.get_cursor(db) + ) as cursor: + if user: + user.begin_progress( + _("Filter"), _("Applying ..."), self.get_number(db) + ) + + for handle, data in cursor: + if user: + user.step_progress() + + if handle in handles_out: + continue + + if apply_logical_op(db, data, self.flist) != self.invert: + final_list.append(handle) + else: + if user: + user.begin_progress(_("Filter"), _("Applying ..."), len(id_list)) for data in id_list: - if tupleind is None: - handle = data - else: - handle = data[tupleind] - person = self.find_from_handle(db, handle) if user: user.step_progress() - if task(db, person) != self.invert: - final_list.append(data) - if user: - user.end_progress() - return final_list - def check_and(self, db, id_list, user=None, tupleind=None, tree=False): - final_list = [] - flist = self.flist - if user: - user.begin_progress(_("Filter"), _("Applying ..."), self.get_number(db)) - if id_list is None: - with self.get_tree_cursor(db) if tree else self.get_cursor(db) as cursor: - for handle, data in cursor: - person = from_dict(data) - if user: - user.step_progress() - val = all(rule.apply(db, person) for rule in flist) - if val != self.invert: - final_list.append(handle) - else: - for data in id_list: if tupleind is None: handle = data else: handle = data[tupleind] - person = self.find_from_handle(db, handle) - if user: - user.step_progress() - val = all(rule.apply(db, person) for rule in flist if person) - if val != self.invert: + + if handles_in is not None: + if handle not in handles_in: + continue + elif handle in handles_out: + continue + + json_data = self.get_raw_data(db, handle) + + if apply_logical_op(db, json_data, self.flist) != self.invert: final_list.append(data) + if user: user.end_progress() - return final_list - - def check_or(self, db, id_list, user=None, tupleind=None, tree=False): - return self.check_func(db, id_list, self.or_test, user, tupleind, tree=False) - - def check_one(self, db, id_list, user=None, tupleind=None, tree=False): - return self.check_func(db, id_list, self.one_test, user, tupleind, tree=False) - def check_xor(self, db, id_list, user=None, tupleind=None, tree=False): - return self.check_func(db, id_list, self.xor_test, user, tupleind, tree=False) + return final_list - def xor_test(self, db, person): - test = False - for rule in self.flist: - test = test ^ rule.apply(db, person) - return test + def and_test(self, db, data, flist): + return all(rule.apply_to_one(db, data) for rule in flist) - def one_test(self, db, person): + def one_test(self, db, data, flist): found_one = False - for rule in self.flist: - if rule.apply(db, person): + for rule in flist: + if rule.apply_to_one(db, data): if found_one: return False # There can be only one! found_one = True return found_one - def or_test(self, db, person): - return any(rule.apply(db, person) for rule in self.flist) + def or_test(self, db, data, flist): + return any(rule.apply_to_one(db, data) for rule in flist) - def get_check_func(self): - try: - m = getattr(self, "check_" + self.logical_op) - except AttributeError: - m = self.check_and - return m + def get_logical_op(self): + return self.logical_op - def check(self, db, handle): - return self.get_check_func()(db, [handle]) + def apply_to_one(self, db, data): + """ + Filter-level apply rules to single data item. + """ + if self.logical_op == "and": + res = self.and_test(db, data, self.flist) + elif self.logical_op == "or": + res = self.or_test(db, data, self.flist) + elif self.logical_op == "one": + res = self.one_test(db, data, self.flist) + else: + raise Exception("invalid operator: %r" % self.logical_op) + return res != self.invert def apply(self, db, id_list=None, tupleind=None, user=None, tree=False): """ @@ -250,16 +348,44 @@ def apply(self, db, id_list=None, tupleind=None, user=None, tree=False): if id_list not given, all items in the database that match the filter are returned as a list of handles """ - m = self.get_check_func() + if user: + user.begin_progress(_("Filter"), _("Preparing ..."), len(self.flist) + 1) + # Give the progress popup some time to be visible: + time.sleep(0.1) + for rule in self.flist: + if user: + user.step_progress() rule.requestprepare(db, user) - res = m(db, id_list, user, tupleind, tree) + + if user: + user.end_progress() + + if self.logical_op == "and": + apply_logical_op = self.and_test + elif self.logical_op == "or": + apply_logical_op = self.or_test + elif self.logical_op == "one": + apply_logical_op = self.one_test + else: + raise Exception("invalid operator: %r" % self.logical_op) + + res = self.apply_logical_op_to_all( + db, id_list, apply_logical_op, user, tupleind, tree + ) + for rule in self.flist: rule.requestreset() + return res + def get_raw_data(self, db, handle): + return db.get_raw_person_data(handle) + class GenericFamilyFilter(GenericFilter): + tables = "family" + def __init__(self, source=None): GenericFilter.__init__(self, source) @@ -275,8 +401,13 @@ def find_from_handle(self, db, handle): def get_number(self, db): return db.get_number_of_families() + def get_raw_data(self, db, handle): + return db.get_raw_family_data(handle) + class GenericEventFilter(GenericFilter): + table = "event" + def __init__(self, source=None): GenericFilter.__init__(self, source) @@ -292,8 +423,13 @@ def find_from_handle(self, db, handle): def get_number(self, db): return db.get_number_of_events() + def get_raw_data(self, db, handle): + return db.get_raw_event_data(handle) + class GenericSourceFilter(GenericFilter): + table = "source" + def __init__(self, source=None): GenericFilter.__init__(self, source) @@ -309,8 +445,13 @@ def find_from_handle(self, db, handle): def get_number(self, db): return db.get_number_of_sources() + def get_raw_data(self, db, handle): + return db.get_raw_source_data(handle) + class GenericCitationFilter(GenericFilter): + table = "citation" + def __init__(self, source=None): GenericFilter.__init__(self, source) @@ -329,8 +470,13 @@ def find_from_handle(self, db, handle): def get_number(self, db): return db.get_number_of_citations() + def get_raw_data(self, db, handle): + return db.get_raw_citation_data(handle) + class GenericPlaceFilter(GenericFilter): + table = "place" + def __init__(self, source=None): GenericFilter.__init__(self, source) @@ -349,8 +495,13 @@ def find_from_handle(self, db, handle): def get_number(self, db): return db.get_number_of_places() + def get_raw_data(self, db, handle): + return db.get_raw_place_data(handle) + class GenericMediaFilter(GenericFilter): + table = "media" + def __init__(self, source=None): GenericFilter.__init__(self, source) @@ -366,8 +517,13 @@ def find_from_handle(self, db, handle): def get_number(self, db): return db.get_number_of_media() + def get_raw_data(self, db, handle): + return db.get_raw_media_data(handle) + class GenericRepoFilter(GenericFilter): + table = "repository" + def __init__(self, source=None): GenericFilter.__init__(self, source) @@ -383,8 +539,13 @@ def find_from_handle(self, db, handle): def get_number(self, db): return db.get_number_of_repositories() + def get_raw_data(self, db, handle): + return db.get_raw_repository_data(handle) + class GenericNoteFilter(GenericFilter): + table = "note" + def __init__(self, source=None): GenericFilter.__init__(self, source) @@ -400,6 +561,9 @@ def find_from_handle(self, db, handle): def get_number(self, db): return db.get_number_of_notes() + def get_raw_data(self, db, handle): + return db.get_raw_note_data(handle) + def GenericFilterFactory(namespace): if namespace == "Person": diff --git a/gramps/gen/filters/rules/_changedsincebase.py b/gramps/gen/filters/rules/_changedsincebase.py index 3cc57b1ed92..5e1a955f787 100644 --- a/gramps/gen/filters/rules/_changedsincebase.py +++ b/gramps/gen/filters/rules/_changedsincebase.py @@ -101,8 +101,8 @@ def prepare(self, db, user): if self.list[1]: self.before = self.time_str_to_sec(self.list[1]) - def apply(self, db, obj): - obj_time = obj.get_change_time() + def apply_to_one(self, db, data): + obj_time = data["change"] if self.since: if obj_time < self.since: return False diff --git a/gramps/gen/filters/rules/_everything.py b/gramps/gen/filters/rules/_everything.py index 3ec66484367..6bca78ad56d 100644 --- a/gramps/gen/filters/rules/_everything.py +++ b/gramps/gen/filters/rules/_everything.py @@ -50,5 +50,5 @@ class Everything(Rule): def is_empty(self): return True - def apply(self, db, obj): + def apply_to_one(self, db, data): return True diff --git a/gramps/gen/filters/rules/_hasattributebase.py b/gramps/gen/filters/rules/_hasattributebase.py index 1b29aa2530d..4063928a269 100644 --- a/gramps/gen/filters/rules/_hasattributebase.py +++ b/gramps/gen/filters/rules/_hasattributebase.py @@ -63,10 +63,11 @@ def prepare(self, db, user): self.attribute_type = AttributeType() self.attribute_type.set_from_xml_str(self.list[0]) - def apply(self, db, obj): + def apply_to_one(self, db, data): """ Apply the rule. Return True if a match. """ + obj = self.get_object(data) if self.attribute_type: for attribute in obj.get_attribute_list(): name_match = attribute.get_type() == self.attribute_type diff --git a/gramps/gen/filters/rules/_hascitationbase.py b/gramps/gen/filters/rules/_hascitationbase.py index 0d2c0cfcff7..352e3682f56 100644 --- a/gramps/gen/filters/rules/_hascitationbase.py +++ b/gramps/gen/filters/rules/_hascitationbase.py @@ -62,7 +62,8 @@ def prepare(self, db, user): except: pass - def apply(self, dbase, object): + def apply_to_one(self, dbase, data): + object = self.get_object(data) for citation_handle in object.get_citation_list(): citation = dbase.get_citation_from_handle(citation_handle) if self._apply(dbase, citation): diff --git a/gramps/gen/filters/rules/_haseventbase.py b/gramps/gen/filters/rules/_haseventbase.py index dff30f83cba..40c63bbe592 100644 --- a/gramps/gen/filters/rules/_haseventbase.py +++ b/gramps/gen/filters/rules/_haseventbase.py @@ -71,10 +71,11 @@ def prepare(self, db, user): except: pass - def apply(self, db, event): + def apply_to_one(self, db, data): """ Apply the rule. Return True if a match. """ + event = self.get_object(data) if self.event_type: if self.event_type.is_custom() and self.use_regex: if self.regex[0].search(str(event.type)) is None: diff --git a/gramps/gen/filters/rules/_hasgallerybase.py b/gramps/gen/filters/rules/_hasgallerybase.py index 5bf5c61bee2..b2565bc9a17 100644 --- a/gramps/gen/filters/rules/_hasgallerybase.py +++ b/gramps/gen/filters/rules/_hasgallerybase.py @@ -60,8 +60,8 @@ def prepare(self, db, user): self.userSelectedCount = int(self.list[0]) - def apply(self, db, obj): - count = len(obj.get_media_list()) + def apply_to_one(self, db, data): + count = len(data["media_list"]) if self.count_type == 0: # "less than" return count < self.userSelectedCount elif self.count_type == 2: # "greater than" diff --git a/gramps/gen/filters/rules/_hasgrampsid.py b/gramps/gen/filters/rules/_hasgrampsid.py index fbfb5a8262a..4c8c1b10898 100644 --- a/gramps/gen/filters/rules/_hasgrampsid.py +++ b/gramps/gen/filters/rules/_hasgrampsid.py @@ -49,9 +49,9 @@ class HasGrampsId(Rule): description = "Matches objects with a specified Gramps ID" category = _("General filters") - def apply(self, db, obj): + def apply_to_one(self, db, data): """ apply the rule on the obj. return true if the rule passes, false otherwise. """ - return obj.gramps_id == self.list[0] + return data["gramps_id"] == self.list[0] diff --git a/gramps/gen/filters/rules/_hasldsbase.py b/gramps/gen/filters/rules/_hasldsbase.py index 8e29ed2c4fa..a1662a13ffa 100644 --- a/gramps/gen/filters/rules/_hasldsbase.py +++ b/gramps/gen/filters/rules/_hasldsbase.py @@ -63,7 +63,8 @@ def prepare(self, db, user): self.userSelectedCount = int(self.list[0]) - def apply(self, db, obj): + def apply_to_one(self, db, data): + obj = self.get_object(data) count = len(obj.get_lds_ord_list()) if self.count_type == 0: # "less than" return count < self.userSelectedCount diff --git a/gramps/gen/filters/rules/_hasnotebase.py b/gramps/gen/filters/rules/_hasnotebase.py index 441bc582e0a..bbd9a00333e 100644 --- a/gramps/gen/filters/rules/_hasnotebase.py +++ b/gramps/gen/filters/rules/_hasnotebase.py @@ -69,8 +69,8 @@ def prepare(self, db, user): self.userSelectedCount = int(self.list[0]) - def apply(self, db, obj): - count = len(obj.get_note_list()) + def apply_to_one(self, db, data): + count = len(data["note_list"]) if self.count_type == 0: # "less than" return count < self.userSelectedCount elif self.count_type == 2: # "greater than" diff --git a/gramps/gen/filters/rules/_hasnoteregexbase.py b/gramps/gen/filters/rules/_hasnoteregexbase.py index 50677efd96a..38018bc7c09 100644 --- a/gramps/gen/filters/rules/_hasnoteregexbase.py +++ b/gramps/gen/filters/rules/_hasnoteregexbase.py @@ -51,8 +51,8 @@ class HasNoteRegexBase(Rule): category = _("General filters") allow_regex = True - def apply(self, db, person): - for handle in person.get_note_list(): + def apply_to_one(self, db, data): + for handle in data["note_list"]: note = db.get_note_from_handle(handle) if self.match_substring(0, note.get()): return True diff --git a/gramps/gen/filters/rules/_hasnotesubstrbase.py b/gramps/gen/filters/rules/_hasnotesubstrbase.py index 25b3c3fc878..f308e5dd060 100644 --- a/gramps/gen/filters/rules/_hasnotesubstrbase.py +++ b/gramps/gen/filters/rules/_hasnotesubstrbase.py @@ -46,8 +46,8 @@ class HasNoteSubstrBase(Rule): description = "Matches objects whose notes contain text matching a " "substring" category = _("General filters") - def apply(self, db, person): - notelist = person.get_note_list() + def apply_to_one(self, db, data): + notelist = data["note_list"] for notehandle in notelist: note = db.get_note_from_handle(notehandle) n = note.get() diff --git a/gramps/gen/filters/rules/_hasreferencecountbase.py b/gramps/gen/filters/rules/_hasreferencecountbase.py index c8a6e2977db..f8ec74f25e0 100644 --- a/gramps/gen/filters/rules/_hasreferencecountbase.py +++ b/gramps/gen/filters/rules/_hasreferencecountbase.py @@ -57,11 +57,9 @@ def prepare(self, db, user): self.userSelectedCount = int(self.list[1]) - def apply(self, db, obj): - handle = obj.get_handle() - count = 0 - for item in db.find_backlink_handles(handle): - count += 1 + def apply_to_one(self, db, data): + handle = data["handle"] + count = len(list(db.find_backlink_handles(handle))) if self.count_type == 0: # "less than" return count < self.userSelectedCount diff --git a/gramps/gen/filters/rules/_hassourcebase.py b/gramps/gen/filters/rules/_hassourcebase.py index 024143571ae..8394ad5f200 100644 --- a/gramps/gen/filters/rules/_hassourcebase.py +++ b/gramps/gen/filters/rules/_hassourcebase.py @@ -50,7 +50,8 @@ class HasSourceBase(Rule): category = _("Citation/source filters") allow_regex = True - def apply(self, db, source): + def apply_to_one(self, db, data): + source = self.get_object(data) if not self.match_substring(0, source.get_title()): return False diff --git a/gramps/gen/filters/rules/_hassourcecountbase.py b/gramps/gen/filters/rules/_hassourcecountbase.py index 8b4aab709bc..459bc26bb15 100644 --- a/gramps/gen/filters/rules/_hassourcecountbase.py +++ b/gramps/gen/filters/rules/_hassourcecountbase.py @@ -63,7 +63,8 @@ def prepare(self, db, user): self.userSelectedCount = int(self.list[0]) - def apply(self, db, obj): + def apply_to_one(self, db, data): + obj = self.get_object(data) count = len(obj.get_citation_list()) if self.count_type == 0: # "less than" return count < self.userSelectedCount diff --git a/gramps/gen/filters/rules/_hassourceofbase.py b/gramps/gen/filters/rules/_hassourceofbase.py index 4e04be727fa..44f05533cb2 100644 --- a/gramps/gen/filters/rules/_hassourceofbase.py +++ b/gramps/gen/filters/rules/_hassourceofbase.py @@ -61,7 +61,8 @@ def prepare(self, db, user): except: self.source_handle = None - def apply(self, db, object): + def apply_to_one(self, db, data): + object = self.get_object(data) if not self.source_handle: if self.nosource: # check whether the citation list is empty as a proxy for diff --git a/gramps/gen/filters/rules/_hastagbase.py b/gramps/gen/filters/rules/_hastagbase.py index 9d708776121..d9b2010f74e 100644 --- a/gramps/gen/filters/rules/_hastagbase.py +++ b/gramps/gen/filters/rules/_hastagbase.py @@ -62,10 +62,10 @@ def prepare(self, db, user): if tag is not None: self.tag_handle = tag.get_handle() - def apply(self, db, obj): + def apply_to_one(self, db, data): """ Apply the rule. Return True for a match. """ if self.tag_handle is None: return False - return self.tag_handle in obj.get_tag_list() + return self.tag_handle in data["tag_list"] diff --git a/gramps/gen/filters/rules/_isprivate.py b/gramps/gen/filters/rules/_isprivate.py index 53c2b95a0fa..bd3e804d2c1 100644 --- a/gramps/gen/filters/rules/_isprivate.py +++ b/gramps/gen/filters/rules/_isprivate.py @@ -43,5 +43,5 @@ class IsPrivate(Rule): description = "Matches objects that are indicated as private" category = _("General filters") - def apply(self, db, obj): - return obj.get_privacy() + def apply_to_one(self, db, data): + return data["private"] diff --git a/gramps/gen/filters/rules/_ispublic.py b/gramps/gen/filters/rules/_ispublic.py index 2ffdf608120..180354b743d 100644 --- a/gramps/gen/filters/rules/_ispublic.py +++ b/gramps/gen/filters/rules/_ispublic.py @@ -40,5 +40,5 @@ class IsPublic(Rule): description = "Matches objects that are not indicated as private" category = _("General filters") - def apply(self, db, obj): - return not obj.get_privacy() + def apply_to_one(self, db, data): + return not data["private"] diff --git a/gramps/gen/filters/rules/_matcheseventfilterbase.py b/gramps/gen/filters/rules/_matcheseventfilterbase.py index 9e551392f39..4f8655df7dc 100644 --- a/gramps/gen/filters/rules/_matcheseventfilterbase.py +++ b/gramps/gen/filters/rules/_matcheseventfilterbase.py @@ -61,13 +61,14 @@ def prepare(self, db, user): MatchesFilterBase.prepare(self, db, user) self.MEF_filt = self.find_filter() - def apply(self, db, object): + def apply_to_one(self, db, data): + object = self.get_object(data) if self.MEF_filt is None: return False eventlist = [x.ref for x in object.get_event_ref_list()] for eventhandle in eventlist: # check if event in event filter - if self.MEF_filt.check(db, eventhandle): + if self.MEF_filt.apply_to_one(db, eventhandle): return True return False diff --git a/gramps/gen/filters/rules/_matchesfilterbase.py b/gramps/gen/filters/rules/_matchesfilterbase.py index 208b876e75c..71dd6c29cd5 100644 --- a/gramps/gen/filters/rules/_matchesfilterbase.py +++ b/gramps/gen/filters/rules/_matchesfilterbase.py @@ -85,12 +85,12 @@ def reset(self): for rule in filt.flist: rule.requestreset() - def apply(self, db, obj): + def apply_to_one(self, db, data): if gramps.gen.filters.CustomFilters: filters = gramps.gen.filters.CustomFilters.get_filters_dict(self.namespace) if self.list[0] in filters: filt = filters[self.list[0]] - return filt.check(db, obj.handle) + return filt.apply_to_one(db, data) return False def find_filter(self): diff --git a/gramps/gen/filters/rules/_matchessourceconfidencebase.py b/gramps/gen/filters/rules/_matchessourceconfidencebase.py index ccb9e8eb059..f871c289d3f 100644 --- a/gramps/gen/filters/rules/_matchessourceconfidencebase.py +++ b/gramps/gen/filters/rules/_matchessourceconfidencebase.py @@ -53,7 +53,8 @@ class MatchesSourceConfidenceBase(Rule): ) category = _("Citation/source filters") - def apply(self, db, obj): + def apply_to_one(self, db, data): + obj = self.get_object(data) required_conf = int(self.list[0]) for citation_handle in obj.get_citation_list(): citation = db.get_citation_from_handle(citation_handle) diff --git a/gramps/gen/filters/rules/_matchessourcefilterbase.py b/gramps/gen/filters/rules/_matchessourcefilterbase.py index 1f9e9801749..a471e203289 100644 --- a/gramps/gen/filters/rules/_matchessourcefilterbase.py +++ b/gramps/gen/filters/rules/_matchessourcefilterbase.py @@ -60,13 +60,15 @@ def prepare(self, db, user): MatchesFilterBase.prepare(self, db, user) self.MSF_filt = self.find_filter() - def apply(self, db, object): + def apply_to_one(self, db, data): if self.MSF_filt is None: return False + object = self.get_object(data) for citation_handle in object.get_citation_list(): citation = db.get_citation_from_handle(citation_handle) sourcehandle = citation.get_reference_handle() - if self.MSF_filt.check(db, sourcehandle): + source_data = db.get_raw_source_data(sourcehandle) + if self.MSF_filt.apply_to_one(db, source_data): return True return False diff --git a/gramps/gen/filters/rules/_regexpidbase.py b/gramps/gen/filters/rules/_regexpidbase.py index 14b5c9a687f..e0ffad2fe17 100644 --- a/gramps/gen/filters/rules/_regexpidbase.py +++ b/gramps/gen/filters/rules/_regexpidbase.py @@ -56,5 +56,5 @@ class RegExpIdBase(Rule): category = _("General filters") allow_regex = True - def apply(self, db, obj): - return self.match_substring(0, obj.gramps_id) + def apply_to_one(self, db, data): + return self.match_substring(0, data["gramps_id"]) diff --git a/gramps/gen/filters/rules/_rule.py b/gramps/gen/filters/rules/_rule.py index 0d565dfcc87..610f5b96ffb 100644 --- a/gramps/gen/filters/rules/_rule.py +++ b/gramps/gen/filters/rules/_rule.py @@ -32,6 +32,7 @@ from ...errors import FilterError from ...const import GRAMPS_LOCALE as glocale +from ...lib.serialize import from_dict _ = glocale.translation.gettext @@ -150,10 +151,18 @@ def check(self): """Verify the number of rule values versus the number of rule labels.""" return len(self.list) == len(self.labels) - def apply(self, dummy_db, dummy_person): + def apply_to_one(self, dummy_db, dummy_data): """Apply the rule to some database entry; must be overwritten.""" return True + def get_object(self, data): + """ + Create an object, but only do it once per data. + """ + if "_object" not in data: + data["_object"] = from_dict(data) + return data["_object"] + def display_values(self): """Return the labels and values of this rule.""" l_v = ( diff --git a/gramps/gen/filters/rules/citation/_hascitation.py b/gramps/gen/filters/rules/citation/_hascitation.py index af08fc5a40c..635a51ca9e2 100644 --- a/gramps/gen/filters/rules/citation/_hascitation.py +++ b/gramps/gen/filters/rules/citation/_hascitation.py @@ -61,7 +61,8 @@ def prepare(self, db, user): except: pass - def apply(self, dbase, citation): + def apply_to_one(self, dbase, data): + citation = self.get_object(data) if not self.match_substring(0, citation.get_page()): return False diff --git a/gramps/gen/filters/rules/citation/_hassource.py b/gramps/gen/filters/rules/citation/_hassource.py index 1a63bfcaaf9..f908a1b21ba 100644 --- a/gramps/gen/filters/rules/citation/_hassource.py +++ b/gramps/gen/filters/rules/citation/_hassource.py @@ -52,8 +52,9 @@ class HasSource(HasSourceBase): description = _("Matches citations with a source of a particular " "value") category = _("Source filters") - def apply(self, dbase, citation): - source = dbase.get_source_from_handle(citation.get_reference_handle()) - if HasSourceBase.apply(self, dbase, source): + def apply_to_one(self, dbase, data): + citation = self.get_object(data) + source_data = dbase.get_raw_source_data(citation.get_reference_handle()) + if HasSourceBase.apply_to_one(self, dbase, source_data): return True return False diff --git a/gramps/gen/filters/rules/citation/_hassourceidof.py b/gramps/gen/filters/rules/citation/_hassourceidof.py index de6e07b765e..095ab5a32a9 100644 --- a/gramps/gen/filters/rules/citation/_hassourceidof.py +++ b/gramps/gen/filters/rules/citation/_hassourceidof.py @@ -34,6 +34,7 @@ # # ------------------------------------------------------------------------- from .._hasgrampsid import HasGrampsId +from gramps.gen.lib.serialize import to_dict # ------------------------------------------------------------------------- @@ -49,8 +50,9 @@ class HasSourceIdOf(HasGrampsId): description = _("Matches a citation with a source with a specified Gramps " "ID") category = _("Source filters") - def apply(self, dbase, citation): + def apply_to_one(self, dbase, data): + citation = self.get_object(data) source = dbase.get_source_from_handle(citation.get_reference_handle()) - if HasGrampsId.apply(self, dbase, source): + if HasGrampsId.apply_to_one(self, dbase, to_dict(source)): return True return False diff --git a/gramps/gen/filters/rules/citation/_hassourcenoteregexp.py b/gramps/gen/filters/rules/citation/_hassourcenoteregexp.py index 82ceeb2d4e1..dcd0bdeae5d 100644 --- a/gramps/gen/filters/rules/citation/_hassourcenoteregexp.py +++ b/gramps/gen/filters/rules/citation/_hassourcenoteregexp.py @@ -38,6 +38,7 @@ # # ------------------------------------------------------------------------- from .._hasnoteregexbase import HasNoteRegexBase +from gramps.gen.lib.serialize import to_dict # ------------------------------------------------------------------------- @@ -58,8 +59,9 @@ class HasSourceNoteRegexp(HasNoteRegexBase): ) category = _("Source filters") - def apply(self, db, citation): + def apply_to_one(self, db, data): + citation = self.get_object(data) source = db.get_source_from_handle(citation.get_reference_handle()) - if HasNoteRegexBase.apply(self, db, source): + if HasNoteRegexBase.apply_to_one(self, db, to_dict(source)): return True return False diff --git a/gramps/gen/filters/rules/citation/_matchespagesubstringof.py b/gramps/gen/filters/rules/citation/_matchespagesubstringof.py index f45abf4650c..ec49df97b8f 100644 --- a/gramps/gen/filters/rules/citation/_matchespagesubstringof.py +++ b/gramps/gen/filters/rules/citation/_matchespagesubstringof.py @@ -49,6 +49,6 @@ class MatchesPageSubstringOf(Rule): category = _("General filters") allow_regex = True - def apply(self, db, object): + def apply_to_one(self, db, data): """Apply the filter""" - return self.match_substring(0, object.get_page()) + return self.match_substring(0, data["page"]) diff --git a/gramps/gen/filters/rules/citation/_matchesrepositoryfilter.py b/gramps/gen/filters/rules/citation/_matchesrepositoryfilter.py index a9260647d48..2e2a7a8e759 100644 --- a/gramps/gen/filters/rules/citation/_matchesrepositoryfilter.py +++ b/gramps/gen/filters/rules/citation/_matchesrepositoryfilter.py @@ -63,7 +63,8 @@ def prepare(self, db, user): MatchesFilterBase.prepare(self, db, user) self.MRF_filt = self.find_filter() - def apply(self, db, object): + def apply_to_one(self, db, data): + object = self.get_object(data) if self.MRF_filt is None: return False diff --git a/gramps/gen/filters/rules/citation/_matchessourcefilter.py b/gramps/gen/filters/rules/citation/_matchessourcefilter.py index 0bc9c18fc2c..bbbcf8b35f4 100644 --- a/gramps/gen/filters/rules/citation/_matchessourcefilter.py +++ b/gramps/gen/filters/rules/citation/_matchessourcefilter.py @@ -61,11 +61,11 @@ def prepare(self, db, user): MatchesFilterBase.prepare(self, db, user) self.MRF_filt = self.find_filter() - def apply(self, db, object): + def apply_to_one(self, db, data): if self.MRF_filt is None: return False - source_handle = object.source_handle - if self.MRF_filt.check(db, source_handle): + source_handle = data["source_handle"] + if self.MRF_filt.apply_to_one(db, source_handle): return True return False diff --git a/gramps/gen/filters/rules/citation/_regexpsourceidof.py b/gramps/gen/filters/rules/citation/_regexpsourceidof.py index afa7f2471aa..57cd68dc282 100644 --- a/gramps/gen/filters/rules/citation/_regexpsourceidof.py +++ b/gramps/gen/filters/rules/citation/_regexpsourceidof.py @@ -34,6 +34,7 @@ # # ------------------------------------------------------------------------- from .._regexpidbase import RegExpIdBase +from gramps.gen.lib.serialize import to_dict # ------------------------------------------------------------------------- @@ -54,8 +55,9 @@ class RegExpSourceIdOf(RegExpIdBase): ) category = _("Source filters") - def apply(self, dbase, citation): + def apply_to_one(self, dbase, data): + citation = self.get_object(data) source = dbase.get_source_from_handle(citation.get_reference_handle()) - if RegExpIdBase.apply(self, dbase, source): + if RegExpIdBase.apply_to_one(self, dbase, to_dict(source)): return True return False diff --git a/gramps/gen/filters/rules/event/_hasdata.py b/gramps/gen/filters/rules/event/_hasdata.py index 51352930af9..ea183c47788 100644 --- a/gramps/gen/filters/rules/event/_hasdata.py +++ b/gramps/gen/filters/rules/event/_hasdata.py @@ -71,10 +71,11 @@ def prepare(self, db, user): if self.date: self.date = parser.parse(self.date) - def apply(self, db, obj): + def apply_to_one(self, db, data): """ Apply the rule. Return True on a match. """ + obj = self.get_object(data) if self.event_type and obj.get_type() != self.event_type: # No match return False diff --git a/gramps/gen/filters/rules/event/_hasdayofweek.py b/gramps/gen/filters/rules/event/_hasdayofweek.py index b4aad3c21e2..82169cd0ce9 100644 --- a/gramps/gen/filters/rules/event/_hasdayofweek.py +++ b/gramps/gen/filters/rules/event/_hasdayofweek.py @@ -42,7 +42,8 @@ class HasDayOfWeek(Rule): description = _("Matches events occurring on a particular day of the week") category = _("General filters") - def apply(self, db, event): + def apply_to_one(self, db, data): + event = self.get_object(data) if not self.list[0]: return False else: diff --git a/gramps/gen/filters/rules/event/_hastype.py b/gramps/gen/filters/rules/event/_hastype.py index bec57745b7a..3d9630d107c 100644 --- a/gramps/gen/filters/rules/event/_hastype.py +++ b/gramps/gen/filters/rules/event/_hastype.py @@ -61,10 +61,12 @@ def prepare(self, db, user): self.event_type = EventType() self.event_type.set_from_xml_str(self.list[0]) - def apply(self, _db, obj): + def apply_to_one(self, _db, data): """ Apply the rule. Return True if a match. """ - if self.event_type: + if data["type"]: + obj = self.get_object(data) + # FIXME: probably don't need object to do this: return obj.get_type() == self.event_type return False diff --git a/gramps/gen/filters/rules/event/_matchespersonfilter.py b/gramps/gen/filters/rules/event/_matchespersonfilter.py index b82cb22e335..deec82fe120 100644 --- a/gramps/gen/filters/rules/event/_matchespersonfilter.py +++ b/gramps/gen/filters/rules/event/_matchespersonfilter.py @@ -70,23 +70,32 @@ def prepare(self, db, user): except IndexError: self.MPF_famevents = False - def apply(self, db, event): + def apply_to_one(self, db, event_data): filt = self.find_filter() if filt: for classname, handle in db.find_backlink_handles( - event.get_handle(), ["Person"] + event_data["handle"], ["Person"] ): - if filt.check(db, handle): + data = db.get_raw_person_data(handle) + if filt.apply_to_one(db, data): return True if self.MPF_famevents: # also include if family event of the person for classname, handle in db.find_backlink_handles( - event.get_handle(), ["Family"] + event_data["handle"], ["Family"] ): - family = db.get_family_from_handle(handle) - if family.father_handle and filt.check(db, family.father_handle): - return True - if family.mother_handle and filt.check(db, family.mother_handle): - return True + family_data = db.get_raw_family_data(handle) + if family_data["father_handle"]: + father_data = db.get_raw_person_data( + family_data["father_handle"] + ) + if filt.apply_to_one(db, father_data): + return True + if family_data["mother_handle"]: + mother_data = db.get_raw_person_data( + family_data["mother_handle"] + ) + if filt.apply_to_one(db, mother_data): + return True return False diff --git a/gramps/gen/filters/rules/event/_matchesplacefilter.py b/gramps/gen/filters/rules/event/_matchesplacefilter.py index b05924b0fd8..2a2614f0c17 100644 --- a/gramps/gen/filters/rules/event/_matchesplacefilter.py +++ b/gramps/gen/filters/rules/event/_matchesplacefilter.py @@ -33,6 +33,7 @@ # # ------------------------------------------------------------------------- from .._matchesfilterbase import MatchesFilterBase +from gramps.gen.lib.serialize import to_dict # ------------------------------------------------------------------------- @@ -58,10 +59,11 @@ class MatchesPlaceFilter(MatchesFilterBase): # we want to have this filter show place filters namespace = "Place" - def apply(self, db, event): + def apply_to_one(self, db, data): + event = self.get_object(data) filt = self.find_filter() if filt: handle = event.get_place_handle() - if handle and filt.check(db, handle): + if handle and filt.apply_to_one(db, to_dict(event)): return True return False diff --git a/gramps/gen/filters/rules/family/_childhasidof.py b/gramps/gen/filters/rules/family/_childhasidof.py index ab1b2069244..4c8a670dfbf 100644 --- a/gramps/gen/filters/rules/family/_childhasidof.py +++ b/gramps/gen/filters/rules/family/_childhasidof.py @@ -49,4 +49,4 @@ class ChildHasIdOf(RegExpIdBase): description = _("Matches families where child has a specified " "Gramps ID") category = _("Child filters") base_class = RegExpIdBase - apply = child_base + apply_to_one = child_base diff --git a/gramps/gen/filters/rules/family/_childhasnameof.py b/gramps/gen/filters/rules/family/_childhasnameof.py index 0da60f54884..1ad64b62d2c 100644 --- a/gramps/gen/filters/rules/family/_childhasnameof.py +++ b/gramps/gen/filters/rules/family/_childhasnameof.py @@ -48,4 +48,4 @@ class ChildHasNameOf(HasNameOf): description = _("Matches families where child has a specified " "(partial) name") category = _("Child filters") base_class = HasNameOf - apply = child_base + apply_to_one = child_base diff --git a/gramps/gen/filters/rules/family/_fatherhasidof.py b/gramps/gen/filters/rules/family/_fatherhasidof.py index 5b8ccf79bbf..f3754d1c448 100644 --- a/gramps/gen/filters/rules/family/_fatherhasidof.py +++ b/gramps/gen/filters/rules/family/_fatherhasidof.py @@ -49,4 +49,4 @@ class FatherHasIdOf(RegExpIdBase): description = _("Matches families whose father has a specified " "Gramps ID") category = _("Father filters") base_class = RegExpIdBase - apply = father_base + apply_to_one = father_base diff --git a/gramps/gen/filters/rules/family/_fatherhasnameof.py b/gramps/gen/filters/rules/family/_fatherhasnameof.py index c9030f313f9..ae0d6294c3b 100644 --- a/gramps/gen/filters/rules/family/_fatherhasnameof.py +++ b/gramps/gen/filters/rules/family/_fatherhasnameof.py @@ -48,4 +48,4 @@ class FatherHasNameOf(HasNameOf): description = _("Matches families whose father has a specified " "(partial) name") category = _("Father filters") base_class = HasNameOf - apply = father_base + apply_to_one = father_base diff --git a/gramps/gen/filters/rules/family/_hasevent.py b/gramps/gen/filters/rules/family/_hasevent.py index 0662e546707..1292650846c 100644 --- a/gramps/gen/filters/rules/family/_hasevent.py +++ b/gramps/gen/filters/rules/family/_hasevent.py @@ -56,11 +56,12 @@ class HasEvent(HasEventBase): name = _("Families with the ") description = _("Matches families with an event of a particular value") - def apply(self, dbase, family): - for event_ref in family.get_event_ref_list(): + def apply_to_one(self, dbase, data): + family = self.get_object(data) + for event_ref in data["event_ref_list"]: if not event_ref: continue - event = dbase.get_event_from_handle(event_ref.ref) - if HasEventBase.apply(self, dbase, event): + event_data = dbase.get_raw_event_data(event_ref["ref"]) + if HasEventBase.apply_to_one(self, dbase, event_data): return True return False diff --git a/gramps/gen/filters/rules/family/_hasnote.py b/gramps/gen/filters/rules/family/_hasnote.py index 5a3c981cd1c..b742148c6b8 100644 --- a/gramps/gen/filters/rules/family/_hasnote.py +++ b/gramps/gen/filters/rules/family/_hasnote.py @@ -46,3 +46,4 @@ class HasNote(HasNoteBase): name = _("Families having notes") description = _("Matches families having a certain number notes") + table = "family" diff --git a/gramps/gen/filters/rules/family/_hasreltype.py b/gramps/gen/filters/rules/family/_hasreltype.py index 6b59e88b5df..3844d8f7caa 100644 --- a/gramps/gen/filters/rules/family/_hasreltype.py +++ b/gramps/gen/filters/rules/family/_hasreltype.py @@ -61,10 +61,11 @@ def prepare(self, db, user): self.relation_type = FamilyRelType() self.relation_type.set_from_xml_str(self.list[0]) - def apply(self, _db, obj): + def apply_to_one(self, _db, data): """ Apply the rule. Return True on a match. """ + obj = self.get_object(data) if self.relation_type: if self.relation_type.is_custom() and self.use_regex: if self.regex[0].search(str(obj.get_relationship())) is None: diff --git a/gramps/gen/filters/rules/family/_hastwins.py b/gramps/gen/filters/rules/family/_hastwins.py index fdaa8f19647..cb0ca151ee7 100644 --- a/gramps/gen/filters/rules/family/_hastwins.py +++ b/gramps/gen/filters/rules/family/_hastwins.py @@ -48,7 +48,8 @@ class HasTwins(Rule): description = _("Matches families with twins") category = _("Child filters") - def apply(self, db, family): + def apply_to_one(self, db, data): + family = self.get_object(data) date_list = [] for childref in family.get_child_ref_list(): if int(childref.get_mother_relation()) == ChildRefType.BIRTH: diff --git a/gramps/gen/filters/rules/family/_isancestorof.py b/gramps/gen/filters/rules/family/_isancestorof.py index f9d9473b7e0..9b1f9efb75e 100644 --- a/gramps/gen/filters/rules/family/_isancestorof.py +++ b/gramps/gen/filters/rules/family/_isancestorof.py @@ -58,8 +58,8 @@ def prepare(self, db, user): def reset(self): self.map.clear() - def apply(self, db, family): - return family.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def init_list(self, db, family, first): """ diff --git a/gramps/gen/filters/rules/family/_isbookmarked.py b/gramps/gen/filters/rules/family/_isbookmarked.py index d3cfdf40c26..0ca803a4baf 100644 --- a/gramps/gen/filters/rules/family/_isbookmarked.py +++ b/gramps/gen/filters/rules/family/_isbookmarked.py @@ -50,5 +50,5 @@ class IsBookmarked(Rule): def prepare(self, db, user): self.bookmarks = db.get_family_bookmarks().get() - def apply(self, db, family): - return family.get_handle() in self.bookmarks + def apply_to_one(self, db, data): + return data["handle"] in self.bookmarks diff --git a/gramps/gen/filters/rules/family/_isdescendantof.py b/gramps/gen/filters/rules/family/_isdescendantof.py index 52b0bc48aca..321c202256c 100644 --- a/gramps/gen/filters/rules/family/_isdescendantof.py +++ b/gramps/gen/filters/rules/family/_isdescendantof.py @@ -58,8 +58,8 @@ def prepare(self, db, user): def reset(self): self.map.clear() - def apply(self, db, family): - return family.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def init_list(self, db, family, first): """ diff --git a/gramps/gen/filters/rules/family/_memberbase.py b/gramps/gen/filters/rules/family/_memberbase.py index a042484ca2f..32b0098b5db 100644 --- a/gramps/gen/filters/rules/family/_memberbase.py +++ b/gramps/gen/filters/rules/family/_memberbase.py @@ -32,29 +32,30 @@ """ -def father_base(self, db, family): - father_handle = family.get_father_handle() +def father_base(self, db, data): + father_handle = data["father_handle"] if father_handle: - father = db.get_person_from_handle(father_handle) - if father: - return self.base_class.apply(self, db, father) + father_data = db.get_raw_person_data(father_handle) + if father_data: + return self.base_class.apply_to_one(self, db, father_data) else: return False -def mother_base(self, db, family): - mother_handle = family.get_mother_handle() +def mother_base(self, db, data): + mother_handle = data["mother_handle"] if mother_handle: - mother = db.get_person_from_handle(mother_handle) - if mother: - return self.base_class.apply(self, db, mother) + mother_data = db.get_raw_person_data(mother_handle) + if mother_data: + return self.base_class.apply_to_one(self, db, mother_data) else: return False -def child_base(self, db, family): - for child_ref in family.get_child_ref_list(): - child = db.get_person_from_handle(child_ref.ref) - if self.base_class.apply(self, db, child): - return True +def child_base(self, db, data): + for child_ref in data["child_ref_list"]: + child_data = db.get_raw_person_data(child_ref["ref"]) + if child_data: + if self.base_class.apply_to_one(self, db, child_data): + return True return False diff --git a/gramps/gen/filters/rules/family/_motherhasidof.py b/gramps/gen/filters/rules/family/_motherhasidof.py index 0c8ea2f6ede..bababa6756b 100644 --- a/gramps/gen/filters/rules/family/_motherhasidof.py +++ b/gramps/gen/filters/rules/family/_motherhasidof.py @@ -49,4 +49,4 @@ class MotherHasIdOf(RegExpIdBase): description = _("Matches families whose mother has a specified " "Gramps ID") category = _("Mother filters") base_class = RegExpIdBase - apply = mother_base + apply_to_one = mother_base diff --git a/gramps/gen/filters/rules/family/_motherhasnameof.py b/gramps/gen/filters/rules/family/_motherhasnameof.py index 1872cd46c3a..51288c8212b 100644 --- a/gramps/gen/filters/rules/family/_motherhasnameof.py +++ b/gramps/gen/filters/rules/family/_motherhasnameof.py @@ -48,4 +48,4 @@ class MotherHasNameOf(HasNameOf): description = _("Matches families whose mother has a specified " "(partial) name") category = _("Mother filters") base_class = HasNameOf - apply = mother_base + apply_to_one = mother_base diff --git a/gramps/gen/filters/rules/family/_regexpchildname.py b/gramps/gen/filters/rules/family/_regexpchildname.py index f0fb746b1c8..4813e04e5f6 100644 --- a/gramps/gen/filters/rules/family/_regexpchildname.py +++ b/gramps/gen/filters/rules/family/_regexpchildname.py @@ -51,4 +51,4 @@ class RegExpChildName(RegExpName): ) category = _("Child filters") base_class = RegExpName - apply = child_base + apply_to_one = child_base diff --git a/gramps/gen/filters/rules/family/_regexpfathername.py b/gramps/gen/filters/rules/family/_regexpfathername.py index 6fe0e9dddef..81ac8f6d777 100644 --- a/gramps/gen/filters/rules/family/_regexpfathername.py +++ b/gramps/gen/filters/rules/family/_regexpfathername.py @@ -51,4 +51,4 @@ class RegExpFatherName(RegExpName): ) category = _("Father filters") base_class = RegExpName - apply = father_base + apply_to_one = father_base diff --git a/gramps/gen/filters/rules/family/_regexpmothername.py b/gramps/gen/filters/rules/family/_regexpmothername.py index 24378f10757..f6f068994cf 100644 --- a/gramps/gen/filters/rules/family/_regexpmothername.py +++ b/gramps/gen/filters/rules/family/_regexpmothername.py @@ -51,4 +51,4 @@ class RegExpMotherName(RegExpName): ) category = _("Mother filters") base_class = RegExpName - apply = mother_base + apply_to_one = mother_base diff --git a/gramps/gen/filters/rules/family/_searchchildname.py b/gramps/gen/filters/rules/family/_searchchildname.py index 2450430a287..1fbe1b4dc4c 100644 --- a/gramps/gen/filters/rules/family/_searchchildname.py +++ b/gramps/gen/filters/rules/family/_searchchildname.py @@ -50,4 +50,4 @@ class SearchChildName(SearchName): ) category = _("Child filters") base_class = SearchName - apply = child_base + apply_to_one = child_base diff --git a/gramps/gen/filters/rules/family/_searchfathername.py b/gramps/gen/filters/rules/family/_searchfathername.py index 431717d8cbe..741032fa0de 100644 --- a/gramps/gen/filters/rules/family/_searchfathername.py +++ b/gramps/gen/filters/rules/family/_searchfathername.py @@ -48,4 +48,4 @@ class SearchFatherName(SearchName): description = _("Matches families whose father has a specified " "(partial) name") category = _("Father filters") base_class = SearchName - apply = father_base + apply_to_one = father_base diff --git a/gramps/gen/filters/rules/family/_searchmothername.py b/gramps/gen/filters/rules/family/_searchmothername.py index 8bbca710488..e91458aeb54 100644 --- a/gramps/gen/filters/rules/family/_searchmothername.py +++ b/gramps/gen/filters/rules/family/_searchmothername.py @@ -48,4 +48,4 @@ class SearchMotherName(SearchName): description = _("Matches families whose mother has a specified " "(partial) name") category = _("Mother filters") base_class = SearchName - apply = mother_base + apply_to_one = mother_base diff --git a/gramps/gen/filters/rules/media/_hasmedia.py b/gramps/gen/filters/rules/media/_hasmedia.py index 49ffc7f3975..5e0d53beea8 100644 --- a/gramps/gen/filters/rules/media/_hasmedia.py +++ b/gramps/gen/filters/rules/media/_hasmedia.py @@ -63,7 +63,8 @@ def prepare(self, db, user): except: pass - def apply(self, db, obj): + def apply_to_one(self, db, data): + obj = self.get_object(data) if not self.match_substring(0, obj.get_description()): return False diff --git a/gramps/gen/filters/rules/note/_hasnote.py b/gramps/gen/filters/rules/note/_hasnote.py index d9ed302d0a7..52b99bf1ba1 100644 --- a/gramps/gen/filters/rules/note/_hasnote.py +++ b/gramps/gen/filters/rules/note/_hasnote.py @@ -65,10 +65,11 @@ def prepare(self, db, user): self.note_type = NoteType() self.note_type.set_from_xml_str(self.list[1]) - def apply(self, _db, obj): + def apply_to_one(self, _db, data): """ Apply the rule. Return True on a match. """ + obj = self.get_object(data) if not self.match_substring(0, obj.get()): return False diff --git a/gramps/gen/filters/rules/note/_hastype.py b/gramps/gen/filters/rules/note/_hastype.py index d81f522b8d0..98f3b440e12 100644 --- a/gramps/gen/filters/rules/note/_hastype.py +++ b/gramps/gen/filters/rules/note/_hastype.py @@ -61,10 +61,11 @@ def prepare(self, db, user): self.note_type = NoteType() self.note_type.set_from_xml_str(self.list[0]) - def apply(self, _db, obj): + def apply_to_one(self, _db, data): """ Apply the rule. Return True on a match. """ + obj = self.get_object(data) if self.note_type: return obj.get_type() == self.note_type return False diff --git a/gramps/gen/filters/rules/note/_matchesregexpof.py b/gramps/gen/filters/rules/note/_matchesregexpof.py index ad8c5ada03f..95eabccc612 100644 --- a/gramps/gen/filters/rules/note/_matchesregexpof.py +++ b/gramps/gen/filters/rules/note/_matchesregexpof.py @@ -49,8 +49,9 @@ class MatchesRegexpOf(Rule): category = _("General filters") allow_regex = True - def apply(self, db, note): + def apply_to_one(self, db, data): """Apply the filter""" + note = self.get_object(data) if self.match_substring(0, note.get()): return True return False diff --git a/gramps/gen/filters/rules/note/_matchessubstringof.py b/gramps/gen/filters/rules/note/_matchessubstringof.py index 96cafb9fb0f..b6ece36d1e3 100644 --- a/gramps/gen/filters/rules/note/_matchessubstringof.py +++ b/gramps/gen/filters/rules/note/_matchessubstringof.py @@ -47,8 +47,9 @@ class MatchesSubstringOf(Rule): description = _("Matches notes that contain text " "which matches a substring") category = _("General filters") - def apply(self, db, note): + def apply_to_one(self, db, data): """Apply the filter""" + note = self.get_object(data) text = note.get() if text.upper().find(self.list[0].upper()) != -1: return True diff --git a/gramps/gen/filters/rules/person/_deeprelationshippathbetween.py b/gramps/gen/filters/rules/person/_deeprelationshippathbetween.py index d617b6e36f7..ec1ad073fca 100644 --- a/gramps/gen/filters/rules/person/_deeprelationshippathbetween.py +++ b/gramps/gen/filters/rules/person/_deeprelationshippathbetween.py @@ -157,10 +157,9 @@ def prepare(self, db, user): db.get_number_of_people(), ) target_people = [] - for handle in db.iter_person_handles(): - person = db.get_person_from_handle(handle) - if self.filt.apply(db, person): - target_people.append(handle) + for handle, person_data in db._iter_raw_person_data(): + if self.filt.apply_to_one(db, person_data): + target_people.append(data["handle"]) if user: user.step_progress() if user: @@ -170,13 +169,13 @@ def prepare(self, db, user): _("Evaluating people"), db.get_number_of_people(), ) - self.__matches = find_deep_relations(db, user, root_person, target_people) + self.map = find_deep_relations(db, user, root_person, target_people) if user: user.end_progress() def reset(self): self.filt.requestreset() - self.__matches = set() + self.map.clear() - def apply(self, db, person): - return person.get_handle() in self.__matches + def apply_to_one(self, db, data): + return data["handle"] in self.__matches diff --git a/gramps/gen/filters/rules/person/_disconnected.py b/gramps/gen/filters/rules/person/_disconnected.py index 66b60c28763..8df8f84a912 100644 --- a/gramps/gen/filters/rules/person/_disconnected.py +++ b/gramps/gen/filters/rules/person/_disconnected.py @@ -50,7 +50,5 @@ class Disconnected(Rule): "to any other person in the database" ) - def apply(self, db, person): - return not ( - person.get_parent_family_handle_list() or person.get_family_handle_list() - ) + def apply_to_one(self, db, data): + return not (data["parent_family_list"] or data["family_list"]) diff --git a/gramps/gen/filters/rules/person/_everyone.py b/gramps/gen/filters/rules/person/_everyone.py index 29832d2d676..48695e40cfd 100644 --- a/gramps/gen/filters/rules/person/_everyone.py +++ b/gramps/gen/filters/rules/person/_everyone.py @@ -50,5 +50,5 @@ class Everyone(Rule): def is_empty(self): return True - def apply(self, db, person): + def apply_to_one(self, db, data): return True diff --git a/gramps/gen/filters/rules/person/_familywithincompleteevent.py b/gramps/gen/filters/rules/person/_familywithincompleteevent.py index c5ff2bdb3f8..4952049fa72 100644 --- a/gramps/gen/filters/rules/person/_familywithincompleteevent.py +++ b/gramps/gen/filters/rules/person/_familywithincompleteevent.py @@ -47,7 +47,8 @@ class FamilyWithIncompleteEvent(Rule): ) category = _("Event filters") - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for family_handle in person.get_family_handle_list(): family = db.get_family_from_handle(family_handle) if family: diff --git a/gramps/gen/filters/rules/person/_hasaddress.py b/gramps/gen/filters/rules/person/_hasaddress.py index 6c8b891aec8..5197d96db7c 100644 --- a/gramps/gen/filters/rules/person/_hasaddress.py +++ b/gramps/gen/filters/rules/person/_hasaddress.py @@ -63,8 +63,8 @@ def prepare(self, db, user): self.userSelectedCount = int(self.list[0]) - def apply(self, db, person): - count = len(person.get_address_list()) + def apply_to_one(self, db, data): + count = len(data["address_list"]) if self.count_type == 0: # "less than" return count < self.userSelectedCount elif self.count_type == 2: # "greater than" diff --git a/gramps/gen/filters/rules/person/_hasaddresstext.py b/gramps/gen/filters/rules/person/_hasaddresstext.py index a42b973634e..6c63dabac89 100644 --- a/gramps/gen/filters/rules/person/_hasaddresstext.py +++ b/gramps/gen/filters/rules/person/_hasaddresstext.py @@ -48,7 +48,8 @@ class HasAddressText(Rule): category = _("General filters") allow_regex = True - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for address in person.get_address_list(): for string in address.get_text_data_list(): if self.match_substring(0, string): diff --git a/gramps/gen/filters/rules/person/_hasalternatename.py b/gramps/gen/filters/rules/person/_hasalternatename.py index 673111879e6..0c0485c9a26 100644 --- a/gramps/gen/filters/rules/person/_hasalternatename.py +++ b/gramps/gen/filters/rules/person/_hasalternatename.py @@ -48,8 +48,8 @@ class HasAlternateName(Rule): description = _("Matches people with an alternate name") category = _("General filters") - def apply(self, db, person): - if person.get_alternate_names(): + def apply_to_one(self, db, data): + if data["alternate_names"]: return True else: return False diff --git a/gramps/gen/filters/rules/person/_hasassociation.py b/gramps/gen/filters/rules/person/_hasassociation.py index e1d95f8c310..9010445c072 100644 --- a/gramps/gen/filters/rules/person/_hasassociation.py +++ b/gramps/gen/filters/rules/person/_hasassociation.py @@ -63,8 +63,8 @@ def prepare(self, db, user): self.selected_count = int(self.list[0]) - def apply(self, db, person): - count = len(person.get_person_ref_list()) + def apply_to_one(self, db, data): + count = len(data["person_ref_list"]) if self.count_type == 0: # "less than" return count < self.selected_count elif self.count_type == 2: # "greater than" diff --git a/gramps/gen/filters/rules/person/_hasbirth.py b/gramps/gen/filters/rules/person/_hasbirth.py index 511a61fa829..74035adc33f 100644 --- a/gramps/gen/filters/rules/person/_hasbirth.py +++ b/gramps/gen/filters/rules/person/_hasbirth.py @@ -59,7 +59,8 @@ def prepare(self, db, user): else: self.date = None - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for event_ref in person.get_event_ref_list(): if not event_ref: continue diff --git a/gramps/gen/filters/rules/person/_hascommonancestorwith.py b/gramps/gen/filters/rules/person/_hascommonancestorwith.py index cba92f5df10..de069e81e19 100644 --- a/gramps/gen/filters/rules/person/_hascommonancestorwith.py +++ b/gramps/gen/filters/rules/person/_hascommonancestorwith.py @@ -106,8 +106,8 @@ def has_common_ancestor(self, other): return True return False - def apply(self, db, person): - if person and person.handle not in self.ancestor_cache: + def apply_to_one(self, db, data): + person = self.get_object(data) + if data["handle"] not in self.ancestor_cache: self.add_ancs(db, person) - return self.has_common_ancestor(person) diff --git a/gramps/gen/filters/rules/person/_hascommonancestorwithfiltermatch.py b/gramps/gen/filters/rules/person/_hascommonancestorwithfiltermatch.py index 78183cfa992..6384b826a05 100644 --- a/gramps/gen/filters/rules/person/_hascommonancestorwithfiltermatch.py +++ b/gramps/gen/filters/rules/person/_hascommonancestorwithfiltermatch.py @@ -35,6 +35,7 @@ from ....utils.db import for_each_ancestor from ._hascommonancestorwith import HasCommonAncestorWith from ._matchesfilter import MatchesFilter +from gramps.gen.lib.serialize import from_dict # ------------------------------------------------------------------------- @@ -73,15 +74,16 @@ def prepare(self, db, user): _("Retrieving all sub-filter matches"), db.get_number_of_people(), ) - for handle in db.iter_person_handles(): - person = db.get_person_from_handle(handle) + for handle, data in db._iter_raw_person_data(): + # person = db.get_person_from_handle(handle) if user: user.step_progress() - if person and self.filt.apply(db, person): + if self.filt.apply_to_one(db, data): # store all people in the filter so as to compare later - self.with_people.append(person.handle) + self.with_people.append(data["handle"]) # fill list of ancestor of person if not present yet - if handle not in self.ancestor_cache: + if data["handle"] not in self.ancestor_cache: + person = from_dict(data) self.add_ancs(db, person) if user: user.end_progress() diff --git a/gramps/gen/filters/rules/person/_hasdeath.py b/gramps/gen/filters/rules/person/_hasdeath.py index d22ba288812..3f6cff14f45 100644 --- a/gramps/gen/filters/rules/person/_hasdeath.py +++ b/gramps/gen/filters/rules/person/_hasdeath.py @@ -59,7 +59,8 @@ def prepare(self, db, user): else: self.date = None - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for event_ref in person.get_event_ref_list(): if not event_ref: continue diff --git a/gramps/gen/filters/rules/person/_hasevent.py b/gramps/gen/filters/rules/person/_hasevent.py index c44bf4d6a0a..7e4c06234d2 100644 --- a/gramps/gen/filters/rules/person/_hasevent.py +++ b/gramps/gen/filters/rules/person/_hasevent.py @@ -55,15 +55,18 @@ class HasEvent(HasEventBase): name = _("People with the personal ") description = _("Matches people with a personal event of a particular value") - def apply(self, db, person): + def apply_to_one(self, db, data): """ Apply the rule. Return True if a match. """ - for event_ref in person.get_event_ref_list(): - if int(self.list[5]) and event_ref.role != EventRoleType.PRIMARY: + for event_ref in data["event_ref_list"]: + if ( + int(self.list[5]) + and event_ref["role"]["value"] != EventRoleType.PRIMARY + ): # Only match primaries, no witnesses continue - event = db.get_event_from_handle(event_ref.ref) - if HasEventBase.apply(self, db, event): + event_data = db.get_raw_event_data(event_ref["ref"]) + if HasEventBase.apply_to_one(self, db, event_data): return True return False diff --git a/gramps/gen/filters/rules/person/_hasfamilyattribute.py b/gramps/gen/filters/rules/person/_hasfamilyattribute.py index e8707b392d7..3c9a9d7f719 100644 --- a/gramps/gen/filters/rules/person/_hasfamilyattribute.py +++ b/gramps/gen/filters/rules/person/_hasfamilyattribute.py @@ -49,9 +49,10 @@ class HasFamilyAttribute(Rule): category = _("General filters") allow_regex = True - def apply(self, db, person): + def apply_to_one(self, db, data): if not self.list[0]: return False + person = self.get_object(data) for f_id in person.get_family_handle_list(): f = db.get_family_from_handle(f_id) if not f: diff --git a/gramps/gen/filters/rules/person/_hasfamilyevent.py b/gramps/gen/filters/rules/person/_hasfamilyevent.py index 6b07bc9ad2d..01f85eb538f 100644 --- a/gramps/gen/filters/rules/person/_hasfamilyevent.py +++ b/gramps/gen/filters/rules/person/_hasfamilyevent.py @@ -67,7 +67,8 @@ def prepare(self, db, user): except: pass - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for handle in person.get_family_handle_list(): family = db.get_family_from_handle(handle) for event_ref in family.get_event_ref_list(): diff --git a/gramps/gen/filters/rules/person/_hasnameof.py b/gramps/gen/filters/rules/person/_hasnameof.py index 2ef2c10dc40..484c6f4a753 100644 --- a/gramps/gen/filters/rules/person/_hasnameof.py +++ b/gramps/gen/filters/rules/person/_hasnameof.py @@ -63,7 +63,8 @@ class HasNameOf(Rule): category = _("General filters") allow_regex = True - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for name in [person.get_primary_name()] + person.get_alternate_names(): if self.match_name(name): return True diff --git a/gramps/gen/filters/rules/person/_hasnameorigintype.py b/gramps/gen/filters/rules/person/_hasnameorigintype.py index 9e999495c94..3ef9753879d 100644 --- a/gramps/gen/filters/rules/person/_hasnameorigintype.py +++ b/gramps/gen/filters/rules/person/_hasnameorigintype.py @@ -61,11 +61,12 @@ def prepare(self, db, user): self.name_origin_type = NameOriginType() self.name_origin_type.set_from_xml_str(self.list[0]) - def apply(self, _db, obj): + def apply_to_one(self, _db, data): """ Apply the rule. Return True on a match. """ if self.name_origin_type: + obj = self.get_object(data) for name in [obj.get_primary_name()] + obj.get_alternate_names(): for surname in name.get_surname_list(): if surname.get_origintype() == self.name_origin_type: diff --git a/gramps/gen/filters/rules/person/_hasnametype.py b/gramps/gen/filters/rules/person/_hasnametype.py index 9e8fa7c0115..378ee81d4f1 100644 --- a/gramps/gen/filters/rules/person/_hasnametype.py +++ b/gramps/gen/filters/rules/person/_hasnametype.py @@ -61,11 +61,12 @@ def prepare(self, db, user): self.name_type = NameType() self.name_type.set_from_xml_str(self.list[0]) - def apply(self, _db, obj): + def apply_to_one(self, _db, data): """ Apply the rule. Return True on a match. """ if self.name_type: + obj = self.get_object(data) for name in [obj.get_primary_name()] + obj.get_alternate_names(): if name.get_type() == self.name_type: return True diff --git a/gramps/gen/filters/rules/person/_hasnickname.py b/gramps/gen/filters/rules/person/_hasnickname.py index 48f7da04057..8ab5ee09fc9 100644 --- a/gramps/gen/filters/rules/person/_hasnickname.py +++ b/gramps/gen/filters/rules/person/_hasnickname.py @@ -48,7 +48,8 @@ class HasNickname(Rule): description = _("Matches people with a nickname") category = _("General filters") - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) if person.get_nick_name(): return True return False diff --git a/gramps/gen/filters/rules/person/_hasothergender.py b/gramps/gen/filters/rules/person/_hasothergender.py index 1d8533f03be..e0f6b0f1397 100644 --- a/gramps/gen/filters/rules/person/_hasothergender.py +++ b/gramps/gen/filters/rules/person/_hasothergender.py @@ -48,5 +48,5 @@ class HasOtherGender(Rule): category = _("General filters") description = _("Matches all people with other gender") - def apply(self, db, person): - return person.gender == Person.OTHER + def apply_to_one(self, db, data): + return data["gender"] == Person.OTHER diff --git a/gramps/gen/filters/rules/person/_hasrelationship.py b/gramps/gen/filters/rules/person/_hasrelationship.py index 7223d991002..d9a346cf6fd 100644 --- a/gramps/gen/filters/rules/person/_hasrelationship.py +++ b/gramps/gen/filters/rules/person/_hasrelationship.py @@ -65,10 +65,11 @@ def prepare(self, db, user): self.relationship_type = FamilyRelType() self.relationship_type.set_from_xml_str(self.list[1]) - def apply(self, db, obj): + def apply_to_one(self, db, data): """ Apply the rule. Return True on a match. """ + obj = self.get_object(data) relationship_type = 0 total_children = 0 number_relations = len(obj.get_family_handle_list()) diff --git a/gramps/gen/filters/rules/person/_hassoundexname.py b/gramps/gen/filters/rules/person/_hassoundexname.py index af3227acd6f..7bef3a65cb0 100644 --- a/gramps/gen/filters/rules/person/_hassoundexname.py +++ b/gramps/gen/filters/rules/person/_hassoundexname.py @@ -65,10 +65,11 @@ def prepare(self, db, user): if self.list[0]: self.soundex = soundex(self.list[0]) - def apply(self, _db, obj): + def apply_to_one(self, _db, data): """ Apply the rule. Return True on a match. """ + obj = self.get_object(data) for name in [obj.get_primary_name()] + obj.get_alternate_names(): if self._match_name(name): return True diff --git a/gramps/gen/filters/rules/person/_hastextmatchingsubstringof.py b/gramps/gen/filters/rules/person/_hastextmatchingsubstringof.py index 7aa4c2aaa78..defc2a984e5 100644 --- a/gramps/gen/filters/rules/person/_hastextmatchingsubstringof.py +++ b/gramps/gen/filters/rules/person/_hastextmatchingsubstringof.py @@ -80,7 +80,8 @@ def reset(self): self.place_map.clear() self.media_map.clear() - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) if person.handle in self.person_map: # Cached by matching Source? return True if self.match_object(person): # first match the person itself diff --git a/gramps/gen/filters/rules/person/_hasunknowngender.py b/gramps/gen/filters/rules/person/_hasunknowngender.py index 5c25eb8995e..e296806ab2f 100644 --- a/gramps/gen/filters/rules/person/_hasunknowngender.py +++ b/gramps/gen/filters/rules/person/_hasunknowngender.py @@ -48,5 +48,5 @@ class HasUnknownGender(Rule): category = _("General filters") description = _("Matches all people with unknown gender") - def apply(self, db, person): - return person.gender == Person.UNKNOWN + def apply_to_one(self, db, data): + return data["gender"] == Person.UNKNOWN diff --git a/gramps/gen/filters/rules/person/_havealtfamilies.py b/gramps/gen/filters/rules/person/_havealtfamilies.py index 41c6b468273..1017785b8ba 100644 --- a/gramps/gen/filters/rules/person/_havealtfamilies.py +++ b/gramps/gen/filters/rules/person/_havealtfamilies.py @@ -46,7 +46,8 @@ class HaveAltFamilies(Rule): description = _("Matches people who were adopted") category = _("Family filters") - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for fhandle in person.get_parent_family_handle_list(): family = db.get_family_from_handle(fhandle) if family: diff --git a/gramps/gen/filters/rules/person/_havechildren.py b/gramps/gen/filters/rules/person/_havechildren.py index 3753d7a8a3a..2980c26d260 100644 --- a/gramps/gen/filters/rules/person/_havechildren.py +++ b/gramps/gen/filters/rules/person/_havechildren.py @@ -48,7 +48,8 @@ class HaveChildren(Rule): description = _("Matches people who have children") category = _("Family filters") - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for family_handle in person.get_family_handle_list(): family = db.get_family_from_handle(family_handle) if family is not None and family.get_child_ref_list(): diff --git a/gramps/gen/filters/rules/person/_incompletenames.py b/gramps/gen/filters/rules/person/_incompletenames.py index 3e11c52b760..28b06ff543b 100644 --- a/gramps/gen/filters/rules/person/_incompletenames.py +++ b/gramps/gen/filters/rules/person/_incompletenames.py @@ -47,7 +47,8 @@ class IncompleteNames(Rule): description = _("Matches people with firstname or lastname missing") category = _("General filters") - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for name in [person.get_primary_name()] + person.get_alternate_names(): if name.get_first_name().strip() == "": return True diff --git a/gramps/gen/filters/rules/person/_isancestorof.py b/gramps/gen/filters/rules/person/_isancestorof.py index ac2668b4a66..6db18c46658 100644 --- a/gramps/gen/filters/rules/person/_isancestorof.py +++ b/gramps/gen/filters/rules/person/_isancestorof.py @@ -65,8 +65,8 @@ def prepare(self, db, user): def reset(self): self.map.clear() - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def init_ancestor_list(self, db, person, first): if not person: diff --git a/gramps/gen/filters/rules/person/_isancestoroffiltermatch.py b/gramps/gen/filters/rules/person/_isancestoroffiltermatch.py index ff7b6ea5bc2..4d013c700bc 100644 --- a/gramps/gen/filters/rules/person/_isancestoroffiltermatch.py +++ b/gramps/gen/filters/rules/person/_isancestoroffiltermatch.py @@ -24,6 +24,7 @@ # # ------------------------------------------------------------------------- from ....const import GRAMPS_LOCALE as glocale +from gramps.gen.lib.serialize import from_dict _ = glocale.translation.gettext @@ -71,10 +72,11 @@ def prepare(self, db, user): _("Retrieving all sub-filter matches"), db.get_number_of_people(), ) - for person in db.iter_people(): + for handle, data in db._iter_raw_person_data(): if user: user.step_progress() - if self.filt.apply(db, person): + if self.filt.apply_to_one(db, data): + person = from_dict(data) self.init_ancestor_list(db, person, first) if user: user.end_progress() @@ -83,5 +85,5 @@ def reset(self): self.filt.requestreset() self.map.clear() - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map diff --git a/gramps/gen/filters/rules/person/_isbookmarked.py b/gramps/gen/filters/rules/person/_isbookmarked.py index 715cefcca3f..7099f490438 100644 --- a/gramps/gen/filters/rules/person/_isbookmarked.py +++ b/gramps/gen/filters/rules/person/_isbookmarked.py @@ -51,5 +51,5 @@ class IsBookmarked(Rule): def prepare(self, db, user): self.bookmarks = db.get_bookmarks().get() - def apply(self, db, person): - return person.handle in self.bookmarks + def apply_to_one(self, db, data): + return data["handle"] in self.bookmarks diff --git a/gramps/gen/filters/rules/person/_ischildoffiltermatch.py b/gramps/gen/filters/rules/person/_ischildoffiltermatch.py index fa737f26522..2eeca007d62 100644 --- a/gramps/gen/filters/rules/person/_ischildoffiltermatch.py +++ b/gramps/gen/filters/rules/person/_ischildoffiltermatch.py @@ -34,6 +34,7 @@ # ------------------------------------------------------------------------- from .. import Rule from ._matchesfilter import MatchesFilter +from gramps.gen.lib.serialize import from_dict # ------------------------------------------------------------------------- @@ -61,11 +62,11 @@ def prepare(self, db, user): _("Retrieving all sub-filter matches"), db.get_number_of_people(), ) - for person in db.iter_people(): + for handle, person_data in db._iter_raw_person_data(): if user: user.step_progress() - if self.filt.apply(db, person): - self.init_list(person) + if self.filt.apply_to_one(db, person_data): + self.init_list(from_dict(person_data)) if user: user.end_progress() @@ -73,8 +74,8 @@ def reset(self): self.filt.requestreset() self.map.clear() - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def init_list(self, person): if not person: diff --git a/gramps/gen/filters/rules/person/_isdefaultperson.py b/gramps/gen/filters/rules/person/_isdefaultperson.py index 2b58ed43d41..207fe7333a0 100644 --- a/gramps/gen/filters/rules/person/_isdefaultperson.py +++ b/gramps/gen/filters/rules/person/_isdefaultperson.py @@ -51,9 +51,8 @@ def prepare(self, db, user): p = db.get_default_person() if p: self.def_handle = p.get_handle() - self.apply = self.apply_real else: - self.apply = lambda db, p: False + self.def_handle = None - def apply_real(self, db, person): - return person.handle == self.def_handle + def apply_to_one(self, db, data): + return data["handle"] == self.def_handle diff --git a/gramps/gen/filters/rules/person/_isdescendantfamilyof.py b/gramps/gen/filters/rules/person/_isdescendantfamilyof.py index bc288b289e8..066e763a08b 100644 --- a/gramps/gen/filters/rules/person/_isdescendantfamilyof.py +++ b/gramps/gen/filters/rules/person/_isdescendantfamilyof.py @@ -58,7 +58,7 @@ class IsDescendantFamilyOf(Rule): def prepare(self, db, user): self.db = db - self.matches = set() + self.map = set() self.root_person = db.get_person_from_gramps_id(self.list[0]) self.add_matches(self.root_person) try: @@ -72,10 +72,10 @@ def prepare(self, db, user): self.exclude() def reset(self): - self.matches = set() + self.map = set() - def apply(self, db, person): - return person.handle in self.matches + def apply_to_one(self, db, data): + return data["handle"] in self.map def add_matches(self, person): if not person: @@ -86,10 +86,10 @@ def add_matches(self, person): while expand: person = expand.pop(0) - if person is None or person.handle in self.matches: + if person is None or person.handle in self.map: # if we have been here before, skip continue - self.matches.add(person.handle) + self.map.add(person.handle) for family_handle in person.get_family_handle_list(): family = self.db.get_family_from_handle(family_handle) if family: @@ -102,13 +102,13 @@ def add_matches(self, person): spouse_handle = family.get_mother_handle() else: spouse_handle = family.get_father_handle() - self.matches.add(spouse_handle) + self.map.add(spouse_handle) def exclude(self): # This removes root person and his/her spouses from the matches set if not self.root_person: return - self.matches.remove(self.root_person.handle) + self.map.remove(self.root_person.handle) for family_handle in self.root_person.get_family_handle_list(): family = self.db.get_family_from_handle(family_handle) if family: @@ -116,4 +116,4 @@ def exclude(self): spouse_handle = family.get_mother_handle() else: spouse_handle = family.get_father_handle() - self.matches.remove(spouse_handle) + self.map.remove(spouse_handle) diff --git a/gramps/gen/filters/rules/person/_isdescendantfamilyoffiltermatch.py b/gramps/gen/filters/rules/person/_isdescendantfamilyoffiltermatch.py index 25634a1bc14..19bbf8def77 100644 --- a/gramps/gen/filters/rules/person/_isdescendantfamilyoffiltermatch.py +++ b/gramps/gen/filters/rules/person/_isdescendantfamilyoffiltermatch.py @@ -24,6 +24,7 @@ # # ------------------------------------------------------------------------- from ....const import GRAMPS_LOCALE as glocale +from gramps.gen.lib.serialize import from_dict _ = glocale.translation.gettext @@ -55,7 +56,7 @@ class IsDescendantFamilyOfFilterMatch(IsDescendantFamilyOf): def prepare(self, db, user): self.db = db - self.matches = set() + self.map = set() self.matchfilt = MatchesFilter(self.list[0:1]) self.matchfilt.requestprepare(db, user) @@ -65,14 +66,14 @@ def prepare(self, db, user): _("Retrieving all sub-filter matches"), db.get_number_of_people(), ) - for person in db.iter_people(): + for handle, person_data in db._iter_raw_person_data(): if user: user.step_progress() - if self.matchfilt.apply(db, person): - self.add_matches(person) + if self.matchfilt.apply_to_one(db, person_data): + self.add_matches(from_dict(person_data)) if user: user.end_progress() def reset(self): self.matchfilt.requestreset() - self.matches = set() + self.map = set() diff --git a/gramps/gen/filters/rules/person/_isdescendantof.py b/gramps/gen/filters/rules/person/_isdescendantof.py index 52cea65c8f9..8922f9b0a85 100644 --- a/gramps/gen/filters/rules/person/_isdescendantof.py +++ b/gramps/gen/filters/rules/person/_isdescendantof.py @@ -65,8 +65,8 @@ def prepare(self, db, user): def reset(self): self.map.clear() - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def init_list(self, person, first): if not person or person.handle in self.map: diff --git a/gramps/gen/filters/rules/person/_isdescendantoffiltermatch.py b/gramps/gen/filters/rules/person/_isdescendantoffiltermatch.py index dbb864b4b44..30b5fe2302b 100644 --- a/gramps/gen/filters/rules/person/_isdescendantoffiltermatch.py +++ b/gramps/gen/filters/rules/person/_isdescendantoffiltermatch.py @@ -24,6 +24,7 @@ # # ------------------------------------------------------------------------- from ....const import GRAMPS_LOCALE as glocale +from gramps.gen.lib.serialize import from_dict _ = glocale.translation.gettext @@ -71,11 +72,11 @@ def prepare(self, db, user): _("Retrieving all sub-filter matches"), db.get_number_of_people(), ) - for person in db.iter_people(): + for handle, person_data in db._iter_raw_person_data(): if user: user.step_progress() - if self.filt.apply(db, person): - self.init_list(person, first) + if self.filt.apply_to_one(db, person_data): + self.init_list(from_dict(person_data), first) if user: user.end_progress() @@ -83,5 +84,5 @@ def reset(self): self.filt.requestreset() self.map.clear() - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map diff --git a/gramps/gen/filters/rules/person/_isduplicatedancestorof.py b/gramps/gen/filters/rules/person/_isduplicatedancestorof.py index 9d31ca2e200..eaf6ceb98c0 100644 --- a/gramps/gen/filters/rules/person/_isduplicatedancestorof.py +++ b/gramps/gen/filters/rules/person/_isduplicatedancestorof.py @@ -54,18 +54,18 @@ class IsDuplicatedAncestorOf(Rule): def prepare(self, db, user): self.db = db + self.cache = set() self.map = set() - self.map2 = set() root_person = db.get_person_from_gramps_id(self.list[0]) if root_person: self.init_ancestor_list(db, root_person) def reset(self): + self.cache.clear() self.map.clear() - self.map2.clear() - def apply(self, db, person): - return person.handle in self.map2 + def apply_to_one(self, db, data): + return data["handle"] in self.map def init_ancestor_list(self, db, person): fam_id = person.get_main_parents_family_handle() @@ -80,10 +80,10 @@ def init_ancestor_list(self, db, person): self.go_deeper(db, db.get_person_from_handle(f_id)) def go_deeper(self, db, person): - if person and person.handle in self.map: - self.map2.add((person.handle)) + if person and person.handle in self.cache: + self.map.add((person.handle)) # the following keeps from scanning same parts of tree multiple # times and avoids crash on tree loops. return - self.map.add((person.handle)) + self.cache.add((person.handle)) self.init_ancestor_list(db, person) diff --git a/gramps/gen/filters/rules/person/_isfemale.py b/gramps/gen/filters/rules/person/_isfemale.py index 2fa21e6e004..ff269ac913b 100644 --- a/gramps/gen/filters/rules/person/_isfemale.py +++ b/gramps/gen/filters/rules/person/_isfemale.py @@ -48,5 +48,5 @@ class IsFemale(Rule): category = _("General filters") description = _("Matches all females") - def apply(self, db, person): - return person.gender == Person.FEMALE + def apply_to_one(self, db, data): + return data["gender"] == Person.FEMALE diff --git a/gramps/gen/filters/rules/person/_islessthannthgenerationancestorof.py b/gramps/gen/filters/rules/person/_islessthannthgenerationancestorof.py index c88f8c332fa..82b2128dc1b 100644 --- a/gramps/gen/filters/rules/person/_islessthannthgenerationancestorof.py +++ b/gramps/gen/filters/rules/person/_islessthannthgenerationancestorof.py @@ -87,5 +87,5 @@ def init_ancestor_list(self, root_handle): def reset(self): self.map.clear() - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map diff --git a/gramps/gen/filters/rules/person/_islessthannthgenerationancestorofbookmarked.py b/gramps/gen/filters/rules/person/_islessthannthgenerationancestorofbookmarked.py index bbdda54b480..261d2492540 100644 --- a/gramps/gen/filters/rules/person/_islessthannthgenerationancestorofbookmarked.py +++ b/gramps/gen/filters/rules/person/_islessthannthgenerationancestorofbookmarked.py @@ -62,11 +62,8 @@ def prepare(self, db, user): self.db = db bookmarks = db.get_bookmarks().get() self.map = set() - if len(bookmarks) == 0: - self.apply = lambda db, p: False - else: + if len(bookmarks) != 0: self.bookmarks = set(bookmarks) - self.apply = self.apply_real for self.bookmarkhandle in self.bookmarks: self.init_ancestor_list(self.bookmarkhandle, 1) @@ -95,8 +92,8 @@ def init_ancestor_list(self, handle, gen): if m_id: self.init_ancestor_list(m_id, gen + 1) - def apply_real(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def reset(self): self.map.clear() diff --git a/gramps/gen/filters/rules/person/_islessthannthgenerationancestorofdefaultperson.py b/gramps/gen/filters/rules/person/_islessthannthgenerationancestorofdefaultperson.py index 8afef235388..28a18a4d78c 100644 --- a/gramps/gen/filters/rules/person/_islessthannthgenerationancestorofdefaultperson.py +++ b/gramps/gen/filters/rules/person/_islessthannthgenerationancestorofdefaultperson.py @@ -58,10 +58,9 @@ def prepare(self, db, user): p = db.get_default_person() if p: self.def_handle = p.get_handle() - self.apply = self.apply_real self.init_ancestor_list(self.def_handle, 1) else: - self.apply = lambda db, p: False + self.def_handle = None def init_ancestor_list(self, handle, gen): # if p.get_handle() in self.map: @@ -88,8 +87,8 @@ def init_ancestor_list(self, handle, gen): if m_id: self.init_ancestor_list(m_id, gen + 1) - def apply_real(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def reset(self): self.map.clear() diff --git a/gramps/gen/filters/rules/person/_islessthannthgenerationdescendantof.py b/gramps/gen/filters/rules/person/_islessthannthgenerationdescendantof.py index d6429edbc0e..c6ee2b0ab40 100644 --- a/gramps/gen/filters/rules/person/_islessthannthgenerationdescendantof.py +++ b/gramps/gen/filters/rules/person/_islessthannthgenerationdescendantof.py @@ -64,8 +64,8 @@ def prepare(self, db, user): def reset(self): self.map.clear() - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def init_list(self, person, gen): if not person or person.handle in self.map: diff --git a/gramps/gen/filters/rules/person/_ismale.py b/gramps/gen/filters/rules/person/_ismale.py index 1349ea18c9a..e0ea087f693 100644 --- a/gramps/gen/filters/rules/person/_ismale.py +++ b/gramps/gen/filters/rules/person/_ismale.py @@ -48,5 +48,5 @@ class IsMale(Rule): category = _("General filters") description = _("Matches all males") - def apply(self, db, person): - return person.gender == Person.MALE + def apply_to_one(self, db, data): + return data["gender"] == Person.MALE diff --git a/gramps/gen/filters/rules/person/_ismorethannthgenerationancestorof.py b/gramps/gen/filters/rules/person/_ismorethannthgenerationancestorof.py index 0391d9bafba..10500fa5079 100644 --- a/gramps/gen/filters/rules/person/_ismorethannthgenerationancestorof.py +++ b/gramps/gen/filters/rules/person/_ismorethannthgenerationancestorof.py @@ -84,5 +84,5 @@ def init_ancestor_list(self, root_handle): def reset(self): self.map.clear() - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map diff --git a/gramps/gen/filters/rules/person/_ismorethannthgenerationdescendantof.py b/gramps/gen/filters/rules/person/_ismorethannthgenerationdescendantof.py index 6869df63142..e1494cb04da 100644 --- a/gramps/gen/filters/rules/person/_ismorethannthgenerationdescendantof.py +++ b/gramps/gen/filters/rules/person/_ismorethannthgenerationdescendantof.py @@ -64,8 +64,8 @@ def prepare(self, db, user): def reset(self): self.map.clear() - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def init_list(self, person, gen): if not person: diff --git a/gramps/gen/filters/rules/person/_isparentoffiltermatch.py b/gramps/gen/filters/rules/person/_isparentoffiltermatch.py index a262ac23e31..14bf8dec59e 100644 --- a/gramps/gen/filters/rules/person/_isparentoffiltermatch.py +++ b/gramps/gen/filters/rules/person/_isparentoffiltermatch.py @@ -34,6 +34,7 @@ # ------------------------------------------------------------------------- from .. import Rule from ._matchesfilter import MatchesFilter +from gramps.gen.lib.serialize import from_dict # ------------------------------------------------------------------------- @@ -61,11 +62,11 @@ def prepare(self, db, user): _("Retrieving all sub-filter matches"), db.get_number_of_people(), ) - for person in db.iter_people(): + for handle, person_data in db._iter_raw_person_data(): if user: user.step_progress() - if self.filt.apply(db, person): - self.init_list(person) + if self.filt.apply_to_one(db, person_data): + self.init_list(from_dict(person_data)) if user: user.end_progress() @@ -73,8 +74,8 @@ def reset(self): self.filt.requestreset() self.map.clear() - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def init_list(self, person): for fam_id in person.get_parent_family_handle_list(): diff --git a/gramps/gen/filters/rules/person/_isrelatedwith.py b/gramps/gen/filters/rules/person/_isrelatedwith.py index c478257ff43..567d0240e04 100644 --- a/gramps/gen/filters/rules/person/_isrelatedwith.py +++ b/gramps/gen/filters/rules/person/_isrelatedwith.py @@ -55,17 +55,17 @@ def prepare(self, db, user): """ self.db = db - self.relatives = [] + self.map = set() self.add_relative(db.get_person_from_gramps_id(self.list[0])) def reset(self): - self.relatives = [] + self.map.clear() - def apply(self, db, person): - return person.handle in self.relatives + def apply_to_one(self, db, data): + return data["handle"] in self.map def add_relative(self, start): - """Non-recursive function that scans relatives and add them to self.relatives""" + """Non-recursive function that scans relatives and add them to self.map""" if not (start): return @@ -107,5 +107,5 @@ def add_relative(self, start): for child_ref in family.get_child_ref_list(): expand.append(self.db.get_person_from_handle(child_ref.ref)) - self.relatives = list(relatives.keys()) + self.map = set(list(relatives.keys())) return diff --git a/gramps/gen/filters/rules/person/_issiblingoffiltermatch.py b/gramps/gen/filters/rules/person/_issiblingoffiltermatch.py index d6974d2d0fd..344730af5e9 100644 --- a/gramps/gen/filters/rules/person/_issiblingoffiltermatch.py +++ b/gramps/gen/filters/rules/person/_issiblingoffiltermatch.py @@ -34,6 +34,7 @@ # ------------------------------------------------------------------------- from .. import Rule from ._matchesfilter import MatchesFilter +from gramps.gen.lib.serialize import from_dict # ------------------------------------------------------------------------- @@ -60,11 +61,11 @@ def prepare(self, db, user): _("Retrieving all sub-filter matches"), db.get_number_of_people(), ) - for person in db.iter_people(): + for handle, person_data in db._iter_raw_person_data(): if user: user.step_progress() - if self.matchfilt.apply(db, person): - self.init_list(person) + if self.matchfilt.apply_to_one(db, person_data): + self.init_list(from_dict(person_data)) if user: user.end_progress() @@ -72,8 +73,8 @@ def reset(self): self.matchfilt.requestreset() self.map.clear() - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def init_list(self, person): if not person: diff --git a/gramps/gen/filters/rules/person/_isspouseoffiltermatch.py b/gramps/gen/filters/rules/person/_isspouseoffiltermatch.py index c96f88a6acd..04a62740bc8 100644 --- a/gramps/gen/filters/rules/person/_isspouseoffiltermatch.py +++ b/gramps/gen/filters/rules/person/_isspouseoffiltermatch.py @@ -54,7 +54,8 @@ def prepare(self, db, user): self.filt = MatchesFilter(self.list) self.filt.requestprepare(db, user) - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for family_handle in person.get_family_handle_list(): family = db.get_family_from_handle(family_handle) if family: @@ -66,7 +67,8 @@ def apply(self, db, person): continue if spouse_id == person.handle: continue - if self.filt.apply(db, db.get_person_from_handle(spouse_id)): + person_data = db.get_raw_person_data(spouse_id) + if self.filt.apply_to_one(db, person_data): return True return False diff --git a/gramps/gen/filters/rules/person/_iswitness.py b/gramps/gen/filters/rules/person/_iswitness.py index a7d755c281e..7abc8f0d2de 100644 --- a/gramps/gen/filters/rules/person/_iswitness.py +++ b/gramps/gen/filters/rules/person/_iswitness.py @@ -62,10 +62,11 @@ def prepare(self, db, user): self.event_type = EventType() self.event_type.set_from_xml_str(self.list[0]) - def apply(self, db, obj): + def apply_to_one(self, db, data): """ Apply the rule. Return True on a match. """ + obj = self.get_object(data) for event_ref in obj.event_ref_list: if event_ref.role == EventRoleType.WITNESS: # This is the witness. diff --git a/gramps/gen/filters/rules/person/_matchidof.py b/gramps/gen/filters/rules/person/_matchidof.py index 52aca2709ca..d3874b78fb7 100644 --- a/gramps/gen/filters/rules/person/_matchidof.py +++ b/gramps/gen/filters/rules/person/_matchidof.py @@ -48,5 +48,5 @@ class MatchIdOf(Rule): description = _("Matches person with a specified Gramps ID") category = _("General filters") - def apply(self, db, person): - return person.gramps_id.find(self.list[0]) != -1 + def apply_to_one(self, db, data): + return data["gramps_id"].find(self.list[0]) != -1 diff --git a/gramps/gen/filters/rules/person/_missingparent.py b/gramps/gen/filters/rules/person/_missingparent.py index 2ee7aea8530..41090cfd474 100644 --- a/gramps/gen/filters/rules/person/_missingparent.py +++ b/gramps/gen/filters/rules/person/_missingparent.py @@ -50,7 +50,8 @@ class MissingParent(Rule): ) category = _("Family filters") - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) families = person.get_parent_family_handle_list() if families == []: return True diff --git a/gramps/gen/filters/rules/person/_multiplemarriages.py b/gramps/gen/filters/rules/person/_multiplemarriages.py index 30532b2d504..7be0d8fb434 100644 --- a/gramps/gen/filters/rules/person/_multiplemarriages.py +++ b/gramps/gen/filters/rules/person/_multiplemarriages.py @@ -45,5 +45,5 @@ class MultipleMarriages(Rule): description = _("Matches people who have more than one spouse") category = _("Family filters") - def apply(self, db, person): - return len(person.get_family_handle_list()) > 1 + def apply_to_one(self, db, data): + return len(data["family_list"]) > 1 diff --git a/gramps/gen/filters/rules/person/_nevermarried.py b/gramps/gen/filters/rules/person/_nevermarried.py index 66a9634d2c8..88b46f12f9b 100644 --- a/gramps/gen/filters/rules/person/_nevermarried.py +++ b/gramps/gen/filters/rules/person/_nevermarried.py @@ -45,5 +45,5 @@ class NeverMarried(Rule): description = _("Matches people who have no spouse") category = _("Family filters") - def apply(self, db, person): - return len(person.get_family_handle_list()) == 0 + def apply_to_one(self, db, data): + return len(data["family_list"]) == 0 diff --git a/gramps/gen/filters/rules/person/_nobirthdate.py b/gramps/gen/filters/rules/person/_nobirthdate.py index 22e979a15b5..be6b9996490 100644 --- a/gramps/gen/filters/rules/person/_nobirthdate.py +++ b/gramps/gen/filters/rules/person/_nobirthdate.py @@ -45,7 +45,9 @@ class NoBirthdate(Rule): description = _("Matches people without a known birthdate") category = _("General filters") - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) + # FIXME: can probably do all of this without object: birth_ref = person.get_birth_ref() if not birth_ref: return True diff --git a/gramps/gen/filters/rules/person/_nodeathdate.py b/gramps/gen/filters/rules/person/_nodeathdate.py index 6884d69d9e4..56e710d927d 100644 --- a/gramps/gen/filters/rules/person/_nodeathdate.py +++ b/gramps/gen/filters/rules/person/_nodeathdate.py @@ -45,7 +45,8 @@ class NoDeathdate(Rule): description = _("Matches people without a known deathdate") category = _("General filters") - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) death_ref = person.get_death_ref() if not death_ref: return True diff --git a/gramps/gen/filters/rules/person/_personwithincompleteevent.py b/gramps/gen/filters/rules/person/_personwithincompleteevent.py index 58ce20d7b31..d0ddcb9df26 100644 --- a/gramps/gen/filters/rules/person/_personwithincompleteevent.py +++ b/gramps/gen/filters/rules/person/_personwithincompleteevent.py @@ -45,7 +45,8 @@ class PersonWithIncompleteEvent(Rule): description = _("Matches people with missing date or place in an event") category = _("Event filters") - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for event_ref in person.get_event_ref_list(): if event_ref: event = db.get_event_from_handle(event_ref.ref) diff --git a/gramps/gen/filters/rules/person/_probablyalive.py b/gramps/gen/filters/rules/person/_probablyalive.py index 91d9e80b690..cbbedd0efb5 100644 --- a/gramps/gen/filters/rules/person/_probablyalive.py +++ b/gramps/gen/filters/rules/person/_probablyalive.py @@ -54,5 +54,6 @@ def prepare(self, db, user): except: self.current_date = None - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) return probably_alive(person, db, self.current_date) diff --git a/gramps/gen/filters/rules/person/_regexpname.py b/gramps/gen/filters/rules/person/_regexpname.py index 95aa6dc2740..48d3da049e9 100644 --- a/gramps/gen/filters/rules/person/_regexpname.py +++ b/gramps/gen/filters/rules/person/_regexpname.py @@ -53,7 +53,8 @@ class RegExpName(Rule): category = _("General filters") allow_regex = True - def apply(self, db, person): + def apply_to_one(self, db, data): + person = self.get_object(data) for name in [person.get_primary_name()] + person.get_alternate_names(): for field in [ name.first_name, diff --git a/gramps/gen/filters/rules/person/_relationshippathbetween.py b/gramps/gen/filters/rules/person/_relationshippathbetween.py index 39b786afd45..881d5614c3f 100644 --- a/gramps/gen/filters/rules/person/_relationshippathbetween.py +++ b/gramps/gen/filters/rules/person/_relationshippathbetween.py @@ -95,8 +95,8 @@ def apply_filter(self, rank, handle, plist, pmap): self.apply_filter(rank + 1, family.get_father_handle(), plist, pmap) self.apply_filter(rank + 1, family.get_mother_handle(), plist, pmap) - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map def init_list(self, p1_handle, p2_handle): firstMap = {} diff --git a/gramps/gen/filters/rules/person/_relationshippathbetweenbookmarks.py b/gramps/gen/filters/rules/person/_relationshippathbetweenbookmarks.py index 9c4619523a3..1cac75e2ee0 100644 --- a/gramps/gen/filters/rules/person/_relationshippathbetweenbookmarks.py +++ b/gramps/gen/filters/rules/person/_relationshippathbetweenbookmarks.py @@ -166,5 +166,5 @@ def init_list(self): except: pass - def apply(self, db, person): - return person.handle in self.map + def apply_to_one(self, db, data): + return data["handle"] in self.map diff --git a/gramps/gen/filters/rules/person/_searchname.py b/gramps/gen/filters/rules/person/_searchname.py index f6b62be8d5b..1173d93e382 100644 --- a/gramps/gen/filters/rules/person/_searchname.py +++ b/gramps/gen/filters/rules/person/_searchname.py @@ -49,11 +49,12 @@ class SearchName(Rule): description = _("Matches people with a specified (partial) name") category = _("General filters") - def apply(self, db, person): + def apply_to_one(self, db, data): src = self.list[0].upper() if not src: return False + person = self.get_object(data) for name in [person.get_primary_name()] + person.get_alternate_names(): for field in [ name.first_name, diff --git a/gramps/gen/filters/rules/place/_hasdata.py b/gramps/gen/filters/rules/place/_hasdata.py index cf431af5ec5..1ceab2d410c 100644 --- a/gramps/gen/filters/rules/place/_hasdata.py +++ b/gramps/gen/filters/rules/place/_hasdata.py @@ -67,7 +67,8 @@ def prepare(self, db, user): self.place_type = PlaceType() self.place_type.set_from_xml_str(self.list[1]) - def apply(self, _db, obj): + def apply_to_one(self, _db, data): + obj = self.get_object(data) """ Apply the rule. Return True on a match. """ diff --git a/gramps/gen/filters/rules/place/_hasnolatorlon.py b/gramps/gen/filters/rules/place/_hasnolatorlon.py index 768592d3c5a..c3f7153d3ec 100644 --- a/gramps/gen/filters/rules/place/_hasnolatorlon.py +++ b/gramps/gen/filters/rules/place/_hasnolatorlon.py @@ -50,7 +50,7 @@ class HasNoLatOrLon(Rule): description = _("Matches places with empty latitude or longitude") category = _("Position filters") - def apply(self, db, place): - if place.get_latitude().strip and place.get_longitude().strip(): + def apply_to_one(self, db, data): + if data["lat"].strip and data["long"].strip(): return False return True diff --git a/gramps/gen/filters/rules/place/_hasplace.py b/gramps/gen/filters/rules/place/_hasplace.py index 544a1cc8f2a..4e854a7b0da 100644 --- a/gramps/gen/filters/rules/place/_hasplace.py +++ b/gramps/gen/filters/rules/place/_hasplace.py @@ -73,7 +73,8 @@ class HasPlace(Rule): PlaceType.PARISH: 8, } - def apply(self, db, place): + def apply_to_one(self, db, data): + place = self.get_object(data) if not self.match_substring(0, place.get_title()): return False diff --git a/gramps/gen/filters/rules/place/_hastitle.py b/gramps/gen/filters/rules/place/_hastitle.py index 6820e480e81..b60f6d7e5fe 100644 --- a/gramps/gen/filters/rules/place/_hastitle.py +++ b/gramps/gen/filters/rules/place/_hastitle.py @@ -53,7 +53,8 @@ class HasTitle(Rule): category = _("General filters") allow_regex = True - def apply(self, db, place): + def apply_to_one(self, db, data): + place = self.get_object(data) if not self.match_substring(0, displayer.display(db, place)): return False return True diff --git a/gramps/gen/filters/rules/place/_inlatlonneighborhood.py b/gramps/gen/filters/rules/place/_inlatlonneighborhood.py index c3c6bfa0b40..e55b7ac6319 100644 --- a/gramps/gen/filters/rules/place/_inlatlonneighborhood.py +++ b/gramps/gen/filters/rules/place/_inlatlonneighborhood.py @@ -131,7 +131,7 @@ def prepare(self, db, user): self.E2 = 180.0 self.W = -180 - def apply(self, db, place): + def apply_to_one(self, db, data): if self.halfheight == -1 and self.halfwidth == -1: return False @@ -145,6 +145,8 @@ def apply(self, db, place): # now we know at least one is given in the filter and is valid + place = self.get_object(data) + # FIXME: rest can probably be done in data: # the place we look at must have lat AND lon entered if not (place.get_latitude().strip and place.get_longitude().strip()): return False diff --git a/gramps/gen/filters/rules/place/_isenclosedby.py b/gramps/gen/filters/rules/place/_isenclosedby.py index 7be1b88465f..a59c3a29323 100644 --- a/gramps/gen/filters/rules/place/_isenclosedby.py +++ b/gramps/gen/filters/rules/place/_isenclosedby.py @@ -58,11 +58,11 @@ def prepare(self, db, user): if place: self.handle = place.handle - def apply(self, db, place): + def apply_to_one(self, db, data): if self.handle is None: return False - if self.list[1] == "1" and place.handle == self.handle: + if self.list[1] == "1" and data["handle"] == self.handle: return True - if located_in(db, place.handle, self.handle): + if located_in(db, data["handle"], self.handle): return True return False diff --git a/gramps/gen/filters/rules/place/_matcheseventfilter.py b/gramps/gen/filters/rules/place/_matcheseventfilter.py index b5a8745d250..510124ef23f 100644 --- a/gramps/gen/filters/rules/place/_matcheseventfilter.py +++ b/gramps/gen/filters/rules/place/_matcheseventfilter.py @@ -58,12 +58,13 @@ class MatchesEventFilter(MatchesFilterBase): # we want to have this filter show event filters namespace = "Event" - def apply(self, db, event): + def apply_to_one(self, db, data): filt = self.find_filter() if filt: for classname, handle in db.find_backlink_handles( - event.get_handle(), ["Event"] + data["handle"], ["Event"] ): - if filt.check(db, handle): + event_data = db.get_raw_event_data(handle) + if filt.apply_to_one(db, event_data): return True return False diff --git a/gramps/gen/filters/rules/place/_withinarea.py b/gramps/gen/filters/rules/place/_withinarea.py index 6f312285350..759c0298fc2 100644 --- a/gramps/gen/filters/rules/place/_withinarea.py +++ b/gramps/gen/filters/rules/place/_withinarea.py @@ -106,16 +106,16 @@ def prepare(self, db, user): self.radius = float(value) self.radius = self.radius / 2 - def apply(self, dummy_db, place): + def apply_to_one(self, dummy_db, data): if self.handle is None: return False if self.latitude is None: return False if self.longitude is None: return False - if place: - lat = place.get_latitude() - lon = place.get_longitude() + if data: + lat = data["lat"] + lon = data["long"] if lat and lon: latit, longit = conv_lat_lon(lat, lon, "D.D8") if latit is None or longit is None: diff --git a/gramps/gen/filters/rules/repository/_hasrepo.py b/gramps/gen/filters/rules/repository/_hasrepo.py index e2afb39add6..140e54ac306 100644 --- a/gramps/gen/filters/rules/repository/_hasrepo.py +++ b/gramps/gen/filters/rules/repository/_hasrepo.py @@ -67,10 +67,12 @@ def prepare(self, db, user): self.rtype = RepositoryType() self.rtype.set_from_xml_str(self.list[1]) - def apply(self, _db, obj): + def apply_to_one(self, _db, data): """ Apply the rule. Return True on a match. """ + obj = self.get_object(data) + # FIXME: probably can do the rest without object: if not self.match_substring(0, obj.get_name()): return False diff --git a/gramps/gen/filters/rules/repository/_matchesnamesubstringof.py b/gramps/gen/filters/rules/repository/_matchesnamesubstringof.py index 8ae45db63c4..876e90fdf1c 100644 --- a/gramps/gen/filters/rules/repository/_matchesnamesubstringof.py +++ b/gramps/gen/filters/rules/repository/_matchesnamesubstringof.py @@ -47,6 +47,6 @@ class MatchesNameSubstringOf(Rule): category = _("General filters") allow_regex = True - def apply(self, db, repository): + def apply_to_one(self, db, data): """Apply the filter""" - return self.match_substring(0, repository.get_name()) + return self.match_substring(0, data["name"]) diff --git a/gramps/gen/filters/rules/source/_hasrepository.py b/gramps/gen/filters/rules/source/_hasrepository.py index e1c9c8e626a..a23fc4d0f4c 100644 --- a/gramps/gen/filters/rules/source/_hasrepository.py +++ b/gramps/gen/filters/rules/source/_hasrepository.py @@ -61,8 +61,8 @@ def prepare(self, db, user): self.userSelectedCount = int(self.list[0]) - def apply(self, db, obj): - count = len(obj.get_reporef_list()) + def apply_to_one(self, db, data): + count = len(data["reporef_list"]) if self.count_type == 0: # "less than" return count < self.userSelectedCount elif self.count_type == 2: # "greater than" diff --git a/gramps/gen/filters/rules/source/_hasrepositorycallnumberref.py b/gramps/gen/filters/rules/source/_hasrepositorycallnumberref.py index 090172cf654..647274dd862 100644 --- a/gramps/gen/filters/rules/source/_hasrepositorycallnumberref.py +++ b/gramps/gen/filters/rules/source/_hasrepositorycallnumberref.py @@ -51,8 +51,8 @@ class HasRepositoryCallNumberRef(Rule): category = _("General filters") allow_regex = True - def apply(self, db, obj): - for repo_ref in obj.get_reporef_list(): - if self.match_substring(0, repo_ref.call_number): + def apply_to_one(self, db, data): + for repo_ref in data["reporef_list"]: + if self.match_substring(0, repo_ref["call_number"]): return True return False diff --git a/gramps/gen/filters/rules/source/_matchesrepositoryfilter.py b/gramps/gen/filters/rules/source/_matchesrepositoryfilter.py index 2c0e8f18222..7b9a60ebb82 100644 --- a/gramps/gen/filters/rules/source/_matchesrepositoryfilter.py +++ b/gramps/gen/filters/rules/source/_matchesrepositoryfilter.py @@ -57,13 +57,14 @@ def prepare(self, db, user): MatchesFilterBase.prepare(self, db, user) self.MRF_filt = self.find_filter() - def apply(self, db, object): + def apply_to_one(self, db, data): if self.MRF_filt is None: return False - repolist = [x.ref for x in object.get_reporef_list()] + repolist = [x.ref for x in data["reporef_list"]] for repohandle in repolist: # check if repo in repository filter - if self.MRF_filt.check(db, repohandle): + repo_data = self.get_raw_repository_data(repohandle) + if self.MRF_filt.apply_to_one(db, repo_data): return True return False diff --git a/gramps/gen/filters/rules/source/_matchestitlesubstringof.py b/gramps/gen/filters/rules/source/_matchestitlesubstringof.py index e88e70c7362..51ebadfd50e 100644 --- a/gramps/gen/filters/rules/source/_matchestitlesubstringof.py +++ b/gramps/gen/filters/rules/source/_matchestitlesubstringof.py @@ -47,6 +47,6 @@ class MatchesTitleSubstringOf(Rule): category = _("General filters") allow_regex = True - def apply(self, db, source): + def apply_to_one(self, db, data): """Apply the filter""" - return self.match_substring(0, source.get_title()) + return self.match_substring(0, data["title"]) diff --git a/gramps/gui/views/treemodels/placemodel.py b/gramps/gui/views/treemodels/placemodel.py index 07c1129f6ab..2ee0d9f25e3 100644 --- a/gramps/gui/views/treemodels/placemodel.py +++ b/gramps/gui/views/treemodels/placemodel.py @@ -139,7 +139,7 @@ def column_name(self, data): def search_name(self, data): """The search name includes all alt names to enable finding by alt name""" return ",".join( - [data["name"]["value"]] + [name["value"] for name in data["alt_name"]] + [data["name"]["value"]] + [name["value"] for name in data["alt_names"]] ) def column_longitude(self, data):