* Narrative web: Some improvements - Event type, Date and place in bold - Family events shifted one column on the left - ancestortree css file before narrative-screen to allow modification - Adaptation for all themes Fixes #11393 * Narrative web: forgot a comma during last merge * Allow scrolling if the ancestor tree is too large * Translation of alternate stylesheets name * Crash when using the family map * Translate only the css title, not the file name * Some minor corrections to css files * Narrative web: open layers optimizations * Narrative web: open layers and link in popup * Narrative web: some events missing in popup * Narrative web: Reference date column too large. Allow the place title to use the maximum of width * NarrativeWeb: shift children from one column - adapt the css files to the new table - some inconsistencies between the source and the css * Make the drop down menu button size usable * NarrativeWeb: Incorrect rendering when use of alternate place name * NarWeb: removing the unused image heigth option * Click on image link gives a not found URL. If the image used in home, introduction or contact page is not already associated by a filtered object, we have a 404 error * NarWeb: Index images and thumbnails pages optional * Narweb: Improper Notes subtitle in web pages * Narweb: List index truncated after 999 * Narweb: NarrativeWeb usage enhancements * Narweb: avoid duplicate files in archive. * Narweb: Add an optional news and updates page: When you have a big database and you make intensive updates, it's useful to have a list of the last modified objects. you can select the period to show and how many records to see per object type. * Narweb: forgot to add the module updates.py * Narweb: some minor changes (pylint, img index bug) * Popups don't work with the last openlayers version It only needs to move the scripts at the end of the html body. Use addEventListener instead of onload in the html body statement. * Narweb: some popup problems * Narweb: better score for pylint
672 lines
30 KiB
Python
672 lines
30 KiB
Python
# -*- 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- Serge Noiraud
|
|
# Copyright (C) 2011 Tim G L Lyons
|
|
# Copyright (C) 2013 Benny Malengier
|
|
# Copyright (C) 2016 Allen Crider
|
|
# Copyright (C) 2018 Theo van Rijn
|
|
#
|
|
# 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)
|
|
self.unused_media_handles = []
|
|
self.cur_fname = None
|
|
self.create_images_index = self.report.options['create_images_index']
|
|
|
|
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))
|
|
if self.create_unused_media:
|
|
media_count = len(self.r_db.get_media_handles())
|
|
else:
|
|
media_count = len(self.report.obj_dict[Media])
|
|
message = _("Creating media pages")
|
|
with self.r_user.progress(_("Narrated Web Site Report"), message,
|
|
media_count + 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)
|
|
|
|
self.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]:
|
|
self.unused_media_handles.append(media_ref)
|
|
self.unused_media_handles = sorted(
|
|
self.unused_media_handles,
|
|
key=lambda x: sort_by_desc_and_gid(
|
|
self.r_db.get_media_from_handle(x)))
|
|
|
|
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)))
|
|
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.
|
|
if index == media_count:
|
|
next_ = None
|
|
elif index < total:
|
|
next_ = sorted_media_handles[index]
|
|
elif self.unused_media_handles:
|
|
next_ = self.unused_media_handles[0]
|
|
else:
|
|
next_ = None
|
|
self.mediapage(self.report, title,
|
|
handle, (prev, next_, index, media_count))
|
|
prev = handle
|
|
step()
|
|
index += 1
|
|
|
|
total = len(self.unused_media_handles)
|
|
idx = 1
|
|
total_m = len(sorted_media_handles)
|
|
prev = sorted_media_handles[total_m-1] if total_m > 0 else 0
|
|
if total > 0:
|
|
for media_handle in self.unused_media_handles:
|
|
gc.collect() # Reduce memory usage when many images.
|
|
if index == media_count:
|
|
next_ = None
|
|
else:
|
|
next_ = self.unused_media_handles[idx]
|
|
self.mediapage(self.report, title, media_handle,
|
|
(prev, next_, index, media_count))
|
|
prev = media_handle
|
|
step()
|
|
index += 1
|
|
idx += 1
|
|
|
|
self.medialistpage(self.report, title, sorted_media_handles)
|
|
|
|
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)
|
|
|
|
if self.create_images_index:
|
|
output_file, sio = self.report.create_file("media")
|
|
# save the media file name in case we create unused media pages
|
|
self.cur_fname = self.report.cur_fname
|
|
result = self.write_header(self._('Media'))
|
|
medialistpage, dummy_head, dummy_body, outerwrapper = result
|
|
|
|
ldatec = 0
|
|
# begin gallery division
|
|
with Html("div", class_="content", id="Gallery") as medialist:
|
|
outerwrapper += 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
|
|
if self.create_unused_media:
|
|
media_count = len(self.r_db.get_media_handles())
|
|
else:
|
|
media_count = len(self.report.obj_dict[Media])
|
|
message = _("Creating list of media pages")
|
|
with self.r_user.progress(_("Narrated Web Site Report"),
|
|
message, media_count + 1
|
|
) as step:
|
|
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
|
|
)
|
|
step()
|
|
index += 1
|
|
|
|
idx = 1
|
|
total = len(self.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 self.unused_media_handles:
|
|
gmfh = self.r_db.get_media_from_handle
|
|
media = gmfh(media_handle)
|
|
gc.collect() # Reduce memory usage when many images.
|
|
if idx != total:
|
|
self.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
|
|
)
|
|
step()
|
|
index += 1
|
|
idx += 1
|
|
|
|
# add footer section
|
|
# add clearline for proper styling
|
|
footer = self.write_footer(ldatec)
|
|
outerwrapper += (FULLCLEAR, footer)
|
|
|
|
# send page out for processing
|
|
# and close the file
|
|
self.report.cur_fname = self.cur_fname
|
|
if self.create_images_index:
|
|
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()
|
|
|
|
if mime_type:
|
|
newpath = self.copy_source_file(media_handle, media)
|
|
target_exists = newpath is not None
|
|
else:
|
|
target_exists = False
|
|
|
|
self.copy_thumbnail(media_handle, media)
|
|
self.page_title = media.get_description()
|
|
esc_page_title = html_escape(self.page_title)
|
|
result = self.write_header("%s - %s" % (self._("Media"),
|
|
self.page_title))
|
|
mediapage, head, dummy_body, outerwrapper = result
|
|
|
|
# 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:
|
|
outerwrapper += 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())
|
|
(width, height) = image_size(orig_image_path)
|
|
max_width = self.report.options[
|
|
'maxinitialimagewidth']
|
|
|
|
# TODO. Convert disk path to URL.
|
|
url = self.report.build_url_fname(orig_image_path,
|
|
None, self.uplink)
|
|
with Html("div", id="GalleryDisplay",
|
|
style='max-width: %dpx; height: auto' % (
|
|
max_width)) 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 _region_items:
|
|
(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)
|
|
s_width = 'width: %dpx;' % max_width
|
|
mediadisplay += Html("a", href=url) + (
|
|
Html("img", src=url,
|
|
style=s_width,
|
|
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)
|
|
s_width = 'width: 48px;'
|
|
hyper = Html("a", href=url,
|
|
title=esc_page_title) + (
|
|
Html("img", src=img_url,
|
|
style=s_width,
|
|
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)
|
|
s_width = 'width: 48px;'
|
|
mediadisplay += Html("img", src=url,
|
|
style=s_width,
|
|
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(), Media)
|
|
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)
|
|
outerwrapper += (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:
|
|
if str(newpath) not in self.report.archive.getnames():
|
|
# The current file not already archived.
|
|
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
|