Implement restructured database objects

svn: r13139
This commit is contained in:
Gerald Britton
2009-08-31 18:42:29 +00:00
parent bc83fa57a3
commit 1587cb8ad1
12 changed files with 494 additions and 1428 deletions

View File

@ -22,7 +22,7 @@
Provide the database state class Provide the database state class
""" """
from gen.db import GrampsDbBase from gen.db import GrampsDbRead
from gen.utils import Callback from gen.utils import Callback
import Config import Config
@ -32,18 +32,18 @@ class DbState(Callback):
""" """
__signals__ = { __signals__ = {
'database-changed' : (GrampsDbBase, ), 'database-changed' : (GrampsDbRead, ),
'active-changed' : (str, ), 'active-changed' : (str, ),
'no-database' : None, 'no-database' : None,
} }
def __init__(self): def __init__(self):
""" """
Initalize the state with an empty (and useless) GrampsDbBase. This is Initalize the state with an empty (and useless) GrampsDbRead. This is
just a place holder until a real DB is assigned. just a place holder until a real DB is assigned.
""" """
Callback.__init__(self) Callback.__init__(self)
self.db = GrampsDbBase() self.db = GrampsDbRead()
self.open = False self.open = False
self.active = None self.active = None
self.sighndl = None self.sighndl = None
@ -115,7 +115,7 @@ class DbState(Callback):
Closes the database without a new database Closes the database without a new database
""" """
self.db.close() self.db.close()
self.db = GrampsDbBase() self.db = GrampsDbRead()
self.db.db_is_open = False self.db.db_is_open = False
self.active = None self.active = None
self.open = False self.open = False

View File

@ -58,7 +58,7 @@ from gettext import gettext as _
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
from QuestionDialog import ErrorDialog from QuestionDialog import ErrorDialog
from gen.db.dbdir import FAMILY_TBL, PLACES_TBL, SOURCES_TBL, MEDIA_TBL, \ from gen.db.write import FAMILY_TBL, PLACES_TBL, SOURCES_TBL, MEDIA_TBL, \
EVENTS_TBL, PERSON_TBL, REPO_TBL, NOTE_TBL, META EVENTS_TBL, PERSON_TBL, REPO_TBL, NOTE_TBL, META
#------------------------------------------------------------------------ #------------------------------------------------------------------------

View File

