# # 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$ """ Narrative Web Page generator. """ #------------------------------------------------------------------------ # # python modules # #------------------------------------------------------------------------ import os import md5 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 import ImgManip from QuestionDialog import ErrorDialog, WarningDialog 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'], [_("No style sheet"), ''], ] _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', ], ] _cc = [ 'Creative Commons License', 'Creative Commons License', 'Creative Commons License', 'Creative Commons License', 'Creative Commons License', 'Creative Commons License', ] class BasePage: def __init__(self, title, options, archive, photo_list, levels, gid): self.title_str = title self.gid = gid self.inc_download = options.handler.options_dict['NWEBdownload'] self.html_dir = options.handler.options_dict['NWEBod'] self.copyright = options.handler.options_dict['NWEBcopyright'] self.options = options self.archive = archive 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.header = options.handler.options_dict['NWEBheader'] self.footer = options.handler.options_dict['NWEBfooter'] self.photo_list = photo_list self.exclude_private = not options.handler.options_dict['NWEBincpriv'] self.levels = levels def store_file(self,archive,html_dir,from_path,to_path): if archive: imagefile = open(from_path,"r") archive.add_file(to_path,time.time(),imagefile) imagefile.close() else: shutil.copyfile(from_path,os.path.join(html_dir,to_path)) def copy_media(self,photo,store_ref=True): handle = photo.get_handle() if store_ref: lnk = (self.cur_name,self.page_title,self.gid) if self.photo_list.has_key(handle): if lnk not in self.photo_list[handle]: self.photo_list[handle].append(lnk) else: self.photo_list[handle] = [lnk] newpath = photo.gramps_id + os.path.splitext(photo.get_path())[1] real_path = os.path.join('images',newpath) thumb_path = os.path.join('thumb',newpath) return (real_path,thumb_path) def create_file(self,name): self.cur_name = self.build_name("",name) if self.archive: self.string_io = StringIO() of = codecs.EncodedFile(self.string_io,'utf-8',self.encoding) else: page_name = os.path.join(self.html_dir,self.cur_name) of = codecs.EncodedFile(open(page_name, "w"),'utf-8',self.encoding) return of def link_path(self,name,path): base = self.build_name("",name) if self.levels == 2: dirpath = os.path.join(path,name[0],name[1],base) else: dirpath = os.path.join(path,name[0],base) return dirpath def create_link_file(self,name,path): self.cur_name = self.link_path(name,path) if self.archive: self.string_io = StringIO() of = codecs.EncodedFile(self.string_io,'utf-8',self.encoding) else: if self.levels == 1: dirname = os.path.join(self.html_dir,path,name[0]) else: dirname = os.path.join(self.html_dir,path,name[0],name[1]) if not os.path.isdir(dirname): os.makedirs(dirname) page_name = self.build_name(dirname,name) 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 md5.new(text).hexdigest() def display_footer(self,of,db): of.write('\n') of.write('



\n') if self.footer: obj = db.get_object_from_handle(self.footer) if obj: of.write('\n') of.write('\n') of.write('\n') def display_header(self,of,db,title,author="",up=False): self.up = up if up: if self.levels == 1: path = "../.." else: path = "../../.." else: path = "" self.author = author of.write('\n') of.write('\n\n') of.write('%s - %s\n' % (self.title_str, title)) of.write('\n' % self.encoding) if path: of.write('\n') of.write('\n') of.write('') of.write('\n') of.write('\n') if self.header: obj = db.get_object_from_handle(self.header) if obj: of.write('
\n') of.write(obj.get_note()) of.write('
\n') of.write('\n') of.write('
\n') def show_link(self,of,lpath,title,path): if path: of.write('%s  ' % (path,lpath,self.ext,title)) else: of.write('%s  ' % (lpath,self.ext,title)) 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: (real_path,newpath) = self.copy_media(photo) of.write('
\n') self.media_link(of,photo_handle,newpath,'',up=True) of.write('
\n') except (IOError,OSError),msg: WarningDialog(_("Could not add photo to page"),str(msg)) def display_additional_images_as_gallery( self, of, db, photolist=None): if not photolist and len(photolist) == 0: return of.write('

%s

\n' % _('Gallery')) of.write('
\n') of.write('
') for mediaref in photolist: photo_handle = mediaref.get_reference_handle() photo = db.get_object_from_handle(photo_handle) if photo.get_mime_type(): try: (real_path,newpath) = self.copy_media(photo) self.media_link(of,photo_handle,newpath, photo.get_description(),up=True) except (IOError,OSError),msg: WarningDialog(_("Could not add photo to page"),str(msg)) of.write('
') def display_note_object(self,of,noteobj=None): if not noteobj: return format = noteobj.get_format() text = noteobj.get() if text: of.write('

%s

\n' % _('Narrative')) of.write('
\n') if format: text = u"
" + u"
".join(text.split("\n"))+u"
" else: text = u"

".join(text.split("\n")) of.write('

%s

\n' % text) def display_url_list(self,of,urllist=None): if not urllist: return of.write('

%s

