diff --git a/src/plugins/webreport/NarrativeWeb.py b/src/plugins/webreport/NarrativeWeb.py index b6ff093d5..a6347eec1 100644 --- a/src/plugins/webreport/NarrativeWeb.py +++ b/src/plugins/webreport/NarrativeWeb.py @@ -1,3 +1,4 @@ +# # encoding: utf-8 # # Gramps - a GTK+/GNOME based genealogy program @@ -5,10 +6,11 @@ # Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2007 Johan Gonqvist # Copyright (C) 2007-2009 Gary Burton -# Copyright (C) 2007-2010 Stephane Charette +# Copyright (C) 2007-2009 Stephane Charette # Copyright (C) 2008-2009 Brian G. Matherly # Copyright (C) 2008 Jason M. Simanek # Copyright (C) 2008-2010 Rob G. Healey +# Copyright (C) 2010 Doug Blank # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -35,7 +37,6 @@ Narrative Web Page generator. # python modules # #------------------------------------------------------------------------ -from __future__ import with_statement import gc import os import sys @@ -61,15 +62,14 @@ from collections import defaultdict # #------------------------------------------------------------------------ import logging -log = logging.getLogger(".WebPage") +log = logging.getLogger(".NarrativeWeb") #------------------------------------------------------------------------ # GRAMPS module #------------------------------------------------------------------------ from gen.ggettext import sgettext as _ import gen.lib -from gen.lib import UrlType, EventType, Person, date, Date, ChildRefType, \ - FamilyRelType, NameType, Name, NoteType, EventRoleType +from gen.lib import UrlType, date, Date, FamilyRelType, NoteType, EventRoleType import const import Sort from gen.plug.menu import PersonOption, NumberOption, StringOption, \ @@ -143,7 +143,7 @@ _NARRATIVESCREEN = "narrative-screen.css" _NARRATIVEPRINT = "narrative-print.css" # variables for alphabet_navigation() -_KEYPERSON, _KEYPLACE, _KEYEVENT, _ALPHAEVENT = 0, 1, 2, 3 +_KEYPERSON, _KEYPLACE, _KEYEVENT = 0, 1, 2 # Web page filename extensions _WEB_EXT = ['.html', '.htm', '.shtml', '.php', '.php3', '.cgi'] @@ -332,28 +332,33 @@ class BasePage(object): trow = Html("tr") attr_data_row = [ - ("AttrType", str(attr.get_type() ) ), - ("AttrValue", attr.get_value() ) ] - - # get attribute note list - notelist = self.dump_notes(attr.get_note_list() ) - attr_data_row.append(("AttrNotes", notelist)) + ("Type", str(attr.get_type() ) ), + ("Value", attr.get_value() ) ] if showsrc: srcrefs = self.get_citation_links(attr.get_source_references()) or " " - else: - srcrefs = " " - attr_data_row.append(("AttrSources", srcrefs)) + attr_data_row.append(("Sources", srcrefs)) + + # get attribute note list + notelist = self.dump_notes(attr.get_note_list() ) + attr_data_row.append(("Notes", notelist)) # display attribute list trow.extend( - Html("td", data, class_ = "Column" + colclass, inline = True) + Html("td", data, class_ = "Column" + colclass, + inline = (colclass == "Type" or colclass == "Sources")) for (colclass, data) in attr_data_row) - # return table row to its callers + # return table row to its caller return trow def get_citation_links(self, source_ref_list): + """ + get citation link from the source reference list + + @param: source_ref_list = list of source references + """ + gid_list = [] lnk = (self.report.cur_fname, self.page_title, self.gid) @@ -372,7 +377,7 @@ class BasePage(object): for ref in gid_list: index, key = self.bibli.add_reference(ref) id_ = "%d%s" % (index+1, key) - text += ' [%s]' % (id_, id_) + text += ' [%s]' % (id_, id_) # return citation list text to its callers return text @@ -464,7 +469,7 @@ class BasePage(object): @param: evt = Event @param: evt_ref = event reference @param: subdirs = add [".."] * 3 for subdirectories or not - @params: hyp = add a hyperlink or not + @param: hyp = add a hyperlink or not @params: omit = role to be omitted in output """ db = self.report.database @@ -493,7 +498,7 @@ class BasePage(object): """ for more information: see get_event_data() """ - event_data = self.get_event_data(evt, evt_ref, subdirs) + event_data = self.get_event_data(evt, evt_ref, True, False, subdirs) trow.extend( Html("td", data or " ", class_ = "Column" + colclass, @@ -507,7 +512,7 @@ class BasePage(object): htmllist = self.dump_notes( notelist ) else: htmllist = Html("p") - + # if the event or event reference has a attributes attached to it, # get the text and format it correctly attrlist = evt.get_attribute_list() @@ -533,7 +538,7 @@ class BasePage(object): return trow def event_link(self, eventtype, handle, gid = None, up = False): - """ createsa hyperlink for an event based on its type """ + """ creates a hyperlink for an event based on its type """ url = self.report.build_url_fname_html(handle, "evt", up) @@ -551,37 +556,43 @@ class BasePage(object): else: return eventtype - def get_event_data(self, evt, evt_ref, up, gid = None): + def get_event_data(self, evt, evt_ref, showplc, showdescr, up, gid = None): """ retrieve event data from event and evt_ref @param: evt = event from database @param: evt_ref = eent reference + @param: showplc = show the event place or not? + @param: showdescr = to show the event description or not? @param: up = either True or False; add subdirs or not? - @param: gid = gramps_id """ db = self.report.database # get place name place = None place_handle = evt.get_place_handle() - place_hyper = None - evt_desc = evt.get_description() if place_handle: place = db.get_place_from_handle(place_handle) - if place: - place_name = ReportUtils.place_name(db, place_handle) - place_hyper = self.place_link(place_handle, place_name, up = up) + + place_hyper = None + if place: + place_name = ReportUtils.place_name(db, place_handle) + place_hyper = self.place_link(place_handle, place_name, up = up) # wrap it all up and return to its callers # position 0 = translatable label, position 1 = column class # position 2 = data info = [ - [DHEAD, "Date", _dd.display(evt.get_date_object() )], - [PHEAD, "Place", place_hyper], - [DESCRHEAD, "Description", evt_desc] + [DHEAD, "Date", _dd.display(evt.get_date_object() )] ] + if showplc: + info.append([PHEAD, "Place", place_hyper]) + + if showdescr: + descr = evt.get_description() + info.append([DESCRHEAD, "Description", descr]) + # return event data information to its callers return info @@ -790,18 +801,23 @@ class BasePage(object): # return summaryarea division to its callers return summaryarea - def addressbook_link(self, handle, up = False): - """ createsa hyperlink for an address book link based on person's handle """ - db = self.report.database + def addressbook_link(self, person_handle, up = False): + """ + creates a hyperlink for an address book link based on person's handle - url = self.report.build_url_fname_html(handle, "addr", up) - person = db.get_person_from_handle(handle) - person_name = self.get_name(person) + @param: person_handle = person's handle from the database + #param: up = rather to add subdirs or not? + """ - addr_hyper = Html("a", person_name, href = url, title = html_escape(person_name)) + url = self.report.build_url_fname_html(person_handle, "addr", up) + person = self.report.database.get_person_from_handle(person_handle) + if person.gender == gen.lib.Person.FEMALE: + person_name = self.get_name(person, person.get_primary_name().get_surname() ) + else: + person_name = self.get_name(person) # return addressbook hyperlink to its caller - return addr_hyper + return Html("a", person_name, href = url, title = html_escape(person_name)) def get_copyright_license(self, copyright, up = False): """ @@ -825,12 +841,16 @@ class BasePage(object): return text def get_name(self, person, maiden_name = None): - """ + """ I5118 + Return person's name, unless maiden_name given, unless married_name listed. + + @param: person = person object from database + @param: maiden_name = Female's family surname """ - # name_format is the name format that you set in options + # get name format for displaying names name_format = self.report.options['name_format'] # Get all of a person's names @@ -838,18 +858,19 @@ class BasePage(object): married_name = None names = [primary_name] + person.get_alternate_names() for name in names: - if int(name.get_type()) == NameType.MARRIED: + if int(name.get_type()) == gen.lib.NameType.MARRIED: married_name = name break # use first + # Now, decide which to use: if maiden_name is not None: if married_name is not None: - name = Name(married_name) + name = gen.lib.Name(married_name) else: - name = Name(primary_name) + name = gen.lib.Name(primary_name) name.set_surname(maiden_name) else: - name = Name(primary_name) + name = gen.lib.Name(primary_name) name.set_display_as(name_format) return _nd.display_name(name) @@ -864,7 +885,7 @@ class BasePage(object): return None # begin attributes division and section title - with Html("div", class_ = "subsection", id = "attributes") as section: + with Html("div", class_ = "ubsection", id = "attributes") as section: section += Html("h4", AHEAD, inline = True) # begin attributes table @@ -877,14 +898,15 @@ class BasePage(object): trow = Html("tr") thead += trow + header_row = [ + (THEAD, "Type"), + (VHEAD, "Value"), + (SHEAD, "Sources"), + (NHEAD, "Notes") ] + trow.extend( Html("th", label, class_ = "Column" + colclass, inline = True) - for (label, colclass) in [ - (_("Attribute/ Type"), "AttrType"), - (VHEAD, "AttrValue"), - (NHEAD, "AttrNotes"), - (SHEAD, "AttrSources") ] - ) + for (label, colclass) in header_row) # begin table body tbody = Html("tbody") @@ -918,26 +940,24 @@ class BasePage(object): # attach note user_footer += note.get() - value = _dd.display(date.Today()) msg = _('Generated by ' - 'Gramps %(version)s on %(date)s') % { - 'date': value, 'homepage' : const.URL_HOMEPAGE, - 'version': const.VERSION - } + 'Gramps %(version)s on %(date)s') % { + 'date': _dd.display(date.Today()), + 'homepage' : const.URL_HOMEPAGE, + 'version': const.VERSION} # optional "link-home" feature; see bug report #2736 if self.report.options['linkhome']: center_person = db.get_person_from_gramps_id(self.report.options['pid']) if center_person and center_person.handle in self.report.person_handles: - home_person_url = self.report.build_url_fname_html( + center_person_url = self.report.build_url_fname_html( center_person.handle, "ppl", self.up) - home_person_name = self.get_name(center_person) - # carriage return was added by Stephane Charette to force it down one line - msg += '
' + _(' Created for %s') % ( - home_person_url, home_person_name) + center_person_name = self.get_name(center_person) + msg += _('
Created for %s') % ( + center_person_url, center_person_name) - # creation date + # creation author footer += Html("p", msg, id = 'createdate') # get copyright license for all pages @@ -960,7 +980,7 @@ class BasePage(object): # return footer to its callers return footer - def write_header(self, title, key): + def write_header(self, title): """ Note. 'title' is used as currentsection in the navigation links and as part of the header title. @@ -987,8 +1007,6 @@ class BasePage(object): meta = (Html("meta", attr = _META1) + Html("meta", attr = _META2, indent = False) ) - # add meta tags to the head section - head += meta # Link to media reference regions behaviour stylesheet fname = "/".join(["styles", "behaviour.css"]) @@ -1003,8 +1021,8 @@ class BasePage(object): url3 = self.report.build_url_fname(fname, None, self.up) # Link to GRAMPS favicon - fname = "/".join(['images', 'favicon.ico']) - url4 = self.report.build_url_image("favicon.ico", "images", self.up) + fname = "/".join(['images', 'favicon2.ico']) + url4 = self.report.build_url_image("favicon2.ico", "images", self.up) # create stylesheet and favicon links links = Html("link", href = url4, type = "image/x-icon", rel = "shortcut icon") + ( @@ -1020,32 +1038,33 @@ class BasePage(object): links.extend( Html("link", href = url, type = "text/css", media = "screen", rel = "stylesheet", indent = False) ) - # add link tags to head section + # add additional meta and link tags + head += meta head += links - # alpha event pages do not need these things - if key is not _ALPHAEVENT: + # begin header section + headerdiv = (Html("div", id = 'header') + + Html("h1", html_escape(self.title_str), id = "SiteTitle", inline = True) + ) + body += headerdiv - # begin header section - headerdiv = (Html("div", id = 'header') + - Html("h1", html_escape(self.title_str), id = "SiteTitle", inline = True) - ) - body += headerdiv + header_note = self.report.options['headernote'] + if header_note: + note = db.get_note_from_gramps_id(header_note) - header_note = self.report.options['headernote'] - if header_note: - note = db.get_note_from_gramps_id(header_note) - - user_header = Html("div", id = 'user_header') - headerdiv += user_header + user_header = Html("div", id = 'user_header') + headerdiv += user_header - # attach note - user_header += note.get() + # attach note + user_header += note.get() - # Begin Navigation Menu - body += self.display_nav_links(title) + # Begin Navigation Menu + body += self.display_nav_links(title) - # return to its caller, page and body + # Add page title for the printed page as there is no navigation menus for reference + body += Html("h2", title, inline = True) + + # return to its callers: page and body return page, body def display_nav_links(self, currentsection): @@ -1073,7 +1092,7 @@ class BasePage(object): ('contact', _("Contact"), self.report.use_contact), ('sources', SHEAD, True), ('repositories', _("Repositories"), inc_repos), - ("addressbook", _("Address Book"), self.report.addressbook) + ("addressbook", _("Address Book"), self.report.inc_addressbook) ] navigation = Html("div", id = 'navigation') @@ -1122,7 +1141,7 @@ class BasePage(object): cs = 'class = "CurrentSection"' if cs else "" ul += (Html("li", attr = cs, inline = True) + - Html("a", nav_text, href = url) + Html("a", nav_text, href = url, title = _("Main navigation item: %s" % nav_text)) ) navigation += ul @@ -1136,8 +1155,9 @@ class BasePage(object): pic_id = self.report.options[option_name] if pic_id: obj = db.get_object_from_gramps_id(pic_id) - if obj is None: + if obj is None: return None + obj_handle = obj.handle mime_type = obj.get_mime_type() if mime_type and mime_type.startswith("image"): @@ -1146,52 +1166,18 @@ class BasePage(object): newpath, thumb_path = self.report.prepare_copy_media(obj) self.report.copy_file(Utils.media_path_full(db, obj.get_path()), newpath) - # get media rectangles - _region_items = self.media_ref_regions(obj_handle) - if len(_region_items): - with Html("div") as mediadisplay: + # begin image + image = Html("img") + img_attr = '' + if height: + img_attr += 'height = "%d"' % height + img_attr += ' src = "%s" alt = "%s"' % (newpath, obj.get_description()) - # Feature #2634; display the mouse-selectable regions. - # See the large block at the top of this function where - # the various regions are stored in _region_items - ordered = Html("ol", class_ = "RegionBox") - mediadisplay += ordered - while len(_region_items): - (name, x, y, w, h, linkurl) = _region_items.pop() - ordered += Html("li", style = "left:%d%%; top:%d%%; width:%d%%; height:%d%%;" - % (x, y, w, h)) +( - Html("a", name, href = linkurl) - ) + # add image attributes to image + image.attr = img_attr - # begin image - image = Html("img") - mediadisplay += image - img_attr = '' - if height: - img_attr += 'height = "%d"' % height - img_attr += ' src = "%s" alt = "%s"' % (newpath, obj.get_description()) - - # add image attributes to image - image.attr = img_attr - - # return image with media behaviours styling - return mediadisplay - - # media has no media references - else: - - # begin image - image = Html("img") - img_attr = '' - if height: - img_attr += 'height = "%d"' % height - img_attr += ' src = "%s" alt = "%s"' % (newpath, obj.get_description()) - - # add image attributes to image - image.attr = img_attr - - # return an image - return image + # return an image + return image except (IOError, OSError), msg: WarningDialog(_("Could not add photo to page"), str(msg)) @@ -1199,7 +1185,7 @@ class BasePage(object): # no image to return return None - def media_ref_regions(self, handle): + def media_ref_rect_regions(self, handle): """ ************************************* @@ -1307,7 +1293,12 @@ class BasePage(object): return mediaref.rect # (x1, y1, x2, y2) return None - def display_first_image_as_thumbnail( self, photolist, object): + def display_first_image_as_thumbnail(self, photolist, object): + """ + Return the Html of the first image of photolist that is + associated with object. First image might be a region in an + image. Or, the first image might have regions defined in it. + """ db = self.report.database if not photolist or not self.create_media: @@ -1336,7 +1327,7 @@ class BasePage(object): snapshot += self.media_link(photo_handle, newpath, '', up = True) else: - _region_items = self.media_ref_regions(photo_handle) + _region_items = self.media_ref_rect_regions(photo_handle) if len(_region_items): with Html("div", id="GalleryDisplay") as mediadisplay: ordered = Html("ol", class_ = "RegionBox") @@ -1432,24 +1423,6 @@ class BasePage(object): if mime_type: try: - # get media rectangles - _region_items = self.media_ref_regions(photo_handle) - if len(_region_items): - with Html("div") as mediadisplay: - section += mediadisplay - - # Feature #2634; display the mouse-selectable regions. - # See the large block at the top of this function where - # the various regions are stored in _region_items - ordered = Html("ol", class_ = "RegionBox") - mediadisplay += ordered - while len(_region_items): - (name, x, y, w, h, linkurl) = _region_items.pop() - ordered += Html("li", style = "left:%d%%; top:%d%%; width:%d%%; height:%d%%;" - % (x, y, w, h)) +( - Html("a", name, href = linkurl) - ) - lnkref = (self.report.cur_fname, self.page_title, self.gid) self.report.add_lnkref_to_photo(photo, lnkref) real_path, newpath = self.report.prepare_copy_media(photo) @@ -1576,9 +1549,9 @@ class BasePage(object): if not uri.startswith("ftp://"): uri = "ftp://%(ftpsite)s" % { "ftpsite" : uri } - descr = Html("a", descr, href = uri, title = html_escape(descr) ) + descr = Html("a", descr, href = uri, title = html_escape(descr)) trow.extend( - Html("td", data, class_ = "Column" + colclass, inline = True) + Html("td", data, class_ = "Column" + colclass) for (data, colclass) in [ (str(_type), "Type"), (descr, "Description") ] @@ -1757,8 +1730,8 @@ class BasePage(object): with Html("div", class_ = "thumbnail") as thumbnail: # begin hyperlink - hyper = (Html("a", href = url, title = name) + - Html("img", src=img_url, alt = name) ) + hyper = (Html("a", href = url, title = html_escape(name)) + + Html("img", src = img_url, alt = html_escape(name)) ) thumbnail += hyper if usedescr: @@ -1775,7 +1748,7 @@ class BasePage(object): thumbnail = Html("div", class_ = "thumbnail") # begin hyperlink - hyper = Html("a", href = url, title = name) + hyper = Html("a", href = url, title = html_escape(name)) thumbnail += hyper url = self.report.build_url_image("document.png", "images", up) @@ -1810,7 +1783,7 @@ class BasePage(object): def dump_place(self, place, table, gid): """ - dump a place information from the database + dump a place's information from within the database """ if not self.noid and gid: @@ -1842,7 +1815,7 @@ class BasePage(object): ) table += trow - # return place table to its caller + # return place table to its callers return table def dump_residence(self, has_res): @@ -1912,7 +1885,7 @@ class IndividualListPage(BasePage): showparents = report.options['showparents'] of = self.report.create_file("individuals") - indlistpage, body = self.write_header(_("Individuals"), _KEYPERSON) + indlistpage, body = self.write_header(_("Individuals")) # begin Individuals division with Html("div", class_ = "content", id = "Individuals") as individuallist: @@ -1925,8 +1898,8 @@ class IndividualListPage(BasePage): individuallist += Html("p", msg, id = "description") # add alphabet navigation - menu_set = get_first_letters(db, person_handle_list, _KEYPERSON) - alpha_nav, menu_set = alphabet_navigation(menu_set, _KEYPERSON) + menu_set = get_first_letters(db, person_handle_list, _KEYPERSON) + alpha_nav, menu_set = alphabet_navigation(menu_set) if alpha_nav is not None: individuallist += alpha_nav @@ -1992,15 +1965,9 @@ class IndividualListPage(BasePage): tcell = Html("td", class_ = "ColumnBirth", inline = True) trow += tcell - birth_ref = person.get_birth_ref() - if birth_ref: - birth = db.get_event_from_handle(birth_ref.ref) - if birth: - birth_date = _dd.display(birth.get_date_object()) - if birth.get_type() == EventType.BIRTH: - tcell += birth_date - else: - tcell += Html('em', birth_date) + birth_date = _find_birth_date(db, person) + if birth_date is not None: + tcell += birth_date else: tcell += " " @@ -2096,7 +2063,7 @@ class SurnamePage(BasePage): of = self.report.create_file(name_to_md5(surname), "srn") self.up = True - surnamepage, body = self.write_header("%s - %s" % (_("Surname"), surname), _KEYPERSON) + surnamepage, body = self.write_header("%s - %s" % (_("Surname"), surname)) # begin SurnameDetail division with Html("div", class_ = "content", id = "SurnameDetail") as surnamedetail: @@ -2158,7 +2125,7 @@ class SurnamePage(BasePage): birth = db.get_event_from_handle(birth_ref.ref) if birth: birth_date = _dd.display(birth.get_date_object()) - if birth.get_type() == EventType.BIRTH: + if birth.get_type() == gen.lib.EventType.BIRTH: tcell += birth_date else: tcell += Html('em', birth_date) @@ -2245,7 +2212,7 @@ class PlaceListPage(BasePage): db = report.database of = self.report.create_file("places") - placelistpage, body = self.write_header(_("Places"), _KEYPLACE) + placelistpage, body = self.write_header(_("Places")) # begin places division with Html("div", class_ = "content", id = "Places") as placelist: @@ -2259,7 +2226,7 @@ class PlaceListPage(BasePage): # begin alphabet navigation menu_set = get_first_letters(db, place_handles, _KEYPLACE) - alpha_nav, menu_set = alphabet_navigation(menu_set, _KEYPLACE) + alpha_nav, menu_set = alphabet_navigation(menu_set) if alpha_nav is not None: placelist += alpha_nav @@ -2334,20 +2301,17 @@ class PlaceListPage(BasePage): class PlacePage(BasePage): def __init__(self, report, title, place_handle, src_list, place_list): - """ - creates the individual place pages - """ - + """ creates the individual place pages """ self.bibli = Bibliography() db = report.database - place = report.database.get_place_from_handle(place_handle) + place = db.get_place_from_handle(place_handle) BasePage.__init__(self, report, title, place.gramps_id) - of = self.report.create_file(place_handle, "plc") + of = self.report.create_file(place.get_handle(), "plc") self.up = True - self.page_title = ReportUtils.place_name(report.database, place_handle) - placepage, body = self.write_header(_("Places"), _KEYPLACE) + self.page_title = ReportUtils.place_name(db, place_handle) + placepage, body = self.write_header(_("Places")) # begin PlaceDetail Division with Html("div", class_ = "content", id = "PlaceDetail") as placedetail: @@ -2418,7 +2382,7 @@ class EventListPage(BasePage): db = report.database of = self.report.create_file("events") - eventslistpage, body = self.write_header(_("Events"), _KEYEVENT) + eventslistpage, body = self.write_header(_("Events")) # begin events list division with Html("div", class_ = "content", id = "EventList") as eventlist: @@ -2430,7 +2394,8 @@ class EventListPage(BasePage): eventlist += Html("p", msg, id = "description") # get alphabet navigation for class EventListPage - alpha_nav, event_types = alphabet_navigation(event_types, _ALPHAEVENT) + menu_set = get_first_letters(db, event_types, _KEYEVENT) + alpha_nav, menu_set = alphabet_navigation(menu_set) if alpha_nav is not None: eventlist += alpha_nav @@ -2447,18 +2412,19 @@ class EventListPage(BasePage): trow.extend( Html("th", label, class_ = "Column" + colclass, inline = True) for (label, colclass) in [ - [THEAD, "Type"], - [DHEAD, "Date"], - [GRAMPSID, "GRAMPSID"], - [_PERSON, "Person"] ] + [_("Letter"), "Letter"], + [THEAD, "Type"], + [DHEAD, "Date"], + [GRAMPSID, "GRAMPSID"], + [_PERSON, "Person"] ] ) tbody = Html("tbody") table += tbody # separate events by their type and then thier event handles - for (evt_type, datalist) in sort_event_types(db, event_types, - event_handle_list): + displayed = [] + for (evt_type, datalist) in sort_event_types(db, event_types, event_handle_list): first_event = True for (date, gid, event_handle) in datalist: @@ -2467,21 +2433,30 @@ class EventListPage(BasePage): trow = Html("tr") tbody += trow + # display first letter if it is the first one + tcell = Html("td", class_ = "ColumnLetter", inline = True) + trow += tcell + + ltr = evt_type[0] + if ltr in displayed: + tcell += " " + else: + trow.attr = 'class = "BeginLetter" ' + tcell += Html("a", ltr, name = ltr, title = "Events beginning with letter %s" % ltr, + inline = True) + # display Event type if first in the list tcell = Html("td", class_ = "ColumnType", inline = True) trow += tcell if first_event: - trow.attr = 'class = "BeginEvent"' - tcell += Html("a", evt_type, name = evt_type, - title = _("Event types beginning with %(eventtype)s") % { - 'eventtype': evt_type}, inline = True) + tcell += evt_type else: tcell += " " # event date tcell = Html("td", class_ = "ColumnDate", inline = True) trow += tcell - if date and date is not Date.EMPTY: + if date and date is not gen.lib.Date.EMPTY: tcell += _dd.display(date) else: tcell += " " @@ -2540,7 +2515,8 @@ class EventListPage(BasePage): first_person = False else: tcell += " " - first_event = False + first_event = False + displayed.append(ltr) # add clearline for proper styling # add footer section @@ -2579,7 +2555,7 @@ class EventPage(BasePage): self.bibli = Bibliography() of = self.report.create_file(event_handle, "evt") - eventpage, body = self.write_header(_("Events"), _KEYEVENT) + eventpage, body = self.write_header(_("Events")) # start event detail division with Html("div", class_ = "content", id = "EventDetail") as eventdetail: @@ -2601,7 +2577,7 @@ class EventPage(BasePage): """ for more information: see get_event_data() """ - event_data = self.get_event_data(event, event_handle, subdirs, evt_gid) + event_data = self.get_event_data(event, event_handle, True, True, subdirs, evt_gid) for (label, colclass, data) in event_data: if data: @@ -2666,13 +2642,16 @@ class EventPage(BasePage): first_person = False # Narrative subsection +# evt_ref = event.get_reference() notelist = event.get_note_list() +# notelist.extend(evt_ref.get_note_list() ) notelist = self.display_note_list(notelist) if notelist is not None: eventdetail += notelist - # Attribute subsection + # get attribute list attrlist = event.get_attribute_list() +# attrlist.extend(evt_ref.get_attribute_list() ) attrlist = self.display_attr_list(attrlist, True) if attrlist is not None: eventdetail += attrlist @@ -2702,7 +2681,7 @@ class MediaPage(BasePage): BasePage.__init__(self, report, title, media.gramps_id) # get media rectangles - _region_items = self.media_ref_regions(handle) + _region_items = self.media_ref_rect_regions(handle) of = self.report.create_file(handle, "img") self.up = True @@ -2722,9 +2701,9 @@ class MediaPage(BasePage): note_only = True target_exists = False - self.copy_thumbnail(handle, media) + copy_thumbnail(self.report, handle, media) self.page_title = media.get_description() - mediapage, body = self.write_header("%s - %s" % (_("Media"), self.page_title), _KEYPERSON) + mediapage, body = self.write_header("%s - %s" % (_("Media"), self.page_title)) # begin MediaDetail division with Html("div", class_ = "content", id = "GalleryDetail") as mediadetail: @@ -2818,9 +2797,9 @@ class MediaPage(BasePage): url = self.report.build_url_fname(newpath, None, self.up) mediadisplay += Html("a", href = url) + ( - Html("img", width=new_width, - height=new_height, src=url, - alt=html_escape(self.page_title)) + Html("img", width = new_width, + height = new_height, src = url, + alt = html_escape(self.page_title)) ) else: dirname = tempfile.mkdtemp() @@ -2847,7 +2826,7 @@ class MediaPage(BasePage): if target_exists: # TODO. Convert disk path to URL url = self.report.build_url_fname(newpath, None, self.up) - hyper = Html("a", href = url) + ( + hyper = Html("a", href = url, title = html_escape(self.page_title)) + ( Html("img", src = img_url, alt = html_escape(self.page_title)) ) mediadisplay += hyper @@ -2886,7 +2865,7 @@ class MediaPage(BasePage): # media date date = media.get_date_object() - if date and date is not Date.EMPTY: + if date and date is not gen.lib.Date.EMPTY: trow = Html("tr") + ( Html("td", DHEAD, class_ = "ColumnAttribute", inline = True), Html("td", _dd.display(date), class_ = "ColumnValue", inline = True) @@ -2966,23 +2945,6 @@ class MediaPage(BasePage): WarningDialog(error, str(msg)) return None - def copy_thumbnail(self, handle, photo): - db = self.report.database - - to_dir = self.report.build_path('thumb', handle) - to_path = os.path.join(to_dir, handle) + '.png' - if photo.get_mime_type(): - from_path = ThumbNails.get_thumbnail_path(Utils.media_path_full( - db, - 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") - - self.report.copy_file(from_path, to_path) - class SurnameListPage(BasePage): ORDER_BY_NAME = 0 @@ -2994,10 +2956,10 @@ class SurnameListPage(BasePage): if order_by == self.ORDER_BY_NAME: of = self.report.create_file(filename) - surnamelistpage, body = self.write_header(_('Surnames'), _KEYPERSON) + surnamelistpage, body = self.write_header(_('Surnames')) else: of = self.report.create_file("surnames_count") - surnamelistpage, body = self.write_header(_('Surnames by person count'), _KEYPERSON) + surnamelistpage, body = self.write_header(_('Surnames by person count')) # begin surnames division with Html("div", class_ = "content", id = "surnames") as surnamelist: @@ -3014,7 +2976,7 @@ class SurnameListPage(BasePage): # only if surname list not surname count if order_by == self.ORDER_BY_NAME: menu_set = get_first_letters(db, person_handle_list, _KEYPERSON) - alpha_nav, menu_set = alphabet_navigation(menu_set, _KEYPERSON) + alpha_nav, menu_set = alphabet_navigation(menu_set) if alpha_nav is not None: surnamelist += alpha_nav @@ -3122,7 +3084,7 @@ class IntroductionPage(BasePage): db = report.database of = self.report.create_file(report.intro_fname) - intropage, body = self.write_header(_('Introduction'), _KEYPERSON) + intropage, body = self.write_header(_('Introduction')) # begin Introduction division with Html("div", class_ = "content", id = "Introduction") as section: @@ -3159,7 +3121,7 @@ class HomePage(BasePage): db = report.database of = self.report.create_file("index") - homepage, body = self.write_header(_('Home'), _KEYPERSON) + homepage, body = self.write_header(_('Home')) # begin home division with Html("div", class_ = "content", id = "Home") as section: @@ -3196,7 +3158,7 @@ class SourceListPage(BasePage): source_dict = {} of = self.report.create_file("sources") - sourcelistpage, body = self.write_header(_("Sources"), _KEYPERSON) + sourcelistpage, body = self.write_header(_("Sources")) # begin source list division with Html("div", class_ = "content", id = "Sources") as sourceslist: @@ -3267,7 +3229,7 @@ class SourcePage(BasePage): of = self.report.create_file(source.get_handle(), "src") self.up = True - sourcepage, body = self.write_header(_('Sources'), _KEYPERSON) + sourcepage, body = self.write_header(_('Sources')) # begin source detail division with Html("div", class_ = "content", id = "SourceDetail") as section: @@ -3312,7 +3274,7 @@ class SourcePage(BasePage): # additional notes notelist = self.display_note_list( source.get_note_list() ) - if notelist is not None: + if notelist is not None: section += notelist # references @@ -3336,7 +3298,7 @@ class MediaListPage(BasePage): db = report.database of = self.report.create_file("media") - medialistpage, body = self.write_header(_('Media'), _KEYPERSON) + medialistpage, body = self.write_header(_('Media')) # begin gallery division with Html("div", class_ = "content", id = "Gallery") as medialist: @@ -3453,7 +3415,7 @@ class DownloadPage(BasePage): return of = self.report.create_file("download") - downloadpage, body = self.write_header(_('Download'), _KEYPERSON) + downloadpage, body = self.write_header(_('Download')) # begin download page and table with Html("div", class_ = "content", id = "Download") as download: @@ -3560,7 +3522,7 @@ class ContactPage(BasePage): db = report.database of = self.report.create_file("contact") - contactpage, body = self.write_header(_('Contact'), _KEYPERSON) + contactpage, body = self.write_header(_('Contact')) # begin contact division with Html("div", class_ = "content", id = "Contact") as section: @@ -3623,12 +3585,12 @@ class IndividualPage(BasePage): This class is used to write HTML for an individual. """ gender_map = { - Person.MALE : _('male'), - Person.FEMALE : _('female'), - Person.UNKNOWN : _('unknown'), + gen.lib.Person.MALE : _('male'), + gen.lib.Person.FEMALE : _('female'), + gen.lib.Person.UNKNOWN : _('unknown'), } - def __init__(self, report, title, person, ind_list, place_list, src_list): + def __init__(self, report, title, person, ind_list, place_list, src_list, attribute_list): BasePage.__init__(self, report, title, person.gramps_id) self.person = person self.ind_list = ind_list @@ -3641,7 +3603,7 @@ class IndividualPage(BasePage): of = self.report.create_file(person.handle, "ppl") self.up = True - indivdetpage, body = self.write_header(self.sort_name, _KEYPERSON) + indivdetpage, body = self.write_header(self.sort_name) # begin individualdetail division with Html("div", class_ = "content", id = 'IndividualDetail') as individualdetail: @@ -3704,8 +3666,8 @@ class IndividualPage(BasePage): if sect8 is not None: individualdetail += sect8 - # display personal attributes and source references if any - sect9 = self.display_attr_list(person.get_attribute_list(), True) + # display attributes + sect9 = self.display_attr_list(attribute_list, True) if sect9 is not None: individualdetail += sect9 @@ -3750,9 +3712,9 @@ class IndividualPage(BasePage): top = center - _HEIGHT/2 xoff = _XOFFSET+col*(_WIDTH+_HGAP) sex = person.gender - if sex == Person.MALE: + if sex == gen.lib.Person.MALE: divclass = "male" - elif sex == Person.FEMALE: + elif sex == gen.lib.Person.FEMALE: divclass = "female" else: divclass = "unknown" @@ -3787,6 +3749,7 @@ class IndividualPage(BasePage): thumbnailUrl = "/".join(['..']*3 + [thumbnailUrl]) if constfunc.win(): thumbnailUrl = thumbnailUrl.replace('\\',"/") + url = self.report.build_url_fname_html(person.handle, "ppl", True) boxbg += self.person_link(url, person, name_style = True, thumbnailUrl=thumbnailUrl) @@ -4027,7 +3990,6 @@ class IndividualPage(BasePage): self.page_title = self.sort_name thumbnail = self.display_first_image_as_thumbnail(self.person.get_media_list(), self.person) - section_title = Html("h3", self.get_name(self.person), inline = True) # begin summaryarea division @@ -4042,7 +4004,7 @@ class IndividualPage(BasePage): # Names [and their sources] for name in all_names: - pname = _nd.display_name(name) + pname = _nd.display_name(name) if name == primary_name: pname += self.get_citation_links(self.person.get_source_references() ) pname += self.get_citation_links( name.get_source_references() ) @@ -4093,6 +4055,7 @@ class IndividualPage(BasePage): # display the nickname attribute nick_name = self.person.get_nick_name() if nick_name and nick_name != first_name: + nick_name += self.get_citation_links(self.person.get_source_references() ) trow = Html("tr") + ( Html("td", _("Nick Name"), class_ = "ColumnAttribute", inline = True), Html("td", nick_name, class_ = "ColumnValue", inline = True) @@ -4117,14 +4080,14 @@ class IndividualPage(BasePage): table += trow # Age At Death??? - birth_date = Date.EMPTY + birth_date = gen.lib.Date.EMPTY birth_ref = self.person.get_birth_ref() if birth_ref: birth = db.get_event_from_handle(birth_ref.ref) if birth: birth_date = birth.get_date_object() - if birth_date and birth_date is not Date.EMPTY: + if birth_date and birth_date is not gen.lib.Date.EMPTY: alive = Utils.probably_alive(self.person, db, date.Today() ) death_date = _find_death_date(db, self.person) @@ -4241,7 +4204,7 @@ class IndividualPage(BasePage): else: person_name = self.get_name(person) tcell2 += person_name - if rel and rel != ChildRefType(ChildRefType.BIRTH): + if rel and rel != gen.lib.ChildRefType(gen.lib.ChildRefType.BIRTH): tcell2 += '   (%s)' % str(rel) # return table columns to its caller @@ -4559,49 +4522,12 @@ class IndividualPage(BasePage): ) table += trow - # family attributes - attrlist = family.get_attribute_list() - if attrlist: - attr_trow = Html("tr") - attr_tcol = Html("td", class_="ColumnValue") - table += attr_trow - attr_trow += Html("td", class_="ColumnType") - attr_trow += Html("td", class_="ColumnAttribute") - attr_trow += attr_tcol - with Html("table", class_ = "infolist attrlist") as attrTable: - attr_tcol += attrTable - - thead = Html("thead") - attrTable += thead - - trow = Html("tr") - thead += trow - - trow.extend( - Html("th", label, class_ = "Column" + colclass, inline = True) - for (label, colclass) in [ - (_("Attribute/ Type"), "AttrType"), - (_("Value"), "AttrValue"), - (NHEAD, "AttrNotes"), - (SHEAD, "AttrSources") ] - ) - - tbody = Html("tbody") - attrTable += tbody - - tbody.extend( - self.dump_attribute(attr, True) - for attr in attrlist) - # return section to its caller return section def display_partner(self, family, table): """ display an individual's partner - - @param: family = an individual family object - @param: table = an HTML table """ gender = self.person.gender @@ -4609,9 +4535,9 @@ class IndividualPage(BasePage): db = self.report.database if reltype == FamilyRelType.MARRIED: - if gender == Person.FEMALE: + if gender == gen.lib.Person.FEMALE: relstr = _("Husband") - elif gender == Person.MALE: + elif gender == gen.lib.Person.MALE: relstr = _("Wife") else: relstr = _PARTNER @@ -4650,7 +4576,7 @@ class IndividualPage(BasePage): trow = Html("tr") + ( Html("td", " ", class_ = "ColumnType", inline = True), Html("td", " ", class_ = "ColumnAttribute", inline = True), - Html("td", self.format_events(family_events) ) + Html("td", self.format_event(family_events), class_ = "ColumnValue") ) table += trow @@ -4702,7 +4628,7 @@ class IndividualPage(BasePage): def display_event_header(self): """ will print the event header row for display_event_row() and - format_events() + format_event() """ trow = Html("tr") @@ -4712,15 +4638,14 @@ class IndividualPage(BasePage): (_EVENT, "Event"), (DHEAD, "Date"), (PHEAD, "Place"), - (DESCRHEAD, "Description"), - (NHEAD, "Notes"), + (NHEAD, "Notes"), (SHEAD, "Sources") ] ) # return header row to its callers return trow - def format_events(self, eventlist): + def format_event(self, eventlist): """ displays the event row for events such as marriage and divorce """ @@ -4765,7 +4690,7 @@ class RepositoryListPage(BasePage): db = report.database of = self.report.create_file("repositories") - repolistpage, body = self.write_header(_("Repositories"), _KEYPERSON) + repolistpage, body = self.write_header(_("Repositories")) # begin RepositoryList division with Html("div", class_ = "content", id = "RepositoryList") as repositorylist: @@ -4834,7 +4759,7 @@ class RepositoryPage(BasePage): of = self.report.create_file(handle, 'repo') self.up = True - repositorypage, body = self.write_header(_('Repositories'), _KEYPERSON) + repositorypage, body = self.write_header(_('Repositories')) # begin RepositoryDetail division and page title with Html("div", class_ = "content", id = "RepositoryDetail") as repositorydetail: @@ -4898,7 +4823,6 @@ class AddressBookListPage(BasePage): address/ Residence events @param: has_url_address -- a list of (sort_name, person_handle, has_add, has_rtes, and has_url - """ BasePage.__init__(self, report, title) db = report.database @@ -4907,8 +4831,7 @@ class AddressBookListPage(BasePage): of = self.report.create_file("addressbook") # Add xml, doctype, meta and stylesheets - addressbooklistpage, body = self.write_header("%s - %s" % (title, - _("Address Book")), _KEYPERSON) + addressbooklistpage, body = self.write_header(_("Address Book")) # begin AddressBookList division with Html("div", class_ = "content", id = "AddressBookList") as addressbooklist: @@ -4916,8 +4839,10 @@ class AddressBookListPage(BasePage): # Internet Address Book Page message msg = _("This page contains an index of all the individuals in the " - "database, sorted by their surname. Selecting the person’s " - "name will take you to their Address Book’s individual page.") + "database, sorted by their surname, with one of the " + "following: Address, Residence, or Web Links. Selecting the " + "person’s name will take you to their Address " + "Book’s individual page.") addressbooklist += Html("p", msg, id = "description") # begin Address Book table @@ -4930,78 +4855,56 @@ class AddressBookListPage(BasePage): trow = Html("tr") thead += trow - header_row = [ - [" ", "RowLabel"], - [_("Name"), "Name"], - [_("Address"), "Address"], - [_("Residence"), "Residence"], - [_("Web Links"), "WebLinks"] ] - trow.extend( Html("th", label, class_="Column" + colclass, inline=True) - for (label, colclass) in header_row) + for (label, colclass) in [ + [" ", "RowLabel"], + [_("Name"), "Name"], + [_("Address"), "Address"], + [_("Residence"), "Residence"], + [_("Web Links"), "WebLinks"] ] + ) tbody = Html("tbody") table += tbody - # local counters for total line - index, countadd, countres, counturl, countfb = 0, 0, 0, 0, 0 - + index = 1 for (sort_name, person_handle, has_add, has_res, has_url) in has_url_address: - person = db.get_person_from_handle(person_handle) - index += 1 address = None residence = None weblinks = None - facebook = None # has address but no residence event if has_add and not has_res: address = "X" - countadd += 1 # has residence, but no addresses elif has_res and not has_add: residence = "X" - countres += 1 # has residence and addresses too elif has_add and has_res: address = "X" residence = "X" - countadd += 1 - countres += 1 # has Web Links if has_url: weblinks = "X" - counturl += 1 trow = Html("tr") tbody += trow - header_row = [ - ["RowLabel", index], - ["Name", self.addressbook_link(person_handle)], - ["Address", address], - ["Residence", residence], - ["WebLinks", weblinks] ] - trow.extend( - Html("td", data or " ", - class_="Column" + colclass, inline=True) - for (colclass, data) in header_row) - - # create totals row for table - trow = Html("tr", class_ = "Totals") + ( - Html("td", _("Total"), classs_ = "ColumnRowlabel", inline = True), - Html("td", index, class_ = "ColumnName", inline = True), - Html("td", countadd, class_ = "ColumnAddress", inline = True), - Html("td", countres, class_ = "ColumnResidence", inline = True), - Html("td", counturl, class_ = "ColumnWebLinks", inline = True) - ) - tbody += trow + Html("td", data or " ", class_="Column" + colclass, inline = True) + for (colclass, data) in [ + ["RowLabel", index], + ["Name", self.addressbook_link(person_handle)], + ["Address", address], + ["Residence", residence], + ["WebLinks", weblinks] ] + ) + index += 1 # Add footer and clearline footer = self.write_footer() @@ -5030,7 +4933,7 @@ class AddressBookPage(BasePage): # set the file name and open file of = self.report.create_file(person_handle, "addr") - addressbookpage, body = self.write_header("%s - %s" % (title, _("Address Book")), _KEYPERSON) + addressbookpage, body = self.write_header(_("Address Book")) # begin address book page division and section title with Html("div", class_ = "content", id = "AddressBookDetail") as addressbookdetail: @@ -5105,7 +5008,7 @@ class NavWebReport(Report): self.inc_contact = self.options['contactnote'] or \ self.options['contactimg'] - # name format option + # name format options self.name_format = self.options['name_format'] # create an event pages or not? @@ -5142,7 +5045,7 @@ class NavWebReport(Report): self.birthorder = self.options['birthorder'] # get option for Internet Address Book - self.addressbook = self.options["addressbook"] + self.inc_addressbook = self.options["inc_addressbook"] if self.use_home: self.index_fname = "index" @@ -5240,7 +5143,7 @@ class NavWebReport(Report): # build classes SurnameListPage and SurnamePage self.surname_pages(ind_list) - # build PlaceListPage and PlacePage + # build classes PlaceListPage and PlacePage self.place_pages(place_list, source_list) # build classes EventListPage and EventPage @@ -5250,11 +5153,11 @@ class NavWebReport(Report): # build classes SourceListPage and SourcePage self.source_pages(source_list) - # build MediaListPage and MediaPage + # build classes MediaListPage and MediaPage if self.inc_gallery: self.gallery_pages(source_list) - # Build source pages a second time to pick up sources referenced + # Build classes source pages a second time to pick up sources referenced # by galleries self.source_pages(source_list) @@ -5264,9 +5167,10 @@ class NavWebReport(Report): if len(repolist): self.repository_pages(repolist) - # build class InternetAddressBook - if self.addressbook: - self.address_book_page(ind_list) + + # build classes ddressBookList and AddressBookPage + if self.inc_addressbook: + self.addressbook_pages(ind_list) # if an archive is being used, close it? if self.archive: @@ -5310,10 +5214,6 @@ class NavWebReport(Report): fname = os.path.join(const.DATA_DIR, self.css) self.copy_file(fname, _NARRATIVESCREEN, "styles") - # copy printer stylesheet - fname = os.path.join(const.DATA_DIR, "Web_Print-Default.css") - self.copy_file(fname, _NARRATIVEPRINT, "styles") - # copy Navigation Menu Layout if Blue or Visually is being used if self.css == "Web_Basic-Blue.css" or "Web_Visually.css": if self.navigation == "Horizontal": @@ -5322,12 +5222,16 @@ class NavWebReport(Report): fname = os.path.join(const.DATA_DIR, "Web_Navigation-Vertical.css") self.copy_file(fname, "Web_Navigation-Menus.css", "styles") + # copy printer stylesheet + fname = os.path.join(const.DATA_DIR, "Web_Print-Default.css") + self.copy_file(fname, _NARRATIVEPRINT, "styles") + imgs = [] # Mainz stylesheet graphics # will only be used if Mainz is slected as the stylesheet Mainz_images = ["Web_Mainz_Bkgd.png", "Web_Mainz_Header.png", - "Web_Mainz_Mid.png", "Web_Mainz_MidLight.png"] + "Web_Mainz_Mid.png", "Web_Mainz_MidLight.png"] # Copy Mainz Style Images if self.css == "Web_Mainz.css": @@ -5339,7 +5243,7 @@ class NavWebReport(Report): imgs += ["somerights20.gif"] # include GRAMPS favicon - imgs += ["favicon.ico"] + imgs += ["favicon2.ico"] # we need the blank image gif neede by behaviour.css imgs += ["blank.gif"] @@ -5350,14 +5254,28 @@ class NavWebReport(Report): # copy Ancestor Tree graphics if needed??? if self.graph: imgs += ["Web_Gender_Female.png", - "Web_Gender_FemaleFFF.png", - "Web_Gender_Male.png", - "Web_Gender_MaleFFF.png"] + "Web_Gender_Male.png" ] for fname in imgs: from_path = os.path.join(const.IMAGE_DIR, fname) self.copy_file(from_path, fname, "images") + def build_attributes(self, person): + """ build a list of attributes for each person """ + db = self.database + + # get personal attributes + attribute_list = person.get_attribute_list() + + for family_handle in person.get_family_handle_list(): + family = db.get_family_from_handle(family_handle) + + # get family attributes + attribute_list.extend(family.get_attribute_list() ) + + # return attributes to its caller + return attribute_list + def person_pages(self, ind_list, place_list, source_list): self.progress.set_pass(_('Creating individual pages'), len(ind_list) + 1) @@ -5371,7 +5289,10 @@ class NavWebReport(Report): self.progress.step() person = self.database.get_person_from_handle(person_handle) - IndividualPage(self, self.title, person, ind_list, place_list, source_list) + # get attributes for each person + attribute_list = self.build_attributes(person) + + IndividualPage(self, self.title, person, ind_list, place_list, source_list, attribute_list) if self.inc_gendex: self.progress.set_pass(_('Creating GENDEX file'), len(ind_list)) @@ -5451,23 +5372,19 @@ class NavWebReport(Report): a dump of all the events sorted by event type, date, and surname for classes EventListPage and EventPage """ - db = self.database # set up progress bar for event pages; using ind list - event_handle_list, event_types = build_event_data(db, ind_list) + event_handle_list, event_types = build_event_data(self.database, ind_list) self.progress.set_pass(_("Creating event pages"), len(event_handle_list)) # send all data to the events list page EventListPage(self, self.title, event_types, event_handle_list) - index = 0 for event_handle in event_handle_list: - self.progress.set_header(_("Creating event page %02d of %02d") % (index + 1, len(event_handle_list))) # create individual event pages EventPage(self, self.title, event_handle) - index += 1 self.progress.step() def gallery_pages(self, source_list): @@ -5511,19 +5428,19 @@ class NavWebReport(Report): will create RepositoryPage() and RepositoryListPage() """ - db = self.database repos_dict = {} # Sort the repositories for handle in repolist: - repo = db.get_repository_from_handle(handle) + repo = self.database.get_repository_from_handle(handle) key = repo.name + str(repo.get_gramps_id()) repos_dict[key] = (repo, handle) - keys = sorted(repos_dict, key=locale.strxfrm) + keys = sorted(repos_dict, key = locale.strxfrm) # set progress bar pass for Repositories - self.progress.set_pass(_('Creating repository pages'), len(repos_dict)) + repo_size = len(repos_dict) + self.progress.set_pass(_('Creating repository pages'), repo_size) # RepositoryListPage Class RepositoryListPage(self, self.title, repos_dict, keys) @@ -5534,19 +5451,19 @@ class NavWebReport(Report): # RepositoryPage Class RepositoryPage(self, self.title, repo, handle, repo.gramps_id) + # increment progress bar self.progress.step() - def address_book_page(self, ind_list): + def addressbook_pages(self, ind_list): """ Creates classes AddressBookListPage and AddressBookPage """ - db = self.database has_url_address = [] for person_handle in ind_list: - person = db.get_person_from_handle(person_handle) + person = self.database.get_person_from_handle(person_handle) addrlist = person.get_address_list() evt_ref_list = person.get_event_ref_list() urllist = person.get_url_list() @@ -5554,13 +5471,14 @@ class NavWebReport(Report): has_add = None has_url = None has_res = None + if addrlist: has_add = addrlist if urllist: has_url = urllist for event_ref in evt_ref_list: - event = db.get_event_from_handle(event_ref.ref) + event = self.database.get_event_from_handle(event_ref.ref) # get event type evt_type = str(event.get_type() ) @@ -5580,13 +5498,16 @@ class NavWebReport(Report): if has_url_address: has_url_address.sort() - self.progress.set_pass(_("Creating address book pages ..."), len(has_url_address)) + addr_size = len( has_url_address ) + self.progress.set_pass(_("Creating address book pages ..."), addr_size) for (sort_name, person_handle, has_add, has_res, has_url) in has_url_address: - self.progress.step() AddressBookPage(self, self.title, person_handle, has_add, has_res, has_url) + # increment progress bar + self.progress.step() + def build_subdirs(self, subdir, fname, up = False): """ If subdir is given, then two extra levels of subdirectory are inserted @@ -6048,8 +5969,7 @@ class NavWebOptions(MenuReportOptions): #menu.add_option(category_name, 'showhalfsiblings', showallsiblings) birthorder = BooleanOption(_('Sort all children in birth order'), False) - birthorder.set_help(_('Whether to display children in birth order' - ' or in entry order?')) + birthorder.set_help(_('Whether to display children in birth order or in entry order?')) menu.add_option(category_name, 'birthorder', birthorder) inc_events = BooleanOption(_('Include event pages'), False) @@ -6064,10 +5984,10 @@ class NavWebOptions(MenuReportOptions): inc_gendex.set_help(_('Whether to include a GENDEX file or not')) menu.add_option(category_name, 'inc_gendex', inc_gendex) - addressbook = BooleanOption(_("Include address book pages"), False) - addressbook.set_help(_("Whether to add Address Book pages or not which can include" - " e-mail and website addresses and personal address/ residence events?")) - menu.add_option(category_name, "addressbook", addressbook) + inc_addressbook = BooleanOption(_("Include address book pages"), False) + inc_addressbook.set_help(_("Whether to add Address Book pages or not which can include" + " e-mail and website addresses and personal address/ residence events?")) + menu.add_option(category_name, "inc_addressbook", inc_addressbook) def __archive_changed(self): """ @@ -6222,7 +6142,7 @@ def _get_short_name(gender, name): prefix = name.get_surname_prefix() if prefix: short_name = prefix + " " + short_name - if gender == Person.FEMALE: + if gender == gen.lib.Person.FEMALE: return short_name else: suffix = name.get_suffix() @@ -6252,30 +6172,46 @@ def first_letter(string): return letter def get_first_letters(db, handle_list, key): - """ key is _PLACE or _PERSON ....""" + """ + return a dictionary for the first letters + + @param: habdle_list = a dictionary of handle or event types + @param: key = _KEYPERSON, _KEYPLACE, or _KEYEVENT + """ first_letters = [] - for handle in handle_list: - if key == _KEYPERSON: - keyname = __get_person_keyname(db, handle) - else: - keyname = __get_place_keyname(db, handle) - ltr = first_letter(keyname) + if key == _KEYEVENT: + for evttype in handle_list: + first_letters.append(evttype[0]) - if ltr is not ",": - first_letters.append(ltr) + else: + for handle in handle_list: + if key == _KEYPERSON: + keyname = __get_person_keyname(db, handle) + else: + keyname = __get_place_keyname(db, handle) + ltr = first_letter(keyname) + + if ltr is not ",": + first_letters.append(ltr) + + # return first letters from data to its callers return first_letters -def alphabet_navigation(menu_set, alphakey): +def alphabet_navigation(menu_set): """ Will create the alphabet navigation bar for classes IndividualListPage, SurnameListPage, PlaceListPage, and EventList @param: menu_set -- a dictionary of either letters or words - @param: alphakey -- either Person, Place, or AlphaEvent """ + + # if no letters or words, return None to its callers + if not menu_set: + return None, [] + sorted_set = defaultdict(int) # The comment below from the glibc locale sv_SE in # localedata/locales/sv_SE : @@ -6290,7 +6226,6 @@ def alphabet_navigation(menu_set, alphakey): # See : http://www.gramps-project.org/bugs/view.php?id = 2933 # (lang_country, modifier ) = locale.getlocale() - ltr = get_first_letters for menu_item in menu_set: sorted_set[menu_item] += 1 @@ -6298,20 +6233,12 @@ def alphabet_navigation(menu_set, alphakey): # remove the number of each occurance of each letter sorted_alpha_index = sorted(sorted_set, key = locale.strxfrm) - # remove any commas from the letter set - sorted_alpha_index = [(menu_item) for menu_item in sorted_alpha_index if menu_item != ","] - - # remove any single spaces from the letter set also - # Event Types can and do have spaces, so leave them alone for now... - if alphakey is not _ALPHAEVENT: - sorted_alpha_index = [(ltr) for ltr in sorted_alpha_index if ltr != " "] - - # if no letters or words, return None to its callers - if not sorted_alpha_index: - return None, [] + # remove any commas and spaces from the letter set + sorted_alpha_index = [(menu_item) for menu_item in sorted_alpha_index + if menu_item not in [ ",", " "]] num_ltrs = len(sorted_alpha_index) - num_of_cols = 34 if alphakey is not _ALPHAEVENT else 10 + num_of_cols = 32 num_of_rows = ((num_ltrs // num_of_cols) + 1) # begin alphabet navigation division @@ -6328,10 +6255,14 @@ def alphabet_navigation(menu_set, alphakey): unordered += list menu_item = sorted_alpha_index[index] + + # adding for Visually Impaired screen readers and braille writers + title_str = _("Alphabet Navigation Item: %s" % menu_item) + if lang_country == "sv_SE" and menu_item == u'V': - hyper = Html("a", "V,W", href = "#V,W", alt = "V,W") + hyper = Html("a", "V,W", href = "#V,W", title = title_str) else: - hyper = Html("a", menu_item, href = "#%s" % menu_item, alt = html_escape(menu_item)) + hyper = Html("a", menu_item, href = "#%s" % menu_item, title = title_str) list += hyper # increase letter/ word in sorted_alpha_index @@ -6367,12 +6298,25 @@ def add_birthdate(db, childlist): if birth: birth_date = birth.get_date_object() else: - birth_date = Date(2199, 12, 31) + birth_date = gen.lib.Date(2199, 12, 31) sorted_children.append((birth_date, child_handle)) # return the list of child handles and their birthdates return sorted_children +def _find_birth_date(db, person): + birth_ref = person.get_birth_ref() + if birth_ref: + birth = db.get_event_from_handle(birth_ref.ref) + return birth.get_date_object() + else: + event_list = person.get_primary_event_ref_list() + for event_ref in event_list: + event = db.get_event_from_handle(event_ref.ref) + if event.get_type().is_birth_fallback(): + return event.get_date_object() + return None + def _find_death_date(db, person): death_ref = person.get_death_ref() if death_ref: diff --git a/src/plugins/webreport/WebCal.py b/src/plugins/webreport/WebCal.py index f02179a6f..a4355e1d3 100644 --- a/src/plugins/webreport/WebCal.py +++ b/src/plugins/webreport/WebCal.py @@ -1,10 +1,11 @@ +# encoding: utf-8 # # Gramps - a GTK+/GNOME based genealogy program # -# Copyright (C) 2007 Thom Sturgill +# Copyright (C) 2007 Thom Sturgill # Copyright (C) 2007-2009 Brian G. Matherly -# Copyright (C) 2008-2009 Rob G. Healey -# Copyright (C) 2008 Jason Simanek +# Copyright (C) 2008-2010 Rob G. Healey +# Copyright (C) 2008 Jason Simanek # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -25,14 +26,9 @@ """ Web Calendar generator. - -Refactoring. This is an ongoing job until this plugin is in a better shape. """ -from __future__ import with_statement #------------------------------------------------------------------------ -# # python modules -# #------------------------------------------------------------------------ import os, codecs, shutil, re import datetime, calendar @@ -41,19 +37,15 @@ from gen.ggettext import ngettext from itertools import imap #------------------------------------------------------------------------ -# # Set up logging -# #------------------------------------------------------------------------ import logging log = logging.getLogger(".WebPage") #------------------------------------------------------------------------ -# # GRAMPS module -# #------------------------------------------------------------------------ -from gen.lib import date, Date, Name, Person, NameType, EventType +import gen.lib import const import constfunc from ReportBase import Report, ReportUtils, MenuReportOptions, CSS_FILES @@ -67,7 +59,6 @@ from gui.utils import ProgressMeter from DateHandler import displayer as _dd from gen.display.name import displayer as _nd -from DateHandler import displayer as _dd import libholiday from libhtml import Html @@ -76,7 +67,6 @@ from libhtmlconst import _CHARACTER_SETS, _CC, _COPY_OPTIONS # import styled notes from # src/plugins/lib/libhtmlbackend.py from libhtmlbackend import HtmlBackend -import Utils #------------------------------------------------------------------------ # # constants @@ -151,7 +141,7 @@ class WebCalReport(Report): self.email = researcher.email # set to today's date - self.today = date.Today() + self.today = gen.lib.date.Today() self.warn_dir = True # Only give warning once. @@ -280,11 +270,11 @@ class WebCalReport(Report): if month > 0: try: - event_date = Date(year, month, day) + event_date = gen.lib.Date(year, month, day) except ValueError: - event_date = Date.EMPTY + event_date = gen.lib.Date.EMPTY else: - event_date = Date.EMPTY # Incomplete date.... + event_date = gen.lib.Date.EMPTY # Incomplete date.... day_list.append((text, event, event_date)) month_dict[day] = day_list @@ -329,6 +319,11 @@ class WebCalReport(Report): fname = os.path.join(const.DATA_DIR, self.css) self.copy_file(fname, _CALENDARSCREEN, "styles") + # copy Navigation Menu Layout if Blue or Visually is being used + if self.css == "Web_Basic-Blue.css" or "Web_Visually.css": + fname = os.path.join(const.DATA_DIR, "Web_Navigation-Horizontal.css") + self.copy_file(fname, "Web_Navigation-Menus.css", "styles") + # copy print stylesheet fname = os.path.join(const.DATA_DIR, "Web_Print-Default.css") self.copy_file(fname, _CALENDARPRINT, "styles") @@ -389,7 +384,7 @@ class WebCalReport(Report): # --------------------------------------------------------------------------------------- # Beginning of Calendar Creation # --------------------------------------------------------------------------------------- - def write_header(self, nr_up, body_id, title, add_print=True): + def write_header(self, nr_up, title, body_id = None, add_print = True): """ This creates the header for the Calendars 'nr_up' - number of directory levels up, started from current page, to the @@ -410,6 +405,10 @@ class WebCalReport(Report): page, head, body = Html.page(title, self.encoding, xmllang) + # add body id tag if not None + if body_id is not None: + body.attr = "id = '%(idtag)s'" % { 'idtag' : body_id } + # GRAMPS favicon fname1 = os.path.join(subdirs, "images", "favicon.ico") @@ -422,24 +421,25 @@ class WebCalReport(Report): ) # links for GRAMPS favicon and stylesheets - links = Html("link", rel='shortcut icon', href=fname1, - type = "image/x-icon") + ( - Html("link",rel="stylesheet", href=fname2, type="text/css", media= "screen", - indent = False) + links = Html("link", rel='shortcut icon', href=fname1, type = "image/x-icon") + ( + Html("link",rel="stylesheet", href=fname2, type="text/css", media= "screen", indent = False) ) # add printer stylesheet to webcalendar() and one_day() only if add_print: fname = os.path.join(subdirs, "styles", _CALENDARPRINT) - links += Html("link",rel="stylesheet", href=fname,type="text/css", media="print", - indent = False) + links += Html("link",rel="stylesheet", href=fname,type="text/css", media="print", indent = False) + + # add horizontal menu if css == Blue or Visually because there is no menus + if self.css in ["Web_Basic-Blue.css", "Web_Visually.css"]: + + # Link to Navigation Menus stylesheet + fname = os.path.join(subdirs, "styles", "Web_Navigation-Menus.css") + links.extend( Html("link", href = fname, type = "text/css", media = "screen", rel = "stylesheet") ) # add meta tags and links to head section head += (meta, links) - # replace standard body element with custom one - body.attr = 'id="%s"' % body_id - # start header division section header = Html("div", id="header") + ( @@ -500,10 +500,11 @@ class WebCalReport(Report): # Figure out if we need
  • or just plain
  • cs = str(cal_year) == currentsection and 'class="CurrentSection"' or '' - unordered += Html("li", attr=cs, inline = True) + ( + unordered += Html("li", attr = cs, inline = True) + ( # create hyperlink - Html("a", str(cal_year), href = url, title = "Year %04d" % cal_year, inline = True) + Html("a", str(cal_year), href = url, title = _("Sub Navigation Menu Item: " + "Year %04d" % cal_year), inline = True) ) # return yearnav to its caller @@ -528,7 +529,9 @@ class WebCalReport(Report): # An optional link to a home page navs.append((self.home_link, _('html|Home'), add_home)) - navs.extend((month, month, True) for month in range(1,13)) + navs.extend( + (month, month, True) for month in range(1,13) + ) # Add a link for year_glance() if requested navs.append(('fullyearlinked', _('Year Glance'), self.fullyear)) @@ -570,7 +573,7 @@ class WebCalReport(Report): unordered += Html("li", attr = cs, inline = True) + ( # create hyperlink - Html("a", nav_text, href = url, title=url_fname, inline = True) + Html("a", nav_text, href = url, title = _("Main Navigation Menu Item: %s" % url_fname), inline = True) ) # return monthnav to its caller @@ -727,7 +730,7 @@ class WebCalReport(Report): bday_anniv_list = self.calendar.get(month, {}).get(thisday.day, []) # date is an instance because of subtracting abilities in date.py - event_date = Date(thisday.year, thisday.month, thisday.day) + event_date = gen.lib.Date(thisday.year, thisday.month, thisday.day) # get events for this day day_list = get_day_list(event_date, holiday_list, bday_anniv_list) @@ -776,8 +779,8 @@ class WebCalReport(Report): tcell += unordered for nyears, date, text, event in day_list: - unordered += Html("li", text, inline = False if event == 'Anniversary' - else True) + unordered += Html("li", text, inline = False + if event == 'Anniversary' else True) # no events for this day else: @@ -839,13 +842,12 @@ class WebCalReport(Report): for month in range(1, 13): - # Name the file, and create it cal_fname = get_full_month_name(month) of = self.create_file(cal_fname, str(year)) # Add xml, doctype, meta and stylesheets # body has already been added to webcal already once - webcal, body = self.write_header(nr_up, 'WebCal', self.title_text) + webcal, body = self.write_header(nr_up, self.title_text) # create Year Navigation menu if (self.multiyear and ((self.end_year - self.start_year) > 0)): @@ -901,7 +903,6 @@ class WebCalReport(Report): # generate progress pass for "Year At A Glance" self.progress.set_pass(_('Creating Year At A Glance calendar'), 12) - # Name the file, and create it of = self.create_file('fullyearlinked', str(year)) # page title @@ -909,7 +910,7 @@ class WebCalReport(Report): # Create page header # body has already been added to yearglance already once - yearglance, body = self.write_header(nr_up, 'fullyearlinked', title, False) + yearglance, body = self.write_header(nr_up, title, "fullyearlinked", False) # create Year Navigation menu if (self.multiyear and ((self.end_year - self.start_year) > 0)): @@ -971,14 +972,13 @@ class WebCalReport(Report): year = event_date.get_year() month = event_date.get_month() - # Name the file, and crate it (see code in calendar_build) od = self.create_file(fname_date, str(year)) # page title title = _('One Day Within A Year') # create page header - oneday, body = self.write_header(nr_up, 'OneDay', title) + oneday, body = self.write_header(nr_up, title, "OneDay") # create Year Navigation menu if (self.multiyear and ((self.end_year - self.start_year) > 0)): @@ -1063,19 +1063,19 @@ class WebCalReport(Report): married_name = None names = [primary_name] + person.get_alternate_names() for name in names: - if int(name.get_type()) == NameType.MARRIED: + if int(name.get_type()) == gen.lib.NameType.MARRIED: married_name = name break # Now, decide which to use: if maiden_name is not None: if married_name is not None: - name = Name(married_name) + name = gen.lib.Name(married_name) else: - name = Name(primary_name) + name = gen.lib.Name(primary_name) name.set_surname(maiden_name) else: - name = Name(primary_name) + name = gen.lib.Name(primary_name) name.set_display_as(self.name_format) return _nd.display_name(name) @@ -1099,14 +1099,13 @@ class WebCalReport(Report): family_list = person.get_family_handle_list() birth_ref = person.get_birth_ref() - birth_date = Date.EMPTY + birth_date = gen.lib.Date.EMPTY if birth_ref: birth_event = db.get_event_from_handle(birth_ref.ref) birth_date = birth_event.get_date_object() # determine birthday information??? - if (self.birthday and birth_date is not Date.EMPTY - and birth_date.is_valid()): + if (self.birthday and birth_date is not gen.lib.Date.EMPTY and birth_date.is_valid()): year = birth_date.get_year() or this_year month = birth_date.get_month() @@ -1114,11 +1113,11 @@ class WebCalReport(Report): # date to figure if someone is still alive # current year of calendar, month nd day is their birth month and birth day - prob_alive_date = Date(this_year, month, day) + prob_alive_date = gen.lib.Date(this_year, month, day) # add some things to handle maiden name: father_surname = None # husband, actually - if person.gender == Person.FEMALE: + if person.gender == gen.lib.Person.FEMALE: # get husband's last name: if self.maiden_name in ['spouse_first', 'spouse_last']: @@ -1134,7 +1133,8 @@ class WebCalReport(Report): if father_handle: father = db.get_person_from_handle(father_handle) if father is not None: - father_surname = _get_regular_surname(person.gender, father.primary_name) + father_surname = _get_regular_surname(person.gender, + father.get_primary_name()) short_name = self.get_name(person, father_surname) alive = probably_alive(person, db, prob_alive_date) if (self.alive and alive) or not self.alive: @@ -1168,13 +1168,13 @@ class WebCalReport(Report): marriage_event = get_marriage_event(db, fam) if marriage_event: event_date = marriage_event.get_date_object() - if event_date is not Date.EMPTY and event_date.is_valid(): + if event_date is not gen.lib.Date.EMPTY and event_date.is_valid(): year = event_date.get_year() month = event_date.get_month() day = event_date.get_day() # date to figure if someone is still alive - prob_alive_date = Date(this_year, month, day) + prob_alive_date = gen.lib.Date(this_year, month, day) if self.link_to_narweb: spouse_name = Html("a", spouse_name, @@ -1209,7 +1209,8 @@ class WebCalReport(Report): # Display date as user set in preferences msg = _('Generated by ' - 'Gramps on %(date)s') % {'date' : _dd.display(date.Today())} + 'Gramps on %(date)s') % {'date' : _dd.display( + gen.lib.date.Today())} footer += Html("p", msg, id = 'createdate') copy_nr = self.copy @@ -1384,7 +1385,7 @@ class WebCalOptions(MenuReportOptions): css = EnumeratedListOption(_('StyleSheet'), CSS_FILES[0][1]) for style in CSS_FILES: css.add_item(style[1], style[0]) - css.set_help( _('The Style Sheet to be used for the web page')) + css.set_help( _('The stylesheet to be used for the web pages')) menu.add_option(category_name, "css", css) def __add_content_options(self, menu): @@ -1394,7 +1395,7 @@ class WebCalOptions(MenuReportOptions): category_name = _("Content Options") # set to today's date for use in menu, etc. - today = date.Today() + today = gen.lib.date.Today() self.__multiyear = BooleanOption(_('Create multiple year calendars'), False) self.__multiyear.set_help(_('Whether to create Multiple year calendars or not.')) @@ -1608,7 +1609,7 @@ def _get_regular_surname(sex, name): prefix = name.get_surname_prefix() if prefix: surname = prefix + " " + surname - if sex is not Person.FEMALE: + if sex is not gen.lib.Person.FEMALE: suffix = name.get_suffix() if suffix: surname = surname + ", " + suffix @@ -1700,7 +1701,7 @@ def get_day_list(event_date, holiday_list, bday_anniv_list): # birthday/ anniversary on this day # Date.EMPTY signifies an incomplete date for an event. See add_day_item() bday_anniv_list = [(t, e, d) for t, e, d in bday_anniv_list - if d != Date.EMPTY] + if d != gen.lib.Date.EMPTY] # number of years have to be at least zero bday_anniv_list = [(t, e, d) for t, e, d in bday_anniv_list