2006-05-06 Alex Roitman <shura@gramps-project.org>

* src/GrampsDb/_GrampsBSDDB.py (load): Use common undodb
	methods; reset undo history.
	* src/GrampsDb/_GrampsInMemDB.py (load): Use common undodb
	methods; reset undo history.
	* src/GrampsDb/_GrampsXMLDB.py: Minor fix.
	* src/GrampsDb/_GrampsGEDDB.py: Minor fix.
	* src/GrampsDb/_GrampsDbBase.py: Undo history support.
	* src/UndoHistory.py: Fixes and additions.
	* src/ViewManager.py (post_load): Re-set undo/redo labels.



svn: r6569
This commit is contained in:
Alex Roitman 2006-05-07 05:22:44 +00:00
parent 064c8ce061
commit 179a8dac52
8 changed files with 144 additions and 76 deletions

View File

@ -1,3 +1,14 @@
2006-05-06 Alex Roitman <shura@gramps-project.org>
* src/GrampsDb/_GrampsBSDDB.py (load): Use common undodb
methods; reset undo history.
* src/GrampsDb/_GrampsInMemDB.py (load): Use common undodb
methods; reset undo history.
* src/GrampsDb/_GrampsXMLDB.py: Minor fix.
* src/GrampsDb/_GrampsGEDDB.py: Minor fix.
* src/GrampsDb/_GrampsDbBase.py: Undo history support.
* src/UndoHistory.py: Fixes and additions.
* src/ViewManager.py (post_load): Re-set undo/redo labels.
2006-05-06 Don Allingham <don@gramps-project.org>
* src/PluginUtils/_ReportUtils.py: fix set_nick_name
* src/RelLib/_MediaRef.py: handle initialization of Ref object

View File

@ -311,7 +311,6 @@ class GrampsBSDDB(GrampsDbBase):
env_flags = db.DB_CREATE|db.DB_PRIVATE|\
db.DB_INIT_MPOOL|db.DB_INIT_LOG
self.undolog = "%s.undo" % name
env_name = os.path.expanduser(const.bsddbenv_dir)
if not os.path.isdir(env_name):
os.mkdir(env_name)
@ -373,12 +372,16 @@ class GrampsBSDDB(GrampsDbBase):
callback(75)
if not self.readonly:
self.undodb = db.DB()
self.undodb.open(self.undolog, db.DB_RECNO, db.DB_CREATE)
self.open_undodb()
self.db_is_open = True
callback(87)
# Re-set the undo history to a fresh session start
self.undoindex = -1
self.translist = [None] * len(self.translist)
self.abort_possible = True
self.undo_history_timestamp = time.time()
return 1
@ -840,13 +843,8 @@ class GrampsBSDDB(GrampsDbBase):
self.event_map.close()
self.env.close()
if not self.readonly:
self.undodb.close()
try:
os.remove(self.undolog)
except:
pass
self.close_undodb()
self.person_map = None
self.family_map = None
self.repository_map = None

View File

