# # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2007 Johan Gonqvist # Copyright (C) 2007 Gary Burton # # 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 tarfile import operator from gettext import gettext as _ from cStringIO import StringIO from textwrap import TextWrapper from unicodedata import normalize #------------------------------------------------------------------------ # # Set up logging # #------------------------------------------------------------------------ import logging log = logging.getLogger(".WebPage") #------------------------------------------------------------------------ # # GNOME/gtk # #------------------------------------------------------------------------ import gtk #------------------------------------------------------------------------ # # GRAMPS module # #------------------------------------------------------------------------ import gen.lib import const from GrampsCfg import get_researcher from Filters import GenericFilter, Rules import Sort from PluginUtils import register_report from ReportBase import Report, ReportUtils, ReportOptions, \ CATEGORY_WEB, MODE_GUI, MODE_CLI from ReportBase import Bibliography from ReportBase._ReportDialog import ReportDialog from ReportBase._CommandLineReport import CommandLineReport import Errors import Utils import ThumbNails import ImgManip import GrampsLocale import GrampsWidgets import Mime from QuestionDialog import ErrorDialog, WarningDialog from BasicUtils import name_displayer as _nd from DateHandler import displayer as _dd from DateHandler import parser as _dp from gen.proxy import PrivateProxyDb from gen.proxy import LivingProxyDb from gen.lib.eventroletype import EventRoleType #------------------------------------------------------------------------ # # constants # #------------------------------------------------------------------------ _NARRATIVE = "narrative.css" _NAME_COL = 3 MAX_IMG_WIDTH=800 # resize images that are wider than this MAX_IMG_HEIGHT=600 # resize images that are taller than this WIDTH=160 HEIGHT=50 VGAP=10 HGAP=30 SHADOW=5 XOFFSET=5 _css_files = [ [_("Modern"), 'main1.css'], [_("Business"), 'main2.css'], [_("Certificate"), 'main3.css'], [_("Antique"), 'main4.css'], [_("Tranquil"), 'main5.css'], [_("Sharp"), 'main6.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 - By attribution', 'Creative Commons License - By attribution, No derivations', 'Creative Commons License - By attribution, Share-alike', 'Creative Commons License - By attribution, Non-commercial', 'Creative Commons License - By attribution, Non-commercial, No derivations', 'Creative Commons License - By attribution, Non-commerical, Share-alike', ] wrapper = TextWrapper() wrapper.break_log_words = True wrapper.width = 20 class BasePage: def __init__(self, title, options, archive, photo_list, 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.linkhome = options.handler.options_dict['NWEBlinkhome'] self.showbirth = options.handler.options_dict['NWEBshowbirth'] self.showdeath = options.handler.options_dict['NWEBshowdeath'] self.showspouse = options.handler.options_dict['NWEBshowspouse'] self.showparents = options.handler.options_dict['NWEBshowparents'] self.showhalfsiblings = options.handler.options_dict['NWEBshowhalfsiblings'] self.use_intro = options.handler.options_dict['NWEBintronote'] != u""\ or options.handler.options_dict['NWEBintropic'] != u"" self.use_contact = options.handler.options_dict['NWEBcontact'] != u""\ or options.handler.options_dict['NWEBcontactpic'] != u"" self.use_gallery = options.handler.options_dict['NWEBgallery'] self.header = options.handler.options_dict['NWEBheader'] self.footer = options.handler.options_dict['NWEBfooter'] self.photo_list = photo_list self.usegraph = options.handler.options_dict['NWEBgraph'] self.graphgens = options.handler.options_dict['NWEBgraphgens'] self.use_home = self.options.handler.options_dict['NWEBhomenote'] != "" or \ self.options.handler.options_dict['NWEBhomepic'] != "" self.page_title = "" self.warn_dir = True def store_file(self,archive,html_dir,from_path,to_path): if archive: archive.add(str(from_path),str(to_path)) else: dest = os.path.join(html_dir,to_path) dirname = os.path.dirname(dest) if not os.path.isdir(dirname): os.makedirs(dirname) if from_path != dest: shutil.copyfile(from_path,dest) elif self.warn_dir: WarningDialog( _("Possible destination error") + "\n" + _("You appear to have set your target directory " "to a directory used for data storage. This " "could create problems with file management. " "It is recommended that you consider using " "a different directory to store your generated " "web pages.")) self.warn_dir = False 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] ext = os.path.splitext(photo.get_path())[1] real_path = "%s/%s" % (self.build_path(handle,'images'),handle+ext) thumb_path = "%s/%s.png" % (self.build_path(handle,'thumb'),handle) 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, 'xmlcharrefreplace') else: page_name = os.path.join(self.html_dir,self.cur_name) of = codecs.EncodedFile(open(page_name, "w"),'utf-8', self.encoding,'xmlcharrefreplace') return of def link_path(self,name,path): path = "%s/%s/%s" % (path,name[0].lower(),name[1].lower()) path = self.build_name(path,name) return path 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,'xmlcharrefreplace') else: dirname = os.path.join(self.html_dir, path,name[0].lower(), name[1].lower()) 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,'xmlcharrefreplace') return of def close_file(self,of): if self.archive: tarinfo = tarfile.TarInfo(self.cur_name) tarinfo.size = len(self.string_io.getvalue()) tarinfo.mtime = time.time() if os.sys.platform != "win32": tarinfo.uid = os.getuid() tarinfo.gid = os.getgid() self.string_io.seek(0) self.archive.addfile(tarinfo,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: note = db.get_note_from_handle(self.footer) of.write('\n') of.write('\n') of.write('\n') def display_header(self,of,db,title,author="",up=False): self.up = up if up: path = "../../.." else: path = "" self.author = author of.write('\n') of.write('\n\n' % (xmllang,xmllang)) of.write('%s - %s\n' % (self.title_str, title)) of.write('\n' % self.encoding) if path: of.write('\n') of.write('\n') of.write('\n' % ('$','$')) of.write('\n') of.write('\n') if self.header: note = db.get_note_from_handle(self.header) of.write('
\n') of.write(note.get(markup=True)) of.write('
\n') of.write('\n') of.write('
\n') def show_link(self,of,lpath,title,path): if path: of.write('%s\n' % (path,lpath,self.ext,title)) else: of.write('%s\n' % (lpath,self.ext,title)) def display_first_image_as_thumbnail( self, of, db, photolist=None): if not photolist or not self.use_gallery: return photo_handle = photolist[0].get_reference_handle() photo = db.get_object_from_handle(photo_handle) mime_type = photo.get_mime_type() if 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)) else: of.write('
\n') descr = " ".join(wrapper.wrap(photo.get_description())) self.doc_link(of, photo_handle, descr, up=True) of.write('
\n') lnk = (self.cur_name, self.page_title, self.gid) if self.photo_list.has_key(photo_handle): if lnk not in self.photo_list[photo_handle]: self.photo_list[photo_handle].append(lnk) else: self.photo_list[photo_handle] = [lnk] def display_additional_images_as_gallery( self, of, db, photolist=None): if not photolist or not self.use_gallery: return of.write('\n') def display_note_list(self,of,db,notelist=None): if not notelist: return for notehandle in notelist: noteobj = db.get_note_from_handle(notehandle) format = noteobj.get_format() text = noteobj.get(markup=True) try: text = unicode(text) except UnicodeDecodeError: text = unicode(str(text),errors='replace') if text: of.write('
\n') of.write('

%s

\n' % _('Narrative')) if format: text = u"
%s
" % text else: text = u"

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

%s

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

%s

