2009-11-23 03:58:30 +05:30
|
|
|
# Gramps - a GTK+/GNOME based genealogy program
|
|
|
|
#
|
|
|
|
# Copyright (C) 2009 Douglas S. Blank <doug.blank@gmail.com>
|
|
|
|
#
|
|
|
|
# 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$
|
|
|
|
#
|
|
|
|
|
|
|
|
""" Django/Gramps utilities """
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
2009-12-21 03:56:45 +05:30
|
|
|
# Python Modules
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
import locale
|
2010-01-01 21:12:31 +05:30
|
|
|
import sys
|
2012-05-29 19:09:55 +05:30
|
|
|
import re
|
2012-05-25 20:30:39 +05:30
|
|
|
import datetime
|
2012-05-29 19:09:55 +05:30
|
|
|
from HTMLParser import HTMLParser
|
2009-12-21 03:56:45 +05:30
|
|
|
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Django Modules
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
from django.utils.safestring import mark_safe
|
|
|
|
from django.contrib.contenttypes.models import ContentType
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Gramps-Connect Modules
|
2009-11-23 03:58:30 +05:30
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
2011-10-16 02:00:34 +05:30
|
|
|
import webapp.grampsdb.models as models
|
|
|
|
import webapp.grampsdb.forms as forms
|
|
|
|
from webapp import libdjango
|
|
|
|
from webapp.dbdjango import DbDjango
|
2009-12-21 03:56:45 +05:30
|
|
|
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Gramps Modules
|
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
2009-11-15 04:18:30 +05:30
|
|
|
from Simple import SimpleTable, SimpleAccess, make_basic_stylesheet
|
|
|
|
import Utils
|
|
|
|
import DbState
|
2012-05-26 07:18:59 +05:30
|
|
|
from gen.datehandler import displayer, parser
|
2009-11-15 04:18:30 +05:30
|
|
|
from gen.lib.date import Date as GDate, Today
|
2009-12-21 03:56:45 +05:30
|
|
|
import gen.lib
|
2009-12-22 06:51:13 +05:30
|
|
|
from gen.utils import get_birth_or_fallback, get_death_or_fallback
|
2009-11-15 04:18:30 +05:30
|
|
|
from gen.plug import BasePluginManager
|
|
|
|
from cli.grampscli import CLIManager
|
|
|
|
|
2009-12-29 08:52:03 +05:30
|
|
|
_ = lambda msg: msg
|
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
util_filters = [
|
|
|
|
'nbsp',
|
2012-05-26 05:11:47 +05:30
|
|
|
'date_as_text',
|
2010-01-01 20:46:20 +05:30
|
|
|
'render_name',
|
2009-12-27 23:53:59 +05:30
|
|
|
]
|
|
|
|
|
|
|
|
util_tags = [
|
2010-01-01 20:46:20 +05:30
|
|
|
'render',
|
2009-12-27 23:53:59 +05:30
|
|
|
"get_person_from_handle",
|
|
|
|
"event_table",
|
|
|
|
"name_table",
|
2012-05-15 20:15:47 +05:30
|
|
|
"surname_table",
|
2011-12-12 09:13:58 +05:30
|
|
|
"citation_table",
|
2009-12-27 23:53:59 +05:30
|
|
|
"source_table",
|
|
|
|
"note_table",
|
|
|
|
"attribute_table",
|
|
|
|
"address_table",
|
|
|
|
"gallery_table",
|
|
|
|
"internet_table",
|
|
|
|
"association_table",
|
|
|
|
"lds_table",
|
|
|
|
"reference_table",
|
|
|
|
"children_table",
|
|
|
|
"make_button",
|
|
|
|
]
|
|
|
|
|
2009-11-23 03:58:30 +05:30
|
|
|
#------------------------------------------------------------------------
|
|
|
|
#
|
2009-12-26 11:10:32 +05:30
|
|
|
# Module Constants
|
2009-11-23 03:58:30 +05:30
|
|
|
#
|
|
|
|
#------------------------------------------------------------------------
|
2009-11-15 04:18:30 +05:30
|
|
|
dji = libdjango.DjangoInterface()
|
2012-05-26 07:18:59 +05:30
|
|
|
dd = displayer.display
|
|
|
|
dp = parser.parse
|
2012-05-26 05:11:47 +05:30
|
|
|
db = DbDjango()
|
2009-11-15 04:18:30 +05:30
|
|
|
|
|
|
|
def register_plugins():
|
|
|
|
dbstate = DbState.DbState()
|
|
|
|
climanager = CLIManager(dbstate, False) # don't load db
|
2010-08-08 18:46:23 +05:30
|
|
|
climanager.do_reg_plugins(dbstate, None)
|
2009-11-15 04:18:30 +05:30
|
|
|
pmgr = BasePluginManager.get_instance()
|
|
|
|
return pmgr
|
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def get_person_from_handle(db, handle):
|
|
|
|
# db is a Gramps Db interface
|
|
|
|
# handle is a Person Handle
|
|
|
|
try:
|
|
|
|
return db.get_person_from_handle(handle)
|
|
|
|
except:
|
2010-01-01 21:12:31 +05:30
|
|
|
print >> sys.stderr, "error in get_person_from_handle:"
|
2009-12-29 08:52:03 +05:30
|
|
|
import sys, traceback
|
|
|
|
cla, exc, trbk = sys.exc_info()
|
2010-01-01 21:12:31 +05:30
|
|
|
print >> sys.stderr, _("Error") + (" : %s %s" %(cla, exc))
|
2009-12-29 08:52:03 +05:30
|
|
|
traceback.print_exc()
|
2009-12-27 23:53:59 +05:30
|
|
|
return None
|
|
|
|
|
2009-11-15 04:18:30 +05:30
|
|
|
def probably_alive(handle):
|
2009-12-29 08:52:03 +05:30
|
|
|
return False
|
2009-12-06 10:39:43 +05:30
|
|
|
person = db.get_person_from_handle(handle)
|
|
|
|
return Utils.probably_alive(person, db)
|
2009-11-15 04:18:30 +05:30
|
|
|
|
2009-11-22 04:48:35 +05:30
|
|
|
def format_number(number, with_grouping=True):
|
|
|
|
# FIXME: should be user's setting
|
|
|
|
locale.setlocale(locale.LC_ALL, "en_US.utf8")
|
2011-12-06 19:22:06 +05:30
|
|
|
if number != "":
|
|
|
|
return locale.format("%d", number, with_grouping)
|
|
|
|
else:
|
|
|
|
return locale.format("%d", 0, with_grouping)
|
2009-11-22 04:48:35 +05:30
|
|
|
|
2011-12-12 17:53:28 +05:30
|
|
|
def table_count(table, with_grouping=True):
|
|
|
|
# FIXME: should be user's setting
|
|
|
|
locale.setlocale(locale.LC_ALL, "en_US.utf8")
|
|
|
|
if table == "person":
|
|
|
|
number = models.Person.objects.count()
|
|
|
|
elif table == "family":
|
|
|
|
number = models.Family.objects.count()
|
|
|
|
elif table == "event":
|
|
|
|
number = models.Event.objects.count()
|
|
|
|
elif table == "note":
|
|
|
|
number = models.Note.objects.count()
|
|
|
|
elif table == "media":
|
|
|
|
number = models.Media.objects.count()
|
|
|
|
elif table == "citation":
|
|
|
|
number = models.Citation.objects.count()
|
|
|
|
elif table == "source":
|
|
|
|
number = models.Source.objects.count()
|
|
|
|
elif table == "place":
|
|
|
|
number = models.Place.objects.count()
|
|
|
|
elif table == "repository":
|
|
|
|
number = models.Repository.objects.count()
|
|
|
|
elif table == "tag":
|
|
|
|
number = models.Tag.objects.count()
|
|
|
|
else:
|
|
|
|
return "[unknown table]"
|
|
|
|
return locale.format("%d", number, with_grouping)
|
|
|
|
|
2009-12-06 23:05:51 +05:30
|
|
|
def nbsp(string):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
if string:
|
2009-12-07 00:08:19 +05:30
|
|
|
return string
|
2009-12-06 23:05:51 +05:30
|
|
|
else:
|
|
|
|
return mark_safe(" ")
|
|
|
|
|
2009-11-15 04:18:30 +05:30
|
|
|
class Table(object):
|
|
|
|
"""
|
|
|
|
>>> table = Table()
|
|
|
|
>>> table.columns("Col1", "Col2", "Col3")
|
|
|
|
>>> table.row("1", "2", "3")
|
|
|
|
>>> table.row("4", "5", "6")
|
|
|
|
>>> table.get_html()
|
|
|
|
"""
|
|
|
|
def __init__(self):
|
2010-01-24 19:31:36 +05:30
|
|
|
self.db = DbDjango()
|
2009-11-15 04:18:30 +05:30
|
|
|
self.access = SimpleAccess(self.db)
|
|
|
|
self.table = SimpleTable(self.access)
|
|
|
|
class Doc(object):
|
|
|
|
def __init__(self, doc):
|
|
|
|
self.doc = doc
|
|
|
|
# None is paperstyle, which is ignored:
|
2009-11-23 07:09:29 +05:30
|
|
|
self.doc = Doc(HtmlDoc.HtmlDoc(make_basic_stylesheet(Table={"set_width":95}), None))
|
2009-11-15 04:18:30 +05:30
|
|
|
self.doc.doc._backend = HtmlBackend()
|
|
|
|
# You can set elements id, class, etc:
|
2011-10-13 06:59:46 +05:30
|
|
|
self.doc.doc.htmllist += [Html('div', class_="content", id="Gallery", style="overflow: auto; height:150px; background-color: #261803;")]
|
2009-11-15 04:18:30 +05:30
|
|
|
|
|
|
|
def columns(self, *args):
|
|
|
|
self.table.columns(*args)
|
|
|
|
|
|
|
|
def row(self, *args):
|
2010-01-22 00:12:53 +05:30
|
|
|
self.table.row(*map(nbsp, args))
|
2009-11-15 04:18:30 +05:30
|
|
|
|
2009-12-06 21:27:53 +05:30
|
|
|
def link(self, object_type_name, handle):
|
|
|
|
self.table.set_link_col((object_type_name, handle))
|
|
|
|
|
2009-12-17 05:34:22 +05:30
|
|
|
def links(self, links):
|
|
|
|
"""
|
|
|
|
A list of (object_type_name, handle) pairs, one per row.
|
|
|
|
"""
|
|
|
|
self.table.set_link_col(links)
|
|
|
|
|
2009-11-15 04:18:30 +05:30
|
|
|
def get_html(self):
|
2009-12-06 23:05:51 +05:30
|
|
|
# The HTML writer escapes data:
|
2009-11-15 04:18:30 +05:30
|
|
|
self.table.write(self.doc) # forces to htmllist
|
2009-12-06 23:05:51 +05:30
|
|
|
# We have a couple of HTML bits that we want to unescape:
|
|
|
|
return str(self.doc.doc.htmllist[0]).replace("&nbsp;", " ")
|
2009-11-15 04:18:30 +05:30
|
|
|
|
|
|
|
_ = lambda text: text
|
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def make_button(text, url, *args):
|
|
|
|
url = url % args
|
2012-05-15 20:15:47 +05:30
|
|
|
#return """[ <a href="%s">%s</a> ] """ % (url, text)
|
|
|
|
return """<input type="button" value="%s" onclick="document.location.href='%s'"/>""" % (text, url)
|
2009-12-20 07:27:17 +05:30
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def event_table(obj, user, action, url=None, *args):
|
2009-12-20 07:27:17 +05:30
|
|
|
retval = ""
|
2009-11-15 04:18:30 +05:30
|
|
|
table = Table()
|
|
|
|
table.columns(_("Description"),
|
|
|
|
_("Type"),
|
|
|
|
_("ID"),
|
|
|
|
_("Date"),
|
|
|
|
_("Place"),
|
|
|
|
_("Role"))
|
2009-11-19 08:11:37 +05:30
|
|
|
if user.is_authenticated():
|
2009-12-27 23:53:59 +05:30
|
|
|
obj_type = ContentType.objects.get_for_model(obj)
|
2009-11-19 08:11:37 +05:30
|
|
|
event_ref_list = models.EventRef.objects.filter(
|
2009-12-27 23:53:59 +05:30
|
|
|
object_id=obj.id,
|
2009-11-19 08:11:37 +05:30
|
|
|
object_type=obj_type).order_by("order")
|
|
|
|
event_list = [(obj.ref_object, obj) for obj in event_ref_list]
|
|
|
|
for (djevent, event_ref) in event_list:
|
|
|
|
table.row(
|
2011-12-13 04:51:13 +05:30
|
|
|
djevent.description or str(djevent),
|
2009-11-19 08:11:37 +05:30
|
|
|
table.db.get_event_from_handle(djevent.handle),
|
|
|
|
djevent.gramps_id,
|
|
|
|
display_date(djevent),
|
|
|
|
get_title(djevent.place),
|
|
|
|
str(event_ref.role_type))
|
2009-12-20 07:27:17 +05:30
|
|
|
retval += table.get_html()
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add event"), (url % args))
|
2009-12-27 23:53:59 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
2009-12-20 07:27:17 +05:30
|
|
|
return retval
|
2009-11-15 04:18:30 +05:30
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def name_table(obj, user, action, url=None, *args):
|
2009-12-20 07:27:17 +05:30
|
|
|
retval = ""
|
2009-11-16 04:17:43 +05:30
|
|
|
table = Table()
|
|
|
|
table.columns(_("Name"),
|
|
|
|
_("Type"),
|
|
|
|
_("Group As"),
|
|
|
|
_("Source"),
|
|
|
|
_("Note Preview"))
|
2009-11-19 08:11:37 +05:30
|
|
|
if user.is_authenticated():
|
2009-12-17 05:34:22 +05:30
|
|
|
links = []
|
2009-12-27 23:53:59 +05:30
|
|
|
for name in obj.name_set.all().order_by("order"):
|
2009-11-19 08:11:37 +05:30
|
|
|
obj_type = ContentType.objects.get_for_model(name)
|
2011-12-12 18:39:44 +05:30
|
|
|
citationq = dji.CitationRef.filter(object_type=obj_type,
|
|
|
|
object_id=name.id).count() > 0
|
2009-11-19 08:11:37 +05:30
|
|
|
note_refs = dji.NoteRef.filter(object_type=obj_type,
|
|
|
|
object_id=name.id)
|
|
|
|
note = ""
|
|
|
|
if note_refs.count() > 0:
|
2009-12-20 07:27:17 +05:30
|
|
|
try:
|
|
|
|
note = dji.Note.get(id=note_refs[0].object_id).text[:50]
|
|
|
|
except:
|
|
|
|
note = None
|
2009-11-19 08:11:37 +05:30
|
|
|
table.row(make_name(name, user),
|
2010-01-01 20:46:20 +05:30
|
|
|
str(name.name_type) + ["", " (preferred)"][int(name.preferred)],
|
2009-11-19 08:11:37 +05:30
|
|
|
name.group_as,
|
2011-12-12 18:39:44 +05:30
|
|
|
["No", "Yes"][citationq],
|
2009-11-19 08:11:37 +05:30
|
|
|
note)
|
2009-12-27 23:53:59 +05:30
|
|
|
links.append(('URL',
|
|
|
|
# url is "/person/%s/name"
|
|
|
|
(url % name.person.handle) + ("/%s" % name.order)))
|
2009-12-17 05:34:22 +05:30
|
|
|
table.links(links)
|
2009-12-20 07:27:17 +05:30
|
|
|
retval += table.get_html()
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add name"), (url % args))
|
2009-12-27 23:53:59 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
2009-12-20 07:27:17 +05:30
|
|
|
return retval
|
2009-11-16 04:17:43 +05:30
|
|
|
|
2012-05-15 20:15:47 +05:30
|
|
|
def surname_table(obj, user, action, url=None, *args):
|
|
|
|
person_handle = args[0]
|
|
|
|
order = args[1]
|
|
|
|
retval = ""
|
|
|
|
table = Table()
|
2012-05-24 22:52:14 +05:30
|
|
|
table.columns(_("Order"), _("Surname"),)
|
2012-05-15 20:15:47 +05:30
|
|
|
if user.is_authenticated():
|
2012-05-24 22:52:14 +05:30
|
|
|
try:
|
|
|
|
name = obj.name_set.filter(order=order)[0]
|
|
|
|
except:
|
|
|
|
name = None
|
|
|
|
if name:
|
|
|
|
links = []
|
2012-05-25 02:21:46 +05:30
|
|
|
for surname in name.surname_set.all().order_by("order"):
|
|
|
|
table.row(str(surname.order), surname.surname)
|
2012-05-24 22:52:14 +05:30
|
|
|
links.append(('URL',
|
|
|
|
# url is "/person/%s/name/%s/surname"
|
2012-05-25 02:21:46 +05:30
|
|
|
(url % args) + ("/%s" % surname.order)))
|
2012-05-24 22:52:14 +05:30
|
|
|
table.links(links)
|
|
|
|
retval += table.get_html()
|
|
|
|
else:
|
|
|
|
retval += "<p id='error'>No such name order = %s</p>" % order
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add surname"), (url % args))
|
2012-05-15 20:15:47 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
|
|
|
return retval
|
|
|
|
|
2009-12-26 11:10:32 +05:30
|
|
|
def source_table(obj, user, action, url=None, *args):
|
2009-12-20 07:27:17 +05:30
|
|
|
retval = ""
|
2009-11-16 04:17:43 +05:30
|
|
|
table = Table()
|
|
|
|
table.columns(_("ID"),
|
|
|
|
_("Title"),
|
|
|
|
_("Author"),
|
|
|
|
_("Page"))
|
2009-11-19 08:11:37 +05:30
|
|
|
if user.is_authenticated():
|
2009-12-26 11:10:32 +05:30
|
|
|
obj_type = ContentType.objects.get_for_model(obj)
|
2011-12-12 18:39:44 +05:30
|
|
|
citation_refs = dji.CitationRef.filter(object_type=obj_type,
|
|
|
|
object_id=obj.id)
|
|
|
|
for citation_ref in citation_refs:
|
|
|
|
if citation_ref.citation:
|
|
|
|
if citation_ref.citation.source:
|
|
|
|
source = citation_ref.citation.source
|
|
|
|
table.row(source,
|
2012-05-16 19:19:53 +05:30
|
|
|
source.title,
|
|
|
|
source.author,
|
|
|
|
citation_ref.citation.page,
|
2011-12-12 18:39:44 +05:30
|
|
|
)
|
2009-12-20 07:27:17 +05:30
|
|
|
retval += table.get_html()
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add source"), (url % args))
|
2009-12-27 23:53:59 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
2009-12-20 07:27:17 +05:30
|
|
|
return retval
|
2009-11-16 04:17:43 +05:30
|
|
|
|
2011-12-12 09:13:58 +05:30
|
|
|
def citation_table(obj, user, action, url=None, *args):
|
|
|
|
retval = ""
|
|
|
|
table = Table()
|
|
|
|
table.columns(_("ID"),
|
|
|
|
_("Confidence"),
|
|
|
|
_("Page"))
|
|
|
|
if user.is_authenticated():
|
|
|
|
obj_type = ContentType.objects.get_for_model(obj)
|
|
|
|
citation_refs = dji.CitationRef.filter(object_type=obj_type,
|
|
|
|
object_id=obj.id)
|
|
|
|
for citation_ref in citation_refs:
|
2011-12-12 18:39:44 +05:30
|
|
|
if citation_ref.citation:
|
2011-12-13 04:51:13 +05:30
|
|
|
citation = table.db.get_citation_from_handle(
|
|
|
|
citation_ref.citation.handle)
|
2011-12-12 18:39:44 +05:30
|
|
|
table.row(citation,
|
|
|
|
str(citation.confidence),
|
|
|
|
str(citation.page),
|
|
|
|
)
|
2011-12-12 09:13:58 +05:30
|
|
|
retval += table.get_html()
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add citation"), (url % args))
|
2011-12-12 09:13:58 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
|
|
|
return retval
|
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def note_table(obj, user, action, url=None, *args):
|
|
|
|
retval = ""
|
|
|
|
table = Table()
|
|
|
|
table.columns(
|
|
|
|
_("ID"),
|
|
|
|
_("Type"),
|
|
|
|
_("Note"))
|
|
|
|
if user.is_authenticated():
|
|
|
|
obj_type = ContentType.objects.get_for_model(obj)
|
|
|
|
note_refs = dji.NoteRef.filter(object_type=obj_type,
|
|
|
|
object_id=obj.id)
|
|
|
|
for note_ref in note_refs:
|
|
|
|
note = table.db.get_note_from_handle(
|
|
|
|
note_ref.ref_object.handle)
|
|
|
|
table.row(table.db.get_note_from_handle(note.handle),
|
|
|
|
str(note_ref.ref_object.note_type),
|
|
|
|
note_ref.ref_object.text[:50])
|
|
|
|
retval += table.get_html()
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 00:18:20 +05:30
|
|
|
retval += make_button(_("Add note"), (url % args))
|
2009-12-27 23:53:59 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
|
|
|
return retval
|
|
|
|
|
|
|
|
def attribute_table(obj, user, action, url=None, *args):
|
2009-12-20 07:27:17 +05:30
|
|
|
retval = ""
|
2009-11-16 04:17:43 +05:30
|
|
|
table = Table()
|
|
|
|
table.columns(_("Type"),
|
|
|
|
_("Value"),
|
|
|
|
)
|
2009-11-19 08:11:37 +05:30
|
|
|
if user.is_authenticated():
|
2009-12-27 23:53:59 +05:30
|
|
|
obj_type = ContentType.objects.get_for_model(obj)
|
2009-11-19 08:11:37 +05:30
|
|
|
attributes = dji.Attribute.filter(object_type=obj_type,
|
2009-12-27 23:53:59 +05:30
|
|
|
object_id=obj.id)
|
2009-11-19 08:11:37 +05:30
|
|
|
for attribute in attributes:
|
|
|
|
table.row(attribute.attribute_type.name,
|
|
|
|
attribute.value)
|
2009-12-20 07:27:17 +05:30
|
|
|
retval += table.get_html()
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add attribute"), (url % args))
|
2009-12-27 23:53:59 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
2009-12-20 07:27:17 +05:30
|
|
|
return retval
|
2009-11-16 04:17:43 +05:30
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def address_table(obj, user, action, url=None, *args):
|
2009-12-20 07:27:17 +05:30
|
|
|
retval = ""
|
2009-11-16 04:17:43 +05:30
|
|
|
table = Table()
|
|
|
|
table.columns(_("Date"),
|
|
|
|
_("Address"),
|
|
|
|
_("City"),
|
|
|
|
_("State"),
|
|
|
|
_("Country"))
|
2009-11-19 08:11:37 +05:30
|
|
|
if user.is_authenticated():
|
2009-12-27 23:53:59 +05:30
|
|
|
for address in obj.address_set.all().order_by("order"):
|
2009-11-19 08:11:37 +05:30
|
|
|
locations = address.location_set.all().order_by("order")
|
|
|
|
for location in locations:
|
|
|
|
table.row(display_date(address),
|
|
|
|
location.street,
|
|
|
|
location.city,
|
|
|
|
location.state,
|
|
|
|
location.country)
|
2009-12-20 07:27:17 +05:30
|
|
|
retval += table.get_html()
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add address"), (url % args))
|
2009-12-27 23:53:59 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
2009-12-20 07:27:17 +05:30
|
|
|
return retval
|
2009-11-16 04:17:43 +05:30
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def gallery_table(obj, user, action, url=None, *args):
|
2009-12-20 07:27:17 +05:30
|
|
|
retval = ""
|
2009-11-16 04:17:43 +05:30
|
|
|
table = Table()
|
|
|
|
table.columns(_("Name"),
|
|
|
|
_("Type"),
|
|
|
|
)
|
2009-12-20 07:27:17 +05:30
|
|
|
retval += table.get_html()
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add gallery"), (url % args))
|
2009-12-27 23:53:59 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
2009-12-20 07:27:17 +05:30
|
|
|
return retval
|
2009-11-16 04:17:43 +05:30
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def internet_table(obj, user, action, url=None, *args):
|
2009-12-20 07:27:17 +05:30
|
|
|
retval = ""
|
2009-11-16 04:17:43 +05:30
|
|
|
table = Table()
|
|
|
|
table.columns(_("Type"),
|
|
|
|
_("Path"),
|
|
|
|
_("Description"))
|
2009-11-19 08:11:37 +05:30
|
|
|
if user.is_authenticated():
|
2009-12-27 23:53:59 +05:30
|
|
|
urls = dji.Url.filter(person=obj)
|
2009-12-29 08:52:03 +05:30
|
|
|
for url_obj in urls:
|
|
|
|
table.row(str(url_obj.url_type),
|
|
|
|
url_obj.path,
|
|
|
|
url_obj.desc)
|
2009-12-20 07:27:17 +05:30
|
|
|
retval += table.get_html()
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add internet"), (str(url) % args))
|
2009-12-27 23:53:59 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
2009-12-20 07:27:17 +05:30
|
|
|
return retval
|
2009-11-16 04:17:43 +05:30
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def association_table(obj, user, action, url=None, *args):
|
2009-12-20 07:27:17 +05:30
|
|
|
retval = ""
|
2009-11-16 04:17:43 +05:30
|
|
|
table = Table()
|
|
|
|
table.columns(_("Name"),
|
|
|
|
_("ID"),
|
|
|
|
_("Association"))
|
2009-11-19 08:11:37 +05:30
|
|
|
if user.is_authenticated():
|
2009-12-27 23:53:59 +05:30
|
|
|
gperson = table.db.get_person_from_handle(obj.handle)
|
2010-01-01 20:46:20 +05:30
|
|
|
if gperson:
|
|
|
|
associations = gperson.get_person_ref_list()
|
|
|
|
for association in associations:
|
|
|
|
table.row()
|
2009-12-20 07:27:17 +05:30
|
|
|
retval += table.get_html()
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add association"), (url % args))
|
2009-12-27 23:53:59 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
2009-12-20 07:27:17 +05:30
|
|
|
return retval
|
2009-11-16 04:17:43 +05:30
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def lds_table(obj, user, action, url=None, *args):
|
2009-12-20 07:27:17 +05:30
|
|
|
retval = ""
|
2009-11-16 04:17:43 +05:30
|
|
|
table = Table()
|
|
|
|
table.columns(_("Type"),
|
|
|
|
_("Date"),
|
|
|
|
_("Status"),
|
|
|
|
_("Temple"),
|
|
|
|
_("Place"))
|
2009-11-19 08:11:37 +05:30
|
|
|
if user.is_authenticated():
|
2009-12-27 23:53:59 +05:30
|
|
|
obj_type = ContentType.objects.get_for_model(obj)
|
|
|
|
ldss = obj.lds_set.all().order_by("order")
|
2009-11-19 08:11:37 +05:30
|
|
|
for lds in ldss:
|
|
|
|
table.row(str(lds.lds_type),
|
|
|
|
display_date(lds),
|
|
|
|
str(lds.status),
|
|
|
|
lds.temple,
|
|
|
|
get_title(lds.place))
|
2009-12-20 07:27:17 +05:30
|
|
|
retval += table.get_html()
|
2012-05-19 17:54:40 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add LDS"), (url % args))
|
2009-12-27 23:53:59 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
2009-12-20 07:27:17 +05:30
|
|
|
return retval
|
2009-11-16 04:17:43 +05:30
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def reference_table(obj, user, action, url=None, *args):
|
2009-12-20 07:27:17 +05:30
|
|
|
retval = ""
|
2009-11-16 04:17:43 +05:30
|
|
|
table = Table()
|
|
|
|
table.columns(_("Type"),
|
|
|
|
_("ID"),
|
|
|
|
_("Name"))
|
2009-11-19 08:11:37 +05:30
|
|
|
if user.is_authenticated():
|
2009-12-27 23:53:59 +05:30
|
|
|
references = dji.PersonRef.filter(ref_object=obj)
|
2009-11-19 08:11:37 +05:30
|
|
|
for reference in references:
|
|
|
|
table.row(str(reference.ref_object),
|
|
|
|
reference.ref_object.gramps_id,
|
|
|
|
make_name(reference.ref_object.name_set, user))
|
2009-12-27 23:53:59 +05:30
|
|
|
retval += table.get_html()
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
|
|
|
return retval
|
2009-11-16 04:17:43 +05:30
|
|
|
|
2009-12-27 23:53:59 +05:30
|
|
|
def children_table(obj, user, action, url=None, *args):
|
2009-12-20 07:27:17 +05:30
|
|
|
retval = ""
|
2009-11-16 04:17:43 +05:30
|
|
|
table = Table()
|
2009-11-18 08:28:29 +05:30
|
|
|
table.columns(
|
|
|
|
_("#"),
|
|
|
|
_("ID"),
|
|
|
|
_("Name"),
|
|
|
|
_("Gender"),
|
|
|
|
_("Paternal"),
|
|
|
|
_("Maternal"),
|
|
|
|
_("Birth Date"),
|
|
|
|
)
|
2010-01-02 07:39:09 +05:30
|
|
|
|
|
|
|
family = obj
|
|
|
|
obj_type = ContentType.objects.get_for_model(family)
|
|
|
|
childrefs = dji.ChildRef.filter(object_id=family.id,
|
|
|
|
object_type=obj_type).order_by("order")
|
|
|
|
links = []
|
|
|
|
count = 1
|
|
|
|
for childref in childrefs:
|
|
|
|
child = childref.ref_object
|
|
|
|
if user.is_authenticated():
|
|
|
|
table.row(str(count),
|
|
|
|
"[%s]" % child.gramps_id,
|
|
|
|
render_name(child, user),
|
|
|
|
child.gender_type,
|
|
|
|
childref.father_rel_type,
|
|
|
|
childref.mother_rel_type,
|
2012-05-26 05:11:47 +05:30
|
|
|
date_as_text(child.birth, user),
|
2010-01-02 07:39:09 +05:30
|
|
|
)
|
|
|
|
links.append(('URL', ("/person/%s" % child.handle)))
|
|
|
|
else:
|
|
|
|
table.row(str(count),
|
|
|
|
"[%s]" % child.gramps_id,
|
|
|
|
render_name(child, user),
|
|
|
|
child.gender_type,
|
|
|
|
"[Private]",
|
|
|
|
"[Private]",
|
|
|
|
"[Private]",
|
|
|
|
)
|
|
|
|
links.append(('URL', ("/person/%s" % child.handle)))
|
|
|
|
count += 1
|
|
|
|
table.links(links)
|
|
|
|
retval += table.get_html()
|
2012-05-25 07:15:16 +05:30
|
|
|
if user.is_superuser and url and action == "view":
|
2012-05-27 02:26:27 +05:30
|
|
|
retval += make_button(_("Add child"), (url % args))
|
2012-05-25 07:15:16 +05:30
|
|
|
else:
|
|
|
|
retval += nbsp("") # to keep tabs same height
|
2010-01-02 07:39:09 +05:30
|
|
|
return retval
|
2009-11-16 04:17:43 +05:30
|
|
|
|
2009-11-15 04:18:30 +05:30
|
|
|
## FIXME: these dji function wrappers just use the functions
|
|
|
|
## written for the import/export. Can be done much more directly.
|
|
|
|
|
2009-11-15 05:18:55 +05:30
|
|
|
def get_title(place):
|
|
|
|
if place:
|
|
|
|
return place.title
|
|
|
|
else:
|
|
|
|
return ""
|
|
|
|
|
2009-11-15 04:18:30 +05:30
|
|
|
def person_get_birth_date(person):
|
2010-01-24 19:31:36 +05:30
|
|
|
#db = DbDjango()
|
2009-12-29 08:52:03 +05:30
|
|
|
#event = get_birth_or_fallback(db, db.get_person_from_handle(person.handle))
|
|
|
|
#if event:
|
|
|
|
# return event.date
|
2009-12-21 03:56:45 +05:30
|
|
|
return None
|
2009-11-15 04:18:30 +05:30
|
|
|
|
|
|
|
def person_get_death_date(person):
|
2010-01-24 19:31:36 +05:30
|
|
|
#db = DbDjango()
|
2009-12-29 08:52:03 +05:30
|
|
|
#event = get_death_or_fallback(db, db.get_person_from_handle(person.handle))
|
|
|
|
#if event:
|
|
|
|
# return event.date
|
2009-12-21 03:56:45 +05:30
|
|
|
return None
|
2009-11-15 04:18:30 +05:30
|
|
|
|
|
|
|
def display_date(obj):
|
|
|
|
date_tuple = dji.get_date(obj)
|
|
|
|
if date_tuple:
|
|
|
|
gdate = GDate()
|
|
|
|
gdate.unserialize(date_tuple)
|
2012-05-26 05:11:47 +05:30
|
|
|
return dd(gdate)
|
2009-11-15 04:18:30 +05:30
|
|
|
else:
|
|
|
|
return ""
|
|
|
|
|
2012-05-16 01:46:39 +05:30
|
|
|
def render(formfield, user, action, test=False, truetext="", id=None):
|
2010-01-01 20:46:20 +05:30
|
|
|
if not user.is_authenticated():
|
|
|
|
action = "view"
|
2012-05-25 18:08:09 +05:30
|
|
|
if action == "view": # show as text
|
2010-01-01 20:46:20 +05:30
|
|
|
if (not user.is_authenticated() and not test) or user.is_authenticated():
|
|
|
|
fieldname = formfield.name # 'surname'
|
2011-10-29 19:28:41 +05:30
|
|
|
try:
|
2012-05-16 17:35:58 +05:30
|
|
|
retval = str(getattr(formfield.form.model, fieldname))
|
2012-05-26 05:11:47 +05:30
|
|
|
if retval == "True":
|
|
|
|
retval = "Yes"
|
|
|
|
elif retval == "False":
|
|
|
|
retval = "No"
|
2011-10-29 19:28:41 +05:30
|
|
|
except:
|
2011-12-13 07:38:47 +05:30
|
|
|
# name, "prefix"
|
|
|
|
try:
|
2012-05-26 05:11:47 +05:30
|
|
|
retval = str(formfield.form.data[fieldname])
|
2011-12-13 07:38:47 +05:30
|
|
|
except:
|
2012-05-25 18:08:09 +05:30
|
|
|
retval = "[None]"
|
2010-01-01 20:46:20 +05:30
|
|
|
else:
|
|
|
|
retval = truetext
|
2012-05-25 18:08:09 +05:30
|
|
|
else: # show as widget
|
2012-05-16 01:46:39 +05:30
|
|
|
if id != None:
|
|
|
|
retval = formfield.as_widget(attrs={"id": id})
|
|
|
|
else:
|
|
|
|
retval = formfield.as_widget()
|
2010-01-01 20:46:20 +05:30
|
|
|
return retval
|
|
|
|
|
|
|
|
def render_name(name, user):
|
|
|
|
"""
|
|
|
|
Given a Django or Gramps object, render the name and return. This
|
|
|
|
function uses authentication, privacy and probably_alive settings.
|
|
|
|
"""
|
2012-05-25 18:08:09 +05:30
|
|
|
if name is None:
|
|
|
|
return "[None]"
|
|
|
|
elif isinstance(name, models.Name):
|
2010-01-01 20:46:20 +05:30
|
|
|
if not user.is_authenticated():
|
|
|
|
name.sanitize()
|
2012-05-24 22:52:14 +05:30
|
|
|
try:
|
|
|
|
surname = name.surname_set.get(primary=True)
|
|
|
|
except:
|
|
|
|
surname = "[No primary surname]"
|
|
|
|
return "%s, %s" % (surname, name.first_name)
|
2010-01-01 20:46:20 +05:30
|
|
|
elif isinstance(name, forms.NameForm):
|
|
|
|
if not user.is_authenticated():
|
|
|
|
name.model.sanitize()
|
2012-05-24 22:52:14 +05:30
|
|
|
try:
|
|
|
|
surname = name.model.surname_set.get(primary=True)
|
|
|
|
except:
|
|
|
|
surname = "[No primary surname]"
|
|
|
|
return "%s, %s" % (surname,
|
2011-02-19 08:06:20 +05:30
|
|
|
name.model.first_name)
|
2010-01-01 20:46:20 +05:30
|
|
|
elif isinstance(name, gen.lib.Person): # name is a gen.lib.Person
|
|
|
|
person = name
|
|
|
|
try:
|
|
|
|
name = person.get_primary_name()
|
|
|
|
except:
|
|
|
|
name = None
|
|
|
|
if name is None:
|
|
|
|
return "[No preferred name]"
|
|
|
|
if not user.is_authenticated():
|
|
|
|
name.sanitize()
|
2012-05-24 22:52:14 +05:30
|
|
|
try:
|
|
|
|
surname = name.surname_set.get(primary=True)
|
|
|
|
except:
|
|
|
|
surname = "[No primary surname]"
|
|
|
|
return "%s, %s" % (surname, name.first_name)
|
2010-01-01 20:46:20 +05:30
|
|
|
elif isinstance(name, models.Person): # django person
|
|
|
|
person = name
|
|
|
|
try:
|
|
|
|
name = person.name_set.get(preferred=True)
|
|
|
|
except:
|
|
|
|
return "Error"
|
|
|
|
return render_name(name, user)
|
|
|
|
else: # no name object
|
|
|
|
return "[No preferred name]"
|
|
|
|
|
|
|
|
def make_name(name, user):
|
|
|
|
return render_name(name, user)
|
|
|
|
|
2012-05-26 05:11:47 +05:30
|
|
|
def date_as_text(obj, user):
|
2010-01-01 20:46:20 +05:30
|
|
|
"""
|
|
|
|
Given a Django object, render the date as text and return. This
|
|
|
|
function uses authentication settings.
|
|
|
|
"""
|
|
|
|
if (user.is_authenticated() or
|
|
|
|
(not user.is_authenticated() and obj and not obj.private)):
|
|
|
|
if obj:
|
|
|
|
date_tuple = dji.get_date(obj)
|
|
|
|
if date_tuple:
|
|
|
|
gdate = GDate().unserialize(date_tuple)
|
2012-05-26 05:11:47 +05:30
|
|
|
return dd(gdate)
|
2010-01-01 20:46:20 +05:30
|
|
|
return ""
|
|
|
|
return "[Private]"
|
|
|
|
|
2009-11-15 04:18:30 +05:30
|
|
|
def person_get_event(person, event_type=None):
|
|
|
|
event_ref_list = dji.get_event_ref_list(person)
|
|
|
|
if event_type:
|
|
|
|
index = libdjango.lookup_role_index(event_type, event_ref_list)
|
|
|
|
if index >= 0:
|
|
|
|
event_handle = event_ref_list[index][3]
|
|
|
|
# (False, [], [], u'b2cfa6cdec87392cf3b', (1, u'Primary'))
|
|
|
|
# WARNING: the same object can be referred to more than once
|
|
|
|
objs = models.EventRef.objects.filter(ref_object__handle=event_handle)
|
|
|
|
if objs.count() > 0:
|
|
|
|
return display_date(objs[0].ref_object)
|
|
|
|
else:
|
|
|
|
return ""
|
|
|
|
else:
|
|
|
|
return ""
|
|
|
|
else:
|
|
|
|
retval = [[obj.ref_object for obj in
|
|
|
|
models.EventRef.objects.filter(ref_object__handle=event_handle[3])]
|
|
|
|
for event_handle in event_ref_list]
|
|
|
|
return [j for i in retval for j in i]
|
|
|
|
|
2012-05-25 02:21:46 +05:30
|
|
|
def boolean(s):
|
|
|
|
return s.lower() in ["true", "1", "yes", "y", "t"]
|
|
|
|
|
2012-05-25 20:30:39 +05:30
|
|
|
def update_last_changed(obj, user):
|
|
|
|
obj.last_changed = datetime.datetime.now()
|
|
|
|
obj.last_changed_by = user
|
|
|
|
|
2009-11-15 04:18:30 +05:30
|
|
|
register_plugins()
|
|
|
|
|
|
|
|
# works after registering plugins:
|
|
|
|
import HtmlDoc
|
2012-05-29 04:22:23 +05:30
|
|
|
from libhtmlbackend import HtmlBackend, DocBackend, process_spaces
|
2009-11-15 04:18:30 +05:30
|
|
|
from libhtml import Html
|
2011-10-16 01:42:11 +05:30
|
|
|
|
2012-05-29 04:22:23 +05:30
|
|
|
class WebAppBackend(HtmlBackend):
|
|
|
|
SUPPORTED_MARKUP = [
|
|
|
|
DocBackend.BOLD,
|
|
|
|
DocBackend.ITALIC,
|
|
|
|
DocBackend.UNDERLINE,
|
|
|
|
DocBackend.FONTFACE,
|
|
|
|
DocBackend.FONTSIZE,
|
|
|
|
DocBackend.FONTCOLOR,
|
2012-05-29 19:09:55 +05:30
|
|
|
DocBackend.SUPERSCRIPT,
|
2012-05-29 04:22:23 +05:30
|
|
|
DocBackend.LINK,
|
|
|
|
]
|
|
|
|
|
|
|
|
STYLETAG_MARKUP = {
|
|
|
|
DocBackend.BOLD : ("<b>", "</b>"),
|
|
|
|
DocBackend.ITALIC : ("<i>", "</i>"),
|
|
|
|
DocBackend.UNDERLINE : ('<u>', '</u>'),
|
2012-05-29 19:09:55 +05:30
|
|
|
DocBackend.SUPERSCRIPT : ("<sup>", "</sup>"),
|
2012-05-29 04:22:23 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
### Taken from Narrated Web Report
|
2012-05-28 22:47:15 +05:30
|
|
|
class StyledNoteFormatter(object):
|
|
|
|
def __init__(self, database):
|
|
|
|
self.database = database
|
2012-05-29 04:22:23 +05:30
|
|
|
self._backend = WebAppBackend()
|
2012-05-28 22:47:15 +05:30
|
|
|
self._backend.build_link = self.build_link
|
|
|
|
|
2012-05-29 06:02:55 +05:30
|
|
|
def format(self, note):
|
2012-05-29 19:09:55 +05:30
|
|
|
return self.styled_note(note.get_styledtext())
|
2012-05-28 22:47:15 +05:30
|
|
|
|
2012-05-29 19:09:55 +05:30
|
|
|
def styled_note(self, styledtext):
|
2012-05-28 22:47:15 +05:30
|
|
|
text = str(styledtext)
|
|
|
|
if not text:
|
|
|
|
return ''
|
|
|
|
s_tags = styledtext.get_tags()
|
2012-05-29 19:09:55 +05:30
|
|
|
markuptext = self._backend.add_markup_from_styled(text, s_tags, split='\n').replace("\n", "<br/>")
|
|
|
|
return markuptext
|
2012-05-28 22:47:15 +05:30
|
|
|
|
|
|
|
def build_link(self, prop, handle, obj_class):
|
|
|
|
"""
|
|
|
|
Build a link to an item.
|
|
|
|
"""
|
|
|
|
if prop == "gramps_id":
|
|
|
|
if obj_class in self.database.get_table_names():
|
|
|
|
obj = self.database.get_table_metadata(obj_class)["gramps_id_func"](handle)
|
|
|
|
if obj:
|
|
|
|
handle = obj.handle
|
|
|
|
else:
|
|
|
|
raise AttributeError("gramps_id '%s' not found in '%s'" %
|
|
|
|
handle, obj_class)
|
|
|
|
else:
|
|
|
|
raise AttributeError("invalid gramps_id lookup "
|
|
|
|
"in table name '%s'" % obj_class)
|
|
|
|
# handle, ppl
|
|
|
|
return "/%s/%s" % (obj_class.lower(), handle)
|
2012-05-29 19:09:55 +05:30
|
|
|
|
|
|
|
class WebAppParser(HTMLParser):
|
|
|
|
BOLD = 0
|
|
|
|
ITALIC = 1
|
|
|
|
UNDERLINE = 2
|
|
|
|
FONTFACE = 3
|
|
|
|
FONTSIZE = 4
|
|
|
|
FONTCOLOR = 5
|
|
|
|
HIGHLIGHT = 6
|
|
|
|
SUPERSCRIPT = 7
|
|
|
|
LINK = 8
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
HTMLParser.__init__(self)
|
|
|
|
self.__text = ""
|
|
|
|
self.__tags = {}
|
|
|
|
self.__stack = []
|
|
|
|
|
|
|
|
def handle_data(self, data):
|
|
|
|
self.__text += data
|
|
|
|
|
|
|
|
def push(self, pos, tag, attrs):
|
|
|
|
self.__stack.append([pos, tag, attrs])
|
|
|
|
|
|
|
|
def pop(self):
|
|
|
|
return self.__stack.pop()
|
|
|
|
|
|
|
|
def handle_starttag(self, tag, attrs):
|
|
|
|
self.push(len(self.__text), tag.lower(), attrs)
|
|
|
|
|
|
|
|
def handle_endtag(self, tag):
|
|
|
|
tag = tag.lower()
|
|
|
|
(start_pos, start_tag, attrs) = self.pop()
|
|
|
|
attrs = {x[0]: x[1] for x in attrs}
|
|
|
|
if tag != start_tag: return # skip <i><b></i></b> formats
|
|
|
|
arg = None
|
|
|
|
tagtype = None
|
|
|
|
if tag == "span":
|
|
|
|
# "span": get color, font, size
|
|
|
|
if "style" in attrs:
|
|
|
|
style = attrs["style"]
|
|
|
|
if 'color' in style:
|
|
|
|
tagtype = self.FONTCOLOR
|
|
|
|
match = re.match("color:([^;]*);", style)
|
|
|
|
if match:
|
|
|
|
arg = match.groups()[0]
|
|
|
|
else:
|
|
|
|
print "Unhandled color tag: '%s'" % style
|
|
|
|
elif "font-family" in style:
|
|
|
|
tagtype = self.FONTFACE
|
|
|
|
match = re.match("font-family:'([^;]*)';", style)
|
|
|
|
if match:
|
|
|
|
arg = match.groups()[0]
|
|
|
|
else:
|
|
|
|
print "Unhandled font-family tag: '%s'" % style
|
|
|
|
elif "font-size" in style:
|
|
|
|
tagtype = self.FONTSIZE
|
|
|
|
match = re.match("font-size:([^;]*)px;", style)
|
|
|
|
if match:
|
|
|
|
arg = int(match.groups()[0])
|
|
|
|
else:
|
|
|
|
print "Unhandled font-size tag: '%s'" % style
|
|
|
|
else:
|
|
|
|
print "Unhandled span arg: '%s'" % attrs
|
|
|
|
else:
|
|
|
|
print "span has no style: '%s'" % attrs
|
|
|
|
# "b", "i", "u", "sup": direct conversion
|
|
|
|
elif tag == "b":
|
|
|
|
tagtype = self.BOLD
|
|
|
|
elif tag == "i":
|
|
|
|
tagtype = self.ITALIC
|
|
|
|
elif tag == "u":
|
|
|
|
tagtype = self.UNDERLINE
|
|
|
|
elif tag == "sup":
|
|
|
|
tagtype = self.SUPERSCRIPT
|
|
|
|
elif tag == "br":
|
|
|
|
self.__text += "\n"
|
|
|
|
return
|
|
|
|
elif tag == "p":
|
|
|
|
self.__text += "\n\n"
|
|
|
|
return
|
|
|
|
elif tag == "a":
|
|
|
|
tagtype = self.LINK
|
|
|
|
# "a": get /object/handle, or url
|
|
|
|
if "href" in attrs:
|
|
|
|
href = attrs["href"]
|
|
|
|
if href.startswith("/"):
|
|
|
|
parts = href.split("/")
|
|
|
|
arg = "gramps://%s/handle/%s" % (parts[-2].title(), parts[-1])
|
|
|
|
else:
|
|
|
|
arg = href
|
|
|
|
else:
|
|
|
|
print "Unhandled a with no href: '%s'" % attrs
|
|
|
|
else:
|
|
|
|
return
|
|
|
|
print "Unhandled tag: '%s'" % tag
|
|
|
|
key = ((tagtype, u''), arg)
|
|
|
|
if key not in self.__tags:
|
|
|
|
self.__tags[key] = []
|
|
|
|
self.__tags[key].append((start_pos, len(self.__text)))
|
|
|
|
|
|
|
|
def tags(self):
|
|
|
|
# [((code, u''), string/num, [(start, stop), ...]), ...]
|
|
|
|
return [(key[0], key[1], self.__tags[key]) for key in self.__tags]
|
|
|
|
|
|
|
|
def text(self):
|
|
|
|
return self.__text
|
|
|
|
|
|
|
|
def parse_styled_text(text):
|
|
|
|
parser = WebAppParser()
|
|
|
|
parser.feed(text)
|
|
|
|
parser.close()
|
|
|
|
return (parser.text(), parser.tags())
|
|
|
|
|