From 86cffe6504859927bd4f8f8ae21c5deff0070ab0 Mon Sep 17 00:00:00 2001 From: Alex Roitman Date: Sun, 7 May 2006 05:22:44 +0000 Subject: [PATCH] 2006-05-06 Alex Roitman * 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 --- gramps2/ChangeLog | 11 ++++ gramps2/src/GrampsDb/_GrampsBSDDB.py | 20 +++---- gramps2/src/GrampsDb/_GrampsDbBase.py | 76 ++++++++++++++++-------- gramps2/src/GrampsDb/_GrampsGEDDB.py | 5 +- gramps2/src/GrampsDb/_GrampsInMemDB.py | 21 ++++--- gramps2/src/GrampsDb/_GrampsXMLDB.py | 4 +- gramps2/src/UndoHistory.py | 81 ++++++++++++++++++-------- gramps2/src/ViewManager.py | 2 + 8 files changed, 144 insertions(+), 76 deletions(-) diff --git a/gramps2/ChangeLog b/gramps2/ChangeLog index 9a759b6be..aa2e0f1ef 100644 --- a/gramps2/ChangeLog +++ b/gramps2/ChangeLog @@ -1,3 +1,14 @@ +2006-05-06 Alex Roitman + * 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 * src/PluginUtils/_ReportUtils.py: fix set_nick_name * src/RelLib/_MediaRef.py: handle initialization of Ref object diff --git a/gramps2/src/GrampsDb/_GrampsBSDDB.py b/gramps2/src/GrampsDb/_GrampsBSDDB.py index 764681d4b..6e36a7697 100644 --- a/gramps2/src/GrampsDb/_GrampsBSDDB.py +++ b/gramps2/src/GrampsDb/_GrampsBSDDB.py @@ -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 diff --git a/gramps2/src/GrampsDb/_GrampsDbBase.py b/gramps2/src/GrampsDb/_GrampsDbBase.py index be464b2c1..adfe1675d 100644 --- a/gramps2/src/GrampsDb/_GrampsDbBase.py +++ b/gramps2/src/GrampsDb/_GrampsDbBase.py @@ -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() diff --git a/gramps2/src/GrampsDb/_GrampsGEDDB.py b/gramps2/src/GrampsDb/_GrampsGEDDB.py index 0f2189417..b00d72c78 100644 --- a/gramps2/src/GrampsDb/_GrampsGEDDB.py +++ b/gramps2/src/GrampsDb/_GrampsGEDDB.py @@ -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 - diff --git a/gramps2/src/GrampsDb/_GrampsInMemDB.py b/gramps2/src/GrampsDb/_GrampsInMemDB.py index ceee636ed..53fa8e2fe 100644 --- a/gramps2/src/GrampsDb/_GrampsInMemDB.py +++ b/gramps2/src/GrampsDb/_GrampsInMemDB.py @@ -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): diff --git a/gramps2/src/GrampsDb/_GrampsXMLDB.py b/gramps2/src/GrampsDb/_GrampsXMLDB.py index d32491e40..c42b90465 100644 --- a/gramps2/src/GrampsDb/_GrampsXMLDB.py +++ b/gramps2/src/GrampsDb/_GrampsXMLDB.py @@ -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 diff --git a/gramps2/src/UndoHistory.py b/gramps2/src/UndoHistory.py index cc1b63e61..13dc6894d 100644 --- a/gramps2/src/UndoHistory.py +++ b/gramps2/src/UndoHistory.py @@ -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() diff --git a/gramps2/src/ViewManager.py b/gramps2/src/ViewManager.py index 1e14b4fd6..5b14f545a 100644 --- a/gramps2/src/ViewManager.py +++ b/gramps2/src/ViewManager.py @@ -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)