7846: Prevent creation of a place cycle when merging

This commit is contained in:
Nick Hall 2014-07-14 22:53:01 +01:00
parent 82543486d0
commit 4ffa3e8c49
2 changed files with 33 additions and 2 deletions

View File

@ -90,3 +90,26 @@ def get_locations(db, place):
if len(place.get_placeref_list()) == 0: if len(place.get_placeref_list()) == 0:
locations.append(dict(tree)) locations.append(dict(tree))
return locations return locations
#-------------------------------------------------------------------------
#
# located_in
#
#-------------------------------------------------------------------------
def located_in(db, handle1, handle2):
"""
Determine if the place identified by handle1 is located within the place
identified by handle2.
"""
place = db.get_place_from_handle(handle1)
todo = [(place, [handle1])]
while len(todo):
place, visited = todo.pop()
for parent in place.get_placeref_list():
if parent.ref == handle2:
return True
if parent.ref not in visited:
parent_place = db.get_place_from_handle(parent.ref)
parent_visited = visited + [parent.ref]
todo.append((parent_place, parent_visited))
return False

View File

@ -57,6 +57,7 @@ from gramps.gui.editors import EditPlace, DeletePlaceQuery
from gramps.gui.filters.sidebar import PlaceSidebarFilter from gramps.gui.filters.sidebar import PlaceSidebarFilter
from gramps.gui.merge import MergePlace from gramps.gui.merge import MergePlace
from gramps.gen.plug import CATEGORY_QR_PLACE from gramps.gen.plug import CATEGORY_QR_PLACE
from gramps.gen.utils.location import located_in
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -412,6 +413,13 @@ class PlaceBaseView(ListView):
"A second place can be selected by holding down the " "A second place can be selected by holding down the "
"control key while clicking on the desired place.") "control key while clicking on the desired place.")
ErrorDialog(msg, msg2) ErrorDialog(msg, msg2)
else:
if (located_in(self.dbstate.db, mlist[0], mlist[1]) or
located_in(self.dbstate.db, mlist[1], mlist[0])):
msg = _("Cannot merge places.")
msg2 = _("Merging these places would create a cycle in the "
"place hierarchy.")
ErrorDialog(msg, msg2)
else: else:
MergePlace(self.dbstate, self.uistate, mlist[0], mlist[1], MergePlace(self.dbstate, self.uistate, mlist[0], mlist[1],
self.merged) self.merged)