@ -63,6 +63,7 @@ class UndoHistory(ManagedWindow.ManagedWindow):
self.title = _("Undo History") self.title = _("Undo History")
ManagedWindow.ManagedWindow.__init__(self,uistate,[],self.__class__) ManagedWindow.ManagedWindow.__init__(self,uistate,[],self.__class__)
self.db = dbstate.db self.db = dbstate.db
self.undodb = self.db.undodb
self.dbstate = dbstate self.dbstate = dbstate
window = gtk.Dialog("",uistate.window, window = gtk.Dialog("",uistate.window,
@ -114,21 +115,21 @@ class UndoHistory(ManagedWindow.ManagedWindow):
return return
path = self.model.get_path(node) path = self.model.get_path(node)
start = min(path[0],self.db.undoindex+1) start = min(path[0],self.undodb.undoindex+1)
end = max(path[0],self.db.undoindex+1) end = max(path[0],self.undodb.undoindex+1)
self._paint_rows(0,len(self.model)-1,False) self._paint_rows(0,len(self.model)-1,False)
self._paint_rows(start,end,True) self._paint_rows(start,end,True)
if path[0] < self.db.undoindex+1: if path[0] < self.undodb.undoindex+1:
self.redo_button.set_sensitive(False) self.redo_button.set_sensitive(False)
self.undo_button.set_sensitive(self.db.undo_available()) self.undo_button.set_sensitive(self.undodb.undo_available())
if path[0] > self.db.undoindex+1: if path[0] > self.undodb.undoindex+1:
self.undo_button.set_sensitive(False) self.undo_button.set_sensitive(False)
self.redo_button.set_sensitive(self.db.redo_available()) self.redo_button.set_sensitive(self.undodb.redo_available())
if path[0] == self.db.undoindex+1: if path[0] == self.undodb.undoindex+1:
self.undo_button.set_sensitive(self.db.undo_available()) self.undo_button.set_sensitive(self.undodb.undo_available())
self.redo_button.set_sensitive(self.db.redo_available()) self.redo_button.set_sensitive(self.undodb.redo_available())
def _paint_rows(self,start,end,selected=False): def _paint_rows(self,start,end,selected=False):
if selected: if selected:
@ -149,7 +150,7 @@ class UndoHistory(ManagedWindow.ManagedWindow):
if not node: if not node:
return return
path = self.model.get_path(node) path = self.model.get_path(node)
nsteps = path[0]-self.db.undoindex-1 nsteps = path[0]-self.undodb.undoindex-1
if nsteps == 0: if nsteps == 0:
self._move(-1) self._move(-1)
else: else:
@ -159,7 +160,7 @@ class UndoHistory(ManagedWindow.ManagedWindow):
if not node: if not node:
return return
path = self.model.get_path(node) path = self.model.get_path(node)
nsteps = path[0]-self.db.undoindex-1 nsteps = path[0]-self.undodb.undoindex-1
if nsteps == 0: if nsteps == 0:
self._move(1) self._move(1)
else: else:
@ -180,9 +181,8 @@ class UndoHistory(ManagedWindow.ManagedWindow):
self.window) self.window)
def clear(self): def clear(self):
self.db.undoindex = -1 self.undodb.clear()
self.db.translist = [None] * len(self.db.translist) self.undodb.abort_possible = False
self.db.abort_possible = False
self.update() self.update()
if self.db.undo_callback: if self.db.undo_callback:
self.db.undo_callback(None) self.db.undo_callback(None)
@ -203,30 +203,30 @@ class UndoHistory(ManagedWindow.ManagedWindow):
def _update_ui(self): def _update_ui(self):
self._paint_rows(0,len(self.model)-1,False) self._paint_rows(0,len(self.model)-1,False)
self.undo_button.set_sensitive(self.db.undo_available()) self.undo_button.set_sensitive(self.undodb.undo_available())
self.redo_button.set_sensitive(self.db.redo_available()) self.redo_button.set_sensitive(self.undodb.redo_available())
self.clear_button.set_sensitive( self.clear_button.set_sensitive(
self.db.undo_available() or self.db.redo_available() ) self.undodb.undo_available() or self.undodb.redo_available() )
def _build_model(self): def _build_model(self):
self.model.clear() self.model.clear()
fg = bg = None fg = bg = None
if self.db.undo_history_timestamp: if self.undodb.undo_history_timestamp:
if self.db.abort_possible: if self.db.abort_possible:
mod_text = _('Database opened') mod_text = _('Database opened')
else: else:
mod_text = _('History cleared') mod_text = _('History cleared')
time_text = time.ctime(self.db.undo_history_timestamp) time_text = time.ctime(self.undodb.undo_history_timestamp)
self.model.append(row=[time_text,mod_text,fg,bg]) self.model.append(row=[time_text,mod_text,fg,bg])
# Get the not-None portion of transaction list # Get the not-None portion of transaction list
translist = [item for item in self.db.translist if item] translist = [item for item in self.undodb.translist if item]
for transaction in translist: for transaction in translist:
time_text = time.ctime(transaction.timestamp) time_text = time.ctime(transaction.timestamp)
mod_text = transaction.get_description() mod_text = transaction.get_description()
self.model.append(row=[time_text,mod_text,fg,bg]) self.model.append(row=[time_text,mod_text,fg,bg])
path = (self.db.undoindex+1,) path = (self.undodb.undoindex+1,)
self.selection.select_path(path) self.selection.select_path(path)
def update(self): def update(self):

View File

