Skip to content

Commit 4974e67

Browse files
vantu5zsam-m888
authored andcommitted
[GraphView]Keep multiple spouses positioned together[gramps51](#209)
apply gburto01 patch (issue 11033) Graphview attempts to keep spouses positioned together but this isn't guaranteed when a person has multiple spouses and sometimes Graphviz will generate a graph where one of the spouses is positioned away. This patch attempts to fix this issue.
1 parent 7d09e78 commit 4974e67

File tree

1 file changed

+69
-28
lines changed

1 file changed

+69
-28
lines changed

GraphView/graphview.py

Lines changed: 69 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,7 +1880,13 @@ def __init__(self, dbstate, view):
18801880

18811881
self.dot = None # will be StringIO()
18821882

1883-
self.person_handles = set()
1883+
# This dictionary contains person handle as the index and the value is
1884+
# the number of families in which the person is a parent. From this
1885+
# dictionary is obtained a list of person handles sorted in decreasing
1886+
# value order which is used to keep multiple spouses positioned
1887+
# together.
1888+
self.person_handles_dict = {}
1889+
self.person_handles = []
18841890

18851891
# list of persons on path to home person
18861892
self.current_list = list()
@@ -1906,7 +1912,7 @@ def init_dot(self):
19061912
self.dot = StringIO()
19071913

19081914
self.current_list.clear()
1909-
self.person_handles.clear()
1915+
self.person_handles_dict.clear()
19101916

19111917
self.show_images = self.view._config.get(
19121918
'interface.graphview-show-images')
@@ -2027,10 +2033,15 @@ def build_graph(self, active_person):
20272033
self.home_person = self.dbstate.db.get_default_person()
20282034
self.set_current_list(active_person)
20292035
self.set_current_list_desc(active_person)
2030-
self.person_handles.update(self.find_descendants(active_person))
2031-
self.person_handles.update(self.find_ancestors(active_person))
2032-
2033-
if self.person_handles:
2036+
self.person_handles_dict.update(
2037+
self.find_descendants(active_person))
2038+
self.person_handles_dict.update(self.find_ancestors(active_person))
2039+
2040+
if self.person_handles_dict:
2041+
self.person_handles = sorted(
2042+
self.person_handles_dict,
2043+
key=self.person_handles_dict.__getitem__,
2044+
reverse=True)
20342045
self.add_persons_and_families()
20352046
self.add_child_links_to_families()
20362047

@@ -2109,7 +2120,7 @@ def find_descendants(self, active_person):
21092120
Spider the database from the active person.
21102121
"""
21112122
person = self.database.get_person_from_handle(active_person)
2112-
person_handles = []
2123+
person_handles = {}
21132124
self.add_descendant(person, self.descendant_generations,
21142125
person_handles)
21152126
return person_handles
@@ -2136,7 +2147,11 @@ def add_descendant(self, person, num_generations, person_handles):
21362147

21372148
# add self if not already processed or if we have children
21382149
if person.handle not in person_handles or nb_child != 0:
2139-
person_handles.append(person.handle)
2150+
spouses = len(person.get_family_handle_list())
2151+
if spouses > 1:
2152+
person_handles[person.handle] = spouses
2153+
else:
2154+
person_handles[person.handle] = 0
21402155

21412156
for family_handle in person.get_family_handle_list():
21422157
family = self.database.get_family_from_handle(family_handle)
@@ -2159,16 +2174,20 @@ def add_spouses(self, person, family, person_handles):
21592174
else:
21602175
spouse_handle = family.get_father_handle()
21612176

2162-
# add spouse itself
2163-
if spouse_handle and spouse_handle not in person_handles:
2164-
person_handles.append(spouse_handle)
2165-
21662177
# add all his(her) spouses recursively
21672178
if spouse_handle:
21682179
sp_person = self.database.get_person_from_handle(spouse_handle)
21692180
else:
21702181
sp_person = None
21712182

2183+
# add spouse itself
2184+
if spouse_handle and spouse_handle not in person_handles:
2185+
spouses = len(sp_person.get_family_handle_list())
2186+
if spouses > 1:
2187+
person_handles[spouse_handle] = spouses
2188+
else:
2189+
person_handles[spouse_handle] = 0
2190+
21722191
if sp_person:
21732192
for family_handle in sp_person.get_family_handle_list():
21742193
sp_family = self.database.get_family_from_handle(family_handle)
@@ -2188,7 +2207,7 @@ def find_ancestors(self, active_person):
21882207
Spider the database from the active person.
21892208
"""
21902209
person = self.database.get_person_from_handle(active_person)
2191-
person_handles = []
2210+
person_handles = {}
21922211
self.add_ancestor(person, self.ancestor_generations, person_handles)
21932212
return person_handles
21942213

@@ -2204,7 +2223,11 @@ def add_ancestor(self, person, num_generations, person_handles):
22042223

22052224
# add self
22062225
if person.handle not in person_handles:
2207-
person_handles.append(person.handle)
2226+
spouses = len(person.get_family_handle_list())
2227+
if spouses > 1:
2228+
person_handles[person.handle] = spouses
2229+
else:
2230+
person_handles[person.handle] = 0
22082231

22092232
for family_handle in person.get_parent_family_handle_list():
22102233
family = self.database.get_family_from_handle(family_handle)
@@ -2280,26 +2303,46 @@ def add_parent_link(self, p_id, parent_handle, rel):
22802303
def add_persons_and_families(self):
22812304
"""
22822305
Adds nodes for persons and their families.
2306+
Subgraphs are used to indicate to Graphviz that parents of families
2307+
should be positioned together. The person_handles list is sorted so
2308+
that people with the largest number of spouses are at the start of the
2309+
list. As families are only processed once, this means people with
2310+
multiple spouses will have their additional spouses included in their
2311+
subgraph.
22832312
"""
22842313
# variable to communicate with get_person_label
22852314
url = ""
22862315

22872316
# The list of families for which we have output the node,
22882317
# so we don't do it twice
2289-
families_done = {}
2318+
family_nodes_done = {}
2319+
family_links_done = {}
22902320
for person_handle in self.person_handles:
22912321
person = self.database.get_person_from_handle(person_handle)
22922322
# Output the person's node
22932323
label = self.get_person_label(person)
22942324
(shape, style, color, fill) = self.get_gender_style(person)
22952325
self.add_node(person_handle, label, shape, color, style, fill, url)
22962326

2297-
# Output families where person is a parent
2327+
# Output family nodes where person is a parent
2328+
family_list = person.get_family_handle_list()
2329+
for fam_handle in family_list:
2330+
if fam_handle not in family_nodes_done:
2331+
family_nodes_done[fam_handle] = 1
2332+
self.__add_family_node(fam_handle)
2333+
2334+
# Output family links where person is a parent
2335+
subgraph_started = False
22982336
family_list = person.get_family_handle_list()
22992337
for fam_handle in family_list:
2300-
if fam_handle not in families_done:
2301-
families_done[fam_handle] = 1
2302-
self.__add_family(fam_handle)
2338+
if fam_handle not in family_links_done:
2339+
family_links_done[fam_handle] = 1
2340+
if not subgraph_started:
2341+
subgraph_started = True
2342+
self.start_subgraph(person_handle)
2343+
self.__add_family_links(fam_handle)
2344+
if subgraph_started:
2345+
self.end_subgraph()
23032346

23042347
def is_in_path_to_home(self, f_handle):
23052348
"""
@@ -2309,9 +2352,9 @@ def is_in_path_to_home(self, f_handle):
23092352
return True
23102353
return False
23112354

2312-
def __add_family(self, fam_handle):
2355+
def __add_family_node(self, fam_handle):
23132356
"""
2314-
Add a node for a family and optionally link the spouses to it.
2357+
Add a node for a family.
23152358
"""
23162359
fam = self.database.get_family_from_handle(fam_handle)
23172360
fill, color = color_graph_family(fam, self.dbstate)
@@ -2320,12 +2363,11 @@ def __add_family(self, fam_handle):
23202363

23212364
self.add_node(fam_handle, label, "ellipse", color, style, fill)
23222365

2323-
# If subgraphs are used then we add both spouses here and Graphviz
2324-
# will attempt to position both spouses closely together.
2325-
# A person who is a parent in more than one family may only be
2326-
# positioned next to one of their spouses. The code currently
2327-
# does not take into account multiple spouses.
2328-
self.start_subgraph(fam_handle)
2366+
def __add_family_links(self, fam_handle):
2367+
"""
2368+
Add the links for spouses.
2369+
"""
2370+
fam = self.database.get_family_from_handle(fam_handle)
23292371
f_handle = fam.get_father_handle()
23302372
m_handle = fam.get_mother_handle()
23312373
if f_handle in self.person_handles:
@@ -2342,7 +2384,6 @@ def __add_family(self, fam_handle):
23422384
self.arrowtailstyle,
23432385
color=self.colors['home_path_color'],
23442386
bold=self.is_in_path_to_home(m_handle))
2345-
self.end_subgraph()
23462387

23472388
def get_gender_style(self, person):
23482389
"""

0 commit comments

Comments
 (0)