Merge pull request #102 from SNoiraud/bug5449
5449: Pedigree view crashes if you happen to choose a child as ancestor
This commit is contained in:
commit
4342b319e3
42
example/gramps/child-father-child-loop.gramps
Normal file
42
example/gramps/child-father-child-loop.gramps
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE database PUBLIC "-//Gramps//DTD Gramps XML 1.6.0//EN"
|
||||||
|
"http://gramps-project.org/xml/1.6.0/grampsxml.dtd">
|
||||||
|
<database xmlns="http://gramps-project.org/xml/1.6.0/">
|
||||||
|
<header>
|
||||||
|
<created date="2015-07-21" version="GrampsAIO64-4.1.3-1"/>
|
||||||
|
<researcher>
|
||||||
|
</researcher>
|
||||||
|
</header>
|
||||||
|
<people>
|
||||||
|
<person handle="_d12d89b02aa5121726adba4f517" change="1437459556" id="I0000">
|
||||||
|
<gender>M</gender>
|
||||||
|
<name type="Birth Name">
|
||||||
|
<first>Child</first>
|
||||||
|
<surname>Child</surname>
|
||||||
|
</name>
|
||||||
|
<childof hlink="_d12d8a32ae01d9449d5da18eda0"/>
|
||||||
|
<parentin hlink="_d12d8a7573462f21848658c9c5d"/>
|
||||||
|
</person>
|
||||||
|
<person handle="_d12d89d4dce7eaaa68e31f6100e" change="1437459556" id="I0001">
|
||||||
|
<gender>M</gender>
|
||||||
|
<name type="Birth Name">
|
||||||
|
<first>Father</first>
|
||||||
|
<surname>Father</surname>
|
||||||
|
</name>
|
||||||
|
<childof hlink="_d12d8a7573462f21848658c9c5d"/>
|
||||||
|
<parentin hlink="_d12d8a32ae01d9449d5da18eda0"/>
|
||||||
|
</person>
|
||||||
|
</people>
|
||||||
|
<families>
|
||||||
|
<family handle="_d12d8a32ae01d9449d5da18eda0" change="1437459531" id="F0000">
|
||||||
|
<rel type="Unknown"/>
|
||||||
|
<father hlink="_d12d89d4dce7eaaa68e31f6100e"/>
|
||||||
|
<childref hlink="_d12d89b02aa5121726adba4f517"/>
|
||||||
|
</family>
|
||||||
|
<family handle="_d12d8a7573462f21848658c9c5d" change="1437459556" id="F0001">
|
||||||
|
<rel type="Unknown"/>
|
||||||
|
<father hlink="_d12d89b02aa5121726adba4f517"/>
|
||||||
|
<childref hlink="_d12d89d4dce7eaaa68e31f6100e"/>
|
||||||
|
</family>
|
||||||
|
</families>
|
||||||
|
</database>
|
72
example/gramps/test_complex_loop.gramps
Normal file
72
example/gramps/test_complex_loop.gramps
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE database PUBLIC "-//Gramps//DTD Gramps XML 1.7.1//EN"
|
||||||
|
"http://gramps-project.org/xml/1.7.1/grampsxml.dtd">
|
||||||
|
<database xmlns="http://gramps-project.org/xml/1.7.1/">
|
||||||
|
<header>
|
||||||
|
<created date="2016-04-10" version="5.0.0"/>
|
||||||
|
<researcher>
|
||||||
|
</researcher>
|
||||||
|
</header>
|
||||||
|
<people>
|
||||||
|
<person handle="_d12d89b02aa5121726adba4f517" change="1456088166" id="I0000">
|
||||||
|
<gender>M</gender>
|
||||||
|
<name type="Birth Name">
|
||||||
|
<first>Child</first>
|
||||||
|
<surname>Child</surname>
|
||||||
|
</name>
|
||||||
|
<childof hlink="_d12d8a32ae01d9449d5da18eda0"/>
|
||||||
|
<childof hlink="_d3e382712c1429da71250fdc5b7"/>
|
||||||
|
<parentin hlink="_d12d8a7573462f21848658c9c5d"/>
|
||||||
|
</person>
|
||||||
|
<person handle="_d12d89d4dce7eaaa68e31f6100e" change="1437459556" id="I0001">
|
||||||
|
<gender>M</gender>
|
||||||
|
<name type="Birth Name">
|
||||||
|
<first>Father</first>
|
||||||
|
<surname>Father</surname>
|
||||||
|
</name>
|
||||||
|
<childof hlink="_d12d8a7573462f21848658c9c5d"/>
|
||||||
|
<parentin hlink="_d12d8a32ae01d9449d5da18eda0"/>
|
||||||
|
</person>
|
||||||
|
<person handle="_d3e381c6e76124b59bb9a4c312e" change="1456088118" id="I0002">
|
||||||
|
<gender>M</gender>
|
||||||
|
<name type="Birth Name">
|
||||||
|
<first>Child2</first>
|
||||||
|
<surname>Father</surname>
|
||||||
|
</name>
|
||||||
|
<childof hlink="_d12d8a32ae01d9449d5da18eda0"/>
|
||||||
|
<parentin hlink="_d3e38215ed8371bb62a9f7785f1"/>
|
||||||
|
</person>
|
||||||
|
<person handle="_d3e382494d07adfa45784539dce" change="1456088166" id="I0003">
|
||||||
|
<gender>M</gender>
|
||||||
|
<name type="Birth Name">
|
||||||
|
<first>Child3</first>
|
||||||
|
<surname>Father</surname>
|
||||||
|
</name>
|
||||||
|
<childof hlink="_d3e38215ed8371bb62a9f7785f1"/>
|
||||||
|
<parentin hlink="_d3e382712c1429da71250fdc5b7"/>
|
||||||
|
</person>
|
||||||
|
</people>
|
||||||
|
<families>
|
||||||
|
<family handle="_d12d8a32ae01d9449d5da18eda0" change="1456088074" id="F0000">
|
||||||
|
<rel type="Unknown"/>
|
||||||
|
<father hlink="_d12d89d4dce7eaaa68e31f6100e"/>
|
||||||
|
<childref hlink="_d12d89b02aa5121726adba4f517"/>
|
||||||
|
<childref hlink="_d3e381c6e76124b59bb9a4c312e"/>
|
||||||
|
</family>
|
||||||
|
<family handle="_d12d8a7573462f21848658c9c5d" change="1437459556" id="F0001">
|
||||||
|
<rel type="Unknown"/>
|
||||||
|
<father hlink="_d12d89b02aa5121726adba4f517"/>
|
||||||
|
<childref hlink="_d12d89d4dce7eaaa68e31f6100e"/>
|
||||||
|
</family>
|
||||||
|
<family handle="_d3e38215ed8371bb62a9f7785f1" change="1456088118" id="F0002">
|
||||||
|
<rel type="Unknown"/>
|
||||||
|
<father hlink="_d3e381c6e76124b59bb9a4c312e"/>
|
||||||
|
<childref hlink="_d3e382494d07adfa45784539dce"/>
|
||||||
|
</family>
|
||||||
|
<family handle="_d3e382712c1429da71250fdc5b7" change="1456088166" id="F0003">
|
||||||
|
<rel type="Unknown"/>
|
||||||
|
<father hlink="_d3e382494d07adfa45784539dce"/>
|
||||||
|
<childref hlink="_d12d89b02aa5121726adba4f517"/>
|
||||||
|
</family>
|
||||||
|
</families>
|
||||||
|
</database>
|
@ -86,6 +86,7 @@ class ProbablyAlive(object):
|
|||||||
self.MAX_SIB_AGE_DIFF = max_sib_age_diff
|
self.MAX_SIB_AGE_DIFF = max_sib_age_diff
|
||||||
self.MAX_AGE_PROB_ALIVE = max_age_prob_alive
|
self.MAX_AGE_PROB_ALIVE = max_age_prob_alive
|
||||||
self.AVG_GENERATION_GAP = avg_generation_gap
|
self.AVG_GENERATION_GAP = avg_generation_gap
|
||||||
|
self.pset = set()
|
||||||
|
|
||||||
def probably_alive_range(self, person, is_spouse=False):
|
def probably_alive_range(self, person, is_spouse=False):
|
||||||
# FIXME: some of these computed dates need to be a span. For
|
# FIXME: some of these computed dates need to be a span. For
|
||||||
@ -95,6 +96,7 @@ class ProbablyAlive(object):
|
|||||||
# "between 1930 and 1940")
|
# "between 1930 and 1940")
|
||||||
if person is None:
|
if person is None:
|
||||||
return (None, None, "", None)
|
return (None, None, "", None)
|
||||||
|
self.pset = set()
|
||||||
birth_ref = person.get_birth_ref()
|
birth_ref = person.get_birth_ref()
|
||||||
death_ref = person.get_death_ref()
|
death_ref = person.get_death_ref()
|
||||||
death_date = None
|
death_date = None
|
||||||
@ -272,6 +274,9 @@ class ProbablyAlive(object):
|
|||||||
# ago.
|
# ago.
|
||||||
|
|
||||||
def descendants_too_old (person, years):
|
def descendants_too_old (person, years):
|
||||||
|
if person.handle in self.pset:
|
||||||
|
return (None, None, "", None)
|
||||||
|
self.pset.add(person.handle)
|
||||||
for family_handle in person.get_family_handle_list():
|
for family_handle in person.get_family_handle_list():
|
||||||
family = self.db.get_family_from_handle(family_handle)
|
family = self.db.get_family_from_handle(family_handle)
|
||||||
if not family:
|
if not family:
|
||||||
@ -343,6 +348,9 @@ class ProbablyAlive(object):
|
|||||||
return (date1, date2, explain, other)
|
return (date1, date2, explain, other)
|
||||||
|
|
||||||
def ancestors_too_old(person, year):
|
def ancestors_too_old(person, year):
|
||||||
|
if person.handle in self.pset:
|
||||||
|
return (None, None, "", None)
|
||||||
|
self.pset.add(person.handle)
|
||||||
LOG.debug("ancestors_too_old('%s', %s)".format(
|
LOG.debug("ancestors_too_old('%s', %s)".format(
|
||||||
name_displayer.display(person), year) )
|
name_displayer.display(person), year) )
|
||||||
family_handle = person.get_main_parents_family_handle()
|
family_handle = person.get_main_parents_family_handle()
|
||||||
|
123
gramps/plugins/tool/findloop.glade
Normal file
123
gramps/plugins/tool/findloop.glade
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generated with glade 3.16.1 -->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="3.10"/>
|
||||||
|
<object class="GtkDialog" id="findloop">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="default_width">450</property>
|
||||||
|
<property name="default_height">400</property>
|
||||||
|
<property name="type_hint">dialog</property>
|
||||||
|
<signal name="delete-event" handler="on_delete_event" swapped="no"/>
|
||||||
|
<child internal-child="vbox">
|
||||||
|
<object class="GtkBox" id="dialog-vbox1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child internal-child="action_area">
|
||||||
|
<object class="GtkButtonBox" id="dialog-action_area1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="layout_style">end</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="close">
|
||||||
|
<property name="label">gtk-close</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="can_default">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
<signal name="clicked" handler="destroy_passed_object" swapped="yes"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="helpbutton1">
|
||||||
|
<property name="label">gtk-help</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="can_default">True</property>
|
||||||
|
<property name="receives_default">False</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
<signal name="clicked" handler="on_help_clicked" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="pack_type">end</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="vbox1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="border_width">6</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="title">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="justify">center</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="padding">8</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow" id="scrolledwindow1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="shadow_type">out</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkTreeView" id="treeview">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<child internal-child="selection">
|
||||||
|
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<placeholder/>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<action-widgets>
|
||||||
|
<action-widget response="0">close</action-widget>
|
||||||
|
</action-widgets>
|
||||||
|
</object>
|
||||||
|
</interface>
|
219
gramps/plugins/tool/findloop.py
Normal file
219
gramps/plugins/tool/findloop.py
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
#
|
||||||
|
# Gramps - a GTK+/GNOME based genealogy program
|
||||||
|
#
|
||||||
|
# Copyright (C) 2007-2009 Stephane Charette
|
||||||
|
# Copyright (C) 2016- Serge Noiraud
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
|
||||||
|
"Find possible loop in a people descendance"
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# GNOME/GTK modules
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import GObject
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Gramps modules
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||||
|
_ = glocale.translation.sgettext
|
||||||
|
ngettext = glocale.translation.ngettext # else "nearby" comments are ignored
|
||||||
|
from gramps.gen.const import URL_MANUAL_PAGE
|
||||||
|
from gramps.gui.plug import tool
|
||||||
|
from gramps.gen.plug.report import utils as ReportUtils
|
||||||
|
from gramps.gui.editors import EditPerson, EditFamily
|
||||||
|
from gramps.gui.managedwindow import ManagedWindow
|
||||||
|
from gramps.gui.utils import ProgressMeter
|
||||||
|
from gramps.gui.display import display_help
|
||||||
|
from gramps.gui.glade import Glade
|
||||||
|
from gramps.gen.lib import Tag
|
||||||
|
from gramps.gen.db import DbTxn
|
||||||
|
from gramps.gen.display.name import displayer as _nd
|
||||||
|
from gramps.gui.editors import EditFamily
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Constants
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
WIKI_HELP_PAGE = '%s_-_Tools' % URL_MANUAL_PAGE
|
||||||
|
WIKI_HELP_SEC = _('manual|Find_database_loop')
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# FindLoop class
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
class FindLoop(ManagedWindow) :
|
||||||
|
|
||||||
|
def __init__(self, dbstate, user, options_class, name, callback=None):
|
||||||
|
uistate = user.uistate
|
||||||
|
|
||||||
|
self.title = _('Find database loop')
|
||||||
|
ManagedWindow.__init__(self, uistate, [], self.__class__)
|
||||||
|
self.dbstate = dbstate
|
||||||
|
self.uistate = uistate
|
||||||
|
self.db = dbstate.db
|
||||||
|
|
||||||
|
topDialog = Glade()
|
||||||
|
|
||||||
|
topDialog.connect_signals({
|
||||||
|
"destroy_passed_object" : self.close,
|
||||||
|
"on_help_clicked" : self.on_help_clicked,
|
||||||
|
"on_delete_event" : self.close,
|
||||||
|
})
|
||||||
|
|
||||||
|
window = topDialog.toplevel
|
||||||
|
title = topDialog.get_object("title")
|
||||||
|
self.set_window(window, title, self.title)
|
||||||
|
|
||||||
|
# start the progress indicator
|
||||||
|
self.progress = ProgressMeter(self.title,_('Starting'),
|
||||||
|
parent=self.window)
|
||||||
|
self.progress.set_pass(_('Looking for possible loop for each person'),
|
||||||
|
self.db.get_number_of_people())
|
||||||
|
|
||||||
|
self.model = Gtk.ListStore(
|
||||||
|
GObject.TYPE_STRING, # 0==father id
|
||||||
|
GObject.TYPE_STRING, # 1==father
|
||||||
|
GObject.TYPE_STRING, # 2==son id
|
||||||
|
GObject.TYPE_STRING, # 3==son
|
||||||
|
GObject.TYPE_STRING) # 4==family gid
|
||||||
|
|
||||||
|
self.treeView = topDialog.get_object("treeview")
|
||||||
|
self.treeView.set_model(self.model)
|
||||||
|
col1 = Gtk.TreeViewColumn(_('Gramps ID'), Gtk.CellRendererText(), text=0)
|
||||||
|
col2 = Gtk.TreeViewColumn(_('Ancestor'), Gtk.CellRendererText(), text=1)
|
||||||
|
col3 = Gtk.TreeViewColumn(_('Gramps ID'), Gtk.CellRendererText(), text=2)
|
||||||
|
col4 = Gtk.TreeViewColumn(_('Descendant'), Gtk.CellRendererText(), text=3)
|
||||||
|
col5 = Gtk.TreeViewColumn(_('Family ID'), Gtk.CellRendererText(), text=4)
|
||||||
|
col1.set_resizable(True)
|
||||||
|
col2.set_resizable(True)
|
||||||
|
col3.set_resizable(True)
|
||||||
|
col4.set_resizable(True)
|
||||||
|
col5.set_resizable(True)
|
||||||
|
col1.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
|
col2.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
|
col3.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
|
col4.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
|
col5.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
|
||||||
|
col1.set_sort_column_id(0)
|
||||||
|
col2.set_sort_column_id(1)
|
||||||
|
col3.set_sort_column_id(2)
|
||||||
|
col4.set_sort_column_id(3)
|
||||||
|
col5.set_sort_column_id(4)
|
||||||
|
self.treeView.append_column(col1)
|
||||||
|
self.treeView.append_column(col2)
|
||||||
|
self.treeView.append_column(col3)
|
||||||
|
self.treeView.append_column(col4)
|
||||||
|
self.treeView.append_column(col5)
|
||||||
|
self.treeSelection = self.treeView.get_selection()
|
||||||
|
self.treeView.connect('row-activated', self.rowActivated)
|
||||||
|
|
||||||
|
people = self.db.get_person_handles()
|
||||||
|
count = 0
|
||||||
|
for person_handle in people:
|
||||||
|
person = self.db.get_person_from_handle(person_handle)
|
||||||
|
count += 1
|
||||||
|
self.current = person
|
||||||
|
self.parent = None
|
||||||
|
self.descendants(person_handle, set())
|
||||||
|
self.progress.set_header("%d/%d" % (count, len(people)))
|
||||||
|
self.progress.step()
|
||||||
|
|
||||||
|
# close the progress bar
|
||||||
|
self.progress.close()
|
||||||
|
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def descendants(self, person_handle, new_list):
|
||||||
|
person = self.db.get_person_from_handle(person_handle)
|
||||||
|
pset = set()
|
||||||
|
for item in new_list:
|
||||||
|
pset.add(item)
|
||||||
|
if person.handle in pset:
|
||||||
|
# We found one loop
|
||||||
|
father_id = self.current.get_gramps_id()
|
||||||
|
father = _nd.display(self.current)
|
||||||
|
son_id = self.parent.get_gramps_id()
|
||||||
|
son = _nd.display(self.parent)
|
||||||
|
value = (father_id, father, son_id, son, self.curr_fam)
|
||||||
|
found = False
|
||||||
|
for pth in range(len(self.model)):
|
||||||
|
path = Gtk.TreePath(pth)
|
||||||
|
treeiter = self.model.get_iter(path)
|
||||||
|
find = (self.model.get_value(treeiter, 0),
|
||||||
|
self.model.get_value(treeiter, 1),
|
||||||
|
self.model.get_value(treeiter, 2),
|
||||||
|
self.model.get_value(treeiter, 3),
|
||||||
|
self.model.get_value(treeiter, 4))
|
||||||
|
if find == value:
|
||||||
|
found = True
|
||||||
|
if not found:
|
||||||
|
self.model.append(value)
|
||||||
|
return
|
||||||
|
pset.add(person.handle)
|
||||||
|
for family_handle in person.get_family_handle_list():
|
||||||
|
family = self.db.get_family_from_handle(family_handle)
|
||||||
|
self.curr_fam = family.get_gramps_id()
|
||||||
|
if not family:
|
||||||
|
# can happen with LivingProxyDb(PrivateProxyDb(db))
|
||||||
|
continue
|
||||||
|
for child_ref in family.get_child_ref_list():
|
||||||
|
child_handle = child_ref.ref
|
||||||
|
self.parent = person
|
||||||
|
self.descendants(child_handle, pset)
|
||||||
|
|
||||||
|
def rowActivated(self, treeView, path, column) :
|
||||||
|
# first we need to check that the row corresponds to a person
|
||||||
|
iter = self.model.get_iter(path)
|
||||||
|
From_id = self.model.get_value(iter, 0)
|
||||||
|
To_id = self.model.get_value(iter, 2)
|
||||||
|
Fam_id = self.model.get_value(iter, 4)
|
||||||
|
fam = self.dbstate.db.get_family_from_gramps_id(Fam_id)
|
||||||
|
if fam:
|
||||||
|
try:
|
||||||
|
EditFamily(self.dbstate, self.uistate, [], fam)
|
||||||
|
except WindowActiveError:
|
||||||
|
pass
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def on_help_clicked(self, obj):
|
||||||
|
"""Display the relevant portion of GRAMPS manual"""
|
||||||
|
display_help(webpage=WIKI_HELP_PAGE, section=WIKI_HELP_SEC)
|
||||||
|
|
||||||
|
def close(self, *obj):
|
||||||
|
ManagedWindow.close(self,*obj)
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# FindLoopOptions
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
class FindLoopOptions(tool.ToolOptions):
|
||||||
|
"""
|
||||||
|
Defines options and provides handling interface.
|
||||||
|
"""
|
||||||
|
def __init__(self, name, person_id=None):
|
||||||
|
""" Initialize the options class """
|
||||||
|
tool.ToolOptions.__init__(self, name, person_id)
|
@ -474,3 +474,25 @@ optionclass = 'MergeCitationsOptions',
|
|||||||
tool_modes = [TOOL_MODE_GUI]
|
tool_modes = [TOOL_MODE_GUI]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Find database Loop
|
||||||
|
#
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
|
||||||
|
register(TOOL,
|
||||||
|
id = 'loop',
|
||||||
|
name = _("Find database loop"),
|
||||||
|
description = _("Searches the entire database, looking for "
|
||||||
|
"a possible loop."),
|
||||||
|
version = '1.0',
|
||||||
|
gramps_target_version = MODULE_VERSION,
|
||||||
|
status = STABLE,
|
||||||
|
fname = 'findloop.py',
|
||||||
|
authors = ["Serge Noiraud"],
|
||||||
|
authors_email = ["serge.noiraud@free.fr"],
|
||||||
|
category = TOOL_UTILS,
|
||||||
|
toolclass = 'FindLoop',
|
||||||
|
optionclass = 'FindLoopOptions',
|
||||||
|
tool_modes = [TOOL_MODE_GUI]
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user