New proxy that traces forward references

svn: r15499
This commit is contained in:
Doug Blank 2010-05-29 20:17:06 +00:00
parent 2a44a7dd77
commit 34c7efe804
3 changed files with 444 additions and 0 deletions

View File

@ -11,6 +11,7 @@ pkgdata_PYTHON = \
living.py \ living.py \
private.py \ private.py \
referenced.py \ referenced.py \
referencedbyselection.py \
proxybase.py proxybase.py
pkgpyexecdir = @pkgpyexecdir@/gen/proxy pkgpyexecdir = @pkgpyexecdir@/gen/proxy

View File

@ -25,3 +25,4 @@ from filter import FilterProxyDb
from living import LivingProxyDb from living import LivingProxyDb
from private import PrivateProxyDb from private import PrivateProxyDb
from referenced import ReferencedProxyDb from referenced import ReferencedProxyDb
from referencedbyselection import ReferencedBySelectionProxyDb

View File

@ -0,0 +1,442 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id $
"""
Proxy class for the GRAMPS databases. Returns objects which are
referenced by a person, or through a chain of references starting with
a person.
"""
#-------------------------------------------------------------------------
#
# GRAMPS libraries
#
#-------------------------------------------------------------------------
from proxybase import ProxyDbBase
class ReferencedBySelectionProxyDb(ProxyDbBase):
"""
A proxy to a Gramps database. This proxy will act like a Gramps
database, but returning all objects which are referenced by a
selection, or by an object that is referenced by an object which
is eventually referenced by one of the selected objects.
"""
def __init__(self, dbase, all_people=False):
"""
Create a new ReferencedByPeopleProxyDb instance.
all_people - if True, get all people, and the items they link
to; if False, get all people that are connected to something,
and all of items they link to.
"""
ProxyDbBase.__init__(self, dbase)
self.reset_references()
# If restricted_to["Person"] is a set, restrict process to
# them, and do not process others outside of them
self.restricted_to = {"Person": None}
# Build lists of referenced objects
# iter through whatever object(s) you want to start
# the trace.
if all_people:
# Spread activation to all:
for person in self.db.iter_people():
self.process_person(person)
else:
# get rid of orphaned people:
# first, get all of the links from people:
for person in self.db.iter_people():
self.process_person(person, reference=False)
# save those people:
self.restricted_to["Person"] = self.referenced["Person"]
# reset, and just follow those people
self.reset_references()
for handle in self.restricted_to["Person"]:
self.process_object("Person", handle)
def reset_references(self):
self.referenced = {
"Person": set(),
"Family": set(),
"Event": set(),
"Place": set(),
"Source": set(),
"Repository": set(),
"MediaObject": set(),
"Note": set(),
}
def process_object(self, class_name, handle):
if class_name == "Person":
obj = self.db.get_person_from_handle(handle)
if obj:
self.process_person(obj)
elif class_name == "Family":
obj = self.db.get_family_from_handle(handle)
if obj:
self.process_family(obj)
elif class_name == "Event":
obj = self.db.get_event_from_handle(handle)
if obj:
self.process_event(obj)
elif class_name == "Place":
obj = self.db.get_place_from_handle(handle)
if obj:
self.process_place(obj)
elif class_name == "Source":
obj = self.db.get_source_from_handle(handle)
if obj:
self.process_source(obj)
elif class_name == "Repository":
obj = self.db.get_repository_from_handle(handle)
if obj:
self.process_repository(obj)
elif class_name == "MediaObject":
obj = self.db.get_object_from_handle(handle)
if obj:
self.process_media(obj)
elif class_name == "Note":
obj = self.db.get_note_from_handle(handle)
if obj:
self.process_note(obj)
else:
raise AttributeError("unknown class: '%s'" % class_name)
def process_person(self, person, reference=True):
"""
Follow the person object and find all of the primary objects
that it references.
"""
if person.handle in self.referenced["Person"]:
return
if (self.restricted_to["Person"] and
person.handle not in self.restricted_to["Person"]):
return
if reference:
# forward reference:
self.referenced["Person"].add(person.handle)
# include backward references to this object:
for (class_name, handle) in self.db.find_backlink_handles(
person.handle, ["Person", "Family"]):
self.process_object(class_name, handle)
name = person.get_primary_name()
if name:
self.process_name(name)
for handle in person.get_family_handle_list():
family = self.db.get_family_from_handle(handle)
if family:
self.process_family(family)
for handle in person.get_parent_family_handle_list():
family = self.db.get_family_from_handle(handle)
if family:
self.process_family(family)
for name in person.get_alternate_names():
if name:
self.process_name(name)
for event_ref in person.get_event_ref_list():
if event_ref:
event = self.db.get_event_from_handle(event_ref.ref)
if event:
self.process_event_ref(event_ref)
self.process_addresses(person)
self.process_attributes(person)
self.process_source_ref_list(person)
self.process_urls(person)
self.process_media_ref_list(person)
self.process_lds_ords(person)
self.process_notes(person)
self.process_associations(person)
def process_family(self, family):
"""
Follow the family object and find all of the primary objects
that it references.
"""
if family.handle in self.referenced["Family"]:
return
self.referenced["Family"].add(family.handle)
self.process_object("Person", family.mother_handle)
self.process_object("Person", family.father_handle)
for child_ref in family.get_child_ref_list():
if not child_ref:
continue
self.process_object("Person", child_ref.ref)
self.process_notes(child_ref)
self.process_source_ref_list(child_ref)
for event_ref in family.get_event_ref_list():
if event_ref:
event = self.db.get_event_from_handle(event_ref.ref)
if event:
self.process_event_ref(event_ref)
self.process_source_ref_list(family)
self.process_notes(family)
self.process_media_ref_list(family)
self.process_attributes(family)
self.process_lds_ords(family)
def process_event(self, event):
"""
Follow the event object and find all of the primary objects
that it references.
"""
if event.handle in self.referenced["Event"]:
return
self.referenced["Event"].add(event.handle)
self.process_source_ref_list(event)
self.process_notes(event)
self.process_media_ref_list(event)
self.process_attributes(event)
place_handle = event.get_place_handle()
place = self.db.get_place_from_handle(place_handle)
if place:
self.process_place(place)
def process_place(self, place):
"""
Follow the place object and find all of the primary objects
that it references.
"""
if place.handle in self.referenced["Place"]:
return
self.referenced["Place"].add(place.handle)
self.process_source_ref_list(place)
self.process_notes(place)
self.process_media_ref_list(place)
self.process_urls(place)
def process_source(self, source):
"""
Follow the source object and find all of the primary objects
that it references.
"""
if source.handle in self.referenced["Source"]:
return
self.referenced["Source"].add(source.handle)
for repo_ref in source.get_reporef_list():
if repo_ref:
self.process_notes(repo_ref)
handle = repo_ref.get_reference_handle()
repo = self.db.get_repository_from_handle(handle)
if repo:
self.process_repository(repo)
self.process_media_ref_list(source)
self.process_notes(source)
def process_repository(self, repository):
"""
Follow the repository object and find all of the primary objects
that it references.
"""
if repository.handle in self.referenced["Repository"]:
return
self.referenced["Repository"].add(repository.handle)
self.process_notes(repository)
self.process_addresses(repository)
self.process_urls(repository)
def process_media(self, media):
"""
Follow the media object and find all of the primary objects
that it references.
"""
if media.handle in self.referenced["MediaObject"]:
return
self.referenced["MediaObject"].add(media.handle)
self.process_source_ref_list(media)
self.process_attributes(media)
self.process_notes(media)
def process_notes(self, original_obj):
"""
Follow the note object and find all of the primary objects
that it references.
"""
for note_handle in original_obj.get_note_list():
if note_handle and note_handle not in self.referenced["Note"]:
note = self.db.get_note_from_handle(note_handle)
if note:
self.referenced["Note"].add(note_handle)
# --------------------------------------------
def process_name(self, name):
""" Find all of the primary objects referred to """
self.process_source_ref_list(name)
self.process_notes(name)
def process_addresses(self, original_obj):
""" Find all of the primary objects referred to """
for address in original_obj.get_address_list():
if address:
self.process_address(address)
def process_address(self, address):
""" Find all of the primary objects referred to """
self.process_source_ref_list(address)
self.process_notes(address)
def process_attributes(self, original_obj):
""" Find all of the primary objects referred to """
for attribute in original_obj.get_attribute_list():
if attribute:
self.process_notes(attribute)
self.process_source_ref_list(attribute)
def process_source_ref_list(self, original_obj):
""" Find all of the primary objects referred to """
for ref in original_obj.get_source_references():
if ref:
handle = ref.get_reference_handle()
source = self.db.get_source_from_handle(handle)
if source:
self.process_source_ref(ref)
def process_source_ref(self, srcref):
""" Find all of the primary objects referred to """
source = self.db.get_source_from_handle(srcref.ref)
if source:
self.process_source(source)
self.process_notes(srcref)
def process_urls(self, original_obj):
""" Find all of the primary objects referred to """
pass
def process_media_ref_list(self, original_obj):
""" Find all of the primary objects referred to """
for media_ref in original_obj.get_media_list():
if media_ref:
self.process_notes(media_ref)
self.process_attributes(media_ref)
self.process_source_ref_list(media_ref)
handle = media_ref.get_reference_handle()
media_object = self.db.get_object_from_handle(handle)
if media_object:
self.process_media(media_object)
def process_lds_ords(self, original_obj):
""" Find all of the primary objects referred to """
for lds_ord in original_obj.get_lds_ord_list():
if lds_ord:
self.process_lds_ord(lds_ord)
def process_lds_ord(self, lds_ord):
""" Find all of the primary objects referred to """
fam_handle = lds_ord.get_family_handle()
fam = self.db.get_family_from_handle(fam_handle)
if fam:
self.process_family(fam)
place_handle = lds_ord.get_place_handle()
place = self.db.get_place_from_handle(place_handle)
if place:
self.process_place(place)
self.process_source_ref_list(lds_ord)
self.process_notes(lds_ord)
def process_associations(self, original_obj):
""" Find all of the primary objects referred to """
for person_ref in original_obj.get_person_ref_list():
if person_ref:
self.process_source_ref_list(person_ref)
self.process_notes(person_ref)
person = self.db.get_person_from_handle(person_ref.ref)
if person:
self.process_person(person)
def process_event_ref(self, event_ref):
""" Find all of the primary objects referred to """
self.process_notes(event_ref)
self.process_attributes(event_ref)
event = self.db.get_event_from_handle(event_ref.ref)
if event:
self.process_event(event)
# ---------------------------------------------------
def include_person(self, handle):
"""
Filter for person
"""
return handle in self.referenced["Person"]
def include_place(self, handle):
"""
Filter for places
"""
return handle in self.referenced["Place"]
def include_family(self, handle):
"""
Filter for families
"""
return handle in self.referenced["Family"]
def include_media_object(self, handle):
"""
Filter for media objects
"""
return handle in self.referenced["MediaObject"]
def include_event(self, handle):
"""
Filter for events
"""
return handle in self.referenced["Event"]
def include_source(self, handle):
"""
Filter for sources
"""
return handle in self.referenced["Source"]
def include_repository(self, handle):
"""
Filter for repositories
"""
return handle in self.referenced["Repository"]
def include_note(self, handle):
"""
Filter for notes
"""
return handle in self.referenced["Note"]
def find_backlink_handles(self, handle, include_classes=None):
"""
Return appropriate backlink handles for this proxy.
"""
for (objclass, handle) in self.db.find_backlink_handles(handle,
include_classes):
if handle in self.referenced[objclass]:
yield (objclass, handle)