Merge branch 'master' of https://github.com/gramps-project/gramps
This commit is contained in:
commit
7efcd2edf6
@ -71,6 +71,7 @@ from .dialog import (DBErrorDialog, ErrorDialog, QuestionDialog2,
|
||||
WarningDialog)
|
||||
from .user import User
|
||||
from gramps.gen.errors import DbError
|
||||
from .managedwindow import ManagedWindow
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -108,18 +109,6 @@ class DbLoader(CLIDbLoader):
|
||||
parent=self.uistate.window)
|
||||
_LOG.error(str(msg) +"\n" + exc)
|
||||
|
||||
def _begin_progress(self):
|
||||
self.uistate.set_busy_cursor(True)
|
||||
self.uistate.progress.show()
|
||||
self.uistate.pulse_progressbar(0)
|
||||
|
||||
def _pulse_progress(self, value):
|
||||
self.uistate.pulse_progressbar(value)
|
||||
|
||||
def _end_progress(self):
|
||||
self.uistate.set_busy_cursor(False)
|
||||
self.uistate.progress.hide()
|
||||
|
||||
def import_file(self):
|
||||
self.import_info = None
|
||||
# First thing first: import is a batch transaction
|
||||
@ -138,142 +127,7 @@ class DbLoader(CLIDbLoader):
|
||||
if not warn_dialog.run():
|
||||
return False
|
||||
|
||||
pmgr = GuiPluginManager.get_instance()
|
||||
|
||||
import_dialog = Gtk.FileChooserDialog(_('Gramps: Import Family Tree'),
|
||||
self.uistate.window,
|
||||
Gtk.FileChooserAction.OPEN,
|
||||
(_('_Cancel'),
|
||||
Gtk.ResponseType.CANCEL,
|
||||
_('Import'),
|
||||
Gtk.ResponseType.OK))
|
||||
import_dialog.set_local_only(False)
|
||||
|
||||
# Always add automatic (match all files) filter
|
||||
add_all_files_filter(import_dialog) # *
|
||||
|
||||
# Add more file type selections for available importers
|
||||
for plugin in pmgr.get_import_plugins():
|
||||
file_filter = Gtk.FileFilter()
|
||||
name = "%s (.%s)" % (plugin.get_name(), plugin.get_extension())
|
||||
file_filter.set_name(name)
|
||||
file_filter.add_pattern("*.%s" % plugin.get_extension())
|
||||
file_filter.add_pattern(plugin.get_extension().capitalize())
|
||||
import_dialog.add_filter(file_filter)
|
||||
|
||||
(box, type_selector) = format_maker()
|
||||
import_dialog.set_extra_widget(box)
|
||||
|
||||
# Suggested folder: try last open file, import, then last export,
|
||||
# then home.
|
||||
default_dir = config.get('paths.recent-import-dir')
|
||||
if len(default_dir)<=1:
|
||||
default_dir = get_default_dir()
|
||||
|
||||
import_dialog.set_current_folder(default_dir)
|
||||
while True:
|
||||
response = import_dialog.run()
|
||||
if response in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
|
||||
break
|
||||
elif response == Gtk.ResponseType.OK:
|
||||
filename = import_dialog.get_filename()
|
||||
if self.check_errors(filename):
|
||||
# displays errors if any
|
||||
continue
|
||||
|
||||
(the_path, the_file) = os.path.split(filename)
|
||||
config.set('paths.recent-import-dir', the_path)
|
||||
|
||||
extension = type_selector.get_value()
|
||||
if extension == 'auto':
|
||||
# Guess the file format based on the file extension.
|
||||
# This will get the lower case extension without a period,
|
||||
# or an empty string.
|
||||
extension = os.path.splitext(filename)[-1][1:].lower()
|
||||
|
||||
for plugin in pmgr.get_import_plugins():
|
||||
if extension == plugin.get_extension():
|
||||
self.do_import(import_dialog,
|
||||
plugin.get_import_function(),
|
||||
filename)
|
||||
return True
|
||||
|
||||
# Finally, we give up and declare this an unknown format
|
||||
ErrorDialog(
|
||||
_("Could not open file: %s") % filename,
|
||||
_('File type "%s" is unknown to Gramps.\n\n'
|
||||
'Valid types are: Gramps database, Gramps XML, '
|
||||
'Gramps package, GEDCOM, and others.') % extension,
|
||||
parent=self.uistate.window)
|
||||
|
||||
import_dialog.destroy()
|
||||
return False
|
||||
|
||||
def check_errors(self, filename):
|
||||
"""
|
||||
Run common error checks and return True if any found.
|
||||
|
||||
In this process, a warning dialog can pop up.
|
||||
|
||||
"""
|
||||
if not isinstance(filename, str):
|
||||
return True
|
||||
|
||||
filename = os.path.normpath(os.path.abspath(filename))
|
||||
|
||||
if len(filename) == 0:
|
||||
return True
|
||||
elif os.path.isdir(filename):
|
||||
ErrorDialog(
|
||||
_('Cannot open file'),
|
||||
_('The selected file is a directory, not a file.\n'),
|
||||
parent=self.uistate.window)
|
||||
return True
|
||||
elif os.path.exists(filename):
|
||||
if not os.access(filename, os.R_OK):
|
||||
ErrorDialog(
|
||||
_('Cannot open file'),
|
||||
_('You do not have read access to the selected file.'),
|
||||
parent=self.uistate.window)
|
||||
return True
|
||||
else:
|
||||
try:
|
||||
f = file(filename,'w')
|
||||
f.close()
|
||||
os.remove(filename)
|
||||
except IOError:
|
||||
ErrorDialog(
|
||||
_('Cannot create file'),
|
||||
_('You do not have write access to the selected file.'),
|
||||
parent=self.uistate.window)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def do_import(self, dialog, importer, filename):
|
||||
self.import_info = None
|
||||
dialog.destroy()
|
||||
self._begin_progress()
|
||||
|
||||
try:
|
||||
#an importer can return an object with info, object.info_text()
|
||||
#returns that info. Otherwise None is set to import_info
|
||||
self.import_info = importer(self.dbstate.db, filename,
|
||||
User(callback=self._pulse_progress,
|
||||
uistate=self.uistate,
|
||||
dbstate=self.dbstate))
|
||||
dirname = os.path.dirname(filename) + os.path.sep
|
||||
config.set('paths.recent-import-dir', dirname)
|
||||
except UnicodeError as msg:
|
||||
ErrorDialog(
|
||||
_("Could not import file: %s") % filename,
|
||||
_("This file incorrectly identifies its character "
|
||||
"set, so it cannot be accurately imported. Please fix the "
|
||||
"encoding, and import again") + "\n\n %s" % msg,
|
||||
parent=self.uistate.window)
|
||||
except Exception:
|
||||
_LOG.error("Failed to import database.", exc_info=True)
|
||||
self._end_progress()
|
||||
GrampsImportFileDialog(self.dbstate, self.uistate)
|
||||
|
||||
def import_info_text(self):
|
||||
"""
|
||||
@ -521,3 +375,172 @@ def format_maker():
|
||||
box.add(type_selector)
|
||||
box.show_all()
|
||||
return (box, type_selector)
|
||||
|
||||
class GrampsImportFileDialog(ManagedWindow):
|
||||
|
||||
def __init__(self, dbstate, uistate):
|
||||
"""
|
||||
A dialog to import a file into Gramps
|
||||
"""
|
||||
self.dbstate = dbstate
|
||||
|
||||
self.title = _("Import Family Tree")
|
||||
ManagedWindow.__init__(self, uistate, [], self.__class__, modal=True)
|
||||
# the import_dialog.run() below makes it modal, so any change to
|
||||
# the previous line's "modal" would require that line to be changed
|
||||
|
||||
pmgr = GuiPluginManager.get_instance()
|
||||
|
||||
import_dialog = Gtk.FileChooserDialog(
|
||||
title='', transient_for=self.uistate.window,
|
||||
action=Gtk.FileChooserAction.OPEN)
|
||||
import_dialog.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
|
||||
_('Import'), Gtk.ResponseType.OK)
|
||||
self.set_window(import_dialog, None, self.title)
|
||||
self.setup_configs('interface.grampsimportfiledialog', 780, 630)
|
||||
import_dialog.set_local_only(False)
|
||||
|
||||
# Always add automatic (match all files) filter
|
||||
add_all_files_filter(import_dialog) # *
|
||||
|
||||
# Add more file type selections for available importers
|
||||
for plugin in pmgr.get_import_plugins():
|
||||
file_filter = Gtk.FileFilter()
|
||||
name = "%s (.%s)" % (plugin.get_name(), plugin.get_extension())
|
||||
file_filter.set_name(name)
|
||||
file_filter.add_pattern("*.%s" % plugin.get_extension())
|
||||
file_filter.add_pattern(plugin.get_extension().capitalize())
|
||||
import_dialog.add_filter(file_filter)
|
||||
|
||||
(box, type_selector) = format_maker()
|
||||
import_dialog.set_extra_widget(box)
|
||||
|
||||
# Suggested folder: try last open file, import, then last export,
|
||||
# then home.
|
||||
default_dir = config.get('paths.recent-import-dir')
|
||||
if len(default_dir)<=1:
|
||||
default_dir = get_default_dir()
|
||||
|
||||
import_dialog.set_current_folder(default_dir)
|
||||
while True:
|
||||
# the import_dialog.run() makes it modal, so any change to that
|
||||
# line would require the ManagedWindow.__init__ to be changed also
|
||||
response = import_dialog.run()
|
||||
if response in (Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT):
|
||||
break
|
||||
elif response == Gtk.ResponseType.OK:
|
||||
filename = import_dialog.get_filename()
|
||||
if self.check_errors(filename):
|
||||
# displays errors if any
|
||||
continue
|
||||
|
||||
(the_path, the_file) = os.path.split(filename)
|
||||
config.set('paths.recent-import-dir', the_path)
|
||||
|
||||
extension = type_selector.get_value()
|
||||
if extension == 'auto':
|
||||
# Guess the file format based on the file extension.
|
||||
# This will get the lower case extension without a period,
|
||||
# or an empty string.
|
||||
extension = os.path.splitext(filename)[-1][1:].lower()
|
||||
|
||||
for plugin in pmgr.get_import_plugins():
|
||||
if extension == plugin.get_extension():
|
||||
self.do_import(import_dialog,
|
||||
plugin.get_import_function(),
|
||||
filename)
|
||||
self.close()
|
||||
return
|
||||
|
||||
# Finally, we give up and declare this an unknown format
|
||||
ErrorDialog(
|
||||
_("Could not open file: %s") % filename,
|
||||
_('File type "%s" is unknown to Gramps.\n\n'
|
||||
'Valid types are: Gramps database, Gramps XML, '
|
||||
'Gramps package, GEDCOM, and others.') % extension,
|
||||
parent=self.uistate.window)
|
||||
|
||||
self.close()
|
||||
|
||||
def check_errors(self, filename):
|
||||
"""
|
||||
Run common error checks and return True if any found.
|
||||
|
||||
In this process, a warning dialog can pop up.
|
||||
|
||||
"""
|
||||
if not isinstance(filename, str):
|
||||
return True
|
||||
|
||||
filename = os.path.normpath(os.path.abspath(filename))
|
||||
|
||||
if len(filename) == 0:
|
||||
return True
|
||||
elif os.path.isdir(filename):
|
||||
ErrorDialog(
|
||||
_('Cannot open file'),
|
||||
_('The selected file is a directory, not a file.\n'),
|
||||
parent=self.uistate.window)
|
||||
return True
|
||||
elif os.path.exists(filename):
|
||||
if not os.access(filename, os.R_OK):
|
||||
ErrorDialog(
|
||||
_('Cannot open file'),
|
||||
_('You do not have read access to the selected file.'),
|
||||
parent=self.uistate.window)
|
||||
return True
|
||||
else:
|
||||
try:
|
||||
f = file(filename,'w')
|
||||
f.close()
|
||||
os.remove(filename)
|
||||
except IOError:
|
||||
ErrorDialog(
|
||||
_('Cannot create file'),
|
||||
_('You do not have write access to the selected file.'),
|
||||
parent=self.uistate.window)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def do_import(self, dialog, importer, filename):
|
||||
self.import_info = None
|
||||
position = self.window.get_position() # crock
|
||||
dialog.hide()
|
||||
self.window.move(position[0], position[1])
|
||||
self._begin_progress()
|
||||
|
||||
try:
|
||||
#an importer can return an object with info, object.info_text()
|
||||
#returns that info. Otherwise None is set to import_info
|
||||
self.import_info = importer(self.dbstate.db, filename,
|
||||
User(callback=self._pulse_progress,
|
||||
uistate=self.uistate,
|
||||
dbstate=self.dbstate))
|
||||
dirname = os.path.dirname(filename) + os.path.sep
|
||||
config.set('paths.recent-import-dir', dirname)
|
||||
except UnicodeError as msg:
|
||||
ErrorDialog(
|
||||
_("Could not import file: %s") % filename,
|
||||
_("This file incorrectly identifies its character "
|
||||
"set, so it cannot be accurately imported. Please fix the "
|
||||
"encoding, and import again") + "\n\n %s" % msg,
|
||||
parent=self.uistate.window)
|
||||
except Exception:
|
||||
_LOG.error("Failed to import database.", exc_info=True)
|
||||
self._end_progress()
|
||||
|
||||
def build_menu_names(self, obj): # this is meaningless since it's modal
|
||||
return (self.title, None)
|
||||
|
||||
def _begin_progress(self):
|
||||
self.uistate.set_busy_cursor(True)
|
||||
self.uistate.progress.show()
|
||||
self.uistate.pulse_progressbar(0)
|
||||
|
||||
def _pulse_progress(self, value):
|
||||
self.uistate.pulse_progressbar(value)
|
||||
|
||||
def _end_progress(self):
|
||||
self.uistate.set_busy_cursor(False)
|
||||
self.uistate.progress.hide()
|
||||
|
@ -307,17 +307,17 @@ class EditCitation(EditPrimary):
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
with DbTxn('', self.db) as trans:
|
||||
if not self.obj.get_handle():
|
||||
if not self.obj.handle:
|
||||
with DbTxn(_("Add Citation (%s)") % self.obj.get_page(),
|
||||
self.db) as trans:
|
||||
self.db.add_citation(self.obj, trans)
|
||||
msg = _("Add Citation (%s)") % self.obj.get_page()
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(
|
||||
self.db.find_next_citation_gramps_id())
|
||||
self.db.commit_citation(self.obj, trans)
|
||||
msg = _("Edit Citation (%s)") % self.obj.get_page()
|
||||
trans.set_description(msg)
|
||||
else:
|
||||
if self.data_has_changed():
|
||||
with DbTxn(_("Edit Citation (%s)") % self.obj.get_page(),
|
||||
self.db) as trans:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_citation_gramps_id())
|
||||
self.db.commit_citation(self.obj, trans)
|
||||
|
||||
if self.callback:
|
||||
self.callback(self.obj.get_handle())
|
||||
|
@ -269,13 +269,12 @@ class EditEvent(EditPrimary):
|
||||
self.db) as trans:
|
||||
self.db.add_event(self.obj, trans)
|
||||
else:
|
||||
orig = self.get_from_handle(self.obj.handle)
|
||||
if self.obj.serialize() != orig.serialize():
|
||||
if self.data_has_changed():
|
||||
with DbTxn(_("Edit Event (%s)") % self.obj.get_gramps_id(),
|
||||
self.db) as trans:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_event_gramps_id())
|
||||
self.commit_event(self.obj, trans)
|
||||
self.db.commit_event(self.obj, trans)
|
||||
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
|
@ -1129,7 +1129,7 @@ class EditFamily(EditPrimary):
|
||||
self.db.commit_person(child, trans)
|
||||
|
||||
self.db.add_family(self.obj, trans)
|
||||
elif original.serialize() != self.obj.serialize():
|
||||
elif self.data_has_changed():
|
||||
|
||||
with DbTxn(_("Edit Family"), self.db) as trans:
|
||||
|
||||
|
@ -320,16 +320,17 @@ class EditMedia(EditPrimary):
|
||||
|
||||
self.obj.set_path(path)
|
||||
|
||||
with DbTxn('', self.db) as trans:
|
||||
if not self.obj.get_handle():
|
||||
if not self.obj.handle:
|
||||
with DbTxn(_("Add Media Object (%s)") % self.obj.get_description(),
|
||||
self.db) as trans:
|
||||
self.db.add_media(self.obj, trans)
|
||||
msg = _("Add Media Object (%s)") % self.obj.get_description()
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_media_gramps_id())
|
||||
self.db.commit_media(self.obj, trans)
|
||||
msg = _("Edit Media Object (%s)") % self.obj.get_description()
|
||||
trans.set_description(msg)
|
||||
else:
|
||||
if self.data_has_changed():
|
||||
with DbTxn(_("Edit Media Object (%s)") % self.obj.get_description(),
|
||||
self.db) as trans:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_media_gramps_id())
|
||||
self.db.commit_media(self.obj, trans)
|
||||
|
||||
if self.callback:
|
||||
self.callback(self.obj)
|
||||
|
@ -301,6 +301,11 @@ class EditNote(EditPrimary):
|
||||
self.obj.set_styledtext(text)
|
||||
_LOG.debug(str(text))
|
||||
|
||||
def close(self, *obj):
|
||||
"""Called when cancel button clicked."""
|
||||
self.update_note()
|
||||
super().close()
|
||||
|
||||
def save(self, *obj):
|
||||
"""Save the data."""
|
||||
self.ok_button.set_sensitive(False)
|
||||
@ -327,16 +332,17 @@ class EditNote(EditPrimary):
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
with DbTxn('', self.db) as trans:
|
||||
if not self.obj.get_handle():
|
||||
if not self.obj.handle:
|
||||
with DbTxn(_("Add Note"),
|
||||
self.db) as trans:
|
||||
self.db.add_note(self.obj, trans)
|
||||
msg = _("Add Note")
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_note_gramps_id())
|
||||
self.db.commit_note(self.obj, trans)
|
||||
msg = _("Edit Note")
|
||||
trans.set_description(msg)
|
||||
else:
|
||||
if self.data_has_changed():
|
||||
with DbTxn(_("Edit Note"),
|
||||
self.db) as trans:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_note_gramps_id())
|
||||
self.db.commit_note(self.obj, trans)
|
||||
|
||||
if self.callback:
|
||||
self.callback(self.obj.get_handle())
|
||||
|
@ -856,19 +856,19 @@ class EditPerson(EditPrimary):
|
||||
|
||||
self.db.set_birth_death_index(self.obj)
|
||||
|
||||
with DbTxn('', self.db) as trans:
|
||||
self._update_family_ids()
|
||||
if not self.obj.get_handle():
|
||||
if not self.obj.handle:
|
||||
with DbTxn(_("Add Person (%s)") % \
|
||||
self.name_displayer.display(self.obj),
|
||||
self.db) as trans:
|
||||
self.db.add_person(self.obj, trans)
|
||||
msg = _("Add Person (%s)") % \
|
||||
self.name_displayer.display(self.obj)
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_person_gramps_id())
|
||||
self.db.commit_person(self.obj, trans)
|
||||
msg = _("Edit Person (%s)") % \
|
||||
self.name_displayer.display(self.obj)
|
||||
trans.set_description(msg)
|
||||
else:
|
||||
if self.data_has_changed():
|
||||
with DbTxn(_("Edit Person (%s)") % \
|
||||
self.name_displayer.display(self.obj),
|
||||
self.db) as trans:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_person_gramps_id())
|
||||
self.db.commit_person(self.obj, trans)
|
||||
|
||||
self._do_close()
|
||||
if self.callback:
|
||||
|
@ -301,17 +301,18 @@ class EditPlace(EditPrimary):
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
with DbTxn('', self.db) as trans:
|
||||
place_title = place_displayer.display(self.db, self.obj)
|
||||
if not self.obj.get_handle():
|
||||
place_title = place_displayer.display(self.db, self.obj)
|
||||
if not self.obj.handle:
|
||||
with DbTxn(_("Add Place (%s)") % place_title,
|
||||
self.db) as trans:
|
||||
self.db.add_place(self.obj, trans)
|
||||
msg = _("Add Place (%s)") % place_title
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_place_gramps_id())
|
||||
self.db.commit_place(self.obj, trans)
|
||||
msg = _("Edit Place (%s)") % place_title
|
||||
trans.set_description(msg)
|
||||
else:
|
||||
if self.data_has_changed():
|
||||
with DbTxn(_("Edit Place (%s)") % place_title,
|
||||
self.db) as trans:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_place_gramps_id())
|
||||
self.db.commit_place(self.obj, trans)
|
||||
|
||||
self._do_close()
|
||||
if self.callback:
|
||||
|
@ -195,16 +195,17 @@ class EditRepository(EditPrimary):
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
with DbTxn('', self.db) as trans:
|
||||
if not self.obj.get_handle():
|
||||
if not self.obj.handle:
|
||||
with DbTxn(_("Add Repository (%s)") % self.obj.get_name(),
|
||||
self.db) as trans:
|
||||
self.db.add_repository(self.obj, trans)
|
||||
msg = _("Add Repository (%s)") % self.obj.get_name()
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_repository_gramps_id())
|
||||
self.db.commit_repository(self.obj, trans)
|
||||
msg = _("Edit Repository (%s)") % self.obj.get_name()
|
||||
trans.set_description(msg)
|
||||
else:
|
||||
if self.data_has_changed():
|
||||
with DbTxn(_("Edit Repository (%s)") % self.obj.get_name(),
|
||||
self.db) as trans:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_repository_gramps_id())
|
||||
self.db.commit_repository(self.obj, trans)
|
||||
|
||||
self._do_close()
|
||||
|
||||
|
@ -216,16 +216,17 @@ class EditSource(EditPrimary):
|
||||
self.ok_button.set_sensitive(True)
|
||||
return
|
||||
|
||||
with DbTxn('', self.db) as trans:
|
||||
if not self.obj.get_handle():
|
||||
if not self.obj.handle:
|
||||
with DbTxn(_("Add Source (%s)") % self.obj.get_title(),
|
||||
self.db) as trans:
|
||||
self.db.add_source(self.obj, trans)
|
||||
msg = _("Add Source (%s)") % self.obj.get_title()
|
||||
else:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_source_gramps_id())
|
||||
self.db.commit_source(self.obj, trans)
|
||||
msg = _("Edit Source (%s)") % self.obj.get_title()
|
||||
trans.set_description(msg)
|
||||
else:
|
||||
if self.data_has_changed():
|
||||
with DbTxn(_("Edit Source (%s)") % self.obj.get_title(),
|
||||
self.db) as trans:
|
||||
if not self.obj.get_gramps_id():
|
||||
self.obj.set_gramps_id(self.db.find_next_source_gramps_id())
|
||||
self.db.commit_source(self.obj, trans)
|
||||
|
||||
self._do_close()
|
||||
if self.callback:
|
||||
|
Loading…
Reference in New Issue
Block a user