diff --git a/ChangeLog b/ChangeLog index 802472c26..9ad4603e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2005-03-30 Don Allingham + * src/MergePeople.py: provide more date in compare window, fix event + merging for families. Copy alternate names. + * src/plugins/Merge.py: support for new merge technique + * src/PeopleView.py: divide rebuild_data into two functions + * src/PeopleModel.py: clean up insertion functions + * src/gramps_main.py: remove unused code + 2005-03-30 Martin Hawlisch * plugins/TestcaseGenerator.py: Added some more testcases of invalid relations * plugins/Check.py: Added some comments an handling for some more invalid references diff --git a/src/GrampsBSDDB.py b/src/GrampsBSDDB.py index 898b481de..500f4dae4 100644 --- a/src/GrampsBSDDB.py +++ b/src/GrampsBSDDB.py @@ -265,6 +265,7 @@ class GrampsBSDDB(GrampsDbBase): if transaction != None: transaction.add(PERSON_KEY,handle,person.serialize()) self.person_map.delete(str(handle)) + self.run_person_delete_callbacks(str(handle)) def remove_source(self,handle,transaction): if not self.readonly: diff --git a/src/GrampsDbBase.py b/src/GrampsDbBase.py index 48a4f05ea..22b12a09f 100644 --- a/src/GrampsDbBase.py +++ b/src/GrampsDbBase.py @@ -165,6 +165,38 @@ class GrampsDbBase: self.place2title = {} self.name_groups = {} + self.person_add_callback = {} + self.person_update_callback = {} + self.person_delete_callback = {} + + def add_person_callbacks(self, key, add, update, delete): + if add: + self.person_add_callback[key] = add + if update: + self.person_update_callback[key] = update + if delete: + self.person_delete_callback[key] = delete + + def remove_person_callbacks(self, key): + if self.person_add_callback.has_key(key): + del self.person_add_callback[key] + if self.person_update_callback.has_key(key): + del self.person_update_callback[key] + if self.person_delete_callback.has_key(key): + del self.person_delete_callback[key] + + def run_person_add_callbacks(self,handle): + for func in self.person_add_callback.values(): + func(handle) + + def run_person_update_callbacks(self,handle): + for func in self.person_update_callback.values(): + func(handle) + + def run_person_delete_callbacks(self,handle): + for func in self.person_delete_callback.values(): + func(handle) + def need_upgrade(self): return False @@ -240,6 +272,7 @@ class GrampsDbBase: transaction.add(PERSON_KEY,handle,old_data) self.person_map[handle] = person.serialize() + self.run_person_update_callbacks(handle) def commit_media_object(self,obj,transaction,change_time=None): """ @@ -474,6 +507,7 @@ class GrampsDbBase: if transaction != None: transaction.add(PERSON_KEY, val, None) self.person_map[str(val)] = person.serialize() + self.run_person_add_callbacks(str(val)) self.genderStats.count_person (person, self) return person @@ -919,8 +953,10 @@ class GrampsDbBase: if key == PERSON_KEY: if data == None: del self.person_map[str(handle)] + self.run_person_delete_callbacks(str(handle)) else: self.person_map[str(handle)] = data + self.run_person_update_callbacks(str(handle)) elif key == FAMILY_KEY: if data == None: del self.family_map[str(handle)] diff --git a/src/GrampsInMemDB.py b/src/GrampsInMemDB.py index 3b4908f88..dcc15bfc7 100644 --- a/src/GrampsInMemDB.py +++ b/src/GrampsInMemDB.py @@ -144,6 +144,7 @@ class GrampsInMemDB(GrampsDbBase): transaction.add(PERSON_KEY,handle,old_data) del self.id_trans[person.get_gramps_id()] del self.person_map[handle] + self.run_person_delete_callbacks(handle) def remove_source(self,handle,transaction): if self.readonly: diff --git a/src/PeopleModel.py b/src/PeopleModel.py index c66fb5358..03e67dd07 100644 --- a/src/PeopleModel.py +++ b/src/PeopleModel.py @@ -75,13 +75,18 @@ class PeopleModel(gtk.GenericTreeModel): self.top_visible = {} self.rebuild_data(data_filter) - def rebuild_data(self,data_filter=None): + def rebuild_data(self,data_filter=None,skip=None): + self.calculate_data(data_filter,skip) + self.assign_data() + + def calculate_data(self,data_filter=None,skip=None): + if data_filter: self.data_filter = data_filter - temp_top_path2iter = [] - temp_iter2path = {} - temp_path2iter = {} - self.sname_sub = {} + self.temp_top_path2iter = [] + self.temp_iter2path = {} + self.temp_path2iter = {} + self.temp_sname_sub = {} if not self.db.is_open(): return @@ -92,8 +97,10 @@ class PeopleModel(gtk.GenericTreeModel): del handle_list else: keys = self.db.get_person_handles(sort_handles=False) - + for person_handle in keys: + if person_handle == skip: + continue person = self.db.get_person_from_handle(person_handle) grp_as = person.get_primary_name().get_group_as() sn = person.get_primary_name().get_surname() @@ -102,17 +109,17 @@ class PeopleModel(gtk.GenericTreeModel): else: surname = self.db.get_name_group_mapping(sn) - if self.sname_sub.has_key(surname): - self.sname_sub[surname].append(person_handle) + if self.temp_sname_sub.has_key(surname): + self.temp_sname_sub[surname].append(person_handle) else: - self.sname_sub[surname] = [person_handle] + self.temp_sname_sub[surname] = [person_handle] - temp_top_path2iter = self.sname_sub.keys() - temp_top_path2iter.sort(locale.strcoll) - for name in temp_top_path2iter: + self.temp_top_path2iter = self.temp_sname_sub.keys() + self.temp_top_path2iter.sort(locale.strcoll) + for name in self.temp_top_path2iter: slist = [] - for handle in self.sname_sub[name]: + for handle in self.temp_sname_sub[name]: n = self.db.person_map.get(handle)[_NAME_COL].get_sort_name() slist.append((n,handle)) slist.sort(self.byname) @@ -120,13 +127,15 @@ class PeopleModel(gtk.GenericTreeModel): val = 0 for person_handle in entries: tpl = (name,val) - temp_iter2path[person_handle] = tpl - temp_path2iter[tpl] = person_handle + self.temp_iter2path[person_handle] = tpl + self.temp_path2iter[tpl] = person_handle val += 1 - self.top_path2iter = temp_top_path2iter - self.iter2path = temp_iter2path - self.path2iter = temp_path2iter + def assign_data(self): + self.top_path2iter = self.temp_top_path2iter + self.iter2path = self.temp_iter2path + self.path2iter = self.temp_path2iter + self.sname_sub = self.temp_sname_sub def byname(self,f,s): return locale.strcoll(f[0],s[0]) @@ -147,6 +156,9 @@ class PeopleModel(gtk.GenericTreeModel): (surname,index) = self.iter2path[node] return (self.top_path2iter.index(surname),index) + def is_visable(self,handle): + return self.iter2path.has_key(handle) + def on_get_column_type(self,index): # return column data-type, from table return COLUMN_DEFS[index][COLUMN_DEF_TYPE] diff --git a/src/PeopleView.py b/src/PeopleView.py index 15cb239b4..79fa9d568 100644 --- a/src/PeopleView.py +++ b/src/PeopleView.py @@ -271,9 +271,16 @@ class PeopleView: self.person_model.rebuild_data(self.DataFilter) self.add_person(person) + def person_added(self,handle): + person = self.parent.db.get_person_from_handle(handle) + self.add_person(person) + def add_person(self,person): node = person.get_handle() top = person.get_primary_name().get_group_name() + self.person_model.rebuild_data(self.DataFilter) + if not self.person_model.is_visable(node): + return if (not self.person_model.sname_sub.has_key(top) or len(self.person_model.sname_sub[top]) == 1): path = self.person_model.on_get_path(top) @@ -283,22 +290,78 @@ class PeopleView: pnode = self.person_model.get_iter(path) self.person_model.row_inserted(path,pnode) - def delete_person(self,person): + def person_removed(self,handle): + person = self.parent.db.get_person_from_handle(handle) + self.delete_person(person) + + def delete_person(self,person,rebuild=False): node = person.get_handle() + if not self.person_model.is_visable(node): + return top = person.get_primary_name().get_group_name() - try: - if len(self.person_model.sname_sub[top]) == 1: - path = self.person_model.on_get_path(top) + mylist = self.person_model.sname_sub.get(top,[]) + if mylist: + try: + path = self.person_model.on_get_path(node) self.person_model.row_deleted(path) - except: - pass - path = self.person_model.on_get_path(node) - self.person_model.row_deleted(path) + if len(mylist) == 1: + path = self.person_model.on_get_path(top) + self.person_model.row_deleted(path) + except KeyError: + pass + self.person_model.rebuild_data(self.DataFilter,skip=node) + + def person_updated(self,handle): + person = self.parent.db.get_person_from_handle(handle) + self.update_person_list(person) def update_person_list(self,person): - self.delete_person(person) - self.person_model.rebuild_data(self.DataFilter) - self.add_person(person) + # find original path,node of person + node = person.get_handle() + try: + oldpath = self.person_model.iter2path[node] + except: + return + pathval = self.person_model.on_get_path(node) + pnode = self.person_model.get_iter(pathval) + + # calculate the new data + self.person_model.calculate_data(self.DataFilter) + + # find the path of the person in the new data build + newpath = self.person_model.temp_iter2path[node] + + # if paths same, just issue row changed signal + if oldpath == newpath: + self.person_model.row_changed(pathval,pnode) + else: + # paths different, get the new surname list + + mylist = self.person_model.temp_sname_sub.get(oldpath[0],[]) + path = self.person_model.on_get_path(node) + + # delete original + self.person_model.row_deleted(pathval) + + # delete top node of original if necessar + if len(mylist)==0: + self.person_model.row_deleted(pathval[0]) + + # determine if we need to insert a new top node', + insert = not self.person_model.sname_sub.has_key(newpath[0]) + + # assign new data + self.person_model.assign_data() + + # insert new row if needed + if insert: + path = self.person_model.on_get_path(newpath[0]) + pnode = self.person_model.get_iter(path) + self.person_model.row_inserted(path,pnode) + + # insert new person + path = self.person_model.on_get_path(node) + pnode = self.person_model.get_iter(path) + self.person_model.row_inserted(path,pnode) self.parent.change_active_person(person) self.goto_active_person() - diff --git a/src/gramps_main.py b/src/gramps_main.py index 2177b1a82..ac7256253 100755 --- a/src/gramps_main.py +++ b/src/gramps_main.py @@ -1625,10 +1625,6 @@ class Gramps: def new_after_edit(self,epo,val): self.active_person = epo.person - pn = self.active_person.get_primary_name() - - mapname = self.db.get_name_group_mapping(pn.get_group_name()) - self.people_view.build_tree() self.family_view.load_family() self.place_view.build_tree() diff --git a/src/plugins/Merge.py b/src/plugins/Merge.py index 19f2f69c0..38946baa7 100644 --- a/src/plugins/Merge.py +++ b/src/plugins/Merge.py @@ -49,7 +49,7 @@ import Utils import soundex import NameDisplay import ListModel -import MergeData +import MergePeople #------------------------------------------------------------------------- # @@ -170,8 +170,9 @@ class Merge: self.find_potentials(active) if len(self.map) == 0: import QuestionDialog - QuestionDialog.ErrorDialog(_("No matches found"), - _("No potential duplicate people were found")) + QuestionDialog.ErrorDialog( + _("No matches found"), + _("No potential duplicate people were found")) else: self.show() @@ -287,8 +288,12 @@ class Merge: for (c,p1key,p2key) in list: c1 = "%5.2f" % c c2 = "%5.2f" % (100-c) - pn1 = self.db.get_person_from_handle(p1key).get_primary_name().get_name() - pn2 = self.db.get_person_from_handle(p2key).get_primary_name().get_name() + p1 = self.db.get_person_from_handle(p1key) + p2 = self.db.get_person_from_handle(p2key) + if not p1 or not p2: + continue + pn1 = NameDisplay.displayer.display(p1) + pn2 = NameDisplay.displayer.display(p2) self.list.add([c, pn1, pn2,c2],(p1key,p2key)) def on_do_merge_clicked(self,obj): @@ -296,16 +301,18 @@ class Merge: if not iter: return - (p1,p2) = self.list.get_object(iter) - pn1 = self.db.get_person_from_handle(p1) - pn2 = self.db.get_person_from_handle(p2) - MergeData.MergePeople(self.parent,self.db,pn1,pn2,self.on_update) + (self.p1,self.p2) = self.list.get_object(iter) + pn1 = self.db.get_person_from_handle(self.p1) + pn2 = self.db.get_person_from_handle(self.p2) - def on_update(self,p1_id,p2_id,old_id): - self.dellist[p2_id] = p1_id + MergePeople.Compare(self.db,pn1,pn2,self.on_update) + + def on_update(self): + self.dellist[self.p2] = self.p1 for key in self.dellist.keys(): - if self.dellist[key] == p2_id: - self.dellist[key] = p1_id + if self.dellist[key] == self.p2: + self.dellist[key] = self.p1 + self.update(None,None) self.redraw() def update_and_destroy(self,obj):