diff --git a/gramps/gen/db/read.py b/gramps/gen/db/read.py
index 4a540282d..4159ece21 100644
--- a/gramps/gen/db/read.py
+++ b/gramps/gen/db/read.py
@@ -1859,6 +1859,11 @@ class DbBsddbRead(DbReadBase, Callback):
return self.metadata.get(b'mediapath', None)
return None
+ def set_GEDCOM_template_handle(self, handle):
+ """Set the default GEDCOM template handle for database"""
+ if (self.metadata is not None) and (not self.readonly):
+ self.metadata[b'gedcom_template'] = handle
+
def find_backlink_handles(self, handle, include_classes=None):
"""
Find all objects that hold a reference to the object handle.
diff --git a/gramps/gen/db/write.py b/gramps/gen/db/write.py
index 03037b9ac..ed7a42d7a 100644
--- a/gramps/gen/db/write.py
+++ b/gramps/gen/db/write.py
@@ -393,17 +393,6 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
txn.put(b'default', handle)
self.emit('home-person-changed')
- @catch_db_error
- def set_GEDCOM_template_handle(self, handle):
- """Set the handle of the GEDCOM template to the passed instance."""
- #we store a byte string!
- if isinstance(handle, UNITYPE):
- handle = handle.encode('utf-8')
- if not self.readonly:
- # Start transaction
- with BSDDBTxn(self.env, self.metadata) as txn:
- txn.put(b'gedcom_template', handle)
-
@catch_db_error
def get_default_person(self):
"""Return the default Person of the database."""
@@ -416,6 +405,17 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
txn.put(b'default', None)
return None
+ @catch_db_error
+ def set_GEDCOM_template_handle(self, handle):
+ """Set the handle of the GEDCOM template to the passed instance."""
+ #we store a byte string!
+ if isinstance(handle, UNITYPE):
+ handle = handle.encode('utf-8')
+ if not self.readonly:
+ # Start transaction
+ with BSDDBTxn(self.env, self.metadata) as txn:
+ txn.put(b'gedcom_template', handle)
+
def set_mediapath(self, path):
"""Set the default media path for database, path should be utf-8."""
if self.metadata and not self.readonly:
diff --git a/gramps/gen/lib/__init__.py b/gramps/gen/lib/__init__.py
index cf2cd3433..b74ab3f00 100644
--- a/gramps/gen/lib/__init__.py
+++ b/gramps/gen/lib/__init__.py
@@ -79,6 +79,7 @@ from .markertype import MarkerType
from .nameorigintype import NameOriginType
from .notetype import NoteType
from .styledtexttagtype import StyledTextTagType
+from .templateelement import TemplateElement
# Text
from .styledtexttag import StyledTextTag
diff --git a/gramps/gen/lib/src.py b/gramps/gen/lib/src.py
index d4ce284e7..7dbd52d2e 100644
--- a/gramps/gen/lib/src.py
+++ b/gramps/gen/lib/src.py
@@ -36,8 +36,6 @@ from .mediabase import MediaBase
from .notebase import NoteBase
from .tagbase import TagBase
from .srcattrbase import SrcAttributeBase
-from .srctemplate import SrcTemplate
-from .srctemplatelist import SrcTemplateList
from .reporef import RepoRef
from .const import DIFFERENT, EQUAL, IDENTICAL
from ..constfunc import cuni, deprecated
diff --git a/gramps/gen/lib/srctemplate.py b/gramps/gen/lib/srctemplate.py
index 3f5aa508a..a25cad08f 100644
--- a/gramps/gen/lib/srctemplate.py
+++ b/gramps/gen/lib/srctemplate.py
@@ -48,9 +48,9 @@ LOG = logging.getLogger('.template')
#
#-------------------------------------------------------------------------
from .tableobj import TableObject
-from .secondaryobj import SecondaryObject
from .handle import Handle
from ..constfunc import cuni
+from .templateelement import TemplateElement
#-------------------------------------------------------------------------
#
@@ -224,191 +224,3 @@ class SrcTemplate(TableObject):
def add_template_element(self, template_element):
self.template_element_list.append(template_element)
-
-class TemplateElement(SecondaryObject):
- """
- TemplateEelement class.
-
- This class is for keeping information about each template-element.
-
- TemplateElement:
-
- - template_element_name - English name of the element exactly as it appears
- in Yates e.g. [WRITER FIRST]
-
- - name to be displayed in the user interface e.g. 'Name of the first
- author'
-
- - hint e.g. "Doe, D.P. & Cameron, E."
-
- - tooltip e.g. "Give names in following form: 'FirstAuthorSurname, Given
- Names & SecondAuthorSurname, Given Names'. Like this Gramps can parse the
- name and shorten as needed."
-
- - citation - True if this element appears in a citation (false for a source
- element)
-
- - short - True if this element is an optional short element
-
- - short_alg - algorithm to shorten the field.
-
- - list of Mappings - there would always be a GEDCOM mapping. Also we would
- expect a CSL mapping
-
- """
-
- def __init__(self, source=None):
- """
- Create a new TemplateEelement instance, copying from the source if present.
- """
- if source:
- self.name = source.name
- self.display = source.display
- self.hint = source.hint
- self.tooltip = source.tooltip
- self.citation = source.citation
- self.short - source.short
- self.short_alg = source.short_alg
- else:
- self.name = ""
- self.display = ""
- self.hint = ""
- self.tooltip = ""
- self.citation = False
- self.short = False
- self.short_alg = ""
-
- def serialize(self):
- """
- Convert the object to a serialized tuple of data.
- """
- return (self.name,
- self.display,
- self.hint,
- self.tooltip,
- self.citation,
- self.short,
- self.short_alg
- )
-
- def to_struct(self):
- """
- Convert the data held in this object to a structure (eg,
- struct) that represents all the data elements.
-
- This method is used to recursively convert the object into a
- self-documenting form that can easily be used for various
- purposes, including diffs and queries.
-
- These structures may be primitive Python types (string,
- integer, boolean, etc.) or complex Python types (lists,
- tuples, or dicts). If the return type is a dict, then the keys
- of the dict match the fieldname of the object. If the return
- struct (or value of a dict key) is a list, then it is a list
- of structs. Otherwise, the struct is just the value of the
- attribute.
-
- :returns: Returns a struct containing the data of the object.
- :rtype: dict
- """
- return {"name": cuni(self.name),
- "display": cuni(self.display),
- "hint": cuni(self.hint),
- "tooltip": cuni(self.tooltip),
- "citation": cuni(self.citation),
- "short": cuni(self.short),
- "short_alg": cuni(self.short_alg),
- }
-
- def unserialize(self, data):
- """
- Convert a serialized tuple of data to an object.
- """
- (self.name, self.display, self.hint, self.tooltip, self.citation,
- self.short, self.short_alg) = data
- return self
-
- def get_name(self):
- """
- Return the name for the Template element.
- """
- return self.name
-
- def set_name(self, name):
- """
- Set the name for the Template element according to the given argument.
- """
- self.name = name
-
- def get_hint(self):
- """
- Return the hint for the Template element.
- """
- return self.hint
-
- def set_hint(self, hint):
- """
- Set the hint for the Template element according to the given argument.
- """
- self.hint = hint
-
- def get_display(self):
- """
- Return the display form for the Template element.
- """
- return self.display
-
- def set_display(self, display):
- """
- Set the display form for the Template element according to the given
- argument.
- """
- self.display = display
-
- def get_tooltip(self):
- """
- Return the tooltip for the Template element.
- """
- return self.tooltip
-
- def set_tooltip(self, tooltip):
- """
- Set the tooltip for the Template element according to the given argument.
- """
- self.tooltip = tooltip
-
- def get_citation(self):
- """
- Return the citation for the Template element.
- """
- return self.citation
-
- def set_citation(self, citation):
- """
- Set the citation for the Template element according to the given argument.
- """
- self.citation = citation
-
- def get_short(self):
- """
- Return the short for the Template element.
- """
- return self.short
-
- def set_short(self, short):
- """
- Set the short for the Template element according to the given argument.
- """
- self.short = short
-
- def get_short_alg(self):
- """
- Return the short_alg for the Template element.
- """
- return self.short_alg
-
- def set_short_alg(self, short_alg):
- """
- Set the short_alg for the Template element according to the given argument.
- """
- self.short_alg = short_alg
diff --git a/gramps/gen/lib/srctemplatelist.py b/gramps/gen/lib/srctemplatelist.py
deleted file mode 100644
index 58e552a40..000000000
--- a/gramps/gen/lib/srctemplatelist.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Gramps - a GTK+/GNOME based genealogy program
-#
-# Copyright (C) 2013 Benny Malengier
-# Copyright (C) 2013 Tim G L Lyons
-#
-# 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
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-
-# $Id$
-
-"""
-SrcTemplateList class for GRAMPS.
-"""
-
-from __future__ import print_function
-
-#-------------------------------------------------------------------------
-#
-# Python modules
-#
-#-------------------------------------------------------------------------
-import sys
-
-#------------------------------------------------------------------------
-#
-# Set up logging
-#
-#------------------------------------------------------------------------
-import logging
-LOG = logging.getLogger('.template')
-
-#-------------------------------------------------------------------------
-#
-# GRAMPS modules
-#
-#-------------------------------------------------------------------------
-
-# Pattern from http://stackoverflow.com/questions/13789235/how-to-initialize-singleton-derived-object-once
-class Singleton(type):
- _instances = {}
- def __call__(cls, *args, **kwargs):
- if cls not in cls._instances:
- cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
- return cls._instances[cls]
-
-# See http://stackoverflow.com/questions/17237857/python3-singleton-metaclass-
-# method-not-working the syntax has changed
-
-# http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/
-# http://stackoverflow.com/questions/6760685/creating-a-singleton-in-python/17840539
-STL = Singleton('STL', (object, ), {})
-
-class SrcTemplateList(STL):
- """
- Manages a singleton list of the source templates.
-
- This should be replaced by access to the database when the templates are
- stored in the database.
-
- I would expect the TemplateList object to contain a dictionary of Template
- objects, with the template ID as a key. It needs a method to return a list
- of keys, and another method to return the Template object for a given key.
- In this way it would act like a database table.
- """
-# __metaclass__ = Singleton
- def __init__(self):
- self.clear()
-
- def clear(self):
- self.template_list = {}
- self.GEDCOM_handle = None
- self.UNKNOWN_handle = None
-
- def add_template(self, handle, template):
- self.template_list[handle] = template
-
-# def get_template_from_handle(self, handle):
-# if handle in self.template_list:
-# return self.template_list[handle]
-# else:
-# return self.template_list[self.get_UNKNOWN_handle()]
-
-# def get_template_list(self):
-# return self.template_list
-#
-# def template_defined(self, handle):
-# if self.get_template_from_handle(handle) is None:
-# return False
-# else:
-# return True
-#
-# def set_GEDCOM_handle(self, handle):
-# self.GEDCOM_handle = handle
-#
-# def get_GEDCOM_handle(self):
-# return self.GEDCOM_handle
-#
-# def set_UNKNOWN_handle(self, handle):
-# self.UNKNOWN_handle = handle
-#
-# def get_UNKNOWN_handle(self):
-# return self.UNKNOWN_handle
diff --git a/gramps/gen/lib/templateelement.py b/gramps/gen/lib/templateelement.py
new file mode 100644
index 000000000..d4713b821
--- /dev/null
+++ b/gramps/gen/lib/templateelement.py
@@ -0,0 +1,244 @@
+# -*- coding: utf-8 -*-
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2013 Benny Malengier
+# Copyright (C) 2013 Tim G L Lyons
+#
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+# $Id$
+
+"""
+SrcTemplate class for GRAMPS.
+"""
+
+#-------------------------------------------------------------------------
+#
+# Python modules
+#
+#-------------------------------------------------------------------------
+from __future__ import print_function
+
+#------------------------------------------------------------------------
+#
+# Set up logging
+#
+#------------------------------------------------------------------------
+import logging
+LOG = logging.getLogger('.template')
+
+#-------------------------------------------------------------------------
+#
+# GRAMPS modules
+#
+#-------------------------------------------------------------------------
+from .secondaryobj import SecondaryObject
+from ..constfunc import cuni
+
+#-------------------------------------------------------------------------
+#
+# TemplateElement class
+#
+#-------------------------------------------------------------------------
+
+class TemplateElement(SecondaryObject):
+ """
+ TemplateEelement class.
+
+ This class is for keeping information about each template-element.
+
+ TemplateElement:
+
+ - template_element_name - English name of the element exactly as it appears
+ in Yates e.g. [WRITER FIRST]
+
+ - name to be displayed in the user interface e.g. 'Name of the first
+ author'
+
+ - hint e.g. "Doe, D.P. & Cameron, E."
+
+ - tooltip e.g. "Give names in following form: 'FirstAuthorSurname, Given
+ Names & SecondAuthorSurname, Given Names'. Like this Gramps can parse the
+ name and shorten as needed."
+
+ - citation - True if this element appears in a citation (false for a source
+ element)
+
+ - short - True if this element is an optional short element
+
+ - short_alg - algorithm to shorten the field.
+
+ - list of Mappings - there would always be a GEDCOM mapping. Also we would
+ expect a CSL mapping
+
+ """
+
+ def __init__(self, source=None):
+ """
+ Create a new TemplateEelement instance, copying from the source if present.
+ """
+ if source:
+ self.name = source.name
+ self.display = source.display
+ self.hint = source.hint
+ self.tooltip = source.tooltip
+ self.citation = source.citation
+ self.short - source.short
+ self.short_alg = source.short_alg
+ else:
+ self.name = ""
+ self.display = ""
+ self.hint = ""
+ self.tooltip = ""
+ self.citation = False
+ self.short = False
+ self.short_alg = ""
+
+ def serialize(self):
+ """
+ Convert the object to a serialized tuple of data.
+ """
+ return (self.name,
+ self.display,
+ self.hint,
+ self.tooltip,
+ self.citation,
+ self.short,
+ self.short_alg
+ )
+
+ def to_struct(self):
+ """
+ Convert the data held in this object to a structure (eg,
+ struct) that represents all the data elements.
+
+ This method is used to recursively convert the object into a
+ self-documenting form that can easily be used for various
+ purposes, including diffs and queries.
+
+ These structures may be primitive Python types (string,
+ integer, boolean, etc.) or complex Python types (lists,
+ tuples, or dicts). If the return type is a dict, then the keys
+ of the dict match the fieldname of the object. If the return
+ struct (or value of a dict key) is a list, then it is a list
+ of structs. Otherwise, the struct is just the value of the
+ attribute.
+
+ :returns: Returns a struct containing the data of the object.
+ :rtype: dict
+ """
+ return {"name": cuni(self.name),
+ "display": cuni(self.display),
+ "hint": cuni(self.hint),
+ "tooltip": cuni(self.tooltip),
+ "citation": cuni(self.citation),
+ "short": cuni(self.short),
+ "short_alg": cuni(self.short_alg),
+ }
+
+ def unserialize(self, data):
+ """
+ Convert a serialized tuple of data to an object.
+ """
+ (self.name, self.display, self.hint, self.tooltip, self.citation,
+ self.short, self.short_alg) = data
+ return self
+
+ def get_name(self):
+ """
+ Return the name for the Template element.
+ """
+ return self.name
+
+ def set_name(self, name):
+ """
+ Set the name for the Template element according to the given argument.
+ """
+ self.name = name
+
+ def get_hint(self):
+ """
+ Return the hint for the Template element.
+ """
+ return self.hint
+
+ def set_hint(self, hint):
+ """
+ Set the hint for the Template element according to the given argument.
+ """
+ self.hint = hint
+
+ def get_display(self):
+ """
+ Return the display form for the Template element.
+ """
+ return self.display
+
+ def set_display(self, display):
+ """
+ Set the display form for the Template element according to the given
+ argument.
+ """
+ self.display = display
+
+ def get_tooltip(self):
+ """
+ Return the tooltip for the Template element.
+ """
+ return self.tooltip
+
+ def set_tooltip(self, tooltip):
+ """
+ Set the tooltip for the Template element according to the given argument.
+ """
+ self.tooltip = tooltip
+
+ def get_citation(self):
+ """
+ Return the citation for the Template element.
+ """
+ return self.citation
+
+ def set_citation(self, citation):
+ """
+ Set the citation for the Template element according to the given argument.
+ """
+ self.citation = citation
+
+ def get_short(self):
+ """
+ Return the short for the Template element.
+ """
+ return self.short
+
+ def set_short(self, short):
+ """
+ Set the short for the Template element according to the given argument.
+ """
+ self.short = short
+
+ def get_short_alg(self):
+ """
+ Return the short_alg for the Template element.
+ """
+ return self.short_alg
+
+ def set_short_alg(self, short_alg):
+ """
+ Set the short_alg for the Template element according to the given argument.
+ """
+ self.short_alg = short_alg
diff --git a/gramps/gui/editors/editsource.py b/gramps/gui/editors/editsource.py
index 204d88203..836ad60a4 100644
--- a/gramps/gui/editors/editsource.py
+++ b/gramps/gui/editors/editsource.py
@@ -89,7 +89,8 @@ class EditSource(EditPrimary):
self.db = dbstate.db
self.citation = citation
self.template_tab = None
- self.attr_tab = None
+ self.citn_attr_tab = None
+ self.src_attr_tab = None
self.citation_loaded = True
if not source and not citation:
raise NotImplementedError
@@ -381,8 +382,10 @@ class EditSource(EditPrimary):
if templatechanged and self.tmplfields:
#the citation template fields must be changed!
self.tmplfields.reset_template_fields(self.obj.get_template())
- if self.attr_tab:
- self.attr_tab.rebuild_callback()
+ if self.citn_attr_tab:
+ self.citn_attr_tab.rebuild_callback()
+ if self.src_attr_tab:
+ self.src_attr_tab.rebuild_callback()
self.update_attr()
def callback_cite_changed(self):
@@ -451,12 +454,12 @@ class EditSource(EditPrimary):
self._add_tab(notebook, self.repo_tab)
self.track_ref_for_deletion("repo_tab")
- self.attr_tab = SrcAttrEmbedList(self.dbstate,
+ self.src_attr_tab = SrcAttrEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj.get_attribute_list())
- self._add_tab(notebook, self.attr_tab)
- self.track_ref_for_deletion("attr_tab")
+ self._add_tab(notebook, self.src_attr_tab)
+ self.track_ref_for_deletion("src_attr_tab")
self.citedin_tab = CitedInTab(self.dbstate, self.uistate,
self.track, self.obj, self.cite_apply_callback,
@@ -509,10 +512,10 @@ class EditSource(EditPrimary):
self._add_tab(notebook_ref, self.gallery_tab)
self.track_ref_for_deletion("gallery_tab")
- self.attr_tab = SrcAttrEmbedList(self.dbstate, self.uistate, self.track,
+ self.citn_attr_tab = SrcAttrEmbedList(self.dbstate, self.uistate, self.track,
self.citation.get_attribute_list())
- self._add_tab(notebook_ref, self.attr_tab)
- self.track_ref_for_deletion("attr_tab")
+ self._add_tab(notebook_ref, self.citn_attr_tab)
+ self.track_ref_for_deletion("citn_attr_tab")
self.citationref_list = CitationBackRefList(self.dbstate, self.uistate,
self.track,
@@ -837,7 +840,7 @@ class EditSource(EditPrimary):
#trigger update of the tab fields
self.comment_tab.rebuild_callback(self.citation.get_note_list())
self.gallery_tab.rebuild_callback(self.citation.get_media_list())
- self.attr_tab.rebuild_callback(self.citation.get_attribute_list())
+ self.citn_attr_tab.rebuild_callback(self.citation.get_attribute_list())
self.citationref_list.rebuild_callback(
self.db.find_backlink_handles(self.citation.handle))
diff --git a/gramps/plugins/export/exportxml.py b/gramps/plugins/export/exportxml.py
index fd5292e71..61d1443d4 100644
--- a/gramps/plugins/export/exportxml.py
+++ b/gramps/plugins/export/exportxml.py
@@ -208,11 +208,12 @@ class GrampsXmlWriter(UpdateCallback):
repo_len = self.db.get_number_of_repositories()
obj_len = self.db.get_number_of_media_objects()
note_len = self.db.get_number_of_notes()
- tag_len = self.db.get_number_of_tags()
+ tag_len = self.db.get_number_of_tags()
+ template_len = self.db.get_number_of_templates()
total_steps = (person_len + family_len + event_len + citation_len +
source_len + place_len + repo_len + obj_len + note_len +
- tag_len
+ tag_len + template_len
)
self.set_total(total_steps)
@@ -256,6 +257,14 @@ class GrampsXmlWriter(UpdateCallback):
self.update()
self.g.write(" \n")
+ if template_len > 0:
+ self.g.write(" \n")
+ for key in sorted(self.db.get_template_handles()):
+ template = self.db.get_template_from_handle(key)
+ self.write_template(template, 2)
+ self.update()
+ self.g.write(" \n")
+
# Write primary objects
if event_len > 0:
self.g.write(" \n")
@@ -350,6 +359,9 @@ class GrampsXmlWriter(UpdateCallback):
mediapath= self.db.get_mediapath()
if mediapath is not None:
self.write_line("mediapath", mediapath, 2)
+ gedcom_handle = self.db.get_GEDCOM_template_handle()
+ if gedcom_handle is not None:
+ self.write_line("gedcom_template", gedcom_handle, 2)
def write_namemaps(self):
group_map = self.db.get_name_group_keys()
@@ -435,6 +447,22 @@ class GrampsXmlWriter(UpdateCallback):
self.g.write(' priority="%d"' % tag.get_priority())
self.g.write('/>\n')
+ def write_template(self, template, index=2):
+ """
+ Write a template definition.
+ """
+ if not template:
+ return
+
+ sp = " "*index
+ self.write_template_tag('template', template, index)
+ self.write_force_line("tname", template.get_name(), index+1)
+ self.write_line("tdescription", template.get_descr(), index+1)
+ self.write_map_list(template.get_map_dict(), index+1)
+ self.write_te_list(template.get_template_element_list(), index+1)
+
+ self.g.write("%s\n" % sp)
+
def fix(self,line):
try:
l = cuni(line)
@@ -595,7 +623,7 @@ class GrampsXmlWriter(UpdateCallback):
sp = " "*index
self.write_primary_tag("source", source, index)
self.write_force_line("sname", source.get_name(), index+1)
- self.write_line("stemplate", source.get_template(), index+1)
+ self.write_ref("stemplate", source.get_template(), index+1)
self.write_line("sabbrev", source.get_abbreviation(), index+1)
self.write_note_list(source.get_note_list(), index+1)
self.write_media_list(source.get_media_list(), index+1)
@@ -809,6 +837,25 @@ class GrampsXmlWriter(UpdateCallback):
if close:
self.g.write('>\n')
+ def write_template_tag(self, templatename, obj, index=1, close=True):
+ """
+ Write the template attributes common to all table objects.
+ """
+ if not obj:
+ return
+ sp = " " * index
+ try:
+ change_text = ' change="%d"' % obj.get_change_time()
+ except:
+ change_text = ' change="%d"' % 0
+
+ handle_text = ' handle="_%s"' % obj.get_handle()
+
+ obj_text = '%s<%s' % (sp, templatename)
+ self.g.write(obj_text + handle_text + change_text)
+ if close:
+ self.g.write('>\n')
+
def write_family_handle(self,family,index=1):
sp = " "*index
self.write_primary_tag('family',family,index)
@@ -1174,6 +1221,27 @@ class GrampsXmlWriter(UpdateCallback):
)
)
+ def write_map_list(self, map_dict, indent=3):
+ sp = ' ' * indent
+ for (key, value) in list(map_dict.items()):
+ self.g.write('%s\n')
+
+ def write_te_list(self, te_list, index=1):
+ sp = " "*index
+ for te in te_list:
+ self.g.write('%s\n' %
+ (sp, te.get_citation(), te.get_short(), te.get_short_alg())
+ )
+ self.write_line("tename", te.get_name(), index+1)
+ self.write_line("Display", te.get_display(), index+1)
+ self.write_line("Hint", te.get_hint(), index+1)
+ self.write_line("Tooltip", te.get_tooltip(), index+1)
+ self.g.write('%s\n' % sp)
+ pass
+
def write_place_obj(self, place, index=1):
self.write_primary_tag("placeobj", place, index)
diff --git a/gramps/plugins/importer/importxml.py b/gramps/plugins/importer/importxml.py
index b447674f2..1d000b3f7 100644
--- a/gramps/plugins/importer/importxml.py
+++ b/gramps/plugins/importer/importxml.py
@@ -55,7 +55,7 @@ from gramps.gen.lib import (Address, Attribute, AttributeType, ChildRef,
Place, RepoRef, Repository, Researcher, Source,
SrcAttribute, SrcAttributeType,
StyledText, StyledTextTag, StyledTextTagType,
- Surname, Tag, Url)
+ Surname, Tag, Url, SrcTemplate, TemplateElement)
from gramps.gen.db import DbTxn
from gramps.gen.db.write import CLASS_TO_KEY_MAP
from gramps.gen.errors import GrampsImportError
@@ -67,7 +67,7 @@ from gramps.gen.display.name import displayer as name_displayer
from gramps.gen.db.dbconst import (PERSON_KEY, FAMILY_KEY, SOURCE_KEY,
EVENT_KEY, MEDIA_KEY, PLACE_KEY,
REPOSITORY_KEY, NOTE_KEY, TAG_KEY,
- CITATION_KEY)
+ CITATION_KEY, TEMPLATE_KEY)
from gramps.gen.updatecallback import UpdateCallback
from gramps.version import VERSION
from gramps.gen.config import config
@@ -215,7 +215,8 @@ class ImportInfo(object):
Class object that can hold information about the import
"""
keyorder = [PERSON_KEY, FAMILY_KEY, SOURCE_KEY, EVENT_KEY, MEDIA_KEY,
- PLACE_KEY, REPOSITORY_KEY, NOTE_KEY, TAG_KEY, CITATION_KEY]
+ PLACE_KEY, REPOSITORY_KEY, NOTE_KEY, TAG_KEY, CITATION_KEY,
+ TEMPLATE_KEY]
key2data = {
PERSON_KEY : 0,
FAMILY_KEY : 1,
@@ -226,7 +227,8 @@ class ImportInfo(object):
REPOSITORY_KEY: 6,
NOTE_KEY: 7,
TAG_KEY: 8,
- CITATION_KEY: 9
+ CITATION_KEY: 9,
+ TEMPLATE_KEY: 10
}
def __init__(self):
@@ -235,9 +237,9 @@ class ImportInfo(object):
This creates the datastructures to hold info
"""
- self.data_mergecandidate = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}]
- self.data_newobject = [0] * 10
- self.data_unknownobject = [0] * 10
+ self.data_mergecandidate = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]
+ self.data_newobject = [0] * 11
+ self.data_unknownobject = [0] * 11
self.data_families = ''
self.expl_note = ''
self.data_relpath = False
@@ -315,6 +317,7 @@ class ImportInfo(object):
NOTE_KEY : _(' Notes: %d\n'),
TAG_KEY : _(' Tags: %d\n'),
CITATION_KEY : _(' Citations: %d\n'),
+ TEMPLATE_KEY : _(' Source Templates; %d\n'),
}
txt = _("Number of new objects imported:\n")
for key in self.keyorder:
@@ -537,6 +540,7 @@ class GrampsParser(UpdateCallback):
self.attribute = None
self.srcattribute = None
self.placeobj = None
+ self.template = None
self.locations = 0
self.place_map = {}
@@ -708,18 +712,28 @@ class GrampsParser(UpdateCallback):
"source": (self.start_source, self.stop_source),
"sourceref": (self.start_sourceref, self.stop_sourceref),
"sources": (None, None),
+ "SourceTemplates": (None, None),
"spage": (None, self.stop_spage), #deprecated
"spubinfo": (None, self.stop_spubinfo), #deprecated in 1.6.0
"state": (None, self.stop_state),
"stext": (None, self.stop_stext),
"stitle": (None, self.stop_stitle), #deprecated in 1.6.0
"sname": (None, self.stop_sname), #new in 1.6.0
- "stemplate": (None, self.stop_stemplate), #new in 1.6.0
+ "stemplate": (self.start_stemplate, None), #new in 1.6.0
"street": (None, self.stop_street),
"style": (self.start_style, None),
"tag": (self.start_tag, self.stop_tag),
"tagref": (self.start_tagref, None),
"tags": (None, None),
+ "tdescription": (None, self.stop_tdescription),
+ "tefield": (self.start_tefield, self.stop_tefield),
+ "tename": (None, self.stop_tename),
+ "tedisplay": (None, self.stop_tedisplay),
+ "tehint": (None, self.stop_tehint),
+ "tetooltip": (None, self.stop_tetooltip),
+ "template": (self.start_template, self.stop_template),
+ "tmap": (self.start_tmap, None),
+ "tname": (None, self.stop_tname), # Template name
"text": (None, self.stop_text),
"url": (self.start_url, None),
"repository": (self.start_repo, self.stop_repo),
@@ -767,7 +781,8 @@ class GrampsParser(UpdateCallback):
"repository": self.db.get_raw_repository_data,
"media": self.db.get_raw_object_data,
"note": self.db.get_raw_note_data,
- "tag": self.db.get_raw_tag_data}[target]
+ "tag": self.db.get_raw_tag_data,
+ "template": self.db.get_raw_template_data}[target]
raw = get_raw_obj_data(handle)
prim_obj.unserialize(raw)
self.import_handles[orig_handle][target][INSTANTIATED] = True
@@ -795,7 +810,8 @@ class GrampsParser(UpdateCallback):
"repository": self.db.has_repository_handle,
"media": self.db.has_object_handle,
"note": self.db.has_note_handle,
- "tag": self.db.has_tag_handle}[target]
+ "tag": self.db.has_tag_handle,
+ "template": self.db.has_template_handle}[target]
while has_handle_func(handle):
handle = create_id()
self.import_handles[orig_handle] = {target: [handle, False]}
@@ -806,6 +822,8 @@ class GrampsParser(UpdateCallback):
prim_obj.set_handle(handle)
if target == "tag":
self.db.add_tag(prim_obj, self.trans)
+ elif target == "template":
+ self.db.add_template(prim_obj, self.trans)
else:
add_func = {"person": self.db.add_person,
"family": self.db.add_family,
@@ -1807,6 +1825,68 @@ class GrampsParser(UpdateCallback):
self.note_tags[-1].ranges.append((int(attrs['start']),
int(attrs['end'])))
+ def start_template(self, attrs):
+ """
+ Template definition.
+ """
+ # Tag defintion
+ self.template = SrcTemplate()
+ self.inaugurate(attrs['handle'], "template", self.template)
+ self.template.change = int(attrs.get('change', self.change))
+ self.info.add('new-object', TEMPLATE_KEY, self.template)
+ self.template.set_name(attrs.get('tname', _('Unknown when imported')))
+ self.template.set_descr(attrs.get('tdescription', _('Unknown when imported')))
+ return self.template
+
+ def stop_template(self, *tag):
+ self.db.commit_template(self.template, self.trans, self.template.get_change_time())
+ self.template = None
+
+ def stop_tname(self, tag):
+ self.template.set_name(tag)
+
+ def stop_tdescription(self, tag):
+ self.template.set_descr(tag)
+
+ def start_tmap(self, attrs):
+ self.template.set_map_element(attrs["key"], attrs["value"])
+
+ @staticmethod
+ def _conv_bool(val, default):
+ """
+ Converts a string attribute to True or False. If the attribute is absent
+ (val is None) the default value is returned. If the value is "True" then
+ True is returned and vice-versa for False
+ """
+ if val is None:
+ return default
+ if val == "True":
+ return True
+ else:
+ return False
+
+ def start_tefield(self, attrs):
+ self.template_element = TemplateElement()
+ self.template_element.set_citation(self._conv_bool(attrs.get("citation"), False))
+ self.template_element.set_short(self._conv_bool(attrs.get("short"), False))
+ self.template_element.set_short_alg(attrs.get("short_alg", None))
+
+ def stop_tename(self, tag):
+ self.template_element.set_name(tag)
+
+ def stop_tedisplay(self, tag):
+ self.template_element.set_display(tag)
+
+ def stop_tehint(self, tag):
+ self.template_element.set_hint(tag)
+
+ def stop_tetooltip(self, tag):
+ self.template_element.set_tooltip(tag)
+
+ def stop_tefield(self, tag):
+ self.template.add_template_element(self.template_element)
+ self.template_element = None
+
def start_note(self, attrs):
"""
Add a note to db if it doesn't exist yet and assign
@@ -2083,6 +2163,7 @@ class GrampsParser(UpdateCallback):
self.inaugurate_id(attrs.get('id'), SOURCE_KEY, self.source)
self.source.private = bool(attrs.get("priv"))
self.source.change = int(attrs.get('change', self.change))
+ self.source.template = None
self.info.add('new-object', SOURCE_KEY, self.source)
return self.source
@@ -2732,10 +2813,13 @@ class GrampsParser(UpdateCallback):
#store descriptive name of the source
self.source.name = tag
- def stop_stemplate(self, tag):
- #store template of the source
- self.source.template = tag
-
+ def start_stemplate(self, attrs):
+ """
+ Add a template reference to the source object currently being processed
+ """
+ handle = self.inaugurate(attrs['hlink'], "template", SrcTemplate)
+ self.source.set_template(handle)
+
def stop_stitle(self, tag):
#title was deprecated and converted to name and attribute TITLE in 1.6.0
if not self.source.name:
@@ -2754,6 +2838,18 @@ class GrampsParser(UpdateCallback):
self.in_old_sourceref = False
def stop_source(self, *tag):
+ # Template are new at 1.6.0. Prior to 1.6.0, sources (and citations) wll
+ # be GEDCOM style, so the template needs to be set to GEDCOM - if the
+ # GEDCOM template has not alraedy been defined, it needs to be built.
+ if self.__xml_version < '1.6.0':
+ gedcom_handle = self.db.get_GEDCOM_template_handle()
+ if gedcom_handle is None:
+ from gramps.plugins.srctemplates.gedcomtemplate import load_template
+ load_template(self.db)
+ gedcom_handle = self.db.get_GEDCOM_template_handle()
+ self.source.set_template(gedcom_handle)
+ # From xml version 1.6.0, if the template is None, this is intentional,
+ # and there is no template defined.
self.db.commit_source(self.source, self.trans,
self.source.get_change_time())
self.source = None
diff --git a/gramps/plugins/srctemplates/gedcomtemplate.py b/gramps/plugins/srctemplates/gedcomtemplate.py
index 4ada18428..4d8900f8c 100644
--- a/gramps/plugins/srctemplates/gedcomtemplate.py
+++ b/gramps/plugins/srctemplates/gedcomtemplate.py
@@ -47,7 +47,8 @@ _ = glocale.translation.gettext
from gramps.gen.db import DbTxn
from gramps.gen.utils.id import create_id
-from gramps.gen.lib.srctemplate import SrcTemplate, TemplateElement
+from gramps.gen.lib.srctemplate import SrcTemplate
+from gramps.gen.lib.templateelement import TemplateElement
from gramps.gen.utils.citeref import (REF_TYPE_L, REF_TYPE_S, REF_TYPE_F,
GED_TITLE, GED_AUTHOR, GED_PUBINF,
GED_DATE, GED_PAGE)
diff --git a/gramps/plugins/srctemplates/importcsv.py b/gramps/plugins/srctemplates/importcsv.py
index ed1c08d4e..94eb0bc25 100644
--- a/gramps/plugins/srctemplates/importcsv.py
+++ b/gramps/plugins/srctemplates/importcsv.py
@@ -48,7 +48,8 @@ from gramps.gen.db import DbTxn
from gramps.gen.utils.id import create_id
from gramps.gen.lib.srcattrtype import *
from gramps.gen.lib.date import Date
-from gramps.gen.lib.srctemplate import SrcTemplate, TemplateElement
+from gramps.gen.lib.srctemplate import SrcTemplate
+from gramps.gen.lib.templateelement import TemplateElement
from gramps.gen.utils.citeref import (REF_TYPE_L, REF_TYPE_S, REF_TYPE_F,
GED_TITLE, GED_AUTHOR, GED_PUBINF,
GED_DATE, GED_PAGE)
@@ -335,7 +336,7 @@ def load_srctemplate_csv(csvfile, db):
optional = True
shorteralg = SHORTERALG.get(row[SHORTERCOL].strip()) or EMPTY
gedcom_type_text = row[GEDCOMCOL].strip()
- gedcommap = GEDCOMFIELDS.get(row[GEDCOMCOL].strip()) or EMPTY
+ gedcommap = GEDCOMFIELDS.get(row[GEDCOMCOL].strip())
style = STYLES.get(row[STYLECOL].strip()) or EMPTY
if source_type in TYPE2TEMPLATEMAP:
@@ -376,7 +377,6 @@ def load_srctemplate_csv(csvfile, db):
# Setup the mapping. A typical mapping would look like:
# ('EE_Full' : '%(COMPILER)s, "%(TITLE)s", %(TYPE)s, %(WEBSITE CREATOR/OWNER)s, %(WEBSITE)s, (%(URL (DIGITAL LOCATION))s: accessed %(DATE ACCESSED)s), %(ITEM OF INTEREST)s; %(CREDIT LINE)s.')
- target = "EE_" + cite_type_text
if te.get_short():
if field_type.lower().endswith(' (short)'):
txt = field_type
@@ -392,8 +392,8 @@ def load_srctemplate_csv(csvfile, db):
if style == STYLE_QUOTE:
txt = '"' + txt + '"'
elif style == STYLE_QUOTECONT:
- if template.get_map_element(target)[-1] == '"':
- template.set_map_element(target, template.get_map_element(target)[:-1])
+ if template.get_map_element(cite_type)[-1] == '"':
+ template.set_map_element(cite_type, template.get_map_element(cite_type)[:-1])
txt = txt + '"'
else:
txt = '"' + txt + '"'
@@ -401,15 +401,14 @@ def load_srctemplate_csv(csvfile, db):
txt = "" + txt + ""
elif style == STYLE_BOLD:
txt = "" + txt + ""
- template.set_map_element(target, template.get_map_element(target) + txt)
+ template.set_map_element(cite_type, template.get_map_element(cite_type) + txt)
# Setup the GEDCOM fields. These are only stored in the L template
if cite_type == REF_TYPE_L and gedcom_type_text:
- target = "GEDCOM_" + gedcom_type_text
if style == STYLE_QUOTECONT:
- if template.get_map_element(target) and template.get_map_element(target)[-1] == '"':
- template.set_map_element(target, template.get_map_element(target)[:-1])
- template.set_map_element(target, template.get_map_element(target) + txt)
+ if template.get_map_element(gedcommap) and template.get_map_element(gedcommap)[-1] == '"':
+ template.set_map_element(gedcommap, template.get_map_element(gedcommap)[:-1])
+ template.set_map_element(gedcommap, template.get_map_element(gedcommap) + txt)
msg = _("Add template (%s)") % template.get_name()
with DbTxn(msg, db) as trans:
@@ -455,9 +454,8 @@ def load_srctemplate_csv(csvfile, db):
template = TYPE2TEMPLATEMAP[source_type]
for te in [x for x in template.get_template_element_list()
if x.get_citation() and not x.get_short()]:
- target = "GEDCOM_PAGE"
- template.set_map_element(target,
- ", ".join((template.get_map_element(target), txt)))
+ template.set_map_element(GED_PAGE,
+ ", ".join((template.get_map_element(GED_PAGE), txt)))
msg = _("Add template (%s)") % template.get_name()
with DbTxn(msg, db) as trans:
db.commit_template(template, trans)