Reorganization of the narrative web report. (#445)
* Reorganization of the narrative web report. Resolves #010151, #07740 * Add empty role to person and family backref lists
This commit is contained in:
parent
1d51fa4f61
commit
8a648e7e22
120
gramps/plugins/webreport/addressbook.py
Normal file
120
gramps/plugins/webreport/addressbook.py
Normal file
@ -0,0 +1,120 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
AddressBookPage
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.plug.report import Bibliography
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import FULLCLEAR
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
class AddressBookPage(BasePage):
|
||||
"""
|
||||
Create one page for one Address
|
||||
"""
|
||||
def __init__(self, report, title, person_handle, has_add, has_res, has_url):
|
||||
"""
|
||||
@param: report -- The instance of the main report class
|
||||
for this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: person_handle -- the url, address and residence to use
|
||||
for the report
|
||||
@param: has_add -- the address to use for the report
|
||||
@param: has_res -- the residence to use for the report
|
||||
@param: has_url -- the url to use for the report
|
||||
"""
|
||||
person = report.database.get_person_from_handle(person_handle)
|
||||
BasePage.__init__(self, report, title, person.gramps_id)
|
||||
self.bibli = Bibliography()
|
||||
|
||||
self.uplink = True
|
||||
|
||||
# set the file name and open file
|
||||
output_file, sio = self.report.create_file(person_handle, "addr")
|
||||
addressbookpage, head, body = self.write_header(_("Address Book"))
|
||||
|
||||
# begin address book page division and section title
|
||||
with Html("div", class_="content",
|
||||
id="AddressBookDetail") as addressbookdetail:
|
||||
body += addressbookdetail
|
||||
|
||||
link = self.new_person_link(person_handle, uplink=True,
|
||||
person=person)
|
||||
addressbookdetail += Html("h3", link)
|
||||
|
||||
# individual has an address
|
||||
if has_add:
|
||||
addressbookdetail += self.display_addr_list(has_add, None)
|
||||
|
||||
# individual has a residence
|
||||
if has_res:
|
||||
addressbookdetail.extend(
|
||||
self.dump_residence(res)
|
||||
for res in has_res
|
||||
)
|
||||
|
||||
# individual has a url
|
||||
if has_url:
|
||||
addressbookdetail += self.display_url_list(has_url)
|
||||
|
||||
# add fullclear for proper styling
|
||||
# and footer section to page
|
||||
footer = self.write_footer(None)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(addressbookpage, output_file, sio, 0)
|
||||
170
gramps/plugins/webreport/addressbooklist.py
Normal file
170
gramps/plugins/webreport/addressbooklist.py
Normal file
@ -0,0 +1,170 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
AddressBookListPage
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import FULLCLEAR
|
||||
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
_ = glocale.translation.sgettext
|
||||
getcontext().prec = 8
|
||||
|
||||
class AddressBookListPage(BasePage):
|
||||
"""
|
||||
Create the index for addresses.
|
||||
"""
|
||||
def __init__(self, report, title, has_url_addr_res):
|
||||
"""
|
||||
@param: report -- The instance of the main report class
|
||||
for this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: has_url_addr_res -- The url, address and residence to use
|
||||
for the report
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
|
||||
# Name the file, and create it
|
||||
output_file, sio = self.report.create_file("addressbook")
|
||||
|
||||
# Add xml, doctype, meta and stylesheets
|
||||
addressbooklistpage, head, body = self.write_header(_("Address Book"))
|
||||
|
||||
# begin AddressBookList division
|
||||
with Html("div", class_="content",
|
||||
id="AddressBookList") as addressbooklist:
|
||||
body += addressbooklist
|
||||
|
||||
# Address Book Page message
|
||||
msg = _("This page contains an index of all the individuals in "
|
||||
"the 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 individual Address Book page.")
|
||||
addressbooklist += Html("p", msg, id="description")
|
||||
|
||||
# begin Address Book table
|
||||
with Html("table",
|
||||
class_="infolist primobjlist addressbook") as table:
|
||||
addressbooklist += table
|
||||
|
||||
thead = Html("thead")
|
||||
table += thead
|
||||
|
||||
trow = Html("tr")
|
||||
thead += trow
|
||||
|
||||
trow.extend(
|
||||
Html("th", label, class_=colclass, inline=True)
|
||||
for (label, colclass) in [
|
||||
[" ", "ColumnRowLabel"],
|
||||
[_("Full Name"), "ColumnName"],
|
||||
[_("Address"), "ColumnAddress"],
|
||||
[_("Residence"), "ColumnResidence"],
|
||||
[_("Web Links"), "ColumnWebLinks"]
|
||||
]
|
||||
)
|
||||
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
index = 1
|
||||
for (sort_name, person_handle,
|
||||
has_add, has_res,
|
||||
has_url) in has_url_addr_res:
|
||||
|
||||
address = None
|
||||
residence = None
|
||||
weblinks = None
|
||||
|
||||
# has address but no residence event
|
||||
if has_add and not has_res:
|
||||
address = "X"
|
||||
|
||||
# has residence, but no addresses
|
||||
elif has_res and not has_add:
|
||||
residence = "X"
|
||||
|
||||
# has residence and addresses too
|
||||
elif has_add and has_res:
|
||||
address = "X"
|
||||
residence = "X"
|
||||
|
||||
# has Web Links
|
||||
if has_url:
|
||||
weblinks = "X"
|
||||
|
||||
trow = Html("tr")
|
||||
tbody += trow
|
||||
|
||||
trow.extend(
|
||||
Html("td", data or " ", class_=colclass,
|
||||
inline=True)
|
||||
for (colclass, data) in [
|
||||
["ColumnRowLabel", index],
|
||||
["ColumnName",
|
||||
self.addressbook_link(person_handle)],
|
||||
["ColumnAddress", address],
|
||||
["ColumnResidence", residence],
|
||||
["ColumnWebLinks", weblinks]
|
||||
]
|
||||
)
|
||||
index += 1
|
||||
|
||||
# Add footer and clearline
|
||||
footer = self.write_footer(None)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send the page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(addressbooklistpage, output_file, sio, 0)
|
||||
2801
gramps/plugins/webreport/basepage.py
Normal file
2801
gramps/plugins/webreport/basepage.py
Normal file
File diff suppressed because it is too large
Load Diff
80
gramps/plugins/webreport/citation.py
Normal file
80
gramps/plugins/webreport/citation.py
Normal file
@ -0,0 +1,80 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
CitationPages - dummy
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
#################################################
|
||||
#
|
||||
# Passes citations through to the Sources page
|
||||
#
|
||||
#################################################
|
||||
class CitationPages(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information about the 'Citation'
|
||||
database objects. It passes this information to the 'Sources' tab. It is
|
||||
told by the 'add_instances' call which 'Citation's to display.
|
||||
"""
|
||||
def __init__(self, report):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
"""
|
||||
BasePage.__init__(self, report, title="")
|
||||
|
||||
def display_pages(self, title):
|
||||
pass
|
||||
863
gramps/plugins/webreport/common.py
Normal file
863
gramps/plugins/webreport/common.py
Normal file
@ -0,0 +1,863 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
This module is used to share variables, enums and functions between all modules
|
||||
|
||||
"""
|
||||
|
||||
from unicodedata import normalize
|
||||
from collections import defaultdict
|
||||
from hashlib import md5
|
||||
import re
|
||||
import logging
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.display.name import displayer as _nd
|
||||
from gramps.gen.display.place import displayer as _pd
|
||||
from gramps.gen.utils.db import get_death_or_fallback
|
||||
from gramps.gen.lib import (EventType, Date)
|
||||
from gramps.gen.plug import BasePluginManager
|
||||
from gramps.plugins.lib.libgedcom import make_gedcom_date, DATE_QUALITY
|
||||
from gramps.gen.plug.report import utils
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
|
||||
# define clear blank line for proper styling
|
||||
FULLCLEAR = Html("div", class_="fullclear", inline=True)
|
||||
# define all possible web page filename extensions
|
||||
_WEB_EXT = ['.html', '.htm', '.shtml', '.php', '.php3', '.cgi']
|
||||
# used to select secured web site or not
|
||||
HTTP = "http://"
|
||||
HTTPS = "https://"
|
||||
|
||||
GOOGLE_MAPS = 'https://maps.googleapis.com/maps/'
|
||||
# javascript code for marker path
|
||||
MARKER_PATH = """
|
||||
var marker_png = '%s'
|
||||
"""
|
||||
|
||||
# javascript code for Google's FamilyLinks...
|
||||
FAMILYLINKS = """
|
||||
var tracelife = %s
|
||||
|
||||
function initialize() {
|
||||
var myLatLng = new google.maps.LatLng(%s, %s);
|
||||
|
||||
var mapOptions = {
|
||||
scaleControl: true,
|
||||
panControl: true,
|
||||
backgroundColor: '#000000',
|
||||
zoom: %d,
|
||||
center: myLatLng,
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||
};
|
||||
var map = new google.maps.Map(document.getElementById("map_canvas"),
|
||||
mapOptions);
|
||||
|
||||
var flightPath = new google.maps.Polyline({
|
||||
path: tracelife,
|
||||
strokeColor: "#FF0000",
|
||||
strokeOpacity: 1.0,
|
||||
strokeWeight: 2
|
||||
});
|
||||
|
||||
flightPath.setMap(map);
|
||||
}"""
|
||||
|
||||
# javascript for Google's Drop Markers...
|
||||
DROPMASTERS = """
|
||||
var markers = [];
|
||||
var iterator = 0;
|
||||
|
||||
var tracelife = %s
|
||||
var map;
|
||||
var myLatLng = new google.maps.LatLng(%s, %s);
|
||||
|
||||
function initialize() {
|
||||
var mapOptions = {
|
||||
scaleControl: true,
|
||||
zoomControl: true,
|
||||
zoom: %d,
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP,
|
||||
center: myLatLng,
|
||||
};
|
||||
map = new google.maps.Map(document.getElementById("map_canvas"),
|
||||
mapOptions);
|
||||
};
|
||||
|
||||
function drop() {
|
||||
for (var i = 0; i < tracelife.length; i++) {
|
||||
setTimeout(function() {
|
||||
addMarker();
|
||||
}, i * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
function addMarker() {
|
||||
var location = tracelife[iterator];
|
||||
var myLatLng = new google.maps.LatLng(location[1], location[2]);
|
||||
|
||||
markers.push(new google.maps.Marker({
|
||||
position: myLatLng,
|
||||
map: map,
|
||||
draggable: true,
|
||||
title: location[0],
|
||||
animation: google.maps.Animation.DROP
|
||||
}));
|
||||
iterator++;
|
||||
}"""
|
||||
|
||||
# javascript for Google's Markers...
|
||||
MARKERS = """
|
||||
var tracelife = %s
|
||||
var map;
|
||||
var myLatLng = new google.maps.LatLng(%s, %s);
|
||||
|
||||
function initialize() {
|
||||
var mapOptions = {
|
||||
scaleControl: true,
|
||||
panControl: true,
|
||||
backgroundColor: '#000000',
|
||||
zoom: %d,
|
||||
center: myLatLng,
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||
};
|
||||
map = new google.maps.Map(document.getElementById("map_canvas"),
|
||||
mapOptions);
|
||||
addMarkers();
|
||||
}
|
||||
|
||||
function addMarkers() {
|
||||
var bounds = new google.maps.LatLngBounds();
|
||||
|
||||
for (var i = 0; i < tracelife.length; i++) {
|
||||
var location = tracelife[i];
|
||||
var myLatLng = new google.maps.LatLng(location[1], location[2]);
|
||||
|
||||
var marker = new google.maps.Marker({
|
||||
position: myLatLng,
|
||||
draggable: true,
|
||||
title: location[0],
|
||||
map: map,
|
||||
zIndex: location[3]
|
||||
});
|
||||
bounds.extend(myLatLng);
|
||||
if ( i > 1 ) { map.fitBounds(bounds); };
|
||||
}
|
||||
}"""
|
||||
|
||||
# javascript for OpenStreetMap's markers...
|
||||
OSM_MARKERS = """
|
||||
function initialize(){
|
||||
var map;
|
||||
var tracelife = %s;
|
||||
var iconStyle = new ol.style.Style({
|
||||
image: new ol.style.Icon(({
|
||||
opacity: 1.0,
|
||||
src: marker_png
|
||||
}))
|
||||
});
|
||||
var markerSource = new ol.source.Vector({
|
||||
});
|
||||
for (var i = 0; i < tracelife.length; i++) {
|
||||
var loc = tracelife[i];
|
||||
var iconFeature = new ol.Feature({
|
||||
geometry: new ol.geom.Point(ol.proj.transform([loc[0], loc[1]],
|
||||
'EPSG:4326', 'EPSG:3857')),
|
||||
name: loc[2],
|
||||
});
|
||||
iconFeature.setStyle(iconStyle);
|
||||
markerSource.addFeature(iconFeature);
|
||||
}
|
||||
markerLayer = new ol.layer.Vector({
|
||||
source: markerSource,
|
||||
style: iconStyle
|
||||
});
|
||||
var centerCoord = new ol.proj.transform([%s, %s], 'EPSG:4326', 'EPSG:3857');
|
||||
map= new ol.Map({
|
||||
target: 'map_canvas',
|
||||
layers: [new ol.layer.Tile({ source: new ol.source.OSM() }),
|
||||
markerLayer],
|
||||
view: new ol.View({ center: centerCoord, zoom: %d })
|
||||
});
|
||||
var element = document.getElementById('popup');
|
||||
var tooltip = new ol.Overlay({
|
||||
element: element,
|
||||
positioning: 'bottom-center',
|
||||
stopEvent: false
|
||||
});
|
||||
map.addOverlay(tooltip);
|
||||
var displayFeatureInfo = function(pixel) {
|
||||
var feature = map.forEachFeatureAtPixel(pixel, function(feature, layer) {
|
||||
return feature;
|
||||
});
|
||||
var info = document.getElementById('popup');
|
||||
if (feature) {
|
||||
var geometry = feature.getGeometry();
|
||||
var coord = geometry.getCoordinates();
|
||||
tooltip.setPosition(coord);
|
||||
$(element).siblings('.popover').css({ width: '250px' });
|
||||
$(element).siblings('.popover').css({ background: '#aaa' });
|
||||
$(info).popover({
|
||||
'placement': 'auto',
|
||||
'html': true,
|
||||
'content': feature.get('name')
|
||||
});
|
||||
$(info).popover('show');
|
||||
} else {
|
||||
// TODO : some warning with firebug here
|
||||
$(info).popover('destroy');
|
||||
$('.popover').remove();
|
||||
}
|
||||
};
|
||||
map.on('pointermove', function(evt) {
|
||||
if (evt.dragging) {
|
||||
return;
|
||||
}
|
||||
var pixel = map.getEventPixel(evt.originalEvent);
|
||||
displayFeatureInfo(pixel);
|
||||
});
|
||||
map.on('click', function(evt) {
|
||||
displayFeatureInfo(evt.pixel);
|
||||
});
|
||||
};
|
||||
"""
|
||||
|
||||
# variables for alphabet_navigation()
|
||||
_KEYPERSON, _KEYPLACE, _KEYEVENT, _ALPHAEVENT = 0, 1, 2, 3
|
||||
|
||||
COLLATE_LANG = glocale.collation
|
||||
|
||||
_NAME_STYLE_SHORT = 2
|
||||
_NAME_STYLE_DEFAULT = 1
|
||||
_NAME_STYLE_FIRST = 0
|
||||
_NAME_STYLE_SPECIAL = None
|
||||
|
||||
PLUGMAN = BasePluginManager.get_instance()
|
||||
CSS = PLUGMAN.process_plugin_data('WEBSTUFF')
|
||||
|
||||
#_NAME_COL = 3
|
||||
|
||||
_WRONGMEDIAPATH = []
|
||||
|
||||
_HTML_DBL_QUOTES = re.compile(r'([^"]*) " ([^"]*) " (.*)', re.VERBOSE)
|
||||
_HTML_SNG_QUOTES = re.compile(r"([^']*) ' ([^']*) ' (.*)", re.VERBOSE)
|
||||
|
||||
# Events that are usually a family event
|
||||
_EVENTMAP = set([EventType.MARRIAGE, EventType.MARR_ALT,
|
||||
EventType.MARR_SETTL, EventType.MARR_LIC,
|
||||
EventType.MARR_CONTR, EventType.MARR_BANNS,
|
||||
EventType.ENGAGEMENT, EventType.DIVORCE,
|
||||
EventType.DIV_FILING])
|
||||
|
||||
# Names for stylesheets
|
||||
_NARRATIVESCREEN = "narrative-screen.css"
|
||||
_NARRATIVEPRINT = "narrative-print.css"
|
||||
|
||||
def sort_people(dbase, handle_list, rlocale=glocale):
|
||||
"""
|
||||
will sort the database people by surname
|
||||
"""
|
||||
sname_sub = defaultdict(list)
|
||||
sortnames = {}
|
||||
|
||||
for person_handle in handle_list:
|
||||
person = dbase.get_person_from_handle(person_handle)
|
||||
primary_name = person.get_primary_name()
|
||||
|
||||
if primary_name.group_as:
|
||||
surname = primary_name.group_as.encode('utf-8')
|
||||
else:
|
||||
group_map = _nd.primary_surname(primary_name)
|
||||
surname = dbase.get_name_group_mapping(group_map)
|
||||
if isinstance(surname, bytes):
|
||||
surname = surname.decode('utf-8')
|
||||
|
||||
# Treat people who have no name with those whose name is just
|
||||
# 'whitespace'
|
||||
if surname is None or surname.isspace():
|
||||
surname = ''
|
||||
sortnames[person_handle] = _nd.sort_string(primary_name)
|
||||
sname_sub[surname].append(person_handle)
|
||||
|
||||
sorted_lists = []
|
||||
temp_list = sorted(sname_sub, key=rlocale.sort_key)
|
||||
|
||||
for name in temp_list:
|
||||
if isinstance(name, bytes):
|
||||
name = name.decode('utf-8')
|
||||
slist = sorted(((sortnames[x], x) for x in sname_sub[name]),
|
||||
key=lambda x: rlocale.sort_key(x[0]))
|
||||
entries = [x[1] for x in slist]
|
||||
sorted_lists.append((name, entries))
|
||||
|
||||
return sorted_lists
|
||||
|
||||
def sort_event_types(dbase, event_types, event_handle_list, rlocale):
|
||||
"""
|
||||
sort a list of event types and their associated event handles
|
||||
|
||||
@param: dbase -- report database
|
||||
@param: event_types -- a dict of event types
|
||||
@param: event_handle_list -- all event handles in this database
|
||||
"""
|
||||
event_dict = dict((evt_type, list()) for evt_type in event_types)
|
||||
|
||||
for event_handle in event_handle_list:
|
||||
|
||||
event = dbase.get_event_from_handle(event_handle)
|
||||
event_type = rlocale.translation.sgettext(event.get_type().xml_str())
|
||||
|
||||
# add (gramps_id, date, handle) from this event
|
||||
if event_type in event_dict:
|
||||
sort_value = event.get_date_object().get_sort_value()
|
||||
event_dict[event_type].append((sort_value, event_handle))
|
||||
|
||||
for tup_list in event_dict.values():
|
||||
tup_list.sort()
|
||||
|
||||
# return a list of sorted tuples, one per event
|
||||
retval = [(event_type, event_list) for (event_type,
|
||||
event_list) in event_dict.items()]
|
||||
retval.sort(key=lambda item: str(item[0]))
|
||||
|
||||
return retval
|
||||
|
||||
# Modified _get_regular_surname from WebCal.py to get prefix, first name,
|
||||
# and suffix
|
||||
def _get_short_name(gender, name):
|
||||
""" Will get suffix for all people passed through it """
|
||||
|
||||
short_name = name.get_first_name()
|
||||
suffix = name.get_suffix()
|
||||
if suffix:
|
||||
short_name = short_name + ", " + suffix
|
||||
return short_name
|
||||
|
||||
def __get_person_keyname(dbase, handle):
|
||||
""" .... """
|
||||
|
||||
person = dbase.get_person_from_handle(handle)
|
||||
return _nd.sort_string(person.get_primary_name())
|
||||
|
||||
def __get_place_keyname(dbase, handle):
|
||||
""" ... """
|
||||
|
||||
return utils.place_name(dbase, handle)
|
||||
|
||||
# See : http://www.gramps-project.org/bugs/view.php?id = 4423
|
||||
|
||||
# Contraction data taken from CLDR 22.1. Only the default variant is considered.
|
||||
# The languages included below are, by no means, all the langauges that have
|
||||
# contractions - just a sample of langauges that have been supported
|
||||
|
||||
# At the time of writing (Feb 2013), the following langauges have greater that
|
||||
# 50% coverage of translation of Gramps: bg Bulgarian, ca Catalan, cs Czech, da
|
||||
# Danish, de German, el Greek, en_GB, es Spanish, fi Finish, fr French, he
|
||||
# Hebrew, hr Croation, hu Hungarian, it Italian, ja Japanese, lt Lithuanian, nb
|
||||
# Noregian Bokmål, nn Norwegian Nynorsk, nl Dutch, pl Polish, pt_BR Portuguese
|
||||
# (Brazil), pt_P Portugeuse (Portugal), ru Russian, sk Slovak, sl Slovenian, sv
|
||||
# Swedish, vi Vietnamese, zh_CN Chinese.
|
||||
|
||||
# Key is the language (or language and country), Value is a list of
|
||||
# contractions. Each contraction consists of a tuple. First element of the
|
||||
# tuple is the list of characters, second element is the string to use as the
|
||||
# index entry.
|
||||
|
||||
# The DUCET contractions (e.g. LATIN CAPIAL LETTER L, MIDDLE DOT) are ignored,
|
||||
# as are the supresscontractions in some locales.
|
||||
|
||||
CONTRACTIONS_DICT = {
|
||||
# bg Bulgarian validSubLocales="bg_BG" no contractions
|
||||
# ca Catalan validSubLocales="ca_AD ca_ES"
|
||||
"ca" : [(("l·", "L·"), "L")],
|
||||
# Czech, validSubLocales="cs_CZ" Czech_Czech Republic
|
||||
"cs" : [(("ch", "cH", "Ch", "CH"), "CH")],
|
||||
# Danish validSubLocales="da_DK" Danish_Denmark
|
||||
"da" : [(("aa", "Aa", "AA"), "Å")],
|
||||
# de German validSubLocales="de_AT de_BE de_CH de_DE de_LI de_LU" no
|
||||
# contractions in standard collation.
|
||||
# el Greek validSubLocales="el_CY el_GR" no contractions.
|
||||
# es Spanish validSubLocales="es_419 es_AR es_BO es_CL es_CO es_CR es_CU
|
||||
# es_DO es_EA es_EC es_ES es_GQ es_GT es_HN es_IC es_MX es_NI es_PA es_PE
|
||||
# es_PH es_PR es_PY es_SV es_US es_UY es_VE" no contractions in standard
|
||||
# collation.
|
||||
# fi Finish validSubLocales="fi_FI" no contractions in default (phonebook)
|
||||
# collation.
|
||||
# fr French no collation data.
|
||||
# he Hebrew validSubLocales="he_IL" no contractions
|
||||
# hr Croation validSubLocales="hr_BA hr_HR"
|
||||
"hr" : [(("dž", "Dž"), "dž"),
|
||||
(("lj", "Lj", 'LJ'), "LJ"),
|
||||
(("Nj", "NJ", "nj"), "NJ")],
|
||||
# Hungarian hu_HU for two and three character contractions.
|
||||
"hu" : [(("cs", "Cs", "CS"), "CS"),
|
||||
(("dzs", "Dzs", "DZS"), "DZS"), # order is important
|
||||
(("dz", "Dz", "DZ"), "DZ"),
|
||||
(("gy", "Gy", "GY"), "GY"),
|
||||
(("ly", "Ly", "LY"), "LY"),
|
||||
(("ny", "Ny", "NY"), "NY"),
|
||||
(("sz", "Sz", "SZ"), "SZ"),
|
||||
(("ty", "Ty", "TY"), "TY"),
|
||||
(("zs", "Zs", "ZS"), "ZS")
|
||||
],
|
||||
# it Italian no collation data.
|
||||
# ja Japanese unable to process the data as it is too complex.
|
||||
# lt Lithuanian no contractions.
|
||||
# Norwegian Bokmål
|
||||
"nb" : [(("aa", "Aa", "AA"), "Å")],
|
||||
# nn Norwegian Nynorsk validSubLocales="nn_NO"
|
||||
"nn" : [(("aa", "Aa", "AA"), "Å")],
|
||||
# nl Dutch no collation data.
|
||||
# pl Polish validSubLocales="pl_PL" no contractions
|
||||
# pt Portuguese no collation data.
|
||||
# ru Russian validSubLocales="ru_BY ru_KG ru_KZ ru_MD ru_RU ru_UA" no
|
||||
# contractions
|
||||
# Slovak, validSubLocales="sk_SK" Slovak_Slovakia
|
||||
# having DZ in Slovak as a contraction was rejected in
|
||||
# http://unicode.org/cldr/trac/ticket/2968
|
||||
"sk" : [(("ch", "cH", "Ch", "CH"), "Ch")],
|
||||
# sl Slovenian validSubLocales="sl_SI" no contractions
|
||||
# sv Swedish validSubLocales="sv_AX sv_FI sv_SE" default collation is
|
||||
# "reformed" no contractions.
|
||||
# vi Vietnamese validSubLocales="vi_VN" no contractions.
|
||||
# zh Chinese validSubLocales="zh_Hans zh_Hans_CN zh_Hans_SG" no contractions
|
||||
# in Latin characters the others are too complex.
|
||||
}
|
||||
|
||||
# The comment below from the glibc locale sv_SE in
|
||||
# localedata/locales/sv_SE :
|
||||
#
|
||||
# % The letter w is normally not present in the Swedish alphabet. It
|
||||
# % exists in some names in Swedish and foreign words, but is accounted
|
||||
# % for as a variant of 'v'. Words and names with 'w' are in Swedish
|
||||
# % ordered alphabetically among the words and names with 'v'. If two
|
||||
# % words or names are only to be distinguished by 'v' or % 'w', 'v' is
|
||||
# % placed before 'w'.
|
||||
#
|
||||
# See : http://www.gramps-project.org/bugs/view.php?id = 2933
|
||||
#
|
||||
|
||||
# HOWEVER: the characters V and W in Swedish are not considered as a special
|
||||
# case for several reasons. (1) The default collation for Swedish (called the
|
||||
# 'reformed' collation type) regards the difference between 'v' and 'w' as a
|
||||
# primary difference. (2) 'v' and 'w' in the 'standard' (non-default) collation
|
||||
# type are not a contraction, just a case where the difference is secondary
|
||||
# rather than primary. (3) There are plenty of other languages where a
|
||||
# difference that is primary in other languages is secondary, and those are not
|
||||
# specially handled.
|
||||
|
||||
def first_letter(string, rlocale=glocale):
|
||||
"""
|
||||
Receives a string and returns the first letter
|
||||
"""
|
||||
if string is None or len(string) < 1:
|
||||
return ' '
|
||||
|
||||
norm_unicode = normalize('NFKC', str(string))
|
||||
contractions = CONTRACTIONS_DICT.get(COLLATE_LANG)
|
||||
if contractions is None:
|
||||
contractions = CONTRACTIONS_DICT.get(COLLATE_LANG.split("_")[0])
|
||||
|
||||
if contractions is not None:
|
||||
for contraction in contractions:
|
||||
count = len(contraction[0][0])
|
||||
if (len(norm_unicode) >= count and
|
||||
norm_unicode[:count] in contraction[0]):
|
||||
return contraction[1]
|
||||
|
||||
# no special case
|
||||
return norm_unicode[0].upper()
|
||||
|
||||
try:
|
||||
import PyICU # pylint : disable=wrong-import-position
|
||||
PRIM_COLL = PyICU.Collator.createInstance(PyICU.Locale(COLLATE_LANG))
|
||||
PRIM_COLL.setStrength(PRIM_COLL.PRIMARY)
|
||||
|
||||
def primary_difference(prev_key, new_key, rlocale=glocale):
|
||||
"""
|
||||
Try to use the PyICU collation.
|
||||
"""
|
||||
|
||||
return PRIM_COLL.compare(prev_key, new_key) != 0
|
||||
|
||||
except:
|
||||
def primary_difference(prev_key, new_key, rlocale=glocale):
|
||||
"""
|
||||
The PyICU collation is not available.
|
||||
|
||||
Returns true if there is a primary difference between the two parameters
|
||||
See http://www.gramps-project.org/bugs/view.php?id=2933#c9317 if
|
||||
letter[i]+'a' < letter[i+1]+'b' and letter[i+1]+'a' < letter[i]+'b' is
|
||||
true then the letters should be grouped together
|
||||
|
||||
The test characters here must not be any that are used in contractions.
|
||||
"""
|
||||
|
||||
return rlocale.sort_key(prev_key + "e") >= \
|
||||
rlocale.sort_key(new_key + "f") or \
|
||||
rlocale.sort_key(new_key + "e") >= \
|
||||
rlocale.sort_key(prev_key + "f")
|
||||
|
||||
def get_first_letters(dbase, handle_list, key, rlocale=glocale):
|
||||
"""
|
||||
get the first letters of the handle_list
|
||||
|
||||
@param: handle_list -- One of a handle list for either person or
|
||||
place handles or an evt types list
|
||||
@param: key -- Either a person, place, or event type
|
||||
|
||||
The first letter (or letters if there is a contraction) are extracted from
|
||||
all the objects in the handle list. There may be duplicates, and there may
|
||||
be letters where there is only a secondary or tertiary difference, not a
|
||||
primary difference. The list is sorted in collation order. For each group
|
||||
with secondary or tertiary differences, the first in collation sequence is
|
||||
retained. For example, assume the default collation sequence (DUCET) and
|
||||
names Ånström and Apple. These will sort in the order shown. Å and A have a
|
||||
secondary difference. If the first letter from these names was chosen then
|
||||
the inex entry would be Å. This is not desirable. Instead, the initial
|
||||
letters are extracted (Å and A). These are sorted, which gives A and Å. Then
|
||||
the first of these is used for the index entry.
|
||||
"""
|
||||
index_list = []
|
||||
|
||||
for handle in handle_list:
|
||||
if key == _KEYPERSON:
|
||||
keyname = __get_person_keyname(dbase, handle)
|
||||
|
||||
elif key == _KEYPLACE:
|
||||
keyname = __get_place_keyname(dbase, handle)
|
||||
|
||||
else:
|
||||
if rlocale != glocale:
|
||||
keyname = rlocale.translation.sgettext(handle)
|
||||
else:
|
||||
keyname = handle
|
||||
ltr = first_letter(keyname)
|
||||
|
||||
index_list.append(ltr)
|
||||
|
||||
# Now remove letters where there is not a primary difference
|
||||
index_list.sort(key=rlocale.sort_key)
|
||||
first = True
|
||||
prev_index = None
|
||||
for key in index_list[:]: #iterate over a slice copy of the list
|
||||
if first or primary_difference(prev_index, key, rlocale):
|
||||
first = False
|
||||
prev_index = key
|
||||
else:
|
||||
index_list.remove(key)
|
||||
|
||||
# return menu set letters for alphabet_navigation
|
||||
return index_list
|
||||
|
||||
def get_index_letter(letter, index_list, rlocale=glocale):
|
||||
"""
|
||||
This finds the letter in the index_list that has no primary difference from
|
||||
the letter provided. See the discussion in get_first_letters above.
|
||||
Continuing the example, if letter is Å and index_list is A, then this would
|
||||
return A.
|
||||
"""
|
||||
for index in index_list:
|
||||
if not primary_difference(letter, index, rlocale):
|
||||
return index
|
||||
|
||||
LOG.warning("Initial letter '%s' not found in alphabetic navigation list",
|
||||
letter)
|
||||
LOG.debug("filtered sorted index list %s", index_list)
|
||||
return letter
|
||||
|
||||
def alphabet_navigation(index_list, rlocale=glocale):
|
||||
"""
|
||||
Will create the alphabet navigation bar for classes IndividualListPage,
|
||||
SurnameListPage, PlaceListPage, and EventList
|
||||
|
||||
@param: index_list -- a dictionary of either letters or words
|
||||
"""
|
||||
sorted_set = defaultdict(int)
|
||||
|
||||
for menu_item in index_list:
|
||||
sorted_set[menu_item] += 1
|
||||
|
||||
# remove the number of each occurance of each letter
|
||||
sorted_alpha_index = sorted(sorted_set, key=rlocale.sort_key)
|
||||
|
||||
# if no letters, return None to its callers
|
||||
if not sorted_alpha_index:
|
||||
return None
|
||||
|
||||
num_ltrs = len(sorted_alpha_index)
|
||||
num_of_cols = 26
|
||||
num_of_rows = ((num_ltrs // num_of_cols) + 1)
|
||||
|
||||
# begin alphabet navigation division
|
||||
with Html("div", id="alphanav") as alphabetnavigation:
|
||||
|
||||
index = 0
|
||||
for row in range(num_of_rows):
|
||||
unordered = Html("ul")
|
||||
|
||||
cols = 0
|
||||
while cols <= num_of_cols and index < num_ltrs:
|
||||
menu_item = sorted_alpha_index[index]
|
||||
if menu_item == ' ':
|
||||
menu_item = ' '
|
||||
# adding title to hyperlink menu for screen readers and
|
||||
# braille writers
|
||||
title_txt = "Alphabet Menu: %s" % menu_item
|
||||
title_str = rlocale.translation.sgettext(title_txt)
|
||||
hyper = Html("a", menu_item, title=title_str,
|
||||
href="#%s" % menu_item)
|
||||
unordered.extend(Html("li", hyper, inline=True))
|
||||
|
||||
index += 1
|
||||
cols += 1
|
||||
num_of_rows -= 1
|
||||
|
||||
alphabetnavigation += unordered
|
||||
|
||||
return alphabetnavigation
|
||||
|
||||
def _has_webpage_extension(url):
|
||||
"""
|
||||
determine if a filename has an extension or not...
|
||||
|
||||
@param: url -- filename to be checked
|
||||
"""
|
||||
return any(url.endswith(ext) for ext in _WEB_EXT)
|
||||
|
||||
def add_birthdate(dbase, ppl_handle_list, rlocale):
|
||||
"""
|
||||
This will sort a list of child handles in birth order
|
||||
For each entry in the list, we'll have :
|
||||
birth date
|
||||
The transtated birth date for the configured locale
|
||||
The transtated death date for the configured locale
|
||||
The handle for the child
|
||||
|
||||
@param: dbase -- The database to use
|
||||
@param: ppl_handle_list -- the handle for the people
|
||||
@param: rlocale -- the locale for date translation
|
||||
"""
|
||||
sortable_individuals = []
|
||||
for person_handle in ppl_handle_list:
|
||||
birth_date = 0 # dummy value in case none is found
|
||||
person = dbase.get_person_from_handle(person_handle)
|
||||
if person:
|
||||
birth_ref = person.get_birth_ref()
|
||||
birth1 = ""
|
||||
if birth_ref:
|
||||
birth = dbase.get_event_from_handle(birth_ref.ref)
|
||||
if birth:
|
||||
birth1 = rlocale.get_date(birth.get_date_object())
|
||||
birth_date = birth.get_date_object().get_sort_value()
|
||||
death_event = get_death_or_fallback(dbase, person)
|
||||
if death_event:
|
||||
death = rlocale.get_date(death_event.get_date_object())
|
||||
else:
|
||||
death = ""
|
||||
sortable_individuals.append((birth_date, birth1, death, person_handle))
|
||||
|
||||
# return a list of handles with the individual's birthdate attached
|
||||
return sortable_individuals
|
||||
|
||||
def _find_birth_date(dbase, individual):
|
||||
"""
|
||||
will look for a birth date within the person's events
|
||||
|
||||
@param: dbase -- The database to use
|
||||
@param: individual -- The individual for who we want to find the birth date
|
||||
"""
|
||||
date_out = None
|
||||
birth_ref = individual.get_birth_ref()
|
||||
if birth_ref:
|
||||
birth = dbase.get_event_from_handle(birth_ref.ref)
|
||||
if birth:
|
||||
date_out = birth.get_date_object()
|
||||
date_out.fallback = False
|
||||
else:
|
||||
person_evt_ref_list = individual.get_primary_event_ref_list()
|
||||
if person_evt_ref_list:
|
||||
for evt_ref in person_evt_ref_list:
|
||||
event = dbase.get_event_from_handle(evt_ref.ref)
|
||||
if event:
|
||||
if event.get_type().is_birth_fallback():
|
||||
date_out = event.get_date_object()
|
||||
date_out.fallback = True
|
||||
LOG.debug("setting fallback to true for '%s'", event)
|
||||
break
|
||||
return date_out
|
||||
|
||||
def _find_death_date(dbase, individual):
|
||||
"""
|
||||
will look for a death date within a person's events
|
||||
|
||||
@param: dbase -- The database to use
|
||||
@param: individual -- The individual for who we want to find the death date
|
||||
"""
|
||||
date_out = None
|
||||
death_ref = individual.get_death_ref()
|
||||
if death_ref:
|
||||
death = dbase.get_event_from_handle(death_ref.ref)
|
||||
if death:
|
||||
date_out = death.get_date_object()
|
||||
date_out.fallback = False
|
||||
else:
|
||||
person_evt_ref_list = individual.get_primary_event_ref_list()
|
||||
if person_evt_ref_list:
|
||||
for evt_ref in person_evt_ref_list:
|
||||
event = dbase.get_event_from_handle(evt_ref.ref)
|
||||
if event:
|
||||
if event.get_type().is_death_fallback():
|
||||
date_out = event.get_date_object()
|
||||
date_out.fallback = True
|
||||
LOG.debug("setting fallback to true for '%s'", event)
|
||||
break
|
||||
return date_out
|
||||
|
||||
def build_event_data_by_individuals(dbase, ppl_handle_list):
|
||||
"""
|
||||
creates a list of event handles and event types for this database
|
||||
|
||||
@param: dbase -- The database to use
|
||||
@param: ppl_handle_list -- the handle for the people
|
||||
"""
|
||||
event_handle_list = []
|
||||
event_types = []
|
||||
|
||||
for person_handle in ppl_handle_list:
|
||||
person = dbase.get_person_from_handle(person_handle)
|
||||
if person:
|
||||
|
||||
evt_ref_list = person.get_event_ref_list()
|
||||
if evt_ref_list:
|
||||
for evt_ref in evt_ref_list:
|
||||
event = dbase.get_event_from_handle(evt_ref.ref)
|
||||
if event:
|
||||
|
||||
event_types.append(str(event.get_type()))
|
||||
event_handle_list.append(evt_ref.ref)
|
||||
|
||||
person_family_handle_list = person.get_family_handle_list()
|
||||
if person_family_handle_list:
|
||||
for family_handle in person_family_handle_list:
|
||||
family = dbase.get_family_from_handle(family_handle)
|
||||
if family:
|
||||
|
||||
family_evt_ref_list = family.get_event_ref_list()
|
||||
if family_evt_ref_list:
|
||||
for evt_ref in family_evt_ref_list:
|
||||
event = dbase.get_event_from_handle(evt_ref.ref)
|
||||
if event:
|
||||
event_types.append(str(event.type))
|
||||
event_handle_list.append(evt_ref.ref)
|
||||
|
||||
# return event_handle_list and event types to its caller
|
||||
return event_handle_list, event_types
|
||||
|
||||
def name_to_md5(text):
|
||||
"""This creates an MD5 hex string to be used as filename."""
|
||||
|
||||
return md5(text.encode('utf-8')).hexdigest()
|
||||
|
||||
def get_gendex_data(database, event_ref):
|
||||
"""
|
||||
Given an event, return the date and place a strings
|
||||
|
||||
@param: database -- The database
|
||||
@param: event_ref -- The event reference
|
||||
"""
|
||||
doe = "" # date of event
|
||||
poe = "" # place of event
|
||||
if event_ref and event_ref.ref:
|
||||
event = database.get_event_from_handle(event_ref.ref)
|
||||
if event:
|
||||
date = event.get_date_object()
|
||||
doe = format_date(date)
|
||||
if event.get_place_handle():
|
||||
place_handle = event.get_place_handle()
|
||||
if place_handle:
|
||||
place = database.get_place_from_handle(place_handle)
|
||||
if place:
|
||||
poe = _pd.display(database, place, date)
|
||||
return doe, poe
|
||||
|
||||
def format_date(date):
|
||||
"""
|
||||
Format the date
|
||||
"""
|
||||
start = date.get_start_date()
|
||||
if start != Date.EMPTY:
|
||||
cal = date.get_calendar()
|
||||
mod = date.get_modifier()
|
||||
quality = date.get_quality()
|
||||
if quality in DATE_QUALITY:
|
||||
qual_text = DATE_QUALITY[quality] + " "
|
||||
else:
|
||||
qual_text = ""
|
||||
if mod == Date.MOD_SPAN:
|
||||
val = "%sFROM %s TO %s" % (
|
||||
qual_text,
|
||||
make_gedcom_date(start, cal, mod, None),
|
||||
make_gedcom_date(date.get_stop_date(), cal, mod, None))
|
||||
elif mod == Date.MOD_RANGE:
|
||||
val = "%sBET %s AND %s" % (
|
||||
qual_text,
|
||||
make_gedcom_date(start, cal, mod, None),
|
||||
make_gedcom_date(date.get_stop_date(), cal, mod, None))
|
||||
else:
|
||||
val = make_gedcom_date(start, cal, mod, quality)
|
||||
return val
|
||||
return ""
|
||||
|
||||
# This command then defines the 'html_escape' option for escaping
|
||||
# special characters for presentation in HTML based on the above list.
|
||||
def html_escape(text):
|
||||
"""Convert the text and replace some characters with a &# variant."""
|
||||
|
||||
# First single characters, no quotes
|
||||
text = escape(text)
|
||||
|
||||
# Deal with double quotes.
|
||||
match = _HTML_DBL_QUOTES.match(text)
|
||||
while match:
|
||||
text = "%s" "“" "%s" "”" "%s" % match.groups()
|
||||
match = _HTML_DBL_QUOTES.match(text)
|
||||
# Replace remaining double quotes.
|
||||
text = text.replace('"', '"')
|
||||
|
||||
# Deal with single quotes.
|
||||
text = text.replace("'s ", '’s ')
|
||||
match = _HTML_SNG_QUOTES.match(text)
|
||||
while match:
|
||||
text = "%s" "‘" "%s" "’" "%s" % match.groups()
|
||||
match = _HTML_SNG_QUOTES.match(text)
|
||||
# Replace remaining single quotes.
|
||||
text = text.replace("'", ''')
|
||||
|
||||
return text
|
||||
|
||||
139
gramps/plugins/webreport/contact.py
Normal file
139
gramps/plugins/webreport/contact.py
Normal file
@ -0,0 +1,139 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
ContactPage
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.utils.config import get_researcher
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import FULLCLEAR
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
class ContactPage(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information about the 'Researcher'
|
||||
"""
|
||||
def __init__(self, report, title):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for this report
|
||||
@param: title -- Is the title of the web page
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
|
||||
output_file, sio = self.report.create_file("contact")
|
||||
contactpage, head, body = self.write_header(self._('Contact'))
|
||||
|
||||
# begin contact division
|
||||
with Html("div", class_="content", id="Contact") as section:
|
||||
body += section
|
||||
|
||||
# begin summaryarea division
|
||||
with Html("div", id='summaryarea') as summaryarea:
|
||||
section += summaryarea
|
||||
|
||||
contactimg = self.add_image('contactimg', 200)
|
||||
if contactimg is not None:
|
||||
summaryarea += contactimg
|
||||
|
||||
# get researcher information
|
||||
res = get_researcher()
|
||||
|
||||
with Html("div", id='researcher') as researcher:
|
||||
summaryarea += researcher
|
||||
|
||||
if res.name:
|
||||
res.name = res.name.replace(',,,', '')
|
||||
researcher += Html("h3", res.name, inline=True)
|
||||
if res.addr:
|
||||
researcher += Html("span", res.addr,
|
||||
id='streetaddress', inline=True)
|
||||
if res.locality:
|
||||
researcher += Html("span", res.locality,
|
||||
id="locality", inline=True)
|
||||
text = "".join([res.city, res.state, res.postal])
|
||||
if text:
|
||||
city = Html("span", res.city, id='city', inline=True)
|
||||
state = Html("span", res.state, id='state', inline=True)
|
||||
postal = Html("span", res.postal, id='postalcode',
|
||||
inline=True)
|
||||
researcher += (city, state, postal)
|
||||
if res.country:
|
||||
researcher += Html("span", res.country,
|
||||
id='country', inline=True)
|
||||
if res.email:
|
||||
researcher += Html("span", id='email') + (
|
||||
Html("a", res.email,
|
||||
href='mailto:%s' % res.email, inline=True)
|
||||
)
|
||||
|
||||
# add clear line for proper styling
|
||||
summaryarea += FULLCLEAR
|
||||
|
||||
note_id = report.options['contactnote']
|
||||
if note_id:
|
||||
note = self.r_db.get_note_from_gramps_id(note_id)
|
||||
note_text = self.get_note_format(note, False)
|
||||
|
||||
# attach note
|
||||
summaryarea += note_text
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(None)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for porcessing
|
||||
# and close the file
|
||||
self.xhtml_writer(contactpage, output_file, sio, 0)
|
||||
195
gramps/plugins/webreport/download.py
Normal file
195
gramps/plugins/webreport/download.py
Normal file
@ -0,0 +1,195 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
DownloadPage
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
import os
|
||||
import datetime
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import (FULLCLEAR, html_escape)
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
class DownloadPage(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information about the Download page
|
||||
"""
|
||||
def __init__(self, report, title):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for this report
|
||||
@param: title -- Is the title of the web page
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
|
||||
# do NOT include a Download Page
|
||||
if not self.report.inc_download:
|
||||
return
|
||||
|
||||
# menu options for class
|
||||
# download and description #1
|
||||
|
||||
dlfname1 = self.report.dl_fname1
|
||||
dldescr1 = self.report.dl_descr1
|
||||
|
||||
# download and description #2
|
||||
dlfname2 = self.report.dl_fname2
|
||||
dldescr2 = self.report.dl_descr2
|
||||
|
||||
# if no filenames at all, return???
|
||||
if dlfname1 or dlfname2:
|
||||
|
||||
output_file, sio = self.report.create_file("download")
|
||||
downloadpage, head, body = self.write_header(self._('Download'))
|
||||
|
||||
# begin download page and table
|
||||
with Html("div", class_="content", id="Download") as download:
|
||||
body += download
|
||||
|
||||
msg = self._("This page is for the user/ creator "
|
||||
"of this Family Tree/ Narrative website "
|
||||
"to share a couple of files with you "
|
||||
"regarding their family. If there are "
|
||||
"any files listed "
|
||||
"below, clicking on them will allow you "
|
||||
"to download them. The "
|
||||
"download page and files have the same "
|
||||
"copyright as the remainder "
|
||||
"of these web pages.")
|
||||
download += Html("p", msg, id="description")
|
||||
|
||||
# begin download table and table head
|
||||
with Html("table", class_="infolist download") as table:
|
||||
download += table
|
||||
|
||||
thead = Html("thead")
|
||||
table += thead
|
||||
|
||||
trow = Html("tr")
|
||||
thead += trow
|
||||
|
||||
trow.extend(
|
||||
Html("th", label, class_="Column" + colclass,
|
||||
inline=True)
|
||||
for (label, colclass) in [
|
||||
(self._("File Name"), "Filename"),
|
||||
(self._("Description"), "Description"),
|
||||
(self._("Last Modified"), "Modified")])
|
||||
# table body
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
# if dlfname1 is not None, show it???
|
||||
if dlfname1:
|
||||
|
||||
trow = Html("tr", id='Row01')
|
||||
tbody += trow
|
||||
|
||||
fname = os.path.basename(dlfname1)
|
||||
# TODO dlfname1 is filename, convert disk path to URL
|
||||
tcell = Html("td", class_="ColumnFilename") + (
|
||||
Html("a", fname, href=dlfname1,
|
||||
title=html_escape(dldescr1))
|
||||
)
|
||||
trow += tcell
|
||||
|
||||
dldescr1 = dldescr1 or " "
|
||||
trow += Html("td", dldescr1,
|
||||
class_="ColumnDescription", inline=True)
|
||||
|
||||
tcell = Html("td", class_="ColumnModified", inline=True)
|
||||
trow += tcell
|
||||
if os.path.exists(dlfname1):
|
||||
modified = os.stat(dlfname1).st_mtime
|
||||
last_mod = datetime.datetime.fromtimestamp(modified)
|
||||
tcell += last_mod
|
||||
else:
|
||||
tcell += " "
|
||||
|
||||
# if download filename #2, show it???
|
||||
if dlfname2:
|
||||
|
||||
# begin row #2
|
||||
trow = Html("tr", id='Row02')
|
||||
tbody += trow
|
||||
|
||||
fname = os.path.basename(dlfname2)
|
||||
tcell = Html("td", class_="ColumnFilename") + (
|
||||
Html("a", fname, href=dlfname2,
|
||||
title=html_escape(dldescr2))
|
||||
)
|
||||
trow += tcell
|
||||
|
||||
dldescr2 = dldescr2 or " "
|
||||
trow += Html("td", dldescr2,
|
||||
class_="ColumnDescription", inline=True)
|
||||
|
||||
tcell = Html("td", id='Col04',
|
||||
class_="ColumnModified", inline=True)
|
||||
trow += tcell
|
||||
if os.path.exists(dlfname2):
|
||||
modified = os.stat(dlfname2).st_mtime
|
||||
last_mod = datetime.datetime.fromtimestamp(modified)
|
||||
tcell += last_mod
|
||||
else:
|
||||
tcell += " "
|
||||
|
||||
# clear line for proper styling
|
||||
# create footer section
|
||||
footer = self.write_footer(None)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(downloadpage, output_file, sio, 0)
|
||||
448
gramps/plugins/webreport/event.py
Normal file
448
gramps/plugins/webreport/event.py
Normal file
@ -0,0 +1,448 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
EventPage - Event index page and individual Event pages
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from collections import defaultdict
|
||||
from operator import itemgetter
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.lib import (Date, Event)
|
||||
from gramps.gen.plug.report import Bibliography
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import (get_first_letters, _ALPHAEVENT,
|
||||
_EVENTMAP, alphabet_navigation,
|
||||
FULLCLEAR, sort_event_types,
|
||||
primary_difference,
|
||||
get_index_letter)
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
#################################################
|
||||
#
|
||||
# creates the Event List Page and EventPages
|
||||
#
|
||||
#################################################
|
||||
class EventPages(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information about the 'Person'
|
||||
database objects. It displays this information under the 'Events'
|
||||
tab. It is told by the 'add_instances' call which 'Person's to display,
|
||||
and remembers the list of persons. A single call to 'display_pages'
|
||||
displays both the Event List (Index) page and all the Event
|
||||
pages.
|
||||
|
||||
The base class 'BasePage' is initialised once for each page that is
|
||||
displayed.
|
||||
"""
|
||||
def __init__(self, report):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
"""
|
||||
BasePage.__init__(self, report, title="")
|
||||
self.event_handle_list = []
|
||||
self.event_types = []
|
||||
self.event_dict = defaultdict(set)
|
||||
|
||||
def display_pages(self, title):
|
||||
"""
|
||||
Generate and output the pages under the Event tab, namely the event
|
||||
index and the individual event pages.
|
||||
|
||||
@param: title -- Is the title of the web page
|
||||
"""
|
||||
LOG.debug("obj_dict[Event]")
|
||||
for item in self.report.obj_dict[Event].items():
|
||||
LOG.debug(" %s", str(item))
|
||||
event_handle_list = self.report.obj_dict[Event].keys()
|
||||
event_types = []
|
||||
for event_handle in event_handle_list:
|
||||
event = self.r_db.get_event_from_handle(event_handle)
|
||||
event_types.append(self._(event.get_type().xml_str()))
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating event pages"),
|
||||
len(event_handle_list) + 1
|
||||
) as step:
|
||||
self.eventlistpage(self.report, title, event_types,
|
||||
event_handle_list)
|
||||
|
||||
for event_handle in event_handle_list:
|
||||
step()
|
||||
self.eventpage(self.report, title, event_handle)
|
||||
|
||||
|
||||
def eventlistpage(self, report, title, event_types, event_handle_list):
|
||||
"""
|
||||
Will create the event list page
|
||||
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: event_types -- A list of the type in the events database
|
||||
@param: event_handle_list -- A list of event handles
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
ldatec = 0
|
||||
prev_letter = " "
|
||||
|
||||
output_file, sio = self.report.create_file("events")
|
||||
eventslistpage, head, body = self.write_header(self._("Events"))
|
||||
|
||||
# begin events list division
|
||||
with Html("div", class_="content", id="EventList") as eventlist:
|
||||
body += eventlist
|
||||
|
||||
msg = self._("This page contains an index of all the events in the "
|
||||
"database, sorted by their type and date (if one is "
|
||||
"present). Clicking on an event’s Gramps ID "
|
||||
"will open a page for that event.")
|
||||
eventlist += Html("p", msg, id="description")
|
||||
|
||||
# get alphabet navigation...
|
||||
index_list = get_first_letters(self.r_db, event_types,
|
||||
_ALPHAEVENT)
|
||||
alpha_nav = alphabet_navigation(index_list, self.rlocale)
|
||||
if alpha_nav:
|
||||
eventlist += alpha_nav
|
||||
|
||||
# begin alphabet event table
|
||||
with Html("table",
|
||||
class_="infolist primobjlist alphaevent") as table:
|
||||
eventlist += table
|
||||
|
||||
thead = Html("thead")
|
||||
table += thead
|
||||
|
||||
trow = Html("tr")
|
||||
thead += trow
|
||||
|
||||
trow.extend(
|
||||
Html("th", label, class_=colclass, inline=True)
|
||||
for (label, colclass) in [(self._("Letter"),
|
||||
"ColumnRowLabel"),
|
||||
(self._("Type"), "ColumnType"),
|
||||
(self._("Date"), "ColumnDate"),
|
||||
(self._("Gramps ID"),
|
||||
"ColumnGRAMPSID"),
|
||||
(self._("Person"), "ColumnPerson")
|
||||
]
|
||||
)
|
||||
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
# separate events by their type and then thier event handles
|
||||
for (evt_type,
|
||||
data_list) in sort_event_types(self.r_db,
|
||||
event_types,
|
||||
event_handle_list,
|
||||
self.rlocale):
|
||||
first = True
|
||||
_event_displayed = []
|
||||
|
||||
# sort datalist by date of event and by event handle...
|
||||
data_list = sorted(data_list, key=itemgetter(0, 1))
|
||||
first_event = True
|
||||
|
||||
for (sort_value, event_handle) in data_list:
|
||||
event = self.r_db.get_event_from_handle(event_handle)
|
||||
_type = event.get_type()
|
||||
gid = event.get_gramps_id()
|
||||
if event.get_change_time() > ldatec:
|
||||
ldatec = event.get_change_time()
|
||||
|
||||
# check to see if we have listed this gramps_id yet?
|
||||
if gid not in _event_displayed:
|
||||
|
||||
# family event
|
||||
if int(_type) in _EVENTMAP:
|
||||
handle_list = set(
|
||||
self.r_db.find_backlink_handles(
|
||||
event_handle,
|
||||
include_classes=['Family', 'Person']))
|
||||
else:
|
||||
handle_list = set(
|
||||
self.r_db.find_backlink_handles(
|
||||
event_handle,
|
||||
include_classes=['Person']))
|
||||
if handle_list:
|
||||
|
||||
trow = Html("tr")
|
||||
tbody += trow
|
||||
|
||||
# set up hyperlinked letter for
|
||||
# alphabet_navigation
|
||||
tcell = Html("td", class_="ColumnLetter",
|
||||
inline=True)
|
||||
trow += tcell
|
||||
|
||||
if evt_type and not evt_type.isspace():
|
||||
letter = get_index_letter(
|
||||
self._(str(evt_type)[0].capitalize()),
|
||||
index_list, self.rlocale)
|
||||
else:
|
||||
letter = " "
|
||||
|
||||
if first or primary_difference(letter,
|
||||
prev_letter,
|
||||
self.rlocale):
|
||||
first = False
|
||||
prev_letter = letter
|
||||
t_a = 'class = "BeginLetter BeginType"'
|
||||
trow.attr = t_a
|
||||
ttle = self._("Event types beginning "
|
||||
"with letter %s") % letter
|
||||
tcell += Html("a", letter, name=letter,
|
||||
id_=letter, title=ttle,
|
||||
inline=True)
|
||||
else:
|
||||
tcell += " "
|
||||
|
||||
# display Event type if first in the list
|
||||
tcell = Html("td", class_="ColumnType",
|
||||
title=self._(evt_type),
|
||||
inline=True)
|
||||
trow += tcell
|
||||
if first_event:
|
||||
tcell += self._(evt_type)
|
||||
if trow.attr == "":
|
||||
trow.attr = 'class = "BeginType"'
|
||||
else:
|
||||
tcell += " "
|
||||
|
||||
# event date
|
||||
tcell = Html("td", class_="ColumnDate",
|
||||
inline=True)
|
||||
trow += tcell
|
||||
date = Date.EMPTY
|
||||
if event:
|
||||
date = event.get_date_object()
|
||||
if date and date is not Date.EMPTY:
|
||||
tcell += self.rlocale.get_date(date)
|
||||
else:
|
||||
tcell += " "
|
||||
|
||||
# Gramps ID
|
||||
trow += Html("td", class_="ColumnGRAMPSID") + (
|
||||
self.event_grampsid_link(event_handle,
|
||||
gid, None)
|
||||
)
|
||||
|
||||
# Person(s) column
|
||||
tcell = Html("td", class_="ColumnPerson")
|
||||
trow += tcell
|
||||
|
||||
# classname can either be a person or a family
|
||||
first_person = True
|
||||
|
||||
# get person(s) for ColumnPerson
|
||||
sorted_list = sorted(handle_list)
|
||||
self.complete_people(tcell, first_person,
|
||||
sorted_list,
|
||||
uplink=False)
|
||||
|
||||
_event_displayed.append(gid)
|
||||
first_event = False
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page ut for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(eventslistpage, output_file, sio, ldatec)
|
||||
|
||||
def _geteventdate(self, event_handle):
|
||||
"""
|
||||
Get the event date
|
||||
|
||||
@param: event_handle -- The handle for the event to use
|
||||
"""
|
||||
event_date = Date.EMPTY
|
||||
event = self.r_db.get_event_from_handle(event_handle)
|
||||
if event:
|
||||
date = event.get_date_object()
|
||||
if date:
|
||||
|
||||
# returns the date in YYYY-MM-DD format
|
||||
return Date(date.get_year_calendar("Gregorian"),
|
||||
date.get_month(), date.get_day())
|
||||
|
||||
# return empty date string
|
||||
return event_date
|
||||
|
||||
def event_grampsid_link(self, handle, grampsid, uplink):
|
||||
"""
|
||||
Create a hyperlink from event handle, but show grampsid
|
||||
|
||||
@param: handle -- The handle for the event
|
||||
@param: grampsid -- The gramps ID to display
|
||||
@param: uplink -- If True, then "../../../" is inserted in front of
|
||||
the result.
|
||||
"""
|
||||
url = self.report.build_url_fname_html(handle, "evt", uplink)
|
||||
|
||||
# return hyperlink to its caller
|
||||
return Html("a", grampsid, href=url, title=grampsid, inline=True)
|
||||
|
||||
def eventpage(self, report, title, event_handle):
|
||||
"""
|
||||
Creates the individual event page
|
||||
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: event_handle -- The event handle for the database
|
||||
"""
|
||||
event = report.database.get_event_from_handle(event_handle)
|
||||
BasePage.__init__(self, report, title, event.get_gramps_id())
|
||||
if not event:
|
||||
return None
|
||||
|
||||
ldatec = event.get_change_time()
|
||||
event_media_list = event.get_media_list()
|
||||
|
||||
self.uplink = True
|
||||
subdirs = True
|
||||
evt_type = self._(event.get_type().xml_str())
|
||||
self.page_title = "%(eventtype)s" % {'eventtype' : evt_type}
|
||||
self.bibli = Bibliography()
|
||||
|
||||
output_file, sio = self.report.create_file(event_handle, "evt")
|
||||
eventpage, head, body = self.write_header(self._("Events"))
|
||||
|
||||
# start event detail division
|
||||
with Html("div", class_="content", id="EventDetail") as eventdetail:
|
||||
body += eventdetail
|
||||
|
||||
thumbnail = self.disp_first_img_as_thumbnail(event_media_list,
|
||||
event)
|
||||
if thumbnail is not None:
|
||||
eventdetail += thumbnail
|
||||
|
||||
# display page title
|
||||
eventdetail += Html("h3", self.page_title, inline=True)
|
||||
|
||||
# begin eventdetail table
|
||||
with Html("table", class_="infolist eventlist") as table:
|
||||
eventdetail += table
|
||||
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
evt_gid = event.get_gramps_id()
|
||||
if not self.noid and evt_gid:
|
||||
trow = Html("tr") + (
|
||||
Html("td", self._("Gramps ID"),
|
||||
class_="ColumnAttribute", inline=True),
|
||||
Html("td", evt_gid,
|
||||
class_="ColumnGRAMPSID", inline=True)
|
||||
)
|
||||
tbody += trow
|
||||
|
||||
# get event data
|
||||
#
|
||||
# for more information: see get_event_data()
|
||||
#
|
||||
event_data = self.get_event_data(event, event_handle,
|
||||
subdirs, evt_gid)
|
||||
|
||||
for (label, colclass, data) in event_data:
|
||||
if data:
|
||||
trow = Html("tr") + (
|
||||
Html("td", label, class_="ColumnAttribute",
|
||||
inline=True),
|
||||
Html('td', data, class_="Column" + colclass)
|
||||
)
|
||||
tbody += trow
|
||||
|
||||
# Narrative subsection
|
||||
notelist = event.get_note_list()
|
||||
notelist = self.display_note_list(notelist)
|
||||
if notelist is not None:
|
||||
eventdetail += notelist
|
||||
|
||||
# get attribute list
|
||||
attrlist = event.get_attribute_list()
|
||||
if attrlist:
|
||||
attrsection, attrtable = self.display_attribute_header()
|
||||
self.display_attr_list(attrlist, attrtable)
|
||||
eventdetail += attrsection
|
||||
|
||||
# event source references
|
||||
srcrefs = self.display_ind_sources(event)
|
||||
if srcrefs is not None:
|
||||
eventdetail += srcrefs
|
||||
|
||||
# display additional images as gallery
|
||||
if self.create_media:
|
||||
addgallery = self.disp_add_img_as_gallery(event_media_list,
|
||||
event)
|
||||
if addgallery:
|
||||
eventdetail += addgallery
|
||||
|
||||
# References list
|
||||
ref_list = self.display_bkref_list(Event, event_handle)
|
||||
if ref_list is not None:
|
||||
eventdetail += ref_list
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the page
|
||||
self.xhtml_writer(eventpage, output_file, sio, ldatec)
|
||||
399
gramps/plugins/webreport/family.py
Normal file
399
gramps/plugins/webreport/family.py
Normal file
@ -0,0 +1,399 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
FamilyPage - Family index page and individual Family pages
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from collections import defaultdict
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.lib import (EventType, Family)
|
||||
from gramps.gen.plug.report import Bibliography
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import (get_first_letters, _KEYPERSON,
|
||||
alphabet_navigation, sort_people,
|
||||
primary_difference, first_letter,
|
||||
FULLCLEAR, get_index_letter)
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
#################################################
|
||||
#
|
||||
# creates the Family List Page and Family Pages
|
||||
#
|
||||
#################################################
|
||||
class FamilyPages(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information about the 'Family'
|
||||
database objects. It displays this information under the 'Families'
|
||||
tab. It is told by the 'add_instances' call which 'Family's to display,
|
||||
and remembers the list of Family. A single call to 'display_pages'
|
||||
displays both the Family List (Index) page and all the Family
|
||||
pages.
|
||||
|
||||
The base class 'BasePage' is initialised once for each page that is
|
||||
displayed.
|
||||
"""
|
||||
def __init__(self, report):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
"""
|
||||
BasePage.__init__(self, report, title="")
|
||||
self.family_dict = defaultdict(set)
|
||||
self.person = None
|
||||
self.familymappages = None
|
||||
|
||||
def display_pages(self, title):
|
||||
"""
|
||||
Generate and output the pages under the Family tab, namely the family
|
||||
index and the individual family pages.
|
||||
|
||||
@param: title -- Is the title of the web page
|
||||
"""
|
||||
LOG.debug("obj_dict[Family]")
|
||||
for item in self.report.obj_dict[Family].items():
|
||||
LOG.debug(" %s", str(item))
|
||||
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating family pages..."),
|
||||
len(self.report.obj_dict[Family]) + 1
|
||||
) as step:
|
||||
self.familylistpage(self.report, title,
|
||||
self.report.obj_dict[Family].keys())
|
||||
|
||||
for family_handle in self.report.obj_dict[Family]:
|
||||
step()
|
||||
self.familypage(self.report, title, family_handle)
|
||||
|
||||
def familylistpage(self, report, title, fam_list):
|
||||
"""
|
||||
Create a family index
|
||||
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: fam_list -- The handle for the place to add
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
|
||||
output_file, sio = self.report.create_file("families")
|
||||
familieslistpage, head, body = self.write_header(self._("Families"))
|
||||
ldatec = 0
|
||||
prev_letter = " "
|
||||
|
||||
# begin Family Division
|
||||
with Html("div", class_="content", id="Relationships") as relationlist:
|
||||
body += relationlist
|
||||
|
||||
# Families list page message
|
||||
msg = self._("This page contains an index of all the "
|
||||
"families/ relationships in the "
|
||||
"database, sorted by their family name/ surname. "
|
||||
"Clicking on a person’s "
|
||||
"name will take you to their "
|
||||
"family/ relationship’s page.")
|
||||
relationlist += Html("p", msg, id="description")
|
||||
|
||||
# go through all the families, and construct a dictionary of all the
|
||||
# people and the families thay are involved in. Note that the people
|
||||
# in the list may be involved in OTHER families, that are not listed
|
||||
# because they are not in the original family list.
|
||||
pers_fam_dict = defaultdict(list)
|
||||
for family_handle in fam_list:
|
||||
family = self.r_db.get_family_from_handle(family_handle)
|
||||
if family:
|
||||
if family.get_change_time() > ldatec:
|
||||
ldatec = family.get_change_time()
|
||||
husband_handle = family.get_father_handle()
|
||||
spouse_handle = family.get_mother_handle()
|
||||
if husband_handle:
|
||||
pers_fam_dict[husband_handle].append(family)
|
||||
if spouse_handle:
|
||||
pers_fam_dict[spouse_handle].append(family)
|
||||
|
||||
# add alphabet navigation
|
||||
index_list = get_first_letters(self.r_db, pers_fam_dict.keys(),
|
||||
_KEYPERSON, rlocale=self.rlocale)
|
||||
alpha_nav = alphabet_navigation(index_list, self.rlocale)
|
||||
if alpha_nav:
|
||||
relationlist += alpha_nav
|
||||
|
||||
# begin families table and table head
|
||||
with Html("table", class_="infolist relationships") as table:
|
||||
relationlist += table
|
||||
|
||||
thead = Html("thead")
|
||||
table += thead
|
||||
|
||||
trow = Html("tr")
|
||||
thead += trow
|
||||
|
||||
# set up page columns
|
||||
trow.extend(
|
||||
Html("th", trans, class_=colclass, inline=True)
|
||||
for trans, colclass in [(self._("Letter"),
|
||||
"ColumnRowLabel"),
|
||||
(self._("Person"), "ColumnPartner"),
|
||||
(self._("Family"), "ColumnPartner"),
|
||||
(self._("Marriage"), "ColumnDate"),
|
||||
(self._("Divorce"), "ColumnDate")]
|
||||
)
|
||||
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
# begin displaying index list
|
||||
ppl_handle_list = sort_people(self.r_db, pers_fam_dict.keys(),
|
||||
self.rlocale)
|
||||
first = True
|
||||
for (surname, handle_list) in ppl_handle_list:
|
||||
|
||||
if surname and not surname.isspace():
|
||||
letter = get_index_letter(first_letter(surname),
|
||||
index_list,
|
||||
self.rlocale)
|
||||
else:
|
||||
letter = ' '
|
||||
|
||||
# get person from sorted database list
|
||||
for person_handle in sorted(
|
||||
handle_list, key=self.sort_on_name_and_grampsid):
|
||||
person = self.r_db.get_person_from_handle(person_handle)
|
||||
if person:
|
||||
family_list = person.get_family_handle_list()
|
||||
first_family = True
|
||||
for family_handle in family_list:
|
||||
get_family = self.r_db.get_family_from_handle
|
||||
family = get_family(family_handle)
|
||||
trow = Html("tr")
|
||||
tbody += trow
|
||||
|
||||
tcell = Html("td", class_="ColumnRowLabel")
|
||||
trow += tcell
|
||||
|
||||
if first or primary_difference(letter,
|
||||
prev_letter,
|
||||
self.rlocale):
|
||||
first = False
|
||||
prev_letter = letter
|
||||
trow.attr = 'class="BeginLetter"'
|
||||
ttle = self._("Families beginning with "
|
||||
"letter ")
|
||||
tcell += Html("a", letter, name=letter,
|
||||
title=ttle + letter,
|
||||
inline=True)
|
||||
else:
|
||||
tcell += ' '
|
||||
|
||||
tcell = Html("td", class_="ColumnPartner")
|
||||
trow += tcell
|
||||
|
||||
if first_family:
|
||||
trow.attr = 'class ="BeginFamily"'
|
||||
|
||||
tcell += self.new_person_link(
|
||||
person_handle, uplink=self.uplink)
|
||||
|
||||
first_family = False
|
||||
else:
|
||||
tcell += ' '
|
||||
|
||||
tcell = Html("td", class_="ColumnPartner")
|
||||
trow += tcell
|
||||
|
||||
tcell += self.family_link(
|
||||
family.get_handle(),
|
||||
self.report.get_family_name(family),
|
||||
family.get_gramps_id(), self.uplink)
|
||||
|
||||
# family events; such as marriage and divorce
|
||||
# events
|
||||
fam_evt_ref_list = family.get_event_ref_list()
|
||||
tcell1 = Html("td", class_="ColumnDate",
|
||||
inline=True)
|
||||
tcell2 = Html("td", class_="ColumnDate",
|
||||
inline=True)
|
||||
trow += (tcell1, tcell2)
|
||||
|
||||
if fam_evt_ref_list:
|
||||
fam_evt_srt_ref_list = sorted(
|
||||
fam_evt_ref_list,
|
||||
key=self.sort_on_grampsid)
|
||||
for evt_ref in fam_evt_srt_ref_list:
|
||||
evt = self.r_db.get_event_from_handle(
|
||||
evt_ref.ref)
|
||||
if evt:
|
||||
evt_type = evt.get_type()
|
||||
if evt_type in [EventType.MARRIAGE,
|
||||
EventType.DIVORCE]:
|
||||
|
||||
cell = self.rlocale.get_date(
|
||||
evt.get_date_object())
|
||||
if (evt_type ==
|
||||
EventType.MARRIAGE):
|
||||
tcell1 += cell
|
||||
else:
|
||||
tcell1 += ' '
|
||||
|
||||
if (evt_type ==
|
||||
EventType.DIVORCE):
|
||||
tcell2 += cell
|
||||
else:
|
||||
tcell2 += ' '
|
||||
else:
|
||||
tcell1 += ' '
|
||||
tcell2 += ' '
|
||||
first_family = False
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(familieslistpage, output_file, sio, ldatec)
|
||||
|
||||
def familypage(self, report, title, family_handle):
|
||||
"""
|
||||
Create a family page
|
||||
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: family_handle -- The handle for the family to add
|
||||
"""
|
||||
family = report.database.get_family_from_handle(family_handle)
|
||||
if not family:
|
||||
return
|
||||
BasePage.__init__(self, report, title, family.get_gramps_id())
|
||||
ldatec = family.get_change_time()
|
||||
|
||||
self.bibli = Bibliography()
|
||||
self.uplink = True
|
||||
family_name = self.report.get_family_name(family)
|
||||
self.page_title = family_name
|
||||
|
||||
self.familymappages = report.options["familymappages"]
|
||||
|
||||
output_file, sio = self.report.create_file(family.get_handle(), "fam")
|
||||
familydetailpage, head, body = self.write_header(family_name)
|
||||
|
||||
# begin FamilyDetaill division
|
||||
with Html("div", class_="content",
|
||||
id="RelationshipDetail") as relationshipdetail:
|
||||
body += relationshipdetail
|
||||
|
||||
# family media list for initial thumbnail
|
||||
if self.create_media:
|
||||
media_list = family.get_media_list()
|
||||
# If Event pages are not being created, then we need to display
|
||||
# the family event media here
|
||||
if not self.inc_events:
|
||||
for evt_ref in family.get_event_ref_list():
|
||||
event = self.r_db.get_event_from_handle(evt_ref.ref)
|
||||
media_list += event.get_media_list()
|
||||
thumbnail = self.disp_first_img_as_thumbnail(media_list,
|
||||
family)
|
||||
if thumbnail:
|
||||
relationshipdetail += thumbnail
|
||||
|
||||
self.person = None # no longer used
|
||||
|
||||
relationshipdetail += Html(
|
||||
"h2", self.page_title, inline=True) + (
|
||||
Html('sup') + (Html('small') +
|
||||
self.get_citation_links(
|
||||
family.get_citation_list())))
|
||||
|
||||
# display relationships
|
||||
families = self.display_family_relationships(family, None)
|
||||
if families is not None:
|
||||
relationshipdetail += families
|
||||
|
||||
# display additional images as gallery
|
||||
if self.create_media and media_list:
|
||||
addgallery = self.disp_add_img_as_gallery(media_list, family)
|
||||
if addgallery:
|
||||
relationshipdetail += addgallery
|
||||
|
||||
# Narrative subsection
|
||||
notelist = family.get_note_list()
|
||||
if notelist:
|
||||
relationshipdetail += self.display_note_list(notelist)
|
||||
|
||||
# display family LDS ordinance...
|
||||
family_lds_ordinance_list = family.get_lds_ord_list()
|
||||
if family_lds_ordinance_list:
|
||||
relationshipdetail += self.display_lds_ordinance(family)
|
||||
|
||||
# get attribute list
|
||||
attrlist = family.get_attribute_list()
|
||||
if attrlist:
|
||||
attrsection, attrtable = self.display_attribute_header()
|
||||
self.display_attr_list(attrlist, attrtable)
|
||||
relationshipdetail += attrsection
|
||||
|
||||
# source references
|
||||
srcrefs = self.display_ind_sources(family)
|
||||
if srcrefs:
|
||||
relationshipdetail += srcrefs
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(familydetailpage, output_file, sio, ldatec)
|
||||
105
gramps/plugins/webreport/home.py
Normal file
105
gramps/plugins/webreport/home.py
Normal file
@ -0,0 +1,105 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
HomePage
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import FULLCLEAR
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
class HomePage(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information about the Home page.
|
||||
"""
|
||||
def __init__(self, report, title):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
@param: title -- Is the title of the web page
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
ldatec = 0
|
||||
|
||||
output_file, sio = self.report.create_file("index")
|
||||
homepage, head, body = self.write_header(self._('Home'))
|
||||
|
||||
# begin home division
|
||||
with Html("div", class_="content", id="Home") as section:
|
||||
body += section
|
||||
|
||||
homeimg = self.add_image('homeimg')
|
||||
if homeimg is not None:
|
||||
section += homeimg
|
||||
|
||||
note_id = report.options['homenote']
|
||||
if note_id:
|
||||
note = self.r_db.get_note_from_gramps_id(note_id)
|
||||
note_text = self.get_note_format(note, False)
|
||||
|
||||
# attach note
|
||||
section += note_text
|
||||
|
||||
# last modification of this note
|
||||
ldatec = note.get_change_time()
|
||||
|
||||
# create clear line for proper styling
|
||||
# create footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(homepage, output_file, sio, ldatec)
|
||||
106
gramps/plugins/webreport/introduction.py
Normal file
106
gramps/plugins/webreport/introduction.py
Normal file
@ -0,0 +1,106 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
IntroductionPage
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import FULLCLEAR
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
class IntroductionPage(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information
|
||||
about the introduction page.
|
||||
"""
|
||||
def __init__(self, report, title):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
@param: title -- Is the title of the web page
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
ldatec = 0
|
||||
|
||||
output_file, sio = self.report.create_file(report.intro_fname)
|
||||
intropage, head, body = self.write_header(self._('Introduction'))
|
||||
|
||||
# begin Introduction division
|
||||
with Html("div", class_="content", id="Introduction") as section:
|
||||
body += section
|
||||
|
||||
introimg = self.add_image('introimg')
|
||||
if introimg is not None:
|
||||
section += introimg
|
||||
|
||||
note_id = report.options['intronote']
|
||||
if note_id:
|
||||
note = self.r_db.get_note_from_gramps_id(note_id)
|
||||
note_text = self.get_note_format(note, False)
|
||||
|
||||
# attach note
|
||||
section += note_text
|
||||
|
||||
# last modification of this note
|
||||
ldatec = note.get_change_time()
|
||||
|
||||
# add clearline for proper styling
|
||||
# create footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(intropage, output_file, sio, ldatec)
|
||||
641
gramps/plugins/webreport/media.py
Normal file
641
gramps/plugins/webreport/media.py
Normal file
@ -0,0 +1,641 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
MediaPage - Media index page and individual Media pages
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
import gc
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from collections import defaultdict
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.lib import (Date, Media)
|
||||
from gramps.gen.plug.report import Bibliography
|
||||
from gramps.gen.utils.file import media_path_full
|
||||
from gramps.gen.utils.thumbnails import run_thumbnailer
|
||||
from gramps.gen.utils.image import image_size # , resize_to_jpeg_buffer
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import (FULLCLEAR, _WRONGMEDIAPATH,
|
||||
html_escape)
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
#################################################
|
||||
#
|
||||
# creates the Media List Page and Media Pages
|
||||
#
|
||||
#################################################
|
||||
class MediaPages(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information about the 'Media'
|
||||
database objects. It displays this information under the 'Individuals'
|
||||
tab. It is told by the 'add_instances' call which 'Media's to display,
|
||||
and remembers the list of persons. A single call to 'display_pages'
|
||||
displays both the Individual List (Index) page and all the Individual
|
||||
pages.
|
||||
|
||||
The base class 'BasePage' is initialised once for each page that is
|
||||
displayed.
|
||||
"""
|
||||
def __init__(self, report):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for this report
|
||||
"""
|
||||
BasePage.__init__(self, report, title="")
|
||||
self.media_dict = defaultdict(set)
|
||||
|
||||
def display_pages(self, title):
|
||||
"""
|
||||
Generate and output the pages under the Media tab, namely the media
|
||||
index and the individual media pages.
|
||||
|
||||
@param: title -- Is the title of the web page
|
||||
"""
|
||||
LOG.debug("obj_dict[Media]")
|
||||
for item in self.report.obj_dict[Media].items():
|
||||
LOG.debug(" %s", str(item))
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating media pages"),
|
||||
len(self.report.obj_dict[Media]) + 1
|
||||
) as step:
|
||||
# bug 8950 : it seems it's better to sort on desc + gid.
|
||||
def sort_by_desc_and_gid(obj):
|
||||
"""
|
||||
Sort by media description and gramps ID
|
||||
"""
|
||||
return (obj.desc.lower(), obj.gramps_id)
|
||||
|
||||
sorted_media_handles = sorted(
|
||||
self.report.obj_dict[Media].keys(),
|
||||
key=lambda x: sort_by_desc_and_gid(
|
||||
self.r_db.get_media_from_handle(x)))
|
||||
self.medialistpage(self.report, title, sorted_media_handles)
|
||||
|
||||
prev = None
|
||||
total = len(sorted_media_handles)
|
||||
index = 1
|
||||
for handle in sorted_media_handles:
|
||||
gc.collect() # Reduce memory usage when there are many images.
|
||||
next_ = None if index == total else sorted_media_handles[index]
|
||||
step()
|
||||
self.mediapage(self.report, title,
|
||||
handle, (prev, next_, index, total))
|
||||
prev = handle
|
||||
index += 1
|
||||
|
||||
def medialistpage(self, report, title, sorted_media_handles):
|
||||
"""
|
||||
Generate and output the Media index page.
|
||||
|
||||
@param: report -- The instance of the main report class
|
||||
for this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: sorted_media_handles -- A list of the handles of the media to be
|
||||
displayed sorted by the media title
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
|
||||
output_file, sio = self.report.create_file("media")
|
||||
medialistpage, head, body = self.write_header(self._('Media'))
|
||||
|
||||
ldatec = 0
|
||||
# begin gallery division
|
||||
with Html("div", class_="content", id="Gallery") as medialist:
|
||||
body += medialist
|
||||
|
||||
msg = self._("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. "
|
||||
"If you see media size dimensions "
|
||||
"above an image, click on the "
|
||||
"image to see the full sized version. ")
|
||||
medialist += Html("p", msg, id="description")
|
||||
|
||||
# begin gallery table and table head
|
||||
with Html("table",
|
||||
class_="infolist primobjlist gallerylist") as table:
|
||||
medialist += table
|
||||
|
||||
# begin table head
|
||||
thead = Html("thead")
|
||||
table += thead
|
||||
|
||||
trow = Html("tr")
|
||||
thead += trow
|
||||
|
||||
trow.extend(
|
||||
Html("th", trans, class_=colclass, inline=True)
|
||||
for trans, colclass in [(" ", "ColumnRowLabel"),
|
||||
(self._("Media | Name"),
|
||||
"ColumnName"),
|
||||
(self._("Date"), "ColumnDate"),
|
||||
(self._("Mime Type"), "ColumnMime")]
|
||||
)
|
||||
|
||||
# begin table body
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
index = 1
|
||||
for media_handle in sorted_media_handles:
|
||||
media = self.r_db.get_media_from_handle(media_handle)
|
||||
if media:
|
||||
if media.get_change_time() > ldatec:
|
||||
ldatec = media.get_change_time()
|
||||
title = media.get_description() or "[untitled]"
|
||||
|
||||
trow = Html("tr")
|
||||
tbody += trow
|
||||
|
||||
media_data_row = [
|
||||
[index, "ColumnRowLabel"],
|
||||
[self.media_ref_link(media_handle,
|
||||
title), "ColumnName"],
|
||||
[self.rlocale.get_date(media.get_date_object()),
|
||||
"ColumnDate"],
|
||||
[media.get_mime_type(), "ColumnMime"]]
|
||||
|
||||
trow.extend(
|
||||
Html("td", data, class_=colclass)
|
||||
for data, colclass in media_data_row
|
||||
)
|
||||
index += 1
|
||||
|
||||
def sort_by_desc_and_gid(obj):
|
||||
"""
|
||||
Sort by media description and gramps ID
|
||||
"""
|
||||
return (obj.desc, obj.gramps_id)
|
||||
|
||||
unused_media_handles = []
|
||||
if self.create_unused_media:
|
||||
# add unused media
|
||||
media_list = self.r_db.get_media_handles()
|
||||
for media_ref in media_list:
|
||||
if media_ref not in self.report.obj_dict[Media]:
|
||||
unused_media_handles.append(media_ref)
|
||||
unused_media_handles = sorted(
|
||||
unused_media_handles,
|
||||
key=lambda x: sort_by_desc_and_gid(
|
||||
self.r_db.get_media_from_handle(x)))
|
||||
|
||||
idx = 1
|
||||
prev = None
|
||||
total = len(unused_media_handles)
|
||||
if total > 0:
|
||||
trow += Html("tr")
|
||||
trow.extend(
|
||||
Html("td", Html("h4", " "), inline=True) +
|
||||
Html("td",
|
||||
Html("h4",
|
||||
self._("Below unused media objects"),
|
||||
inline=True),
|
||||
class_="") +
|
||||
Html("td", Html("h4", " "), inline=True) +
|
||||
Html("td", Html("h4", " "), inline=True)
|
||||
)
|
||||
for media_handle in unused_media_handles:
|
||||
media = self.r_db.get_media_from_handle(media_handle)
|
||||
gc.collect() # Reduce memory usage when many images.
|
||||
next_ = None if idx == total else unused_media_handles[idx]
|
||||
trow += Html("tr")
|
||||
media_data_row = [
|
||||
[index, "ColumnRowLabel"],
|
||||
[self.media_ref_link(media_handle,
|
||||
media.get_description()),
|
||||
"ColumnName"],
|
||||
[self.rlocale.get_date(media.get_date_object()),
|
||||
"ColumnDate"],
|
||||
[media.get_mime_type(), "ColumnMime"]]
|
||||
trow.extend(
|
||||
Html("td", data, class_=colclass)
|
||||
for data, colclass in media_data_row
|
||||
)
|
||||
self.mediapage(self.report, title,
|
||||
media_handle, (prev, next_, index, total))
|
||||
prev = media_handle
|
||||
index += 1
|
||||
idx += 1
|
||||
|
||||
# add footer section
|
||||
# add clearline for proper styling
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(medialistpage, output_file, sio, ldatec)
|
||||
|
||||
def media_ref_link(self, handle, name, uplink=False):
|
||||
"""
|
||||
Create a reference link to a media
|
||||
|
||||
@param: handle -- The media handle
|
||||
@param: name -- The name to use for the link
|
||||
@param: uplink -- If True, then "../../../" is inserted in front of the
|
||||
result.
|
||||
"""
|
||||
# get media url
|
||||
url = self.report.build_url_fname_html(handle, "img", uplink)
|
||||
|
||||
# get name
|
||||
name = html_escape(name)
|
||||
|
||||
# begin hyper link
|
||||
hyper = Html("a", name, href=url, title=name)
|
||||
|
||||
# return hyperlink to its callers
|
||||
return hyper
|
||||
|
||||
def mediapage(self, report, title, media_handle, info):
|
||||
"""
|
||||
Generate and output an individual Media page.
|
||||
|
||||
@param: report -- The instance of the main report class
|
||||
for this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: media_handle -- The media handle to use
|
||||
@param: info -- A tuple containing the media handle for the
|
||||
next and previous media, the current page
|
||||
number, and the total number of media pages
|
||||
"""
|
||||
media = report.database.get_media_from_handle(media_handle)
|
||||
BasePage.__init__(self, report, title, media.gramps_id)
|
||||
(prev, next_, page_number, total_pages) = info
|
||||
|
||||
ldatec = media.get_change_time()
|
||||
|
||||
# get media rectangles
|
||||
_region_items = self.media_ref_rect_regions(media_handle)
|
||||
|
||||
output_file, sio = self.report.create_file(media_handle, "img")
|
||||
self.uplink = True
|
||||
|
||||
self.bibli = Bibliography()
|
||||
|
||||
# get media type to be used primarily with "img" tags
|
||||
mime_type = media.get_mime_type()
|
||||
#mtype = get_description(mime_type)
|
||||
|
||||
if mime_type:
|
||||
#note_only = False
|
||||
newpath = self.copy_source_file(media_handle, media)
|
||||
target_exists = newpath is not None
|
||||
else:
|
||||
#note_only = True
|
||||
target_exists = False
|
||||
|
||||
self.copy_thumbnail(media_handle, media)
|
||||
self.page_title = media.get_description()
|
||||
esc_page_title = html_escape(self.page_title)
|
||||
(mediapage, head,
|
||||
body) = self.write_header("%s - %s" % (self._("Media"),
|
||||
self.page_title))
|
||||
|
||||
# if there are media rectangle regions, attach behaviour style sheet
|
||||
if _region_items:
|
||||
|
||||
fname = "/".join(["css", "behaviour.css"])
|
||||
url = self.report.build_url_fname(fname, None, self.uplink)
|
||||
head += Html("link", href=url, type="text/css",
|
||||
media="screen", rel="stylesheet")
|
||||
|
||||
# begin MediaDetail division
|
||||
with Html("div", class_="content", id="GalleryDetail") as mediadetail:
|
||||
body += mediadetail
|
||||
|
||||
# media navigation
|
||||
with Html("div", id="GalleryNav", role="navigation") as medianav:
|
||||
mediadetail += medianav
|
||||
if prev:
|
||||
medianav += self.media_nav_link(prev,
|
||||
self._("Previous"), True)
|
||||
data = self._('%(strong1_strt)s%(page_number)d%(strong_end)s '
|
||||
'of %(strong2_strt)s%(total_pages)d%(strong_end)s'
|
||||
) % {'strong1_strt' :
|
||||
'<strong id="GalleryCurrent">',
|
||||
'strong2_strt' : '<strong id="GalleryTotal">',
|
||||
'strong_end' : '</strong>',
|
||||
'page_number' : page_number,
|
||||
'total_pages' : total_pages}
|
||||
medianav += Html("span", data, id="GalleryPages")
|
||||
if next_:
|
||||
medianav += self.media_nav_link(next_, self._("Next"), True)
|
||||
|
||||
# missing media error message
|
||||
errormsg = self._("The file has been moved or deleted.")
|
||||
|
||||
# begin summaryarea division
|
||||
with Html("div", id="summaryarea") as summaryarea:
|
||||
mediadetail += summaryarea
|
||||
if mime_type:
|
||||
if mime_type.startswith("image"):
|
||||
if not target_exists:
|
||||
with Html("div", id="MediaDisplay") as mediadisplay:
|
||||
summaryarea += mediadisplay
|
||||
mediadisplay += Html("span", errormsg,
|
||||
class_="MissingImage")
|
||||
|
||||
else:
|
||||
# Check how big the image is relative to the
|
||||
# requested 'initial' image size.
|
||||
# If it's significantly bigger, scale it down to
|
||||
# improve the site's responsiveness. We don't want
|
||||
# the user to have to await a large download
|
||||
# unnecessarily. Either way, set the display image
|
||||
# size as requested.
|
||||
orig_image_path = media_path_full(self.r_db,
|
||||
media.get_path())
|
||||
#mtime = os.stat(orig_image_path).st_mtime
|
||||
(width, height) = image_size(orig_image_path)
|
||||
max_width = self.report.options[
|
||||
'maxinitialimagewidth']
|
||||
max_height = self.report.options[
|
||||
'maxinitialimageheight']
|
||||
if width != 0 and height != 0:
|
||||
scale_w = (float(max_width)/width) or 1
|
||||
# the 'or 1' is so that a max of
|
||||
# zero is ignored
|
||||
scale_h = (float(max_height)/height) or 1
|
||||
else:
|
||||
scale_w = 1.0
|
||||
scale_h = 1.0
|
||||
scale = min(scale_w, scale_h, 1.0)
|
||||
new_width = int(width*scale)
|
||||
new_height = int(height*scale)
|
||||
|
||||
# TODO. Convert disk path to URL.
|
||||
url = self.report.build_url_fname(orig_image_path,
|
||||
None, self.uplink)
|
||||
with Html("div", id="GalleryDisplay",
|
||||
style='width: %dpx; height: %dpx' % (
|
||||
new_width,
|
||||
new_height)) as mediadisplay:
|
||||
summaryarea += 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
|
||||
if _region_items:
|
||||
ordered = Html("ol", class_="RegionBox")
|
||||
mediadisplay += ordered
|
||||
while len(_region_items) > 0:
|
||||
(name, coord_x, coord_y,
|
||||
width, height, linkurl
|
||||
) = _region_items.pop()
|
||||
ordered += Html(
|
||||
"li",
|
||||
style="left:%d%%; "
|
||||
"top:%d%%; "
|
||||
"width:%d%%; "
|
||||
"height:%d%%;" % (
|
||||
coord_x, coord_y,
|
||||
width, height)) + (
|
||||
Html("a", name,
|
||||
href=linkurl)
|
||||
)
|
||||
|
||||
# display the image
|
||||
if orig_image_path != newpath:
|
||||
url = self.report.build_url_fname(
|
||||
newpath, None, self.uplink)
|
||||
mediadisplay += Html("a", href=url) + (
|
||||
Html("img", width=new_width,
|
||||
height=new_height, src=url,
|
||||
alt=esc_page_title)
|
||||
)
|
||||
else:
|
||||
dirname = tempfile.mkdtemp()
|
||||
thmb_path = os.path.join(dirname, "document.png")
|
||||
if run_thumbnailer(mime_type,
|
||||
media_path_full(self.r_db,
|
||||
media.get_path()),
|
||||
thmb_path, 320):
|
||||
try:
|
||||
path = self.report.build_path(
|
||||
"preview", media.get_handle())
|
||||
npath = os.path.join(path, media.get_handle())
|
||||
npath += ".png"
|
||||
self.report.copy_file(thmb_path, npath)
|
||||
path = npath
|
||||
os.unlink(thmb_path)
|
||||
except EnvironmentError:
|
||||
path = os.path.join("images", "document.png")
|
||||
else:
|
||||
path = os.path.join("images", "document.png")
|
||||
os.rmdir(dirname)
|
||||
|
||||
with Html("div", id="GalleryDisplay") as mediadisplay:
|
||||
summaryarea += mediadisplay
|
||||
|
||||
img_url = self.report.build_url_fname(path,
|
||||
None,
|
||||
self.uplink)
|
||||
if target_exists:
|
||||
# TODO. Convert disk path to URL
|
||||
url = self.report.build_url_fname(newpath,
|
||||
None,
|
||||
self.uplink)
|
||||
hyper = Html("a", href=url,
|
||||
title=esc_page_title) + (
|
||||
Html("img", src=img_url,
|
||||
alt=esc_page_title)
|
||||
)
|
||||
mediadisplay += hyper
|
||||
else:
|
||||
mediadisplay += Html("span", errormsg,
|
||||
class_="MissingImage")
|
||||
else:
|
||||
with Html("div", id="GalleryDisplay") as mediadisplay:
|
||||
summaryarea += mediadisplay
|
||||
url = self.report.build_url_image("document.png",
|
||||
"images", self.uplink)
|
||||
mediadisplay += Html("img", src=url,
|
||||
alt=esc_page_title,
|
||||
title=esc_page_title)
|
||||
|
||||
# media title
|
||||
title = Html("h3", html_escape(self.page_title.strip()),
|
||||
inline=True)
|
||||
summaryarea += title
|
||||
|
||||
# begin media table
|
||||
with Html("table", class_="infolist gallery") as table:
|
||||
summaryarea += table
|
||||
|
||||
# Gramps ID
|
||||
media_gid = media.gramps_id
|
||||
if not self.noid and media_gid:
|
||||
trow = Html("tr") + (
|
||||
Html("td", self._("Gramps ID"),
|
||||
class_="ColumnAttribute",
|
||||
inline=True),
|
||||
Html("td", media_gid, class_="ColumnValue",
|
||||
inline=True)
|
||||
)
|
||||
table += trow
|
||||
|
||||
# mime type
|
||||
if mime_type:
|
||||
trow = Html("tr") + (
|
||||
Html("td", self._("File Type"),
|
||||
class_="ColumnAttribute",
|
||||
inline=True),
|
||||
Html("td", mime_type, class_="ColumnValue",
|
||||
inline=True)
|
||||
)
|
||||
table += trow
|
||||
|
||||
# media date
|
||||
date = media.get_date_object()
|
||||
if date and date is not Date.EMPTY:
|
||||
trow = Html("tr") + (
|
||||
Html("td", self._("Date"), class_="ColumnAttribute",
|
||||
inline=True),
|
||||
Html("td", self.rlocale.get_date(date),
|
||||
class_="ColumnValue",
|
||||
inline=True)
|
||||
)
|
||||
table += trow
|
||||
|
||||
# get media notes
|
||||
notelist = self.display_note_list(media.get_note_list())
|
||||
if notelist is not None:
|
||||
mediadetail += notelist
|
||||
|
||||
# get attribute list
|
||||
attrlist = media.get_attribute_list()
|
||||
if attrlist:
|
||||
attrsection, attrtable = self.display_attribute_header()
|
||||
self.display_attr_list(attrlist, attrtable)
|
||||
mediadetail += attrsection
|
||||
|
||||
# get media sources
|
||||
srclist = self.display_media_sources(media)
|
||||
if srclist is not None:
|
||||
mediadetail += srclist
|
||||
|
||||
# get media references
|
||||
reflist = self.display_bkref_list(Media, media_handle)
|
||||
if reflist is not None:
|
||||
mediadetail += reflist
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(mediapage, output_file, sio, ldatec)
|
||||
|
||||
def media_nav_link(self, handle, name, uplink=False):
|
||||
"""
|
||||
Creates the Media Page Navigation hyperlinks for Next and Prev
|
||||
"""
|
||||
url = self.report.build_url_fname_html(handle, "img", uplink)
|
||||
name = html_escape(name)
|
||||
return Html("a", name, name=name, id=name, href=url,
|
||||
title=name, inline=True)
|
||||
|
||||
def display_media_sources(self, photo):
|
||||
"""
|
||||
Display media sources
|
||||
|
||||
@param: photo -- The source object (image, pdf, ...)
|
||||
"""
|
||||
list(map(
|
||||
lambda i: self.bibli.add_reference(
|
||||
self.r_db.get_citation_from_handle(i)),
|
||||
photo.get_citation_list()))
|
||||
sourcerefs = self.display_source_refs(self.bibli)
|
||||
|
||||
# return source references to its caller
|
||||
return sourcerefs
|
||||
|
||||
def copy_source_file(self, handle, photo):
|
||||
"""
|
||||
Copy source file in the web tree.
|
||||
|
||||
@param: handle -- Handle of the source
|
||||
@param: photo -- The source object (image, pdf, ...)
|
||||
"""
|
||||
ext = os.path.splitext(photo.get_path())[1]
|
||||
to_dir = self.report.build_path('images', handle)
|
||||
newpath = os.path.join(to_dir, handle) + ext
|
||||
|
||||
fullpath = media_path_full(self.r_db, photo.get_path())
|
||||
if not os.path.isfile(fullpath):
|
||||
_WRONGMEDIAPATH.append([photo.get_gramps_id(), fullpath])
|
||||
return None
|
||||
try:
|
||||
mtime = os.stat(fullpath).st_mtime
|
||||
if self.report.archive:
|
||||
self.report.archive.add(fullpath, str(newpath))
|
||||
else:
|
||||
to_dir = os.path.join(self.html_dir, to_dir)
|
||||
if not os.path.isdir(to_dir):
|
||||
os.makedirs(to_dir)
|
||||
new_file = os.path.join(self.html_dir, newpath)
|
||||
shutil.copyfile(fullpath, new_file)
|
||||
os.utime(new_file, (mtime, mtime))
|
||||
return newpath
|
||||
except (IOError, OSError) as msg:
|
||||
error = _("Missing media object:"
|
||||
) + "%s (%s)" % (photo.get_description(),
|
||||
photo.get_gramps_id())
|
||||
self.r_user.warn(error, str(msg))
|
||||
return None
|
||||
File diff suppressed because it is too large
Load Diff
1787
gramps/plugins/webreport/person.py
Normal file
1787
gramps/plugins/webreport/person.py
Normal file
File diff suppressed because it is too large
Load Diff
451
gramps/plugins/webreport/place.py
Normal file
451
gramps/plugins/webreport/place.py
Normal file
@ -0,0 +1,451 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
PlacePage - Place index page and individual Place pages
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from collections import defaultdict
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.lib import (PlaceType, Place)
|
||||
from gramps.gen.plug.report import Bibliography
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
from gramps.gen.utils.place import conv_lat_lon
|
||||
from gramps.gen.utils.location import get_main_location
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import (get_first_letters, first_letter,
|
||||
alphabet_navigation, GOOGLE_MAPS,
|
||||
primary_difference, _KEYPLACE,
|
||||
get_index_letter, FULLCLEAR,
|
||||
MARKER_PATH, OSM_MARKERS, MARKERS,
|
||||
html_escape)
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
######################################################
|
||||
# #
|
||||
# Place Pages #
|
||||
# #
|
||||
######################################################
|
||||
class PlacePages(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information about the 'Person'
|
||||
database objects. It displays this information under the 'Events'
|
||||
tab. It is told by the 'add_instances' call which 'Person's to display,
|
||||
and remembers the list of persons. A single call to 'display_pages'
|
||||
displays both the Event List (Index) page and all the Event
|
||||
pages.
|
||||
|
||||
The base class 'BasePage' is initialised once for each page that is
|
||||
displayed.
|
||||
"""
|
||||
def __init__(self, report):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
"""
|
||||
BasePage.__init__(self, report, title="")
|
||||
self.place_dict = defaultdict(set)
|
||||
self.placemappages = None
|
||||
self.mapservice = None
|
||||
self.person = None
|
||||
self.familymappages = None
|
||||
self.googlemapkey = None
|
||||
|
||||
def display_pages(self, title):
|
||||
"""
|
||||
Generate and output the pages under the Place tab, namely the place
|
||||
index and the individual place pages.
|
||||
|
||||
@param: title -- Is the title of the web page
|
||||
"""
|
||||
LOG.debug("obj_dict[Place]")
|
||||
for item in self.report.obj_dict[Place].items():
|
||||
LOG.debug(" %s", str(item))
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating place pages"),
|
||||
len(self.report.obj_dict[Place]) + 1
|
||||
) as step:
|
||||
|
||||
self.placelistpage(self.report, title,
|
||||
self.report.obj_dict[Place].keys())
|
||||
|
||||
for place_handle in self.report.obj_dict[Place]:
|
||||
step()
|
||||
self.placepage(self.report, title, place_handle)
|
||||
|
||||
def placelistpage(self, report, title, place_handles):
|
||||
"""
|
||||
Create a place index
|
||||
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: place_handles -- The handle for the place to add
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
|
||||
output_file, sio = self.report.create_file("places")
|
||||
placelistpage, head, body = self.write_header(self._("Places"))
|
||||
ldatec = 0
|
||||
prev_letter = " "
|
||||
|
||||
# begin places division
|
||||
with Html("div", class_="content", id="Places") as placelist:
|
||||
body += placelist
|
||||
|
||||
# place list page message
|
||||
msg = self._("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.")
|
||||
placelist += Html("p", msg, id="description")
|
||||
|
||||
# begin alphabet navigation
|
||||
index_list = get_first_letters(self.r_db, place_handles,
|
||||
_KEYPLACE, rlocale=self.rlocale)
|
||||
alpha_nav = alphabet_navigation(index_list, self.rlocale)
|
||||
if alpha_nav is not None:
|
||||
placelist += alpha_nav
|
||||
|
||||
# begin places table and table head
|
||||
with Html("table",
|
||||
class_="infolist primobjlist placelist") as table:
|
||||
placelist += table
|
||||
|
||||
# begin table head
|
||||
thead = Html("thead")
|
||||
table += thead
|
||||
|
||||
trow = Html("tr")
|
||||
thead += trow
|
||||
|
||||
trow.extend(
|
||||
Html("th", label, class_=colclass, inline=True)
|
||||
for (label, colclass) in [
|
||||
[self._("Letter"), "ColumnLetter"],
|
||||
[self._("Place Name | Name"), "ColumnName"],
|
||||
[self._("State/ Province"), "ColumnState"],
|
||||
[self._("Country"), "ColumnCountry"],
|
||||
[self._("Latitude"), "ColumnLatitude"],
|
||||
[self._("Longitude"), "ColumnLongitude"]
|
||||
]
|
||||
)
|
||||
|
||||
# bug 9495 : incomplete display of place hierarchy labels
|
||||
def sort_by_place_name(obj):
|
||||
""" sort by lower case place name. """
|
||||
name = self.report.obj_dict[Place][obj][1]
|
||||
return name.lower()
|
||||
|
||||
handle_list = sorted(place_handles,
|
||||
key=lambda x: sort_by_place_name(x))
|
||||
first = True
|
||||
|
||||
# begin table body
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
for place_handle in handle_list:
|
||||
place = self.r_db.get_place_from_handle(place_handle)
|
||||
if place:
|
||||
if place.get_change_time() > ldatec:
|
||||
ldatec = place.get_change_time()
|
||||
plc_title = self.report.obj_dict[Place][place_handle][1]
|
||||
main_location = get_main_location(self.r_db, place)
|
||||
|
||||
if plc_title and plc_title != " ":
|
||||
letter = get_index_letter(first_letter(plc_title),
|
||||
index_list,
|
||||
self.rlocale)
|
||||
else:
|
||||
letter = ' '
|
||||
|
||||
trow = Html("tr")
|
||||
tbody += trow
|
||||
|
||||
tcell = Html("td", class_="ColumnLetter", inline=True)
|
||||
trow += tcell
|
||||
if first or primary_difference(letter, prev_letter,
|
||||
self.rlocale):
|
||||
first = False
|
||||
prev_letter = letter
|
||||
trow.attr = 'class = "BeginLetter"'
|
||||
|
||||
ttle = self._("Places beginning "
|
||||
"with letter %s") % letter
|
||||
tcell += Html("a", letter, name=letter, title=ttle)
|
||||
else:
|
||||
tcell += " "
|
||||
|
||||
trow += Html("td",
|
||||
self.place_link(
|
||||
place.get_handle(),
|
||||
plc_title, place.get_gramps_id()),
|
||||
class_="ColumnName")
|
||||
|
||||
trow.extend(
|
||||
Html("td", data or " ", class_=colclass,
|
||||
inline=True)
|
||||
for (colclass, data) in [
|
||||
["ColumnState",
|
||||
main_location.get(PlaceType.STATE, '')],
|
||||
["ColumnCountry",
|
||||
main_location.get(PlaceType.COUNTRY, '')]
|
||||
]
|
||||
)
|
||||
|
||||
tcell1 = Html("td", class_="ColumnLatitude",
|
||||
inline=True)
|
||||
tcell2 = Html("td", class_="ColumnLongitude",
|
||||
inline=True)
|
||||
trow += (tcell1, tcell2)
|
||||
|
||||
if place.lat and place.long:
|
||||
latitude, longitude = conv_lat_lon(place.lat,
|
||||
place.long,
|
||||
"DEG")
|
||||
tcell1 += latitude
|
||||
tcell2 += longitude
|
||||
else:
|
||||
tcell1 += ' '
|
||||
tcell2 += ' '
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(placelistpage, output_file, sio, ldatec)
|
||||
|
||||
def placepage(self, report, title, place_handle):
|
||||
"""
|
||||
Create a place page
|
||||
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: place_handle -- The handle for the place to add
|
||||
"""
|
||||
place = report.database.get_place_from_handle(place_handle)
|
||||
if not place:
|
||||
return None
|
||||
BasePage.__init__(self, report, title, place.get_gramps_id())
|
||||
self.bibli = Bibliography()
|
||||
place_name = self.report.obj_dict[Place][place_handle][1]
|
||||
ldatec = place.get_change_time()
|
||||
|
||||
output_file, sio = self.report.create_file(place_handle, "plc")
|
||||
self.uplink = True
|
||||
self.page_title = place_name
|
||||
placepage, head, body = self.write_header(_("Places"))
|
||||
|
||||
self.placemappages = self.report.options['placemappages']
|
||||
self.mapservice = self.report.options['mapservice']
|
||||
self.googlemapkey = self.report.options['googlemapkey']
|
||||
|
||||
# begin PlaceDetail Division
|
||||
with Html("div", class_="content", id="PlaceDetail") as placedetail:
|
||||
body += placedetail
|
||||
|
||||
if self.create_media:
|
||||
media_list = place.get_media_list()
|
||||
thumbnail = self.disp_first_img_as_thumbnail(media_list,
|
||||
place)
|
||||
if thumbnail is not None:
|
||||
placedetail += thumbnail
|
||||
|
||||
# add section title
|
||||
placedetail += Html("h3",
|
||||
html_escape(place_name),
|
||||
inline=True)
|
||||
|
||||
# begin summaryarea division and places table
|
||||
with Html("div", id='summaryarea') as summaryarea:
|
||||
placedetail += summaryarea
|
||||
|
||||
with Html("table", class_="infolist place") as table:
|
||||
summaryarea += table
|
||||
|
||||
# list the place fields
|
||||
self.dump_place(place, table)
|
||||
|
||||
# place gallery
|
||||
if self.create_media:
|
||||
placegallery = self.disp_add_img_as_gallery(media_list, place)
|
||||
if placegallery is not None:
|
||||
placedetail += placegallery
|
||||
|
||||
# place notes
|
||||
notelist = self.display_note_list(place.get_note_list())
|
||||
if notelist is not None:
|
||||
placedetail += notelist
|
||||
|
||||
# place urls
|
||||
urllinks = self.display_url_list(place.get_url_list())
|
||||
if urllinks is not None:
|
||||
placedetail += urllinks
|
||||
|
||||
# add place map here
|
||||
# Link to Gramps marker
|
||||
fname = "/".join(['images', 'marker.png'])
|
||||
marker_path = self.report.build_url_image("marker.png",
|
||||
"images", self.uplink)
|
||||
|
||||
if self.placemappages:
|
||||
if place and (place.lat and place.long):
|
||||
latitude, longitude = conv_lat_lon(place.get_latitude(),
|
||||
place.get_longitude(),
|
||||
"D.D8")
|
||||
placetitle = place_name
|
||||
|
||||
# add narrative-maps CSS...
|
||||
fname = "/".join(["css", "narrative-maps.css"])
|
||||
url = self.report.build_url_fname(fname, None, self.uplink)
|
||||
head += Html("link", href=url, type="text/css",
|
||||
media="screen", rel="stylesheet")
|
||||
|
||||
# add MapService specific javascript code
|
||||
src_js = GOOGLE_MAPS + "api/js?sensor=false"
|
||||
if self.mapservice == "Google":
|
||||
if self.googlemapkey:
|
||||
src_js += "&key=" + self.googlemapkey
|
||||
head += Html("script", type="text/javascript",
|
||||
src=src_js, inline=True)
|
||||
else:
|
||||
url = self.secure_mode
|
||||
url += ("maxcdn.bootstrapcdn.com/bootstrap/3.3.7/"
|
||||
"css/bootstrap.min.css")
|
||||
head += Html("link", href=url, type="text/javascript",
|
||||
rel="stylesheet")
|
||||
src_js = self.secure_mode
|
||||
src_js += ("ajax.googleapis.com/ajax/libs/jquery/1.9.1/"
|
||||
"jquery.min.js")
|
||||
head += Html("script", type="text/javascript",
|
||||
src=src_js, inline=True)
|
||||
src_js = self.secure_mode
|
||||
src_js += "openlayers.org/en/v3.17.1/build/ol.js"
|
||||
head += Html("script", type="text/javascript",
|
||||
src=src_js, inline=True)
|
||||
url = self.secure_mode
|
||||
url += "openlayers.org/en/v3.17.1/css/ol.css"
|
||||
head += Html("link", href=url, type="text/javascript",
|
||||
rel="stylesheet")
|
||||
src_js = self.secure_mode
|
||||
src_js += ("maxcdn.bootstrapcdn.com/bootstrap/3.3.7/"
|
||||
"js/bootstrap.min.js")
|
||||
head += Html("script", type="text/javascript",
|
||||
src=src_js, inline=True)
|
||||
|
||||
# section title
|
||||
placedetail += Html("h4", self._("Place Map"), inline=True)
|
||||
|
||||
# begin map_canvas division
|
||||
with Html("div", id="map_canvas", inline=True) as canvas:
|
||||
placedetail += canvas
|
||||
|
||||
# Begin inline javascript code because jsc is a
|
||||
# docstring, it does NOT have to be properly indented
|
||||
if self.mapservice == "Google":
|
||||
with Html("script", type="text/javascript",
|
||||
indent=False) as jsc:
|
||||
head += jsc
|
||||
|
||||
# Google adds Latitude/ Longitude to its maps...
|
||||
plce = placetitle.replace("'", "\\'")
|
||||
jsc += MARKER_PATH % marker_path
|
||||
jsc += MARKERS % ([[plce,
|
||||
latitude,
|
||||
longitude,
|
||||
1]],
|
||||
latitude, longitude,
|
||||
10)
|
||||
|
||||
else:
|
||||
# OpenStreetMap (OSM) adds Longitude/ Latitude
|
||||
# to its maps, and needs a country code in
|
||||
# lowercase letters...
|
||||
with Html("script", type="text/javascript") as jsc:
|
||||
canvas += jsc
|
||||
#param1 = xml_lang()[3:5].lower()
|
||||
jsc += MARKER_PATH % marker_path
|
||||
jsc += OSM_MARKERS % ([[float(longitude),
|
||||
float(latitude),
|
||||
placetitle]],
|
||||
longitude, latitude, 10)
|
||||
|
||||
# add javascript function call to body element
|
||||
body.attr += ' onload = "initialize();" '
|
||||
|
||||
# add div for popups.
|
||||
with Html("div", id="popup", inline=True) as popup:
|
||||
placedetail += popup
|
||||
|
||||
# source references
|
||||
srcrefs = self.display_ind_sources(place)
|
||||
if srcrefs is not None:
|
||||
placedetail += srcrefs
|
||||
|
||||
# References list
|
||||
ref_list = self.display_bkref_list(Place, place_handle)
|
||||
if ref_list is not None:
|
||||
placedetail += ref_list
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(placepage, output_file, sio, ldatec)
|
||||
287
gramps/plugins/webreport/repository.py
Normal file
287
gramps/plugins/webreport/repository.py
Normal file
@ -0,0 +1,287 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
RepositoryPage - Repository index page and individual Repository pages
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from collections import defaultdict
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.lib import Repository
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import (FULLCLEAR, html_escape)
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
#################################################
|
||||
#
|
||||
# creates the Repository List Page and Repository Pages
|
||||
#
|
||||
#################################################
|
||||
class RepositoryPages(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information about the 'Repository'
|
||||
database objects. It displays this information under the 'Individuals'
|
||||
tab. It is told by the 'add_instances' call which 'Repository's to display,
|
||||
and remembers the list of persons. A single call to 'display_pages'
|
||||
displays both the Individual List (Index) page and all the Individual
|
||||
pages.
|
||||
|
||||
The base class 'BasePage' is initialised once for each page that is
|
||||
displayed.
|
||||
"""
|
||||
def __init__(self, report):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for this report
|
||||
"""
|
||||
BasePage.__init__(self, report, title="")
|
||||
self.repos_dict = defaultdict(set)
|
||||
|
||||
def display_pages(self, title):
|
||||
"""
|
||||
Generate and output the pages under the Repository tab, namely the
|
||||
repository index and the individual repository pages.
|
||||
|
||||
@param: title -- Is the title of the web page
|
||||
"""
|
||||
LOG.debug("obj_dict[Person]")
|
||||
for item in self.report.obj_dict[Repository].items():
|
||||
LOG.debug(" %s", str(item))
|
||||
|
||||
# set progress bar pass for Repositories
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_('Creating repository pages'),
|
||||
len(self.report.obj_dict[Repository]) + 1
|
||||
) as step:
|
||||
# Sort the repositories
|
||||
repos_dict = {}
|
||||
for repo_handle in self.report.obj_dict[Repository]:
|
||||
repository = self.r_db.get_repository_from_handle(repo_handle)
|
||||
key = repository.get_name() + str(repository.get_gramps_id())
|
||||
repos_dict[key] = (repository, repo_handle)
|
||||
|
||||
keys = sorted(repos_dict, key=self.rlocale.sort_key)
|
||||
|
||||
# RepositoryListPage Class
|
||||
self.repositorylistpage(self.report, title, repos_dict, keys)
|
||||
|
||||
for index, key in enumerate(keys):
|
||||
(repo, handle) = repos_dict[key]
|
||||
|
||||
step()
|
||||
self.repositorypage(self.report, title, repo, handle)
|
||||
|
||||
def repositorylistpage(self, report, title, repos_dict, keys):
|
||||
"""
|
||||
Create Index for repositories
|
||||
|
||||
@param: report -- The instance of the main report class
|
||||
for this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: repos_dict -- The dictionary for all repositories
|
||||
@param: keys -- The keys used to access repositories
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
#inc_repos = self.report.options["inc_repository"]
|
||||
|
||||
output_file, sio = self.report.create_file("repositories")
|
||||
repolistpage, head, body = self.write_header(_("Repositories"))
|
||||
|
||||
ldatec = 0
|
||||
# begin RepositoryList division
|
||||
with Html("div", class_="content",
|
||||
id="RepositoryList") as repositorylist:
|
||||
body += repositorylist
|
||||
|
||||
msg = self._("This page contains an index of "
|
||||
"all the repositories in the "
|
||||
"database, sorted by their title. "
|
||||
"Clicking on a repositories’s title "
|
||||
"will take you to that repositories’s page.")
|
||||
repositorylist += Html("p", msg, id="description")
|
||||
|
||||
# begin repositories table and table head
|
||||
with Html("table", class_="infolist primobjlist repolist") as table:
|
||||
repositorylist += table
|
||||
|
||||
thead = Html("thead")
|
||||
table += thead
|
||||
|
||||
trow = Html("tr") + (
|
||||
Html("th", " ", class_="ColumnRowLabel", inline=True),
|
||||
Html("th", self._("Type"), class_="ColumnType",
|
||||
inline=True),
|
||||
Html("th", self._("Repository |Name"), class_="ColumnName",
|
||||
inline=True)
|
||||
)
|
||||
thead += trow
|
||||
|
||||
# begin table body
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
for index, key in enumerate(keys):
|
||||
(repo, handle) = repos_dict[key]
|
||||
|
||||
trow = Html("tr")
|
||||
tbody += trow
|
||||
|
||||
# index number
|
||||
trow += Html("td", index + 1, class_="ColumnRowLabel",
|
||||
inline=True)
|
||||
|
||||
# repository type
|
||||
rtype = self._(repo.type.xml_str())
|
||||
trow += Html("td", rtype, class_="ColumnType", inline=True)
|
||||
|
||||
# repository name and hyperlink
|
||||
if repo.get_name():
|
||||
trow += Html("td",
|
||||
self.repository_link(handle,
|
||||
repo.get_name(),
|
||||
repo.get_gramps_id(),
|
||||
self.uplink),
|
||||
class_="ColumnName")
|
||||
ldatec = repo.get_change_time()
|
||||
else:
|
||||
trow += Html("td", "[ untitled ]", class_="ColumnName")
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(repolistpage, output_file, sio, ldatec)
|
||||
|
||||
def repositorypage(self, report, title, repo, handle):
|
||||
"""
|
||||
Create one page for one repository.
|
||||
|
||||
@param: report -- The instance of the main report class for this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: repo -- the repository to use
|
||||
@param: handle -- the handle to use
|
||||
"""
|
||||
gid = repo.get_gramps_id()
|
||||
BasePage.__init__(self, report, title, gid)
|
||||
ldatec = repo.get_change_time()
|
||||
|
||||
output_file, sio = self.report.create_file(handle, 'repo')
|
||||
self.uplink = True
|
||||
repositorypage, head, body = self.write_header(_('Repositories'))
|
||||
|
||||
# begin RepositoryDetail division and page title
|
||||
with Html("div", class_="content",
|
||||
id="RepositoryDetail") as repositorydetail:
|
||||
body += repositorydetail
|
||||
|
||||
# repository name
|
||||
repositorydetail += Html("h3", html_escape(repo.name),
|
||||
inline=True)
|
||||
|
||||
# begin repository table
|
||||
with Html("table", class_="infolist repolist") as table:
|
||||
repositorydetail += table
|
||||
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
if not self.noid and gid:
|
||||
trow = Html("tr") + (
|
||||
Html("td", self._("Gramps ID"),
|
||||
class_="ColumnAttribute",
|
||||
inline=True),
|
||||
Html("td", gid, class_="ColumnValue", inline=True)
|
||||
)
|
||||
tbody += trow
|
||||
|
||||
trow = Html("tr") + (
|
||||
Html("td", self._("Type"), class_="ColumnAttribute",
|
||||
inline=True),
|
||||
Html("td", self._(repo.get_type().xml_str()),
|
||||
class_="ColumnValue",
|
||||
inline=True)
|
||||
)
|
||||
tbody += trow
|
||||
|
||||
# repository: address(es)...
|
||||
# repository addresses do NOT have Sources
|
||||
repo_address = self.display_addr_list(repo.get_address_list(),
|
||||
False)
|
||||
if repo_address is not None:
|
||||
repositorydetail += repo_address
|
||||
|
||||
# repository: urllist
|
||||
urllist = self.display_url_list(repo.get_url_list())
|
||||
if urllist is not None:
|
||||
repositorydetail += urllist
|
||||
|
||||
# reposity: notelist
|
||||
notelist = self.display_note_list(repo.get_note_list())
|
||||
if notelist is not None:
|
||||
repositorydetail += notelist
|
||||
|
||||
# display Repository Referenced Sources...
|
||||
ref_list = self.display_bkref_list(Repository, repo.get_handle())
|
||||
if ref_list is not None:
|
||||
repositorydetail += ref_list
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(repositorypage, output_file, sio, ldatec)
|
||||
306
gramps/plugins/webreport/source.py
Normal file
306
gramps/plugins/webreport/source.py
Normal file
@ -0,0 +1,306 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
SourcePage - Source index page and individual Source pages
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from collections import defaultdict
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.lib import Source
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import (FULLCLEAR, html_escape)
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb.source")
|
||||
getcontext().prec = 8
|
||||
|
||||
#################################################
|
||||
#
|
||||
# creates the Source List Page and Source Pages
|
||||
#
|
||||
#################################################
|
||||
class SourcePages(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information about the 'Source'
|
||||
database objects. It displays this information under the 'Sources'
|
||||
tab. It is told by the 'add_instances' call which 'Source's to display,
|
||||
and remembers the list of persons. A single call to 'display_pages'
|
||||
displays both the Individual List (Index) page and all the Individual
|
||||
pages.
|
||||
|
||||
The base class 'BasePage' is initialised once for each page that is
|
||||
displayed.
|
||||
"""
|
||||
def __init__(self, report):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
"""
|
||||
BasePage.__init__(self, report, title="")
|
||||
self.source_dict = defaultdict(set)
|
||||
self.navigation = None
|
||||
self.citationreferents = None
|
||||
|
||||
def display_pages(self, title):
|
||||
"""
|
||||
Generate and output the pages under the Sources tab, namely the sources
|
||||
index and the individual sources pages.
|
||||
|
||||
@param: title -- Is the title of the web page
|
||||
"""
|
||||
LOG.debug("obj_dict[Source]")
|
||||
for item in self.report.obj_dict[Source].items():
|
||||
LOG.debug(" %s", str(item))
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating source pages"),
|
||||
len(self.report.obj_dict[Source]) + 1
|
||||
) as step:
|
||||
self.sourcelistpage(self.report, title,
|
||||
self.report.obj_dict[Source].keys())
|
||||
|
||||
for source_handle in self.report.obj_dict[Source]:
|
||||
step()
|
||||
self.sourcepage(self.report, title, source_handle)
|
||||
|
||||
def sourcelistpage(self, report, title, source_handles):
|
||||
"""
|
||||
Generate and output the Sources index page.
|
||||
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: source_handles -- A list of the handles of the sources to be
|
||||
displayed
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
|
||||
source_dict = {}
|
||||
|
||||
output_file, sio = self.report.create_file("sources")
|
||||
sourcelistpage, head, body = self.write_header(self._("Sources"))
|
||||
|
||||
# begin source list division
|
||||
with Html("div", class_="content", id="Sources") as sourceslist:
|
||||
body += sourceslist
|
||||
|
||||
# Sort the sources
|
||||
for handle in source_handles:
|
||||
source = self.r_db.get_source_from_handle(handle)
|
||||
if source is not None:
|
||||
key = source.get_title() + source.get_author()
|
||||
key += str(source.get_gramps_id())
|
||||
source_dict[key] = (source, handle)
|
||||
|
||||
keys = sorted(source_dict, key=self.rlocale.sort_key)
|
||||
|
||||
msg = self._("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.")
|
||||
sourceslist += Html("p", msg, id="description")
|
||||
|
||||
# begin sourcelist table and table head
|
||||
with Html("table",
|
||||
class_="infolist primobjlist sourcelist") as table:
|
||||
sourceslist += table
|
||||
thead = Html("thead")
|
||||
table += thead
|
||||
|
||||
trow = Html("tr")
|
||||
thead += trow
|
||||
|
||||
header_row = [
|
||||
(self._("Number"), "ColumnRowLabel"),
|
||||
(self._("Author"), "ColumnAuthor"),
|
||||
(self._("Source Name|Name"), "ColumnName")]
|
||||
|
||||
trow.extend(
|
||||
Html("th", label or " ", class_=colclass, inline=True)
|
||||
for (label, colclass) in header_row
|
||||
)
|
||||
|
||||
# begin table body
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
for index, key in enumerate(keys):
|
||||
source, source_handle = source_dict[key]
|
||||
|
||||
trow = Html("tr") + (
|
||||
Html("td", index + 1, class_="ColumnRowLabel",
|
||||
inline=True)
|
||||
)
|
||||
tbody += trow
|
||||
trow.extend(
|
||||
Html("td", source.get_author(), class_="ColumnAuthor",
|
||||
inline=True)
|
||||
)
|
||||
trow.extend(
|
||||
Html("td", self.source_link(source_handle,
|
||||
source.get_title(),
|
||||
source.get_gramps_id()),
|
||||
class_="ColumnName")
|
||||
)
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(None)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(sourcelistpage, output_file, sio, 0)
|
||||
|
||||
def sourcepage(self, report, title, source_handle):
|
||||
"""
|
||||
Generate and output an individual Source page.
|
||||
|
||||
@param: report -- The instance of the main report class
|
||||
for this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: source_handle -- The handle of the source to be output
|
||||
"""
|
||||
source = report.database.get_source_from_handle(source_handle)
|
||||
BasePage.__init__(self, report, title, source.get_gramps_id())
|
||||
if not source:
|
||||
return
|
||||
|
||||
self.page_title = source.get_title()
|
||||
|
||||
inc_repositories = self.report.options["inc_repository"]
|
||||
self.navigation = self.report.options['navigation']
|
||||
self.citationreferents = self.report.options['citationreferents']
|
||||
|
||||
output_file, sio = self.report.create_file(source_handle, "src")
|
||||
self.uplink = True
|
||||
sourcepage, head, body = self.write_header(
|
||||
"%s - %s" % (self._('Sources'), self.page_title))
|
||||
|
||||
ldatec = 0
|
||||
# begin source detail division
|
||||
with Html("div", class_="content", id="SourceDetail") as sourcedetail:
|
||||
body += sourcedetail
|
||||
|
||||
media_list = source.get_media_list()
|
||||
if self.create_media and media_list:
|
||||
thumbnail = self.disp_first_img_as_thumbnail(media_list,
|
||||
source)
|
||||
if thumbnail is not None:
|
||||
sourcedetail += thumbnail
|
||||
|
||||
# add section title
|
||||
sourcedetail += Html("h3", html_escape(source.get_title()),
|
||||
inline=True)
|
||||
|
||||
# begin sources table
|
||||
with Html("table", class_="infolist source") as table:
|
||||
sourcedetail += table
|
||||
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
source_gid = False
|
||||
if not self.noid and self.gid:
|
||||
source_gid = source.get_gramps_id()
|
||||
|
||||
# last modification of this source
|
||||
ldatec = source.get_change_time()
|
||||
|
||||
for (label, value) in [(self._("Gramps ID"), source_gid),
|
||||
(self._("Author"), source.get_author()),
|
||||
(self._("Abbreviation"),
|
||||
source.get_abbreviation()),
|
||||
(self._("Publication information"),
|
||||
source.get_publication_info())]:
|
||||
if value:
|
||||
trow = Html("tr") + (
|
||||
Html("td", label, class_="ColumnAttribute",
|
||||
inline=True),
|
||||
Html("td", value, class_="ColumnValue", inline=True)
|
||||
)
|
||||
tbody += trow
|
||||
|
||||
# Source notes
|
||||
notelist = self.display_note_list(source.get_note_list())
|
||||
if notelist is not None:
|
||||
sourcedetail += notelist
|
||||
|
||||
# additional media from Source (if any?)
|
||||
if self.create_media and media_list:
|
||||
sourcemedia = self.disp_add_img_as_gallery(media_list, source)
|
||||
if sourcemedia is not None:
|
||||
sourcedetail += sourcemedia
|
||||
|
||||
# Source Data Map...
|
||||
src_data_map = self.write_srcattr(source.get_attribute_list())
|
||||
if src_data_map is not None:
|
||||
sourcedetail += src_data_map
|
||||
|
||||
# Source Repository list
|
||||
if inc_repositories:
|
||||
repo_list = self.dump_repository_ref_list(
|
||||
source.get_reporef_list())
|
||||
if repo_list is not None:
|
||||
sourcedetail += repo_list
|
||||
|
||||
# Source references list
|
||||
ref_list = self.display_bkref_list(Source, source_handle)
|
||||
if ref_list is not None:
|
||||
sourcedetail += ref_list
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(sourcepage, output_file, sio, ldatec)
|
||||
243
gramps/plugins/webreport/statistics.py
Normal file
243
gramps/plugins/webreport/statistics.py
Normal file
@ -0,0 +1,243 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
StatisticsPage
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.lib import (Person, Family, Event, Place, Source,
|
||||
Citation, Repository)
|
||||
from gramps.gen.plug.report import Bibliography
|
||||
from gramps.gen.utils.file import media_path_full
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import FULLCLEAR
|
||||
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
_ = glocale.translation.sgettext
|
||||
|
||||
class StatisticsPage(BasePage):
|
||||
"""
|
||||
Create one page for statistics
|
||||
"""
|
||||
def __init__(self, report, title, step):
|
||||
"""
|
||||
@param: report -- The instance of the main report class
|
||||
for this report
|
||||
@param: title -- Is the title of the web page
|
||||
"""
|
||||
import posixpath
|
||||
BasePage.__init__(self, report, title)
|
||||
self.bibli = Bibliography()
|
||||
self.uplink = False
|
||||
self.report = report
|
||||
# set the file name and open file
|
||||
output_file, sio = self.report.create_file("statistics")
|
||||
addressbookpage, head, body = self.write_header(_("Statistics"))
|
||||
(males,
|
||||
females,
|
||||
unknown) = self.get_gender(report.database.iter_person_handles())
|
||||
|
||||
mobjects = report.database.get_number_of_media()
|
||||
npersons = report.database.get_number_of_people()
|
||||
nfamilies = report.database.get_number_of_families()
|
||||
nsurnames = len(set(report.database.surname_list))
|
||||
notfound = []
|
||||
total_media = 0
|
||||
mbytes = "0"
|
||||
chars = 0
|
||||
for media in report.database.iter_media():
|
||||
total_media += 1
|
||||
fullname = media_path_full(report.database, media.get_path())
|
||||
try:
|
||||
chars += posixpath.getsize(fullname)
|
||||
length = len(str(chars))
|
||||
if chars <= 999999:
|
||||
mbytes = _("less than 1")
|
||||
else:
|
||||
mbytes = str(chars)[:(length-6)]
|
||||
except OSError:
|
||||
notfound.append(media.get_path())
|
||||
|
||||
|
||||
with Html("div", class_="content", id='EventDetail') as section:
|
||||
section += Html("h3", self._("Database overview"), inline=True)
|
||||
body += section
|
||||
with Html("div", class_="content", id='subsection narrative') as sec11:
|
||||
sec11 += Html("h4", self._("Individuals"), inline=True)
|
||||
body += sec11
|
||||
with Html("div", class_="content", id='subsection narrative') as sec1:
|
||||
sec1 += Html("br", self._("Number of individuals") + self.colon +
|
||||
"%d" % npersons, inline=True)
|
||||
sec1 += Html("br", self._("Males") + self.colon +
|
||||
"%d" % males, inline=True)
|
||||
sec1 += Html("br", self._("Females") + self.colon +
|
||||
"%d" % females, inline=True)
|
||||
sec1 += Html("br", self._("Individuals with unknown gender") +
|
||||
self.colon + "%d" % unknown, inline=True)
|
||||
body += sec1
|
||||
with Html("div", class_="content", id='subsection narrative') as sec2:
|
||||
sec2 += Html("h4", self._("Family Information"), inline=True)
|
||||
sec2 += Html("br", self._("Number of families") + self.colon +
|
||||
"%d" % nfamilies, inline=True)
|
||||
sec2 += Html("br", self._("Unique surnames") + self.colon +
|
||||
"%d" % nsurnames, inline=True)
|
||||
body += sec2
|
||||
with Html("div", class_="content", id='subsection narrative') as sec3:
|
||||
sec3 += Html("h4", self._("Media Objects"), inline=True)
|
||||
sec3 += Html("br",
|
||||
self._("Total number of media object references") +
|
||||
self.colon + "%d" % total_media, inline=True)
|
||||
sec3 += Html("br", self._("Number of unique media objects") +
|
||||
self.colon + "%d" % mobjects, inline=True)
|
||||
sec3 += Html("br", self._("Total size of media objects") +
|
||||
self.colon +
|
||||
"%8s %s" % (mbytes, self._("Megabyte|MB")),
|
||||
inline=True)
|
||||
sec3 += Html("br", self._("Missing Media Objects") +
|
||||
self.colon + "%d" % len(notfound), inline=True)
|
||||
body += sec3
|
||||
with Html("div", class_="content", id='subsection narrative') as sec4:
|
||||
sec4 += Html("h4", self._("Miscellaneous"), inline=True)
|
||||
sec4 += Html("br", self._("Number of events") + self.colon +
|
||||
"%d" % report.database.get_number_of_events(),
|
||||
inline=True)
|
||||
sec4 += Html("br", self._("Number of places") + self.colon +
|
||||
"%d" % report.database.get_number_of_places(),
|
||||
inline=True)
|
||||
nsources = report.database.get_number_of_sources()
|
||||
sec4 += Html("br", self._("Number of sources") +
|
||||
self.colon + "%d" % nsources,
|
||||
inline=True)
|
||||
ncitations = report.database.get_number_of_citations()
|
||||
sec4 += Html("br", self._("Number of citations") +
|
||||
self.colon + "%d" % ncitations,
|
||||
inline=True)
|
||||
nrepo = report.database.get_number_of_repositories()
|
||||
sec4 += Html("br", self._("Number of repositories") +
|
||||
self.colon + "%d" % nrepo,
|
||||
inline=True)
|
||||
body += sec4
|
||||
|
||||
(males,
|
||||
females,
|
||||
unknown) = self.get_gender(self.report.bkref_dict[Person].keys())
|
||||
|
||||
origin = " :<br/>" + report.filter.get_name(self.rlocale)
|
||||
with Html("div", class_="content", id='EventDetail') as section:
|
||||
section += Html("h3",
|
||||
self._("Narrative web content report for") + origin,
|
||||
inline=True)
|
||||
body += section
|
||||
with Html("div", class_="content", id='subsection narrative') as sec5:
|
||||
sec5 += Html("h4", self._("Individuals"), inline=True)
|
||||
sec5 += Html("br", self._("Number of individuals") + self.colon +
|
||||
"%d" % len(self.report.bkref_dict[Person]),
|
||||
inline=True)
|
||||
sec5 += Html("br", self._("Males") + self.colon +
|
||||
"%d" % males, inline=True)
|
||||
sec5 += Html("br", self._("Females") + self.colon +
|
||||
"%d" % females, inline=True)
|
||||
sec5 += Html("br", self._("Individuals with unknown gender") +
|
||||
self.colon + "%d" % unknown, inline=True)
|
||||
body += sec5
|
||||
with Html("div", class_="content", id='subsection narrative') as sec6:
|
||||
sec6 += Html("h4", self._("Family Information"), inline=True)
|
||||
sec6 += Html("br", self._("Number of families") + self.colon +
|
||||
"%d" % len(self.report.bkref_dict[Family]),
|
||||
inline=True)
|
||||
body += sec6
|
||||
with Html("div", class_="content", id='subsection narrative') as sec7:
|
||||
sec7 += Html("h4", self._("Miscellaneous"), inline=True)
|
||||
sec7 += Html("br", self._("Number of events") + self.colon +
|
||||
"%d" % len(self.report.bkref_dict[Event]),
|
||||
inline=True)
|
||||
sec7 += Html("br", self._("Number of places") + self.colon +
|
||||
"%d" % len(self.report.bkref_dict[Place]),
|
||||
inline=True)
|
||||
sec7 += Html("br", self._("Number of sources") + self.colon +
|
||||
"%d" % len(self.report.bkref_dict[Source]),
|
||||
inline=True)
|
||||
sec7 += Html("br", self._("Number of citations") + self.colon +
|
||||
"%d" % len(self.report.bkref_dict[Citation]),
|
||||
inline=True)
|
||||
sec7 += Html("br", self._("Number of repositories") + self.colon +
|
||||
"%d" % len(self.report.bkref_dict[Repository]),
|
||||
inline=True)
|
||||
body += sec7
|
||||
|
||||
# add fullclear for proper styling
|
||||
# and footer section to page
|
||||
footer = self.write_footer(None)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(addressbookpage, output_file, sio, 0)
|
||||
|
||||
def get_gender(self, person_list):
|
||||
"""
|
||||
This function return the number of males, females and unknown gender
|
||||
from a person list.
|
||||
"""
|
||||
males = 0
|
||||
females = 0
|
||||
unknown = 0
|
||||
for person_handle in person_list:
|
||||
person = self.report.database.get_person_from_handle(person_handle)
|
||||
gender = person.get_gender()
|
||||
if gender == Person.MALE:
|
||||
males += 1
|
||||
elif gender == Person.FEMALE:
|
||||
females += 1
|
||||
else:
|
||||
unknown += 1
|
||||
return (males, females, unknown)
|
||||
265
gramps/plugins/webreport/surname.py
Normal file
265
gramps/plugins/webreport/surname.py
Normal file
@ -0,0 +1,265 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
SurnamePage - creates list of individuals with same surname
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.plug.report import utils
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import (name_to_md5, _NAME_STYLE_FIRST,
|
||||
_find_birth_date, _find_death_date,
|
||||
FULLCLEAR, html_escape)
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
#################################################
|
||||
#
|
||||
# create the page from SurnameListPage
|
||||
#
|
||||
#################################################
|
||||
class SurnamePage(BasePage):
|
||||
"""
|
||||
This will create a list of individuals with the same surname
|
||||
"""
|
||||
def __init__(self, report, title, surname, ppl_handle_list):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: surname -- The surname to use
|
||||
@param: ppl_handle_list -- The list of people for whom we need to create
|
||||
a page.
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
|
||||
# module variables
|
||||
showbirth = report.options['showbirth']
|
||||
showdeath = report.options['showdeath']
|
||||
showpartner = report.options['showpartner']
|
||||
showparents = report.options['showparents']
|
||||
|
||||
if surname == '':
|
||||
surname = self._("<absent>")
|
||||
|
||||
output_file, sio = self.report.create_file(name_to_md5(surname), "srn")
|
||||
self.uplink = True
|
||||
(surnamepage, head,
|
||||
body) = self.write_header("%s - %s" % (self._("Surname"), surname))
|
||||
ldatec = 0
|
||||
|
||||
# begin SurnameDetail division
|
||||
with Html("div", class_="content", id="SurnameDetail") as surnamedetail:
|
||||
body += surnamedetail
|
||||
|
||||
# section title
|
||||
surnamedetail += Html("h3", html_escape(surname), inline=True)
|
||||
|
||||
# feature request 2356: avoid genitive form
|
||||
msg = self._("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.") % html_escape(surname)
|
||||
surnamedetail += Html("p", msg, id="description")
|
||||
|
||||
# begin surname table and thead
|
||||
with Html("table", class_="infolist primobjlist surname") as table:
|
||||
surnamedetail += table
|
||||
thead = Html("thead")
|
||||
table += thead
|
||||
|
||||
trow = Html("tr")
|
||||
thead += trow
|
||||
|
||||
# Name Column
|
||||
trow += Html("th", self._("Given Name"), class_="ColumnName",
|
||||
inline=True)
|
||||
|
||||
if showbirth:
|
||||
trow += Html("th", self._("Birth"), class_="ColumnDate",
|
||||
inline=True)
|
||||
|
||||
if showdeath:
|
||||
trow += Html("th", self._("Death"), class_="ColumnDate",
|
||||
inline=True)
|
||||
|
||||
if showpartner:
|
||||
trow += Html("th", self._("Partner"),
|
||||
class_="ColumnPartner",
|
||||
inline=True)
|
||||
|
||||
if showparents:
|
||||
trow += Html("th", self._("Parents"),
|
||||
class_="ColumnParents",
|
||||
inline=True)
|
||||
|
||||
# begin table body
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
for person_handle in sorted(ppl_handle_list,
|
||||
key=self.sort_on_name_and_grampsid):
|
||||
|
||||
person = self.r_db.get_person_from_handle(person_handle)
|
||||
if person.get_change_time() > ldatec:
|
||||
ldatec = person.get_change_time()
|
||||
trow = Html("tr")
|
||||
tbody += trow
|
||||
|
||||
# firstname column
|
||||
link = self.new_person_link(person_handle, uplink=True,
|
||||
person=person,
|
||||
name_style=_NAME_STYLE_FIRST)
|
||||
trow += Html("td", link, class_="ColumnName")
|
||||
|
||||
# birth column
|
||||
if showbirth:
|
||||
tcell = Html("td", class_="ColumnBirth", inline=True)
|
||||
trow += tcell
|
||||
|
||||
birth_date = _find_birth_date(self.r_db, person)
|
||||
if birth_date is not None:
|
||||
if birth_date.fallback:
|
||||
tcell += Html('em',
|
||||
self.rlocale.get_date(birth_date),
|
||||
inline=True)
|
||||
else:
|
||||
tcell += self.rlocale.get_date(birth_date)
|
||||
else:
|
||||
tcell += " "
|
||||
|
||||
# death column
|
||||
if showdeath:
|
||||
tcell = Html("td", class_="ColumnDeath", inline=True)
|
||||
trow += tcell
|
||||
|
||||
death_date = _find_death_date(self.r_db, person)
|
||||
if death_date is not None:
|
||||
if death_date.fallback:
|
||||
tcell += Html('em',
|
||||
self.rlocale.get_date(death_date),
|
||||
inline=True)
|
||||
else:
|
||||
tcell += self.rlocale.get_date(death_date)
|
||||
else:
|
||||
tcell += " "
|
||||
|
||||
# partner column
|
||||
if showpartner:
|
||||
tcell = Html("td", class_="ColumnPartner")
|
||||
trow += tcell
|
||||
family_list = person.get_family_handle_list()
|
||||
if family_list:
|
||||
fam_count = 0
|
||||
for family_handle in family_list:
|
||||
fam_count += 1
|
||||
family = self.r_db.get_family_from_handle(
|
||||
family_handle)
|
||||
partner_handle = utils.find_spouse(
|
||||
person, family)
|
||||
if partner_handle:
|
||||
link = self.new_person_link(partner_handle,
|
||||
uplink=True)
|
||||
if fam_count < len(family_list):
|
||||
if isinstance(link, Html):
|
||||
link.inside += ","
|
||||
else:
|
||||
link += ','
|
||||
tcell += link
|
||||
else:
|
||||
tcell += " "
|
||||
|
||||
# parents column
|
||||
if showparents:
|
||||
parent_hdl_list = person.get_parent_family_handle_list()
|
||||
if parent_hdl_list:
|
||||
parent_hdl = parent_hdl_list[0]
|
||||
fam = self.r_db.get_family_from_handle(parent_hdl)
|
||||
f_id = fam.get_father_handle()
|
||||
m_id = fam.get_mother_handle()
|
||||
mother = father = None
|
||||
if f_id:
|
||||
father = self.r_db.get_person_from_handle(f_id)
|
||||
if father:
|
||||
father_name = self.get_name(father)
|
||||
if m_id:
|
||||
mother = self.r_db.get_person_from_handle(m_id)
|
||||
if mother:
|
||||
mother_name = self.get_name(mother)
|
||||
if mother and father:
|
||||
tcell = Html("span", father_name,
|
||||
class_="father fatherNmother")
|
||||
tcell += Html("span", mother_name,
|
||||
class_="mother")
|
||||
elif mother:
|
||||
tcell = Html("span", mother_name,
|
||||
class_="mother", inline=True)
|
||||
elif father:
|
||||
tcell = Html("span", father_name,
|
||||
class_="father", inline=True)
|
||||
samerow = False
|
||||
else:
|
||||
tcell = " " # pylint: disable=R0204
|
||||
samerow = True
|
||||
trow += Html("td", tcell,
|
||||
class_="ColumnParents", inline=samerow)
|
||||
|
||||
# add clearline for proper styling
|
||||
# add footer section
|
||||
footer = self.write_footer(ldatec)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(surnamepage, output_file, sio, ldatec)
|
||||
249
gramps/plugins/webreport/surnamelist.py
Normal file
249
gramps/plugins/webreport/surnamelist.py
Normal file
@ -0,0 +1,249 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
SurnameListPage - Index for first letters of surname
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import (get_first_letters, _KEYPERSON,
|
||||
alphabet_navigation, html_escape,
|
||||
sort_people, name_to_md5,
|
||||
first_letter, get_index_letter,
|
||||
primary_difference, FULLCLEAR)
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
#################################################
|
||||
#
|
||||
# Creates the Surname List page
|
||||
#
|
||||
#################################################
|
||||
class SurnameListPage(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying the list of Surnames
|
||||
"""
|
||||
ORDER_BY_NAME = 0
|
||||
ORDER_BY_COUNT = 1
|
||||
|
||||
def __init__(self, report, title, ppl_handle_list,
|
||||
order_by=ORDER_BY_NAME, filename="surnames"):
|
||||
"""
|
||||
@param: report -- The instance of the main report class for
|
||||
this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: ppl_handle_list -- The list of people for whom we need to create
|
||||
a page.
|
||||
@param: order_by -- The way to sort surnames :
|
||||
Surnames or Surnames count
|
||||
@param: filename -- The name to use for the Surnames page
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
prev_surname = ""
|
||||
prev_letter = " "
|
||||
|
||||
if order_by == self.ORDER_BY_NAME:
|
||||
output_file, sio = self.report.create_file(filename)
|
||||
surnamelistpage, head, body = self.write_header(self._('Surnames'))
|
||||
else:
|
||||
output_file, sio = self.report.create_file("surnames_count")
|
||||
(surnamelistpage, head,
|
||||
body) = self.write_header(self._('Surnames by person count'))
|
||||
|
||||
# begin surnames division
|
||||
with Html("div", class_="content", id="surnames") as surnamelist:
|
||||
body += surnamelist
|
||||
|
||||
# page message
|
||||
msg = self._('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.')
|
||||
surnamelist += Html("p", msg, id="description")
|
||||
|
||||
# add alphabet navigation...
|
||||
# only if surname list not surname count
|
||||
if order_by == self.ORDER_BY_NAME:
|
||||
index_list = get_first_letters(self.r_db, ppl_handle_list,
|
||||
_KEYPERSON, rlocale=self.rlocale)
|
||||
alpha_nav = alphabet_navigation(index_list, self.rlocale)
|
||||
if alpha_nav is not None:
|
||||
surnamelist += alpha_nav
|
||||
|
||||
if order_by == self.ORDER_BY_COUNT:
|
||||
table_id = 'SortByCount'
|
||||
else:
|
||||
table_id = 'SortByName'
|
||||
|
||||
# begin surnamelist table and table head
|
||||
with Html("table", class_="infolist primobjlist surnamelist",
|
||||
id=table_id) as table:
|
||||
surnamelist += table
|
||||
|
||||
thead = Html("thead")
|
||||
table += thead
|
||||
|
||||
trow = Html("tr")
|
||||
thead += trow
|
||||
|
||||
trow += Html("th", self._("Letter"), class_="ColumnLetter",
|
||||
inline=True)
|
||||
|
||||
# create table header surname hyperlink
|
||||
fname = self.report.surname_fname + self.ext
|
||||
tcell = Html("th", class_="ColumnSurname", inline=True)
|
||||
trow += tcell
|
||||
hyper = Html("a", self._("Surname"),
|
||||
href=fname, title=self._("Surnames"))
|
||||
tcell += hyper
|
||||
|
||||
# create table header number of people hyperlink
|
||||
fname = "surnames_count" + self.ext
|
||||
tcell = Html("th", class_="ColumnQuantity", inline=True)
|
||||
trow += tcell
|
||||
num_people = self._("Number of People")
|
||||
hyper = Html("a", num_people, href=fname, title=num_people)
|
||||
tcell += hyper
|
||||
|
||||
# begin table body
|
||||
with Html("tbody") as tbody:
|
||||
table += tbody
|
||||
|
||||
ppl_handle_list = sort_people(self.r_db, ppl_handle_list,
|
||||
self.rlocale)
|
||||
if order_by == self.ORDER_BY_COUNT:
|
||||
temp_list = {}
|
||||
for (surname, data_list) in ppl_handle_list:
|
||||
index_val = "%90d_%s" % (999999999-len(data_list),
|
||||
surname)
|
||||
temp_list[index_val] = (surname, data_list)
|
||||
|
||||
lkey = self.rlocale.sort_key
|
||||
ppl_handle_list = (temp_list[key]
|
||||
for key in sorted(temp_list,
|
||||
key=lkey))
|
||||
|
||||
first = True
|
||||
first_surname = True
|
||||
|
||||
for (surname, data_list) in ppl_handle_list:
|
||||
|
||||
if surname and not surname.isspace():
|
||||
letter = first_letter(surname)
|
||||
if order_by == self.ORDER_BY_NAME:
|
||||
# There will only be an alphabetic index list if
|
||||
# the ORDER_BY_NAME page is being generated
|
||||
letter = get_index_letter(letter, index_list,
|
||||
self.rlocale)
|
||||
else:
|
||||
letter = ' '
|
||||
surname = self._("<absent>")
|
||||
|
||||
trow = Html("tr")
|
||||
tbody += trow
|
||||
|
||||
tcell = Html("td", class_="ColumnLetter", inline=True)
|
||||
trow += tcell
|
||||
|
||||
if first or primary_difference(letter, prev_letter,
|
||||
self.rlocale):
|
||||
first = False
|
||||
prev_letter = letter
|
||||
trow.attr = 'class = "BeginLetter"'
|
||||
ttle = self._("Surnames beginning with "
|
||||
"letter %s") % letter
|
||||
hyper = Html("a", letter, name=letter,
|
||||
title=ttle, inline=True)
|
||||
tcell += hyper
|
||||
elif first_surname or surname != prev_surname:
|
||||
first_surname = False
|
||||
tcell += " "
|
||||
prev_surname = surname
|
||||
|
||||
trow += Html("td",
|
||||
self.surname_link(name_to_md5(surname),
|
||||
#html_escape(surname)),
|
||||
surname),
|
||||
class_="ColumnSurname", inline=True)
|
||||
|
||||
trow += Html("td", len(data_list),
|
||||
class_="ColumnQuantity", inline=True)
|
||||
|
||||
# create footer section
|
||||
# add clearline for proper styling
|
||||
footer = self.write_footer(None)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(surnamelistpage,
|
||||
output_file, sio, 0) # 0 => current date modification
|
||||
|
||||
def surname_link(self, fname, name, opt_val=None, uplink=False):
|
||||
"""
|
||||
Create a link to the surname page.
|
||||
|
||||
@param: fname -- Path to the file name
|
||||
@param: name -- Name to see in the link
|
||||
@param: opt_val -- Option value to use
|
||||
@param: uplink -- If True, then "../../../" is inserted in front of
|
||||
the result.
|
||||
"""
|
||||
url = self.report.build_url_fname_html(fname, "srn", uplink)
|
||||
hyper = Html("a", html_escape(name), href=url,
|
||||
title=name, inline=True)
|
||||
if opt_val is not None:
|
||||
hyper += opt_val
|
||||
|
||||
# return hyperlink to its caller
|
||||
return hyper
|
||||
277
gramps/plugins/webreport/thumbnail.py
Normal file
277
gramps/plugins/webreport/thumbnail.py
Normal file
@ -0,0 +1,277 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2007 Johan Gonqvist <johan.gronqvist@gmail.com>
|
||||
# Copyright (C) 2007-2009 Gary Burton <gary.burton@zen.co.uk>
|
||||
# Copyright (C) 2007-2009 Stephane Charette <stephanecharette@gmail.com>
|
||||
# Copyright (C) 2008-2009 Brian G. Matherly
|
||||
# Copyright (C) 2008 Jason M. Simanek <jason@bohemianalps.com>
|
||||
# Copyright (C) 2008-2011 Rob G. Healey <robhealey1@gmail.com>
|
||||
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2010-2017 Serge Noiraud
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2013 Benny Malengier
|
||||
# Copyright (C) 2016 Allen Crider
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
"""
|
||||
Narrative Web Page generator.
|
||||
|
||||
Classe:
|
||||
ThumbnailPreviewPage
|
||||
"""
|
||||
#------------------------------------------------
|
||||
# python modules
|
||||
#------------------------------------------------
|
||||
from decimal import getcontext
|
||||
import logging
|
||||
|
||||
#------------------------------------------------
|
||||
# Gramps module
|
||||
#------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.lib import Media
|
||||
from gramps.plugins.lib.libhtml import Html
|
||||
|
||||
#------------------------------------------------
|
||||
# specific narrative web import
|
||||
#------------------------------------------------
|
||||
from gramps.plugins.webreport.basepage import BasePage
|
||||
from gramps.plugins.webreport.common import (FULLCLEAR, html_escape)
|
||||
|
||||
_ = glocale.translation.sgettext
|
||||
LOG = logging.getLogger(".NarrativeWeb")
|
||||
getcontext().prec = 8
|
||||
|
||||
class ThumbnailPreviewPage(BasePage):
|
||||
"""
|
||||
This class is responsible for displaying information about
|
||||
the Thumbnails page.
|
||||
"""
|
||||
def __init__(self, report, title, cb_progress):
|
||||
"""
|
||||
@param: report -- The instance of the main report class
|
||||
for this report
|
||||
@param: title -- Is the title of the web page
|
||||
@param: cb_progress -- The step used for the progress bar.
|
||||
"""
|
||||
BasePage.__init__(self, report, title)
|
||||
self.create_thumbs_only = report.options['create_thumbs_only']
|
||||
# bug 8950 : it seems it's better to sort on desc + gid.
|
||||
def sort_by_desc_and_gid(obj):
|
||||
"""
|
||||
Sort by media description and gramps ID
|
||||
"""
|
||||
return (obj.desc, obj.gramps_id)
|
||||
|
||||
self.photo_keys = sorted(self.report.obj_dict[Media],
|
||||
key=lambda x: sort_by_desc_and_gid(
|
||||
self.r_db.get_media_from_handle(x)))
|
||||
|
||||
if self.create_unused_media:
|
||||
# add unused media
|
||||
media_list = self.r_db.get_media_handles()
|
||||
for media_ref in media_list:
|
||||
if media_ref not in self.report.obj_dict[Media]:
|
||||
self.photo_keys.append(media_ref)
|
||||
|
||||
media_list = []
|
||||
for person_handle in self.photo_keys:
|
||||
photo = self.r_db.get_media_from_handle(person_handle)
|
||||
if photo:
|
||||
if photo.get_mime_type().startswith("image"):
|
||||
media_list.append((photo.get_description(), person_handle,
|
||||
photo))
|
||||
|
||||
if self.create_thumbs_only:
|
||||
self.copy_thumbnail(person_handle, photo)
|
||||
|
||||
media_list.sort(key=lambda x: self.rlocale.sort_key(x[0]))
|
||||
|
||||
# Create thumbnail preview page...
|
||||
output_file, sio = self.report.create_file("thumbnails")
|
||||
thumbnailpage, head, body = self.write_header(self._("Thumbnails"))
|
||||
|
||||
with Html("div", class_="content", id="Preview") as previewpage:
|
||||
body += previewpage
|
||||
|
||||
msg = self._("This page displays a indexed list "
|
||||
"of all the media objects "
|
||||
"in this database. It is sorted by media title. "
|
||||
"There is an index "
|
||||
"of all the media objects in this database. "
|
||||
"Clicking on a thumbnail "
|
||||
"will take you to that image’s page.")
|
||||
previewpage += Html("p", msg, id="description")
|
||||
|
||||
with Html("table", class_="calendar") as table:
|
||||
previewpage += table
|
||||
|
||||
thead = Html("thead")
|
||||
table += thead
|
||||
|
||||
# page title...
|
||||
trow = Html("tr")
|
||||
thead += trow
|
||||
|
||||
trow += Html("th", self._("Thumbnail Preview"),
|
||||
class_="monthName", colspan=7, inline=True)
|
||||
|
||||
# table header cells...
|
||||
trow = Html("tr")
|
||||
thead += trow
|
||||
|
||||
ltrs = [" ", " ", " ",
|
||||
" ", " ", " ", " "]
|
||||
for ltr in ltrs:
|
||||
trow += Html("th", ltr, class_="weekend", inline=True)
|
||||
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
index, indexpos = 1, 0
|
||||
num_of_images = len(media_list)
|
||||
num_of_rows = ((num_of_images // 7) + 1)
|
||||
num_of_cols = 7
|
||||
grid_row = 0
|
||||
while grid_row < num_of_rows:
|
||||
trow = Html("tr", id="RowNumber: %08d" % grid_row)
|
||||
tbody += trow
|
||||
|
||||
cols = 0
|
||||
while cols < num_of_cols and indexpos < num_of_images:
|
||||
ptitle = media_list[indexpos][0]
|
||||
person_handle = media_list[indexpos][1]
|
||||
photo = media_list[indexpos][2]
|
||||
|
||||
# begin table cell and attach to table row(trow)...
|
||||
tcell = Html("td", class_="highlight weekend")
|
||||
trow += tcell
|
||||
|
||||
# attach index number...
|
||||
numberdiv = Html("div", class_="date")
|
||||
tcell += numberdiv
|
||||
|
||||
# attach anchor name to date cell in upper right
|
||||
# corner of grid...
|
||||
numberdiv += Html("a", index, name=index, title=index,
|
||||
inline=True)
|
||||
|
||||
# begin unordered list and
|
||||
# attach to table cell(tcell)...
|
||||
unordered = Html("ul")
|
||||
tcell += unordered
|
||||
|
||||
# create thumbnail
|
||||
(real_path,
|
||||
newpath) = self.report.prepare_copy_media(photo)
|
||||
newpath = self.report.build_url_fname(newpath)
|
||||
|
||||
list_html = Html("li")
|
||||
unordered += list_html
|
||||
|
||||
# attach thumbnail to list...
|
||||
list_html += self.thumb_hyper_image(newpath, "img",
|
||||
person_handle,
|
||||
ptitle)
|
||||
|
||||
index += 1
|
||||
indexpos += 1
|
||||
cols += 1
|
||||
grid_row += 1
|
||||
|
||||
# if last row is incomplete, finish it off?
|
||||
if grid_row == num_of_rows and cols < num_of_cols:
|
||||
for emptycols in range(cols, num_of_cols):
|
||||
trow += Html("td", class_="emptyDays", inline=True)
|
||||
|
||||
# begin Thumbnail Reference section...
|
||||
with Html("div", class_="subsection", id="references") as section:
|
||||
body += section
|
||||
section += Html("h4", self._("References"), inline=True)
|
||||
|
||||
with Html("table", class_="infolist") as table:
|
||||
section += table
|
||||
|
||||
tbody = Html("tbody")
|
||||
table += tbody
|
||||
|
||||
index = 1
|
||||
for ptitle, person_handle, photo in media_list:
|
||||
trow = Html("tr")
|
||||
tbody += trow
|
||||
|
||||
tcell1 = Html("td",
|
||||
self.thumbnail_link(ptitle, index),
|
||||
class_="ColumnRowLabel")
|
||||
tcell2 = Html("td", ptitle, class_="ColumnName")
|
||||
trow += (tcell1, tcell2)
|
||||
|
||||
# increase index for row number...
|
||||
index += 1
|
||||
|
||||
# increase progress meter...
|
||||
cb_progress()
|
||||
|
||||
# add body id element
|
||||
body.attr = 'id ="ThumbnailPreview"'
|
||||
|
||||
# add footer section
|
||||
# add clearline for proper styling
|
||||
footer = self.write_footer(None)
|
||||
body += (FULLCLEAR, footer)
|
||||
|
||||
# send page out for processing
|
||||
# and close the file
|
||||
self.xhtml_writer(thumbnailpage, output_file, sio, 0)
|
||||
|
||||
|
||||
def thumbnail_link(self, name, index):
|
||||
"""
|
||||
creates a hyperlink for Thumbnail Preview Reference...
|
||||
"""
|
||||
return Html("a", index, title=html_escape(name),
|
||||
href="#%d" % index)
|
||||
|
||||
def thumb_hyper_image(self, thumbnail_url, subdir, fname, name):
|
||||
"""
|
||||
eplaces media_link() because it doesn't work for this instance
|
||||
"""
|
||||
name = html_escape(name)
|
||||
url = "/".join(self.report.build_subdirs(subdir,
|
||||
fname) + [fname]) + self.ext
|
||||
|
||||
with Html("div", class_="content", id="ThumbnailPreview") as section:
|
||||
with Html("div", class_="snapshot") as snapshot:
|
||||
section += snapshot
|
||||
|
||||
with Html("div", class_="thumbnail") as thumbnail:
|
||||
snapshot += thumbnail
|
||||
|
||||
if not self.create_thumbs_only:
|
||||
thumbnail_link = Html("a", href=url, title=name) + (
|
||||
Html("img", src=thumbnail_url, alt=name)
|
||||
)
|
||||
else:
|
||||
thumbnail_link = Html("img", src=thumbnail_url,
|
||||
alt=name)
|
||||
thumbnail += thumbnail_link
|
||||
return section
|
||||
@ -34,13 +34,13 @@ plg.id = 'navwebpage'
|
||||
plg.name = _("Narrated Web Site")
|
||||
plg.description = _("Produces web (HTML) pages for individuals, or a set of "
|
||||
"individuals")
|
||||
plg.version = '1.0'
|
||||
plg.version = '2.0'
|
||||
plg.gramps_target_version = MODULE_VERSION
|
||||
plg.status = STABLE
|
||||
plg.fname = 'narrativeweb.py'
|
||||
plg.ptype = REPORT
|
||||
plg.authors = ["Donald N. Allingham", "Rob G. Healey"]
|
||||
plg.authors_email = ["don@gramps-project.org", "robhealey1@gmail.com"]
|
||||
plg.authors = ["Donald N. Allingham", "Rob G. Healey", "Serge Noiraud"]
|
||||
plg.authors_email = ["don@gramps-project.org", "serge.noiraud@free.fr"]
|
||||
plg.category = CATEGORY_WEB
|
||||
plg.reportclass = 'NavWebReport'
|
||||
plg.optionclass = 'NavWebOptions'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user