@ -19,7 +19,9 @@
# #
from base import * from base import *
from cursor import *
from dbconst import * from dbconst import *
from dbdir import * from read import *
from cursor import *
from bsddbtxn import *
from write import *
from exceptions import * from exceptions import *

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,10 @@
# $Id$ # $Id$
"""
Declare constants used by database modules
"""
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# standard python modules # standard python modules
@ -31,6 +35,44 @@
# constants # constants
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
__all__ = (
('DBPAGE', 'DBMODE', 'DBCACHE', 'DBLOCKS', 'DBOBJECTS', 'DBUNDO',
'DBEXT', 'DBMODE_R', 'DBMODE_W', 'DBUNDOFN', 'DBLOCKFN',
'DBRECOVFN', 'DBLOGNAME', 'DBFLAGS_O', 'DBFLAGS_R', 'DBFLAGS_D',
) +
('PERSON_KEY', 'FAMILY_KEY', 'SOURCE_KEY', 'EVENT_KEY',
'MEDIA_KEY', 'PLACE_KEY', 'REPOSITORY_KEY', 'NOTE_KEY',
'REFERENCE_KEY', 'PERSON_COL_KEY', 'FAMILY_COL_KEY',
'CHILD_COL_KEY'
) +
('PERSON_COL_KEY', 'FAMILY_COL_KEY', 'CHILD_COL_KEY',
'PLACE_COL_KEY', 'SOURCE_COL_KEY', 'MEDIA_COL_KEY',
'EVENT_COL_KEY', 'REPOSITORY_COL_KEY', 'NOTE_COL_KEY'
) +
('TXNADD', 'TXNUPD', 'TXNDEL')
)
DBEXT = ".db" # File extension to be used for database files
DBUNDOFN = "undo.db" # File name of 'undo' database
DBLOCKFN = "lock" # File name of lock file
DBRECOVFN = "need_recover" # File name of recovery file
DBLOGNAME = ".GrampsDb" # Name of logger
DBMODE_R = "r" # Read-only access
DBMODE_W = "w" # Full Reaw/Write access
DBPAGE = 16384 # Size of the pages used to hold items in the database
DBMODE = 0666 # Unix mode for database creation
DBCACHE = 0x4000000 # Size of the shared memory buffer pool
DBLOCKS = 25000 # Maximum number of locks supported
DBOBJECTS = 25000 # Maximum number of simultaneously locked objects
DBUNDO = 1000 # Maximum size of undo buffer
from bsddb.db import DB_CREATE, DB_AUTO_COMMIT, DB_DUP, DB_DUPSORT, DB_RDONLY
DBFLAGS_O = DB_CREATE | DB_AUTO_COMMIT # Default flags for database open
DBFLAGS_R = DB_RDONLY # Flags to open a database read-only
DBFLAGS_D = DB_DUP | DB_DUPSORT # Default flags for duplicate keys
PERSON_KEY = 0 PERSON_KEY = 0
FAMILY_KEY = 1 FAMILY_KEY = 1
@ -51,3 +93,5 @@ REPOSITORY_COL_KEY = 'repository_columns'
EVENT_COL_KEY = 'event_columns' EVENT_COL_KEY = 'event_columns'
FAMILY_COL_KEY = 'family_columns' FAMILY_COL_KEY = 'family_columns'
NOTE_COL_KEY = 'note_columns' NOTE_COL_KEY = 'note_columns'
TXNADD, TXNUPD, TXNDEL = 0, 1, 2

View File

@ -1102,8 +1102,6 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
if not obj.handle: if not obj.handle:
obj.handle = self.create_id() obj.handle = self.create_id()
commit_func(obj, transaction) commit_func(obj, transaction)
if obj.__class__.__name__ == 'Person':
self.genderStats.count_person (obj)
return obj.handle return obj.handle
def add_person(self, person, transaction, set_gid=True): def add_person(self, person, transaction, set_gid=True):
@ -1113,9 +1111,11 @@ class GrampsDBDir(GrampsDbRead, Callback, UpdateCallback):
If not set_gid, then gramps_id is not set. If not set_gid, then gramps_id is not set.
""" """
return self.__add_object(person, transaction, handle = self.__add_object(person, transaction,
self.find_next_person_gramps_id if set_gid else None, self.find_next_person_gramps_id if set_gid else None,
self.commit_person) self.commit_person)
self.genderStats.count_person(person)
return handle
def add_family(self, family, transaction, set_gid=True): def add_family(self, family, transaction, set_gid=True):
""" """