@ -39,6 +39,7 @@ import random
import locale
import os
from sys import maxint
from bsddb import db
from gettext import gettext as _
try:
@ -261,6 +262,7 @@ class GrampsDbBase(GrampsDBCallback):
self.undoindex = -1
self.translist = [None] * _UNDO_SIZE
self.abort_possible = True
self.undo_history_timestamp = 0
self.default = None
self.owner = Researcher()
self.bookmarks = []
@ -333,6 +335,20 @@ class GrampsDbBase(GrampsDBCallback):
def get_repository_cursor(self):
assert False, "Needs to be overridden in the derived class"
def open_undodb(self):
if not self.readonly:
self.undolog = "%s.undo" % self.full_name
self.undodb = db.DB()
self.undodb.open(self.undolog, db.DB_RECNO, db.DB_CREATE)
def close_undodb(self):
if not self.readonly:
self.undodb.close()
try:
os.remove(self.undolog)
except:
pass
def load(self, name, callback, mode="w"):
"""
Opens the specified database. The method needs to be overridden
@ -1209,6 +1225,7 @@ class GrampsDbBase(GrampsDBCallback):
# A batch transaction does not store the commits
# Aborting the session completely will become impossible.
self.abort_possible = False
self.undo_history_timestamp = time.time()
# Undo is also impossible after batch transaction
self.undoindex = -1
return Transaction(msg, self.undodb, batch)
@ -1230,6 +1247,7 @@ class GrampsDbBase(GrampsDBCallback):
# We overran the undo size.
# Aborting the session completely will become impossible.
self.abort_possible = False
self.undo_history_timestamp = time.time()
self.translist = self.translist[0:-1] + [ transaction ]
else:
self.translist[self.undoindex] = transaction
@ -1306,12 +1324,29 @@ class GrampsDbBase(GrampsDBCallback):
retlist.append(str(handle))
return retlist
def undo_available(self):
# returns boolean of whether or not there's a possibility of undo
if self.undoindex == -1 or self.readonly:
return False
return True
def redo_available(self):
# returns boolean of whether or not there's a possibility of redo
if self.undoindex >= _UNDO_SIZE or self.readonly:
return False
if self.translist[self.undoindex+1] == None:
return False
return True
def undo(self,update_history=True):
"""
Accesses the last committed transaction, and reverts the data to
the state before the transaction was committed.
"""
if self.undoindex == -1 or self.readonly:
if not self.undo_available():
return False
transaction = self.translist[self.undoindex]
@ -1331,19 +1366,19 @@ class GrampsDbBase(GrampsDBCallback):
self.undo_data(old_data, handle, mapbase[key], _sigbase[key])
if self.undo_callback:
if self.undoindex == -1:
self.undo_callback(None)
else:
if self.undo_available():
new_transaction = self.translist[self.undoindex]
self.undo_callback(_("_Undo %s")
% new_transaction.get_description())
if self.redo_callback:
if self.undoindex >= _UNDO_SIZE \
or self.translist[self.undoindex+1]==None:
self.redo_callback(None)
else:
self.undo_callback(None)
if self.redo_callback:
if self. redo_available():
self.redo_callback(_("_Redo %s")
% transaction.get_description())
else:
self.redo_callback(None)
if update_history and self.undo_history_callback:
self.undo_history_callback()
@ -1354,14 +1389,12 @@ class GrampsDbBase(GrampsDBCallback):
Accesses the last undone transaction, and reverts the data to
the state before the transaction was undone.
"""
if self.undoindex >= _UNDO_SIZE or self.readonly:
return False
transaction = self.translist[self.undoindex+1]
if transaction == None:
if not self.redo_available():
return False
self.undoindex += 1
transaction = self.translist[self.undoindex]
mapbase = (self.person_map, self.family_map, self.source_map,
self.event_map, self.media_map, self.place_map,
self.repository_map)
@ -1375,26 +1408,19 @@ class GrampsDbBase(GrampsDBCallback):
self.undo_data(new_data, handle, mapbase[key], _sigbase[key])
if self.undo_callback:
if self.undoindex == -1:
self.undo_callback(None)
else:
if self.undo_available():
self.undo_callback(_("_Undo %s")
% transaction.get_description())
if self.redo_callback:
if self.undoindex >= _UNDO_SIZE \
or self.translist[self.undoindex+1]==None:
self.redo_callback(None)
else:
self.undo_callback(None)
if self.redo_callback:
if self.redo_available():
new_transaction = self.translist[self.undoindex+1]
self.redo_callback(_("_Redo %s")
% new_transaction.get_description())
if self.undo_callback:
if self.undoindex == _UNDO_SIZE:
self.undo_callback(None)
else:
self.undo_callback(_("_Undo %s")
% transaction.get_description())
self.redo_callback(None)
if update_history and self.undo_history_callback:
self.undo_history_callback()

View File

@ -1,7 +1,7 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2004 Donald N. Allingham
# Copyright (C) 2000-2006 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -61,6 +61,5 @@ class GrampsGEDDB(GrampsInMemDB):
return
if not self.readonly and len(self.undodb) > 0:
writer = WriteGedcom.GedcomWriter(self,self.get_default_person())
writer.export_data(self.filename)
writer.export_data(self.full_name)
self.db_is_open = False

View File

@ -30,8 +30,8 @@ must hold all of their data in memory.
# Python modules
#
#-------------------------------------------------------------------------
from bsddb import dbshelve, db
import sets
import time
#-------------------------------------------------------------------------
#
@ -99,12 +99,16 @@ class GrampsInMemDB(GrampsDbBase):
self.undodb = []
def load(self,name,callback,mode="w"):
self.undolog = "%s.log" % name
self.undodb = db.DB()
self.undodb.open(self.undolog, db.DB_RECNO, db.DB_CREATE)
self.filename = name
self.open_undodb()
self.full_name = name
self.readonly = mode == "r"
# Re-set the undo history to a fresh session start
self.undoindex = -1
self.translist = [None] * len(self.state.db.translist)
self.abort_possible = True
self.undo_history_timestamp = time.time()
def get_person_cursor(self):
return GrampsInMemCursor(self.person_map)
@ -130,12 +134,7 @@ class GrampsInMemDB(GrampsDbBase):
return GrampsInMemCursor(self.event_map)
def close(self):
if not self.readonly:
self.undodb.close()
try:
os.remove(self.undolog)
except:
pass
self.close_undodb()
def set_name_group_mapping(self,name,group):
if group == None and self.name_group.has_key(name):

View File

@ -1,7 +1,7 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2004 Donald N. Allingham
# Copyright (C) 2000-2006 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -62,5 +62,5 @@ class GrampsXMLDB(GrampsInMemDB):
if not self.db_is_open:
return
if not self.readonly and len(self.undodb) > 0:
WriteXML.quick_write(self,self.filename)
WriteXML.quick_write(self,self.full_name)
self.db_is_open = False

