Fix for delete of a ref'd primary obj while editing an added obj. (#779)
Also fixed to update the ref'd obj on changes from outside the editor. Fixes #10999, #11000, #11001, #11002
This commit is contained in:
@@ -131,15 +131,15 @@ class EventEmbedList(DbGUIElement, GroupEmbeddedList):
|
|||||||
refs = self.get_data()[self._WORKGROUP]
|
refs = self.get_data()[self._WORKGROUP]
|
||||||
ref_list = [eref.ref for eref in refs]
|
ref_list = [eref.ref for eref in refs]
|
||||||
indexlist = []
|
indexlist = []
|
||||||
last = 0
|
last = -1
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
last = ref_list.index(handle)
|
last = ref_list.index(handle, last + 1)
|
||||||
indexlist.append(last)
|
indexlist.append(last)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
break
|
break
|
||||||
#remove the deleted workgroup events from the object
|
#remove the deleted workgroup events from the object
|
||||||
for index in indexlist.reverse():
|
for index in reversed(indexlist):
|
||||||
del refs[index]
|
del refs[index]
|
||||||
#now rebuild the display tab
|
#now rebuild the display tab
|
||||||
self.rebuild_callback()
|
self.rebuild_callback()
|
||||||
|
@@ -38,13 +38,15 @@ from gramps.gen.errors import WindowActiveError
|
|||||||
from ...ddtargets import DdTargets
|
from ...ddtargets import DdTargets
|
||||||
from .personrefmodel import PersonRefModel
|
from .personrefmodel import PersonRefModel
|
||||||
from .embeddedlist import EmbeddedList, TEXT_COL, MARKUP_COL, ICON_COL
|
from .embeddedlist import EmbeddedList, TEXT_COL, MARKUP_COL, ICON_COL
|
||||||
|
from ...dbguielement import DbGUIElement
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
class PersonRefEmbedList(EmbeddedList):
|
class PersonRefEmbedList(DbGUIElement, EmbeddedList):
|
||||||
|
|
||||||
_HANDLE_COL = 4
|
_HANDLE_COL = 4
|
||||||
_DND_TYPE = DdTargets.PERSONREF
|
_DND_TYPE = DdTargets.PERSONREF
|
||||||
@@ -69,15 +71,61 @@ class PersonRefEmbedList(EmbeddedList):
|
|||||||
|
|
||||||
def __init__(self, dbstate, uistate, track, data):
|
def __init__(self, dbstate, uistate, track, data):
|
||||||
self.data = data
|
self.data = data
|
||||||
|
DbGUIElement.__init__(self, dbstate.db)
|
||||||
EmbeddedList.__init__(self, dbstate, uistate, track,
|
EmbeddedList.__init__(self, dbstate, uistate, track,
|
||||||
_('_Associations'), PersonRefModel,
|
_('_Associations'), PersonRefModel,
|
||||||
move_buttons=True)
|
move_buttons=True)
|
||||||
|
|
||||||
|
def _connect_db_signals(self):
|
||||||
|
"""
|
||||||
|
called on init of DbGUIElement, connect to db as required.
|
||||||
|
"""
|
||||||
|
#note: person-rebuild closes the editors, so no need to connect to it
|
||||||
|
self.callman.register_callbacks(
|
||||||
|
{'person-update': self.person_change, # change to person we track
|
||||||
|
'person-delete': self.person_delete, # delete of person we track
|
||||||
|
})
|
||||||
|
self.callman.connect_all(keys=['person'])
|
||||||
|
|
||||||
|
def person_change(self, *obj):
|
||||||
|
"""
|
||||||
|
Callback method called when a tracked person changes (description
|
||||||
|
changes...)
|
||||||
|
"""
|
||||||
|
self.rebuild()
|
||||||
|
|
||||||
|
def person_delete(self, hndls):
|
||||||
|
"""
|
||||||
|
Callback method called when a tracked person is deleted.
|
||||||
|
There are two possibilities:
|
||||||
|
* a tracked non-workgroup person is deleted, just rebuilding the view
|
||||||
|
will correct this.
|
||||||
|
* a workgroup person is deleted. The person must be removed from the
|
||||||
|
obj so that no inconsistent data is shown.
|
||||||
|
"""
|
||||||
|
for handle in hndls:
|
||||||
|
ref_list = [pref.ref for pref in self.data]
|
||||||
|
indexlist = []
|
||||||
|
last = -1
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
last = ref_list.index(handle, last + 1)
|
||||||
|
indexlist.append(last)
|
||||||
|
except ValueError:
|
||||||
|
break
|
||||||
|
#remove the deleted workgroup persons from the object
|
||||||
|
for index in reversed(indexlist):
|
||||||
|
del self.data[index]
|
||||||
|
#now rebuild the display tab
|
||||||
|
self.rebuild()
|
||||||
|
|
||||||
def get_ref_editor(self):
|
def get_ref_editor(self):
|
||||||
from .. import EditPersonRef
|
from .. import EditPersonRef
|
||||||
return EditPersonRef
|
return EditPersonRef
|
||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
|
self.callman.register_handles(
|
||||||
|
{'person': [pref.ref for pref in self.data]})
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
def column_order(self):
|
def column_order(self):
|
||||||
|
@@ -40,13 +40,15 @@ from ...ddtargets import DdTargets
|
|||||||
from .placerefmodel import PlaceRefModel
|
from .placerefmodel import PlaceRefModel
|
||||||
from .embeddedlist import EmbeddedList, TEXT_COL
|
from .embeddedlist import EmbeddedList, TEXT_COL
|
||||||
from ...selectors import SelectorFactory
|
from ...selectors import SelectorFactory
|
||||||
|
from ...dbguielement import DbGUIElement
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
class PlaceRefEmbedList(EmbeddedList):
|
class PlaceRefEmbedList(DbGUIElement, EmbeddedList):
|
||||||
|
|
||||||
_HANDLE_COL = 4
|
_HANDLE_COL = 4
|
||||||
_DND_TYPE = DdTargets.PLACEREF
|
_DND_TYPE = DdTargets.PLACEREF
|
||||||
@@ -65,11 +67,57 @@ class PlaceRefEmbedList(EmbeddedList):
|
|||||||
self.data = data
|
self.data = data
|
||||||
self.handle = handle
|
self.handle = handle
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
|
DbGUIElement.__init__(self, dbstate.db)
|
||||||
EmbeddedList.__init__(self, dbstate, uistate, track,
|
EmbeddedList.__init__(self, dbstate, uistate, track,
|
||||||
_('Enclosed By'), PlaceRefModel,
|
_('Enclosed By'), PlaceRefModel,
|
||||||
share_button=True, move_buttons=True)
|
share_button=True, move_buttons=True)
|
||||||
|
|
||||||
|
def _connect_db_signals(self):
|
||||||
|
"""
|
||||||
|
called on init of DbGUIElement, connect to db as required.
|
||||||
|
"""
|
||||||
|
#note: place-rebuild closes the editors, so no need to connect to it
|
||||||
|
self.callman.register_callbacks(
|
||||||
|
{'place-update': self.place_change, # change to place we track
|
||||||
|
'place-delete': self.place_delete, # delete of place we track
|
||||||
|
})
|
||||||
|
self.callman.connect_all(keys=['place'])
|
||||||
|
|
||||||
|
def place_change(self, *obj):
|
||||||
|
"""
|
||||||
|
Callback method called when a tracked place changes (description
|
||||||
|
changes...)
|
||||||
|
"""
|
||||||
|
self.rebuild()
|
||||||
|
|
||||||
|
def place_delete(self, hndls):
|
||||||
|
"""
|
||||||
|
Callback method called when a tracked place is deleted.
|
||||||
|
There are two possibilities:
|
||||||
|
* a tracked non-workgroup place is deleted, just rebuilding the view
|
||||||
|
will correct this.
|
||||||
|
* a workgroup place is deleted. The place must be removed from the
|
||||||
|
obj so that no inconsistent data is shown.
|
||||||
|
"""
|
||||||
|
for handle in hndls:
|
||||||
|
ref_list = [pref.ref for pref in self.data]
|
||||||
|
indexlist = []
|
||||||
|
last = -1
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
last = ref_list.index(handle, last + 1)
|
||||||
|
indexlist.append(last)
|
||||||
|
except ValueError:
|
||||||
|
break
|
||||||
|
#remove the deleted workgroup places from the object
|
||||||
|
for index in reversed(indexlist):
|
||||||
|
del self.data[index]
|
||||||
|
#now rebuild the display tab
|
||||||
|
self.rebuild()
|
||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
|
self.callman.register_handles(
|
||||||
|
{'place': [pref.ref for pref in self.data]})
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
def column_order(self):
|
def column_order(self):
|
||||||
|
@@ -174,6 +174,8 @@ class EditCitation(EditPrimary):
|
|||||||
|
|
||||||
self._add_db_signal('citation-rebuild', self._do_close)
|
self._add_db_signal('citation-rebuild', self._do_close)
|
||||||
self._add_db_signal('citation-delete', self.check_for_close)
|
self._add_db_signal('citation-delete', self.check_for_close)
|
||||||
|
self._add_db_signal('source-delete', self.source_delete)
|
||||||
|
self._add_db_signal('source-update', self.source_update)
|
||||||
|
|
||||||
def _setup_fields(self):
|
def _setup_fields(self):
|
||||||
"""
|
"""
|
||||||
@@ -269,6 +271,26 @@ class EditCitation(EditPrimary):
|
|||||||
author = ''
|
author = ''
|
||||||
self.glade.get_object("author").set_text(author)
|
self.glade.get_object("author").set_text(author)
|
||||||
|
|
||||||
|
def source_update(self, hndls):
|
||||||
|
''' Source changed outside of dialog, update text if its ours '''
|
||||||
|
handle = self.obj.get_reference_handle()
|
||||||
|
if handle and handle in hndls:
|
||||||
|
source = self.db.get_source_from_handle(handle)
|
||||||
|
s_lbl = "%s [%s]" % (source.get_title(), source.gramps_id)
|
||||||
|
self.glade.get_object("source").set_text(s_lbl)
|
||||||
|
author = source.get_author()
|
||||||
|
self.glade.get_object("author").set_text(author)
|
||||||
|
|
||||||
|
def source_delete(self, hndls):
|
||||||
|
''' Source deleted outside of dialog, remove it if its ours'''
|
||||||
|
handle = self.obj.get_reference_handle()
|
||||||
|
if handle and handle in hndls:
|
||||||
|
self.obj.set_reference_handle(None)
|
||||||
|
self.glade.get_object("source").set_markup(
|
||||||
|
self.source_field.EMPTY_TEXT)
|
||||||
|
self.glade.get_object("author").set_text('')
|
||||||
|
self.source_field.set_button(False)
|
||||||
|
|
||||||
def build_menu_names(self, source):
|
def build_menu_names(self, source):
|
||||||
"""
|
"""
|
||||||
Provide the information needed by the base class to define the
|
Provide the information needed by the base class to define the
|
||||||
|
@@ -129,6 +129,8 @@ class EditEvent(EditPrimary):
|
|||||||
"""
|
"""
|
||||||
self._add_db_signal('event-rebuild', self._do_close)
|
self._add_db_signal('event-rebuild', self._do_close)
|
||||||
self._add_db_signal('event-delete', self.check_for_close)
|
self._add_db_signal('event-delete', self.check_for_close)
|
||||||
|
self._add_db_signal('place-delete', self.place_delete)
|
||||||
|
self._add_db_signal('place-update', self.place_update)
|
||||||
|
|
||||||
def _setup_fields(self):
|
def _setup_fields(self):
|
||||||
|
|
||||||
@@ -301,6 +303,24 @@ class EditEvent(EditPrimary):
|
|||||||
cmp_obj = self.empty_object()
|
cmp_obj = self.empty_object()
|
||||||
return cmp_obj.serialize(True)[1:] != self.obj.serialize()[1:]
|
return cmp_obj.serialize(True)[1:] != self.obj.serialize()[1:]
|
||||||
|
|
||||||
|
def place_update(self, hndls):
|
||||||
|
''' Place changed outside of dialog, update text if its ours '''
|
||||||
|
handle = self.obj.get_place_handle()
|
||||||
|
if handle and handle in hndls:
|
||||||
|
place = self.db.get_place_from_handle(handle)
|
||||||
|
p_lbl = "%s [%s]" % (place.get_title(), place.gramps_id)
|
||||||
|
self.top.get_object("place").set_text(p_lbl)
|
||||||
|
|
||||||
|
def place_delete(self, hndls):
|
||||||
|
''' Place deleted outside of dialog, remove it if its ours'''
|
||||||
|
handle = self.obj.get_place_handle()
|
||||||
|
if handle and handle in hndls:
|
||||||
|
self.obj.set_place_handle(None)
|
||||||
|
self.top.get_object("place").set_markup(
|
||||||
|
self.place_field.EMPTY_TEXT)
|
||||||
|
self.place_field.set_button(False)
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Delete Query class
|
# Delete Query class
|
||||||
|
@@ -120,6 +120,8 @@ class EditEventRef(EditReference):
|
|||||||
"""
|
"""
|
||||||
self._add_db_signal('event-rebuild', self.close)
|
self._add_db_signal('event-rebuild', self.close)
|
||||||
self._add_db_signal('event-delete', self.check_for_close)
|
self._add_db_signal('event-delete', self.check_for_close)
|
||||||
|
self._add_db_signal('place-delete', self.place_delete)
|
||||||
|
self._add_db_signal('place-update', self.place_update)
|
||||||
|
|
||||||
def _setup_fields(self):
|
def _setup_fields(self):
|
||||||
|
|
||||||
@@ -279,3 +281,20 @@ class EditEventRef(EditReference):
|
|||||||
self.update(self.source_ref,self.source)
|
self.update(self.source_ref,self.source)
|
||||||
|
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
def place_update(self, hndls):
|
||||||
|
''' Place changed outside of dialog, update text if its ours '''
|
||||||
|
handle = self.source.get_place_handle()
|
||||||
|
if handle and handle in hndls:
|
||||||
|
place = self.db.get_place_from_handle(handle)
|
||||||
|
p_lbl = "%s [%s]" % (place.get_title(), place.gramps_id)
|
||||||
|
self.top.get_object("eer_place").set_text(p_lbl)
|
||||||
|
|
||||||
|
def place_delete(self, hndls):
|
||||||
|
''' Place deleted outside of dialog, remove it if its ours'''
|
||||||
|
handle = self.source.get_place_handle()
|
||||||
|
if handle and handle in hndls:
|
||||||
|
self.source.set_place_handle(None)
|
||||||
|
self.top.get_object("eer_place").set_markup(
|
||||||
|
self.place_field.EMPTY_TEXT)
|
||||||
|
self.place_field.set_button(False)
|
||||||
|
@@ -80,6 +80,7 @@ from gramps.gen.utils.db import (get_birth_or_fallback, get_death_or_fallback,
|
|||||||
from ..selectors import SelectorFactory
|
from ..selectors import SelectorFactory
|
||||||
from gramps.gen.utils.id import create_id
|
from gramps.gen.utils.id import create_id
|
||||||
from gramps.gen.const import URL_MANUAL_SECT1
|
from gramps.gen.const import URL_MANUAL_SECT1
|
||||||
|
from ..dbguielement import DbGUIElement
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@@ -97,7 +98,8 @@ _KP_ENTER = Gdk.keyval_from_name("KP_Enter")
|
|||||||
_LEFT_BUTTON = 1
|
_LEFT_BUTTON = 1
|
||||||
_RIGHT_BUTTON = 3
|
_RIGHT_BUTTON = 3
|
||||||
|
|
||||||
class ChildEmbedList(EmbeddedList):
|
|
||||||
|
class ChildEmbedList(DbGUIElement, EmbeddedList):
|
||||||
"""
|
"""
|
||||||
The child embed list is specific to the Edit Family dialog, so it
|
The child embed list is specific to the Edit Family dialog, so it
|
||||||
is contained here instead of in displaytabs.
|
is contained here instead of in displaytabs.
|
||||||
@@ -139,9 +141,54 @@ class ChildEmbedList(EmbeddedList):
|
|||||||
Create the object, storing the passed family value
|
Create the object, storing the passed family value
|
||||||
"""
|
"""
|
||||||
self.family = family
|
self.family = family
|
||||||
|
DbGUIElement.__init__(self, dbstate.db)
|
||||||
EmbeddedList.__init__(self, dbstate, uistate, track, _('Chil_dren'),
|
EmbeddedList.__init__(self, dbstate, uistate, track, _('Chil_dren'),
|
||||||
ChildModel, share_button=True, move_buttons=True)
|
ChildModel, share_button=True, move_buttons=True)
|
||||||
|
|
||||||
|
def _connect_db_signals(self):
|
||||||
|
"""
|
||||||
|
called on init of DbGUIElement, connect to db as required.
|
||||||
|
"""
|
||||||
|
#note: event-rebuild closes the editors, so no need to connect to it
|
||||||
|
self.callman.register_callbacks(
|
||||||
|
{'person-update': self.person_change, # change to person we track
|
||||||
|
'person-delete': self.person_delete, # delete of person we track
|
||||||
|
})
|
||||||
|
self.callman.connect_all(keys=['person'])
|
||||||
|
|
||||||
|
def person_change(self, *obj):
|
||||||
|
"""
|
||||||
|
Callback method called when a tracked person changes (description
|
||||||
|
changes...)
|
||||||
|
"""
|
||||||
|
self.rebuild()
|
||||||
|
|
||||||
|
def person_delete(self, hndls):
|
||||||
|
"""
|
||||||
|
Callback method called when a tracked person is deleted.
|
||||||
|
There are two possibilities:
|
||||||
|
* a tracked non-workgroup person is deleted, just rebuilding the view
|
||||||
|
will correct this.
|
||||||
|
* a workgroup person is deleted. The person must be removed from the
|
||||||
|
obj so that no inconsistent data is shown.
|
||||||
|
"""
|
||||||
|
for handle in hndls:
|
||||||
|
prefs = self.get_data()
|
||||||
|
ref_list = [pref.ref for pref in prefs]
|
||||||
|
indexlist = []
|
||||||
|
last = -1
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
last = ref_list.index(handle, last + 1)
|
||||||
|
indexlist.append(last)
|
||||||
|
except ValueError:
|
||||||
|
break
|
||||||
|
#remove the deleted workgroup persons from the object
|
||||||
|
for index in reversed(indexlist):
|
||||||
|
del prefs[index]
|
||||||
|
#now rebuild the display tab
|
||||||
|
self.rebuild()
|
||||||
|
|
||||||
def get_popup_menu_items(self):
|
def get_popup_menu_items(self):
|
||||||
return [
|
return [
|
||||||
(False, _('Edit child'), self.edit_child_button_clicked),
|
(False, _('Edit child'), self.edit_child_button_clicked),
|
||||||
@@ -163,7 +210,10 @@ class ChildEmbedList(EmbeddedList):
|
|||||||
Normally, get_data returns a list. However, we return family
|
Normally, get_data returns a list. However, we return family
|
||||||
object here instead.
|
object here instead.
|
||||||
"""
|
"""
|
||||||
return self.family.get_child_ref_list()
|
prefs = self.family.get_child_ref_list()
|
||||||
|
self.callman.register_handles(
|
||||||
|
{'person': [eref.ref for eref in prefs]})
|
||||||
|
return prefs
|
||||||
|
|
||||||
def column_order(self):
|
def column_order(self):
|
||||||
return [(1, 13), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6),
|
return [(1, 13), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6),
|
||||||
@@ -413,11 +463,22 @@ class EditFamily(EditPrimary):
|
|||||||
'event-update': self.topdata_updated, # change eg birth event fath
|
'event-update': self.topdata_updated, # change eg birth event fath
|
||||||
'event-rebuild': self.topdata_updated,
|
'event-rebuild': self.topdata_updated,
|
||||||
'event-delete': self.topdata_updated, # delete eg birth event fath
|
'event-delete': self.topdata_updated, # delete eg birth event fath
|
||||||
'person-update': self.topdata_updated, # change eg name of father
|
'person-update': self.topdata_updated, # change eg name of father
|
||||||
|
'person-delete' : self.person_delete, # mother/father deleted?
|
||||||
'person-rebuild': self._do_close,
|
'person-rebuild': self._do_close,
|
||||||
})
|
})
|
||||||
self.callman.connect_all(keys=['family', 'event', 'person'])
|
self.callman.connect_all(keys=['family', 'event', 'person'])
|
||||||
|
|
||||||
|
def person_delete(self, handles):
|
||||||
|
""" This checks if mother/father is deleted, specifically when newly
|
||||||
|
added before data is saved """
|
||||||
|
for hndl in handles:
|
||||||
|
if self.obj.father_handle == hndl:
|
||||||
|
self.obj.father_handle = None
|
||||||
|
if self.obj.mother_handle == hndl:
|
||||||
|
self.obj.mother_handle = None
|
||||||
|
self.load_data()
|
||||||
|
|
||||||
def check_for_family_change(self, handles):
|
def check_for_family_change(self, handles):
|
||||||
"""
|
"""
|
||||||
Callback for family-update signal
|
Callback for family-update signal
|
||||||
|
@@ -274,9 +274,7 @@ class EditPerson(EditPrimary):
|
|||||||
self._add_db_signal('family-delete', self.family_change)
|
self._add_db_signal('family-delete', self.family_change)
|
||||||
self._add_db_signal('family-update', self.family_change)
|
self._add_db_signal('family-update', self.family_change)
|
||||||
self._add_db_signal('family-add', self.family_change)
|
self._add_db_signal('family-add', self.family_change)
|
||||||
self._add_db_signal('event-update', self.event_updated)
|
|
||||||
self._add_db_signal('event-rebuild', self.event_updated)
|
self._add_db_signal('event-rebuild', self.event_updated)
|
||||||
self._add_db_signal('event-delete', self.event_updated)
|
|
||||||
|
|
||||||
def family_change(self, handle_list=[]):
|
def family_change(self, handle_list=[]):
|
||||||
"""
|
"""
|
||||||
|
Reference in New Issue
Block a user