View File

@ -644,7 +644,7 @@ class ViewManager(CLIManager):
""" """
import GrampsDbUtils import GrampsDbUtils
if self.dbstate.db.undoindex >= 0: if self.dbstate.db.has_changed:
self.uistate.set_busy_cursor(1) self.uistate.set_busy_cursor(1)
self.uistate.progress.show() self.uistate.progress.show()
self.uistate.push_message(self.dbstate, _("Autobackup...")) self.uistate.push_message(self.dbstate, _("Autobackup..."))

View File

@ -48,6 +48,7 @@ from GrampsDbUtils._GedcomStageOne import StageOne
from QuestionDialog import ErrorDialog, DBErrorDialog from QuestionDialog import ErrorDialog, DBErrorDialog
from gen.plug import PluginManager, ImportPlugin from gen.plug import PluginManager, ImportPlugin
from glade import Glade from glade import Glade
from libmixin import GrampsDbMixin
try: try:
import Config import Config
@ -65,6 +66,11 @@ def importData(database, filename, callback=None):
""" """
Try to handle ANSEL encoded files that are not really ANSEL encoded Try to handle ANSEL encoded files that are not really ANSEL encoded
""" """
if GrampsDbMixin not in database.__class__.__bases__:
database.__class__.__bases__ = (GrampsDbMixin,) + \
database.__class__.__bases__
try: try:
ifile = open(filename, "r") ifile = open(filename, "r")
except IOError: except IOError:

View File