\n' % _('Weblinks')) of.write('
\n') of.write('\n') index = 1 for url in urllist: uri = url.get_path() descr = url.get_description() of.write('' % index) of.write('\n') index = index + 1 of.write('
%d.%s' % (uri,descr)) of.write('
\n') def display_attr_list(self,of,attrlist=None): if not attrlist: return of.write('

%s

\n' % _('Attributes')) of.write('
\n') of.write('\n') for attr in attrlist: type = attr.get_type() value = attr.get_value() of.write('' % _(type)) of.write('\n' % value) of.write('
%s%s
\n') def display_references(self,of,db,handlelist): if not handlelist: return of.write('

%s

\n' % _('References')) of.write('
\n') of.write('\n') index = 1 for (path,name,gid) in handlelist: of.write('\n') index = index + 1 of.write('
%d. ' % index) self.person_link(of,path,name,gid) of.write('
\n') def build_path(self,handle,dirroot,up): if up: if self.levels == 1: return '../../%s/%s' % (dirroot,handle[0]) elif self.levels == 2: return '../../../%s/%s/%s' % (dirroot,handle[0],handle[1]) else: return '%s/%s' % (dirroot,handle[0]) else: if self.levels == 2: return "%s/%s/%s" % (dirroot,handle[0],handle[1]) else: return "%s/%s" % (dirroot,handle[0]) def build_name(self,path,base): if path: return path + "/" + base + "." + self.ext else: return base + "." + self.ext def person_link(self,of,path,name,gid=""): if self.levels == 1: path = "../../" + path elif self.levels == 2: path = "../../../" + path of.write('%s' % (path,name)) if not self.noid and gid != "": of.write(' [%s]' % gid) of.write('') def surname_link(self,of,name,opt_val=None,up=False): handle = self.lnkfmt(name) dirpath = self.build_path(handle,'srn',up) of.write('%s' % (dirpath,handle,self.ext,name)) if opt_val != None: of.write(' (%d)' % opt_val) of.write('') def media_ref_link(self,of,handle,name,up=False): dirpath = self.build_path(handle,'img',up) of.write('%s' % ( dirpath,handle,self.ext,name)) def media_link(self,of,handle,path,name,up,usedescr=True): dirpath = self.build_path(handle,'img',up) of.write('' % ( dirpath,handle,self.ext)) of.write('%s' % (const.thumbScale,name)) if usedescr: of.write('
%s
' % name) of.write('') def source_link(self,of,handle,name,gid="",up=False): dirpath = self.build_path(handle,'src',up) of.write('%s' % ( dirpath,handle,self.ext,name)) if not self.noid and gid != "": of.write(' [%s]' % gid) of.write('') def place_link(self,of,handle,name,gid="",up=False): dirpath = self.build_path(handle,'plc',up) of.write('%s' % ( dirpath,handle,self.ext,name)) if not self.noid and gid != "": of.write(' [%s]' % gid) of.write('') def place_link_str(self,handle,name,gid="",up=False): dirpath = self.build_path(handle,'plc',up) retval = '%s' % ( dirpath,handle,self.ext,name) if not self.noid and gid != "": retval = retval + ' [%s]' % gid return retval + '' #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class IndividualListPage(BasePage): def __init__(self, db, title, person_handle_list, options, archive, media_list, levels): BasePage.__init__(self, title, options, archive, media_list, levels, "") of = self.create_file("individuals") self.display_header(of,db,_('Individuals'), get_researcher().get_name()) msg = _("This page contains an index of all the individuals in the " "database, sorted by their last names. Selecting the person's " "name will take you to that person's individual page.") of.write('

%s

\n' % _('Individuals')) of.write('

%s

\n' % msg) of.write('
\n') of.write('\n') of.write('\n' % _('Surname')) of.write('\n' % _('Name')) of.write('\n' % _('Birth date')) of.write('\n') person_handle_list = sort_people(db,person_handle_list) for (surname,handle_list) in person_handle_list: first = True of.write('\n') for person_handle in handle_list: person = db.get_person_from_handle(person_handle) of.write('\n') first = False of.write('
%s%s%s
 
') if first: of.write('%s' % (self.lnkfmt(surname),surname)) else: of.write(' ') of.write('') path = self.build_path(person.handle,"ppl",False) self.person_link(of, self.build_name(path,person.handle), person.get_primary_name().get_first_name(), person.gramps_id) of.write('') birth_handle = person.get_birth_handle() if birth_handle: birth = db.get_event_from_handle(birth_handle) of.write(birth.get_date()) of.write('
\n
\n') self.display_footer(of,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class SurnamePage(BasePage): def __init__(self, db, title, person_handle_list, options, archive, media_list, levels): BasePage.__init__(self, title, options, archive, media_list, levels, "") of = self.create_link_file(md5.new(title).hexdigest(),'srn') self.display_header(of,db,title,get_researcher().get_name(),True) msg = _("This page contains an index of all the individuals in the " "database with the surname of %s. Selecting the person's name " "will take you to that person's individual page.") % title of.write('

%s

\n' % title) of.write('

%s