\n' % _('Source References')) of.write('\n') cindex = 0 for citation in self.bibli.get_citation_list(): cindex += 1 # Add this source to the global list of sources to be displayed # on each source page. lnk = (self.cur_name, self.page_title, self.gid) shandle = citation.get_source_handle() if self.src_list.has_key(shandle): if lnk not in self.src_list[shandle]: self.src_list[shandle].append(lnk) else: self.src_list[shandle] = [lnk] # Add this source and its references to the page source = self.db.get_source_from_handle(shandle) title = source.get_title() of.write('' % (cindex,cindex)) of.write('\n') for key,sref in citation.get_ref_list(): tmp = [] confidence = Utils.confidence.get(sref.confidence, _('Unknown')) if confidence == _('Normal'): confidence = None for (label,data) in [(_('Date'),_dd.display(sref.date)), (_('Page'),sref.page), (_('Confidence'),confidence)]: if data: tmp.append("%s: %s" % (label,data)) notelist = sref.get_note_list() for notehandle in notelist: note = self.db.get_note_from_handle(notehandle) tmp.append("%s: %s" % (_('Text'),note.get(True))) if len(tmp) > 0: of.write('\t') of.write('' % (cindex,key)) of.write('\n') of.write('
') of.write('%d.') self.source_link(of,source.handle,title,source.gramps_id,True) of.write('

') of.write('

') of.write('' % (cindex,key)) of.write('%d%s.') of.write('
'.join(tmp)) of.write('

') of.write('

\n') of.write('
\n') def display_references(self,of,db,handlelist): if not handlelist: return of.write('
\n') of.write('

%s

\n' % _('References')) of.write('\n') sortlist = sorted(handlelist, key = operator.itemgetter(1), cmp = locale.strcoll) index = 1 for (path,name,gid) in sortlist: of.write('\n') index = index + 1 of.write('
%d. ' % index) self.person_link(of,path,name,gid) of.write('
\n') of.write('
\n') def build_path(self,handle,dirroot,up=False): path = "" if up: path = '../../../%s/%s/%s' % (dirroot, handle[0].lower(), handle[1].lower()) else: path = "%s/%s/%s" % (dirroot,handle[0].lower(),handle[1].lower()) return path 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="",up=True): if up: 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('
\n') of.write('

' % (dirpath,handle,self.ext)) of.write('

\n' % name) if usedescr: of.write('

%s

\n' % name) of.write('
\n') def doc_link(self,of,handle,name,up,usedescr=True): path = os.path.join('images','document.png') dirpath = self.build_path(handle,'img',up) of.write('
\n') of.write('

' % (dirpath,handle,self.ext)) of.write('' % name) of.write('

\n') if usedescr: of.write('

%s

\n' % name) of.write('
\n') 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): BasePage.__init__(self, title, options, archive, media_list, "") 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\n') of.write('\n' % _('Surname')) of.write('\n' % _('Name')) column_count = 2 if self.showbirth: of.write('\n' % _('Birth')) column_count += 1 if self.showdeath: of.write('\n' % _('Death')) column_count += 1 if self.showspouse: of.write('\n' % _('Partner')) column_count += 1 if self.showparents: of.write('\n' % _('Parents')) column_count += 1 of.write('\n\n') person_handle_list = sort_people(db,person_handle_list) for (surname,handle_list) in person_handle_list: first = True of.write('\n' % column_count) for person_handle in handle_list: person = db.get_person_from_handle(person_handle) # surname column of.write('') # firstname column of.write('') # birth column if self.showbirth: of.write('') # death column if self.showdeath: of.write('') # spouse (partner) column if self.showspouse: of.write('') # parents column if self.showparents: of.write('') # finished writing all columns of.write('\n') first = False of.write('\n
%s%s%s%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), _nd.display_given(person), person.gramps_id,False) of.write('') birth = ReportUtils.get_birth_or_fallback(db, person) if birth: if birth.get_type() == gen.lib.EventType.BIRTH: of.write(_dd.display(birth.get_date_object())) else: of.write('') of.write(_dd.display(birth.get_date_object())) of.write('') of.write('') death = ReportUtils.get_death_or_fallback(db, person) if death: if death.get_type() == gen.lib.EventType.DEATH: of.write(_dd.display(death.get_date_object())) else: of.write('') of.write(_dd.display(death.get_date_object())) of.write('') of.write('') family_list = person.get_family_handle_list() first_family = True spouse_name = None if family_list: for family_handle in family_list: family = db.get_family_from_handle(family_handle) spouse_id = ReportUtils.find_spouse(person, family) if spouse_id: spouse = db.get_person_from_handle(spouse_id) spouse_name = spouse.get_primary_name().get_regular_name() if not first_family: of.write(', ') of.write('%s' % spouse_name) first_family = False of.write('') parent_handle_list = person.get_parent_family_handle_list() if parent_handle_list: parent_handle = parent_handle_list[0] family = db.get_family_from_handle(parent_handle) father_name = '' mother_name = '' father_id = family.get_father_handle() mother_id = family.get_mother_handle() father = db.get_person_from_handle(father_id) mother = db.get_person_from_handle(mother_id) if father: father_name = father.get_primary_name().get_regular_name() if mother: mother_name = mother.get_primary_name().get_regular_name() if mother and father: of.write('%s, %s' % (father_name, mother_name)) elif mother: of.write('%s' % mother_name) elif father: of.write('%s' % father_name) of.write('
\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): BasePage.__init__(self, title, options, archive, media_list, "") 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\n') of.write('\n' % _('Name')) if self.showbirth: of.write('\n' % _('Birth')) if self.showdeath: of.write('\n' % _('Death')) if self.showspouse: of.write('\n' % _('Partner')) if self.showparents: of.write('\n' % _('Parents')) of.write('\n\n') for person_handle in person_handle_list: # firstname column person = db.get_person_from_handle(person_handle) of.write('') # birth column if self.showbirth: of.write('') # death column if self.showdeath: of.write('') # spouse (partner) column if self.showspouse: of.write('') # parents column if self.showparents: of.write('') # finished writing all columns of.write('\n') of.write('\n
%s%s%s%s%s
') path = self.build_path(person.handle,"ppl",True) self.person_link(of, self.build_name(path,person.handle), person.get_primary_name().get_first_name(), person.gramps_id,False) of.write('') birth = ReportUtils.get_birth_or_fallback(db, person) if birth: if birth.get_type() == gen.lib.EventType.BIRTH: of.write(_dd.display(birth.get_date_object())) else: of.write('') of.write(_dd.display(birth.get_date_object())) of.write('') of.write('') death = ReportUtils.get_death_or_fallback(db, person) if death: if death.get_type() == gen.lib.EventType.DEATH: of.write(_dd.display(death.get_date_object())) else: of.write('') of.write(_dd.display(death.get_date_object())) of.write('') of.write('') family_list = person.get_family_handle_list() first_family = True spouse_name = None if family_list: for family_handle in family_list: family = db.get_family_from_handle(family_handle) spouse_id = ReportUtils.find_spouse(person, family) if spouse_id: spouse = db.get_person_from_handle(spouse_id) spouse_name = spouse.get_primary_name().get_regular_name() if not first_family: of.write(', ') of.write('%s' % spouse_name) first_family = False of.write('') parent_handle_list = person.get_parent_family_handle_list() if parent_handle_list: parent_handle = parent_handle_list[0] family = db.get_family_from_handle(parent_handle) father_name = '' mother_name = '' father_id = family.get_father_handle() mother_id = family.get_mother_handle() father = db.get_person_from_handle(father_id) mother = db.get_person_from_handle(mother_id) if father: father_name = father.get_primary_name().get_regular_name() if mother: mother_name = mother.get_primary_name().get_regular_name() if mother and father: of.write('%s, %s' % (father_name, mother_name)) elif mother: of.write('%s' % mother_name) elif father: of.write('%s' % father_name) of.write('
\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): BasePage.__init__(self, title, options, archive, media_list, "") 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\n') of.write('\n' % _('Letter')) of.write('\n' % _('Place')) of.write('\n\n') self.sort = Sort.Sort(db) handle_list = place_handles.keys() handle_list.sort(self.sort.by_place_title) 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 letter = normalize('NFD',n)[0].upper() if letter != last_letter: last_letter = letter of.write('\n') of.write('' % last_letter) of.write('') else: of.write('') of.write('') of.write('\n
%s%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') 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): place = db.get_place_from_handle( place_handle) BasePage.__init__(self, title, options, archive, media_list, 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) media_list = place.get_media_list() self.display_first_image_as_thumbnail(of, db, media_list) of.write('
\n') of.write('