@ -48,12 +48,11 @@ __LOG = logging.getLogger(".GrampsDb")
from gen.lib import (GenderStats, Source, Person, Family, Event, Place, from gen.lib import (GenderStats, Source, Person, Family, Event, Place,
MediaObject, Repository, Note, Attribute, AttributeType, MediaObject, Repository, Note, Attribute, AttributeType,
NoteType) NoteType)
from gen.db.base import (GrampsDbBase, KEY_TO_CLASS_MAP, CLASS_TO_KEY_MAP, from gen.db.write import (GrampsDBDir, KEY_TO_CLASS_MAP, CLASS_TO_KEY_MAP)
Transaction) from libgrdb import GrampsDbGrdb
from gen.db.txn import GrampsDbTxn as Transaction
from gen.db.cursor import GrampsCursor from gen.db.cursor import GrampsCursor
from gen.db.dbconst import (REFERENCE_KEY, PERSON_COL_KEY, EVENT_COL_KEY, from gen.db.dbconst import *
EVENT_KEY, FAMILY_KEY, SOURCE_KEY, PLACE_KEY,
MEDIA_KEY, REPOSITORY_KEY, PERSON_KEY, NOTE_KEY)
from gen.db.exceptions import FileVersionError from gen.db.exceptions import FileVersionError
from gen.utils import db_copy from gen.utils import db_copy
import const import const
@ -136,7 +135,7 @@ class GrampsBSDDBDupCursor(GrampsBSDDBAssocCursor):
# GrampsBSDDB # GrampsBSDDB
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
class GrampsBSDDB(GrampsDbBase, UpdateCallback): class GrampsBSDDB(GrampsDbGrdb, UpdateCallback):
""" GRAMPS database object for Berkeley DB. """ GRAMPS database object for Berkeley DB.
This is replaced for internal use by gen/db/dbdir.py This is replaced for internal use by gen/db/dbdir.py
However, this class is still used for import of the 2.2.x However, this class is still used for import of the 2.2.x
@ -146,7 +145,7 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
def __init__(self, use_txn = True): def __init__(self, use_txn = True):
"""creates a new GrampsDB""" """creates a new GrampsDB"""
GrampsDbBase.__init__(self) GrampsDbGrdb.__init__(self)
#UpdateCallback.__init__(self) #UpdateCallback.__init__(self)
self.txn = None self.txn = None
self.secondary_connected = False self.secondary_connected = False
@ -460,7 +459,6 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
# If secondary indices change, then they should removed # If secondary indices change, then they should removed
# or rebuilt by upgrade as well. In any case, the # or rebuilt by upgrade as well. In any case, the
# self.secondary_connected flag should be set accordingly. # self.secondary_connected flag should be set accordingly.
if self.need_upgrade(): if self.need_upgrade():
self.gramps_upgrade(callback) self.gramps_upgrade(callback)
@ -471,10 +469,10 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
self.db_is_open = True self.db_is_open = True
# Re-set the undo history to a fresh session start # Re-set the undo history to a fresh session start
self.undoindex = -1 #self.undoindex = -1
self.translist = [None] * len(self.translist) #self.translist = [None] * len(self.translist)
self.abort_possible = True self.abort_possible = True
self.undo_history_timestamp = time.time() #self.undo_history_timestamp = time.time()
return 1 return 1
@ -772,7 +770,6 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
while (ret is not None): while (ret is not None):
(key, data) = ret (key, data) = ret
print key, data
# data values are of the form: # data values are of the form:
# ((primary_object_class_name, primary_object_handle), # ((primary_object_class_name, primary_object_handle),
@ -1461,8 +1458,8 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
# Aborting the session completely will become impossible. # Aborting the session completely will become impossible.
self.abort_possible = False self.abort_possible = False
# Undo is also impossible after batch transaction # Undo is also impossible after batch transaction
self.undoindex = -1 #self.undoindex = -1
self.translist = [None] * len(self.translist) #self.translist = [None] * len(self.translist)
transaction = BdbTransaction(msg, self.undodb, batch, no_magic) transaction = BdbTransaction(msg, self.undodb, batch, no_magic)
if transaction.batch: if transaction.batch:
if self.UseTXN: if self.UseTXN:
@ -2665,9 +2662,9 @@ class GrampsBSDDB(GrampsDbBase, UpdateCallback):
class BdbTransaction(Transaction): class BdbTransaction(Transaction):
def __init__(self, msg, db, batch=False, no_magic=False): def __init__(self, msg, db, batch=False, no_magic=False):
Transaction.__init__(self, msg, db, batch, no_magic) Transaction.__init__(self, msg, db)
self.reference_del = [] self.batch = batch
self.reference_add = [] self.no_magic = no_magic
def convert_name_10(name): def convert_name_10(name):
# Names lost the "sname" attribute # Names lost the "sname" attribute
@ -2697,7 +2694,6 @@ def convert_location_11(loc):
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
def importData(database, filename, callback=None, cl=0): def importData(database, filename, callback=None, cl=0):
other_database = GrampsBSDDB() other_database = GrampsBSDDB()
# Since we don't want to modify the file being imported, # Since we don't want to modify the file being imported,

View File

@ -49,6 +49,7 @@ from BasicUtils import UpdateCallback
import const import const
from gen.plug import PluginManager, ImportPlugin from gen.plug import PluginManager, ImportPlugin
import libgrampsxml import libgrampsxml
from libmixin import GrampsDbMixin
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -83,6 +84,10 @@ EVENT_PERSON_STR = _("%(event_name)s of %(person)s")
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
def importData(database, filename, callback=None, cl=0): def importData(database, filename, callback=None, cl=0):
if GrampsDbMixin not in database.__class__.__bases__:
database.__class__.__bases__ = (GrampsDbMixin,) + \
database.__class__.__bases__
filename = os.path.normpath(filename) filename = os.path.normpath(filename)
basefile = os.path.dirname(filename) basefile = os.path.dirname(filename)
database.smap = {} database.smap = {}

View File

@ -114,8 +114,8 @@ def _table_low_level(db,table):
return True return True
# import gen.db # import gen.db
from gen.db import GrampsDBDirDupCursor from gen.db import GrampsDBDirAssocCursor
table_cursor = GrampsDBDirDupCursor(table) table_cursor = GrampsDBDirAssocCursor(table)
for handle in dup_handles: for handle in dup_handles:
print " Duplicates found for handle: %s" % handle print " Duplicates found for handle: %s" % handle
try: try: