* src/ViewManager.py: Connect undo handler to the menu item.

* src/GrampsDb/_GrampsBSDDB.py: Place reference_map under
transaction management.
* src/GrampsDb/_GrampsDbBase.py: reference_map changes.


svn: r5728
This commit is contained in:
Alex Roitman 2006-01-12 22:02:58 +00:00
parent 80049496c0
commit 825f0e9f62
4 changed files with 152 additions and 67 deletions

View File

@ -1,3 +1,9 @@
2006-01-12 Alex Roitman <shura@gramps-project.org>
* src/ViewManager.py: Connect undo handler to the menu item.
* src/GrampsDb/_GrampsBSDDB.py: Place reference_map under
transaction management.
* src/GrampsDb/_GrampsDbBase.py: reference_map changes.
2006-01-11 Alex Roitman <shura@gramps-project.org> 2006-01-11 Alex Roitman <shura@gramps-project.org>
* src/Assistant.py: Many changes. * src/Assistant.py: Many changes.
* src/Exporter.py: Work with new Assistant. * src/Exporter.py: Work with new Assistant.

View File

@ -257,15 +257,15 @@ class GrampsBSDDB(GrampsDbBase):
self.env = db.DBEnv() self.env = db.DBEnv()
self.env.set_cachesize(0,0x2000000) # 2MB self.env.set_cachesize(0,0x2000000) # 2MB
# The DB_PRIVATE flag must go if we ever move to multi-user setup # The DB_PRIVATE flag must go if we ever move to multi-user setup
flags = db.DB_CREATE|db.DB_PRIVATE|\ env_flags = db.DB_CREATE|db.DB_PRIVATE|\
db.DB_INIT_MPOOL|db.DB_INIT_LOCK|\ db.DB_INIT_MPOOL|db.DB_INIT_LOCK|\
db.DB_INIT_LOG|db.DB_INIT_TXN|db.DB_RECOVER db.DB_INIT_LOG|db.DB_INIT_TXN|db.DB_RECOVER
self.undolog = "%s.log" % name self.undolog = "%s.log" % name
env_name = os.path.expanduser(const.bsddbenv_dir) env_name = os.path.expanduser(const.bsddbenv_dir)
if not os.path.isdir(env_name): if not os.path.isdir(env_name):
os.mkdir(env_name) os.mkdir(env_name)
self.env.open(env_name, flags) self.env.open(env_name,env_flags)
self.full_name = os.path.abspath(name) self.full_name = os.path.abspath(name)
self.brief_name = os.path.basename(name) self.brief_name = os.path.basename(name)
@ -282,96 +282,96 @@ class GrampsBSDDB(GrampsDbBase):
# index tables used just for speeding up searches # index tables used just for speeding up searches
if self.readonly: if self.readonly:
openflags = db.DB_RDONLY table_flags = db.DB_RDONLY
else: else:
openflags = db.DB_CREATE|db.DB_AUTO_COMMIT table_flags = db.DB_CREATE|db.DB_AUTO_COMMIT
self.surnames = db.DB(self.env) self.surnames = db.DB(self.env)
self.surnames.set_flags(db.DB_DUP) self.surnames.set_flags(db.DB_DUP)
self.surnames.open(self.full_name, "surnames", self.surnames.open(self.full_name, "surnames",
db.DB_HASH, flags=openflags) db.DB_HASH, flags=table_flags)
self.name_group = db.DB(self.env) self.name_group = db.DB(self.env)
self.name_group.set_flags(db.DB_DUP) self.name_group.set_flags(db.DB_DUP)
self.name_group.open(self.full_name, "name_group", self.name_group.open(self.full_name, "name_group",
db.DB_HASH, flags=openflags) db.DB_HASH, flags=table_flags)
self.id_trans = db.DB(self.env) self.id_trans = db.DB(self.env)
self.id_trans.set_flags(db.DB_DUP) self.id_trans.set_flags(db.DB_DUP)
self.id_trans.open(self.full_name, "idtrans", self.id_trans.open(self.full_name, "idtrans",
db.DB_HASH, flags=openflags) db.DB_HASH, flags=table_flags)
self.fid_trans = db.DB(self.env) self.fid_trans = db.DB(self.env)
self.fid_trans.set_flags(db.DB_DUP) self.fid_trans.set_flags(db.DB_DUP)
self.fid_trans.open(self.full_name, "fidtrans", self.fid_trans.open(self.full_name, "fidtrans",
db.DB_HASH, flags=openflags) db.DB_HASH, flags=table_flags)
self.eid_trans = db.DB(self.env) self.eid_trans = db.DB(self.env)
self.eid_trans.set_flags(db.DB_DUP) self.eid_trans.set_flags(db.DB_DUP)
self.eid_trans.open(self.full_name, "eidtrans", self.eid_trans.open(self.full_name, "eidtrans",
db.DB_HASH, flags=openflags) db.DB_HASH, flags=table_flags)
self.pid_trans = db.DB(self.env) self.pid_trans = db.DB(self.env)
self.pid_trans.set_flags(db.DB_DUP) self.pid_trans.set_flags(db.DB_DUP)
self.pid_trans.open(self.full_name, "pidtrans", self.pid_trans.open(self.full_name, "pidtrans",
db.DB_HASH, flags=openflags) db.DB_HASH, flags=table_flags)
self.sid_trans = db.DB(self.env) self.sid_trans = db.DB(self.env)
self.sid_trans.set_flags(db.DB_DUP) self.sid_trans.set_flags(db.DB_DUP)
self.sid_trans.open(self.full_name, "sidtrans", self.sid_trans.open(self.full_name, "sidtrans",
db.DB_HASH, flags=openflags) db.DB_HASH, flags=table_flags)
self.oid_trans = db.DB(self.env) self.oid_trans = db.DB(self.env)
self.oid_trans.set_flags(db.DB_DUP) self.oid_trans.set_flags(db.DB_DUP)
self.oid_trans.open(self.full_name, "oidtrans", self.oid_trans.open(self.full_name, "oidtrans",
db.DB_HASH, flags=openflags) db.DB_HASH, flags=table_flags)
self.rid_trans = db.DB(self.env) self.rid_trans = db.DB(self.env)
self.rid_trans.set_flags(db.DB_DUP) self.rid_trans.set_flags(db.DB_DUP)
self.rid_trans.open(self.full_name, "ridtrans", self.rid_trans.open(self.full_name, "ridtrans",
db.DB_HASH, flags=openflags) db.DB_HASH, flags=table_flags)
self.eventnames = db.DB(self.env) self.eventnames = db.DB(self.env)
self.eventnames.set_flags(db.DB_DUP) self.eventnames.set_flags(db.DB_DUP)
self.eventnames.open(self.full_name, "eventnames", self.eventnames.open(self.full_name, "eventnames",
db.DB_HASH, flags=openflags) db.DB_HASH, flags=table_flags)
self.repository_types = db.DB(self.env) self.repository_types = db.DB(self.env)
self.repository_types.set_flags(db.DB_DUP) self.repository_types.set_flags(db.DB_DUP)
self.repository_types.open(self.full_name, "repostypes", self.repository_types.open(self.full_name, "repostypes",
db.DB_HASH, flags=openflags) db.DB_HASH, flags=table_flags)
self.reference_map_primary_map = db.DB(self.env) self.reference_map_primary_map = db.DB(self.env)
self.reference_map_primary_map.set_flags(db.DB_DUP) self.reference_map_primary_map.set_flags(db.DB_DUP)
self.reference_map_primary_map.open(self.full_name, self.reference_map_primary_map.open(self.full_name,
"reference_map_primary_map", "reference_map_primary_map",
db.DB_BTREE, flags=openflags) db.DB_BTREE, flags=table_flags)
self.reference_map_referenced_map = db.DB(self.env) self.reference_map_referenced_map = db.DB(self.env)
self.reference_map_referenced_map.set_flags(db.DB_DUP) self.reference_map_referenced_map.set_flags(db.DB_DUP)
self.reference_map_referenced_map.open(self.full_name, self.reference_map_referenced_map.open(self.full_name,
"reference_map_referenced_map", "reference_map_referenced_map",
db.DB_BTREE, flags=openflags) db.DB_BTREE, flags=table_flags)
if not self.readonly: if not self.readonly:
self.person_map.associate(self.surnames, find_surname, openflags) self.person_map.associate(self.surnames, find_surname, table_flags)
self.person_map.associate(self.id_trans, find_idmap, openflags) self.person_map.associate(self.id_trans, find_idmap, table_flags)
self.family_map.associate(self.fid_trans, find_idmap, openflags) self.family_map.associate(self.fid_trans, find_idmap, table_flags)
self.event_map.associate(self.eid_trans, find_idmap, openflags) self.event_map.associate(self.eid_trans, find_idmap, table_flags)
self.repository_map.associate(self.rid_trans, find_idmap, self.repository_map.associate(self.rid_trans, find_idmap,
openflags) table_flags)
self.repository_map.associate(self.repository_types, self.repository_map.associate(self.repository_types,
find_repository_type, openflags) find_repository_type, table_flags)
self.place_map.associate(self.pid_trans, find_idmap, openflags) self.place_map.associate(self.pid_trans, find_idmap, table_flags)
self.media_map.associate(self.oid_trans, find_idmap, openflags) self.media_map.associate(self.oid_trans, find_idmap, table_flags)
self.source_map.associate(self.sid_trans, find_idmap, openflags) self.source_map.associate(self.sid_trans, find_idmap, table_flags)
self.reference_map.associate(self.reference_map_primary_map, self.reference_map.associate(self.reference_map_primary_map,
find_primary_handle, find_primary_handle,
openflags) table_flags)
self.reference_map.associate(self.reference_map_referenced_map, self.reference_map.associate(self.reference_map_referenced_map,
find_referenced_handle, find_referenced_handle,
openflags) table_flags)
self.undodb = db.DB() self.undodb = db.DB()
self.undodb.open(self.undolog, db.DB_RECNO, db.DB_CREATE) self.undodb.open(self.undolog, db.DB_RECNO, db.DB_CREATE)
@ -401,7 +401,7 @@ class GrampsBSDDB(GrampsDbBase):
return 1 return 1
def rebuild_secondary(self,callback=None): def rebuild_secondary(self,callback=None):
openflags = db.DB_CREATE|db.DB_AUTO_COMMIT table_flags = db.DB_CREATE|db.DB_AUTO_COMMIT
# Repair secondary indices related to person_map # Repair secondary indices related to person_map
@ -411,13 +411,13 @@ class GrampsBSDDB(GrampsDbBase):
self.id_trans = db.DB(self.env) self.id_trans = db.DB(self.env)
self.id_trans.set_flags(db.DB_DUP) self.id_trans.set_flags(db.DB_DUP)
self.id_trans.open(self.full_name, "idtrans", db.DB_HASH, self.id_trans.open(self.full_name, "idtrans", db.DB_HASH,
flags=openflags) flags=table_flags)
self.id_trans.truncate() self.id_trans.truncate()
self.surnames = db.DB(self.env) self.surnames = db.DB(self.env)
self.surnames.set_flags(db.DB_DUP) self.surnames.set_flags(db.DB_DUP)
self.surnames.open(self.full_name, "surnames", db.DB_HASH, self.surnames.open(self.full_name, "surnames", db.DB_HASH,
flags=openflags) flags=table_flags)
self.surnames.truncate() self.surnames.truncate()
self.person_map.associate(self.surnames, find_surname, db.DB_CREATE) self.person_map.associate(self.surnames, find_surname, db.DB_CREATE)
@ -436,7 +436,7 @@ class GrampsBSDDB(GrampsDbBase):
self.fid_trans = db.DB(self.env) self.fid_trans = db.DB(self.env)
self.fid_trans.set_flags(db.DB_DUP) self.fid_trans.set_flags(db.DB_DUP)
self.fid_trans.open(self.full_name, "fidtrans", db.DB_HASH, self.fid_trans.open(self.full_name, "fidtrans", db.DB_HASH,
flags=openflags) flags=table_flags)
self.fid_trans.truncate() self.fid_trans.truncate()
self.family_map.associate(self.fid_trans, find_idmap, db.DB_CREATE) self.family_map.associate(self.fid_trans, find_idmap, db.DB_CREATE)
@ -452,7 +452,7 @@ class GrampsBSDDB(GrampsDbBase):
self.pid_trans = db.DB(self.env) self.pid_trans = db.DB(self.env)
self.pid_trans.set_flags(db.DB_DUP) self.pid_trans.set_flags(db.DB_DUP)
self.pid_trans.open(self.full_name, "pidtrans", db.DB_HASH, self.pid_trans.open(self.full_name, "pidtrans", db.DB_HASH,
flags=openflags) flags=table_flags)
self.pid_trans.truncate() self.pid_trans.truncate()
self.place_map.associate(self.pid_trans, find_idmap, db.DB_CREATE) self.place_map.associate(self.pid_trans, find_idmap, db.DB_CREATE)
@ -468,7 +468,7 @@ class GrampsBSDDB(GrampsDbBase):
self.oid_trans = db.DB(self.env) self.oid_trans = db.DB(self.env)
self.oid_trans.set_flags(db.DB_DUP) self.oid_trans.set_flags(db.DB_DUP)
self.oid_trans.open(self.full_name, "oidtrans", db.DB_HASH, self.oid_trans.open(self.full_name, "oidtrans", db.DB_HASH,
flags=openflags) flags=table_flags)
self.oid_trans.truncate() self.oid_trans.truncate()
self.media_map.associate(self.oid_trans, find_idmap, db.DB_CREATE) self.media_map.associate(self.oid_trans, find_idmap, db.DB_CREATE)
@ -484,7 +484,7 @@ class GrampsBSDDB(GrampsDbBase):
self.sid_trans = db.DB(self.env) self.sid_trans = db.DB(self.env)
self.sid_trans.set_flags(db.DB_DUP) self.sid_trans.set_flags(db.DB_DUP)
self.sid_trans.open(self.full_name, "sidtrans", db.DB_HASH, self.sid_trans.open(self.full_name, "sidtrans", db.DB_HASH,
flags=openflags) flags=table_flags)
self.sid_trans.truncate() self.sid_trans.truncate()
self.source_map.associate(self.sid_trans, find_idmap, db.DB_CREATE) self.source_map.associate(self.sid_trans, find_idmap, db.DB_CREATE)
@ -500,7 +500,7 @@ class GrampsBSDDB(GrampsDbBase):
self.rid_trans = db.DB(self.env) self.rid_trans = db.DB(self.env)
self.rid_trans.set_flags(db.DB_DUP) self.rid_trans.set_flags(db.DB_DUP)
self.rid_trans.open(self.full_name, "ridtrans", db.DB_HASH, self.rid_trans.open(self.full_name, "ridtrans", db.DB_HASH,
flags=openflags) flags=table_flags)
self.rid_trans.truncate() self.rid_trans.truncate()
self.repository_map.associate(self.rid_trans, find_idmap, db.DB_CREATE) self.repository_map.associate(self.rid_trans, find_idmap, db.DB_CREATE)
@ -555,7 +555,7 @@ class GrampsBSDDB(GrampsDbBase):
return return
def _delete_primary_from_reference_map(self, handle): def _delete_primary_from_reference_map(self, handle, transaction):
"""Remove all references to the primary object from the reference_map""" """Remove all references to the primary object from the reference_map"""
primary_cur = self.get_reference_map_primary_cursor() primary_cur = self.get_reference_map_primary_cursor()
@ -577,13 +577,13 @@ class GrampsBSDDB(GrampsDbBase):
main_key = (handle, cPickle.loads(data)[1][1]) main_key = (handle, cPickle.loads(data)[1][1])
self.reference_map.delete(str(main_key),txn=self.txn) self._remove_reference(main_key,transaction)
ret = primary_cur.next_dup() ret = primary_cur.next_dup()
primary_cur.close() primary_cur.close()
def _update_reference_map(self, obj): def _update_reference_map(self, obj, transaction):
# Add references to the reference_map for all primary object referenced # Add references to the reference_map for all primary object referenced
# from the primary object 'obj' or any of its secondary objects. # from the primary object 'obj' or any of its secondary objects.
@ -641,21 +641,49 @@ class GrampsBSDDB(GrampsDbBase):
if len(new_references) > 0: if len(new_references) > 0:
for (ref_class_name,ref_handle) in new_references: for (ref_class_name,ref_handle) in new_references:
self.reference_map.put( self._add_reference((handle,ref_handle),data,transaction)
str((handle,ref_handle),), #self.reference_map.put(
((CLASS_TO_KEY_MAP[obj.__class__.__name__],handle), # str((handle,ref_handle),),
(CLASS_TO_KEY_MAP[ref_class_name],ref_handle),), # ((CLASS_TO_KEY_MAP[obj.__class__.__name__],handle),
txn=self.txn) # (CLASS_TO_KEY_MAP[ref_class_name],ref_handle),),
# txn=self.txn)
# handle deletion of old references # handle deletion of old references
if len(no_longer_required_references) > 0: if len(no_longer_required_references) > 0:
for (ref_class_name,ref_handle) in no_longer_required_references: for (ref_class_name,ref_handle) in no_longer_required_references:
try: try:
self.reference_map.delete(str((handle,ref_handle),), self._remove_reference((handle,ref_handle),transaction)
txn=self.txn) #self.reference_map.delete(str((handle,ref_handle),),
# txn=self.txn)
except: # ignore missing old reference except: # ignore missing old reference
pass pass
def _remove_reference(self,key,transaction):
"""
Removes the reference specified by the key,
preserving the change in the passed transaction.
"""
if not self.readonly:
data = self.reference_map.get(str(main_key),txn=self.txn)
if not transaction.batch:
transaction.add(REFERENCE_KEY,str(key),cPickle.dumps(data))
transaction.reference_del.append(str(key))
def _add_reference(self,key,data,transaction):
"""
Adds the reference specified by the key and the data,
preserving the change in the passed transaction.
"""
if self.readonly or not key:
return
if transaction.batch:
self.reference_map.put(str(key),data,txn=self.txn)
else:
transaction.add(REFERENCE_KEY,str(key),None)
transaction.reference_add.append(str(key),data)
def reindex_reference_map(self): def reindex_reference_map(self):
"""Reindex all primary records in the database. This will be a """Reindex all primary records in the database. This will be a
slow process for large databases. slow process for large databases.
@ -704,7 +732,7 @@ class GrampsBSDDB(GrampsDbBase):
obj = class_func() obj = class_func()
obj.unserialize(val) obj.unserialize(val)
self._update_reference_map(obj) self._update_reference_map(obj,transaction)
data = cursor.next() data = cursor.next()
@ -771,31 +799,24 @@ class GrampsBSDDB(GrampsDbBase):
self.db_is_open = False self.db_is_open = False
def _del_person(self,handle): def _del_person(self,handle):
self._delete_primary_from_reference_map(handle)
self.person_map.delete(str(handle),txn=self.txn) self.person_map.delete(str(handle),txn=self.txn)
def _del_source(self,handle): def _del_source(self,handle):
self._delete_primary_from_reference_map(handle)
self.source_map.delete(str(handle),txn=self.txn) self.source_map.delete(str(handle),txn=self.txn)
def _del_repository(self,handle): def _del_repository(self,handle):
self._delete_primary_from_reference_map(handle)
self.repository_map.delete(str(handle),txn=self.txn) self.repository_map.delete(str(handle),txn=self.txn)
def _del_place(self,handle): def _del_place(self,handle):
self._delete_primary_from_reference_map(handle)
self.place_map.delete(str(handle),txn=self.txn) self.place_map.delete(str(handle),txn=self.txn)
def _del_media(self,handle): def _del_media(self,handle):
self._delete_primary_from_reference_map(handle)
self.media_map.delete(str(handle),txn=self.txn) self.media_map.delete(str(handle),txn=self.txn)
def _del_family(self,handle): def _del_family(self,handle):
self._delete_primary_from_reference_map(handle)
self.family_map.delete(str(handle),txn=self.txn) self.family_map.delete(str(handle),txn=self.txn)
def _del_event(self,handle): def _del_event(self,handle):
self._delete_primary_from_reference_map(handle)
self.event_map.delete(str(handle),txn=self.txn) self.event_map.delete(str(handle),txn=self.txn)
def set_name_group_mapping(self,name,group): def set_name_group_mapping(self,name,group):
@ -1012,16 +1033,48 @@ class GrampsBSDDB(GrampsDbBase):
# Start BSD DB transaction -- DBTxn # Start BSD DB transaction -- DBTxn
self.txn = self.env.txn_begin() self.txn = self.env.txn_begin()
return GrampsDbBase.transaction_begin(self,msg) return BdbTransaction(msg,self.undodb)
def transaction_commit(self,transaction,msg): def transaction_commit(self,transaction,msg):
GrampsDbBase.transaction_commit(self,transaction,msg) GrampsDbBase.transaction_commit(self,transaction,msg)
for (key,data) in transaction.reference_add:
self.reference_map.put(str(key),data,txn=self.txn)
for (key,data) in transaction.reference_del:
self.reference_map.delete(str(key),txn=self.txn)
# Commit BSD DB transaction -- DBTxn # Commit BSD DB transaction -- DBTxn
self.txn.commit() self.txn.commit()
self.txn = None self.txn = None
def undo(self):
print "Doing it"
self.txn = self.env.txn_begin()
GrampsDbBase.undo(self)
self.txn.commit()
self.txn = None
def undo_reference(self,data,handle):
if data == None:
self.reference_map.delete(handle,txn=self.txn)
else:
self.reference_map.put(handl,data,txn=self.txn)
def undo_data(self,data,handle,db_map,signal_root):
if data == None:
self.emit(signal_root + '-delete',([handle],))
db_map.delete(handle,txn=self.txn)
else:
ex_data = db_map.get(handle,txn=self.txn)
if ex_data:
signal = signal_root + '-update'
else:
signal = signal_root + '-add'
db_map.put(handle,data,txn=self.txn)
self.emit(signal,([handle],))
def gramps_upgrade(self): def gramps_upgrade(self):
child_rel_notrans = [ child_rel_notrans = [
"None", "Birth", "Adopted", "Stepchild", "None", "Birth", "Adopted", "Stepchild",
@ -1391,6 +1444,14 @@ class GrampsBSDDB(GrampsDbBase):
self.transaction_commit(trans,"Upgrade to DB version 9") self.transaction_commit(trans,"Upgrade to DB version 9")
print "Done upgrading to DB version 9" print "Done upgrading to DB version 9"
class BdbTransaction(Transaction):
def __init__(self,msg,db):
Transaction.__init__(self,msg,db)
self.reference_del = []
self.reference_add = []
_attribute_conversion_9 = { _attribute_conversion_9 = {
"Caste" : (Attribute.CASTE,""), "Caste" : (Attribute.CASTE,""),
"Description" : (Attribute.DESCRIPTION,""), "Description" : (Attribute.DESCRIPTION,""),

View File

@ -64,6 +64,7 @@ EVENT_KEY = 3
MEDIA_KEY = 4 MEDIA_KEY = 4
PLACE_KEY = 5 PLACE_KEY = 5
REPOSITORY_KEY = 6 REPOSITORY_KEY = 6
REFERENCE_KEY = 7
PERSON_COL_KEY = 'columns' PERSON_COL_KEY = 'columns'
CHILD_COL_KEY = 'child_columns' CHILD_COL_KEY = 'child_columns'
@ -385,7 +386,7 @@ class GrampsDbBase(GrampsDBCallback):
as part of the transaction. as part of the transaction.
""" """
self._update_reference_map(person) self._update_reference_map(person,transaction)
old_data = self._commit_base( old_data = self._commit_base(
person, self.person_map, PERSON_KEY, transaction.person_update, person, self.person_map, PERSON_KEY, transaction.person_update,
@ -410,7 +411,7 @@ class GrampsDbBase(GrampsDBCallback):
as part of the transaction. as part of the transaction.
""" """
self._update_reference_map(obj) self._update_reference_map(obj,transaction)
self._commit_base(obj, self.media_map, MEDIA_KEY, self._commit_base(obj, self.media_map, MEDIA_KEY,
transaction.media_update, transaction.media_add, transaction.media_update, transaction.media_add,
@ -422,7 +423,7 @@ class GrampsDbBase(GrampsDBCallback):
as part of the transaction. as part of the transaction.
""" """
self._update_reference_map(source) self._update_reference_map(source,transaction)
self._commit_base(source, self.source_map, SOURCE_KEY, self._commit_base(source, self.source_map, SOURCE_KEY,
transaction.source_update, transaction.source_add, transaction.source_update, transaction.source_add,
@ -434,7 +435,7 @@ class GrampsDbBase(GrampsDBCallback):
as part of the transaction. as part of the transaction.
""" """
self._update_reference_map(place) self._update_reference_map(place,transaction)
self._commit_base(place, self.place_map, PLACE_KEY, self._commit_base(place, self.place_map, PLACE_KEY,
transaction.place_update, transaction.place_add, transaction.place_update, transaction.place_add,
@ -456,7 +457,7 @@ class GrampsDbBase(GrampsDBCallback):
as part of the transaction. as part of the transaction.
""" """
self._update_reference_map(event) self._update_reference_map(event,transaction)
self._commit_base(event, self.event_map, EVENT_KEY, self._commit_base(event, self.event_map, EVENT_KEY,
transaction.event_update, transaction.event_add, transaction.event_update, transaction.event_add,
@ -468,7 +469,7 @@ class GrampsDbBase(GrampsDBCallback):
as part of the transaction. as part of the transaction.
""" """
self._update_reference_map(family) self._update_reference_map(family,transaction)
self._commit_base(family, self.family_map, FAMILY_KEY, self._commit_base(family, self.family_map, FAMILY_KEY,
transaction.family_update, transaction.family_add, transaction.family_update, transaction.family_add,
@ -483,7 +484,7 @@ class GrampsDbBase(GrampsDBCallback):
as part of the transaction. as part of the transaction.
""" """
self._update_reference_map(repository) self._update_reference_map(repository,transaction)
self._commit_base(repository, self.repository_map, REPOSITORY_KEY, self._commit_base(repository, self.repository_map, REPOSITORY_KEY,
transaction.repository_update, transaction.repository_add, transaction.repository_update, transaction.repository_add,
@ -1173,7 +1174,10 @@ class GrampsDbBase(GrampsDBCallback):
subitems.reverse() subitems.reverse()
for record_id in subitems: for record_id in subitems:
(key, handle, data) = transaction.get_record(record_id) (key, handle, data) = transaction.get_record(record_id)
self.undo_data(data,handle,mapbase[key],_sigbase[key]) if key == REFERENCE_KEY:
self.undo_reference(data,handle)
else:
self.undo_data(data,handle,mapbase[key],_sigbase[key])
if self.undo_callback: if self.undo_callback:
if self.undoindex == -1: if self.undoindex == -1:
@ -1183,6 +1187,9 @@ class GrampsDbBase(GrampsDBCallback):
self.undo_callback(_("_Undo %s") % transaction.get_description()) self.undo_callback(_("_Undo %s") % transaction.get_description())
return True return True
def undo_reference(self,data,handle):
pass
def undo_data(self,data,handle,db_map,signal_root): def undo_data(self,data,handle,db_map,signal_root):
if data == None: if data == None:
self.emit(signal_root + '-delete',([handle],)) self.emit(signal_root + '-delete',([handle],))
@ -1309,6 +1316,7 @@ class GrampsDbBase(GrampsDBCallback):
method must be overridden in the derived class. method must be overridden in the derived class.
""" """
self._delete_primary_from_reference_map(handle,transaction)
if not self.readonly: if not self.readonly:
person = self.get_person_from_handle(handle) person = self.get_person_from_handle(handle)
self.genderStats.uncount_person (person) self.genderStats.uncount_person (person)
@ -1317,6 +1325,7 @@ class GrampsDbBase(GrampsDBCallback):
transaction.person_del.append(str(handle)) transaction.person_del.append(str(handle))
def _do_remove_object(self,handle,trans,dmap,key,del_list): def _do_remove_object(self,handle,trans,dmap,key,del_list):
self._delete_primary_from_reference_map(handle,transaction)
if not self.readonly: if not self.readonly:
handle = str(handle) handle = str(handle)
if not trans.batch: if not trans.batch:
@ -1594,7 +1603,13 @@ class GrampsDbBase(GrampsDBCallback):
default = [(1,0),(1,1),(0,5),(0,6),(1,2),(1,3),(0,4),(0,7),(0,8),(0,9),(0,10)] default = [(1,0),(1,1),(0,5),(0,6),(1,2),(1,3),(0,4),(0,7),(0,8),(0,9),(0,10)]
return self._get_column_order(REPOSITORY_COL_KEY,default) return self._get_column_order(REPOSITORY_COL_KEY,default)
def _update_reference_map(self,obj): def _delete_primary_from_reference_map(self, handle, transaction):
"""Called each time an object is removed from the database. This can
be used by subclasses to update any additional index tables that might
need to be changed."""
pass
def _update_reference_map(self,obj,transaction):
"""Called each time an object is writen to the database. This can """Called each time an object is writen to the database. This can
be used by subclasses to update any additional index tables that might be used by subclasses to update any additional index tables that might
need to be changed.""" need to be changed."""

View File

@ -313,7 +313,7 @@ class ViewManager:
('SaveAs', gtk.STOCK_SAVE_AS, '_Save As'), ('SaveAs', gtk.STOCK_SAVE_AS, '_Save As'),
('Export', gtk.STOCK_SAVE_AS, '_Export', "<control>e", None, self.export_data), ('Export', gtk.STOCK_SAVE_AS, '_Export', "<control>e", None, self.export_data),
('Abandon', gtk.STOCK_REVERT_TO_SAVED, '_Abandon changes and quit'), ('Abandon', gtk.STOCK_REVERT_TO_SAVED, '_Abandon changes and quit'),
('Undo', gtk.STOCK_UNDO, '_Undo', '<control>z' ), ('Undo', gtk.STOCK_UNDO, '_Undo', '<control>z', None, self.undo),
('CmpMerge', None, '_Compare and merge'), ('CmpMerge', None, '_Compare and merge'),
('FastMerge', None, '_Fast merge'), ('FastMerge', None, '_Fast merge'),
('ScratchPad', gtk.STOCK_PASTE, '_ScratchPad', None, None, self.scratchpad), ('ScratchPad', gtk.STOCK_PASTE, '_ScratchPad', None, None, self.scratchpad),
@ -821,6 +821,9 @@ class ViewManager:
while gtk.events_pending(): while gtk.events_pending():
gtk.main_iteration() gtk.main_iteration()
def undo(self,obj):
self.state.db.undo()
def export_data(self,obj): def export_data(self,obj):
import Exporter import Exporter
Exporter.Exporter(self.state,self.uistate) Exporter.Exporter(self.state,self.uistate)