%s

\n' % self.page_title.strip()) 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 [(_('Street'),ml.street), (_('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') if self.use_gallery: self.display_additional_images_as_gallery(of, db, media_list) self.display_note_list(of, db, place.get_note_list()) 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): (prev, next, page_number, total_pages) = info photo = db.get_object_from_handle(handle) BasePage.__init__(self, title, options, archive, media_list, photo.gramps_id) of = self.create_link_file(handle,"img") self.db = db self.src_list = src_list mime_type = photo.get_mime_type() if mime_type: note_only = False newpath = self.copy_source_file(handle, photo) target_exists = newpath != None else: note_only = True target_exists = False self.copy_thumbnail(handle, photo) 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.strip()) # 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') if mime_type: if mime_type.startswith("image/"): of.write('
\n') if target_exists: # if the image is spectacularly large, then force the client # to resize it, and include a "\n' % newpath) of.write('%s\n' % (newpath, self.page_title)) if scale <> 1.0: of.write('\n'); else: of.write('
(%s)' % _("The file has been moved or deleted")) of.write('
\n') else: import tempfile dirname = tempfile.mkdtemp() thmb_path = os.path.join(dirname,"temp.png") if ThumbNails.run_thumbnailer(mime_type, photo.get_path(), thmb_path, 320): try: path = "%s/%s.png" % (self.build_path(photo.handle,"preview"),photo.handle) self.store_file(archive, self.html_dir, thmb_path, path) os.unlink(thmb_path) except IOError: path = os.path.join('images','document.png') else: path = os.path.join('images','document.png') os.rmdir(dirname) of.write('
\n') if target_exists: of.write('\n' % (newpath, self.page_title)) of.write('%s\n' % (path, self.page_title)) if target_exists: of.write('\n') else: of.write('
(%s)' % _("The file has been moved or deleted")) of.write('
\n') else: path = os.path.join('images','document.png') of.write('
\n') of.write('%s\n' % (path, self.page_title)) of.write('
\n') of.write('\n') if not self.noid: of.write('\n') of.write('\n' % _('GRAMPS ID')) of.write('\n' % photo.gramps_id) of.write('\n') if not note_only and not mime_type.startswith("image/"): of.write('\n') of.write('\n' % _('File type')) of.write('\n' % Mime.get_description(mime_type)) of.write('\n') date = _dd.display(photo.get_date_object()) if date != "": of.write('\n') of.write('\n' % _('Date')) of.write('\n' % date) of.write('\n') of.write('
%s%s
%s%s
%s%s
\n') of.write('
\n') self.display_note_list(of, db, photo.get_note_list()) self.display_attr_list(of, photo.get_attribute_list()) self.display_media_sources(of, db, photo) self.display_references(of,db,media_list) self.display_footer(of,db) self.close_file(of) def display_media_sources(self, of, db, photo): self.bibli = Bibliography() for sref in photo.get_source_references(): self.bibli.add_reference(sref) self.display_source_refs(of, db) def display_attr_list(self,of,attrlist=None): if not attrlist: return of.write('
\n') of.write('

%s

\n' % _('Attributes')) of.write('\n') for attr in attrlist: atType = str( attr.get_type() ) of.write('' % atType) of.write('\n' % attr.get_value()) of.write('
%s%s
\n') of.write('
\n') def copy_source_file(self,handle,photo): ext = os.path.splitext(photo.get_path())[1] to_dir = self.build_path(handle,'images') newpath = to_dir + "/" + handle + ext try: if self.archive: self.archive.add(photo.get_path(),str(newpath)) else: to_dir = os.path.join(self.html_dir,to_dir) if not os.path.isdir(to_dir): os.makedirs(to_dir) shutil.copyfile(photo.get_path(), os.path.join(self.html_dir,newpath)) return newpath except (IOError,OSError),msg: error = _("Missing media object:") + \ "%s (%s)" % (photo.get_description(),photo.get_gramps_id()) WarningDialog(error,str(msg)) return None def copy_thumbnail(self,handle,photo): to_dir = self.build_path(handle,'thumb') to_path = os.path.join(to_dir,handle+".png") if photo.get_mime_type(): from_path = ThumbNails.get_thumbnail_path(photo.get_path(),photo.get_mime_type()) if not os.path.isfile(from_path): from_path = os.path.join(const.IMAGE_DIR,"document.png") else: from_path = os.path.join(const.IMAGE_DIR,"document.png") if self.archive: self.archive.add(from_path,to_path) else: to_dir = os.path.join(self.html_dir,to_dir) dest = os.path.join(self.html_dir,to_path) if not os.path.isdir(to_dir): os.makedirs(to_dir) try: shutil.copyfile(from_path,dest) except IOError: print "Could not copy file" #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class SurnameListPage(BasePage): ORDER_BY_NAME = 0 ORDER_BY_COUNT = 1 def __init__(self, db, title, person_handle_list, options, archive, media_list, order_by=ORDER_BY_NAME,filename="surnames"): BasePage.__init__(self, title, options, archive, media_list, "") if order_by == self.ORDER_BY_NAME: of = self.create_file(filename) 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\n') of.write('\n' % _('Letter')) if not self.use_home and not self.use_intro: of.write('\n' % ("index", self.ext, _('Surname'))) else: of.write('\n' % ("surnames", self.ext, _('Surname'))) of.write('\n' % ("surnames_count", self.ext, _('Number of people'))) of.write('\n\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: index_val = "%90d_%s" % (999999999-len(data_list),surname) temp_list[index_val] = (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 # Get a capital normalized version of the first letter of # the surname letter = normalize('NFD',surname)[0].upper() if letter != last_letter: last_letter = letter of.write('' % last_letter) of.write('') elif surname != last_surname: of.write('') of.write('') last_surname = surname of.write('' % len(data_list)) of.write('\n
%s%s%s%s
%s') self.surname_link(of,surname) of.write('
 ') self.surname_link(of,surname) of.write('%d
\n') self.display_footer(of,db) 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'] pic_id = options.handler.options_dict['NWEBintropic'] if self.use_home: of = self.create_file("introduction") else: of = self.create_file("index") author = get_researcher().get_name() self.display_header(of, db, _('Introduction'), author) of.write('

%s

\n' % _('Introduction')) if pic_id: obj = db.get_object_from_handle(pic_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)) if note_id: note_obj = db.get_note_from_handle(note_id) text = note_obj.get(markup=True) 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): BasePage.__init__(self, title, options, archive, media_list, "") note_id = options.handler.options_dict['NWEBhomenote'] pic_id = options.handler.options_dict['NWEBhomepic'] of = self.create_file("index") author = get_researcher().get_name() self.display_header(of,db,_('Home'),author) of.write('

%s

\n' % _('Home')) if pic_id: obj = db.get_object_from_handle(pic_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)) if note_id: note_obj = db.get_note_from_handle(note_id) text = note_obj.get(markup=True) 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): BasePage.__init__(self, title, options, archive, media_list, "") of = self.create_file("sources") author = get_researcher().get_name() self.display_header(of, db, _('Sources'), author) handle_list = list(handle_set) source_dict = {} #Sort the sources for handle in handle_list: source = db.get_source_from_handle(handle) key = source.get_title() + str(source.get_gramps_id()) source_dict[key] = (source, handle) keys = source_dict.keys() keys.sort(locale.strcoll) 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') index = 1 for key in keys: (source, handle) = source_dict[key] 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') self.display_footer(of,db) 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, 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) media_list = source.get_media_list() self.display_first_image_as_thumbnail(of, db, media_list) of.write('
\n') of.write('

