#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2007 Thom Sturgill
# Copyright (C) 2007-2008 Brian G. Matherly
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Pubilc License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Web Calendar generator.
Created 4/22/07 by Thom Sturgill based on Calendar.py (with patches)
by Doug Blank with input dialog based on NarrativeWeb.py by Don Allingham.
Reports/Web Page/Web Calendar...
"""
#------------------------------------------------------------------------
#
# python modules
#
#------------------------------------------------------------------------
import os
import time
import datetime
#import const
import codecs
import shutil
from gettext import gettext as _
from xml.parsers import expat
try:
set()
except:
from sets import Set as set
#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
log = logging.getLogger(".WebPage")
#------------------------------------------------------------------------
#
# GRAMPS module
#
#------------------------------------------------------------------------
import gen.lib
import const
import BaseDoc
from GrampsCfg import get_researcher
from PluginUtils import register_report
from ReportBase import (Report, ReportUtils, MenuReportOptions, CATEGORY_WEB,
MODE_GUI)
from PluginUtils import FilterOption, EnumeratedListOption, PersonOption, \
BooleanOption, NumberOption, StringOption, DestinationOption
import Utils
import GrampsLocale
from QuestionDialog import ErrorDialog
from Utils import probably_alive
#------------------------------------------------------------------------
#
# constants
#
#------------------------------------------------------------------------
_CALENDAR = "calendar.css"
_CHARACTER_SETS = [
[_('Unicode (recommended)'), 'utf-8'],
['ISO-8859-1', 'iso-8859-1' ],
['ISO-8859-2', 'iso-8859-2' ],
['ISO-8859-3', 'iso-8859-3' ],
['ISO-8859-4', 'iso-8859-4' ],
['ISO-8859-5', 'iso-8859-5' ],
['ISO-8859-6', 'iso-8859-6' ],
['ISO-8859-7', 'iso-8859-7' ],
['ISO-8859-8', 'iso-8859-8' ],
['ISO-8859-9', 'iso-8859-9' ],
['ISO-8859-10', 'iso-8859-10' ],
['ISO-8859-13', 'iso-8859-13' ],
['ISO-8859-14', 'iso-8859-14' ],
['ISO-8859-15', 'iso-8859-15' ],
['koi8_r', 'koi8_r', ],
]
_CC = [
''
'',
''
'
',
''
'
',
''
'
',
''
'
',
''
'
'
]
_COPY_OPTIONS = [
_('Standard copyright'),
_('Creative Commons - By attribution'),
_('Creative Commons - By attribution, No derivations'),
_('Creative Commons - By attribution, Share-alike'),
_('Creative Commons - By attribution, Non-commercial'),
_('Creative Commons - By attribution, Non-commercial, No derivations'),
_('Creative Commons - By attribution, Non-commercial, Share-alike'),
_('No copyright notice'),
]
def make_date(year, month, day):
"""
Return a Date object of the particular year/month/day.
"""
retval = gen.lib.Date()
retval.set_yr_mon_day(year, month, day)
return retval
#------------------------------------------------------------------------
#
# WebCalReport
#
#------------------------------------------------------------------------
class WebCalReport(Report):
"""
Create WebCalReport object that produces the report.
"""
def __init__(self, database, options):
Report.__init__(self, database, options)
menu = options.menu
self.database = database
self.options = options
self.html_dir = menu.get_option_by_name('target').get_value()
filter_option = menu.get_option_by_name('filter')
self.filter = filter_option.get_filter()
self.ext = menu.get_option_by_name('ext').get_value()
self.copy = menu.get_option_by_name('cright').get_value()
self.encoding = menu.get_option_by_name('encoding').get_value()
self.Country = menu.get_option_by_name('country').get_value()
self.Year = menu.get_option_by_name('year').get_value()
self.Surname = menu.get_option_by_name('surname').get_value()
self.Alive = menu.get_option_by_name('alive').get_value()
self.Birthday = menu.get_option_by_name('birthdays').get_value()
self.Anniv = menu.get_option_by_name('anniversaries').get_value()
self.Title_text = menu.get_option_by_name('title').get_value()
self.Month_image = menu.get_option_by_name('background').get_value()
self.Month_repeat = menu.get_option_by_name('repeat').get_value()
self.Serif_fonts = menu.get_option_by_name('serif_fonts').get_value()
self.SanSerif_fonts = \
menu.get_option_by_name('sanserif_fonts').get_value()
self.Home_link = menu.get_option_by_name('home_link').get_value()
self.Note = [ menu.get_option_by_name('note_jan').get_value(),
menu.get_option_by_name('note_feb').get_value(),
menu.get_option_by_name('note_mar').get_value(),
menu.get_option_by_name('note_apr').get_value(),
menu.get_option_by_name('note_may').get_value(),
menu.get_option_by_name('note_jun').get_value(),
menu.get_option_by_name('note_jul').get_value(),
menu.get_option_by_name('note_aug').get_value(),
menu.get_option_by_name('note_sep').get_value(),
menu.get_option_by_name('note_oct').get_value(),
menu.get_option_by_name('note_nov').get_value(),
menu.get_option_by_name('note_dec').get_value()]
def get_short_name(self, person, maiden_name = None):
""" Return person's name, unless maiden_name given, unless married_name listed. """
# Get all of a person's names:
primary_name = person.get_primary_name()
married_name = None
names = [primary_name] + person.get_alternate_names()
for n in names:
if int(n.get_type()) == gen.lib.NameType.MARRIED:
married_name = n
# Now, decide which to use:
if maiden_name != None:
if married_name != None:
first_name, family_name = married_name.get_first_name(), married_name.get_surname()
call_name = married_name.get_call_name()
else:
first_name, family_name = primary_name.get_first_name(), maiden_name
call_name = primary_name.get_call_name()
else:
first_name, family_name = primary_name.get_first_name(), primary_name.get_surname()
call_name = primary_name.get_call_name()
# If they have a nickname use it
if call_name != None and call_name.strip() != "":
first_name = call_name.strip()
else: # else just get the first name:
first_name = first_name.strip()
if " " in first_name:
first_name, rest = first_name.split(" ", 1) # just one split max
return ("%s %s" % (first_name, family_name)).strip()
def add_day_item(self, text, year, month, day):
month_dict = self.calendar.get(month, {})
day_list = month_dict.get(day, [])
day_list.append(text)
month_dict[day] = day_list
self.calendar[month] = month_dict
def get_holidays(self, year, country = "United States"):
""" Looks in multiple places for holidays.xml files """
locations = [const.PLUGINS_DIR, const.USER_PLUGINS]
holiday_file = 'holidays.xml'
for dir in locations:
holiday_full_path = os.path.join(dir, holiday_file)
if os.path.exists(holiday_full_path):
self.process_holiday_file(holiday_full_path, year, country)
def process_holiday_file(self, filename, year, country):
""" This will process a holiday file """
parser = Xml2Obj()
element = parser.Parse(filename)
calendar = Holidays(element, country)
date = datetime.date(year, 1, 1)
while date.year == year:
holidays = calendar.check_date( date )
for text in holidays:
self.add_day_item(text, date.year, date.month, date.day)
date = date.fromordinal( date.toordinal() + 1)
def write_css(self):
"""
Create the CSS file.
"""
# simplify the style and weight printing
font_style = ['normal','italic']
font_weight = ['normal','bold']
# use user defined font families
font_family = [self.SanSerif_fonts,self.Serif_fonts]
default_style = BaseDoc.StyleSheet()
self.options.make_default_style(default_style)
# Read all style sheets available for this item
style_file = self.options.handler.get_stylesheet_savefile()
self.style_list = BaseDoc.StyleSheetList(style_file,default_style)
# Get the selected stylesheet
style_name = self.options.handler.get_default_stylesheet_name()
self.selected_style = self.style_list.get_style_sheet(style_name)
default_style = BaseDoc.StyleSheet(self.selected_style)
#
# NAVIGATION BLOCK
#
of = self.create_file(_CALENDAR)
of.write('ul#navlist { padding: 0;\n\tmargin: 0;\n\tlist-style-type: none;')
of.write('\n\tfloat: left;\n\twidth: 100%;')
of.write('\n\tcolor: #FFFFFF;\n\tbackground-color: #003366;\n\t}\n')
of.write('ul#navlist li { display: inline; }\n')
of.write('ul#navlist li a { float: left;\n\twidth: 2.8em;')
of.write('\n\tcolor: #FFFFFF;\n\tbackground-color: #003366;')
of.write('\n\tpadding: 0.2em 1em;\n\ttext-decoration: none;')
of.write('\n\tborder-right: 1px solid #FFFFFF;\n\t}\n')
of.write('ul#navlist li a:hover { background-color: #336699;')
of.write('\n\tcolor: #FFFFFF;\n\t}\n')
#
# HEADER / BODY BACKGROUND
#
of.write('h1 {')
style = default_style.get_paragraph_style("WC-Title")
font = style.get_font()
italic = font_style[font.get_italic()]
bold = font_weight[font.get_bold()]
family = font_family[font.get_type_face()]
color = "#%02X%02X%02X" % font.get_color()
of.write('\tfont-family: %s;\n\tfont-size: %dpt;\n'
'\tfont-style: %s;\n\tfont-weight: %s;\n'
'\tcolor: %s;\n\ttext-align: %s;\n\t}\n'
% (family, font.get_size(), italic, bold,
color, style.get_alignment_text()))
of.write('body { background-color: #%02X%02X%02X;\n}\n' % style.get_background_color() )
#
# CALENDAR TABLE
#
of.write('.calendar { ')
style = default_style.get_paragraph_style("WC-Table")
font = style.get_font()
italic = font_style[font.get_italic()]
bold = font_weight[font.get_bold()]
family = font_family[font.get_type_face()]
color = "#%02X%02X%02X" % font.get_color()
of.write('font-family: %s;\n\tfont-size: %dpt;\n'
'\tfont-style: %s;\n\tfont-weight: %s;\n'
'\tcolor: %s;\n\ttext-align: %s;\n'
% (family, font.get_size(), italic, bold,
color, style.get_alignment_text()))
of.write('\tbackground-color: #%02X%02X%02X;\n}\n' % style.get_background_color() )
#
# MONTH NAME
#
style = default_style.get_paragraph_style("WC-Month")
of.write('.cal_month { border-bottom-width: 0;\n')
font = style.get_font()
italic = font_style[font.get_italic()]
bold = font_weight[font.get_bold()]
family = font_family[font.get_type_face()]
color = "#%02X%02X%02X" % font.get_color()
mon_backcolor = "#%02X%02X%02X" % style.get_background_color()
of.write('\tfont-family:%s;\n\tfont-size: %dpt;\n'
'\tfont-style: %s;\n\tfont-weight: %s;\n'
'\tcolor: %s;\n\ttext-align: %s;\n'
% (family, font.get_size(), italic, bold, color, style.get_alignment_text()))
if self.Month_image.strip() != "":
of.write('\tbackground-image: URL( %s );\n' % self.Month_image)
of.write('\tbackground-repeat: %s;\n' % self.options.repeat_options[self.Month_repeat] )
of.write('\tbackground-color: %s;\n}\n' % mon_backcolor )
#
# WEEKDAY NAMES
#
of.write('.cal_sun { border-top-width: 0;\n\tborder-right-width: 0;')
of.write('\n\tborder-style: solid; ')
of.write('background-color: %s }\n' % mon_backcolor )
of.write('.cal_weekday { border-top-width: 0;\n\tborder-left-width: 0;\n\tborder-right-width: 0; ')
of.write('\n\tborder-style: solid;\n\tbackground-color: %s }\n' % mon_backcolor )
of.write('.cal_sat { border-top-width: 0;\n\tborder-left-width: 0;\n')
of.write('\tborder-right-width: 0;\n\tborder-style: solid;')
of.write('\n\tbackground-color: %s }\n' % mon_backcolor )
#of.write('.cal_day_num { text-align: right;\n\tfont-size: x-large;\n\tfont-weight: bold;}\n')
#
# CALENDAR ENTRY TEXT
#
style = default_style.get_paragraph_style("WC-Text")
of.write('.cal_text { vertical-align:bottom;\n')
font = style.get_font()
italic = font_style[font.get_italic()]
bold = font_weight[font.get_bold()]
family = font_family[font.get_type_face()]
color = "#%02X%02X%02X" % font.get_color()
msg_backcolor = "#%02X%02X%02X" % style.get_background_color()
of.write('\tfont-family:%s;\n\tfont-size: %dpt;\n'
'\tfont-style: %s;\n\tfont-weight: %s;\n'
'\tcolor: %s;\n\ttext-align: %s;\n\t}\n'
% (family, font.get_size(), italic, bold, color, style.get_alignment_text()))
of.write('.cal_row { height: 70px;\n\tborder-style: solid;\n\t}\n')
of.write('.cal_cell_hilite {background-color: %s;}\n' % msg_backcolor )
#
# CALENDAR NOTE TEXT
#
style = default_style.get_paragraph_style("WC-Note")
font = style.get_font()
italic = font_style[font.get_italic()]
bold = font_weight[font.get_bold()]
family = font_family[font.get_type_face()]
color = "#%02X%02X%02X" % font.get_color()
backcolor = "#%02X%02X%02X" % style.get_background_color()
of.write('.cal_cell { background-color: %s;}\n' % backcolor )
of.write('.cal_note {\n')
of.write('\tfont-family:%s;\n\tfont-size: %dpt;\n'
'\tfont-style: %s;\n\tfont-weight: %s;\n'
'\tcolor: %s;\n\ttext-align: %s;\n'
'\tbackground-color: %s;\n\t}\n'
% (family, font.get_size(), italic, bold, color, style.get_alignment_text(), backcolor))
#
# FOOTER AND DONE
#
of.write('.footer { text-align: center;\n\tfont-size:small; }\n')
of.write('img { border: 0; }\n')
of.close()
def write_footer(self, of):
author = get_researcher().get_name()
value = unicode(time.strftime('%x',time.localtime(time.time())),
GrampsLocale.codeset)
msg = _('Generated by '
'GRAMPS on %(date)s') % { 'date' : value }
of.write(' \n')
of.write('