Updates to undo/redo logic -- part 1
svn: r15277
This commit is contained in:
parent
71575f91ea
commit
72e19bb7a9
@ -29,6 +29,7 @@
|
||||
#------------------------------------------------------------------------
|
||||
import time
|
||||
from gen.ggettext import gettext as _
|
||||
from itertools import chain
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -110,29 +111,27 @@ class UndoHistory(ManagedWindow.ManagedWindow):
|
||||
self.show()
|
||||
|
||||
def _selection_changed(self, obj):
|
||||
assert self.undodb.undo_count == self.undodb.undoindex + 1
|
||||
(model, node) = self.selection.get_selected()
|
||||
if not node:
|
||||
return
|
||||
path = self.model.get_path(node)
|
||||
|
||||
start = min(path[0], self.undodb.undoindex+1)
|
||||
end = max(path[0], self.undodb.undoindex+1)
|
||||
start = min(path[0], self.undodb.undo_count)
|
||||
end = max(path[0], self.undodb.undo_count)
|
||||
|
||||
self._paint_rows(0, len(self.model)-1, False)
|
||||
self._paint_rows(start, end, True)
|
||||
|
||||
if path[0] < self.undodb.undoindex+1:
|
||||
if path[0] < self.undodb.undo_count:
|
||||
# This transaction is an undo candidate
|
||||
self.redo_button.set_sensitive(False)
|
||||
self.undo_button.set_sensitive(self.undodb.undo_available())
|
||||
|
||||
elif path[0] > self.undodb.undoindex+1:
|
||||
else: # path[0] >= self.undodb.undo_count:
|
||||
# This transaction is an redo candidate
|
||||
self.undo_button.set_sensitive(False)
|
||||
self.redo_button.set_sensitive(self.undodb.redo_available())
|
||||
|
||||
else: #path[0] == self.undodb.undoindex+1
|
||||
self.undo_button.set_sensitive(self.undodb.undo_available())
|
||||
self.redo_button.set_sensitive(self.undodb.redo_available())
|
||||
|
||||
def _paint_rows(self, start, end, selected=False):
|
||||
if selected:
|
||||
(fg, bg) = get_colors(self.tree, gtk.STATE_SELECTED)
|
||||
@ -145,23 +144,26 @@ class UndoHistory(ManagedWindow.ManagedWindow):
|
||||
self.model.set(the_iter, 3, bg)
|
||||
|
||||
def _response(self, obj, response_id):
|
||||
assert self.undodb.undo_count == self.undodb.undoindex + 1
|
||||
if response_id == gtk.RESPONSE_CLOSE:
|
||||
self.close(obj)
|
||||
|
||||
elif response_id == gtk.RESPONSE_REJECT:
|
||||
# Undo the selected entries
|
||||
(model, node) = self.selection.get_selected()
|
||||
if not node:
|
||||
return
|
||||
path = self.model.get_path(node)
|
||||
nsteps = path[0]-self.undodb.undoindex-1
|
||||
nsteps = path[0]-self.undodb.undo_count-1
|
||||
self._move(nsteps or -1)
|
||||
|
||||
elif response_id == gtk.RESPONSE_ACCEPT:
|
||||
# Redo the selected entries
|
||||
(model, node) = self.selection.get_selected()
|
||||
if not node:
|
||||
return
|
||||
path = self.model.get_path(node)
|
||||
nsteps = path[0]-self.undodb.undoindex-1
|
||||
nsteps = path[0]-self.undodb.undo_count
|
||||
self._move(nsteps or 1)
|
||||
|
||||
elif response_id == gtk.RESPONSE_APPLY:
|
||||
@ -181,7 +183,7 @@ class UndoHistory(ManagedWindow.ManagedWindow):
|
||||
|
||||
def clear(self):
|
||||
self.undodb.clear()
|
||||
self.undodb.abort_possible = False
|
||||
self.db.abort_possible = False
|
||||
self.update()
|
||||
if self.db.undo_callback:
|
||||
self.db.undo_callback(None)
|
||||
@ -206,6 +208,7 @@ class UndoHistory(ManagedWindow.ManagedWindow):
|
||||
)
|
||||
|
||||
def _build_model(self):
|
||||
assert self.undodb.undoindex+1 == len(self.undodb.undoq)
|
||||
self.model.clear()
|
||||
fg = bg = None
|
||||
|
||||
@ -217,13 +220,12 @@ class UndoHistory(ManagedWindow.ManagedWindow):
|
||||
time_text = time.ctime(self.undodb.undo_history_timestamp)
|
||||
self.model.append(row=[time_text, mod_text, fg, bg])
|
||||
|
||||
# Get the not-None portion of transaction list
|
||||
translist = filter(None, self.undodb.translist)
|
||||
for transaction in translist:
|
||||
time_text = time.ctime(transaction.timestamp)
|
||||
mod_text = transaction.get_description()
|
||||
# Add the undo and redo queues to the model
|
||||
for txn in chain(self.undodb.undoq, reversed(self.undodb.redoq)):
|
||||
time_text = time.ctime(txn.timestamp)
|
||||
mod_text = txn.get_description()
|
||||
self.model.append(row=[time_text, mod_text, fg, bg])
|
||||
path = (self.undodb.undoindex+1,)
|
||||
path = (self.undodb.undo_count,)
|
||||
self.selection.select_path(path)
|
||||
|
||||
def update(self):
|
||||
|
@ -35,6 +35,7 @@ import time, os
|
||||
import cPickle as pickle
|
||||
from bsddb import db
|
||||
from gen.ggettext import gettext as _
|
||||
from collections import deque
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -53,8 +54,8 @@ import Errors
|
||||
DBERRS = (db.DBRunRecoveryError, db.DBAccessError,
|
||||
db.DBPageNotFoundError, db.DBInvalidArgError)
|
||||
|
||||
_SIGBASE = ('person', 'family', 'source', 'event', 'media',
|
||||
'place', 'repository', 'reference', 'note')
|
||||
_SIGBASE = ('person', 'family', 'source', 'event', 'media', 'place',
|
||||
'repository', 'reference', 'note', 'undoq', 'redoq')
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# DbUndo class
|
||||
@ -91,6 +92,8 @@ class DbUndo(object):
|
||||
"""
|
||||
Clear the undo/redo list (but not the backing storage)
|
||||
"""
|
||||
self.undoq = deque()
|
||||
self.redoq = deque()
|
||||
self.translist = []
|
||||
self.undoindex = -1
|
||||
self.undo_history_timestamp = time.time()
|
||||
@ -161,6 +164,7 @@ class DbUndo(object):
|
||||
txn.timestamp = time.time()
|
||||
|
||||
# If we're within our undo limit, add this transaction
|
||||
self.undoq.append(txn)
|
||||
self.undoindex += 1
|
||||
if self.undoindex < DBUNDO:
|
||||
if self.undoindex >= len(self.translist):
|
||||
@ -168,17 +172,21 @@ class DbUndo(object):
|
||||
else:
|
||||
self.translist[self.undoindex] = txn
|
||||
del self.translist[self.undoindex+1:]
|
||||
self.redoq.clear()
|
||||
|
||||
# Otherwise, we've exceeded our undo limit
|
||||
else:
|
||||
self.db.abort_possible = False
|
||||
self.undo_history_timestamp = time.time()
|
||||
self.translist[-1] = txn
|
||||
self.redoq.clear()
|
||||
|
||||
def undo_available(self):
|
||||
"""
|
||||
Return boolean of whether or not there's a possibility of undo.
|
||||
"""
|
||||
#print "Undo available:", bool(self.undoq)
|
||||
return len(self.undoq)
|
||||
if 0 <= self.undoindex < len(self.translist):
|
||||
return True
|
||||
return False
|
||||
@ -187,6 +195,8 @@ class DbUndo(object):
|
||||
"""
|
||||
Return boolean of whether or not there's a possibility of redo.
|
||||
"""
|
||||
#print "Redo available:", bool(self.redoq)
|
||||
return len(self.redoq)
|
||||
if 0 <= self.undoindex+1 < len(self.translist):
|
||||
return True
|
||||
return False
|
||||
@ -229,7 +239,11 @@ class DbUndo(object):
|
||||
Access the last committed transaction, and revert the data to the
|
||||
state before the transaction was committed.
|
||||
"""
|
||||
transaction = self.translist[self.undoindex]
|
||||
txn = self.undoq.pop()
|
||||
self.redoq.append(txn)
|
||||
#transaction = self.translist[self.undoindex]
|
||||
#assert transaction == txn
|
||||
transaction = txn
|
||||
db = self.db
|
||||
self.undoindex -= 1
|
||||
subitems = transaction.get_recnos(reverse=True)
|
||||
@ -262,12 +276,15 @@ class DbUndo(object):
|
||||
|
||||
def __redo(self, db=None, update_history=True):
|
||||
"""
|
||||
Accesse the last undone transaction, and revert the data to the state
|
||||
Access the last undone transaction, and revert the data to the state
|
||||
before the transaction was undone.
|
||||
"""
|
||||
|
||||
txn = self.redoq.pop()
|
||||
self.undoq.append(txn)
|
||||
self.undoindex += 1
|
||||
transaction = self.translist[self.undoindex]
|
||||
#transaction = self.translist[self.undoindex]
|
||||
#assert transaction == txn
|
||||
transaction = txn
|
||||
db = self.db
|
||||
subitems = transaction.get_recnos()
|
||||
|
||||
@ -287,8 +304,9 @@ class DbUndo(object):
|
||||
% transaction.get_description())
|
||||
|
||||
if db.redo_callback:
|
||||
if self.redo_available():
|
||||
new_transaction = self.translist[self.undoindex+1]
|
||||
if len(self.redoq) > 1:
|
||||
#new_transaction = self.translist[self.undoindex+1]
|
||||
new_transaction = self.redoq[-2]
|
||||
db.redo_callback(_("_Redo %s")
|
||||
% new_transaction.get_description())
|
||||
else:
|
||||
@ -333,6 +351,11 @@ class DbUndo(object):
|
||||
self.db._log_error()
|
||||
raise Errors.DbError(msg)
|
||||
|
||||
@property
|
||||
def undo_count(self):
|
||||
"""Number of undo requests in the queue"""
|
||||
return len(self.undoq)
|
||||
|
||||
class DbUndoList(DbUndo):
|
||||
"""
|
||||
Implementation of the gramps undo database using a Python list
|
||||
|
Loading…
Reference in New Issue
Block a user