%s

\n' % self.page_title.strip()) of.write('') grampsid = None if not self.noid: grampsid = source.gramps_id for (label,val) in [(_('GRAMPS ID'),grampsid), (_('Author'),source.author), (_('Publication information'),source.pubinfo), (_('Abbreviation'),source.abbrev)]: if val: of.write('\n' % label) of.write('\n' % val) of.write('') of.write('
%s%s
') self.display_additional_images_as_gallery(of, db, media_list) self.display_note_list(of, db, source.get_note_list()) 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): BasePage.__init__(self, title, options, archive, media_list, "") 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') self.db = db index = 1 mlist = media_list.keys() sort = Sort.Sort(self.db) mlist.sort(sort.by_media_title) for handle in mlist: media = db.get_object_from_handle(handle) date = _dd.display(media.get_date_object()) title = media.get_description() if title == "": title = "untitled" of.write('\n') of.write('\n' % index) of.write('\n') of.write('\n' % date) of.write('\n') index += 1 of.write('
%d.') self.media_ref_link(of,handle,title) of.write('%s
\n') self.display_footer(of,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ 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,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): BasePage.__init__(self, title, options, archive, media_list, "") 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'] pic_id = options.handler.options_dict['NWEBcontactpic'] if pic_id: obj = db.get_object_from_handle(pic_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') if r.name: of.write('%s
\n' % r.name.replace(',,,','')) if r.addr: of.write('%s
\n' % r.addr) text = "".join([r.city,r.state,r.postal]) if text: of.write('%s
\n' % text) if r.country: of.write('%s
\n' % r.country) if r.email: of.write('%s
\n' % r.email) of.write('
\n') of.write('
\n') if note_id: note_obj = db.get_note_from_handle(note_id) text = note_obj.get(markup=True) if note_obj.get_format(): text = u"
%s
" % text else: text = u"
".join(text.split("\n")) of.write('

%s

\n' % text) of.write('
\n') self.display_footer(of,db) self.close_file(of) #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class IndividualPage(BasePage): gender_map = { gen.lib.Person.MALE : _('male'), gen.lib.Person.FEMALE : _('female'), gen.lib.Person.UNKNOWN : _('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, person.gramps_id) self.person = person self.db = db self.ind_list = ind_list self.src_list = src_list self.bibli = Bibliography() self.place_list = place_list self.sort_name = _nd.sorted(self.person) self.name = _nd.sorted(self.person) 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) self.display_addresses(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 += family.get_media_list() for evt_ref in family.get_event_ref_list(): event = self.db.get_event_from_handle(evt_ref.ref) media_list += event.get_media_list() for evt_ref in self.person.get_primary_event_ref_list(): event = self.db.get_event_from_handle(evt_ref.ref) if event: media_list += event.get_media_list() self.display_additional_images_as_gallery(of, db, media_list) self.display_note_list(of, db, self.person.get_note_list()) self.display_url_list(of, self.person.get_url_list()) self.display_ind_sources(of) self.display_ind_pedigree(of) if self.usegraph: self.display_tree(of) self.display_footer(of,db) self.close_file(of) def display_attr_list(self,of,attrlist=None): if not attrlist: return of.write('
\n') of.write('

%s

\n' % _('Attributes')) of.write('\n') for attr in attrlist: atType = str( attr.get_type() ) of.write('' % atType) value = attr.get_value() value += self.get_citation_links( attr.get_source_references() ) of.write('\n' % value) of.write('
%s%s
\n') of.write('
\n') def draw_box(self,of,center,col,person): top = center - HEIGHT/2 xoff = XOFFSET+col*(WIDTH+HGAP) of.write('
\n' % (top,xoff+1)) of.write('
') person_link = person.handle in self.ind_list if person_link: person_name = _nd.display(person) 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(_nd.display(person)) of.write('
\n') of.write('
\n') of.write('
\n' % (top+SHADOW,xoff+SHADOW)) of.write('
\n' % (top-1, xoff)) def extend_line(self,of,y0,x0): of.write('
\n' % (y0,x0,HGAP/2)) of.write('
\n' % (y0+SHADOW,x0,HGAP/2+SHADOW)) def connect_line(self,of,y0,y1,col): if y0 < y1: y = y0 else: y = y1 x0 = XOFFSET + col * WIDTH + (col-1)*HGAP + HGAP/2 of.write('
\n' % (y1,x0,HGAP/2)) of.write('
\n' % (y1+SHADOW,x0+SHADOW,HGAP/2+SHADOW)) of.write('
\n' % (y,x0,abs(y0-y1))) of.write('
\n' % (y+SHADOW,x0+SHADOW,abs(y0-y1))) def draw_connected_box(self,of,center1,center2,col,handle): if not handle: return None person = self.db.get_person_from_handle(handle) self.draw_box(of,center2,col,person) self.connect_line(of,center1,center2,col) return person def display_tree(self,of): if not self.person.get_main_parents_family_handle(): return of.write('
\n') of.write('

%s

\n' % _('Ancestors')) of.write('
\n') generations = self.graphgens max_in_col = 1 <<(generations-1) max_size = HEIGHT*max_in_col + VGAP*(max_in_col+1) center = int(max_size/2) self.draw_tree(of,1,generations,max_size,0,center,self.person.handle) of.write('
\n') of.write('
\n') of.write('
\n' % (max_size,XOFFSET+(generations)*WIDTH+(generations-1)*HGAP)) def draw_tree(self,of,gen,maxgen,max_size,old_center,new_center,phandle): if gen > maxgen: return gen_offset = int(max_size / pow(2,gen+1)) person = self.db.get_person_from_handle(phandle) if not person: return if gen == 1: self.draw_box(of,new_center,0,person) else: self.draw_connected_box(of,old_center,new_center,gen-1,phandle) if gen == maxgen: return family_handle = person.get_main_parents_family_handle() if family_handle: line_offset = XOFFSET + (gen)*WIDTH + (gen-1)*HGAP self.extend_line(of,new_center,line_offset) gen = gen + 1 family = self.db.get_family_from_handle(family_handle) f_center = new_center-gen_offset f_handle = family.get_father_handle() self.draw_tree(of,gen,maxgen,max_size,new_center,f_center,f_handle) m_center = new_center+gen_offset m_handle = family.get_mother_handle() self.draw_tree(of,gen,maxgen,max_size,new_center,m_center,m_handle) def display_ind_sources(self,of): for sref in self.person.get_source_references(): self.bibli.add_reference(sref) if self.bibli.get_citation_count() == 0: return self.display_source_refs(of, self.db) def display_ind_pedigree(self,of): parent_handle_list = self.person.get_parent_family_handle_list() if parent_handle_list: parent_handle = 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('
\n') of.write('

%s

\n' % _('Pedigree')) of.write('
\n') if father or mother: of.write('
\n') if father: self.pedigree_person(of,father) if mother: self.pedigree_person(of,mother,True) of.write('
\n') if family: for child_ref in family.get_child_ref_list(): child_handle = child_ref.ref 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
\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.strip()) 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 = _nd.display_name(name) pname += self.get_citation_links( name.get_source_references() ) type = str( name.get_type() ) of.write('\n' % _(type)) of.write('\n\n') # Gender nick = self.person.get_nick_name() if nick: of.write('\n' % _('Nickname')) of.write('\n' % nick) of.write('\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) of.write('
%s%s
%s%s
\n
\n') def display_ind_events(self,of): evt_ref_list = self.person.get_event_ref_list() if not evt_ref_list: return of.write('
\n') of.write('

%s

\n' % _('Events')) of.write('\n') for event_ref in evt_ref_list: event = self.db.get_event_from_handle(event_ref.ref) if event: evt_name = str(event.get_type()) if event_ref.get_role() == EventRoleType.PRIMARY: of.write('\n' % evt_name) else: of.write('\n' \ % (evt_name, event_ref.get_role())) of.write('\n') of.write('\n') of.write('
%s
%s (%s)\n') of.write(self.format_event(event, event_ref)) of.write('
\n') of.write('
\n') def display_addresses(self,of): alist = self.person.get_address_list() if len(alist) == 0: return of.write('
\n') of.write('

%s

\n' % _('Addresses')) of.write('\n') for addr in alist: location = ReportUtils.get_address_str(addr) location += self.get_citation_links( addr.get_source_references() ) date = _dd.display(addr.get_date_object()) of.write('\n' % date) of.write('\n' % location) of.write('\n') of.write('
%s%s
\n') 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 = _nd.display(child) path = self.build_path(child_handle,"ppl",False) self.person_link(of, self.build_name(path,child_handle), child_name, gid) else: of.write(_nd.display(child)) 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, _nd.display(person), val) else: of.write(_nd.display(person)) if rel != gen.lib.ChildRefType.BIRTH: of.write('   (%s)' % str(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('
\n') of.write('

%s

\n' % _("Parents")) of.write('\n') first = True if parent_list: for family_handle in parent_list: family = self.db.get_family_from_handle(family_handle) # Get the mother and father relationships frel = "" mrel = "" sibling = set() child_handle = self.person.get_handle() child_ref_list = family.get_child_ref_list() for child_ref in child_ref_list: if child_ref.ref == child_handle: frel = str(child_ref.get_father_relation()) mrel = str(child_ref.get_mother_relation()) if not first: of.write('\n') else: first = False father_handle = family.get_father_handle() if father_handle: of.write('\n') self.display_parent(of,father_handle,_('Father'),frel) of.write('\n') mother_handle = family.get_mother_handle() if mother_handle: of.write('\n') self.display_parent(of,mother_handle,_('Mother'),mrel) of.write('\n') first = False if len(child_ref_list) > 1: of.write('\n') of.write('\n' % _("Siblings")) of.write('\n\n') # Also try to identify half-siblings other_siblings = set() # if we have a known father... if father_handle and self.showhalfsiblings: # 1) get all of the families in which this father is involved # 2) get all of the children from those families # 3) if the children are not already listed as siblings... # 4) then remember those children since we're going to list them father = self.db.get_person_from_handle(father_handle) for family_handle in father.get_family_handle_list(): family = self.db.get_family_from_handle(family_handle) for step_child_ref in family.get_child_ref_list(): step_child_handle = step_child_ref.ref if step_child_handle not in sibling: if step_child_handle != self.person.handle: # we have a new step/half sibling other_siblings.add(step_child_ref.ref) # do the same thing with the mother (see "father" just above): if mother_handle and self.showhalfsiblings: mother = self.db.get_person_from_handle(mother_handle) for family_handle in mother.get_family_handle_list(): family = self.db.get_family_from_handle(family_handle) for step_child_ref in family.get_child_ref_list(): step_child_handle = step_child_ref.ref if step_child_handle not in sibling: if step_child_handle != self.person.handle: # we have a new step/half sibling other_siblings.add(step_child_ref.ref) # now that we have all of the step-siblings/half-siblings, print them out if len(other_siblings) > 0: of.write('\n') of.write('\n' % _("Half Siblings")) of.write('\n\n') of.write('\n') of.write('
 
%s\n') for child_ref in child_ref_list: child_handle = child_ref.ref sibling.add(child_handle) # remember that we've already "seen" this child if child_handle != self.person.handle: self.display_child_link(of,child_handle) of.write('
%s\n') for child_handle in other_siblings: self.display_child_link(of, child_handle) of.write('
 
\n') of.write('
\n') def display_ind_relationships(self,of): family_list = self.person.get_family_handle_list() if not family_list: return of.write('
\n') of.write('

%s

\n' % _("Families")) 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_ref_list() if childlist: of.write('\n') of.write('\n' % _("Children")) of.write('\n\n') of.write('
 %s\n') for child_ref in childlist: self.display_child_link(of,child_ref.ref) of.write('
\n') of.write('
\n') def display_spouse(self,of,family,first=True): gender = self.person.get_gender() reltype = family.get_relationship() if reltype == gen.lib.FamilyRelType.MARRIED: if gender == gen.lib.Person.FEMALE: relstr = _("Husband") elif gender == gen.lib.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 = _nd.display(spouse) else: name = _("unknown") if not first: of.write(' \n') rtype = str(family.get_relationship()) 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 = _nd.display(spouse) 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_ref in family.get_event_ref_list(): event = self.db.get_event_from_handle(event_ref.ref) evtType = str(event.get_type()) of.write(' \n') of.write('%s\n' % evtType) of.write('\n') of.write(self.format_event(event, event_ref)) of.write('\n\n') for attr in family.get_attribute_list(): attrType = str(attr.get_type()) of.write(' \n') of.write('%s' % attrType) of.write('%s\n\n' % attr.get_value()) notelist = family.get_note_list() for notehandle in notelist: nobj = self.db.get_note_from_handle(notehandle) if nobj: text = nobj.get(markup=True) format = nobj.get_format() if text: of.write(' \n') of.write('%s\n' % _('Narrative')) of.write('\n') if format: of.write( u"
%s
" % text ) else: of.write( u"
".join(text.split("\n"))) of.write('\n\n') def pedigree_person(self,of,person,is_spouse=False): person_link = person.handle in self.ind_list if is_spouse: of.write('') if person_link: person_name = _nd.display(person) 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(_nd.display(person)) if is_spouse: of.write('') 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,True) childlist = rel_family.get_child_ref_list() if childlist: of.write('
\n') for child_ref in childlist: child = self.db.get_person_from_handle(child_ref.ref) self.pedigree_person(of,child) of.write('
\n') def format_event(self,event,event_ref): lnk = (self.cur_name, self.page_title, self.gid) 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 and place: text = _('%(description)s  at  %(place)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' text += self.get_citation_links( event.get_source_references() ) # if the event or event reference has a attributes attached to it, # get the text and format it correctly attr_list = event.get_attribute_list() attr_list.extend(event_ref.get_attribute_list()) for attr in attr_list: text += _("
%(type)s: %(value)s") % { 'type' : attr.get_type(), 'value' : attr.get_value() } # if the event or event reference has a note attached to it, # get the text and format it correctly notelist = event.get_note_list() notelist.extend(event_ref.get_note_list()) for notehandle in notelist: nobj = self.db.get_note_from_handle(notehandle) if nobj: note_text = nobj.get(markup=True) format = nobj.get_format() if note_text: if format: text += u"
%s
" % note_text else: text += u"

" text += u"
".join(note_text.split("\n")) text += u"

" return text def get_citation_links(self, source_ref_list): gid_list = [] lnk = (self.cur_name, self.page_title, self.gid) text = "" for sref in source_ref_list: handle = sref.get_reference_handle() source = self.db.get_source_from_handle(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] if len(gid_list) > 0: text = text + " " for ref in gid_list: index,key = self.bibli.add_reference(ref) id = "%d%s" % (index+1,key) text = text + ' %s' % (id,id) text = text + "" return text #------------------------------------------------------------------------ # # WebReport # #------------------------------------------------------------------------ class WebReport(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 NWEBlivinginfo NWEByearsafterdeath NWEBincpriv NWEBnonames NWEBidxcol NWEBincid NWEBext NWEBencoding NWEBintronote NWEBhomenote NWEBhomepic NWEBnoid NWEBlinkhome NWEBshowbirth NWEBshowdeath NWEBshowspouse NWEBshowparents NWEBshowhalfsiblings """ if not options.handler.options_dict['NWEBincpriv']: self.database = PrivateProxyDb(database) else: self.database = database livinginfo = options.handler.options_dict['NWEBlivinginfo'] yearsafterdeath = options.handler.options_dict['NWEByearsafterdeath'] if livinginfo == LivingProxyDb.MODE_EXCLUDE: self.database = LivingProxyDb(self.database, LivingProxyDb.MODE_EXCLUDE, None, yearsafterdeath) elif livinginfo == LivingProxyDb.MODE_RESTRICT: self.database = LivingProxyDb(self.database, LivingProxyDb.MODE_RESTRICT, None, yearsafterdeath) self.start_person = person self.options = options filter_num = options.handler.options_dict['NWEBfilter'] filters = ReportUtils.get_person_filters(person,include_single=False) 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.noid = options.handler.options_dict['NWEBnoid'] self.linkhome = options.handler.options_dict['NWEBlinkhome'] self.showbirth = options.handler.options_dict['NWEBshowbirth'] self.showdeath = options.handler.options_dict['NWEBshowdeath'] self.showspouse = options.handler.options_dict['NWEBshowspouse'] self.showparents = options.handler.options_dict['NWEBshowparents'] self.showhalfsiblings = options.handler.options_dict['NWEBshowhalfsiblings'] self.title = options.handler.options_dict['NWEBtitle'] self.sort = Sort.Sort(self.database) self.inc_gallery = options.handler.options_dict['NWEBgallery'] self.inc_contact = options.handler.options_dict['NWEBcontact'] != u""\ or options.handler.options_dict['NWEBcontactpic'] != 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""\ or options.handler.options_dict['NWEBintropic'] != u"" self.use_home = options.handler.options_dict['NWEBhomenote'] != u"" or\ options.handler.options_dict['NWEBhomepic'] != 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 archive = None else: if os.path.isdir(self.target_path): ErrorDialog(_('Invalid file name'), _('The archive file must be a file, not a directory')) return try: archive = tarfile.open(self.target_path,"w:gz") except (OSError,IOError),value: ErrorDialog(_("Could not create %s") % self.target_path, value) return self.progress = Utils.ProgressMeter(_("Generate HTML reports"),'') # Build the person list ind_list = self.build_person_list() # Generate the CSS file if requested if self.css != '': self.write_css(archive,self.target_path,self.css) # Copy the Creative Commons icon if the a Creative Commons # license is requested if 0 < self.copyright < 7: from_path = os.path.join(const.IMAGE_DIR,"somerights20.gif") to_path = os.path.join("images","somerights20.gif") self.store_file(archive,self.target_path,from_path,to_path) from_path = os.path.join(const.IMAGE_DIR,"document.png") to_path = os.path.join("images","document.png") self.store_file(archive,self.target_path,from_path,to_path) place_list = {} source_list = {} self.photo_list = {} self.base_pages(self.photo_list, archive) self.person_pages(ind_list, place_list, source_list, archive) self.surname_pages(ind_list, archive) self.place_pages(place_list, source_list, archive) if self.inc_gallery: self.gallery_pages(self.photo_list, source_list, archive) self.source_pages(source_list, self.photo_list, archive) if archive: archive.close() self.progress.close() def build_person_list(self): """ Builds the person list. Gets all the handles from the database and then applies the cosen filter: """ # gets the person list and applies the requested filter ind_list = self.database.get_person_handles(sort_handles=False) self.progress.set_pass(_('Filtering'),1) ind_list = self.filter.apply(self.database,ind_list) return ind_list def write_css(self,archive,html_dir,css_file): """ Copy the CSS file to the destination. """ if archive: fname = os.path.join(const.DATA_DIR, css_file) archive.add(fname,_NARRATIVE) else: shutil.copyfile(os.path.join(const.DATA_DIR, css_file), os.path.join(html_dir,_NARRATIVE)) def person_pages(self, ind_list, place_list, source_list, archive): self.progress.set_pass(_('Creating individual pages'),len(ind_list) + 1) self.progress.step() # otherwise the progress indicator sits at 100% # for a short while from the last step we did, # which was to apply the privacy filter IndividualListPage( self.database, self.title, ind_list, self.options, archive, self.photo_list) for person_handle in ind_list: self.progress.step() person = self.database.get_person_from_handle(person_handle) IndividualPage( self.database, person, self.title, ind_list, place_list, source_list, self.options, archive, self.photo_list) def surname_pages(self, ind_list, archive): """ Generates the surname related pages from list of individual people. """ local_list = sort_people(self.database,ind_list) self.progress.set_pass(_("Creating surname pages"),len(local_list)) if self.use_home or self.use_intro: defname="surnames" else: defname="index" SurnameListPage( self.database, self.title, ind_list, self.options, archive, self.photo_list, SurnameListPage.ORDER_BY_NAME,defname) SurnameListPage( self.database, self.title, ind_list, self.options, archive, self.photo_list, SurnameListPage.ORDER_BY_COUNT,"surnames_count") for (surname,handle_list) in local_list: SurnamePage(self.database, surname, handle_list, self.options, archive, self.photo_list) self.progress.step() def source_pages(self, source_list, photo_list, archive): self.progress.set_pass(_("Creating source pages"),len(source_list)) SourcesPage(self.database,self.title, source_list.keys(), self.options, archive, photo_list) for key in list(source_list): SourcePage(self.database, self.title, key, source_list, self.options, archive, photo_list) self.progress.step() def place_pages(self, place_list, source_list, archive): self.progress.set_pass(_("Creating place pages"),len(place_list)) PlaceListPage( self.database, self.title, place_list, source_list, self.options, archive, self.photo_list) for place in place_list.keys(): PlacePage( self.database, self.title, place, source_list, place_list, self.options, archive, self.photo_list) self.progress.step() def gallery_pages(self, photo_list, source_list, archive): import gc self.progress.set_pass(_("Creating media pages"),len(photo_list)) GalleryPage(self.database, self.title, source_list, self.options, archive, self.photo_list) prev = None total = len(self.photo_list) index = 1 photo_keys = self.photo_list.keys() sort = Sort.Sort(self.database) photo_keys.sort(sort.by_media_title) for photo_handle in photo_keys: gc.collect() # Reduce memory usage when there are many images. if index == total: next = None else: next = photo_keys[index] MediaPage(self.database, self.title, photo_handle, source_list, self.options, archive, self.photo_list[photo_handle], (prev, next, index, total)) self.progress.step() prev = photo_handle index += 1 def base_pages(self, photo_list, archive): if self.use_home: HomePage(self.database, self.title, self.options, archive, photo_list) if self.inc_contact: ContactPage(self.database, self.title, self.options, archive, photo_list) if self.inc_download: DownloadPage(self.database, self.title, self.options, archive, photo_list) if self.use_intro: IntroductionPage(self.database, self.title, self.options, archive, photo_list) def store_file(self,archive,html_dir,from_path,to_path): """ Store the file in the destination. """ if archive: archive.add(from_path,to_path) else: shutil.copyfile(from_path,os.path.join(html_dir,to_path)) def add_styles(self,doc): pass #------------------------------------------------------------------------ # # # #------------------------------------------------------------------------ class WebReportOptions(ReportOptions): """ Defines options and provides handling interface. """ def __init__(self,name,database=None,person_id=None): ReportOptions.__init__(self,name,person_id) self.db = database def set_new_options(self): # Options specific for this report self.options_dict = { 'NWEBfilter' : 0, 'NWEBarchive' : 0, 'NWEBgraph' : 1, 'NWEBgraphgens' : 4, 'NWEBod' : os.path.join(const.USER_HOME,"NWEB"), 'NWEBcopyright' : 0, 'NWEBlivinginfo' : 2, 'NWEByearsafterdeath' : 30, 'NWEBincpriv' : 0, 'NWEBnonames' : 0, 'NWEBnoid' : 0, 'NWEBlinkhome' : 0, 'NWEBshowbirth' : 1, 'NWEBshowdeath' : 0, 'NWEBshowspouse' : 0, 'NWEBshowparents' : 0, 'NWEBshowhalfsiblings' : 0, 'NWEBcontact' : '', 'NWEBcontactpic' : '', 'NWEBgallery' : 1, 'NWEBheader' : '', 'NWEBfooter' : '', 'NWEBdownload' : 0, 'NWEBtitle' : _('My Family Tree'), 'NWEBincid' : 0, 'NWEBext' : 'html', 'NWEBencoding' : 'utf-8', 'NWEBcss' : 'main0.css', 'NWEBintronote' : '', 'NWEBintropic' : '', 'NWEBhomenote' : '', 'NWEBhomepic' : '', } self.options_help = { } def add_user_options(self, dialog): priv_msg = _("Do not include records marked private") living_msg = _("Living People") death_msg = _("Years from death to consider living") title_msg = _("Web site title") ext_msg = _("File extension") contact_msg = _("Publisher contact note") contactpic_msg = _("Publisher contact image") gallery_msg = _("Include images and media objects") download_msg = _("Include download page") graph_msg = _("Include ancestor graph") filter_index = self.options_dict['NWEBfilter'] filter_list = ReportUtils.get_person_filters(dialog.person, include_single=False) self.filter_menu = gtk.combo_box_new_text() for filter in filter_list: self.filter_menu.append_text(filter.get_name()) if filter_index > len(filter_list): filter_index = 0 self.filter_menu.set_active(filter_index) dialog.add_option('Filter',self.filter_menu) self.no_private = gtk.CheckButton(priv_msg) self.no_private.set_active(not self.options_dict['NWEBincpriv']) self.inc_graph = gtk.CheckButton(graph_msg) self.inc_graph.set_active(self.options_dict['NWEBgraph']) self.graph_gens = gtk.combo_box_new_text() self.graph_gens_options = ['2','3','4','5'] for text in self.graph_gens_options: self.graph_gens.append_text(text) def_gens = str(self.options_dict['NWEBgraphgens']) if def_gens in self.graph_gens_options: self.graph_gens.set_active(self.graph_gens_options.index(def_gens)) else: self.graph_gens.set_active(0) self.noid = gtk.CheckButton(_('Suppress GRAMPS ID')) self.noid.set_active(self.options_dict['NWEBnoid']) self.include_gallery = gtk.CheckButton(gallery_msg) self.include_gallery.set_active(self.options_dict['NWEBgallery']) self.living = gtk.combo_box_new_text() self.living.append_text(_("Exclude")) self.living.append_text(_("Restrict")) self.living.append_text(_("Include")) self.living.set_active(self.options_dict['NWEBlivinginfo']) self.restrict_years = gtk.SpinButton(gtk.Adjustment(1,0,100,1)) self.restrict_years.set_value(self.options_dict['NWEByearsafterdeath']) self.inc_download = gtk.CheckButton(download_msg) self.inc_download.set_active(self.options_dict['NWEBdownload']) self.linkhome = gtk.CheckButton(_('Include link to home person on every page')) self.linkhome.set_active(self.options_dict['NWEBlinkhome']) self.showbirth = gtk.CheckButton(_('Include a column for birth dates on the index pages')) self.showbirth.set_active(self.options_dict['NWEBshowbirth']) self.showdeath = gtk.CheckButton(_('Include a column for death dates on the index pages')) self.showdeath.set_active(self.options_dict['NWEBshowdeath']) self.showspouse = gtk.CheckButton(_('Include a column for partners on the index pages')) self.showspouse.set_active(self.options_dict['NWEBshowspouse']) self.showparents = gtk.CheckButton(_('Include a column for parents on the index pages')) self.showparents.set_active(self.options_dict['NWEBshowparents']) self.showhalfsiblings = gtk.CheckButton(_('Include half-brothers and half-sisters as siblings')) self.showhalfsiblings.set_active(self.options_dict['NWEBshowhalfsiblings']) # FIXME: document this: # 0 -- no images of any kind # 1 -- no living images, but some images # 2 -- any images 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-commercial, 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) dialog.add_option(_('Ancestor graph generations'),self.graph_gens) dialog.add_option(None,self.inc_graph) title = _("Page Generation") self.home_nt_box, self.home_nt_label, self.home_nt_share_btn \ = mk_object_entry() self.home_note = GrampsWidgets.NoteEntry(dialog.dbstate, dialog.uistate, dialog.track, self.home_nt_label, self.set_home_nt_val, self.get_home_nt_val, None, self.home_nt_share_btn) self.home_pic_box, self.home_pic_label, self.home_pic_share_btn \ = mk_object_entry() self.home_pic = GrampsWidgets.MediaEntry(dialog.dbstate, dialog.uistate, dialog.track, self.home_pic_label, self.set_home_pic_val, self.get_home_pic_val, None, self.home_pic_share_btn) self.intro_nt_box, self.intro_nt_label, self.intro_nt_share_btn \ = mk_object_entry() self.intro_note = GrampsWidgets.NoteEntry(dialog.dbstate, dialog.uistate, dialog.track, self.intro_nt_label, self.set_intro_nt_val, self.get_intro_nt_val, None, self.intro_nt_share_btn) self.intro_pic_box, self.intro_pic_label, self.intro_pic_share_btn \ = mk_object_entry() self.intro_pic = GrampsWidgets.MediaEntry(dialog.dbstate, dialog.uistate, dialog.track, self.intro_pic_label, self.set_intro_pic_val, self.get_intro_pic_val, None, self.intro_pic_share_btn) self.contact_nt_box, self.contact_nt_label, self.contact_nt_share_btn \ = mk_object_entry() self.contact = GrampsWidgets.NoteEntry(dialog.dbstate, dialog.uistate, dialog.track, self.contact_nt_label, self.set_contact_nt_val, self.get_contact_nt_val, None, self.contact_nt_share_btn) self.contact_pic_box, self.contact_pic_label, \ self.contact_pic_share_btn = mk_object_entry() self.contact_pic = GrampsWidgets.MediaEntry(dialog.dbstate, dialog.uistate, dialog.track, self.contact_pic_label, self.set_contact_pic_val, self.get_contact_pic_val, None, self.contact_pic_share_btn) self.header_nt_box, self.header_nt_label, self.header_nt_share_btn \ = mk_object_entry() self.header = GrampsWidgets.NoteEntry(dialog.dbstate, dialog.uistate, dialog.track, self.header_nt_label, self.set_header_nt_val, self.get_header_nt_val, None, self.header_nt_share_btn) self.footer_nt_box, self.footer_nt_label, self.footer_nt_share_btn \ = mk_object_entry() self.footer = GrampsWidgets.NoteEntry(dialog.dbstate, dialog.uistate, dialog.track, self.footer_nt_label, self.set_footer_nt_val, self.get_footer_nt_val, None, self.footer_nt_share_btn) dialog.add_frame_option(title,_('Home Page note'), self.home_nt_box) dialog.add_frame_option(title,_('Home Page image'), self.home_pic_box) dialog.add_frame_option(title,_('Introduction Note'), self.intro_nt_box) dialog.add_frame_option(title,_('Introduction image'), self.intro_pic_box) dialog.add_frame_option(title, contact_msg, self.contact_nt_box) dialog.add_frame_option(title, contactpic_msg, self.contact_pic_box) dialog.add_frame_option(title, _('HTML user header'), self.header_nt_box) dialog.add_frame_option(title, _('HTML user footer'), self.footer_nt_box) dialog.add_frame_option(title, '', self.include_gallery) 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,living_msg,self.living) dialog.add_frame_option(title,death_msg,self.restrict_years) title = _("Advanced Options") dialog.add_frame_option(title,None,self.linkhome,) dialog.add_frame_option(title,None,self.showbirth) dialog.add_frame_option(title,None,self.showdeath) dialog.add_frame_option(title,None,self.showspouse) dialog.add_frame_option(title,None,self.showparents) dialog.add_frame_option(title,None,self.showhalfsiblings) def set_nt_val(self, opt, val): ''' store the note handle in options ''' if val is None: self.options_dict[opt] = u'' else: self.options_dict[opt] = unicode(val) def get_nt_val(self, opt): ''' obtain note handle ''' val = self.options_dict[opt] if val == "": return None else: return val def set_home_nt_val(self, val): self.set_nt_val('NWEBhomenote', val) def get_home_nt_val(self): return self.get_nt_val('NWEBhomenote') def set_home_pic_val(self, val): self.set_nt_val('NWEBhomepic', val) def get_home_pic_val(self): return self.get_nt_val('NWEBhomepic') def set_intro_nt_val(self, val): self.set_nt_val('NWEBintronote', val) def get_intro_nt_val(self): return self.get_nt_val('NWEBintronote') def set_intro_pic_val(self, val): self.set_nt_val('NWEBintropic', val) def get_intro_pic_val(self): return self.get_nt_val('NWEBintropic') def set_contact_nt_val(self, val): self.set_nt_val('NWEBcontact', val) def get_contact_nt_val(self): return self.get_nt_val('NWEBcontact') def set_contact_pic_val(self, val): self.set_nt_val('NWEBcontactpic', val) def get_contact_pic_val(self): return self.get_nt_val('NWEBcontactpic') def set_header_nt_val(self, val): self.set_nt_val('NWEBheader', val) def get_header_nt_val(self): return self.get_nt_val('NWEBheader') def set_footer_nt_val(self, val): self.set_nt_val('NWEBfooter', val) def get_footer_nt_val(self): return self.get_nt_val('NWEBfooter') 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['NWEBfilter'] = int(self.filter_menu.get_active()) self.options_dict['NWEBlivinginfo'] = int(self.living.get_active()) self.options_dict['NWEByearsafterdeath'] = \ 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['NWEBlinkhome'] = int(self.linkhome.get_active()) self.options_dict['NWEBshowbirth'] = int(self.showbirth.get_active()) self.options_dict['NWEBshowdeath'] = int(self.showdeath.get_active()) self.options_dict['NWEBshowspouse'] = int(self.showspouse.get_active()) self.options_dict['NWEBshowparents'] = int(self.showparents.get_active()) self.options_dict['NWEBshowhalfsiblings'] = int(self.showhalfsiblings.get_active()) self.options_dict['NWEBgallery'] = int(self.include_gallery.get_active()) self.options_dict['NWEBdownload'] = int(self.inc_download.get_active()) self.options_dict['NWEBtitle'] = unicode(self.title.get_text()) self.options_dict['NWEBgraph'] = int(self.inc_graph.get_active()) index = self.graph_gens.get_active() generations = 4 if index >= 0: generations = int(self.graph_gens_options[index]) self.options_dict['NWEBgraphgens'] = generations 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(ReportDialog): HELP_TOPIC = "rep-web" def __init__(self, dbstate, uistate, person): self.database = dbstate.db self.person = person name = "navwebpage" translated_name = _("Generate Web Site") self.options = WebReportOptions(name,self.database) self.category = CATEGORY_WEB ReportDialog.__init__(self, dbstate, uistate, person, self.options, name, translated_name) self.style_name = None while True: response = self.window.run() if response == gtk.RESPONSE_OK: self.close() self.make_report() break elif (response == gtk.RESPONSE_DELETE_EVENT or response == gtk.RESPONSE_CANCEL): # the buttons generating this already call close via connect break def on_cancel(self, *obj): self.close(*obj) 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.""" self.options.handler.options_dict['NWEBarchive'] = int( self.archive.get_active()) def parse_html_frame(self): pass def parse_paper_frame(self): pass def setup_html_frame(self): self.archive = gtk.CheckButton(_('Store web pages in .tar.gz archive')) self.archive.set_alignment(0.0,0.5) self.archive.set_active( self.options.handler.options_dict['NWEBarchive']) self.archive.connect('toggled',self.archive_toggle) self.add_option(None,self.archive) def archive_toggle(self,obj): if obj.get_active(): # The .tar.gz box is on # Set doc label, mark file vs dir, add '.tar.gz' to the path self.target_fileentry.set_directory_entry(False) self.doc_label.set_label("%s:" % _("Filename")) fname = self.target_fileentry.get_full_path(0) if fname[-7:] != '.tar.gz': fname = fname + '.tar.gz' self.target_fileentry.set_filename(fname) else: # The .tar.gz box is off # Set doc label, mark dir vs file, remove '.tar.gz' from path self.target_fileentry.set_directory_entry(True) self.doc_label.set_label("%s:" % _("Directory")) fname = self.target_fileentry.get_full_path(0) if fname[-7:] == '.tar.gz': fname = fname[:-7] self.target_fileentry.set_filename(fname) 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 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): flist = set(handle_list) sname_sub = {} sortnames = {} for person_handle in handle_list: person = db.get_person_from_handle(person_handle) primary_name = person.get_primary_name() if primary_name.group_as: surname = primary_name.group_as else: surname = db.get_name_group_mapping(primary_name.surname) sortnames[person_handle] = _nd.sort_string(primary_name) if sname_sub.has_key(surname): sname_sub[surname].append(person_handle) else: sname_sub[surname] = [person_handle] 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 = CommandLineReport(database,name,category,WebReportOptions, options_str_dict) # Exit here if show option was given if clr.show: return MyReport = WebReport(database,clr.person,clr.option_class) MyReport.write_report() #------------------------------------------------------------------------ # # 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 mk_object_entry(): ''' return a vbox widget with fields for object selection ''' box = gtk.HBox() label = gtk.Label() button_sel = gtk.Button() box.pack_start(label) box.pack_start(button_sel, expand=False, fill=False) return (box, label, button_sel) #------------------------------------------------------------------------- # # # #------------------------------------------------------------------------- register_report( name = 'navwebpage', category = CATEGORY_WEB, report_class = WebReportDialog, options_class = cl_report, modes = MODE_GUI | MODE_CLI, translated_name = _("Narrative Web Site"), status = _("Stable"), author_name="Donald N. Allingham", author_email="don@gramps-project.org", description=_("Generates web (HTML) pages for individuals, or a set of individuals."), )