\n' % msg) of.write('
\n') of.write('\n') of.write('\n' % _('Name')) of.write('\n' % _('Birth date')) of.write('\n') for person_handle in person_handle_list: person = db.get_person_from_handle(person_handle) of.write('\n') of.write('
%s%s
') path = self.build_path(person.handle,"ppl",False) self.person_link(of, self.build_name(path,person.handle), person.get_primary_name().get_first_name(), person.gramps_id) of.write('') birth_handle = person.get_birth_handle() if birth_handle: birth = db.get_event_from_handle(birth_handle) of.write(birth.get_date()) of.write('
\n
\n') self.display_footer(of,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class PlaceListPage(BasePage): def __init__(self, db, title, place_handles, src_list, options, archive, media_list, levels): BasePage.__init__(self, title, options, archive, media_list, levels, "") of = self.create_file("places") self.display_header(of,db,_('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('

%s

\n' % _('Places')) of.write('

%s

\n' % msg ) of.write('
\n') of.write('\n') of.write('\n' % _('Letter')) of.write('\n' % _('Place')) of.write('\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('\n') of.write('' % last_letter) of.write('') last_surname = n elif n != last_surname: of.write('') of.write('') last_surname = n of.write('
') of.write('%s') of.write('%s
 
%s') self.place_link(of,place.handle,n,place.gramps_id) of.write('
 ') self.place_link(of,place.handle,n,place.gramps_id) of.write('
\n
\n') self.display_footer(of,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class PlacePage(BasePage): def __init__(self, db, title, place_handle, src_list, place_list, options, archive, media_list, levels): place = db.get_place_from_handle( place_handle) BasePage.__init__(self, title, options, archive, media_list, levels, place.gramps_id) of = self.create_link_file(place.get_handle(),"plc") self.page_title = ReportUtils.place_name(db,place_handle) self.display_header(of,db,"%s - %s" % (_('Places'), self.page_title), get_researcher().get_name(),up=True) self.display_first_image_as_thumbnail(of, db, place.get_media_list()) of.write('
\n') of.write('

%s

\n' % self.page_title) of.write('\n') if not self.noid: of.write('\n' % _('GRAMPS ID')) of.write('\n' % place.gramps_id) of.write('\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('\n' % val[0]) of.write('\n' % val[1]) of.write('\n') if place.long: of.write('\n' % _('Longitude')) of.write('\n' % place.long) of.write('\n') if place.lat: of.write('\n' % _('Latitude')) of.write('\n' % place.lat) of.write('\n') of.write('
%s%s
%s%s
%s%s
%s%s
\n') of.write('
\n') 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,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class MediaPage(BasePage): def __init__(self, db, title, handle, src_list, options, archive, media_list, info, levels): (prev, next, page_number, total_pages) = info photo = db.get_object_from_handle(handle) BasePage.__init__(self, title, options, archive, media_list, levels, photo.gramps_id) of = self.create_link_file(handle,"img") newpath = photo.gramps_id + os.path.splitext(photo.get_path())[1] newpath = os.path.join('images',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)) to_path = photo.gramps_id + os.path.splitext(photo.get_path())[1] to_path = os.path.join('thumb',to_path) from_path = ImgManip.get_thumbnail_path(photo.get_path()) if self.archive: imagefile = open(from_path,"r") self.archive.add_file(to_path,time.time(),imagefile) imagefile.close() else: shutil.copyfile(from_path,os.path.join(self.html_dir,to_path)) self.page_title = photo.get_description() self.display_header(of,db, "%s - %s" % (_('Gallery'), title), get_researcher().get_name(),up=True) of.write('
\n') of.write('

%s

\n' % self.page_title) # gallery navigation of.write('
') if prev: self.media_ref_link(of,prev,_('Previous'),True) data = _('%(page_number)d of %(total_pages)d' ) % { 'page_number' : page_number, 'total_pages' : total_pages } of.write('  %s  ' % data) if next: self.media_ref_link(of,next,_('Next'),True) of.write('

\n') mime_type = photo.get_mime_type() if mime_type and mime_type.startswith("image"): try: of.write('
\n') of.write('%s' % (newpath, self.page_title)) of.write('
\n') except (IOError,OSError),msg: WarningDialog(_("Could not add photo to page"),str(msg)) of.write('\n') if not self.noid: of.write('\n' % _('GRAMPS ID')) of.write('\n' % photo.gramps_id) of.write('\n') of.write('\n' % _('MIME type')) of.write('\n' % photo.mime) of.write('\n') of.write('
%s%s
%s%s
\n') of.write('
\n') self.display_note_object(of, photo.get_note_object()) self.display_attr_list(of, photo.get_attribute_list()) self.display_references(of,db,media_list) self.display_footer(of,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class SurnameListPage(BasePage): ORDER_BY_NAME = 0 ORDER_BY_COUNT = 1 def __init__(self, db, title, person_handle_list, options, archive, media_list, levels, order_by=ORDER_BY_NAME): BasePage.__init__(self, title, options, archive, media_list, levels, "") if order_by == self.ORDER_BY_NAME: of = self.create_file("surnames") self.display_header(of,db,_('Surnames'),get_researcher().get_name()) of.write('

%s

\n' % _('Surnames')) else: of = self.create_file("surnames_count") self.display_header(of,db,_('Surnames by person count'), get_researcher().get_name()) of.write('

%s

\n' % _('Surnames by person count')) of.write('

%s

\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('
\n') of.write('\n') of.write('\n' % _('Letter')) of.write('\n' % ("surnames", self.ext, _('Surname'))) of.write('\n' % ("surnames_count", self.ext, _('Number of people'))) of.write('\n') person_handle_list = sort_people(db,person_handle_list) if order_by == self.ORDER_BY_COUNT: temp_list = {} for (surname,data_list) in person_handle_list: temp_list["%90d_%s" % (999999999-len(data_list),surname)] = (surname,data_list) temp_keys = temp_list.keys() temp_keys.sort() person_handle_list = [] for key in temp_keys: person_handle_list.append(temp_list[key]) 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('' % last_letter) of.write('') elif surname != last_surname: of.write('') of.write('') last_surname = surname of.write('' % len(data_list)) of.write('
') of.write('%s') of.write('%s') of.write('%s
%s') self.surname_link(of,surname) of.write('
 ') self.surname_link(of,surname) of.write('%d
\n
\n') self.display_footer(of,db) self.close_file(of) return #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class IntroductionPage(BasePage): def __init__(self, db, title, options, archive, media_list, levels): BasePage.__init__(self, title, options, archive, media_list, levels, "") note_id = options.handler.options_dict['NWEBintronote'] of = self.create_file("introduction") author = get_researcher().get_name() self.display_header(of, db, _('Introduction'), author) of.write('

%s

\n' % _('Introduction')) if note_id: obj = db.get_object_from_handle(note_id) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): try: (newpath,thumb_path) = self.copy_media(obj,False) self.store_file(archive,self.html_dir,obj.get_path(), newpath) of.write('
\n') of.write('' % obj.get_description()) of.write('
\n') except (IOError,OSError),msg: WarningDialog(_("Could not add photo to page"),str(msg)) note_obj = obj.get_note_object() if note_obj: text = note_obj.get() if note_obj.get_format(): of.write('
\n%s\n
\n' % text) else: of.write('

') of.write('

'.join(text.split('\n'))) of.write('

') self.display_footer(of,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class HomePage(BasePage): def __init__(self, db, title, options, archive, media_list, levels): BasePage.__init__(self, title, options, archive, media_list, levels, "") note_id = options.handler.options_dict['NWEBhomenote'] of = self.create_file("index") author = get_researcher().get_name() self.display_header(of,db,_('Home'),author) of.write('

%s

\n' % _('Home')) if note_id: obj = db.get_object_from_handle(note_id) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): try: (newpath,thumb_path) = self.copy_media(obj,False) self.store_file(archive,self.html_dir,obj.get_path(), newpath) of.write('
\n') of.write('' % obj.get_description()) of.write('
\n') except (IOError,OSError),msg: WarningDialog(_("Could not add photo to page"),str(msg)) note_obj = obj.get_note_object() if note_obj: text = note_obj.get() if note_obj.get_format(): of.write('
\n%s\n
\n' % text) else: of.write('

') of.write('

'.join(text.split('\n'))) of.write('

') self.display_footer(of,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class SourcesPage(BasePage): def __init__(self, db, title, handle_set, options, archive, media_list, levels): BasePage.__init__(self, title, options, archive, media_list, levels, "") of = self.create_file("sources") author = get_researcher().get_name() self.display_header(of, db, _('Sources'), author) 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 source's " "title will take you to that source's page.") of.write('

%s

\n

' % _('Sources')) of.write(msg) of.write('

\n
\n\n') index = 1 for handle in handle_list: source = db.get_source_from_handle(handle) of.write('\n' % index) of.write('\n') index += 1 of.write('
%d.') self.source_link(of,handle,source.get_title(),source.gramps_id) of.write('
\n
\n') self.display_footer(of,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class SourcePage(BasePage): def __init__(self, db, title, handle, src_list, options, archive, media_list, levels): source = db.get_source_from_handle( handle) BasePage.__init__(self, title, options, archive, media_list, levels, source.gramps_id) of = self.create_link_file(source.get_handle(),"src") self.page_title = source.get_title() self.display_header(of,db,"%s - %s" % (_('Sources'), self.page_title), get_researcher().get_name(),up=True) self.display_first_image_as_thumbnail(of, db, source.get_media_list()) of.write('
\n') of.write('

%s

\n' % self.page_title) of.write('\n') for (label,val) in [(_('GRAMPS ID'),source.gramps_id), (_('Author'),source.author), (_('Publication information'),source.pubinfo), (_('Abbreviation'),source.abbrev)]: if val: of.write('\n' % label) of.write('\n' % val) of.write('\n') of.write('
%s%s
\n') of.write('
\n') source_media = source.get_media_list() self.display_additional_images_as_gallery(of, db, source_media) self.display_note_object(of, source.get_note_object()) self.display_references(of,db,src_list[source.handle]) self.display_footer(of,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class GalleryPage(BasePage): def __init__(self, db, title, handle_set, options, archive, media_list, levels): BasePage.__init__(self, title, options, archive, media_list, levels, "") of = self.create_file("gallery") self.display_header(of,db, _('Gallery'), get_researcher().get_name()) of.write('

%s

\n

' % _('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('

\n
\n\n') self.db = db index = 1 mlist = media_list.keys() mlist.sort(self.by_media_title) for handle in mlist: media = db.get_object_from_handle(handle) of.write('\n' % index) of.write('\n') index += 1 of.write('
%d.') self.media_ref_link(of,handle,media.get_description()) of.write('
\n
\n') self.display_footer(of,db) 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, levels): BasePage.__init__(self, title, options, archive, media_list, levels, "") of = self.create_file("download") self.display_header(of,db,_('Download'), get_researcher().get_name()) of.write('

%s

\n' % _('Download')) self.display_footer(of,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class ContactPage(BasePage): def __init__(self, db, title, options, archive, media_list, levels): BasePage.__init__(self, title, options, archive, media_list, levels, "") of = self.create_file("contact") self.display_header(of,db,_('Contact'), get_researcher().get_name()) of.write('
\n') of.write('

%s

\n' % _('Contact')) note_id = options.handler.options_dict['NWEBcontact'] if note_id: obj = db.get_object_from_handle(note_id) mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): try: (newpath,thumb_path) = self.copy_media(obj,False) self.store_file(archive,self.html_dir,obj.get_path(), newpath) of.write('
\n') of.write('') of.write('
') of.write('' % obj.get_description()) of.write('
\n') of.write('
\n') except (IOError,OSError),msg: WarningDialog(_("Could not add photo to page"),str(msg)) r = get_researcher() of.write('
\n') of.write('%s
\n' % r.name) of.write('%s
\n' % r.addr) of.write('%s, %s, %s
\n' % (r.city,r.state,r.postal)) of.write('%s
\n' % r.country) of.write('%s
\n' % r.email) of.write('
\n') if obj: nobj = obj.get_note_object() if nobj: format = nobj.get_format() text = nobj.get() if format: text = u"
" + u"
".join(text.split("\n"))+u"
" else: text = u"

".join(text.split("\n")) of.write('

%s

\n' % text) else: of.write('



\n') else: of.write('



\n') of.write('
\n') self.display_footer(of,db) 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, levels): BasePage.__init__(self, title, options, archive, media_list, levels, person.gramps_id) 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.exclude_private) self.name = sort_nameof(self.person,self.exclude_private) of = self.create_link_file(person.handle,"ppl") self.display_header(of,db, self.sort_name, get_researcher().get_name(),up=True) 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,db) 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('

%s

\n' % _('Source References')) of.write('
\n') of.write('\n') index = 1 for sref in sreflist: lnk = (self.cur_name, self.page_title, self.gid) shandle = sref.get_base_handle() if self.src_list.has_key(lnk): if lnk not in self.src_list[shandle]: self.src_list[shandle].append(lnk) else: self.src_list[shandle] = [lnk] source = self.db.get_source_from_handle(shandle) title = source.get_title() of.write('' % (index,index)) of.write('\n') index += 1 of.write('
') of.write('%d.') self.source_link(of,source.handle,title,source.gramps_id,True) of.write('') 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('
' + '
'.join(tmp)) of.write('
\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('

%s

\n' % _('Pedigree')) of.write('
\n
\n') of.write('\n') of.write('\n\n
\n') if father or mother: of.write('
\n') if father: self.pedigree_person(of,father) if mother: self.pedigree_person(of,mother) of.write('
\n') if family: for child_handle in family.get_child_handle_list(): if child_handle == self.person.handle: of.write('| %s
\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('| %s
\n' % self.name) self.pedigree_family(of) of.write('
\n') if father or mother: of.write('
\n') of.write('
\n') def display_ind_general(self,of): self.page_title = self.sort_name self.display_first_image_as_thumbnail(of, self.db, self.person.get_media_list()) of.write('
\n') of.write('

%s

\n' % self.sort_name) of.write('\n') # GRAMPS ID if not self.noid: of.write('\n' % _('GRAMPS ID')) of.write('\n' % self.person.gramps_id) of.write('\n') # Names [and their sources] for name in [self.person.get_primary_name(),]+self.person.get_alternate_names(): pname = name_nameof(name,self.exclude_private) of.write('\n' % _(name.get_type())) of.write('\n\n') # Gender of.write('\n' % _('Gender')) gender = self.gender_map[self.person.gender] of.write('\n' % gender) of.write('\n
%s%s
%s%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( " ") for nsh in nshl: index = self.src_refs.index(nsh)+1 of.write(' %d' % (index,index)) of.write( " ") of.write('
%s%s
\n
\n') def display_ind_events(self,of): if len(self.person.get_event_list()) == 0: return of.write('

%s

\n' % _('Events')) of.write('
\n') of.write('\n') # Birth handle = self.person.get_birth_handle() if handle: event = self.db.get_event_from_handle(handle) of.write('\n' % _('Birth')) of.write('\n' % self.format_event(event)) of.write('\n') # Death handle = self.person.get_death_handle() if handle: event = self.db.get_event_from_handle(handle) of.write('\n' % _('Death')) of.write('\n' % self.format_event(event)) of.write('\n') for event_id in self.person.get_event_list(): event = self.db.get_event_from_handle(event_id) of.write('\n' % event.get_name()) of.write('\n') of.write('\n') of.write('
%s%s
%s%s
%s\n') of.write(self.format_event(event)) of.write('
\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: child_name = nameof(child, self.exclude_private) path = self.build_path(child_handle,"ppl",False) self.person_link(of, self.build_name(path,child_handle), child_name, gid) else: of.write(nameof(child,self.exclude_private)) of.write(u"
\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('%s\n' % title) of.write('') val = person.gramps_id if use_link: path = self.build_path(handle,"ppl",False) fname = self.build_name(path,handle) self.person_link(of, fname, nameof(person,self.exclude_private), val) else: of.write(nameof(person,self.exclude_private)) if rel != RelLib.Person.CHILD_REL_BIRTH: of.write('   (%s)' % const.child_rel_list[rel]) of.write('\n') def display_ind_parents(self,of): parent_list = self.person.get_parent_family_handle_list() if not parent_list: return of.write('

%s

\n' % _("Parents")) of.write('
\n') of.write('\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('\n') else: first = False father_handle = family.get_father_handle() if father_handle: self.display_parent(of,father_handle,_('Father'),frel) of.write('\n') mother_handle = family.get_mother_handle() if mother_handle: self.display_parent(of,mother_handle,_('Mother'),mrel) of.write('\n') first = False childlist = family.get_child_handle_list() if len(childlist) > 1: of.write('\n') of.write('\n' % _("Siblings")) of.write('\n\n') of.write('\n') of.write('
 
%s\n') for child_handle in childlist: if child_handle != self.person.handle: self.display_child_link(of,child_handle) of.write('
 
\n') def display_ind_relationships(self,of): family_list = self.person.get_family_handle_list() if not family_list: return of.write('

%s

\n' % _("Families")) of.write('
\n') of.write('\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('\n') of.write('\n' % _("Children")) of.write('\n\n') of.write('
 %s\n') for child_handle in childlist: self.display_child_link(of,child_handle) of.write('
\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.exclude_private) else: name = _("unknown") if not first: of.write(' \n') rtype = const.family_relations[family.get_relationship()][0] of.write('%s\n' % rtype) of.write('%s\n' % relstr) of.write('') if spouse_id: use_link = spouse_id in self.ind_list gid = spouse.get_gramps_id() if use_link: spouse_name = nameof(spouse,self.exclude_private) path = self.build_path(spouse.handle,"ppl",False) fname = self.build_name(path,spouse.handle) self.person_link(of, fname, spouse_name, gid) else: of.write(name) of.write('\n\n') for event_id in family.get_event_list(): event = self.db.get_event_from_handle(event_id) of.write(' \n') of.write('%s\n' % event.get_name()) of.write('\n') of.write(self.format_event(event)) of.write('\n\n') for attr in family.get_attribute_list(): type = attr.get_type() value = attr.get_value() of.write(' \n') of.write('%s' % _(type)) of.write('%s\n\n' % value) nobj = family.get_note_object() if nobj: of.write(' \n') of.write('%s\n' % _('Narrative')) of.write('\n') format = nobj.get_format() text = nobj.get() if format: of.write( u"
" + u"
".join(text.split("\n"))+u"
") else: of.write( u"

".join(text.split("\n"))) of.write('\n\n') def pedigree_person(self,of,person,bullet='|'): person_link = person.handle in self.ind_list of.write('%s ' % bullet) if person_link: person_name = nameof(person,self.exclude_private) path = self.build_path(person.handle,"ppl",False) fname = self.build_name(path,person.handle) self.person_link(of, fname, person_name) else: of.write(nameof(person,self.exclude_private)) of.write('
\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,'•') childlist = rel_family.get_child_handle_list() if childlist: of.write('

\n') for child_handle in childlist: child = self.db.get_person_from_handle(child_handle) self.pedigree_person(of,child) of.write('
\n') def format_event(self,event): gid_list = [] lnk = (self.cur_name, self.page_title, self.gid) for sref in event.get_source_references(): handle = sref.get_base_handle() gid_list.append(sref) if self.src_list.has_key(handle): if lnk not in self.src_list[handle]: self.src_list[handle].append(lnk) else: self.src_list[handle] = [lnk] 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 lnk not in self.place_list[place_handle]: self.place_list[place_handle].append(lnk) else: self.place_list[place_handle] = [lnk] place = self.place_link_str(place_handle, ReportUtils.place_name(self.db,place_handle), up=True) 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,  %(date)s  at  %(place)s') % tmap elif descr and date: text = _('%(description)s,  %(date)s  ') % tmap elif descr: text = descr elif date and place: text = _('%(date)s  at  %(place)s') % tmap elif date: text = date elif place: text = place else: text = '\n' if len(gid_list) > 0: text = text + " " for ref in gid_list: index = self.src_refs.index(ref)+1 text = text + ' %d' % (index,index) text = text + "" return text #------------------------------------------------------------------------ # # WebReport # #------------------------------------------------------------------------ class WebReport(Report.Report): def __init__(self,database,person,options): """ Creates WebReport object that produces the report. The arguments are: database - the GRAMPS database instance person - currently selected person options - instance of the Options class for this report This report needs the following parameters (class variables) that come in the options class. filter od NWEBrestrictinfo NWEBrestrictyears NWEBincpriv NWEBnonames NWEBidxcol NWEBincid NWEBext NWEBencoding NWEBintronote NWEBhomenote NWEBnoid """ self.database = database self.start_person = person self.options = options filter_num = options.get_filter_number() filters = options.get_report_filters(person) filters.extend(GenericFilter.CustomFilters.get_filters()) self.filter = filters[filter_num] self.target_path = options.handler.options_dict['NWEBod'] self.copyright = options.handler.options_dict['NWEBcopyright'] self.ext = options.handler.options_dict['NWEBext'] self.encoding = options.handler.options_dict['NWEBencoding'] self.css = options.handler.options_dict['NWEBcss'] self.restrict = options.handler.options_dict['NWEBrestrictinfo'] self.restrict_years = options.handler.options_dict['NWEBrestrictyears'] self.exclude_private = options.handler.options_dict['NWEBincpriv'] self.noid = options.handler.options_dict['NWEBnoid'] self.title = options.handler.options_dict['NWEBtitle'] self.sort = Sort.Sort(self.database) self.inc_contact = options.handler.options_dict['NWEBcontact'] != u"" self.inc_download = options.handler.options_dict['NWEBdownload'] self.user_header = options.handler.options_dict['NWEBheader'] self.user_footer = options.handler.options_dict['NWEBfooter'] self.use_archive = options.handler.options_dict['NWEBarchive'] self.use_intro = options.handler.options_dict['NWEBintronote'] != u"" 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 try: image_dir_name = os.path.join(dir_name, 'images') if not os.path.isdir(image_dir_name): os.mkdir(image_dir_name) image_dir_name = os.path.join(dir_name, 'thumb') if not os.path.isdir(image_dir_name): 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 progress = Utils.ProgressMeter(_("Generate HTML reports"),'') ind_list = self.database.get_person_handles(sort_handles=False) progress.set_pass(_('Filtering'),1) ind_list = self.filter.apply(self.database,ind_list) if not self.exclude_private: new_list = [] progress.set_pass(_('Applying privacy filter'),len(ind_list)) for key in ind_list: progress.step() if not self.database.get_person_from_handle(key).private : new_list.append(key) ind_list = new_list years = time.localtime(time.time())[0] - self.restrict_years if self.restrict: new_list = [] progress.set_pass(_('Filtering living people'),len(ind_list)) for key in ind_list: progress.step() p = self.database.get_person_from_handle(key) if not Utils.probably_alive(p,self.database,years): new_list.append(key) ind_list = new_list if self.use_archive: import TarFile archive = TarFile.TarFile(self.target_path) else: archive = None if self.css != '': self.write_css(archive,self.target_path,self.css) if 1 < self.copyright < 7: from_path = os.path.join(const.dataDir,"somerights20.gif") to_path = os.path.join("images","somerights20.gif") self.store_file(archive,self.target_path,from_path,to_path) if len(ind_list) > 9000: levels = 2 else: levels = 1 place_list = {} source_list = {} photo_list = {} HomePage(self.database, self.title, self.options, archive, photo_list, levels) if self.inc_contact: ContactPage(self.database, self.title, self.options, archive, photo_list, levels) if self.inc_download: DownloadPage(self.database, self.title, self.options, archive, photo_list, levels) if self.use_intro: IntroductionPage(self.database, self.title, self.options, archive, photo_list, levels) progress.set_pass(_('Creating individual pages'),len(ind_list)) for person_handle in ind_list: progress.step() person = self.database.get_person_from_handle(person_handle) if not self.exclude_private: person = ReportUtils.sanitize_person(self.database,person) idoc = IndividualPage(self.database, person, self.title, ind_list, place_list, source_list, self.options, archive, photo_list, levels) if len(ind_list) > 1: IndividualListPage(self.database, self.title, ind_list, self.options, archive, photo_list, 0) SurnameListPage(self.database, self.title, ind_list, self.options, archive, photo_list, 0, SurnameListPage.ORDER_BY_NAME) SurnameListPage(self.database, self.title, ind_list, self.options, archive, photo_list, 0, SurnameListPage.ORDER_BY_COUNT) local_list = sort_people(self.database,ind_list) progress.set_pass(_("Creating surname pages"),len(local_list)) for (surname,handle_list) in local_list: SurnamePage(self.database, surname, handle_list, self.options, archive, photo_list, levels) progress.step() PlaceListPage(self.database, self.title, place_list, source_list,self.options, archive, photo_list, levels) progress.set_pass(_("Creating place pages"),len(place_list)) for place in place_list.keys(): PlacePage(self.database, self.title, place, source_list, place_list, self.options, archive, photo_list, levels) progress.step() SourcesPage(self.database,self.title, source_list.keys(), self.options, archive, photo_list, levels) progress.set_pass(_("Creating source pages"),len(source_list)) for key in list(source_list): SourcePage(self.database,self.title, key, source_list, self.options, archive, photo_list, levels) progress.step() GalleryPage(self.database, self.title, source_list, self.options, archive, photo_list, levels) prev = None total = len(photo_list) index = 1 photo_keys = photo_list.keys() progress.set_pass(_("Creating media pages"),len(photo_keys)) for photo_handle in photo_keys: if index == total: next = None else: next = photo_keys[index] try: MediaPage(self.database, self.title, photo_handle, source_list, self.options, archive, photo_list[photo_handle], (prev, next, index, total), levels) except (IOError,OSError),msg: WarningDialog(_("Missing media object"),str(msg)) progress.step() prev = photo_handle index += 1 if archive: archive.close() progress.close() 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 store_file(self,archive,html_dir,from_path,to_path): if archive: imagefile = open(from_path,"r") archive.add_file(to_path,time.time(),imagefile) imagefile.close() else: shutil.copyfile(from_path,os.path.join(html_dir,to_path)) 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' : './', 'NWEBcopyright' : 0, 'NWEBrestrictinfo' : 0, 'NWEBrestrictyears' : 30, 'NWEBincpriv' : 0, 'NWEBnonames' : 0, 'NWEBnoid' : 0, 'NWEBcontact' : '', 'NWEBheader' : '', 'NWEBfooter' : '', 'NWEBdownload' : 0, 'NWEBtitle' : _('My Family Tree'), 'NWEBincid' : 0, 'NWEBext' : 'html', 'NWEBencoding' : 'utf-8', 'NWEBcss' : 'main0.css', 'NWEBintronote' : '', 'NWEBhomenote' : '', } 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") restrict_years = _("Years to restrict from person's death") 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.connect('toggled',self.restrict_toggled) self.restrict_years = gtk.Entry() self.restrict_years.set_text(str(self.options_dict['NWEBrestrictyears'])) self.restrict_years.set_sensitive(False) self.restrict_living.set_active(self.options_dict['NWEBrestrictinfo']) self.hbox = gtk.HBox() self.hbox.set_spacing(12) self.hbox.pack_start(gtk.Label(" "),False,False) self.hbox.pack_start(gtk.Label("%s:" % restrict_years),False,False) self.hbox.add(self.restrict_years) 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 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.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) self.copy = gtk.combo_box_new_text() self.copy_options = [ _('Standard copyright'), _('Creative Commons - By attribution'), _('Creative Commons - By attribution, No derivations'), _('Creative Commons - By attribution, Share-alike'), _('Creative Commons - By attribution, Non-commercial'), _('Creative Commons - By attribution, Non-commercial, No derivations'), _('Creative Commons - By attribution, Non-commerical, Share-alike'), _('No copyright notice'), ] for text in self.copy_options: self.copy.append_text(text) def_ext = "." + self.options_dict['NWEBext'] self.ext.set_active(self.ext_options.index(def_ext)) index = self.options_dict['NWEBcopyright'] self.copy.set_active(index) 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(ext_msg,self.ext) dialog.add_option(_('Character set encoding'),self.encoding) dialog.add_option(_('Stylesheet'),self.css) dialog.add_option(_('Copyright'),self.copy) title = _("Page Generation") cursor = self.db.get_media_cursor() media_list = [['','']] html_list = [['','']] data = cursor.first() while data: (handle, value) = data if value[3]: media_list.append([value[4],handle]) else: html_list.append([value[4],handle]) data = cursor.next() cursor.close() media_list.sort() html_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']) self.header = build_combo_box(html_list,self.options_dict['NWEBheader']) self.footer = build_combo_box(html_list,self.options_dict['NWEBfooter']) 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,('HTML user header'),self.header) dialog.add_frame_option(title,('HTML user footer'),self.footer) 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.hbox) def restrict_toggled(self,obj): self.restrict_years.set_sensitive(obj.get_active()) 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['NWEBrestrictyears'] = int(self.restrict_years.get_text()) 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['NWEBheader'] = unicode(self.header.get_handle()) self.options_dict['NWEBfooter'] = unicode(self.footer.get_handle()) self.options_dict['NWEBdownload'] = int(self.inc_download.get_active()) 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['NWEBod'] = dialog.target_path self.options_dict['NWEBcopyright'] = self.copy.get_active() #------------------------------------------------------------------------ # # Callback functions from the dialog # #------------------------------------------------------------------------ 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 = WebReportOptions(name,database) self.category = const.CATEGORY_WEB Report.ReportDialog.__init__(self,database,person,self.options, name,translated_name) self.style_name = None response = self.window.run() if response == gtk.RESPONSE_OK: self.make_report() 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.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("%s" % _("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.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) 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, translated_name = _("Narrative Web Site"), author_name="Donald N. Allingham", author_email="don@gramps-project.org", status=(_("Beta")), description=_("Generates web (HTML) pages for individuals, or a set of individuals."), )