# # 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, StyleOption 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()] self.__style = menu.get_option_by_name("style").get_style() 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] # # 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 = self.__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 = self.__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 = self.__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 = self.__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 = self.__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('
\n') of.write('