diff --git a/gramps/gen/db/generic.py b/gramps/gen/db/generic.py index ca476cd9e..7100e8376 100644 --- a/gramps/gen/db/generic.py +++ b/gramps/gen/db/generic.py @@ -144,7 +144,15 @@ class DbGenericUndo(DbUndo): if key == REFERENCE_KEY: self.undo_reference(new_data, handle) else: - self.undo_data(new_data, handle, key, db.emit, SIGBASE[key]) + self.undo_data(new_data, handle, key) + # now emit the signals + for record_id in subitems: + (key, trans_type, handle, old_data, new_data) = \ + pickle.loads(self.undodb[record_id]) + + if key != REFERENCE_KEY: + self.undo_signals(new_data, handle, key, + db.emit, SIGBASE[key]) self.db._txn_commit() except: self.db._txn_abort() @@ -187,8 +195,15 @@ class DbGenericUndo(DbUndo): if key == REFERENCE_KEY: self.undo_reference(old_data, handle) else: - self.undo_data(old_data, handle, key, db.emit, SIGBASE[key]) + self.undo_data(old_data, handle, key) + # now emit the signals + for record_id in subitems: + (key, trans_type, handle, old_data, new_data) = \ + pickle.loads(self.undodb[record_id]) + if key != REFERENCE_KEY: + self.undo_signals(old_data, handle, key, + db.emit, SIGBASE[key]) self.db._txn_commit() except: self.db._txn_abort() @@ -224,7 +239,26 @@ class DbGenericUndo(DbUndo): "VALUES(?, ?, ?, ?)") self.db.dbapi.execute(sql, data) - def undo_data(self, data, handle, obj_key, emit, signal_root): + def undo_data(self, data, handle, obj_key): + """ + Helper method to undo/redo the changes made + """ + cls = KEY_TO_CLASS_MAP[obj_key] + table = cls.lower() + if data is None: + sql = "DELETE FROM %s WHERE handle = ?" % table + self.db.dbapi.execute(sql, [handle]) + else: + if self.db.has_handle(obj_key, handle): + sql = "UPDATE %s SET blob_data = ? WHERE handle = ?" % table + self.db.dbapi.execute(sql, [pickle.dumps(data), handle]) + else: + sql = "INSERT INTO %s (handle, blob_data) VALUES (?, ?)" % table + self.db.dbapi.execute(sql, [handle, pickle.dumps(data)]) + obj = self.db.get_table_func(cls)["class_func"].create(data) + self.db._update_secondary_values(obj) + + def undo_signals(self, data, handle, obj_key, emit, signal_root): """ Helper method to undo/redo the changes made """ @@ -232,19 +266,11 @@ class DbGenericUndo(DbUndo): table = cls.lower() if data is None: emit(signal_root + '-delete', ([handle],)) - sql = "DELETE FROM %s WHERE handle = ?" % table - self.db.dbapi.execute(sql, [handle]) else: if self.db.has_handle(obj_key, handle): signal = signal_root + '-update' - sql = "UPDATE %s SET blob_data = ? WHERE handle = ?" % table - self.db.dbapi.execute(sql, [pickle.dumps(data), handle]) else: signal = signal_root + '-add' - sql = "INSERT INTO %s (handle, blob_data) VALUES (?, ?)" % table - self.db.dbapi.execute(sql, [handle, pickle.dumps(data)]) - obj = self.db.get_table_func(cls)["class_func"].create(data) - self.db._update_secondary_values(obj) emit(signal, ([handle],)) class Cursor: diff --git a/gramps/plugins/db/bsddb/undoredo.py b/gramps/plugins/db/bsddb/undoredo.py index be62072ce..21e1951e3 100644 --- a/gramps/plugins/db/bsddb/undoredo.py +++ b/gramps/plugins/db/bsddb/undoredo.py @@ -237,8 +237,15 @@ class DbUndo: if key == REFERENCE_KEY: self.undo_reference(old_data, handle, self.mapbase[key]) else: - self.undo_data(old_data, handle, self.mapbase[key], - db.emit, _SIGBASE[key]) + self.undo_data(old_data, handle, self.mapbase[key]) + # now emit the signals + for record_id in subitems: + (key, trans_type, handle, old_data, new_data) = \ + pickle.loads(self.undodb[record_id]) + + if key != REFERENCE_KEY: + self.undo_signals(old_data, handle, self.mapbase[key], + db.emit, _SIGBASE[key]) # Notify listeners if db.undo_callback: if self.undo_count > 0: @@ -275,8 +282,15 @@ class DbUndo: if key == REFERENCE_KEY: self.undo_reference(new_data, handle, self.mapbase[key]) else: - self.undo_data(new_data, handle, self.mapbase[key], - db.emit, _SIGBASE[key]) + self.undo_data(new_data, handle, self.mapbase[key]) + # Process all signals in the transaction + for record_id in subitems: + (key, trans_type, handle, old_data, new_data) = \ + pickle.loads(self.undodb[record_id]) + + if key != REFERENCE_KEY: + self.undo_signals(new_data, handle, self.mapbase[key], + db.emit, _SIGBASE[key]) # Notify listeners if db.undo_callback: db.undo_callback(_("_Undo %s") @@ -308,21 +322,33 @@ class DbUndo: self.db._log_error() raise DbError(msg) - def undo_data(self, data, handle, db_map, emit, signal_root): + def undo_data(self, data, handle, db_map): + """ + Helper method to undo/redo the changes made + """ + try: + if data is None: + db_map.delete(handle, txn=self.txn) + else: + db_map.put(handle, data, txn=self.txn) + + except DBERRS as msg: + self.db._log_error() + raise DbError(msg) + + def undo_signals(self, data, handle, db_map, emit, signal_root): """ Helper method to undo/redo the changes made """ try: if data is None: emit(signal_root + '-delete', ([handle.decode('utf-8')],)) - 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) emit(signal, ([handle.decode('utf-8')],)) except DBERRS as msg: