GEP 18: * read in template data

* manage template via SrcTemplate
        * obtain author/pubinfo from attributes via template


svn: r22469
This commit is contained in:
Benny Malengier 2013-06-02 10:08:26 +00:00
parent be45ac54fe
commit 6e2272bb78
11 changed files with 2836 additions and 2146 deletions

View File

@ -55,6 +55,7 @@ STYLECOL = 12
PRIVACYCOL = 13
OPTCOL = 14
CITE_TYPES = {'F': 'REF_TYPE_F', 'L': 'REF_TYPE_L', 'S': 'REF_TYPE_S'}
GEDCOMFIELDS = {'A': 'GED_AUTHOR', 'T': 'GED_TITLE',
'P': 'GED_PUBINF', 'D': 'GED_DATE'}
SHORTERALG = {'LOC': 'SHORTERALG_LOC', 'YEAR': 'SHORTERALG_YEAR',
@ -106,7 +107,8 @@ with open(csvfilename, 'rb') as csvfile:
if source_type in TYPE2CITEMAP:
assert TYPE2CITEMAP[source_type] ['descr'] == source_descr, source_type + ' ' + TYPE2CITEMAP[source_type] ['descr'] + ' NOT ' + source_descr
else:
TYPE2CITEMAP[source_type] = {'L': [], 'F': [], 'S': [],
TYPE2CITEMAP[source_type] = {'REF_TYPE_L': [], 'REF_TYPE_F': [],
'REF_TYPE_S': [],
'i': indexval, 'descr': source_descr,
'descrcode': source_descr_code}
indexval += 1
@ -119,6 +121,7 @@ with open(csvfilename, 'rb') as csvfile:
shortcite = True
else:
shortcite = False
cite_type = CITE_TYPES[cite_type]
#add field for template to evidence style
field = row[FIELDCOL].strip()
field_type = field.replace(' ', '_').replace("'","")\
@ -148,7 +151,7 @@ with open(csvfilename, 'rb') as csvfile:
shorteralg, gedcommap)]
#if shorttype, we store a type for the short version so user can store
#this
if shortcite and shorteralg == '':
if shortcite and shorteralg == 'EMPTY':
field_type_short = field_type + '_SHORT_VERSION'
if field_type_short in FIELDTYPEMAP:
pass
@ -197,8 +200,8 @@ code += "\n #templates for the source types defined\n"\
code += ' EVIDENCETEMPLATES = {\n'
for source_type in allkeys:
code += " " + source_type + ": {\n"
for val in ['F', 'L', 'S']:
code += " '" + val + "': [\n"
for val in ['REF_TYPE_L', 'REF_TYPE_F', 'REF_TYPE_S']:
code += " " + val + ": [\n"
for field in TYPE2CITEMAP[source_type][val]:
# field is tuple (row[LDELCOL], field_type, row[RDELCOL], row[STYLECOL]
# , private, optional, shorteralg, gedcommap)

View File

@ -55,6 +55,9 @@ from .repo import Repository
from .note import Note
from .citation import Citation
# Logical objects
from .srctemplate import SrcTemplate
# Table objects
from .tag import Tag

View File