View File

@ -62,18 +62,22 @@ class UndoHistory(ManagedWindow.ManagedWindow):
self.title = _("Undo History")
ManagedWindow.ManagedWindow.__init__(self,uistate,[],self.__class__)
self.db = dbstate.db
self.dbstate = dbstate
self.set_window(
gtk.Dialog("",uistate.window,
gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_UNDO,gtk.RESPONSE_REJECT,
gtk.STOCK_REDO,gtk.RESPONSE_ACCEPT,
gtk.STOCK_CLEAR,gtk.RESPONSE_APPLY,
gtk.STOCK_CLOSE,gtk.RESPONSE_CLOSE,
)
),
None, self.title)
self.window.set_size_request(600,400)
window = gtk.Dialog("",uistate.window,
gtk.DIALOG_DESTROY_WITH_PARENT,None)
self.undo_button = window.add_button(gtk.STOCK_UNDO,
gtk.RESPONSE_REJECT)
self.redo_button = window.add_button(gtk.STOCK_REDO,
gtk.RESPONSE_ACCEPT)
self.clear_button = window.add_button(gtk.STOCK_CLEAR,
gtk.RESPONSE_APPLY)
self.close_button = window.add_button(gtk.STOCK_CLOSE,
gtk.RESPONSE_CLOSE)
self.set_window(window, None, self.title)
self.window.set_size_request(400,200)
self.window.connect('response', self._response)
scrolled_window = gtk.ScrolledWindow()
@ -88,7 +92,7 @@ class UndoHistory(ManagedWindow.ManagedWindow):
gtk.TreeViewColumn(_('Original time'), gtk.CellRendererText(),
text=0))
self.list.append_column(
gtk.TreeViewColumn(_('Modification'), gtk.CellRendererText(),
gtk.TreeViewColumn(_('Action'), gtk.CellRendererText(),
text=1))
scrolled_window.add(self.list)
@ -96,9 +100,21 @@ class UndoHistory(ManagedWindow.ManagedWindow):
self.window.show_all()
self._build_model()
self._update_ui()
self.db_change_key = dbstate.connect('database-changed',self._close)
self.selection.connect('changed',self._selection_changed)
self.show()
self.db.connect('database-changed',self.clear)
self.selection.connect('changed',self._move)
def _close(self,obj):
self.dbstate.disconnect(self.db_change_key)
self.close()
def _selection_changed(self,obj):
(model,node) = self.selection.get_selected()
if node:
path = self.model.get_path(node)
self._move(path[0]-self.db.undoindex-1)
def _response(self,obj,response_id):
if response_id == gtk.RESPONSE_CLOSE:
@ -123,33 +139,50 @@ class UndoHistory(ManagedWindow.ManagedWindow):
def clear(self):
self.db.undoindex = -1
self.db.translist = [None] * len(self.db.translist)
self.db.abort_possible = False
self.update()
if self.db.undo_callback:
self.db.undo_callback(None)
if self.db.redo_callback:
self.db.redo_callback(None)
def _move(self,obj,steps=-1):
self._update_ui()
def _move(self,steps=-1):
if steps == 0 :
return
elif steps < 0:
func = self.db.undo
elif steps > 0:
func = self.db.redo
for step in range(abs(steps)):
func(False)
self.update()
def _update_ui(self):
pass
self.undo_button.set_sensitive(self.db.undo_available())
self.redo_button.set_sensitive(self.db.redo_available())
self.clear_button.set_sensitive(
self.db.undo_available() or self.db.redo_available() )
def _build_model(self):
self.model.clear()
if self.db.abort_possible:
mod_text = _('Database opened')
else:
mod_text = _('History cleared')
time_text = time.ctime(self.db.undo_history_timestamp)
self.model.append(row=[time_text,mod_text])
# Get the not-None portion of transaction list
translist = [item for item in self.db.translist if item]
translist.reverse()
for transaction in translist:
time_text = time.ctime(transaction.timestamp)
mod_text = transaction.get_description()
self.model.append(row=[time_text,mod_text])
if self.db.undoindex < 0:
self.selection.unselect_all()
else:
path = (self.db.undoindex,)
self.selection.select_path(path)
path = (self.db.undoindex+1,)
self.selection.select_path(path)
def update(self):
self._build_model()
self._update_ui()

View File

@ -938,6 +938,8 @@ class ViewManager:
self.change_page(None, None)
self.state.db.undo_callback = self.change_undo_label
self.state.db.redo_callback = self.change_redo_label
self.change_undo_label(None)
self.change_redo_label(None)
self.state.db.undo_history_callback = self.undo_history_update
self.actiongroup.set_visible(True)
self.window.window.set_cursor(None)