Added tagging on import for GEDCOM, XML, and CSV. Also fixed CSV iterator issue with next. Default tag is set in Preferences using time.strftime codes (eg, %Y, %m, etc). Noticed that adding source on input is only for GEDCOM, so adjusted the text description for it. Tagging on input supports all taggable items (notes, media, family, person --- although csv does not import media). Will add to gramps40 if all ok.
svn: r20914
This commit is contained in:
parent
1c240f9bef
commit
771ae761e2
@ -279,6 +279,8 @@ register('preferences.date-format', 0)
|
||||
register('preferences.calendar-format-report', 0)
|
||||
register('preferences.cprefix', 'C%04d')
|
||||
register('preferences.default-source', False)
|
||||
register('preferences.tag-on-import', False)
|
||||
register('preferences.tag-on-import-format', _("Imported %Y/%m/%d %H:%M:%S"))
|
||||
register('preferences.eprefix', 'E%04d')
|
||||
register('preferences.family-warn', True)
|
||||
register('preferences.fprefix', 'F%04d')
|
||||
|
@ -327,13 +327,18 @@ class ConfigureDialog(ManagedWindow):
|
||||
config = self.__config
|
||||
if not callback:
|
||||
callback = self.update_entry
|
||||
lwidget = BasicLabel("%s: " % label)
|
||||
if label:
|
||||
lwidget = BasicLabel("%s: " % label)
|
||||
entry = Gtk.Entry()
|
||||
entry.set_text(config.get(constant))
|
||||
entry.connect('changed', callback, constant)
|
||||
table.attach(lwidget, col_attach, col_attach+1, index, index+1, yoptions=0,
|
||||
xoptions=Gtk.AttachOptions.FILL)
|
||||
table.attach(entry, col_attach+1, col_attach+2, index, index+1, yoptions=0)
|
||||
if label:
|
||||
table.attach(lwidget, col_attach, col_attach+1, index, index+1, yoptions=0,
|
||||
xoptions=Gtk.AttachOptions.FILL)
|
||||
table.attach(entry, col_attach+1, col_attach+2, index, index+1, yoptions=0)
|
||||
else:
|
||||
table.attach(entry, col_attach, col_attach+1, index, index+1, yoptions=0)
|
||||
return entry
|
||||
|
||||
def add_pos_int_entry(self, table, label, index, constant, callback=None,
|
||||
config=None, col_attach=1):
|
||||
@ -1101,6 +1106,11 @@ class GrampsPreferences(ConfigureDialog):
|
||||
config.set('behavior.do-not-show-previously-seen-updates',
|
||||
bool(active))
|
||||
|
||||
def toggle_tag_on_import(self, obj):
|
||||
active = obj.get_active()
|
||||
config.set('preferences.tag-on-import', bool(active))
|
||||
self.tag_format_entry.set_sensitive(bool(active))
|
||||
|
||||
def check_for_updates_changed(self, obj):
|
||||
active = obj.get_active()
|
||||
config.set('behavior.check-for-updates', active)
|
||||
@ -1153,27 +1163,49 @@ class GrampsPreferences(ConfigureDialog):
|
||||
table.set_col_spacings(6)
|
||||
table.set_row_spacings(6)
|
||||
|
||||
current_line = 0
|
||||
self.add_checkbox(table,
|
||||
_('Add default source on import'),
|
||||
0, 'preferences.default-source')
|
||||
_('Add default source on GEDCOM import'),
|
||||
current_line, 'preferences.default-source')
|
||||
|
||||
current_line += 1
|
||||
checkbutton = Gtk.CheckButton(_("Add tag on import"))
|
||||
checkbutton.set_active(config.get('preferences.tag-on-import'))
|
||||
checkbutton.connect("toggled", self.toggle_tag_on_import)
|
||||
table.attach(checkbutton, 1, 2, current_line, current_line+1, yoptions=0)
|
||||
self.tag_format_entry = self.add_entry(table, None, current_line,
|
||||
'preferences.tag-on-import-format',
|
||||
col_attach=2)
|
||||
self.tag_format_entry.set_sensitive(config.get('preferences.tag-on-import'))
|
||||
|
||||
current_line += 1
|
||||
self.add_checkbox(table,
|
||||
_('Enable spelling checker'),
|
||||
1, 'behavior.spellcheck')
|
||||
current_line, 'behavior.spellcheck')
|
||||
|
||||
current_line += 1
|
||||
self.add_checkbox(table,
|
||||
_('Display Tip of the Day'),
|
||||
2, 'behavior.use-tips')
|
||||
current_line, 'behavior.use-tips')
|
||||
|
||||
current_line += 1
|
||||
self.add_checkbox(table,
|
||||
_('Remember last view displayed'),
|
||||
3, 'preferences.use-last-view')
|
||||
current_line, 'preferences.use-last-view')
|
||||
|
||||
current_line += 1
|
||||
self.add_spinner(table,
|
||||
_('Max generations for relationships'),
|
||||
4, 'behavior.generation-depth', (5, 50), self.update_gendepth)
|
||||
current_line, 'behavior.generation-depth', (5, 50), self.update_gendepth)
|
||||
|
||||
current_line += 1
|
||||
self.path_entry = Gtk.Entry()
|
||||
self.add_path_box(table,
|
||||
_('Base path for relative media paths'),
|
||||
5, self.path_entry, self.dbstate.db.get_mediapath(),
|
||||
current_line, self.path_entry, self.dbstate.db.get_mediapath(),
|
||||
self.set_mediapath, self.select_mediapath)
|
||||
|
||||
current_line += 1
|
||||
# Check for updates:
|
||||
obox = Gtk.ComboBoxText()
|
||||
formats = [_("Never"),
|
||||
@ -1186,9 +1218,10 @@ class GrampsPreferences(ConfigureDialog):
|
||||
obox.set_active(active)
|
||||
obox.connect('changed', self.check_for_updates_changed)
|
||||
lwidget = BasicLabel("%s: " % _('Check for updates'))
|
||||
table.attach(lwidget, 1, 2, 6, 7, yoptions=0)
|
||||
table.attach(obox, 2, 3, 6, 7, yoptions=0)
|
||||
table.attach(lwidget, 1, 2, current_line, current_line+1, yoptions=0)
|
||||
table.attach(obox, 2, 3, current_line, current_line+1, yoptions=0)
|
||||
|
||||
current_line += 1
|
||||
self.whattype_box = Gtk.ComboBoxText()
|
||||
formats = [_("Updated addons only"),
|
||||
_("New addons only"),
|
||||
@ -1203,21 +1236,23 @@ class GrampsPreferences(ConfigureDialog):
|
||||
self.whattype_box.set_active(0)
|
||||
self.whattype_box.connect('changed', self.check_for_type_changed)
|
||||
lwidget = BasicLabel("%s: " % _('What to check'))
|
||||
table.attach(lwidget, 1, 2, 7, 8, yoptions=0)
|
||||
table.attach(self.whattype_box, 2, 3, 7, 8, yoptions=0)
|
||||
table.attach(lwidget, 1, 2, current_line, current_line+1, yoptions=0)
|
||||
table.attach(self.whattype_box, 2, 3, current_line, current_line+1, yoptions=0)
|
||||
|
||||
self.add_entry(table, _('Where to check'), 8, 'behavior.addons-url', col_attach=1)
|
||||
current_line += 1
|
||||
self.add_entry(table, _('Where to check'), current_line, 'behavior.addons-url', col_attach=1)
|
||||
|
||||
current_line += 1
|
||||
checkbutton = Gtk.CheckButton(
|
||||
_("Do not ask about previously notified addons"))
|
||||
checkbutton.set_active(config.get('behavior.do-not-show-previously-seen-updates'))
|
||||
checkbutton.connect("toggled", self.toggle_hide_previous_addons)
|
||||
|
||||
table.attach(checkbutton, 0, 3, 9, 10, yoptions=0)
|
||||
table.attach(checkbutton, 0, 3, current_line, current_line+1, yoptions=0)
|
||||
button = Gtk.Button(_("Check now"))
|
||||
button.connect("clicked", lambda obj: \
|
||||
self.uistate.viewmanager.check_for_updates(force=True))
|
||||
table.attach(button, 3, 4, 9, 10, yoptions=0)
|
||||
table.attach(button, 3, 4, current_line, current_line+1, yoptions=0)
|
||||
|
||||
return _('General'), table
|
||||
|
||||
|
@ -50,7 +50,7 @@ LOG = logging.getLogger(".ImportCSV")
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.ggettext import sgettext as _
|
||||
from gramps.gen.ggettext import ngettext
|
||||
from gramps.gen.lib import ChildRef, Citation, Event, EventRef, EventType, Family, FamilyRelType, Name, NameType, Note, NoteType, Person, Place, Source, Surname
|
||||
from gramps.gen.lib import ChildRef, Citation, Event, EventRef, EventType, Family, FamilyRelType, Name, NameType, Note, NoteType, Person, Place, Source, Surname, Tag
|
||||
from gramps.gen.db import DbTxn
|
||||
from gramps.gen.plug.utils import OpenFileOrStdin
|
||||
from gramps.gen.datehandler import parser as _dp
|
||||
@ -59,6 +59,7 @@ from gramps.gen.utils.id import create_id
|
||||
from gramps.gui.utils import ProgressMeter
|
||||
from gramps.gen.lib.eventroletype import EventRoleType
|
||||
from gramps.gen.constfunc import cuni, conv_to_unicode, STRTYPE
|
||||
from gramps.gen.config import config
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -95,6 +96,8 @@ class UTF8Recoder(object):
|
||||
"Encode the next line of the file."
|
||||
return self.reader.next().encode("utf-8")
|
||||
|
||||
next = __next__
|
||||
|
||||
class UnicodeReader(object):
|
||||
"""
|
||||
A CSV reader which will iterate over lines in the CSV file,
|
||||
@ -120,6 +123,8 @@ class UnicodeReader(object):
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
next = __next__
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Support and main functions
|
||||
@ -141,7 +146,8 @@ def rd(line_number, row, col, key, default = None):
|
||||
|
||||
def importData(dbase, filename, user):
|
||||
"""Function called by Gramps to import data on persons in CSV format."""
|
||||
parser = CSVParser(dbase, user)
|
||||
parser = CSVParser(dbase, user, (config.get('preferences.tag-on-import-format') if
|
||||
config.get('preferences.tag-on-import') else None))
|
||||
try:
|
||||
with OpenFileOrStdin(filename, 'b') as filehandle:
|
||||
parser.parse(filehandle)
|
||||
@ -157,7 +163,7 @@ def importData(dbase, filename, user):
|
||||
#-------------------------------------------------------------------------
|
||||
class CSVParser(object):
|
||||
"""Class to read data in CSV format from a file object."""
|
||||
def __init__(self, dbase, user):
|
||||
def __init__(self, dbase, user, default_tag_format=None):
|
||||
self.db = dbase
|
||||
self.user = user
|
||||
self.trans = None
|
||||
@ -235,6 +241,16 @@ class CSVParser(object):
|
||||
for val in column2label[key]:
|
||||
lab2col_dict.append((val, key))
|
||||
self.label2column = dict(lab2col_dict)
|
||||
if default_tag_format:
|
||||
name = time.strftime(default_tag_format)
|
||||
tag = self.db.get_tag_from_name(name)
|
||||
if tag:
|
||||
self.default_tag = tag
|
||||
else:
|
||||
self.default_tag = Tag()
|
||||
self.default_tag.set_name(name)
|
||||
else:
|
||||
self.default_tag = None
|
||||
|
||||
def cleanup_column_name(self, column):
|
||||
"""Handle column aliases for CSV spreadsheet import and SQL."""
|
||||
@ -313,6 +329,8 @@ class CSVParser(object):
|
||||
tym = time.time()
|
||||
self.db.disable_signals()
|
||||
with DbTxn(_("CSV import"), self.db, batch=True) as self.trans:
|
||||
if self.default_tag and self.default_tag.handle is None:
|
||||
self.db.add_tag(self.default_tag, self.trans)
|
||||
self._parse_csv_data(data, progress)
|
||||
self.db.enable_signals()
|
||||
self.db.request_rebuild()
|
||||
@ -432,6 +450,8 @@ class CSVParser(object):
|
||||
new_note.handle = create_id()
|
||||
new_note.type.set(NoteType.EVENT)
|
||||
new_note.set(note)
|
||||
if self.default_tag:
|
||||
new_note.add_tag(self.default_tag.handle)
|
||||
self.db.add_note(new_note, self.trans)
|
||||
marriage.add_note(new_note.handle)
|
||||
self.db.commit_event(marriage, self.trans)
|
||||
@ -709,6 +729,8 @@ class CSVParser(object):
|
||||
if wife.get_handle() != fam_wife_handle:
|
||||
# this wife is not the same old one! Add her!
|
||||
family.set_mother_handle(wife.get_handle())
|
||||
if self.default_tag:
|
||||
family.add_tag(self.default_tag.handle)
|
||||
LOG.debug(" returning existing family")
|
||||
return family
|
||||
# if not, create one:
|
||||
@ -775,6 +797,8 @@ class CSVParser(object):
|
||||
def create_person(self):
|
||||
""" Used to create a new person we know doesn't exist """
|
||||
person = Person()
|
||||
if self.default_tag:
|
||||
person.add_tag(self.default_tag.handle)
|
||||
self.db.add_person(person, self.trans)
|
||||
self.indi_count += 1
|
||||
return person
|
||||
|
@ -115,8 +115,10 @@ def importData(database, filename, user):
|
||||
stage_one.set_encoding(code_set)
|
||||
ifile.seek(0)
|
||||
gedparse = libgedcom.GedcomParser(
|
||||
database, ifile, filename, user, stage_one,
|
||||
config.get('preferences.default-source'))
|
||||
database, ifile, filename, user, stage_one,
|
||||
config.get('preferences.default-source'),
|
||||
(config.get('preferences.tag-on-import-format') if
|
||||
config.get('preferences.tag-on-import') else None))
|
||||
except IOError as msg:
|
||||
user.notify_error(_("%s could not be opened\n") % filename, str(msg))
|
||||
return
|
||||
|
@ -94,6 +94,7 @@ def impData(database, name, user):
|
||||
|
||||
importer = importData
|
||||
info = importer(database, imp_db_name, user)
|
||||
|
||||
newmediapath = database.get_mediapath()
|
||||
#import of gpkg should not change media path as all media has new paths!
|
||||
if not oldmediapath == newmediapath :
|
||||
|
@ -67,6 +67,7 @@ from gramps.gen.db.dbconst import (PERSON_KEY, FAMILY_KEY, SOURCE_KEY,
|
||||
CITATION_KEY)
|
||||
from gramps.gen.updatecallback import UpdateCallback
|
||||
from gramps.gen.const import VERSION
|
||||
from gramps.gen.config import config
|
||||
#import gramps.plugins.lib.libgrampsxml
|
||||
from gramps.plugins.lib import libgrampsxml
|
||||
|
||||
@ -123,7 +124,9 @@ def importData(database, filename, user):
|
||||
change = time.time()
|
||||
else:
|
||||
change = os.path.getmtime(filename)
|
||||
parser = GrampsParser(database, user, change)
|
||||
parser = GrampsParser(database, user, change,
|
||||
(config.get('preferences.tag-on-import-format') if
|
||||
config.get('preferences.tag-on-import') else None))
|
||||
|
||||
if filename != '-':
|
||||
linecounter = LineParser(filename)
|
||||
@ -457,7 +460,7 @@ class ImportOpenFileContextManager:
|
||||
#-------------------------------------------------------------------------
|
||||
class GrampsParser(UpdateCallback):
|
||||
|
||||
def __init__(self, database, user, change):
|
||||
def __init__(self, database, user, change, default_tag_format=None):
|
||||
UpdateCallback.__init__(self, user.callback)
|
||||
self.user = user
|
||||
self.__gramps_version = 'unknown'
|
||||
@ -564,6 +567,17 @@ class GrampsParser(UpdateCallback):
|
||||
self.eidswap = {}
|
||||
self.import_handles = {}
|
||||
|
||||
if default_tag_format:
|
||||
name = time.strftime(default_tag_format)
|
||||
tag = self.db.get_tag_from_name(name)
|
||||
if tag:
|
||||
self.default_tag = tag
|
||||
else:
|
||||
self.default_tag = Tag()
|
||||
self.default_tag.set_name(name)
|
||||
else:
|
||||
self.default_tag = None
|
||||
|
||||
self.func_map = {
|
||||
#name part
|
||||
"name": (self.start_name, self.stop_name),
|
||||
@ -895,6 +909,9 @@ class GrampsParser(UpdateCallback):
|
||||
|
||||
self.db.disable_signals()
|
||||
|
||||
if self.default_tag and self.default_tag.handle is None:
|
||||
self.db.add_tag(self.default_tag, self.trans)
|
||||
|
||||
self.p = ParserCreate()
|
||||
self.p.StartElementHandler = self.startElement
|
||||
self.p.EndElementHandler = self.endElement
|
||||
@ -1384,6 +1401,8 @@ class GrampsParser(UpdateCallback):
|
||||
self.person.change = int(attrs.get('change', self.change))
|
||||
self.info.add('new-object', PERSON_KEY, self.person)
|
||||
self.convert_marker(attrs, self.person)
|
||||
if self.default_tag:
|
||||
self.person.add_tag(self.default_tag.handle)
|
||||
return self.person
|
||||
|
||||
def start_people(self, attrs):
|
||||
@ -1520,6 +1539,8 @@ class GrampsParser(UpdateCallback):
|
||||
if 'type' in attrs:
|
||||
self.family.type.set_from_xml_str(attrs["type"])
|
||||
self.convert_marker(attrs, self.family)
|
||||
if self.default_tag:
|
||||
self.family.add_tag(self.default_tag.handle)
|
||||
return self.family
|
||||
|
||||
def start_rel(self, attrs):
|
||||
@ -1833,6 +1854,8 @@ class GrampsParser(UpdateCallback):
|
||||
#set correct change time
|
||||
self.db.commit_note(self.note, self.trans, self.change)
|
||||
self.info.add('new-object', NOTE_KEY, self.note)
|
||||
if self.default_tag:
|
||||
self.note.add_tag(self.default_tag.handle)
|
||||
return self.note
|
||||
|
||||
def start_noteref(self, attrs):
|
||||
@ -2088,6 +2111,8 @@ class GrampsParser(UpdateCallback):
|
||||
src = attrs.get("src", '')
|
||||
if src:
|
||||
self.object.path = src
|
||||
if self.default_tag:
|
||||
self.object.add_tag(self.default_tag.handle)
|
||||
return self.object
|
||||
|
||||
def start_repo(self, attrs):
|
||||
|
@ -127,7 +127,7 @@ from gramps.gen.lib import (Address, Attribute, AttributeType, ChildRef,
|
||||
ChildRefType, Citation, Date, Event, EventRef, EventRoleType,
|
||||
EventType, Family, FamilyRelType, LdsOrd, Location, MediaObject,
|
||||
MediaRef, Name, NameType, Note, NoteType, Person, PersonRef, Place,
|
||||
RepoRef, Repository, RepositoryType, Researcher, Source,
|
||||
RepoRef, Repository, RepositoryType, Researcher, Source, Tag,
|
||||
SourceMediaType, Surname, Url, UrlType)
|
||||
from gramps.gen.db import DbTxn
|
||||
from gramps.gen.updatecallback import UpdateCallback
|
||||
@ -1807,7 +1807,7 @@ class GedcomParser(UpdateCallback):
|
||||
return name
|
||||
|
||||
def __init__(self, dbase, ifile, filename, user, stage_one,
|
||||
default_source):
|
||||
default_source, default_tag_format=None):
|
||||
UpdateCallback.__init__(self, user.callback)
|
||||
self.user = user
|
||||
self.set_total(stage_one.get_line_count())
|
||||
@ -1835,6 +1835,16 @@ class GedcomParser(UpdateCallback):
|
||||
self.def_src = Source()
|
||||
fname = os.path.basename(filename).split('\\')[-1]
|
||||
self.def_src.set_title(_("Import from GEDCOM (%s)") % fname)
|
||||
if default_tag_format:
|
||||
name = time.strftime(default_tag_format)
|
||||
tag = self.dbase.get_tag_from_name(name)
|
||||
if tag:
|
||||
self.default_tag = tag
|
||||
else:
|
||||
self.default_tag = Tag()
|
||||
self.default_tag.set_name(name)
|
||||
else:
|
||||
self.default_tag = None
|
||||
self.dir_path = os.path.dirname(filename)
|
||||
self.is_ftw = False
|
||||
self.groups = None
|
||||
@ -2594,6 +2604,8 @@ class GedcomParser(UpdateCallback):
|
||||
self.want_parse_warnings = True
|
||||
if self.use_def_src:
|
||||
self.dbase.add_source(self.def_src, self.trans)
|
||||
if self.default_tag and self.default_tag.handle is None:
|
||||
self.dbase.add_tag(self.default_tag, self.trans)
|
||||
self.__parse_record()
|
||||
self.__parse_trailer()
|
||||
for title, handle in self.inline_srcs.items():
|
||||
@ -3318,6 +3330,9 @@ class GedcomParser(UpdateCallback):
|
||||
# Add the default reference if no source has found
|
||||
self.__add_default_source(person)
|
||||
|
||||
# Add a default tag if provided
|
||||
self.__add_default_tag(person)
|
||||
|
||||
self.__check_msgs(_("INDI (individual) Gramps ID %s") %
|
||||
person.get_gramps_id(), state, person)
|
||||
# commit the person to the database
|
||||
@ -4579,6 +4594,9 @@ class GedcomParser(UpdateCallback):
|
||||
# add default reference if no reference exists
|
||||
self.__add_default_source(family)
|
||||
|
||||
# Add a default tag if provided
|
||||
self.__add_default_tag(family)
|
||||
|
||||
self.__check_msgs(_("FAM (family) Gramps ID %s") % family.get_gramps_id(),
|
||||
state, family)
|
||||
# commit family to database
|
||||
@ -6118,6 +6136,9 @@ class GedcomParser(UpdateCallback):
|
||||
# Add the default reference if no source has found
|
||||
self.__add_default_source(media)
|
||||
|
||||
# Add a default tag if provided
|
||||
self.__add_default_tag(media)
|
||||
|
||||
self.__check_msgs(_("OBJE (multi-media object) Gramps ID %s") %
|
||||
media.get_gramps_id(), state, media)
|
||||
# commit the person to the database
|
||||
@ -6931,6 +6952,9 @@ class GedcomParser(UpdateCallback):
|
||||
self.__undefined)
|
||||
state.msg += sub_state.msg
|
||||
|
||||
# Add a default tag if provided
|
||||
self.__add_default_tag(new_note)
|
||||
|
||||
self.dbase.commit_note(new_note, self.trans, new_note.change)
|
||||
obj.add_note(new_note.get_handle())
|
||||
|
||||
@ -7255,6 +7279,13 @@ class GedcomParser(UpdateCallback):
|
||||
self.dbase.add_citation(citation, self.trans)
|
||||
obj.add_citation(citation.handle)
|
||||
|
||||
def __add_default_tag(self, obj):
|
||||
"""
|
||||
Add the default tag to the object.
|
||||
"""
|
||||
if self.default_tag:
|
||||
obj.add_tag(self.default_tag.handle)
|
||||
|
||||
def __subm_name(self, line, state):
|
||||
"""
|
||||
@param line: The current line in GedLine format
|
||||
|
Loading…
Reference in New Issue
Block a user