Updates to undo/redo logic -- part 1
svn: r15277
This commit is contained in:
		| @@ -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: | ||||
| @@ -331,7 +349,12 @@ class DbUndo(object): | ||||
|  | ||||
|         except DBERRS, msg: | ||||
|             self.db._log_error() | ||||
|             raise Errors.DbError(msg)         | ||||
|             raise Errors.DbError(msg) | ||||
|  | ||||
|     @property | ||||
|     def undo_count(self): | ||||
|         """Number of undo requests in the queue""" | ||||
|         return len(self.undoq) | ||||
|  | ||||
| class DbUndoList(DbUndo): | ||||
|     """ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user