gramps/gramps2/src/plugins/NavWebPage.py

2109 lines
79 KiB
Python

#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2005 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Pubilc 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$
"Web Site/Generate Web Site"
#------------------------------------------------------------------------
#
# python modules
#
#------------------------------------------------------------------------
import os
import time
import locale
import shutil
import codecs
import sets
from gettext import gettext as _
from cStringIO import StringIO
#------------------------------------------------------------------------
#
# GNOME/gtk
#
#------------------------------------------------------------------------
import gtk
#------------------------------------------------------------------------
#
# GRAMPS module
#
#------------------------------------------------------------------------
import RelLib
import const
from GrampsCfg import get_researcher
import GenericFilter
import Sort
import Report
import Errors
import Utils
import ReportOptions
import BaseDoc
import ReportUtils
from QuestionDialog import ErrorDialog
from NameDisplay import displayer as _nd
from DateHandler import displayer as _dd
#------------------------------------------------------------------------
#
# constants
#
#------------------------------------------------------------------------
_NARRATIVE = "narrative.css"
_NAME_COL = 3
_css_files = [
[_("Modern"), 'main1.css'],
[_("Business"), 'main2.css'],
[_("Certificate"),'main3.css'],
[_("Antique"), 'main4.css'],
[_("Tranquil"), 'main5.css'],
]
_character_sets = [
[_('Unicode (recommended)'), 'utf-8'],
['ISO-8859-1', 'iso-8859-1' ],
['ISO-8859-2', 'iso-8859-2' ],
['ISO-8859-3', 'iso-8859-3' ],
['ISO-8859-4', 'iso-8859-4' ],
['ISO-8859-5', 'iso-8859-5' ],
['ISO-8859-6', 'iso-8859-6' ],
['ISO-8859-7', 'iso-8859-7' ],
['ISO-8859-8', 'iso-8859-8' ],
['ISO-8859-9', 'iso-8859-9' ],
['ISO-8859-10', 'iso-8859-10' ],
['ISO-8859-13', 'iso-8859-13' ],
['ISO-8859-14', 'iso-8859-14' ],
['ISO-8859-15', 'iso-8859-15' ],
['koi8_r', 'koi8_r', ],
]
class BasePage:
def __init__(self, title, options, archive, photo_list):
self.title_str = title
self.inc_download = options.handler.options_dict['NWEBdownload']
self.html_dir = options.handler.options_dict['NWEBod']
self.options = options
self.archive = archive
self.image_dir = options.handler.options_dict['NWEBimagedir'].strip()
self.ext = options.handler.options_dict['NWEBext']
self.encoding = options.handler.options_dict['NWEBencoding']
self.css = options.handler.options_dict['NWEBcss']
self.noid = options.handler.options_dict['NWEBnoid']
self.use_intro = options.handler.options_dict['NWEBintronote'] != u""
self.use_contact = options.handler.options_dict['NWEBcontact'] != u""
self.photo_list = photo_list
self.private = not options.handler.options_dict['NWEBincpriv']
def copy_media(self,photo):
if photo.get_handle() != self.photo_list:
self.photo_list.append(photo.get_handle())
newpath = photo.gramps_id + os.path.splitext(photo.get_path())[1]
if self.image_dir:
newpath = os.path.join(self.image_dir,newpath)
return newpath
def create_file(self,name):
if self.archive:
self.string_io = StringIO()
of = codecs.EncodedFile(self.string_io,'utf-8',self.encoding)
self.cur_name = name + "." + self.ext
else:
page_name = os.path.join(self.html_dir,name + "." + self.ext)
of = codecs.EncodedFile(open(page_name, "w"),'utf-8',self.encoding)
return of
def close_file(self,of):
if self.archive:
self.archive.add_file(self.cur_name,time.time(),self.string_io)
of.close()
else:
of.close()
def lnkfmt(self,text):
return text.replace(' ','%20')
def display_footer(self,of):
format = locale.nl_langinfo(locale.D_FMT)
value = time.strftime(format,time.localtime(time.time()))
msg = _('Generated by <a href="http://gramps-project.org">'
'GRAMPS</a> on %(date)s' % { 'date' : value })
of.write('</div>\n')
of.write('<div class="footer">%s</div>\n' % msg)
of.write('<br><br><hr>\n')
of.write('</body>\n')
of.write('</html>\n')
def display_header(self,of,title,author=""):
if author:
author = author.replace(',,,','')
year = time.localtime(time.time())[0]
cright = _('Copyright &copy; %(person)s %(year)d') % {
'person' : author,
'year' : year }
of.write('<!DOCTYPE HTML PUBLIC ')
of.write('"-//W3C//DTD HTML 4.01 Transitional//EN">\n')
of.write('<html>\n<head>\n')
of.write('<title>%s - %s</title>\n' % (self.title_str, title))
of.write('<meta http-equiv="Content-Type" content="text/html; ')
of.write('charset=%s">\n' % self.encoding)
of.write('<link href="%s" ' % _NARRATIVE)
of.write('rel="stylesheet" type="text/css">\n')
of.write('<link href="favicon.png" rel="Shortcut Icon">\n')
of.write('<!-- $Id$ -->')
of.write('</head>\n')
of.write('<body>\n')
of.write('<div class="navheader">\n')
if author:
of.write(' <div class="navbyline">%s</div>\n' % cright)
of.write(' <h1 class="navtitle">%s</h1>\n' % self.title_str)
of.write(' <hr>\n')
of.write(' <div class="nav">\n')
of.write(' <a href="index.%s">%s</a> &nbsp;\n' % (self.ext,_('Home')))
if self.use_intro:
of.write(' <a href="introduction.%s">%s</a> &nbsp;\n' % (self.ext,_('Introduction')))
of.write(' <a href="surnames.%s">%s</a> &nbsp;\n' % (self.ext,_('Surnames')))
of.write(' <a href="individuals.%s">%s</a> &nbsp;\n' % (self.ext,_('Individuals')))
of.write(' <a href="sources.%s">%s</a> &nbsp;\n' % (self.ext,_('Sources')))
of.write(' <a href="places.%s">%s</a> &nbsp;\n' % (self.ext,_('Places')))
of.write(' <a href="gallery.%s">%s</a> &nbsp;\n' % (self.ext,_('Gallery')))
if self.inc_download:
of.write(' <a href="download.%s">%s</a> &nbsp;\n' % (self.ext,_('Download')))
if self.use_contact:
of.write(' <a href="contact.%s">%s</a> &nbsp;\n' % (self.ext,_('Contact')))
of.write(' </div>\n')
of.write(' </div>\n')
of.write(' <div class="content">\n')
def display_first_image_as_thumbnail( self, of, db, photolist=None):
if not photolist:
return
photo_handle = photolist[0].get_reference_handle()
photo = db.get_object_from_handle(photo_handle)
if photo.get_mime_type():
try:
newpath = self.copy_media(photo)
of.write('<div class="snapshot">\n')
of.write('<a href="%s.%s">' % (photo_handle,self.ext))
of.write('<img class="thumbnail" border="0" src="%s" ' % newpath)
of.write('height="100" alt="%s"></a>' % photo.get_description())
of.write('</div>\n')
except (IOError,OSError),msg:
ErrorDialog(str(msg))
def display_additional_images_as_gallery( self, of, db, photolist=None):
if not photolist and len(photolist) == 0:
return
of.write('<h4>%s</h4>\n' % _('Gallery'))
of.write('<hr>\n')
of.write('<blockquote>')
for mediaref in photolist:
photo_handle = mediaref.get_reference_handle()
photo = db.get_object_from_handle(photo_handle)
if photo.get_mime_type():
try:
newpath = self.copy_media(photo)
of.write('<div class="galleryentry">\n')
of.write('<a href="%s.%s">' % (photo_handle,self.ext))
of.write('<img class="thumbnail" border="0" src="%s" ' % newpath)
of.write('height="100" alt="%s"></a>' % photo.get_description())
of.write('<div>%s</div>' % photo.get_description())
of.write('</div>\n')
except (IOError,OSError),msg:
ErrorDialog(str(msg))
of.write('</blockquote>')
def display_note_object(self,of,noteobj=None):
if not noteobj:
return
format = noteobj.get_format()
text = noteobj.get()
if text:
of.write('<h4>%s</h4>\n' % _('Narrative'))
of.write('<hr>\n')
if format:
text = u"<pre>" + u"<br>".join(text.split("\n"))+u"</pre>"
else:
text = u"</p><p>".join(text.split("\n"))
of.write('<p>%s</p>\n' % text)
def display_url_list(self,of,urllist=None):
if not urllist:
return
of.write('<h4>%s</h4>\n' % _('Weblinks'))
of.write('<hr>\n')
of.write('<table class="infolist" cellpadding="0" ')
of.write('cellspacing="0" border="0">\n')
index = 1
for url in urllist:
uri = url.get_path()
descr = url.get_description()
of.write('<tr><td class="field">%d.</td>' % index)
of.write('<td class="data"><a href="%s">%s</a>' % (uri,descr))
of.write('</td></tr>\n')
index = index + 1
of.write('</table>\n')
def display_attr_list(self,of,attrlist=None):
if not attrlist:
return
of.write('<h4>%s</h4>\n' % _('Attributes'))
of.write('<hr>\n')
of.write('<table class="infolist" cellpadding="0" ')
of.write('cellspacing="0" border="0">\n')
for attr in attrlist:
type = attr.get_type()
value = attr.get_value()
of.write('<tr><td class="field">%s</td>' % _(type))
of.write('<td class="data">%s</td></tr>\n' % value)
of.write('</table>\n')
def display_references(self,of,db,handlelist):
if not handlelist:
return
of.write('<h4>%s</h4>\n' % _('References'))
of.write('<hr>\n')
of.write('<table class="infolist" cellpadding="0" ')
of.write('cellspacing="0" border="0">\n')
index = 1
for handle in handlelist:
person = db.get_person_from_handle(handle)
of.write('<tr><td class="field">%d. ' % index)
of.write('<a href="%s.%s">%s</a>' % (handle,self.ext,
nameof(person,self.private)))
of.write('</td></tr>\n')
index = index + 1
of.write('</table>\n')
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class IndividualListPage(BasePage):
def __init__(self, db, title, person_handle_list, options, archive, media_list):
BasePage.__init__(self, title, options, archive, media_list)
of = self.create_file("individuals")
self.display_header(of,_('Individuals'),
get_researcher().get_name())
msg = _("This page contains an index of all the individuals in the "
"database, sorted by their last names. Selecting person's name "
"will take you to that person's individual page.")
of.write('<h3>%s</h3>\n' % _('Individuals'))
of.write('<p>%s</p>\n' % msg)
of.write('<blockquote>\n')
of.write('<table class="infolist" cellspacing="0" ')
of.write('cellpadding="0" border="0">\n')
of.write('<tr><td class="field"><u><b>%s</b></u></td>\n' % _('Surname'))
of.write('<td class="field"><u><b>%s</b></u></td>\n' % _('Name'))
of.write('</tr>\n')
flist = sets.Set(person_handle_list)
person_handle_list = sort_people(db,person_handle_list)
for (surname,handle_list) in person_handle_list:
first = True
of.write('<tr><td colspan="2">&nbsp;</td></tr>\n')
for person_handle in handle_list:
person = db.get_person_from_handle(person_handle)
of.write('<tr><td class="category">')
if first:
of.write('<a name="%s">%s</a>' % (self.lnkfmt(surname),surname))
else:
of.write('&nbsp')
of.write('</td><td class="data">')
of.write(' <a href="%s.%s">' % (person.handle,self.ext))
of.write(person.get_primary_name().get_first_name())
if not self.noid:
of.write(u'&nbsp;<span class="grampsid">[%s]</span>' % person.gramps_id)
of.write('</a></td></tr>\n')
first = False
of.write('</table>\n</blockquote>\n')
self.display_footer(of)
self.close_file(of)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class PlaceListPage(BasePage):
def __init__(self, db, title, place_handles, src_list, options, archive, media_list):
BasePage.__init__(self, title, options, archive, media_list)
of = self.create_file("places")
self.display_header(of,_('Places'),
get_researcher().get_name())
msg = _("This page contains an index of all the places in the "
"database, sorted by their title. Clicking on a place's "
"title will take you to that place's page.")
of.write('<h3>%s</h3>\n' % _('Places'))
of.write('<p>%s</p>\n' % msg )
of.write('<blockquote>\n')
of.write('<table class="infolist" cellspacing="0" ')
of.write('cellpadding="0" border="0">\n')
of.write('<tr><td class="field"><u>')
of.write('<b>%s</b></u></td>\n' % _('Letter'))
of.write('<td class="field"><u>')
of.write('<b>%s</b></u></td>\n' % _('Place'))
of.write('</tr>\n')
self.sort = Sort.Sort(db)
handle_list = place_handles.keys()
handle_list.sort(self.sort.by_place_title)
last_name = ""
last_letter = ''
for handle in handle_list:
place = db.get_place_from_handle(handle)
n = ReportUtils.place_name(db,handle)
if not n or len(n) == 0:
continue
if n[0] != last_letter:
last_letter = n[0]
of.write('<tr><td colspan="2">&nbsp;</td></tr>\n')
of.write('<tr><td class="category">%s</td>' % last_letter)
of.write('<td class="data">')
of.write('<a href="%s.%s">' % (place.handle,self.ext))
of.write(n)
if not self.noid:
of.write('&nbsp;<span class="grampsid">[%s]</span>' % place.gramps_id)
of.write('</a></td></tr>')
last_surname = n
elif n != last_surname:
of.write('<tr><td class="category">&nbsp;</td>')
of.write('<td class="data">')
of.write('<a href="%s.%s">' % (place.handle,self.ext))
of.write(n)
if not self.noid:
of.write('&nbsp;<span class="grampsid">[%s]</span>' % place.gramps_id)
of.write('</a></td></tr>')
last_surname = n
of.write('</table>\n</blockquote>\n')
self.display_footer(of)
self.close_file(of)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class PlacePage(BasePage):
def __init__(self, db, title, place_handle, src_list, place_list, options, archive, media_list):
place = db.get_place_from_handle( place_handle)
BasePage.__init__(self, title, options, archive, media_list)
of = self.create_file(place.get_handle())
place_name = ReportUtils.place_name(db,place_handle)
self.display_header(of,"%s - %s" % (_('Places'), place_name),
get_researcher().get_name())
self.display_first_image_as_thumbnail(of, db, place.get_media_list())
of.write('<div class="summaryarea">\n')
of.write('<h3>%s</h3>\n' % place_name)
of.write('<table class="infolist" cellpadding="0" cellspacing="0" ')
of.write('border="0">\n')
if not self.noid:
of.write('<tr><td class="field">%s</td>\n' % _('GRAMPS ID'))
of.write('<td class="data">%s</td>\n' % place.gramps_id)
of.write('</tr>\n')
if place.main_loc:
ml = place.main_loc
for val in [(_('City'),ml.city),(_('Church Parish'),ml.parish),
(_('County'),ml.county),(_('State/Province'),ml.state),
(_('Postal Code'),ml.postal),(_('Country'),ml.country)]:
if val[1]:
of.write('<tr><td class="field">%s</td>\n' % val[0])
of.write('<td class="data">%s</td>\n' % val[1])
of.write('</tr>\n')
if place.long:
of.write('<tr><td class="field">%s</td>\n' % _('Longitude'))
of.write('<td class="data">%s</td>\n' % place.long)
of.write('</tr>\n')
if place.lat:
of.write('<tr><td class="field">%s</td>\n' % _('Latitude'))
of.write('<td class="data">%s</td>\n' % place.lat)
of.write('</tr>\n')
of.write('</table>\n')
of.write('</div>\n')
# TODO: Add more information
self.display_additional_images_as_gallery(of, db, place.get_media_list())
self.display_note_object(of, place.get_note_object())
self.display_url_list(of, place.get_url_list())
self.display_references(of,db,place_list[place.handle])
self.display_footer(of)
self.close_file(of)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class MediaPage(BasePage):
def __init__(self, db, title, handle, src_list, options, archive, media_list):
photo = db.get_object_from_handle(handle)
BasePage.__init__(self, title, options, archive, media_list)
of = self.create_file(handle)
newpath = photo.gramps_id + os.path.splitext(photo.get_path())[1]
if self.image_dir:
newpath = os.path.join(self.image_dir,newpath)
if self.archive:
imagefile = open(photo.get_path(),"r")
self.archive.add_file(newpath,time.time(),imagefile)
imagefile.close()
else:
shutil.copyfile(photo.get_path(),
os.path.join(self.html_dir,newpath))
title = photo.get_description()
self.display_header(of, "%s - %s" % (_('Gallery'), title), get_researcher().get_name())
of.write('<div class="summaryarea">\n')
of.write('<h3>%s</h3>\n' % title)
mime_type = photo.get_mime_type()
if mime_type and mime_type.startswith("image"):
try:
of.write('<div align="center">\n')
of.write('<img border="0" ')
of.write('src="%s" alt="%s"/>' % (newpath, title))
of.write('</div>\n')
except (IOError,OSError),msg:
ErrorDialog(str(msg))
of.write('<table class="infolist" cellpadding="0" cellspacing="0" ')
of.write('border="0">\n')
if not self.noid:
of.write('<tr><td class="field">%s</td>\n' % _('GRAMPS ID'))
of.write('<td class="data">%s</td>\n' % photo.gramps_id)
of.write('</tr>\n')
of.write('<tr><td class="field">%s</td>\n' % _('MIME type'))
of.write('<td class="data">%s</td>\n' % photo.mime)
of.write('</tr>\n')
of.write('</table>\n')
of.write('</div>\n')
self.display_note_object(of, photo.get_note_object())
self.display_attr_list(of, photo.get_attribute_list())
self.display_footer(of)
self.close_file(of)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class SurnameListPage(BasePage):
def __init__(self, db, title, person_handle_list, options, archive, media_list):
BasePage.__init__(self, title, options, archive, media_list)
of = self.create_file("surnames")
self.display_header(of,_('Surnames'),
get_researcher().get_name())
of.write('<h3>%s</h3>\n' % _('Surnames'))
of.write('<p>%s</p>\n' % _(
'This page contains an index of all the '
'surnames in the database. Selecting a link '
'will lead to a list of individuals in the '
'database with this same surname.'))
of.write('<blockquote>\n')
of.write('<table class="infolist" cellspacing="0" ')
of.write('cellpadding="0" border="0">\n')
of.write('<tr><td class="field"><u>')
of.write('<b>%s</b></u></td>\n' % _('Letter'))
of.write('<td class="field"><u>')
of.write('<b>%s</b></u></td>\n' % _('Surname'))
of.write('</tr>\n')
person_handle_list = sort_people(db,person_handle_list)
last_letter = ''
last_surname = ''
for (surname,data_list) in person_handle_list:
if len(surname) == 0:
continue
if surname[0] != last_letter:
last_letter = surname[0]
of.write('<tr><td class="category">%s</td>' % last_letter)
of.write('<td class="data">')
of.write('<a href="individuals.%s#%s">' % (self.ext,self.lnkfmt(surname)))
of.write("%s (%d)" % (surname,len(data_list)))
of.write('</a></td></tr>')
elif surname != last_surname:
of.write('<tr><td class="category">&nbsp;</td>')
of.write('<td class="data">')
of.write('<a href="individuals.%s#%s">' % (self.ext,self.lnkfmt(surname)))
of.write("%s (%d)" % (surname,len(data_list)))
of.write('</a></td></tr>')
last_surname = surname
of.write('</table>\n</blockquote>\n')
self.display_footer(of)
self.close_file(of)
return
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class IntroductionPage(BasePage):
def __init__(self, db, title, options, archive, media_list):
BasePage.__init__(self, title, options, archive, media_list)
note_id = options.handler.options_dict['NWEBintronote']
of = self.create_file("introduction")
self.display_header(of,_('Introduction'),
get_researcher().get_name())
of.write('<h3>%s</h3>\n' % _('Introduction'))
if note_id:
obj = db.get_object_from_handle(note_id)
if obj:
mime_type = obj.get_mime_type()
if mime_type and mime_type.startswith("image"):
try:
newpath = self.copy_media(obj)
of.write('<div align="center">\n')
of.write('<img border="0" ')
of.write('src="%s" alt="%s" />' % (newpath, obj.get_description()))
of.write('</div>\n')
except (IOError,OSError),msg:
ErrorDialog(str(msg))
note_obj = obj.get_note_object()
if note_obj:
text = note_obj.get()
if note_obj.get_format():
of.write('<pre>\n%s\n</pre>\n' % text)
else:
of.write('<p>')
of.write('</p><p>'.join(text.split('\n')))
of.write('</p>')
self.display_footer(of)
self.close_file(of)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class HomePage(BasePage):
def __init__(self, db, title, options, archive, media_list):
BasePage.__init__(self, title, options, archive, media_list)
note_id = options.handler.options_dict['NWEBhomenote']
of = self.create_file("index")
self.display_header(of,_('Home'),
get_researcher().get_name())
of.write('<h3>%s</h3>\n' % _('Home'))
if note_id:
obj = db.get_object_from_handle(note_id)
if obj:
mime_type = obj.get_mime_type()
if mime_type and mime_type.startswith("image"):
try:
newpath = self.copy_media(obj)
of.write('<div align="center">\n')
of.write('<img border="0" ')
of.write('src="%s" alt="%s" />' % (newpath, obj.get_description()))
of.write('</div>\n')
except (IOError,OSError),msg:
ErrorDialog(str(msg))
note_obj = obj.get_note_object()
if note_obj:
text = note_obj.get()
if note_obj.get_format():
of.write('<pre>\n%s\n</pre>\n' % text)
else:
of.write('<p>')
of.write('</p><p>'.join(text.split('\n')))
of.write('</p>')
self.display_footer(of)
self.close_file(of)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class SourcesPage(BasePage):
def __init__(self, db, title, handle_set, options, archive, media_list):
BasePage.__init__(self, title, options, archive, media_list)
of = self.create_file("sources")
self.display_header(of,_('Sources'),
get_researcher().get_name())
handle_list = list(handle_set)
msg = _("This page contains an index of all the sources in the "
"database, sorted by their title. Clicking on a sources's "
"title will take you to that sources's page.")
of.write('<h3>%s</h3>\n<p>' % _('Sources'))
of.write(msg)
of.write('</p>\n<blockquote>\n<table class="infolist">\n')
index = 1
for handle in handle_list:
source = db.get_source_from_handle(handle)
of.write('<tr><td class="category">%d.</td>\n' % index)
of.write('<td class="data">')
of.write('<a href="%s.%s">' % (handle,self.ext))
of.write('%s&nbsp;<span class="grampsid">[%s]</span>' % (source.get_title(),source.gramps_id))
of.write('</a></td></tr>\n')
index += 1
of.write('</table>\n</blockquote>\n')
self.display_footer(of)
self.close_file(of)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class SourcePage(BasePage):
def __init__(self, db, title, handle, src_list, options, archive, media_list):
source = db.get_source_from_handle( handle)
BasePage.__init__(self, title, options, archive, media_list)
of = self.create_file(source.get_handle())
source_name = source.get_title()
self.display_header(of,"%s - %s" % (_('Sources'), source_name),get_researcher().get_name())
self.display_first_image_as_thumbnail(of, db, source.get_media_list())
of.write('<div class="summaryarea">\n')
of.write('<h3>%s</h3>\n' % source_name)
of.write('<table class="infolist" cellpadding="0" cellspacing="0" ')
of.write('border="0">\n')
for (label,val) in [(_('GRAMPS ID'),source.gramps_id),
(_('Author'),source.author),
(_('Publication information'),source.pubinfo),
(_('Abbreviation'),source.abbrev)]:
if val:
of.write('<tr><td class="field">%s</td>\n' % label)
of.write('<td class="data">%s</td>\n' % val)
of.write('</tr>\n')
of.write('</table>\n')
of.write('</div>\n')
# TODO: Add more information
self.display_additional_images_as_gallery(of, db, source.get_media_list())
self.display_note_object(of, source.get_note_object())
self.display_references(of,db,src_list[source.handle])
self.display_footer(of)
self.close_file(of)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class GalleryPage(BasePage):
def __init__(self, db, title, handle_set, options, archive, media_list):
BasePage.__init__(self, title, options, archive, media_list)
of = self.create_file("gallery")
self.display_header(of, _('Gallery'), get_researcher().get_name())
of.write('<h3>%s</h3>\n<p>' % _('Gallery'))
of.write(_("This page contains an index of all the media objects in the "
"database, sorted by their title. Clicking on the title will "
"take you to that media object's page"))
of.write('</p>\n<blockquote>\n<table class="infolist">\n')
self.db = db
index = 1
media_list.sort(self.by_media_title)
for handle in media_list:
media = db.get_object_from_handle(handle)
of.write('<tr><td class="category">%d.</td>\n' % index)
of.write('<td class="data">')
of.write('<a href="%s.%s">' % (handle,self.ext))
of.write(media.get_description())
of.write('</a>\n')
of.write('</td></tr>\n')
index += 1
of.write('</table>\n</blockquote>\n')
self.display_footer(of)
self.close_file(of)
def by_media_title(self,a_id,b_id):
"""Sort routine for comparing two events by their dates. """
if not (a_id and b_id):
return False
a = self.db.get_object_from_handle(a_id)
b = self.db.get_object_from_handle(b_id)
return cmp(a.desc,b.desc)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class DownloadPage(BasePage):
def __init__(self, db, title, options, archive, media_list):
BasePage.__init__(self, title, options, archive, media_list)
of = self.create_file("download")
self.display_header(of,_('Download'),
get_researcher().get_name())
of.write('<h3>%s</h3>\n' % _('Download'))
self.display_footer(of)
self.close_file(of)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class ContactPage(BasePage):
def __init__(self, db, title, options, archive, media_list):
BasePage.__init__(self, title, options, archive, media_list)
of = self.create_file("contact")
self.display_header(of,_('Contact'),
get_researcher().get_name())
of.write('<div class="summaryarea">\n')
of.write('<h3>%s</h3>\n' % _('Contact'))
note_id = options.handler.options_dict['NWEBcontact']
if note_id:
obj = db.get_object_from_handle(note_id)
if obj:
mime_type = obj.get_mime_type()
if mime_type and mime_type.startswith("image"):
try:
newpath = self.copy_media(obj)
of.write('<div class="rightwrap">\n')
of.write('<table cellspacing="0" cellpadding="0" border="0"><tr>')
of.write('<td height="205">')
of.write('<img border="0" height="200" ')
of.write('src="%s.%s" alt="%s" />' % (note_id,self.ext,obj.get_description()))
of.write('</td></tr></table>\n')
of.write('</div>\n')
except (IOError,OSError),msg:
ErrorDialog(str(msg))
r = get_researcher()
of.write('<blockquote>\n')
of.write('%s<br>\n' % r.name)
of.write('%s<br>\n' % r.addr)
of.write('%s, %s, %s<br>\n' % (r.city,r.state,r.postal))
of.write('%s<br>\n' % r.country)
of.write('%s<br>\n' % r.email)
of.write('</blockquote>\n')
if obj:
nobj = obj.get_note_object()
if nobj:
format = nobj.get_format()
text = nobj.get()
if format:
text = u"<pre>" + u"<br>".join(text.split("\n"))+u"</pre>"
else:
text = u"</p><p>".join(text.split("\n"))
of.write('<p>%s</p>\n' % text)
else:
of.write('<br><br><br><br>\n')
else:
of.write('<br><br><br><br>\n')
of.write('</div>\n')
self.display_footer(of)
self.close_file(of)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class IndividualPage(BasePage):
gender_map = {
RelLib.Person.MALE : const.male,
RelLib.Person.FEMALE : const.female,
RelLib.Person.UNKNOWN : const.unknown,
}
def __init__(self, db, person, title, ind_list,
place_list, src_list, options, archive, media_list):
BasePage.__init__(self, title, options, archive, media_list)
self.person = person
self.db = db
self.ind_list = ind_list
self.src_list = src_list
self.src_refs = []
self.place_list = place_list
self.sort_name = sort_nameof(self.person,self.private)
self.name = sort_nameof(self.person,self.private)
of = self.create_file(person.handle)
self.display_header(of, self.sort_name,
get_researcher().get_name())
self.display_ind_general(of)
self.display_ind_events(of)
self.display_attr_list(of, self.person.get_attribute_list())
self.display_ind_parents(of)
self.display_ind_relationships(of)
media_list = []
photolist = self.person.get_media_list()
if len(photolist) > 1:
media_list = photolist[1:]
for handle in self.person.get_family_handle_list():
family = self.db.get_family_from_handle(handle)
media_list = media_list + family.get_media_list()
self.display_additional_images_as_gallery(of, db, media_list)
self.display_note_object(of, self.person.get_note_object())
self.display_url_list(of, self.person.get_url_list())
self.display_ind_sources(of)
self.display_ind_pedigree(of)
self.display_footer(of)
self.close_file(of)
def display_ind_sources(self,of):
sreflist = self.src_refs + self.person.get_source_references()
if not sreflist:
return
of.write('<h4>%s</h4>\n' % _('Source Referencess'))
of.write('<hr>\n')
of.write('<table class="infolist" cellpadding="0" ')
of.write('cellspacing="0" border="0">\n')
index = 1
for sref in sreflist:
shandle = sref.get_base_handle()
if self.src_list.has_key(shandle):
if self.person.handle not in self.src_list[shandle]:
self.src_list[shandle].append(self.person.handle)
else:
self.src_list[shandle] = [self.person.handle]
source = self.db.get_source_from_handle(shandle)
title = source.get_title()
of.write('<tr><td class="field"><a name="sref%d">%d.</a></td>' % (index,index))
of.write('<td class="field"><a href="%s.%s">' % (source.handle,self.ext))
of.write('%s <span class="grampsid">[%s]</span>' %(title,source.gramps_id))
of.write('</a>')
tmp = []
for (label,data) in [(_('Page'),sref.page),
(_('Confidence'),const.confidence[sref.confidence]),
(_('Text'),sref.text)]:
if data:
tmp.append("%s: %s" % (label,data))
if len(tmp) > 0:
of.write('<br>' + '<br>'.join(tmp))
of.write('</td></tr>\n')
index += 1
of.write('</table>\n')
def display_ind_pedigree(self,of):
parent_handle_list = self.person.get_parent_family_handle_list()
if parent_handle_list:
(parent_handle, mrel,frel) = parent_handle_list[0]
family = self.db.get_family_from_handle(parent_handle)
father_id = family.get_father_handle()
mother_id = family.get_mother_handle()
mother = self.db.get_person_from_handle(mother_id)
father = self.db.get_person_from_handle(father_id)
else:
family = None
father = None
mother = None
of.write('<h4>%s</h4>\n' % _('Pedigree'))
of.write('<hr>\n<br>\n')
of.write('<table class="pedigree">\n')
of.write('<tr><td>\n')
if father or mother:
of.write('<blockquote class="pedigreeind">\n')
if father:
self.pedigree_person(of,father)
if mother:
self.pedigree_person(of,mother)
of.write('<blockquote class="pedigreeind">\n')
if family:
for child_handle in family.get_child_handle_list():
if child_handle == self.person.handle:
of.write('| <strong>%s</strong><br>\n' % self.name)
self.pedigree_family(of)
else:
child = self.db.get_person_from_handle(child_handle)
self.pedigree_person(of,child)
else:
of.write('| <strong>%s</strong><br>\n' % self.name)
self.pedigree_family(of)
of.write('</blockquote>\n')
if father or mother:
of.write('</blockquote>\n')
of.write('</td>\n</tr>\n</table>\n')
def display_ind_general(self,of):
self.display_first_image_as_thumbnail(of, self.db, self.person.get_media_list())
of.write('<div class="summaryarea">\n')
of.write('<h3>%s</h3>\n' % self.sort_name)
of.write('<table class="infolist" cellpadding="0" cellspacing="0" ')
of.write('border="0">\n')
# GRAMPS ID
if not self.noid:
of.write('<tr><td class="field">%s</td>\n' % _('GRAMPS ID'))
of.write('<td class="data">%s</td>\n' % self.person.gramps_id)
of.write('</tr>\n')
# Names [and their sources]
for name in [self.person.get_primary_name(),]+self.person.get_alternate_names():
pname = name_nameof(name,self.private)
of.write('<tr><td class="field">%s</td>\n' % _(name.get_type()))
of.write('<td class="data">%s' % pname)
nshl = []
for nsref in name.get_source_references():
self.src_refs.append(nsref)
nsh = nsref.get_base_handle()
if self.src_list.has_key(nsh):
if self.person.handle not in self.src_list[nsh]:
self.src_list[nsh].append(self.person.handle)
else:
self.src_list[nsh] = [self.person.handle]
nshl.append(nsref)
if nshl:
of.write( " <sup>")
for nsh in nshl:
index = self.src_refs.index(nsh)+1
of.write(' <a href="#sref%d">%d</a>' % (index,index))
of.write( " </sup>")
of.write('</td>\n</tr>\n')
# Gender
of.write('<tr><td class="field">%s</td>\n' % _('Gender'))
gender = self.gender_map[self.person.gender]
of.write('<td class="data">%s</td>\n' % gender)
of.write('</tr>\n</table>\n</div>\n')
def display_ind_events(self,of):
if len(self.person.get_event_list()) == 0:
return
of.write('<h4>%s</h4>\n' % _('Events'))
of.write('<hr>\n')
of.write('<table class="infolist" cellpadding="0" cellspacing="0" ')
of.write('border="0">\n')
# Birth
handle = self.person.get_birth_handle()
if handle:
event = self.db.get_event_from_handle(handle)
of.write('<tr><td class="field">%s</td>\n' % _('Birth'))
of.write('<td class="data">%s</td>\n' % self.format_event(event))
of.write('</tr>\n')
# Death
handle = self.person.get_death_handle()
if handle:
event = self.db.get_event_from_handle(handle)
of.write('<tr><td class="field">%s</td>\n' % _('Death'))
of.write('<td class="data">%s</td>\n' % self.format_event(event))
of.write('</tr>\n')
for event_id in self.person.get_event_list():
event = self.db.get_event_from_handle(event_id)
of.write('<tr><td class="field">%s</td>\n' % event.get_name())
of.write('<td class="data">\n')
of.write(self.format_event(event))
of.write('</td>\n')
of.write('</tr>\n')
of.write('</table>\n')
def display_child_link(self, of, child_handle):
use_link = child_handle in self.ind_list
child = self.db.get_person_from_handle(child_handle)
gid = child.get_gramps_id()
if use_link:
of.write('<a href="%s.%s">' % (child.handle,self.ext))
of.write(nameof(child,self.private))
if not self.noid:
of.write('&nbsp;<span class="grampsid">[%s]</span>' % gid)
if use_link:
of.write('</a>\n')
of.write(u"<br>\n")
def display_parent(self, of, handle, title, rel):
use_link = handle in self.ind_list
person = self.db.get_person_from_handle(handle)
of.write('<td class="field">%s</td>\n' % title)
of.write('<td class="data">')
val = person.gramps_id
if use_link:
of.write('<a href="%s.%s">' % (person.handle,self.ext))
of.write(nameof(person,self.private))
if not self.noid:
of.write('&nbsp;<span class="grampsid">[%s]</span>' % (val))
if use_link:
of.write('</a>')
if rel != RelLib.Person.CHILD_REL_BIRTH:
of.write('&nbsp;&nbsp;&nbsp;(%s)' % const.child_rel_list[rel])
of.write('</td>\n')
def display_ind_parents(self,of):
parent_list = self.person.get_parent_family_handle_list()
if not parent_list:
return
of.write('<h4>%s</h4>\n' % _("Parents"))
of.write('<hr>\n')
of.write('<table class="infolist" cellpadding="0" ')
of.write('cellspacing="0" border="0">\n')
first = True
if parent_list:
for (family_handle,mrel,frel) in parent_list:
family = self.db.get_family_from_handle(family_handle)
if not first:
of.write('<tr><td colspan="2">&nbsp;</td></tr>\n')
else:
first = False
father_handle = family.get_father_handle()
if father_handle:
self.display_parent(of,father_handle,_('Father'),frel)
of.write('<tr>\n')
mother_handle = family.get_mother_handle()
if mother_handle:
self.display_parent(of,mother_handle,_('Mother'),mrel)
of.write('</tr>\n')
first = False
childlist = family.get_child_handle_list()
if len(childlist) > 1:
of.write('<tr>\n')
of.write('<td class="field">%s</td>\n' % _("Siblings"))
of.write('<td class="data">\n')
for child_handle in childlist:
if child_handle != self.person.handle:
self.display_child_link(of,child_handle)
of.write('</td>\n</tr>\n')
of.write('<tr><td colspan="3">&nbsp;</td></tr>\n')
of.write('</table>\n')
def display_ind_relationships(self,of):
family_list = self.person.get_family_handle_list()
if not family_list:
return
of.write('<h4>%s</h4>\n' % _("Families"))
of.write('<hr>\n')
of.write('<table class="infolist" cellpadding="0" ')
of.write('cellspacing="0" border="0">\n')
first = True
for family_handle in family_list:
family = self.db.get_family_from_handle(family_handle)
self.display_spouse(of,family,first)
first = False
childlist = family.get_child_handle_list()
if childlist:
of.write('<tr><td>&nbsp;</td>\n')
of.write('<td class="field">%s</td>\n' % _("Children"))
of.write('<td class="data">\n')
for child_handle in childlist:
self.display_child_link(of,child_handle)
of.write('</td>\n</tr>\n')
of.write('</table>\n')
def display_spouse(self,of,family,first=True):
gender = self.person.get_gender()
reltype = family.get_relationship()
if reltype == RelLib.Family.MARRIED:
if gender == RelLib.Person.FEMALE:
relstr = _("Husband")
elif gender == RelLib.Person.MALE:
relstr = _("Wife")
else:
relstr = _("Partner")
else:
relstr = _("Partner")
spouse_id = ReportUtils.find_spouse(self.person,family)
if spouse_id:
spouse = self.db.get_person_from_handle(spouse_id)
name = nameof(spouse,self.private)
else:
name = _("unknown")
if not first:
of.write('<tr><td colspan="3">&nbsp;</td></tr>\n')
rtype = const.family_relations[family.get_relationship()][0]
of.write('<tr><td class="category">%s</td>\n' % rtype)
of.write('<td class="field">%s</td>\n' % relstr)
of.write('<td class="data">')
if spouse_id:
use_link = spouse_id in self.ind_list
gid = spouse.get_gramps_id()
if use_link:
of.write('<a href="%s.%s">' % (spouse.handle,self.ext))
of.write(name)
if not self.noid:
of.write('&nbsp;<span class="grampsid">[%s]</span>' % (gid))
if use_link:
of.write('</a>')
of.write('</td>\n</tr>\n')
for event_id in family.get_event_list():
event = self.db.get_event_from_handle(event_id)
of.write('<tr><td>&nbsp;</td>\n')
of.write('<td class="field">%s</td>\n' % event.get_name())
of.write('<td class="data">\n')
of.write(self.format_event(event))
of.write('</td>\n</tr>\n')
for attr in family.get_attribute_list():
type = attr.get_type()
value = attr.get_value()
of.write('<tr><td>&nbsp;</td>\n')
of.write('<td class="field">%s</td>' % _(type))
of.write('<td class="data">%s</td>\n</tr>\n' % value)
nobj = family.get_note_object()
if nobj:
of.write('<tr><td>&nbsp;</td>\n')
of.write('<td class="field">%s</td>\n' % _('Narrative'))
of.write('<td class="data">\n')
format = nobj.get_format()
text = nobj.get()
if format:
of.write( u"<pre>" + u"<br>".join(text.split("\n"))+u"</pre>")
else:
of.write( u"</p><p>".join(text.split("\n")))
of.write('</td>\n</tr>\n')
def pedigree_person(self,of,person,bullet='|'):
person_link = person.handle in self.ind_list
of.write('%s ' % bullet)
if person_link:
of.write('<a href="%s.%s">' % (person.handle,self.ext))
of.write(nameof(person,self.private))
if person_link:
of.write('</a>')
of.write('<br>\n')
def pedigree_family(self,of):
for family_handle in self.person.get_family_handle_list():
rel_family = self.db.get_family_from_handle(family_handle)
spouse_handle = ReportUtils.find_spouse(self.person,rel_family)
if spouse_handle:
spouse = self.db.get_person_from_handle(spouse_handle)
self.pedigree_person(of,spouse,'&bull;')
childlist = rel_family.get_child_handle_list()
if childlist:
of.write('<blockquote class="pedigreeind">\n')
for child_handle in childlist:
child = self.db.get_person_from_handle(child_handle)
self.pedigree_person(of,child)
of.write('</blockquote>\n')
def format_event(self,event):
gid_list = []
for sref in event.get_source_references():
handle = sref.get_base_handle()
gid_list.append(sref)
if self.src_list.has_key(handle):
if self.person.handle not in self.src_list[handle]:
self.src_list[handle].append(self.person.handle)
else:
self.src_list[handle] = [self.person.handle]
self.src_refs.append(sref)
descr = event.get_description()
place_handle = event.get_place_handle()
if place_handle:
if self.place_list.has_key(place_handle):
if self.person.handle not in self.place_list[place_handle]:
self.place_list[place_handle].append(self.person.handle)
else:
self.place_list[place_handle] = [self.person.handle]
place = '<a href="%s.%s">%s</a>' % (place_handle,self.ext,ReportUtils.place_name(self.db,place_handle))
else:
place = u""
date = _dd.display(event.get_date_object())
tmap = {'description' : descr, 'date' : date, 'place' : place}
if descr and date and place:
text = _('%(description)s,&nbsp;&nbsp;%(date)s&nbsp;&nbsp;at&nbsp;&nbsp;%(place)s') % tmap
elif descr and date:
text = _('%(description)s,&nbsp;&nbsp;%(date)s&nbsp;&nbsp;') % tmap
elif descr:
text = descr
elif date and place:
text = _('%(date)s&nbsp;&nbsp;at&nbsp;&nbsp;%(place)s') % tmap
elif date:
text = date
elif place:
text = place
else:
text = '\n'
if len(gid_list) > 0:
text = text + " <sup>"
for ref in gid_list:
index = self.src_refs.index(ref)+1
text = text + ' <a href="#sref%d">%d</a>' % (index,index)
text = text + "</sup>"
return text
#------------------------------------------------------------------------
#
# WebReport
#
#------------------------------------------------------------------------
class WebReport(Report.Report):
def __init__(self,database,person,options_class):
"""
Creates WebReport object that produces the report.
The arguments are:
database - the GRAMPS database instance
person - currently selected person
options_class - instance of the Options class for this report
This report needs the following parameters (class variables)
that come in the options class.
filter
od
NWEBimg
NWEBrestrictinfo
NWEBincpriv
NWEBnotxtsi
NWEBlnktoalphabet
NWEBsplita
NWEBplaceidx
NWEBshorttree
NWEBidxcol
NWEBimagedir
NWEBincid
NWEBidurl
NWEBlinktidx
NWEBext
NWEBencoding
NWEBtreed
NWEBidxt
NWEBidxbirth
NWEBintronote
NWEBhomenote
NWEBnoid
yearso
"""
self.database = database
self.start_person = person
self.options_class = options_class
filter_num = options_class.get_filter_number()
filters = options_class.get_report_filters(person)
filters.extend(GenericFilter.CustomFilters.get_filters())
self.filter = filters[filter_num]
self.target_path = options_class.handler.options_dict['NWEBod']
self.ext = options_class.handler.options_dict['NWEBext']
self.encoding = options_class.handler.options_dict['NWEBencoding']
self.css = options_class.handler.options_dict['NWEBcss']
self.id_link = options_class.handler.options_dict['NWEBlinktidx']
self.photos = options_class.handler.options_dict['NWEBimg']
self.restrict = options_class.handler.options_dict['NWEBrestrictinfo']
self.private = options_class.handler.options_dict['NWEBincpriv']
self.noid = options_class.handler.options_dict['NWEBnoid']
self.srccomments = options_class.handler.options_dict['NWEBcmtxtsi']
self.image_dir = options_class.handler.options_dict['NWEBimagedir']
self.title = options_class.handler.options_dict['NWEBtitle']
self.separate_alpha = options_class.handler.options_dict['NWEBsplita']
self.depth = options_class.handler.options_dict['NWEBtreed']
self.sort = Sort.Sort(self.database)
self.inc_contact = options_class.handler.options_dict['NWEBcontact'] != u""
self.inc_download = options_class.handler.options_dict['NWEBdownload']
self.use_archive = options_class.handler.options_dict['NWEBarchive']
self.use_intro = options_class.handler.options_dict['NWEBintronote'] != u""
def get_progressbar_data(self):
return (_("Generate HTML reports - GRAMPS"),
'<span size="larger" weight="bold">%s</span>' %
_("Creating Web Pages"))
def write_report(self):
if not self.use_archive:
dir_name = self.target_path
if dir_name == None:
dir_name = os.getcwd()
elif not os.path.isdir(dir_name):
parent_dir = os.path.dirname(dir_name)
if not os.path.isdir(parent_dir):
ErrorDialog(_("Neither %s nor %s are directories") % \
(dir_name,parent_dir))
return
else:
try:
os.mkdir(dir_name)
except IOError, value:
ErrorDialog(_("Could not create the directory: %s") % \
dir_name + "\n" + value[1])
return
except:
ErrorDialog(_("Could not create the directory: %s") % \
dir_name)
return
if self.image_dir:
image_dir_name = os.path.join(dir_name, self.image_dir)
else:
image_dir_name = dir_name
if not os.path.isdir(image_dir_name) and self.photos != 0:
try:
os.mkdir(image_dir_name)
except IOError, value:
ErrorDialog(_("Could not create the directory: %s") % \
image_dir_name + "\n" + value[1])
return
except:
ErrorDialog(_("Could not create the directory: %s") % \
image_dir_name)
return
ind_list = self.database.get_person_handles(sort_handles=False)
ind_list = self.filter.apply(self.database,ind_list)
if not self.private:
new_list = []
for key in ind_list:
if not self.database.get_person_from_handle(key).private:
new_list.append(key)
ind_list = new_list
progress_steps = len(ind_list)
if len(ind_list) > 1:
progress_steps = progress_steps+1
progress_steps = progress_steps+1
self.progress_bar_setup(float(progress_steps))
if self.use_archive:
import TarFile
archive = TarFile.TarFile(self.target_path)
else:
archive = None
self.write_css(archive,self.target_path,self.css)
photo_list = []
HomePage(self.database, self.title, self.options_class, archive, photo_list)
if self.inc_contact:
ContactPage(self.database, self.title, self.options_class,
archive, photo_list)
if self.inc_download:
DownloadPage(self.database, self.title, self.options_class,
archive, photo_list)
if self.use_intro:
IntroductionPage(self.database, self.title, self.options_class,
archive, photo_list)
place_list = {}
source_list = {}
for person_handle in ind_list:
person = self.database.get_person_from_handle(person_handle)
if not self.private:
person = ReportUtils.sanitize_person(self.database,person)
idoc = IndividualPage(self.database, person, self.title,
ind_list, place_list, source_list,
self.options_class, archive, photo_list)
self.progress_bar_step()
while gtk.events_pending():
gtk.main_iteration()
if len(ind_list) > 1:
IndividualListPage(self.database, self.title, ind_list,
self.options_class, archive, photo_list)
SurnameListPage(self.database, self.title, ind_list,
self.options_class, archive, photo_list)
self.progress_bar_step()
while gtk.events_pending():
gtk.main_iteration()
PlaceListPage(self.database, self.title, place_list,
source_list,self.options_class, archive, photo_list)
for place in place_list.keys():
PlacePage(self.database, self.title, place, source_list, place_list,
self.options_class, archive, photo_list)
SourcesPage(self.database,self.title, source_list.keys(), self.options_class,
archive, photo_list)
for key in list(source_list):
SourcePage(self.database,self.title, key, source_list, self.options_class,
archive, photo_list)
GalleryPage(self.database, self.title, source_list, self.options_class,
archive, photo_list)
for photo_handle in photo_list:
MediaPage(self.database, self.title, photo_handle, source_list,
self.options_class, archive, photo_list)
if archive:
archive.close()
self.progress_bar_done()
def write_css(self,archive,html_dir,css_file):
if archive:
f = open(os.path.join(const.dataDir,css_file),"r")
archive.add_file(_NARRATIVE,time.time(),f)
f.close()
else:
shutil.copyfile(os.path.join(const.dataDir,css_file),
os.path.join(html_dir,_NARRATIVE))
def add_styles(self,doc):
pass
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class WebReportOptions(ReportOptions.ReportOptions):
"""
Defines options and provides handling interface.
"""
def __init__(self,name,database,person_id=None):
ReportOptions.ReportOptions.__init__(self,name,person_id)
self.db = database
def set_new_options(self):
# Options specific for this report
self.options_dict = {
'NWEBarchive' : 0,
'NWEBod' : './',
'NWEBimg' : 2,
'NWEBrestrictinfo' : 0,
'NWEBincpriv' : 0,
'NWEBnoid' : 0,
'NWEBcmtxtsi' : 0,
'NWEBlnktoalphabet' : 0,
'NWEBsplita' : 0,
'NWEBcontact' : '',
'NWEBdownload' : 0,
'NWEBshorttree' : 1,
'NWEBimagedir' : 'images',
'NWEBtitle' : _('My Family Tree'),
'NWEBincid' : 0,
'NWEBidurl' : '',
'NWEBlinktidx' : 1,
'NWEBext' : 'html',
'NWEBencoding' : 'utf-8',
'NWEBcss' : 'main0.css',
'NWEBtreed' : 3,
'NWEBidxt' : '',
'NWEBintronote' : '',
'NWEBhomenote' : '',
'NWEBidxbirth' : 0,
'NWEBplaceidx' : 0,
'NWEByearso' : 1,
}
self.options_help = {
}
def enable_options(self):
# Semi-common options that should be enabled for this report
self.enable_dict = {
'filter' : 0,
}
def get_report_filters(self,person):
"""Set up the list of possible content filters."""
if person:
name = person.get_primary_name().get_name()
gramps_id = person.get_gramps_id()
else:
name = 'PERSON'
gramps_is = ''
all = GenericFilter.GenericFilter()
all.set_name(_("Entire Database"))
all.add_rule(GenericFilter.Everyone([]))
des = GenericFilter.GenericFilter()
des.set_name(_("Descendants of %s") % name)
des.add_rule(GenericFilter.IsDescendantOf([gramps_id,1]))
df = GenericFilter.GenericFilter()
df.set_name(_("Descendant Families of %s") % name)
df.add_rule(GenericFilter.IsDescendantFamilyOf([gramps_id]))
ans = GenericFilter.GenericFilter()
ans.set_name(_("Ancestors of %s") % name)
ans.add_rule(GenericFilter.IsAncestorOf([gramps_id,1]))
com = GenericFilter.GenericFilter()
com.set_name(_("People with common ancestor with %s") % name)
com.add_rule(GenericFilter.HasCommonAncestorWith([gramps_id]))
return [all,des,df,ans,com]
def add_user_options(self,dialog):
priv_msg = _("Do not include records marked private")
restrict_msg = _("Restrict information on living people")
no_img_msg = _("Do not use images")
no_limg_msg = _("Do not use images for living people")
no_com_msg = _("Do not include comments and text in source information")
imgdir_msg = _("Image subdirectory")
title_msg = _("Web site title")
ext_msg = _("File extension")
sep_alpha_msg = _("Split alphabetical sections to separate pages")
tree_msg = _("Include short ancestor tree")
contact_msg = _("Publisher contact/Note ID")
download_msg = _("Include download page")
self.no_private = gtk.CheckButton(priv_msg)
self.no_private.set_active(not self.options_dict['NWEBincpriv'])
self.noid = gtk.CheckButton(_('Suppress GRAMPS ID'))
self.noid.set_active(self.options_dict['NWEBnoid'])
self.restrict_living = gtk.CheckButton(restrict_msg)
self.restrict_living.set_active(self.options_dict['NWEBrestrictinfo'])
self.inc_download = gtk.CheckButton(download_msg)
self.inc_download.set_active(self.options_dict['NWEBdownload'])
# FIXME: document this:
# 0 -- no images of any kind
# 1 -- no living images, but some images
# 2 -- any images
images = self.options_dict['NWEBimg']
self.no_images = gtk.CheckButton(no_img_msg)
self.no_images.set_active(not images)
self.no_living_images = gtk.CheckButton(no_limg_msg)
self.no_living_images.set_sensitive(not images)
self.no_living_images.set_active(images in (0,1))
self.no_comments = gtk.CheckButton(no_com_msg)
self.no_comments.set_active(not self.options_dict['NWEBcmtxtsi'])
self.imgdir = gtk.Entry()
self.imgdir.set_text(self.options_dict['NWEBimagedir'])
self.intro_note = gtk.Entry()
self.intro_note.set_text(self.options_dict['NWEBintronote'])
self.title = gtk.Entry()
self.title.set_text(self.options_dict['NWEBtitle'])
self.linkpath = gtk.Entry()
self.linkpath.set_sensitive(self.options_dict['NWEBincid'])
self.linkpath.set_text(self.options_dict['NWEBidurl'])
self.ext = gtk.combo_box_new_text()
self.ext_options = ['.html','.htm','.shtml','.php','.php3','.cgi']
for text in self.ext_options:
self.ext.append_text(text)
def_ext = "." + self.options_dict['NWEBext']
self.ext.set_active(self.ext_options.index(def_ext))
cset_node = None
cset = self.options_dict['NWEBencoding']
store = gtk.ListStore(str,str)
for data in _character_sets:
if data[1] == cset:
cset_node = store.append(row=data)
else:
store.append(row=data)
self.encoding = GrampsNoteComboBox(store,cset_node)
cset_node = None
cset = self.options_dict['NWEBcss']
store = gtk.ListStore(str,str)
for data in _css_files:
if data[1] == cset:
cset_node = store.append(row=data)
else:
store.append(row=data)
self.css = GrampsNoteComboBox(store,cset_node)
dialog.add_option(title_msg,self.title)
dialog.add_option(imgdir_msg,self.imgdir)
dialog.add_option(ext_msg,self.ext)
dialog.add_option(_('Character set encoding'),self.encoding)
dialog.add_option(_('Stylesheet'),self.css)
title = _("Page Generation")
cursor = self.db.get_media_cursor()
media_list = [['',None]]
data = cursor.first()
while data:
(handle, value) = data
media_list.append([value[4],handle])
data = cursor.next()
cursor.close()
media_list.sort()
self.home_note = build_combo_box(media_list,self.options_dict['NWEBhomenote'])
self.intro_note = build_combo_box(media_list,self.options_dict['NWEBintronote'])
self.contact = build_combo_box(media_list,self.options_dict['NWEBcontact'])
dialog.add_frame_option(title,_('Home Media/Note ID'),
self.home_note)
dialog.add_frame_option(title,_('Introduction Media/Note ID'),
self.intro_note)
dialog.add_frame_option(title,contact_msg,self.contact)
dialog.add_frame_option(title,None,self.inc_download)
dialog.add_frame_option(title,None,self.noid)
title = _("Privacy")
dialog.add_frame_option(title,None,self.no_private)
dialog.add_frame_option(title,None,self.restrict_living)
dialog.add_frame_option(title,None,self.no_images)
dialog.add_frame_option(title,None,self.no_living_images)
dialog.add_frame_option(title,None,self.no_comments)
self.no_images.connect('toggled',self.on_nophotos_toggled)
def parse_user_options(self,dialog):
"""Parse the privacy options frame of the dialog. Save the
user selected choices for later use."""
self.options_dict['NWEBrestrictinfo'] = int(self.restrict_living.get_active())
self.options_dict['NWEBincpriv'] = int(not self.no_private.get_active())
self.options_dict['NWEBnoid'] = int(self.noid.get_active())
self.options_dict['NWEBcontact'] = unicode(self.contact.get_handle())
self.options_dict['NWEBdownload'] = int(self.inc_download.get_active())
self.options_dict['NWEBimagedir'] = unicode(self.imgdir.get_text())
self.options_dict['NWEBtitle'] = unicode(self.title.get_text())
self.options_dict['NWEBintronote'] = unicode(self.intro_note.get_handle())
self.options_dict['NWEBhomenote'] = unicode(self.home_note.get_handle())
index = self.ext.get_active()
if index >= 0:
html_ext = self.ext_options[index]
else:
html_ext = "html"
if html_ext[0] == '.':
html_ext = html_ext[1:]
self.options_dict['NWEBext'] = html_ext
self.options_dict['NWEBencoding'] = self.encoding.get_handle()
self.options_dict['NWEBcss'] = self.css.get_handle()
self.options_dict['NWEBidurl'] = unicode(self.linkpath.get_text().strip())
self.options_dict['NWEBcmtxtsi'] = int(not self.no_comments.get_active())
if self.no_images.get_active():
photos = 0
elif self.no_living_images.get_active():
photos = 1
else:
photos = 2
self.options_dict['NWEBimg'] = photos
self.options_dict['NWEBod'] = dialog.target_path
#------------------------------------------------------------------------
#
# Callback functions from the dialog
#
#------------------------------------------------------------------------
def show_link(self,obj):
self.linkpath.set_sensitive(obj.get_active())
def on_nophotos_toggled(self,obj):
"""Keep the 'restrict photos' checkbox in line with the 'no
photos' checkbox. If there are no photos included, it makes
no sense to worry about restricting which photos are included,
now does it?"""
self.no_living_images.set_sensitive(not obj.get_active())
def make_default_style(self,default_style):
"""Make the default output style for the Web Pages Report."""
pass
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class WebReportDialog(Report.ReportDialog):
def __init__(self,database,person):
self.database = database
self.person = person
name = "navwebpage"
translated_name = _("Generate Web Site")
self.options_class = WebReportOptions(name,database)
self.category = const.CATEGORY_WEB
Report.ReportDialog.__init__(self,database,person,self.options_class,
name,translated_name)
self.style_name = None
response = self.window.run()
if response == gtk.RESPONSE_OK:
try:
self.make_report()
except (IOError,OSError),msg:
ErrorDialog(str(msg))
self.window.destroy()
def setup_style_frame(self):
"""The style frame is not used in this dialog."""
pass
def parse_style_frame(self):
"""The style frame is not used in this dialog."""
pass
def parse_html_frame(self):
self.options_class.handler.options_dict['NWEBarchive'] = self.archive.get_active()
def parse_paper_frame(self):
pass
def setup_html_frame(self):
self.html_table = gtk.Table(3,3)
self.html_table.set_col_spacings(12)
self.html_table.set_row_spacings(6)
self.html_table.set_border_width(0)
html_label = gtk.Label("<b>%s</b>" % _("HTML Options"))
html_label.set_alignment(0.0,0.5)
html_label.set_use_markup(True)
self.html_table.attach(html_label, 0, 3, 0, 1, gtk.FILL)
label = gtk.Label(_("HTML Options"))
self.output_notebook.append_page(self.html_table,label)
self.archive = gtk.CheckButton(_('Store web pages in .tar.gz archive'))
self.archive.set_alignment(0.0,0.5)
self.archive.connect('toggled',self.archive_toggle)
self.html_table.attach(self.archive, 1, 2, 1, 2, gtk.SHRINK|gtk.FILL)
def archive_toggle(self,obj):
if obj.get_active():
self.target_fileentry.set_directory_entry(False)
self.doc_label.set_label("%s:" % _("Filename"))
else:
self.target_fileentry.set_directory_entry(True)
self.doc_label.set_label("%s:" % _("Directory"))
def setup_paper_frame(self):
pass
def get_title(self):
"""The window title for this dialog"""
return "%s - %s - GRAMPS" % (_("Generate Web Site"),_("Web Page"))
def get_target_browser_title(self):
"""The title of the window created when the 'browse' button is
clicked in the 'Save As' frame."""
return _("Target Directory")
def get_target_is_directory(self):
"""This report creates a directory full of files, not a single file."""
return 1
def get_default_directory(self):
"""Get the name of the directory to which the target dialog
box should default. This value can be set in the preferences
panel."""
return self.options_class.handler.options_dict['NWEBod']
def make_document(self):
"""Do Nothing. This document will be created in the
make_report routine."""
pass
def setup_format_frame(self):
"""Do nothing, since we don't want a format frame (NWEB only)"""
pass
def setup_post_process(self):
"""The format frame is not used in this dialog. Hide it, and
set the output notebook to always display the html template
page."""
self.output_notebook.set_current_page(1)
def parse_format_frame(self):
"""The format frame is not used in this dialog."""
pass
def make_report(self):
"""Create the object that will produce the web pages."""
try:
MyReport = WebReport(self.database,self.person,
self.options_class)
MyReport.write_report()
except Errors.FilterError, msg:
(m1,m2) = msg.messages()
ErrorDialog(m1,m2)
def sort_people(db,handle_list):
import sets
flist = sets.Set(handle_list)
sname_sub = {}
sortnames = {}
cursor = db.get_person_cursor()
node = cursor.first()
while node:
if node[0] in flist:
primary_name = node[1][_NAME_COL]
if primary_name.group_as:
surname = primary_name.group_as
else:
surname = db.get_name_group_mapping(primary_name.surname)
sortnames[node[0]] = primary_name.sname
if sname_sub.has_key(surname):
sname_sub[surname].append(node[0])
else:
sname_sub[surname] = [node[0]]
node = cursor.next()
cursor.close()
sorted_lists = []
temp_list = sname_sub.keys()
temp_list.sort(locale.strcoll)
for name in temp_list:
slist = map(lambda x: (sortnames[x],x),sname_sub[name])
slist.sort(lambda x,y: locale.strcoll(x[0],y[0]))
entries = map(lambda x: x[1], slist)
sorted_lists.append((name,entries))
return sorted_lists
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def cl_report(database,name,category,options_str_dict):
clr = Report.CommandLineReport(database,name,category,WebReportOptions,options_str_dict)
# Exit here if show option was given
if clr.show:
return
try:
MyReport = WebReport(database,clr.person,clr.option_class)
MyReport.write_report()
except:
import DisplayTrace
DisplayTrace.DisplayTrace()
#------------------------------------------------------------------------
#
# Empty class to keep the BaseDoc-targeted format happy
#
#------------------------------------------------------------------------
class EmptyDoc:
def __init__(self,styles,type,template,orientation,source=None):
pass
def init(self):
pass
#-------------------------------------------------------------------------
#
# GrampsNoteComboBox
#
#-------------------------------------------------------------------------
class GrampsNoteComboBox(gtk.ComboBox):
"""
Derived from the ComboBox, this widget provides handling of Report
Styles.
"""
def __init__(self,model=None,node=None):
"""
Initializes the combobox, building the display column.
"""
gtk.ComboBox.__init__(self,model)
cell = gtk.CellRendererText()
self.pack_start(cell,True)
self.add_attribute(cell,'text',0)
if node:
self.set_active_iter(node)
else:
self.set_active(0)
self.local_store = model
def get_handle(self):
"""
Returns the selected key (style sheet name).
@returns: Returns the name of the selected style sheet
@rtype: str
"""
active = self.get_active_iter()
handle = u""
if active:
handle = self.local_store.get_value(active,1)
return handle
def build_combo_box(media_list,select_value):
store = gtk.ListStore(str,str)
node = None
for data in media_list:
if data[1] == select_value:
node = store.append(row=data)
else:
store.append(row=data)
widget = GrampsNoteComboBox(store,node)
if len(media_list) == 0:
widget.set_sensitive(False)
return widget
def nameof(person,private):
if person.private and private:
return _("Private")
else:
return _nd.display(person)
def name_nameof(name,private):
if name.private and private:
return _("Private")
else:
return _nd.display_name(name)
def sort_nameof(person, private):
if person.private and private:
return _("Private")
else:
return _nd.sorted(person)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
from PluginMgr import register_report
register_report(
name = 'navwebpage',
category = const.CATEGORY_WEB,
report_class = WebReportDialog,
options_class = cl_report,
modes = Report.MODE_GUI | Report.MODE_CLI,
translated_name = _("Narrative Web Site"),
status=(_("Beta")),
description=_("Generates web (HTML) pages for individuals, or a set of individuals."),
)