* src/GrampsDb/_GrampsBSDDB.py (load_from): Add method.
* src/GrampsDb/_GrampsXMLDB.py (load_from): Add method. * src/GrampsDb/_GrampsGEDDB.py (load_from): Add method. * src/GrampsDb/_GrampsDbBase.py (load_from): Add method. * src/GrampsDb/_WriteGrdb.py: Use db_copy. * src/GrampsDb/_DbUtils.py (db_copy): Add function. * src/ViewManager.py: Save as support. * src/DataViews/_MapView.py (enable_debug): Set to False to be able to see the output besides MapView. svn: r6604
This commit is contained in:
parent
626185cff8
commit
40f355e17d
10
ChangeLog
10
ChangeLog
@ -8,6 +8,16 @@
|
||||
the session
|
||||
|
||||
2006-05-09 Alex Roitman <shura@gramps-project.org>
|
||||
* src/GrampsDb/_GrampsBSDDB.py (load_from): Add method.
|
||||
* src/GrampsDb/_GrampsXMLDB.py (load_from): Add method.
|
||||
* src/GrampsDb/_GrampsGEDDB.py (load_from): Add method.
|
||||
* src/GrampsDb/_GrampsDbBase.py (load_from): Add method.
|
||||
* src/GrampsDb/_WriteGrdb.py: Use db_copy.
|
||||
* src/GrampsDb/_DbUtils.py (db_copy): Add function.
|
||||
* src/ViewManager.py: Save as support.
|
||||
* src/DataViews/_MapView.py (enable_debug): Set to False to be
|
||||
able to see the output besides MapView.
|
||||
|
||||
* src/plugins/FamilyGroup.py: Use triple quotes.
|
||||
* src/Exporter.py (Exporter.native_export): Use callback.
|
||||
* src/Utils.py (get_new_filename): Add path separator.
|
||||
|
@ -78,7 +78,7 @@ glob_loc_data = [ # (Name, longitude, latitude)
|
||||
("Mannheim-Neckarau",8.48,49.45),
|
||||
("Gorxheimertal",8.73,49.53)]
|
||||
|
||||
enable_debug = True
|
||||
enable_debug = False
|
||||
|
||||
|
||||
# Draws a map image and tries to allocate space in the correct aspect ratio
|
||||
|
@ -143,3 +143,95 @@ def add_child_to_family(db, family, child,
|
||||
|
||||
if need_commit:
|
||||
db.transaction_commit(trans, _('Add child to family') )
|
||||
|
||||
|
||||
def db_copy(from_db,to_db,callback):
|
||||
if '__call__' in dir(callback): # callback is really callable
|
||||
update = update_real
|
||||
|
||||
# Prepare length for the callback
|
||||
person_len = from_db.get_number_of_people()
|
||||
family_len = from_db.get_number_of_families()
|
||||
event_len = from_db.get_number_of_events()
|
||||
source_len = from_db.get_number_of_sources()
|
||||
place_len = from_db.get_number_of_places()
|
||||
repo_len = from_db.get_number_of_repositories()
|
||||
obj_len = from_db.get_number_of_media_objects()
|
||||
|
||||
total = person_len + family_len + event_len + place_len + \
|
||||
source_len + obj_len + repo_len
|
||||
else:
|
||||
update = update_empty
|
||||
total = 0
|
||||
|
||||
primary_tables = {
|
||||
'Person': {'cursor_func': from_db.get_person_cursor,
|
||||
'table': to_db.person_map },
|
||||
'Family': {'cursor_func': from_db.get_family_cursor,
|
||||
'table': to_db.family_map },
|
||||
'Event': {'cursor_func': from_db.get_event_cursor,
|
||||
'table': to_db.event_map },
|
||||
'Place': {'cursor_func': from_db.get_place_cursor,
|
||||
'table': to_db.place_map },
|
||||
'Source': {'cursor_func': from_db.get_source_cursor,
|
||||
'table': to_db.source_map },
|
||||
'MediaObject': {'cursor_func': from_db.get_media_cursor,
|
||||
'table': to_db.media_map },
|
||||
'Repository': {'cursor_func': from_db.get_repository_cursor,
|
||||
'table': to_db.repository_map },
|
||||
}
|
||||
|
||||
|
||||
if to_db.__class__.__name__ == 'GrampsBSDDB':
|
||||
if to_db.UseTXN:
|
||||
add_data = add_data_txn
|
||||
else:
|
||||
add_data = add_data_notxn
|
||||
else:
|
||||
add_data = add_data_dict
|
||||
|
||||
oldval = 0
|
||||
count = 0
|
||||
|
||||
for table_name in primary_tables.keys():
|
||||
cursor_func = primary_tables[table_name]['cursor_func']
|
||||
table = primary_tables[table_name]['table']
|
||||
|
||||
cursor = cursor_func()
|
||||
item = cursor.first()
|
||||
while item:
|
||||
(handle,data) = item
|
||||
add_data(to_db,table,handle,data)
|
||||
item = cursor.next()
|
||||
count,oldval = update(callback,count,oldval,total)
|
||||
update(callback,count,oldval,total)
|
||||
cursor.close()
|
||||
|
||||
# The metadata is always transactionless,
|
||||
# and the table is small, so using key iteration is OK here.
|
||||
for handle in from_db.metadata.keys():
|
||||
data = from_db.metadata.get(handle)
|
||||
to_db.metadata[handle] = data
|
||||
|
||||
|
||||
def add_data_txn(db,table,handle,data):
|
||||
the_txn = db.env.txn_begin()
|
||||
table.put(handle,data,txn=the_txn)
|
||||
the_txn.commit()
|
||||
|
||||
def add_data_notxn(db,table,handle,data):
|
||||
table.put(handle,data)
|
||||
|
||||
def add_data_dict(db,table,handle,data):
|
||||
table[handle] = data
|
||||
|
||||
def update_empty(callback,count,oldval,total):
|
||||
pass
|
||||
|
||||
def update_real(callback,count,oldval,total):
|
||||
count += 1
|
||||
newval = int(100.0*count/total)
|
||||
if newval != oldval:
|
||||
callback(newval)
|
||||
oldval = newval
|
||||
return count,oldval
|
||||
|
@ -53,6 +53,7 @@ except NameError:
|
||||
#-------------------------------------------------------------------------
|
||||
from RelLib import *
|
||||
from _GrampsDbBase import *
|
||||
from _DbUtils import db_copy
|
||||
import const
|
||||
|
||||
_MINVERSION = 5
|
||||
@ -316,15 +317,14 @@ class GrampsBSDDB(GrampsDbBase):
|
||||
else:
|
||||
env_flags = db.DB_CREATE|db.DB_PRIVATE|\
|
||||
db.DB_INIT_MPOOL|db.DB_INIT_LOG
|
||||
env_name = self.brief_name
|
||||
env_name = os.path.expanduser('~')
|
||||
|
||||
self.env.open(env_name,env_flags)
|
||||
if self.UseTXN:
|
||||
self.env.txn_checkpoint()
|
||||
|
||||
callback(25)
|
||||
|
||||
self.metadata =self.open_table(self.full_name,"meta",no_txn=True)
|
||||
self.metadata = self.open_table(self.full_name,"meta",no_txn=True)
|
||||
|
||||
self.family_map = self.open_table(self.full_name, "family")
|
||||
self.place_map = self.open_table(self.full_name, "places")
|
||||
@ -386,6 +386,11 @@ class GrampsBSDDB(GrampsDbBase):
|
||||
|
||||
return 1
|
||||
|
||||
def load_from(self, other_database, filename, callback):
|
||||
self.load(filename,callback)
|
||||
db_copy(other_database,self,callback)
|
||||
return 1
|
||||
|
||||
def connect_secondary(self):
|
||||
"""
|
||||
This method connects or creates secondary index tables.
|
||||
|
@ -356,6 +356,14 @@ class GrampsDbBase(GrampsDBCallback):
|
||||
"""
|
||||
assert False, "Needs to be overridden in the derived class"
|
||||
|
||||
def load_from(self, other_database, filename, callback):
|
||||
"""
|
||||
Loads data from the other database into itself.
|
||||
The filename is the name of the file for the newly created database.
|
||||
The method needs to be overridden in the derived class.
|
||||
"""
|
||||
assert False, "Needs to be overridden in the derived class"
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Closes the specified database. The method needs to be overridden
|
||||
|
@ -30,6 +30,7 @@ from _GrampsInMemDB import *
|
||||
|
||||
import _ReadGedcom as ReadGedcom
|
||||
import _WriteGedcom as WriteGedcom
|
||||
from _DbUtils import db_copy
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -56,6 +57,17 @@ class GrampsGEDDB(GrampsInMemDB):
|
||||
self.db_is_open = True
|
||||
return 1
|
||||
|
||||
def load_from(self, other_database, filename, callback):
|
||||
db_copy(other_database,self,callback)
|
||||
GrampsInMemDB.load(self,filename,callback)
|
||||
self.bookmarks = self.metadata.get('bookmarks')
|
||||
if self.bookmarks == None:
|
||||
self.bookmarks = []
|
||||
self.db_is_open = True
|
||||
writer = WriteGedcom.GedcomWriter(self,self.get_default_person())
|
||||
writer.export_data(self.full_name)
|
||||
return 1
|
||||
|
||||
def close(self):
|
||||
if not self.db_is_open:
|
||||
return
|
||||
|
@ -30,6 +30,7 @@ from _GrampsInMemDB import *
|
||||
|
||||
import _ReadXML as ReadXML
|
||||
import _WriteXML as WriteXML
|
||||
from _DbUtils import db_copy
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -58,6 +59,17 @@ class GrampsXMLDB(GrampsInMemDB):
|
||||
self.db_is_open = True
|
||||
return 1
|
||||
|
||||
def load_from(self, other_database, filename, callback):
|
||||
self.id_trans = {}
|
||||
db_copy(other_database,self,callback)
|
||||
GrampsInMemDB.load(self,filename,callback)
|
||||
self.bookmarks = self.metadata.get('bookmarks')
|
||||
if self.bookmarks == None:
|
||||
self.bookmarks = []
|
||||
self.db_is_open = True
|
||||
WriteXML.quick_write(self,self.full_name)
|
||||
return 1
|
||||
|
||||
def close(self):
|
||||
if not self.db_is_open:
|
||||
return
|
||||
|
@ -37,6 +37,7 @@ from gettext import gettext as _
|
||||
#-------------------------------------------------------------------------
|
||||
from _GrampsBSDDB import GrampsBSDDB
|
||||
from QuestionDialog import ErrorDialog
|
||||
from _DbUtils import db_copy
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -44,25 +45,7 @@ from QuestionDialog import ErrorDialog
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def exportData(database, filename, person=None, callback=None, cl=False):
|
||||
|
||||
if '__call__' in dir(callback): # callback is really callable
|
||||
update = update_real
|
||||
|
||||
# Prepare length for the callback
|
||||
person_len = database.get_number_of_people()
|
||||
family_len = database.get_number_of_families()
|
||||
event_len = database.get_number_of_events()
|
||||
source_len = database.get_number_of_sources()
|
||||
place_len = database.get_number_of_places()
|
||||
repo_len = database.get_number_of_repositories()
|
||||
obj_len = database.get_number_of_media_objects()
|
||||
|
||||
total = person_len + family_len + event_len + place_len + \
|
||||
source_len + obj_len + repo_len
|
||||
else:
|
||||
update = update_empty
|
||||
total = 0
|
||||
|
||||
|
||||
filename = os.path.normpath(filename)
|
||||
new_database = GrampsBSDDB()
|
||||
try:
|
||||
@ -75,69 +58,6 @@ def exportData(database, filename, person=None, callback=None, cl=False):
|
||||
return
|
||||
|
||||
# copy all data from new_database to database
|
||||
|
||||
# Need different adders depending on whether the new db is transactional
|
||||
if new_database.UseTXN:
|
||||
add_data = add_data_txn
|
||||
else:
|
||||
add_data = add_data_notxn
|
||||
|
||||
primary_tables = {
|
||||
'Person': {'cursor_func': database.get_person_cursor,
|
||||
'new_table': new_database.person_map },
|
||||
'Family': {'cursor_func': database.get_family_cursor,
|
||||
'new_table': new_database.family_map },
|
||||
'Event': {'cursor_func': database.get_event_cursor,
|
||||
'new_table': new_database.event_map },
|
||||
'Place': {'cursor_func': database.get_place_cursor,
|
||||
'new_table': new_database.place_map },
|
||||
'Source': {'cursor_func': database.get_source_cursor,
|
||||
'new_table': new_database.source_map },
|
||||
'MediaObject': {'cursor_func': database.get_media_cursor,
|
||||
'new_table': new_database.media_map },
|
||||
'Repository': {'cursor_func': database.get_repository_cursor,
|
||||
'new_table': new_database.repository_map },
|
||||
}
|
||||
|
||||
count = 0
|
||||
oldval = 0
|
||||
|
||||
for table_name in primary_tables.keys():
|
||||
cursor_func = primary_tables[table_name]['cursor_func']
|
||||
new_table = primary_tables[table_name]['new_table']
|
||||
|
||||
cursor = cursor_func()
|
||||
item = cursor.first()
|
||||
while item:
|
||||
(handle,data) = item
|
||||
add_data(new_database,new_table,handle,data)
|
||||
item = cursor.next()
|
||||
count,oldval = update(callback,count,oldval,total)
|
||||
cursor.close()
|
||||
|
||||
# The metadata is always transactionless,
|
||||
# and the table is small, so using key iteration is OK here.
|
||||
for handle in database.metadata.keys():
|
||||
new_database.metadata.put(handle,database.metadata.get(handle))
|
||||
db_copy(database,new_database,callback)
|
||||
|
||||
new_database.close()
|
||||
|
||||
|
||||
def add_data_txn(db,table,handle,data):
|
||||
the_txn = db.env.txn_begin()
|
||||
table.put(handle,data,txn=the_txn)
|
||||
the_txn.commit()
|
||||
|
||||
def add_data_notxn(db,table,handle,data):
|
||||
table.put(handle,data)
|
||||
|
||||
def update_empty(callback,count,oldval,total):
|
||||
pass
|
||||
|
||||
def update_real(callback,count,oldval,total):
|
||||
count += 1
|
||||
newval = int(100.0*count/total)
|
||||
if newval != oldval:
|
||||
callback(newval)
|
||||
oldval = newval
|
||||
return count,oldval
|
||||
|
@ -329,7 +329,8 @@ class ViewManager:
|
||||
]
|
||||
|
||||
self._action_action_list = [
|
||||
('SaveAs', gtk.STOCK_SAVE_AS, _('_Save As')),
|
||||
('SaveAs', gtk.STOCK_SAVE_AS, _('_Save As'),"<control><shift>s",
|
||||
None, self.save_as_activate),
|
||||
('Export', gtk.STOCK_SAVE_AS, _('_Export'), "<control>e", None,
|
||||
self.export_data),
|
||||
('Abandon', gtk.STOCK_REVERT_TO_SAVED,
|
||||
@ -755,6 +756,79 @@ class ViewManager:
|
||||
choose.destroy()
|
||||
return False
|
||||
|
||||
def save_as_activate(self,obj):
|
||||
choose = gtk.FileChooserDialog(
|
||||
_('GRAMPS: Create GRAMPS database'),
|
||||
self.uistate.window,
|
||||
gtk.FILE_CHOOSER_ACTION_SAVE,
|
||||
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
|
||||
|
||||
# Always add automatic (macth all files) filter
|
||||
add_all_files_filter(choose)
|
||||
add_gramps_files_filter(choose)
|
||||
add_grdb_filter(choose)
|
||||
add_xml_filter(choose)
|
||||
add_gedcom_filter(choose)
|
||||
|
||||
format_list = [const.app_gramps,const.app_gramps_xml,const.app_gedcom]
|
||||
(box, type_selector) = format_maker(format_list)
|
||||
choose.set_extra_widget(box)
|
||||
|
||||
# Suggested folder: try last open file, import, then last export,
|
||||
# then home.
|
||||
default_dir = os.path.split(Config.get(Config.RECENT_FILE))[0] \
|
||||
+ os.path.sep
|
||||
if len(default_dir)<=1:
|
||||
default_dir = Config.get(Config.RECENT_IMPORT_DIR)
|
||||
if len(default_dir)<=1:
|
||||
default_dir = Config.get(Config.RECENT_EXPORT_DIR)
|
||||
if len(default_dir)<=1:
|
||||
default_dir = '~/'
|
||||
|
||||
new_filename = Utils.get_new_filename('grdb', default_dir)
|
||||
|
||||
choose.set_current_folder(default_dir)
|
||||
choose.set_current_name(os.path.split(new_filename)[1])
|
||||
|
||||
response = choose.run()
|
||||
if response == gtk.RESPONSE_OK:
|
||||
filename = choose.get_filename()
|
||||
if filename == None:
|
||||
choose.destroy()
|
||||
return False
|
||||
|
||||
filetype = type_selector.get_value()
|
||||
if filetype == 'auto':
|
||||
try:
|
||||
the_file = open(filename,'wb')
|
||||
the_file.close()
|
||||
filetype = Mime.get_type(filename)
|
||||
os.remove(filename)
|
||||
except RuntimeError, msg:
|
||||
QuestionDialog.ErrorDialog(
|
||||
_("Could not open file: %s") % filename,
|
||||
str(msg))
|
||||
return False
|
||||
# First we try our best formats
|
||||
if filetype not in (const.app_gramps,
|
||||
const.app_gramps_xml,
|
||||
const.app_gedcom):
|
||||
QuestionDialog.ErrorDialog(
|
||||
_("Could not open file: %s") % filename,
|
||||
_("Unknown type: %s") % filetype
|
||||
)
|
||||
return False
|
||||
choose.destroy()
|
||||
try:
|
||||
return self.open_saved_as(filename,filetype)
|
||||
except:
|
||||
log.error("Failed to save as", exc_info=True)
|
||||
return False
|
||||
else:
|
||||
choose.destroy()
|
||||
return False
|
||||
|
||||
def new_activate(self, obj):
|
||||
|
||||
choose = gtk.FileChooserDialog(
|
||||
@ -1159,6 +1233,66 @@ class ViewManager:
|
||||
self.progress.hide()
|
||||
self.window.window.set_cursor(None)
|
||||
|
||||
def open_saved_as(self, filename, filetype):
|
||||
(the_path, the_file) = os.path.split(filename)
|
||||
Config.set(Config.RECENT_IMPORT_DIR,the_path)
|
||||
|
||||
dbclass = GrampsDb.gramps_db_factory(filetype)
|
||||
success = self.do_save_as(filename,dbclass)
|
||||
self.state.signal_change()
|
||||
self.change_page(None, None)
|
||||
|
||||
if success:
|
||||
# Add the file to the recent items
|
||||
RecentFiles.recent_files(filename, filetype)
|
||||
self.recent_manager.build()
|
||||
self.actiongroup.set_visible(True)
|
||||
self.uistate.clear_history()
|
||||
return success
|
||||
|
||||
def do_save_as(self,filename,dbclass):
|
||||
# FIXME: error checking on filename here
|
||||
self.state.emit('database-changed', (GrampsDb.GrampsDbBase(), ))
|
||||
try:
|
||||
if self._do_copy(filename,dbclass):
|
||||
if filename[-1] == '/':
|
||||
filename = filename[:-1]
|
||||
name = os.path.basename(filename)
|
||||
msg = "%s - GRAMPS" % name
|
||||
self.uistate.window.set_title(msg)
|
||||
else:
|
||||
Config.set(Config.RECENT_FILE,"")
|
||||
QuestionDialog.ErrorDialog(
|
||||
_('Cannot save a copy of the database'),
|
||||
_('The database copy could not be saved.'))
|
||||
return False
|
||||
except (IOError,OSError), msg:
|
||||
QuestionDialog.ErrorDialog(_('Cannot save database'), str(msg))
|
||||
return False
|
||||
except (db.DBAccessError, db.DBError), msg:
|
||||
QuestionDialog.ErrorDialog(
|
||||
_('Cannot save database'),
|
||||
_('%s could not be saved.' % filename) + '\n' + msg[1])
|
||||
return False
|
||||
except Exception:
|
||||
log.error("Failed to open database.", exc_info=True)
|
||||
return False
|
||||
self.file_loaded = True
|
||||
self.actiongroup.set_visible(True)
|
||||
return True
|
||||
|
||||
def _do_copy(self,filename,dbclass):
|
||||
self.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
||||
self.progress.show()
|
||||
new_database = dbclass()
|
||||
if not new_database.load_from(self.state.db,filename,
|
||||
self.uistate.pulse_progressbar):
|
||||
return False
|
||||
self.progress.hide()
|
||||
self.state.db.close()
|
||||
self.state.change_database(new_database)
|
||||
return self.post_load(filename,self.uistate.pulse_progressbar)
|
||||
|
||||
def build_tools_menu(self):
|
||||
self.toolactions = gtk.ActionGroup('ToolWindow')
|
||||
(ui, actions) = self.build_plugin_menu('ToolsMenu',
|
||||
|
Loading…
Reference in New Issue
Block a user