@ -36,6 +36,7 @@ from .mediabase import MediaBase
from .notebase import NoteBase
from .tagbase import TagBase
from .srcattrbase import SrcAttributeBase
from .srctemplate import SrcTemplate
from .reporef import RepoRef
from .const import DIFFERENT, EQUAL, IDENTICAL
from ..constfunc import cuni
@ -281,21 +282,37 @@ class Source(MediaBase, NoteBase, SrcAttributeBase, PrimaryObject):
"""
return self.title
def set_author(self, author):
"""Set the author of the Source."""
self.author = author
## def set_author(self, author):
## """Set the author of the Source."""
## self.author = author
def get_author(self):
"""Return the author of the Source."""
return self.author
"""Return the author of the Source.
Author depends on the source template. The logic is:
1. obtain template
2. create author from the 'full' reference
3. if no template, it defaults to GEDCOM, so AUTHOR will be used
"""
attrlist = self.get_attribute_list()
stemp = SrcTemplate(self.get_source_template()[0])
return stemp.author_gedcom(attrlist)
def set_publication_info(self, text):
"""Set the publication information of the Source."""
self.pubinfo = text
## def set_publication_info(self, text):
## """Set the publication information of the Source."""
## self.pubinfo = text
def get_publication_info(self):
"""Return the publication information of the Source."""
return self.pubinfo
"""Return the publication information of the Source.
PubInfo depends on the source template. The logic is:
1. obtain template
2. create pubinfo from the 'full' reference
3. if no template, it defaults to GEDCOM, so PUB_INFO will be used
"""
attrlist = self.get_attribute_list()
stemp = SrcTemplate(self.get_source_template()[0])
return stemp.pubinfo_gedcom(attrlist)
def set_abbreviation(self, abbrev):
"""Set the title abbreviation of the Source."""

View File

@ -53,21 +53,31 @@ class SrcAttributeBase(AttributeRootBase):
This is the value of the first source template in the attribute list
If not known UNKNOWN is returned as key, which is integer. Other keys
will be str.
:rtype tuple: (key, translated_string, english_string)
:rtype tuple: (key, description, string_key_as stored)
"""
templ = SrcAttributeType.UNKNOWN
#no template is UNKNOWN!
templ = SrcAttributeType.UNKNOWN
for attr in self.attribute_list:
if int(attr.get_type()) == SrcAttributeType.SRCTEMPLATE:
val = attr.get_value()
try:
templ = SrcAttributeType.E2I_SRCTEMPLATEMAP[val]
templ = SrcAttributeType.K2I_SRCTEMPLATEMAP[val]
except KeyError:
# a template not in the predefined list. convert to unknown
print ('SrcAttributeType: Keyerror "', val,
print ('SrcAttributeBase: Keyerror "', val,
'"for now UNKNOWN taken, later custom templates?')
break
return (templ, SrcAttributeType.I2S_SRCTEMPLATEMAP[templ],
SrcAttributeType.I2E_SRCTEMPLATEMAP[templ])
try:
retval = (templ, SrcAttributeType.I2S_SRCTEMPLATEMAP[templ],
SrcAttributeType.I2K_SRCTEMPLATEMAP[templ])
except KeyError:
#templ is not present, return the default GEDCOM value as actual
#template
templ = SrcAttributeType.UNKNOWN
retval = (templ,
SrcAttributeType.I2S_SRCTEMPLATEMAP[SrcAttributeType.UNKNOWN],
SrcAttributeType.I2K_SRCTEMPLATEMAP[SrcAttributeType.UNKNOWN])
return retval
def set_source_template(self, tempindex, tempcustom_str):
"""
@ -94,8 +104,7 @@ class SrcAttributeBase(AttributeRootBase):
(tempindex == SrcAttributeType.CUSTOM and tempcustom_str.strip() == ''):
self.remove_attribute(attrtemp)
elif not (tempindex == SrcAttributeType.CUSTOM):
attr.set_value(SrcAttributeType.I2E_SRCTEMPLATEMAP[tempindex])
attrtemp.set_value(SrcAttributeType.I2K_SRCTEMPLATEMAP[tempindex])
else:
#custom key, store string as is
attr.set_value(tempindex)
attrtemp.set_value(tempindex)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,300 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2013 Benny Malengier
#
# 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.
"""
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from .srcattrtype import (SrcAttributeType, REF_TYPE_F, REF_TYPE_S, REF_TYPE_L,
GED_AUTHOR, GED_TITLE, GED_PUBINF)
#-------------------------------------------------------------------------
#
# SrcTemplate class
#
#-------------------------------------------------------------------------
class SrcTemplate(object):
"""
Sources conform to a certain template, which governs their styling when
used in reports.
The SrcTemplate object holds all the logic to do the actual styling.
Predefined templates themself are stored in SrcAttributeType, or in extra
xml files with defenitions
The structure typically is a dictionary as follows:
{
REF_TYPE_L: [
('', AUTHOR, '.', EMPTY, False, False, EMPTY, GED_AUTHOR),
('', TITLE, '.', STYLE_QUOTE, False, False, EMPTY, GED_TITLE),
('', PUB_INFO, '', EMPTY, False, False, EMPTY, GED_PUBINF),
],
REF_TYPE_F: [
('', AUTHOR, ',', EMPTY, False, False, EMPTY, EMPTY),
('', TITLE, ',', STYLE_QUOTE, False, False, EMPTY, EMPTY),
('', PUB_INFO, '.', EMPTY, False, False, EMPTY, EMPTY),
('', DATE, ' -', EMPTY, False, False, EMPTY, EMPTY),
('', PAGE6S9, '.', EMPTY, False, False, EMPTY, EMPTY),
],
REF_TYPE_S: [
('', AUTHOR, ',', EMPTY, False, False, EMPTY, EMPTY),
('', DATE, ' -', EMPTY, False, False, EMPTY, EMPTY),
('', PAGE6S9, '.', EMPTY, False, False, EMPTY, EMPTY),
],
}
This defines the 3 source reference types. A reference type consists of
a list of tuples with fieldsdescriptions.
A fielddescription consists of the columns:
0/ left delimiter
1/ field, this is a SrcAttributeType
2/ right delimiter
3/ style to use
4/ bool: if field should be private by default on creation
5/ bool: if optional field
6/ shortening algorithm to use, EMPTY indicates no transformation
7/ the REF_TYPE_L reference maps to GEDCOM fields on export via
this column. GEDCOM contains Title, Author and Pub.Info field
"""
def __init__(self, template_key):
"""
Initialize the template from a given key.
If key is an integer, EVIDENCETEMPLATES is used of SrtAttrType.
If Key is string, it is first searched as the Key of EVIDENCETEMPLATES,
otherwise from xml templates (not implemented yet !!)
"""
self.set_template_key(template_key)
def empty(self):
"""
remove all computed data
"""
self.refL = None
self.refF = None
self.refS = None
# attrmap will hold mapping of field to normal value and short value
# short value will be None if not given
self.attrmap = {}
def set_template_key(self, template_key):
"""
Change to the new template key for reference styling
"""
self.empty()
if template_key == SrcAttributeType.UNKNOWN:
#for key unknown we use styling according to GEDCOM
template_key = SrcAttributeType.GEDCOM
if isinstance(template_key, int):
self.tempstruct = SrcAttributeType.EVIDENCETEMPLATES[template_key]
else:
try:
self.tempstruct = SrcAttributeType.EVIDENCETEMPLATES[
K2I_SRCTEMPLATEMAP[template_key]]
except:
#
print ('SrcTemplate: Keyerror "', template_key,
'", custom templates templates not implemented?')
raise NotImplementedError
def set_attr_list(self, attr_list):
"""
Set the attribute list of this template. Setting once for difference
references saves some time
"""
self.empty()
self.attr_list = attr_list or []
# store attributes in a dict last to first. this overwrites data so first
# attribute will be the one taken if duplicates are present
for attr in attr_list[::-1]:
lower = False
typ = attr.get_type()
key = int(typ)
keystr = typ.xml_str().lower()
if keystr.lower().endswith(' (short)'):
#a shorter version, we store with base type
key = int(SrcAttributeType(keystr[:-8]))
lower = True
if key == SrcAttributeType.CUSTOM:
key = str(typ)
if key in self.attrmap:
if lower:
self.attrmap[key] = (self.attrmap[key][0], attr.get_value())
else:
self.attrmap[key] = (attr.get_value(), self.attrmap[key][1])
else:
if lower:
#store also in normal already value of short
self.attrmap[key] = (attr.get_value(), attr.get_value())
else:
self.attrmap[key] = (attr.get_value(), None)
def reference_L(self, attr_list=None):
"""
Return the list reference based on the passed source attribute list
If attr_list is None, same list as before is used.
"""
if attr_list:
self.set_attr_list(attr_list)
if self.refL is not None:
return self.refL
self.refL = self._reference(REF_TYPE_L)
return self.refL
def reference_S(self, attr_list=None):
"""
Return the short reference based on the passed source attribute list
If attr_list is None, same list as before is used.
"""
if attr_list:
self.set_attr_list(attr_list)
if self.refS is not None:
return self.refS
self.refS = self._reference(REF_TYPE_S)
return self.refS
def reference_F(self, attr_list=None):
"""
Return the full reference based on the passed source attribute list
If attr_list is None, same list as before is used.
"""
if attr_list:
self.set_attr_list(attr_list)
if self.refF is not None:
return self.refF
self.refF = self._reference(REF_TYPE_F)
return self.refF
def _reference(self, reftype, gedcomfield=None):
"""
Compute the reference based on data present.
At the moment no style is applied!
"""
reflist = self.tempstruct[reftype]
# reflist is typically a list like
# [ ('', AUTHOR, ',', EMPTY, False, False, EMPTY, EMPTY),
# ('', TITLE, ',', STYLE_QUOTE, False, False, EMPTY, EMPTY),
# ('', PUB_INFO, '.', EMPTY, False, False, EMPTY, EMPTY),
# ('', DATE, ' -', EMPTY, False, False, EMPTY, EMPTY),
# ('', PAGE6S9, '.', EMPTY, False, False, EMPTY, EMPTY),
# ]
ref = ['']
for (ldel, field, rdel, style, priv, opt, short, gedcom) in reflist:
if not gedcomfield is None and gedcom != gedcomfield:
continue
customshort = False
#left delimiter
if ldel in ['(', '[', '{']:
ref += ['']
ref[-1] += ldel
ldeltodo = ''
else:
ldeltodo = ldel
val = self.attrmap.get(field)
#field
field = ''
if val is not None:
if reftype == REF_TYPE_S and val[1] is not None:
customshort = True
field = val[1]
else:
field = val[0]
if short and not customshort:
#we apply the shortening algorithm
## TODO: not implemented yet
pass
if field:
ref[-1] += ldeltodo + field
#right delimiter
if ')' in rdel:
if len(ref[-1] [ref[-1].find('('):]) > 0 :
newval = ref[-1] + rdel
ref = ref[:-1]
ref[-1] += newval
else:
#no data inside of delimiter, we remove it entirely
ref = ref[:-1]
elif ']' in rdel:
if len(ref[-1] [ref[-1].find(']'):]) > 0 :
newval = ref[-1] + rdel
ref = ref[:-1]
ref[-1] += newval
else:
#no data inside of delimiter, we remove it entirely
ref = ref[:-1]
elif '}' in rdel:
if len(ref[-1] [ref[-1].find('}'):]) > 0 :
newval = ref[-1] + rdel
ref = ref[:-1]
ref[-1] += newval
else:
#no data inside of delimiter, we remove it entirely
ref = ref[:-1]
else:
# we add rdel
if not ref[-1]:
#nothing there, don't add delimiter
pass
elif len(rdel) and rdel[0] == '.':
curval = ref[-1]
if len(curval) and curval[-1] == '.':
pass
elif len(curval) and curval[-1] == ',':
ref[-1] = ref[-1][:-1] + rdel
else:
ref[-1] = ref[-1] + rdel
elif len(rdel) and rdel[0] == ',':
curval = ref[-1]
if len(curval) and curval[-1] == '.':
pass
elif len(curval) and curval[-1] == ',':
pass
else:
ref[-1] = ref[-1] + rdel
else:
ref[-1] = ref[-1] + rdel
ref = ''.join(ref)
return ref
def author_gedcom(self, attr_list=None):
if attr_list:
self.set_attr_list(attr_list)
return self._reference(REF_TYPE_L, GED_AUTHOR)
def title_gedcom(self, attr_list=None):
if attr_list:
self.set_attr_list(attr_list)
return self._reference(REF_TYPE_L, GED_TITLE)
def pubinfo_gedcom(self, attr_list=None):
if attr_list:
self.set_attr_list(attr_list)
return self._reference(REF_TYPE_L, GED_PUBINF)

View File

@ -41,7 +41,8 @@ from gi.repository import Gtk
# Gramps libraries
#
#-------------------------------------------------------------------------
from gramps.gen.lib.srcattrtype import SrcAttributeType
from gramps.gen.lib.srcattrtype import (SrcAttributeType, REF_TYPE_F,
REF_TYPE_S, REF_TYPE_L)
from gramps.gen.lib.srcattribute import SrcAttribute
from ...autocomp import StandardCustomSelector
from ...widgets.srctemplatetreeview import SrcTemplateTreeView
@ -138,7 +139,7 @@ class SrcTemplateTab(GrampsTab):
self.inpts = []
row = 1
# now add new fields
for fielddef in template['F']:
for fielddef in template[REF_TYPE_F]:
self.gridfields.insert_row(row)
row += 1
field = fielddef[1]
@ -178,7 +179,6 @@ class SrcTemplateTab(GrampsTab):
Set attribute of source of type srcattrtype (which is integer!) to
value. If not present, create attribute. If value == '', remove
"""
print 'set field called', value, srcattrtype
src = self.src
value = value.strip()
foundattr = None

View File

@ -82,8 +82,8 @@ class EditPrimary(ManagedWindow, DbGUIElement):
self._local_init()
self._set_size()
self._create_tabbed_pages()
self._setup_fields()
self._create_tabbed_pages()
self._connect_signals()
#if the database is changed, all info shown is invalid and the window
# should close

View File

@ -45,7 +45,7 @@ from gi.repository import Gtk, Gdk
# gramps modules
#
#-------------------------------------------------------------------------
from gramps.gen.lib import NoteType, Source
from gramps.gen.lib import NoteType, Source, SrcTemplate
from gramps.gen.db import DbTxn
from gramps.gen.utils.file import media_path_full
from ..thumbnails import get_thumbnail_image
@ -58,6 +58,7 @@ from .displaytabs import (NoteTab, GalleryTab, SrcAttrEmbedList,
CitationBackRefList, RepoEmbedList)
from ..widgets import MonitoredEntry, PrivacyButton, MonitoredTagList
from ..dialog import ErrorDialog
from ..utils import is_right_click, open_file_with_default_application
from ..glade import Glade
#-------------------------------------------------------------------------
@ -213,6 +214,7 @@ class EditSource(EditPrimary):
"""
if self.attr_tab:
self.attr_tab.rebuild_callback()
self.update_attr()
def _create_tabbed_pages(self):
notebook = self.glade.get_object('notebook')

View File

@ -160,6 +160,7 @@
<object class="UndoableEntry" id="source_title">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Title of the source.</property>
<property name="invisible_char">•</property>
</object>
<packing>
@ -244,6 +245,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">•</property>
<property name="tooltip_text" translatable="yes">A unique ID to identify the source</property>
</object>
<packing>
<property name="expand">True</property>
@ -531,6 +533,7 @@
<object class="UndoableEntry" id="abbrev">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Provide the short identifier you use for local sorting, filing, and retrieving source records.</property>
<property name="invisible_char">•</property>
</object>
<packing>
@ -649,6 +652,27 @@
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>

View File

@ -75,9 +75,9 @@ class SrcTemplateTreeView(Gtk.TreeView):
"""
srcattrt = SrcAttributeType()
self.I2Str = srcattrt.I2S_SRCTEMPLATEMAP
self.I2Key = srcattrt.I2E_SRCTEMPLATEMAP
self.I2Key = srcattrt.I2K_SRCTEMPLATEMAP
self.Str2I = srcattrt.S2I_SRCTEMPLATEMAP
self.Key2I = srcattrt.E2I_SRCTEMPLATEMAP
self.Key2I = srcattrt.K2I_SRCTEMPLATEMAP
self.Key2Path = {}
# store (index, key, cat, cat_type, src_type)
self.model = Gtk.TreeStore(int, str, str)
@ -87,11 +87,18 @@ class SrcTemplateTreeView(Gtk.TreeView):
prevstrval = ['', '']
for alltext in alltexts:
vals = alltext.split('-')
lastval = vals[-1]
if len(vals) > 3:
vals = [vals[0], vals[1], ' - '.join(vals[2:])]
lastval = vals[2]
vals = [x.strip() for x in vals]
#lastval is last non '' value
lastval = vals[-1]
if not lastval:
lastval = vals[-2]
if not lastval:
lastval = vals[-3]
if vals[0] == 'All':
print lastval
print vals
truevals = ['','','']
if len(vals) < 3 :
truevals[:len(vals)] = vals[:]
@ -121,6 +128,7 @@ class SrcTemplateTreeView(Gtk.TreeView):
#only new sublevel1 needed
parentiterlev1 = self.model.append(None, [-10, '', vals[0]])
parentiter = parentiterlev1
print 'here', row, alltext
iter = self.model.append(parentiter, row)
else:
#only a top level